aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marchi <simon.marchi@efficios.com>2025-07-22 15:08:40 -0400
committerSimon Marchi <simon.marchi@efficios.com>2025-08-22 10:45:48 -0400
commita7ba2c42b807d1f23b2cc11598973a1c7386e379 (patch)
treeefaa7d39462e8ab1889328f0ac8425f6a7ed32d6
parentfbb487b4510dc2cd6cf7e82df062d7e40eeb8c27 (diff)
downloadbinutils-a7ba2c42b807d1f23b2cc11598973a1c7386e379.zip
binutils-a7ba2c42b807d1f23b2cc11598973a1c7386e379.tar.gz
binutils-a7ba2c42b807d1f23b2cc11598973a1c7386e379.tar.bz2
gdb/solib-svr4: centralize fetching of default debug base
When running an inferior, solib_ops_svr4::current_sos is called very early, at a point where the default debug base is not yet accessible. The inferior is stopped at its entry point, before the dynamic linker had the time to fill the DT_DEBUG slot. It only becomes available a little bit later. In a following patch, I will want to do some action when the debug base becomes known (namely, update the debug base in the previously created lm_info_svr4 instances). For this reason, add the svr4_solib_ops::default_debug_base method to centralize where we fetch the default debug base. I will then be able to add my code there, when detecting the debug base changes. This patch brings the following behavior change: since all svr4_solib_ops entry points now use svr4_solib_ops::default_debug_base to get the debug base value, they will now all re-fetch the value from the inferior. Previously, this was not done consistently, only in two spots. It seems to me like it would be good to be consistent about that, because we can't really predict which methods will get called in which order in all scenarios. Some internal methods still access svr4_info::default_debug_base directly, because it is assumed that their caller would have used svr4_solib_ops::default_debug_base, updating the value in svr4_info::default_debug_base if necessary. Change-Id: Ie08da34bbb3ad6fd317c0e5802c5c94d8c7d1ce5 Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
-rw-r--r--gdb/solib-svr4.c102
-rw-r--r--gdb/solib-svr4.h4
2 files changed, 69 insertions, 37 deletions
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 7f10323..eb25087 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -335,8 +335,11 @@ struct svr4_so
struct svr4_info
{
- /* Base of dynamic linker structures in default namespace. */
- CORE_ADDR debug_base = 0;
+ /* Base of dynamic linker structures in default namespace.
+
+ The value is fetched from the inferior every time we need it. This field
+ represents the last known value. */
+ CORE_ADDR default_debug_base = 0;
/* Validity flag for debug_loader_offset. */
int debug_loader_offset_p = 0;
@@ -442,7 +445,7 @@ svr4_maybe_add_namespace (svr4_info *info, CORE_ADDR lmid)
static bool
svr4_is_default_namespace (const svr4_info *info, CORE_ADDR debug_base)
{
- return (debug_base == info->debug_base);
+ return debug_base == info->default_debug_base;
}
/* Free the probes table. */
@@ -707,8 +710,8 @@ scan_dyntag_auxv (const int desired_dyntag, CORE_ADDR *ptr,
return 0;
}
-/* Locate the base address of dynamic linker structs for SVR4 elf
- targets.
+/* Locate the base address the dynamic linker structure for the default
+ namespace.
For SVR4 elf targets the address of the dynamic linker's runtime
structure is contained within the dynamic info section in the
@@ -717,10 +720,13 @@ scan_dyntag_auxv (const int desired_dyntag, CORE_ADDR *ptr,
real address before starting the inferior, we have to read in the
dynamic info section from the inferior address space.
If there are any errors while trying to find the address, we
- silently return 0, otherwise the found address is returned. */
+ silently return 0, otherwise the found address is returned.
+
+ If we try to read the address before the dynamic linker had a change to
+ fill in the real address, this will also typically return 0. */
static CORE_ADDR
-elf_locate_base (void)
+locate_default_debug_base ()
{
CORE_ADDR dyn_ptr, dyn_ptr_addr;
@@ -784,6 +790,20 @@ elf_locate_base (void)
return 0;
}
+/* See solib-svr4.h. */
+
+CORE_ADDR
+svr4_solib_ops::default_debug_base (svr4_info *info, bool *changed) const
+{
+ CORE_ADDR default_debug_base = locate_default_debug_base ();
+
+ if (changed != nullptr)
+ *changed = default_debug_base == info->default_debug_base;
+
+ info->default_debug_base = default_debug_base;
+ return default_debug_base;
+}
+
/* Find the first element in the inferior's dynamic link map, and
return its address in the inferior. Return zero if the address
could not be determined.
@@ -822,8 +842,10 @@ svr4_solib_ops::find_r_brk (svr4_info *info) const
type *ptr_type
= builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
- return read_memory_typed_address (info->debug_base + lmo->r_brk_offset,
- ptr_type);
+ gdb_assert (info->default_debug_base != 0);
+
+ return read_memory_typed_address ((info->default_debug_base
+ + lmo->r_brk_offset), ptr_type);
}
/* Find the link map for the dynamic linker (if it is not in the
@@ -838,12 +860,15 @@ svr4_solib_ops::find_r_ldsomap (svr4_info *info) const
enum bfd_endian byte_order = type_byte_order (ptr_type);
ULONGEST version = 0;
+ gdb_assert (info->default_debug_base != 0);
+
try
{
/* Check version, and return zero if `struct r_debug' doesn't have
the r_ldsomap member. */
version
- = read_memory_unsigned_integer (info->debug_base + lmo->r_version_offset,
+ = read_memory_unsigned_integer ((info->default_debug_base
+ + lmo->r_version_offset),
lmo->r_version_size, byte_order);
}
catch (const gdb_exception_error &ex)
@@ -854,7 +879,8 @@ svr4_solib_ops::find_r_ldsomap (svr4_info *info) const
if (version < 2 || lmo->r_ldsomap_offset == -1)
return 0;
- return read_memory_typed_address (info->debug_base + lmo->r_ldsomap_offset,
+ return read_memory_typed_address ((info->default_debug_base
+ + lmo->r_ldsomap_offset),
ptr_type);
}
@@ -903,9 +929,9 @@ svr4_solib_ops::keep_data_in_core (CORE_ADDR vaddr, unsigned long size) const
CORE_ADDR name_lm;
info = get_svr4_info (current_program_space);
+ CORE_ADDR default_debug_base = this->default_debug_base (info);
- info->debug_base = elf_locate_base ();
- if (info->debug_base == 0)
+ if (default_debug_base == 0)
return false;
ldsomap = this->find_r_ldsomap (info);
@@ -939,13 +965,13 @@ svr4_solib_ops::open_symbol_file_object (int from_tty) const
if (!query (_("Attempt to reload symbols from process? ")))
return false;
- /* Always locate the debug struct, in case it has moved. */
- info->debug_base = elf_locate_base ();
- if (info->debug_base == 0)
+ CORE_ADDR default_debug_base = this->default_debug_base (info);
+
+ if (default_debug_base == 0)
return false; /* failed somehow... */
/* First link map member should be the executable. */
- lm = this->read_r_map (info->debug_base);
+ lm = this->read_r_map (default_debug_base);
if (lm == 0)
return false; /* failed somehow... */
@@ -1345,8 +1371,9 @@ svr4_solib_ops::current_sos_direct (svr4_info *info) const
/* If we can't find the dynamic linker's base structure, this
must not be a dynamically linked executable. Hmm. */
- info->debug_base = elf_locate_base ();
- if (info->debug_base == 0)
+ CORE_ADDR default_debug_base = this->default_debug_base (info);
+
+ if (default_debug_base == 0)
return;
/* Assume that everything is a library if the dynamic loader was loaded
@@ -1365,7 +1392,8 @@ svr4_solib_ops::current_sos_direct (svr4_info *info) const
});
/* Collect the sos in each namespace. */
- CORE_ADDR debug_base = info->debug_base;
+ CORE_ADDR debug_base = default_debug_base;
+
for (; debug_base != 0;
ignore_first = false, debug_base = this->read_r_next (debug_base))
{
@@ -2160,17 +2188,14 @@ svr4_solib_ops::handle_event () const
if (debug_base == 0)
return;
- /* If the global _r_debug object moved, we need to reload everything
- since we cannot identify namespaces (by the location of their
- r_debug_ext object) anymore. */
- CORE_ADDR global_debug_base = elf_locate_base ();
- if (global_debug_base != info->debug_base)
- {
- info->debug_base = global_debug_base;
- action = FULL_RELOAD;
- }
+ bool default_debug_base_changed;
+ CORE_ADDR default_debug_base
+ = this->default_debug_base (info, &default_debug_base_changed);
+
+ if (default_debug_base_changed)
+ action = FULL_RELOAD;
- if (info->debug_base == 0)
+ if (default_debug_base == 0)
{
/* It's possible for the reloc_complete probe to be triggered before
the linker has set the DT_DEBUG pointer (for example, when the
@@ -2461,7 +2486,6 @@ svr4_solib_ops::enable_break (svr4_info *info, int from_tty) const
{
const char * const *bkpt_namep;
asection *interp_sect;
- CORE_ADDR sym_addr;
info->interp_text_sect_low = info->interp_text_sect_high = 0;
info->interp_plt_sect_low = info->interp_plt_sect_high = 0;
@@ -2472,8 +2496,11 @@ svr4_solib_ops::enable_break (svr4_info *info, int from_tty) const
is the object containing r_brk. */
solib_add (NULL, from_tty, auto_solib_add);
- sym_addr = 0;
- if (info->debug_base && this->read_r_map (info->debug_base) != 0)
+
+ CORE_ADDR sym_addr = 0;
+ CORE_ADDR default_debug_base = this->default_debug_base (info);
+
+ if (default_debug_base != 0 && this->read_r_map (default_debug_base) != 0)
sym_addr = this->find_r_brk (info);
if (sym_addr != 0)
@@ -3295,7 +3322,7 @@ void
svr4_solib_ops::clear_solib (program_space *pspace) const
{
svr4_info *info = get_svr4_info (pspace);
- info->debug_base = 0;
+ info->default_debug_base = 0;
info->debug_loader_offset_p = 0;
info->debug_loader_offset = 0;
info->debug_loader_name.clear ();
@@ -3627,11 +3654,12 @@ svr4_solib_ops::iterate_over_objfiles_in_search_order
/* The linker namespace to iterate identified by the address of its
r_debug object, defaulting to the initial namespace. */
- CORE_ADDR initial = elf_locate_base ();
+ svr4_info *info = get_svr4_info (current_program_space);
+ CORE_ADDR default_debug_base = this->default_debug_base (info);
const solib *curr_solib = find_solib_for_objfile (current_objfile);
CORE_ADDR debug_base = find_debug_base_for_solib (curr_solib);
if (debug_base == 0)
- debug_base = initial;
+ debug_base = default_debug_base;
for (objfile *objfile : m_pspace->objfiles ())
{
@@ -3646,7 +3674,7 @@ svr4_solib_ops::iterate_over_objfiles_in_search_order
const solib *solib = find_solib_for_objfile (objfile);
CORE_ADDR solib_base = find_debug_base_for_solib (solib);
if (solib_base == 0)
- solib_base = initial;
+ solib_base = default_debug_base;
/* Ignore objfiles that were added to a different namespace. */
if (solib_base != debug_base)
diff --git a/gdb/solib-svr4.h b/gdb/solib-svr4.h
index 9a70c8f..4584d18 100644
--- a/gdb/solib-svr4.h
+++ b/gdb/solib-svr4.h
@@ -136,6 +136,10 @@ private:
int update_incremental (svr4_info *info, CORE_ADDR debug_base,
CORE_ADDR lm) const;
bool update_event_breakpoint (breakpoint *b) const;
+
+ /* Return the base address of the dynamic linker structure for the default
+ namespace. */
+ CORE_ADDR default_debug_base (svr4_info *info, bool *changed = nullptr) const;
};
/* solib_ops for ILP32 SVR4 systems. */