/* Handle shared libraries for GDB, the GNU Debugger.
- Copyright (C) 1990-2019 Free Software Foundation, Inc.
+ Copyright (C) 1990-2022 Free Software Foundation, Inc.
This file is part of GDB.
#include "command.h"
#include "target.h"
#include "frame.h"
-#include "gdb_regex.h"
+#include "gdbsupport/gdb_regex.h"
#include "inferior.h"
-#include "common/environ.h"
+#include "gdbsupport/environ.h"
#include "language.h"
#include "gdbcmd.h"
#include "completer.h"
+#include "elf/external.h"
+#include "elf/common.h"
#include "filenames.h" /* for DOSish file names */
#include "exec.h"
#include "solist.h"
#include "observable.h"
-#include "readline/readline.h"
+#include "readline/tilde.h"
#include "remote.h"
#include "solib.h"
#include "interps.h"
#include "filesystem.h"
#include "gdb_bfd.h"
-#include "common/filestuff.h"
+#include "gdbsupport/filestuff.h"
#include "source.h"
+#include "cli/cli-style.h"
/* Architecture-specific operations. */
/* If non-empty, this is a search path for loading non-absolute shared library
symbol files. This takes precedence over the environment variables PATH
and LD_LIBRARY_PATH. */
-static char *solib_search_path = NULL;
+static std::string solib_search_path;
static void
show_solib_search_path (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
* If IS_SOLIB is non-zero:
* Look in inferior's $LD_LIBRARY_PATH.
*
- * The last check avoids doing this search when targetting remote
+ * The last check avoids doing this search when targeting remote
* machines since a sysroot will almost always be set.
*/
static gdb::unique_xmalloc_ptr<char>
-solib_find_1 (const char *in_pathname, int *fd, int is_solib)
+solib_find_1 (const char *in_pathname, int *fd, bool is_solib)
{
const struct target_so_ops *ops = solib_ops (target_gdbarch ());
int found_file = -1;
gdb::unique_xmalloc_ptr<char> temp_pathname;
const char *fskind = effective_target_file_system_kind ();
- const char *sysroot = gdb_sysroot;
+ const char *sysroot = gdb_sysroot.c_str ();
int prefix_len, orig_prefix_len;
/* If the absolute prefix starts with "target:" but the filesystem
temp_pathname.reset (xstrdup (in_pathname));
else
{
- int need_dir_separator;
+ bool need_dir_separator;
/* Concatenate the sysroot and the target reported filename. We
may need to glue them with a directory separator. Cases to
consider:
- | sysroot | separator | in_pathname |
- |-----------------+-----------+----------------|
- | /some/dir | / | c:/foo/bar.dll |
- | /some/dir | | /foo/bar.dll |
- | target: | | c:/foo/bar.dll |
- | target: | | /foo/bar.dll |
- | target:some/dir | / | c:/foo/bar.dll |
- | target:some/dir | | /foo/bar.dll |
+ | sysroot | separator | in_pathname |
+ |-----------------+-----------+----------------|
+ | /some/dir | / | c:/foo/bar.dll |
+ | /some/dir | | /foo/bar.dll |
+ | target: | | c:/foo/bar.dll |
+ | target: | | /foo/bar.dll |
+ | target:some/dir | / | c:/foo/bar.dll |
+ | target:some/dir | | /foo/bar.dll |
IOW, we don't need to add a separator if IN_PATHNAME already
has one, or when the sysroot is exactly "target:".
}
/* Now see if we can open it. */
- found_file = gdb_open_cloexec (temp_pathname.get (), O_RDONLY | O_BINARY, 0);
+ found_file = gdb_open_cloexec (temp_pathname.get (),
+ O_RDONLY | O_BINARY, 0).release ();
/* If the search in gdb_sysroot failed, and the path name has a
drive spec (e.g, c:/foo), try stripping ':' from the drive spec,
&& sysroot != NULL
&& HAS_TARGET_DRIVE_SPEC (fskind, in_pathname))
{
- int need_dir_separator = !IS_DIR_SEPARATOR (in_pathname[2]);
+ bool need_dir_separator = !IS_DIR_SEPARATOR (in_pathname[2]);
char drive[2] = { in_pathname[0], '\0' };
temp_pathname.reset (concat (sysroot,
in_pathname + 2, (char *) NULL));
found_file = gdb_open_cloexec (temp_pathname.get (),
- O_RDONLY | O_BINARY, 0);
+ O_RDONLY | O_BINARY, 0).release ();
if (found_file < 0)
{
/* If the search in gdb_sysroot still failed, try fully
in_pathname + 2, (char *) NULL));
found_file = gdb_open_cloexec (temp_pathname.get (),
- O_RDONLY | O_BINARY, 0);
+ O_RDONLY | O_BINARY, 0).release ();
}
}
/* If not found, and we're looking for a solib, search the
solib_search_path (if any). */
- if (is_solib && found_file < 0 && solib_search_path != NULL)
- found_file = openp (solib_search_path,
+ if (is_solib && found_file < 0 && !solib_search_path.empty ())
+ found_file = openp (solib_search_path.c_str (),
OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
in_pathname, O_RDONLY | O_BINARY, &temp_pathname);
solib_search_path (if any) for the basename only (ignoring the
path). This is to allow reading solibs from a path that differs
from the opened path. */
- if (is_solib && found_file < 0 && solib_search_path != NULL)
- found_file = openp (solib_search_path,
+ if (is_solib && found_file < 0 && !solib_search_path.empty ())
+ found_file = openp (solib_search_path.c_str (),
OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
target_lbasename (fskind, in_pathname),
O_RDONLY | O_BINARY, &temp_pathname);
if (in_pathname == NULL)
return NULL;
- if (*gdb_sysroot != '\0' && IS_TARGET_ABSOLUTE_PATH (fskind, in_pathname))
+ if (!gdb_sysroot.empty () && IS_TARGET_ABSOLUTE_PATH (fskind, in_pathname))
{
- result = solib_find_1 (in_pathname, fd, 0);
+ result = solib_find_1 (in_pathname, fd, false);
if (result == NULL && fskind == file_system_kind_dos_based)
{
strcpy (new_pathname, in_pathname);
strcat (new_pathname, ".exe");
- result = solib_find_1 (new_pathname, fd, 0);
+ result = solib_find_1 (new_pathname, fd, false);
}
}
else
}
}
- return solib_find_1 (in_pathname, fd, 1);
+ return solib_find_1 (in_pathname, fd, true);
}
/* Open and return a BFD for the shared library PATHNAME. If FD is not -1,
/* Check bfd format. */
if (!bfd_check_format (abfd.get (), bfd_object))
error (_("`%s': not in executable format: %s"),
- bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
+ bfd_get_filename (abfd.get ()), bfd_errmsg (bfd_get_error ()));
/* Check bfd arch. */
b = gdbarch_bfd_arch_info (target_gdbarch ());
if (!b->compatible (b, bfd_get_arch_info (abfd.get ())))
warning (_("`%s': Shared library architecture %s is not compatible "
- "with target architecture %s."), bfd_get_filename (abfd),
- bfd_get_arch_info (abfd.get ())->printable_name,
+ "with target architecture %s."), bfd_get_filename (abfd.get ()),
+ bfd_get_arch_info (abfd.get ())->printable_name,
b->printable_name);
return abfd;
solib_map_sections (struct so_list *so)
{
const struct target_so_ops *ops = solib_ops (target_gdbarch ());
- struct target_section *p;
gdb::unique_xmalloc_ptr<char> filename (tilde_expand (so->so_name));
gdb_bfd_ref_ptr abfd (ops->bfd_open (filename.get ()));
error (_("Shared library file name is too long."));
strcpy (so->so_name, bfd_get_filename (so->abfd));
- if (build_section_table (so->abfd, &so->sections, &so->sections_end))
- {
- error (_("Can't find the file sections in `%s': %s"),
- bfd_get_filename (so->abfd), bfd_errmsg (bfd_get_error ()));
- }
+ if (so->sections == nullptr)
+ so->sections = new target_section_table;
+ *so->sections = build_section_table (so->abfd);
- for (p = so->sections; p < so->sections_end; p++)
+ for (target_section &p : *so->sections)
{
/* Relocate the section binding addresses as recorded in the shared
- object's file by the base address to which the object was actually
- mapped. */
- ops->relocate_section_addresses (so, p);
+ object's file by the base address to which the object was actually
+ mapped. */
+ ops->relocate_section_addresses (so, &p);
/* If the target didn't provide information about the address
range of the shared object, assume we want the location of
the .text section. */
if (so->addr_low == 0 && so->addr_high == 0
- && strcmp (p->the_bfd_section->name, ".text") == 0)
+ && strcmp (p.the_bfd_section->name, ".text") == 0)
{
- so->addr_low = p->addr;
- so->addr_high = p->endaddr;
+ so->addr_low = p.addr;
+ so->addr_high = p.endaddr;
}
}
section tables. Do this immediately after mapping the object so
that later nodes in the list can query this object, as is needed
in solib-osf.c. */
- add_target_sections (so, so->sections, so->sections_end);
+ current_program_space->add_target_sections (so, *so->sections);
return 1;
}
{
const struct target_so_ops *ops = solib_ops (target_gdbarch ());
- if (so->sections)
- {
- xfree (so->sections);
- so->sections = so->sections_end = NULL;
- }
+ delete so->sections;
+ so->sections = NULL;
gdb_bfd_unref (so->abfd);
so->abfd = NULL;
}
-/* Return address of first so_list entry in master shared object list. */
-struct so_list *
-master_so_list (void)
-{
- return so_list_head;
-}
-
/* Read in symbols for shared object SO. If SYMFILE_VERBOSE is set in FLAGS,
- be chatty about it. Return non-zero if any symbols were actually
- loaded. */
+ be chatty about it. Return true if any symbols were actually loaded. */
-int
+bool
solib_read_symbols (struct so_list *so, symfile_add_flags flags)
{
if (so->symbols_loaded)
if (so->objfile == NULL)
{
section_addr_info sap
- = build_section_addr_info_from_section_table (so->sections,
- so->sections_end);
+ = build_section_addr_info_from_section_table (*so->sections);
so->objfile = symbol_file_add_from_bfd (so->abfd, so->so_name,
flags, &sap,
OBJF_SHARED, NULL);
so->so_name);
}
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-/* Return 1 if KNOWN->objfile is used by any other so_list object in the
- SO_LIST_HEAD list. Return 0 otherwise. */
+/* Return true if KNOWN->objfile is used by any other so_list object
+ in the list of shared libraries. Return false otherwise. */
-static int
+static bool
solib_used (const struct so_list *const known)
{
- const struct so_list *pivot;
-
- for (pivot = so_list_head; pivot != NULL; pivot = pivot->next)
+ for (const struct so_list *pivot : current_program_space->solibs ())
if (pivot != known && pivot->objfile == known->objfile)
- return 1;
- return 0;
+ return true;
+ return false;
}
/* See solib.h. */
/* We can reach here due to changing solib-search-path or the
sysroot, before having any inferior. */
- if (target_has_execution && inferior_ptid != null_ptid)
+ if (target_has_execution () && inferior_ptid != null_ptid)
{
struct inferior *inf = current_inferior ();
/* If we are attaching to a running process for which we
have not opened a symbol file, we may be able to get its
symbols now! */
- if (inf->attach_flag && symfile_objfile == NULL)
+ if (inf->attach_flag
+ && current_program_space->symfile_object_file == NULL)
{
try
{
the time we're done walking GDB's list, the inferior's list
contains only the new shared objects, which we then add. */
- gdb = so_list_head;
- gdb_link = &so_list_head;
+ gdb = current_program_space->so_list;
+ gdb_link = ¤t_program_space->so_list;
while (gdb)
{
struct so_list *i = inferior;
}
/* If the shared object appears on the inferior's list too, then
- it's still loaded, so we don't need to do anything. Delete
- it from the inferior's list, and leave it on GDB's list. */
+ it's still loaded, so we don't need to do anything. Delete
+ it from the inferior's list, and leave it on GDB's list. */
if (i)
{
*i_link = i->next;
/* Unless the user loaded it explicitly, free SO's objfile. */
if (gdb->objfile && ! (gdb->objfile->flags & OBJF_USERLOADED)
&& !solib_used (gdb))
- delete gdb->objfile;
+ gdb->objfile->unlink ();
/* Some targets' section tables might be referring to
sections from so->abfd; remove them. */
- remove_target_sections (gdb);
+ current_program_space->remove_target_sections (gdb);
free_so (gdb);
gdb = *gdb_link;
Uses a fairly simplistic heuristic approach where we check
the file name against "/libpthread". This can lead to false
- positives, but this should be good enough in practice. */
+ positives, but this should be good enough in practice.
-int
+ As of glibc-2.34, functions formerly residing in libpthread have
+ been moved to libc, so "/libc." needs to be checked too. (Matching
+ the "." will avoid matching libraries such as libcrypt.) */
+
+bool
libpthread_name_p (const char *name)
{
- return (strstr (name, "/libpthread") != NULL);
+ return (strstr (name, "/libpthread") != NULL
+ || strstr (name, "/libc.") != NULL );
}
/* Return non-zero if SO is the libpthread shared library. */
-static int
+static bool
libpthread_solib_p (struct so_list *so)
{
return libpthread_name_p (so->so_name);
void
solib_add (const char *pattern, int from_tty, int readsyms)
{
- struct so_list *gdb;
-
if (print_symbol_loading_p (from_tty, 0, 0))
{
if (pattern != NULL)
symbols for any that match the pattern --- or any whose symbols
aren't already loaded, if no pattern was given. */
{
- int any_matches = 0;
- int loaded_any_symbols = 0;
+ bool any_matches = false;
+ bool loaded_any_symbols = false;
symfile_add_flags add_flags = SYMFILE_DEFER_BP_RESET;
if (from_tty)
- add_flags |= SYMFILE_VERBOSE;
+ add_flags |= SYMFILE_VERBOSE;
- for (gdb = so_list_head; gdb; gdb = gdb->next)
+ for (struct so_list *gdb : current_program_space->solibs ())
if (! pattern || re_exec (gdb->so_name))
{
- /* Normally, we would read the symbols from that library
- only if READSYMS is set. However, we're making a small
- exception for the pthread library, because we sometimes
- need the library symbols to be loaded in order to provide
- thread support (x86-linux for instance). */
- const int add_this_solib =
- (readsyms || libpthread_solib_p (gdb));
-
- any_matches = 1;
+ /* Normally, we would read the symbols from that library
+ only if READSYMS is set. However, we're making a small
+ exception for the pthread library, because we sometimes
+ need the library symbols to be loaded in order to provide
+ thread support (x86-linux for instance). */
+ const int add_this_solib =
+ (readsyms || libpthread_solib_p (gdb));
+
+ any_matches = true;
if (add_this_solib)
{
if (gdb->symbols_loaded)
gdb->so_name);
}
else if (solib_read_symbols (gdb, add_flags))
- loaded_any_symbols = 1;
+ loaded_any_symbols = true;
}
}
static void
info_sharedlibrary_command (const char *pattern, int from_tty)
{
- struct so_list *so = NULL; /* link map state variable */
- int so_missing_debug_info = 0;
+ bool so_missing_debug_info = false;
int addr_width;
int nr_libs;
struct gdbarch *gdbarch = target_gdbarch ();
/* ui_out_emit_table table_emitter needs to know the number of rows,
so we need to make two passes over the libs. */
- for (nr_libs = 0, so = so_list_head; so; so = so->next)
+ nr_libs = 0;
+ for (struct so_list *so : current_program_space->solibs ())
{
if (so->so_name[0])
{
uiout->table_body ();
- ALL_SO_LIBS (so)
+ for (struct so_list *so : current_program_space->solibs ())
{
if (! so->so_name[0])
continue;
&& so->symbols_loaded
&& !objfile_has_symbols (so->objfile))
{
- so_missing_debug_info = 1;
+ so_missing_debug_info = true;
uiout->field_string ("syms-read", "Yes (*)");
}
else
uiout->field_string ("syms-read", so->symbols_loaded ? "Yes" : "No");
- uiout->field_string ("name", so->so_name, ui_out_style_kind::FILE);
+ uiout->field_string ("name", so->so_name, file_name_style.style ());
uiout->text ("\n");
}
}
}
-/* Return 1 if ADDRESS lies within SOLIB. */
+/* See solib.h. */
-int
+bool
solib_contains_address_p (const struct so_list *const solib,
CORE_ADDR address)
{
- struct target_section *p;
+ if (solib->sections == nullptr)
+ return false;
- for (p = solib->sections; p < solib->sections_end; p++)
- if (p->addr <= address && address < p->endaddr)
- return 1;
+ for (target_section &p : *solib->sections)
+ if (p.addr <= address && address < p.endaddr)
+ return true;
- return 0;
+ return false;
}
/* If ADDRESS is in a shared lib in program space PSPACE, return its
return (0);
}
-/* Return whether the data starting at VADDR, size SIZE, must be kept
- in a core file for shared libraries loaded before "gcore" is used
- to be handled correctly when the core file is loaded. This only
- applies when the section would otherwise not be kept in the core
- file (in particular, for readonly sections). */
+/* See solib.h. */
-int
+bool
solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
{
const struct target_so_ops *ops = solib_ops (target_gdbarch ());
if (ops->keep_data_in_core)
- return ops->keep_data_in_core (vaddr, size);
+ return ops->keep_data_in_core (vaddr, size) != 0;
else
- return 0;
+ return false;
}
/* Called by free_all_symtabs */
disable_breakpoints_in_shlibs ();
- while (so_list_head)
+ while (current_program_space->so_list)
{
- struct so_list *so = so_list_head;
+ struct so_list *so = current_program_space->so_list;
- so_list_head = so->next;
+ current_program_space->so_list = so->next;
gdb::observers::solib_unloaded.notify (so);
- remove_target_sections (so);
+ current_program_space->remove_target_sections (so);
free_so (so);
}
ops->solib_create_inferior_hook (from_tty);
}
-/* Check to see if an address is in the dynamic loader's dynamic
- symbol resolution code. Return 1 if so, 0 otherwise. */
+/* See solib.h. */
-int
+bool
in_solib_dynsym_resolve_code (CORE_ADDR pc)
{
const struct target_so_ops *ops = solib_ops (target_gdbarch ());
- return ops->in_dynsym_resolve_code (pc);
+ return ops->in_dynsym_resolve_code (pc) != 0;
}
/* Implements the "sharedlibrary" command. */
if (ops->handle_event != NULL)
ops->handle_event ();
- clear_program_space_solib_cache (current_inferior ()->pspace);
+ current_inferior ()->pspace->clear_solib_cache ();
/* Check for any newly added shared libraries if we're supposed to
be adding them automatically. Switch terminal for any messages
static void
reload_shared_libraries_1 (int from_tty)
{
- struct so_list *so;
-
if (print_symbol_loading_p (from_tty, 0, 0))
printf_unfiltered (_("Loading symbols for shared libraries.\n"));
- for (so = so_list_head; so != NULL; so = so->next)
+ for (struct so_list *so : current_program_space->solibs ())
{
- char *found_pathname = NULL;
- int was_loaded = so->symbols_loaded;
+ const char *found_pathname = NULL;
+ bool was_loaded = so->symbols_loaded != 0;
symfile_add_flags add_flags = SYMFILE_DEFER_BP_RESET;
if (from_tty)
{
if (so->objfile && ! (so->objfile->flags & OBJF_USERLOADED)
&& !solib_used (so))
- delete so->objfile;
- remove_target_sections (so);
+ so->objfile->unlink ();
+ current_program_space->remove_target_sections (so);
clear_so (so);
}
&& (!was_loaded
|| filename_cmp (found_pathname, so->so_name) != 0))
{
- int got_error = 0;
+ bool got_error = false;
try
{
exception_fprintf (gdb_stderr, e,
_("Error while mapping "
"shared library sections:\n"));
- got_error = 1;
+ got_error = true;
}
if (!got_error
Absent this call, if we've just connected to a target and set
solib-absolute-prefix or solib-search-path, we'll lose all information
about ld.so. */
- if (target_has_execution)
+ if (target_has_execution ())
{
/* Reset or free private data structures not associated with
so_list entries. */
const char *old_prefix = "remote:";
const char *new_prefix = TARGET_SYSROOT_PREFIX;
- if (startswith (gdb_sysroot, old_prefix))
+ if (startswith (gdb_sysroot.c_str (), old_prefix))
{
- static int warning_issued = 0;
+ static bool warning_issued = false;
gdb_assert (strlen (old_prefix) == strlen (new_prefix));
- memcpy (gdb_sysroot, new_prefix, strlen (new_prefix));
+ gdb_sysroot = new_prefix + gdb_sysroot.substr (strlen (old_prefix));
if (!warning_issued)
{
warning (_("\"%s\" is deprecated, use \"%s\" instead."),
old_prefix, new_prefix);
- warning (_("sysroot set to \"%s\"."), gdb_sysroot);
+ warning (_("sysroot set to \"%s\"."), gdb_sysroot.c_str ());
- warning_issued = 1;
+ warning_issued = true;
}
}
}
-/* Handler for library-specific lookup of global symbol NAME in OBJFILE. Call
- the library-specific handler if it is installed for the current target. */
-
-struct block_symbol
-solib_global_lookup (struct objfile *objfile,
- const char *name,
- const domain_enum domain)
-{
- const struct target_so_ops *ops = solib_ops (target_gdbarch ());
-
- if (ops->lookup_lib_global_symbol != NULL)
- return ops->lookup_lib_global_symbol (objfile, name, domain);
- return {};
-}
-
/* Lookup the value for a specific symbol from dynamic symbol table. Look
up symbol from ABFD. MATCH_SYM is a callback function to determine
whether to pick up a symbol. DATA is the input of this callback
symaddr = sym->value;
/* Some ELF targets fiddle with addresses of symbols they
- consider special. They use minimal symbols to do that
- and this is needed for correct breakpoint placement,
- but we do not have full data here to build a complete
- minimal symbol, so just set the address and let the
- targets cope with that. */
+ consider special. They use minimal symbols to do that
+ and this is needed for correct breakpoint placement,
+ but we do not have full data here to build a complete
+ minimal symbol, so just set the address and let the
+ targets cope with that. */
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& gdbarch_elf_make_msymbol_special_p (gdbarch))
{
return symaddr;
}
+/* See solib.h. */
+
+int
+gdb_bfd_scan_elf_dyntag (const int desired_dyntag, bfd *abfd, CORE_ADDR *ptr,
+ CORE_ADDR *ptr_addr)
+{
+ int arch_size, step, sect_size;
+ long current_dyntag;
+ CORE_ADDR dyn_ptr, dyn_addr;
+ gdb_byte *bufend, *bufstart, *buf;
+ Elf32_External_Dyn *x_dynp_32;
+ Elf64_External_Dyn *x_dynp_64;
+ struct bfd_section *sect;
+
+ if (abfd == NULL)
+ return 0;
+
+ if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+ return 0;
+
+ arch_size = bfd_get_arch_size (abfd);
+ if (arch_size == -1)
+ return 0;
+
+ /* Find the start address of the .dynamic section. */
+ sect = bfd_get_section_by_name (abfd, ".dynamic");
+ if (sect == NULL)
+ return 0;
+
+ bool found = false;
+ for (const target_section &target_section
+ : current_program_space->target_sections ())
+ if (sect == target_section.the_bfd_section)
+ {
+ dyn_addr = target_section.addr;
+ found = true;
+ break;
+ }
+ if (!found)
+ {
+ /* ABFD may come from OBJFILE acting only as a symbol file without being
+ loaded into the target (see add_symbol_file_command). This case is
+ such fallback to the file VMA address without the possibility of
+ having the section relocated to its actual in-memory address. */
+
+ dyn_addr = bfd_section_vma (sect);
+ }
+
+ /* Read in .dynamic from the BFD. We will get the actual value
+ from memory later. */
+ sect_size = bfd_section_size (sect);
+ buf = bufstart = (gdb_byte *) alloca (sect_size);
+ if (!bfd_get_section_contents (abfd, sect,
+ buf, 0, sect_size))
+ return 0;
+
+ /* Iterate over BUF and scan for DYNTAG. If found, set PTR and return. */
+ step = (arch_size == 32) ? sizeof (Elf32_External_Dyn)
+ : sizeof (Elf64_External_Dyn);
+ for (bufend = buf + sect_size;
+ buf < bufend;
+ buf += step)
+ {
+ if (arch_size == 32)
+ {
+ x_dynp_32 = (Elf32_External_Dyn *) buf;
+ current_dyntag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_tag);
+ dyn_ptr = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_un.d_ptr);
+ }
+ else
+ {
+ x_dynp_64 = (Elf64_External_Dyn *) buf;
+ current_dyntag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag);
+ dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr);
+ }
+ if (current_dyntag == DT_NULL)
+ return 0;
+ if (current_dyntag == desired_dyntag)
+ {
+ /* If requested, try to read the runtime value of this .dynamic
+ entry. */
+ if (ptr)
+ {
+ struct type *ptr_type;
+ gdb_byte ptr_buf[8];
+ CORE_ADDR ptr_addr_1;
+
+ ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
+ ptr_addr_1 = dyn_addr + (buf - bufstart) + arch_size / 8;
+ if (target_read_memory (ptr_addr_1, ptr_buf, arch_size / 8) == 0)
+ dyn_ptr = extract_typed_address (ptr_buf, ptr_type);
+ *ptr = dyn_ptr;
+ if (ptr_addr)
+ *ptr_addr = dyn_addr + (buf - bufstart);
+ }
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/* Lookup the value for a specific symbol from symbol table. Look up symbol
from ABFD. MATCH_SYM is a callback function to determine whether to pick
up a symbol. DATA is the input of this callback function. Return NULL
return symaddr;
}
-/* SO_LIST_HEAD may contain user-loaded object files that can be removed
- out-of-band by the user. So upon notification of free_objfile remove
- all references to any user-loaded file that is about to be freed. */
+/* The shared library list may contain user-loaded object files that
+ can be removed out-of-band by the user. So upon notification of
+ free_objfile remove all references to any user-loaded file that is
+ about to be freed. */
static void
remove_user_added_objfile (struct objfile *objfile)
{
- struct so_list *so;
-
if (objfile != 0 && objfile->flags & OBJF_USERLOADED)
{
- for (so = so_list_head; so != NULL; so = so->next)
+ for (struct so_list *so : current_program_space->solibs ())
if (so->objfile == objfile)
so->objfile = NULL;
}
}
+void _initialize_solib ();
void
-_initialize_solib (void)
+_initialize_solib ()
{
solib_data = gdbarch_data_register_pre_init (solib_init);
- gdb::observers::free_objfile.attach (remove_user_added_objfile);
+ gdb::observers::free_objfile.attach (remove_user_added_objfile,
+ "solib");
+ gdb::observers::inferior_execd.attach ([] (inferior *inf)
+ {
+ solib_create_inferior_hook (0);
+ }, "solib");
add_com ("sharedlibrary", class_files, sharedlibrary_command,
_("Load shared object library symbols for files matching REGEXP."));
- add_info ("sharedlibrary", info_sharedlibrary_command,
- _("Status of loaded shared object libraries."));
- add_info_alias ("dll", "sharedlibrary", 1);
+ cmd_list_element *info_sharedlibrary_cmd
+ = add_info ("sharedlibrary", info_sharedlibrary_command,
+ _("Status of loaded shared object libraries."));
+ add_info_alias ("dll", info_sharedlibrary_cmd, 1);
add_com ("nosharedlibrary", class_files, no_shared_libraries,
_("Unload all shared object library symbols."));
show_auto_solib_add,
&setlist, &showlist);
- add_setshow_optional_filename_cmd ("sysroot", class_support,
- &gdb_sysroot, _("\
+ set_show_commands sysroot_cmds
+ = add_setshow_optional_filename_cmd ("sysroot", class_support,
+ &gdb_sysroot, _("\
Set an alternate system root."), _("\
Show the current system root."), _("\
The system root is used to load absolute shared library symbol files.\n\
For other (relative) files, you can add directories using\n\
`set solib-search-path'."),
- gdb_sysroot_changed,
- NULL,
- &setlist, &showlist);
+ gdb_sysroot_changed,
+ NULL,
+ &setlist, &showlist);
- add_alias_cmd ("solib-absolute-prefix", "sysroot", class_support, 0,
+ add_alias_cmd ("solib-absolute-prefix", sysroot_cmds.set, class_support, 0,
&setlist);
- add_alias_cmd ("solib-absolute-prefix", "sysroot", class_support, 0,
+ add_alias_cmd ("solib-absolute-prefix", sysroot_cmds.show, class_support, 0,
&showlist);
add_setshow_optional_filename_cmd ("solib-search-path", class_support,