From: Simon Marchi <simark@simark.ca>
To: Andrew Burgess <aburgess@redhat.com>, gdb-patches@sourceware.org
Cc: Eli Zaretskii <eliz@gnu.org>
Subject: Re: [PATCHv6 2/4] gdb: introduce program_space::get_entry_point_info function
Date: Fri, 10 Jul 2026 11:39:53 -0400 [thread overview]
Message-ID: <a0146d34-7e9e-4c0d-8410-7e2dcac2eeb9@simark.ca> (raw)
In-Reply-To: <747603001ab3638f26cd7b1c84c7fbee4e33c005.1783693321.git.aburgess@redhat.com>
Some comments below, I think they are pretty straightfowrard, so with
those fixed (and if you don't end up making more major changes):
Approved-By: Simon Marchi <simon.marchi@efficios.com>
On 7/10/26 10:24 AM, Andrew Burgess wrote:
> diff --git a/gdb/progspace.c b/gdb/progspace.c
> index 0e8516f4640..26e16cae8d0 100644
> --- a/gdb/progspace.c
> +++ b/gdb/progspace.c
> @@ -26,6 +26,7 @@
> #include <algorithm>
> #include "cli/cli-style.h"
> #include "observable.h"
> +#include "arch-utils.h"
>
> /* The last program space number assigned. */
> static int last_program_space_num = 0;
> @@ -288,6 +289,55 @@ program_space::exec_entry_point_address () const
>
> /* See progspace.h. */
>
> +program_space::entry_point_info
> +program_space::get_entry_point_info () const
> +{
> + std::optional<CORE_ADDR> exec_entry_address
> + = this->exec_entry_point_address_if_available ();
> +
> + std::optional<CORE_ADDR> inferior_entry_address;
> + if (m_solib_ops != nullptr)
> + inferior_entry_address = m_solib_ops->inferior_entry_point_address ();
> +
> + return entry_point_info (std::move (inferior_entry_address),
> + std::move (exec_entry_address));
I wouldn't std::move those (I think it's the same as cpying on this
type).
> diff --git a/gdb/progspace.h b/gdb/progspace.h
> index 1ae1e42f3bb..d75379fe621 100644
> --- a/gdb/progspace.h
> +++ b/gdb/progspace.h
> @@ -323,6 +323,54 @@ struct program_space
> return m_target_sections;
> }
>
> + /* Class for tracking two possible entry points that an inferior might
> + have, the entry point for the entire inferior, and the entry point
> + within the main executable. */
> + struct entry_point_info
I think it would be preferable to define this class outside of struct
program_space. I think that having (unnecessarily) nested classes just
makes them harder to read.
> + {
> + explicit entry_point_info (std::optional<CORE_ADDR> inferior_entry_address,
You can drop explicit, as the constructor has two parameters.
> + std::optional<CORE_ADDR> exec_entry_address)
> + : m_inferior_entry_address (std::move (inferior_entry_address)),
> + m_exec_entry_address (std::move (exec_entry_address))
I'm not sure it helps to std::move optional<CORE_ADDR>.
> + { /* Nothing. */ }
> +
> + DISABLE_COPY_AND_ASSIGN (entry_point_info);
> +
> + /* The entry address within the inferior as a whole. See the member
> + variable definition below for more details. */
> + const std::optional<CORE_ADDR> &inferior_entry_address () const
> + {
> + return m_inferior_entry_address;
> + }
> +
> + /* The entry address within the main executable. See the member
> + variable definition below for more details. */
> + const std::optional<CORE_ADDR> &exec_entry_address () const
> + {
> + return m_exec_entry_address;
> + }
std::optional<CORE_ADDR> is small enough (16 bytes) that I would return
it by value.
> diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
> index 8e3de4d3ea1..12f3e783744 100644
> --- a/gdb/solib-svr4.c
> +++ b/gdb/solib-svr4.c
> @@ -3777,6 +3777,91 @@ svr4_solib_ops::get_solibs_in_ns (int nsid) const
> return ns_solibs;
> }
>
> +/* See solib.h. */
> +
> +std::optional<CORE_ADDR>
> +svr4_solib_ops::inferior_entry_point_address () const
> +{
> + std::optional<gdb::byte_vector> interp_name_holder
> + = svr4_find_program_interpreter ();
> +
> + /* No interpreter means this is a static executable. Ask the
> + program_space for the entry address within the main executable. */
> + if (!interp_name_holder.has_value ())
> + return m_pspace->exec_entry_point_address_if_available ();
> +
> + /* For a dynamically linked executable the inferior's true entry point
> + is the entry point of the dynamic linker. We find this using the
> + AT_BASE auxiliary vector entry, which gives the dynamic linker's
> + load address, combined with e_entry address pulled from the
> + inferior. We assume that the ELF header can be read from AT_BASE. */
> + CORE_ADDR at_base_addr;
> + if (target_auxv_search (AT_BASE, &at_base_addr) <= 0)
> + return {};
> +
> + /* Determine ELF architecture type. Use the size of a program header
> + entry to determine which ELF header we can expect to find. */
> + size_t e_entry_offset = 0;
> + size_t e_entry_size = 0;
> + CORE_ADDR at_phent;
> + if (target_auxv_search (AT_PHENT, &at_phent) <= 0)
> + return {};
> + if (at_phent == sizeof (Elf32_External_Phdr))
> + {
> + e_entry_offset = offsetof (Elf32_External_Ehdr, e_entry);
> + e_entry_size = 4;
> + }
> + else if (at_phent == sizeof (Elf64_External_Phdr))
> + {
> + e_entry_offset = offsetof (Elf64_External_Ehdr, e_entry);
> + e_entry_size = 8;
> + }
> + else
> + return {};
> +
> + /* Architecture of the current inferior. */
> + gdbarch *gdbarch = current_inferior ()->arch ();
> +
> + /* Read the entry address from the ELF header at AT_BASE_ADDR. */
> + CORE_ADDR e_entry;
> + gdb_byte buffer[sizeof (CORE_ADDR)];
> + if (target_read_memory (at_base_addr + e_entry_offset, buffer, e_entry_size))
> + return {};
> + bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> + e_entry = extract_unsigned_integer (buffer, e_entry_size, byte_order);
> +
> + /* Ensure AT_BASE_ADDR has proper sign in its possible upper bits so
> + that `+ at_base_addr' will overflow CORE_ADDR width not creating
> + invalid addresses like 0x101234567 for 32bit inferiors on 64bit
> + GDB. */
> + int addr_bit = gdbarch_addr_bit (gdbarch);
> + if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
> + {
> + CORE_ADDR space_size = (CORE_ADDR) 1 << addr_bit;
> +
> + gdb_assert (at_base_addr < space_size);
> +
> + /* E_ENTRY exceeding SPACE_SIZE would be for prelinked
> + 64bit ld.so with 32bit executable, it should not happen. */
> + if (e_entry < space_size
> + && e_entry + at_base_addr >= space_size)
> + at_base_addr -= space_size;
> + }
> +
> + /* Compute the entry address. */
> + e_entry = at_base_addr + e_entry;
> +
> + /* Handle the case where E_ENTRY is a function descriptor. Also remove
> + any non-address (e.g. tag) bits from E_ENTRY. */
> + e_entry
> + = gdbarch_convert_from_func_ptr_addr (gdbarch, e_entry,
> + current_inferior ()->top_target ());
> + e_entry
> + = gdbarch_addr_bits_remove (gdbarch, e_entry);
> +
> + return e_entry;
> +}
Is there some code to be shared with svr4_solib_ops::enable_break,
regarding fetching AT_BASE and the checks / post processing that
follows?
> diff --git a/gdb/testsuite/gdb.base/bt-after-starti.exp b/gdb/testsuite/gdb.base/bt-after-starti.exp
> new file mode 100644
> index 00000000000..c2a78a05cf4
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/bt-after-starti.exp
> @@ -0,0 +1,215 @@
> +# Copyright 2026 Free Software Foundation, Inc.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +
> +# Check that 'bt' from the very first instruction (where 'starti'
> +# stops GDB) doesn't display any unexpected frames.
> +
> +require !use_gdb_stub
I think you used this because of the use of the gdb_starti_cmd proc. It
might be possible to make it work for native-gdbserver: after
connection, the inferior should be at the very first instruction. But
coverage with native-extended-gdbserver is perhaps sufficient too.
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index a19e8ba6729..085f098fd6e 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -4217,6 +4217,45 @@ proc is_aarch64_target {} {
> return [expr {![is_aarch32_target]}]
> }
>
> +# Return true for svr4 targets, otherwise, return false.
> +
> +proc is_svr4_target {} {
> + return [expr {[istarget *-linux*] || [istarget *-freebsd*]
> + || [istarget *-netbsd*] || [istarget *-openbsd*]
> + || [istarget *-solaris*] || [istarget *-gnu]}]
> +}
> +
> +# Return false for targets that don't support finding the whole
> +# process entry address, otherwise, return true.
I find it surprising to read that you use the negative first, it would
be more typical to read:
# Return true for targets that support finding the whole process entry
# address, otherwise, return false.
> +
> +proc supports_process_entry_point {} {
> + # SVR4 targets support finding the entry point. This is done
> + # within GDB so will work even for remote targets.
> + if {[is_svr4_target]} {
> + return true
> + }
> +
> + # Windows and Darwin don't currently support this.
> + if {[istarget *-*-mingw*]
> + || [istarget *-*-cygwin*]
> + || [istarget *-*-pe*]
> + || [istarget *-*-darwin*]} {
> + return false
> + }
> +
> + # For remote targets there is no RSP packet to retrieve the entry
> + # point, so this won't work unless the solib code can handle this
> + # within GDB, see the svr4 check above.
> + if {[gdb_protocol_is_remote]} {
> + return false
> + }
> +
> + # Assume everything else supports this by default. If a test
> + # fails because we get here then either fix GDB to support this
> + # feature, or add a new deny list entry above.
> + return true
> +}
I can't verify the logic here, but from the comments it sounds fine.
Simon
next prev parent reply other threads:[~2026-07-10 15:40 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-08 18:14 [PATCH] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-06-11 19:24 ` Guinevere Larsen
2026-06-11 20:40 ` Andrew Burgess
2026-06-12 12:49 ` Guinevere Larsen
2026-06-11 21:59 ` [PATCHv2 0/3] " Andrew Burgess
2026-06-11 21:59 ` [PATCHv2 1/3] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-06-12 15:41 ` Pedro Alves
2026-06-11 21:59 ` [PATCHv2 2/3] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-06-12 6:07 ` Eli Zaretskii
2026-06-15 10:14 ` Andrew Burgess
2026-06-15 12:01 ` Eli Zaretskii
2026-06-12 15:41 ` Pedro Alves
2026-06-15 10:29 ` Andrew Burgess
2026-06-16 18:36 ` Pedro Alves
2026-06-23 9:46 ` Andrew Burgess
2026-06-23 10:20 ` Pedro Alves
2026-06-11 21:59 ` [PATCHv2 3/3] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-06-12 15:57 ` Pedro Alves
2026-06-16 19:47 ` [PATCHv3 0/4] " Andrew Burgess
2026-06-16 19:47 ` [PATCHv3 1/4] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-06-16 19:47 ` [PATCHv3 2/4] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-06-17 11:52 ` Eli Zaretskii
2026-06-16 19:47 ` [PATCHv3 3/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-06-16 19:47 ` [PATCHv3 4/4] gdb: cache program space entry point information Andrew Burgess
2026-06-23 10:47 ` [PATCHv4 0/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-06-23 10:47 ` [PATCHv4 1/4] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-06-23 10:47 ` [PATCHv4 2/4] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-06-23 10:47 ` [PATCHv4 3/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-06-23 10:47 ` [PATCHv4 4/4] gdb: cache program space entry point information Andrew Burgess
2026-06-25 15:26 ` [PATCHv5 0/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-06-25 15:26 ` [PATCHv5 1/4] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-06-25 15:26 ` [PATCHv5 2/4] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-06-25 15:26 ` [PATCHv5 3/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-06-25 15:26 ` [PATCHv5 4/4] gdb: cache program space entry point information Andrew Burgess
2026-07-10 14:24 ` [PATCHv6 0/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-07-10 14:24 ` [PATCHv6 1/4] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-07-10 14:24 ` [PATCHv6 2/4] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-07-10 15:39 ` Simon Marchi [this message]
2026-07-10 14:24 ` [PATCHv6 3/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-07-10 17:00 ` Simon Marchi
2026-07-10 17:01 ` Simon Marchi
2026-07-16 15:06 ` Andrew Burgess
2026-07-10 14:24 ` [PATCHv6 4/4] gdb: cache program space entry point information Andrew Burgess
2026-07-10 17:07 ` Simon Marchi
2026-07-18 13:11 ` [PATCHv7 0/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-07-18 13:11 ` [PATCHv7 1/4] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-07-18 13:11 ` [PATCHv7 2/4] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-07-18 13:11 ` [PATCHv7 3/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-07-18 13:11 ` [PATCHv7 4/4] gdb: cache program space entry point information Andrew Burgess
2026-07-20 9:52 ` [PATCHv8 0/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-07-20 9:52 ` [PATCHv8 1/4] gdb: rename program_space::entry_point_address* functions Andrew Burgess
2026-07-20 9:52 ` [PATCHv8 2/4] gdb: introduce program_space::get_entry_point_info function Andrew Burgess
2026-07-20 9:52 ` [PATCHv8 3/4] gdb: allow 'until' to work in outermost frame Andrew Burgess
2026-07-20 9:52 ` [PATCHv8 4/4] gdb: cache program space entry point information Andrew Burgess
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=a0146d34-7e9e-4c0d-8410-7e2dcac2eeb9@simark.ca \
--to=simark@simark.ca \
--cc=aburgess@redhat.com \
--cc=eliz@gnu.org \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox