X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fsolib.c;h=a2ad0c4c1cdf475b943ee1155decd2166adf1a23;hb=82a3a7558d46b812cdc392c22cf5af0d87b4d3b5;hp=7e2f75891e108413188a0884c943ebb454e5db88;hpb=cb851954200d7cf1d391dc9d28dddbefd9840eac;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/solib.c b/gdb/solib.c index 7e2f75891e..a2ad0c4c1c 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -1,13 +1,14 @@ /* Handle shared libraries for GDB, the GNU Debugger. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. + 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. This file is part of GDB. 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 2 of the License, or + 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, @@ -16,9 +17,7 @@ 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, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ #include "defs.h" @@ -45,6 +44,9 @@ #include "solist.h" #include "observer.h" #include "readline/readline.h" +#include "remote.h" +#include "solib.h" +#include "interps.h" /* Architecture-specific operations. */ @@ -88,12 +90,8 @@ struct target_so_ops *current_target_so_ops; static struct so_list *so_list_head; /* List of known shared objects */ -static int solib_cleanup_queued = 0; /* make_run_cleanup called */ - /* Local function prototypes */ -static void do_clear_solib (void *); - /* 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. */ @@ -111,11 +109,11 @@ The search path for loading non-absolute shared library symbol files is %s.\n"), GLOBAL FUNCTION - solib_open -- Find a shared library file and open it. + solib_find -- Find a shared library file. SYNOPSIS - int solib_open (char *in_patname, char **found_pathname); + char *solib_find (char *in_pathname, int *fd); DESCRIPTION @@ -142,15 +140,16 @@ The search path for loading non-absolute shared library symbol files is %s.\n"), RETURNS - file handle for opened solib, or -1 for failure. */ + Full pathname of the shared library file, or NULL if not found. + (The pathname is malloc'ed; it needs to be freed by the caller.) + *FD is set to either -1 or an open file handle for the library. */ -int -solib_open (char *in_pathname, char **found_pathname) +char * +solib_find (char *in_pathname, int *fd) { - struct target_so_ops *ops = solib_ops (current_gdbarch); + struct target_so_ops *ops = solib_ops (target_gdbarch); int found_file = -1; char *temp_pathname = NULL; - char *p = in_pathname; int gdb_sysroot_is_empty; gdb_sysroot_is_empty = (gdb_sysroot == NULL || *gdb_sysroot == 0); @@ -173,6 +172,13 @@ solib_open (char *in_pathname, char **found_pathname) strcat (temp_pathname, in_pathname); } + /* Handle remote files. */ + if (remote_filename_p (temp_pathname)) + { + *fd = -1; + return xstrdup (temp_pathname); + } + /* Now see if we can open it. */ found_file = open (temp_pathname, O_RDONLY | O_BINARY, 0); @@ -205,14 +211,14 @@ solib_open (char *in_pathname, char **found_pathname) /* If not found, search the solib_search_path (if any). */ if (found_file < 0 && solib_search_path != NULL) found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST, - in_pathname, O_RDONLY | O_BINARY, 0, &temp_pathname); + in_pathname, O_RDONLY | O_BINARY, &temp_pathname); /* If not found, next search the 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 (found_file < 0 && solib_search_path != NULL) found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST, - lbasename (in_pathname), O_RDONLY | O_BINARY, 0, + lbasename (in_pathname), O_RDONLY | O_BINARY, &temp_pathname); /* If not found, try to use target supplied solib search method */ @@ -223,26 +229,93 @@ solib_open (char *in_pathname, char **found_pathname) /* If not found, next search the inferior's $PATH environment variable. */ if (found_file < 0 && gdb_sysroot_is_empty) found_file = openp (get_in_environ (inferior_environ, "PATH"), - OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY | O_BINARY, 0, + OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY | O_BINARY, &temp_pathname); /* If not found, next search the inferior's $LD_LIBRARY_PATH environment variable. */ if (found_file < 0 && gdb_sysroot_is_empty) found_file = openp (get_in_environ (inferior_environ, "LD_LIBRARY_PATH"), - OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY | O_BINARY, 0, + OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY | O_BINARY, &temp_pathname); - /* Done. If not found, tough luck. Return found_file and - (optionally) found_pathname. */ - if (temp_pathname) + *fd = found_file; + return temp_pathname; +} + +/* Open and return a BFD for the shared library PATHNAME. If FD is not -1, + it is used as file handle to open the file. Throws an error if the file + could not be opened. Handles both local and remote file access. + + PATHNAME must be malloc'ed by the caller. If successful, the new BFD's + name will point to it. If unsuccessful, PATHNAME will be freed and the + FD will be closed (unless FD was -1). */ + +bfd * +solib_bfd_fopen (char *pathname, int fd) +{ + bfd *abfd; + + if (remote_filename_p (pathname)) { - if (found_pathname != NULL) - *found_pathname = temp_pathname; - else - xfree (temp_pathname); + gdb_assert (fd == -1); + abfd = remote_bfd_open (pathname, gnutarget); + } + else + { + abfd = bfd_fopen (pathname, gnutarget, FOPEN_RB, fd); + + if (abfd) + bfd_set_cacheable (abfd, 1); + else if (fd != -1) + close (fd); + } + + if (!abfd) + { + make_cleanup (xfree, pathname); + error (_("Could not open `%s' as an executable file: %s"), + pathname, bfd_errmsg (bfd_get_error ())); + } + + return abfd; +} + +/* Find shared library PATHNAME and open a BFD for it. */ + +bfd * +solib_bfd_open (char *pathname) +{ + char *found_pathname; + int found_file; + bfd *abfd; + const struct bfd_arch_info *b; + + /* Search for shared library file. */ + found_pathname = solib_find (pathname, &found_file); + if (found_pathname == NULL) + perror_with_name (pathname); + + /* Open bfd for shared library. */ + abfd = solib_bfd_fopen (found_pathname, found_file); + + /* Check bfd format. */ + if (!bfd_check_format (abfd, bfd_object)) + { + bfd_close (abfd); + make_cleanup (xfree, found_pathname); + error (_("`%s': not in executable format: %s"), + found_pathname, bfd_errmsg (bfd_get_error ())); } - return found_file; + + /* Check bfd arch. */ + b = gdbarch_bfd_arch_info (target_gdbarch); + if (!b->compatible (b, bfd_get_arch_info (abfd))) + warning (_("`%s': Shared library architecture %s is not compatible " + "with target architecture %s."), found_pathname, + bfd_get_arch_info (abfd)->printable_name, b->printable_name); + + return abfd; } @@ -277,47 +350,26 @@ static int solib_map_sections (void *arg) { struct so_list *so = (struct so_list *) arg; /* catch_errors bogon */ + struct target_so_ops *ops = solib_ops (target_gdbarch); char *filename; - char *scratch_pathname; - int scratch_chan; - struct section_table *p; + struct target_section *p; struct cleanup *old_chain; bfd *abfd; filename = tilde_expand (so->so_name); - old_chain = make_cleanup (xfree, filename); - scratch_chan = solib_open (filename, &scratch_pathname); - - if (scratch_chan < 0) - { - perror_with_name (filename); - } - - /* Leave scratch_pathname allocated. abfd->name will point to it. */ - abfd = bfd_fopen (scratch_pathname, gnutarget, FOPEN_RB, scratch_chan); - if (!abfd) - { - close (scratch_chan); - error (_("Could not open `%s' as an executable file: %s"), - scratch_pathname, bfd_errmsg (bfd_get_error ())); - } + abfd = ops->bfd_open (filename); + do_cleanups (old_chain); /* Leave bfd open, core_xfer_memory and "info files" need it. */ - so->abfd = abfd; - bfd_set_cacheable (abfd, 1); + so->abfd = gdb_bfd_ref (abfd); /* copy full path name into so_name, so that later symbol_file_add can find it */ - if (strlen (scratch_pathname) >= SO_NAME_MAX_PATH_SIZE) - error (_("Full path name length of shared library exceeds SO_NAME_MAX_PATH_SIZE in so_list structure.")); - strcpy (so->so_name, scratch_pathname); + if (strlen (bfd_get_filename (abfd)) >= SO_NAME_MAX_PATH_SIZE) + error (_("Shared library file name is too long.")); + strcpy (so->so_name, bfd_get_filename (abfd)); - if (!bfd_check_format (abfd, bfd_object)) - { - error (_("\"%s\": not in executable format: %s."), - scratch_pathname, bfd_errmsg (bfd_get_error ())); - } if (build_section_table (abfd, &so->sections, &so->sections_end)) { error (_("Can't find the file sections in `%s': %s"), @@ -326,8 +378,6 @@ solib_map_sections (void *arg) for (p = so->sections; p < so->sections_end; p++) { - struct target_so_ops *ops = solib_ops (current_gdbarch); - /* Relocate the section binding addresses as recorded in the shared object's file by the base address to which the object was actually mapped. */ @@ -344,9 +394,6 @@ solib_map_sections (void *arg) } } - /* Free the file names, close the file now. */ - do_cleanups (old_chain); - return (1); } @@ -374,22 +421,12 @@ solib_map_sections (void *arg) void free_so (struct so_list *so) { - struct target_so_ops *ops = solib_ops (current_gdbarch); - char *bfd_filename = 0; + struct target_so_ops *ops = solib_ops (target_gdbarch); if (so->sections) xfree (so->sections); - - if (so->abfd) - { - bfd_filename = bfd_get_filename (so->abfd); - if (! bfd_close (so->abfd)) - warning (_("cannot close \"%s\": %s"), - bfd_filename, bfd_errmsg (bfd_get_error ())); - } - if (bfd_filename) - xfree (bfd_filename); + gdb_bfd_unref (so->abfd); ops->free_so (so); @@ -404,60 +441,63 @@ master_so_list (void) return so_list_head; } - -/* A small stub to get us past the arg-passing pinhole of catch_errors. */ - -static int -symbol_add_stub (void *arg) +static void +symbol_add_stub (struct so_list *so, int flags) { - struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */ struct section_addr_info *sap; /* Have we already loaded this shared object? */ ALL_OBJFILES (so->objfile) { if (strcmp (so->objfile->name, so->so_name) == 0) - return 1; + return; } sap = build_section_addr_info_from_section_table (so->sections, so->sections_end); - so->objfile = symbol_file_add (so->so_name, so->from_tty, - sap, 0, OBJF_SHARED); + so->objfile = symbol_file_add_from_bfd (so->abfd, flags, sap, OBJF_SHARED); free_section_addr_info (sap); - return (1); + return; } -/* Read in symbols for shared object SO. If FROM_TTY is non-zero, be - chatty about it. Return non-zero if any symbols were actually +/* 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. */ int -solib_read_symbols (struct so_list *so, int from_tty) +solib_read_symbols (struct so_list *so, int flags) { + const int from_tty = flags & SYMFILE_VERBOSE; + if (so->symbols_loaded) { - if (from_tty) + if (from_tty || info_verbose) printf_unfiltered (_("Symbols already loaded for %s\n"), so->so_name); } else if (so->abfd == NULL) { - if (from_tty) + if (from_tty || info_verbose) printf_unfiltered (_("Symbol file not found for %s\n"), so->so_name); } else { - if (catch_errors (symbol_add_stub, so, - "Error while reading shared library symbols:\n", - RETURN_MASK_ALL)) - { - if (from_tty) - printf_unfiltered (_("Loaded symbols for %s\n"), so->so_name); - so->symbols_loaded = 1; - return 1; - } + volatile struct gdb_exception exception; + TRY_CATCH (exception, RETURN_MASK_ALL) + { + symbol_add_stub (so, flags); + } + if (exception.reason != 0) + { + exception_fprintf (gdb_stderr, exception, + "Error while reading shared library symbols:\n"); + return 0; + } + if (from_tty || info_verbose) + printf_unfiltered (_("Loaded symbols for %s\n"), so->so_name); + so->symbols_loaded = 1; + return 1; } return 0; @@ -495,26 +535,23 @@ solib_read_symbols (struct so_list *so, int from_tty) static void update_solib_list (int from_tty, struct target_ops *target) { - struct target_so_ops *ops = solib_ops (current_gdbarch); + struct target_so_ops *ops = solib_ops (target_gdbarch); struct so_list *inferior = ops->current_sos(); struct so_list *gdb, **gdb_link; - /* 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 (attach_flag && - symfile_objfile == NULL) - catch_errors (ops->open_symbol_file_object, &from_tty, - "Error reading attached process's symbol file.\n", - RETURN_MASK_ALL); - - /* Since this function might actually add some elements to the - so_list_head list, arrange for it to be cleaned up when - appropriate. */ - if (!solib_cleanup_queued) + /* We can reach here due to changing solib-search-path or the + sysroot, before having any inferior. */ + if (target_has_execution && !ptid_equal (inferior_ptid, null_ptid)) { - make_run_cleanup (do_clear_solib, NULL); - solib_cleanup_queued = 1; + 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) + catch_errors (ops->open_symbol_file_object, &from_tty, + "Error reading attached process's symbol file.\n", + RETURN_MASK_ALL); } /* GDB and the inferior's dynamic linker each maintain their own @@ -552,8 +589,16 @@ update_solib_list (int from_tty, struct target_ops *target) the inferior's current list. */ while (i) { - if (! strcmp (gdb->so_original_name, i->so_original_name)) - break; + if (ops->same) + { + if (ops->same (gdb, i)) + break; + } + else + { + if (! strcmp (gdb->so_original_name, i->so_original_name)) + break; + } i_link = &i->next; i = *i_link; @@ -612,21 +657,11 @@ update_solib_list (int from_tty, struct target_ops *target) "Error while mapping shared library sections:\n", RETURN_MASK_ALL); - /* If requested, add the shared object's sections to the TARGET's - section table. 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. */ - if (target) - { - int count = (i->sections_end - i->sections); - if (count > 0) - { - int space = target_resize_to_sections (target, count); - memcpy (target->to_sections + space, - i->sections, - count * sizeof (i->sections[0])); - } - } + /* Add the shared object's sections to the current set of + file 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 (i->sections, i->sections_end); /* Notify any observer that the shared object has been loaded now that we've added it to GDB's tables. */ @@ -635,16 +670,25 @@ update_solib_list (int from_tty, struct target_ops *target) } } -/* Return non-zero if SO is the libpthread shared library. + +/* Return non-zero if NAME is the libpthread shared library. 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. */ +int +libpthread_name_p (const char *name) +{ + return (strstr (name, "/libpthread") != NULL); +} + +/* Return non-zero if SO is the libpthread shared library. */ + static int libpthread_solib_p (struct so_list *so) { - return (strstr (so->so_name, "/libpthread") != NULL); + return libpthread_name_p (so->so_name); } /* GLOBAL FUNCTION @@ -688,6 +732,8 @@ solib_add (char *pattern, int from_tty, struct target_ops *target, int readsyms) { int any_matches = 0; int loaded_any_symbols = 0; + const int flags = + SYMFILE_DEFER_BP_RESET | (from_tty ? SYMFILE_VERBOSE : 0); for (gdb = so_list_head; gdb; gdb = gdb->next) if (! pattern || re_exec (gdb->so_name)) @@ -701,17 +747,20 @@ solib_add (char *pattern, int from_tty, struct target_ops *target, int readsyms) (readsyms || libpthread_solib_p (gdb)); any_matches = 1; - if (add_this_solib && solib_read_symbols (gdb, from_tty)) + if (add_this_solib && solib_read_symbols (gdb, flags)) loaded_any_symbols = 1; } + if (loaded_any_symbols) + breakpoint_re_set (); + if (from_tty && pattern && ! any_matches) printf_unfiltered ("No loaded shared libraries match the pattern `%s'.\n", pattern); if (loaded_any_symbols) { - struct target_so_ops *ops = solib_ops (current_gdbarch); + struct target_so_ops *ops = solib_ops (target_gdbarch); /* Getting new symbols may change our opinion about what is frameless. */ @@ -736,64 +785,145 @@ solib_add (char *pattern, int from_tty, struct target_ops *target, int readsyms) DESCRIPTION Walk through the shared library list and print information - about each attached library. + about each attached library matching PATTERN. If PATTERN is elided, + print them all. */ static void -info_sharedlibrary_command (char *ignore, int from_tty) +info_sharedlibrary_command (char *pattern, int from_tty) { struct so_list *so = NULL; /* link map state variable */ int header_done = 0; + int so_missing_debug_info = 0; int addr_width; + int nr_libs; + struct cleanup *table_cleanup; + struct gdbarch *gdbarch = target_gdbarch; + + if (pattern) + { + char *re_err = re_comp (pattern); + + if (re_err) + error (_("Invalid regexp: %s"), re_err); + } /* "0x", a little whitespace, and two hex digits per byte of pointers. */ - addr_width = 4 + (gdbarch_ptr_bit (current_gdbarch) / 4); + addr_width = 4 + (gdbarch_ptr_bit (gdbarch) / 4); update_solib_list (from_tty, 0); - for (so = so_list_head; so; so = so->next) + /* make_cleanup_ui_out_table_begin_end 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) { if (so->so_name[0]) { - if (!header_done) - { - printf_unfiltered ("%-*s%-*s%-12s%s\n", addr_width, "From", - addr_width, "To", "Syms Read", - "Shared Object Library"); - header_done++; - } + if (pattern && ! re_exec (so->so_name)) + continue; + ++nr_libs; + } + } + + table_cleanup = + make_cleanup_ui_out_table_begin_end (uiout, 4, nr_libs, + "SharedLibraryTable"); - printf_unfiltered ("%-*s", addr_width, - so->addr_high != 0 - ? hex_string_custom ( - (LONGEST) so->addr_low, - addr_width - 4) - : ""); - printf_unfiltered ("%-*s", addr_width, - so->addr_high != 0 - ? hex_string_custom ( - (LONGEST) so->addr_high, - addr_width - 4) - : ""); - printf_unfiltered ("%-12s", so->symbols_loaded ? "Yes" : "No"); - printf_unfiltered ("%s\n", so->so_name); + /* The "- 1" is because ui_out adds one space between columns. */ + ui_out_table_header (uiout, addr_width - 1, ui_left, "from", "From"); + ui_out_table_header (uiout, addr_width - 1, ui_left, "to", "To"); + ui_out_table_header (uiout, 12 - 1, ui_left, "syms-read", "Syms Read"); + ui_out_table_header (uiout, 0, ui_noalign, + "name", "Shared Object Library"); + + ui_out_table_body (uiout); + + for (so = so_list_head; so; so = so->next) + { + struct cleanup *lib_cleanup; + + if (! so->so_name[0]) + continue; + if (pattern && ! re_exec (so->so_name)) + continue; + + lib_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, "lib"); + + if (so->addr_high != 0) + { + ui_out_field_core_addr (uiout, "from", gdbarch, so->addr_low); + ui_out_field_core_addr (uiout, "to", gdbarch, so->addr_high); } + else + { + ui_out_field_skip (uiout, "from"); + ui_out_field_skip (uiout, "to"); + } + + if (! ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ())) + && so->symbols_loaded + && !objfile_has_partial_symbols (so->objfile) + && !objfile_has_full_symbols (so->objfile)) + { + so_missing_debug_info = 1; + ui_out_field_string (uiout, "syms-read", "Yes (*)"); + } + else + ui_out_field_string (uiout, "syms-read", + so->symbols_loaded ? "Yes" : "No"); + + ui_out_field_string (uiout, "name", so->so_name); + + ui_out_text (uiout, "\n"); + + do_cleanups (lib_cleanup); } - if (so_list_head == NULL) + + do_cleanups (table_cleanup); + + if (nr_libs == 0) { - printf_unfiltered (_("No shared libraries loaded at this time.\n")); + if (pattern) + ui_out_message (uiout, 0, + _("No shared libraries matched.\n")); + else + ui_out_message (uiout, 0, + _("No shared libraries loaded at this time.\n")); } + else + { + if (so_missing_debug_info) + ui_out_message (uiout, 0, + _("(*): Shared library is missing debugging information.\n")); + } +} + +/* Return 1 if ADDRESS lies within SOLIB. */ + +int +solib_contains_address_p (const struct so_list *const solib, + CORE_ADDR address) +{ + struct target_section *p; + + for (p = solib->sections; p < solib->sections_end; p++) + if (p->addr <= address && address < p->endaddr) + return 1; + + return 0; } /* GLOBAL FUNCTION - solib_address -- check to see if an address is in a shared lib + solib_name_from_address -- if an address is in a shared lib, return + its name. SYNOPSIS - char * solib_address (CORE_ADDR address) + char * solib_name_from_address (CORE_ADDR address) DESCRIPTION @@ -807,20 +937,13 @@ info_sharedlibrary_command (char *ignore, int from_tty) */ char * -solib_address (CORE_ADDR address) +solib_name_from_address (CORE_ADDR address) { struct so_list *so = 0; /* link map state variable */ for (so = so_list_head; so; so = so->next) - { - struct section_table *p; - - for (p = so->sections; p < so->sections_end; p++) - { - if (p->addr <= address && address < p->endaddr) - return (so->so_name); - } - } + if (solib_contains_address_p (so, address)) + return (so->so_name); return (0); } @@ -830,7 +953,7 @@ solib_address (CORE_ADDR address) void clear_solib (void) { - struct target_so_ops *ops = solib_ops (current_gdbarch); + struct target_so_ops *ops = solib_ops (target_gdbarch); /* This function is expected to handle ELF shared libraries. It is also used on Solaris, which can run either ELF or a.out binaries @@ -860,6 +983,7 @@ clear_solib (void) { struct so_list *so = so_list_head; so_list_head = so->next; + observer_notify_solib_unloaded (so); if (so->abfd) remove_target_sections (so->abfd); free_so (so); @@ -868,13 +992,6 @@ clear_solib (void) ops->clear_solib (); } -static void -do_clear_solib (void *dummy) -{ - solib_cleanup_queued = 0; - clear_solib (); -} - /* GLOBAL FUNCTION solib_create_inferior_hook -- shared library startup support @@ -893,7 +1010,7 @@ do_clear_solib (void *dummy) void solib_create_inferior_hook (void) { - struct target_so_ops *ops = solib_ops (current_gdbarch); + struct target_so_ops *ops = solib_ops (target_gdbarch); ops->solib_create_inferior_hook(); } @@ -916,7 +1033,7 @@ solib_create_inferior_hook (void) int in_solib_dynsym_resolve_code (CORE_ADDR pc) { - struct target_so_ops *ops = solib_ops (current_gdbarch); + struct target_so_ops *ops = solib_ops (target_gdbarch); return ops->in_dynsym_resolve_code (pc); } @@ -956,8 +1073,13 @@ sharedlibrary_command (char *args, int from_tty) void no_shared_libraries (char *ignored, int from_tty) { + /* The order of the two routines below is important: clear_solib notifies + the solib_unloaded observers, and some of these observers might need + access to their associated objfiles. Therefore, we can not purge the + solibs' objfiles before clear_solib has been called. */ + + clear_solib (); objfile_purge_solibs (); - do_clear_solib (NULL); } static void @@ -966,6 +1088,28 @@ reload_shared_libraries (char *ignored, int from_tty, { no_shared_libraries (NULL, from_tty); solib_add (NULL, from_tty, NULL, auto_solib_add); + /* Creating inferior hooks here has two purposes. First, if we reload + shared libraries then the address of solib breakpoint we've computed + previously might be no longer valid. For example, if we forgot to set + solib-absolute-prefix and are setting it right now, then the previous + breakpoint address is plain wrong. Second, installing solib hooks + also implicitly figures were ld.so is and loads symbols for it. + 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) + { +#ifdef SOLIB_CREATE_INFERIOR_HOOK + SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid)); +#else + solib_create_inferior_hook (); +#endif + } + /* We have unloaded and then reloaded debug info for all shared libraries. + However, frames may still reference them, for example a frame's + unwinder might still point of DWARF FDE structures that are now freed. + Reinit frame cache to avoid crashing. */ + reinit_frame_cache (); } static void @@ -984,13 +1128,12 @@ struct symbol * solib_global_lookup (const struct objfile *objfile, const char *name, const char *linkage_name, - const domain_enum domain, - struct symtab **symtab) + const domain_enum domain) { - if (current_target_so_ops->lookup_lib_global_symbol != NULL) - return current_target_so_ops->lookup_lib_global_symbol (objfile, - name, linkage_name, domain, symtab); + struct target_so_ops *ops = solib_ops (target_gdbarch); + if (ops->lookup_lib_global_symbol != NULL) + return ops->lookup_lib_global_symbol (objfile, name, linkage_name, domain); return NULL; }