| Index: gdb/solib.c
|
| diff --git a/gdb/solib.c b/gdb/solib.c
|
| index 90439ba584df76fab8ae9d4bfb53c9f32a1e4aba..1a9215a2605a79a051de1d40e2a5637b67bfd515 100644
|
| --- a/gdb/solib.c
|
| +++ b/gdb/solib.c
|
| @@ -1,6 +1,6 @@
|
| /* Handle shared libraries for GDB, the GNU Debugger.
|
|
|
| - Copyright (C) 1990-2003, 2005-2012 Free Software Foundation, Inc.
|
| + Copyright (C) 1990-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -21,7 +21,7 @@
|
|
|
| #include <sys/types.h>
|
| #include <fcntl.h>
|
| -#include "gdb_string.h"
|
| +#include <string.h>
|
| #include "symtab.h"
|
| #include "bfd.h"
|
| #include "symfile.h"
|
| @@ -46,6 +46,8 @@
|
| #include "solib.h"
|
| #include "interps.h"
|
| #include "filesystem.h"
|
| +#include "gdb_bfd.h"
|
| +#include "filestuff.h"
|
|
|
| /* Architecture-specific operations. */
|
|
|
| @@ -62,10 +64,10 @@ solib_init (struct obstack *obstack)
|
| return ops;
|
| }
|
|
|
| -static struct target_so_ops *
|
| +static const struct target_so_ops *
|
| solib_ops (struct gdbarch *gdbarch)
|
| {
|
| - struct target_so_ops **ops = gdbarch_data (gdbarch, solib_data);
|
| + const struct target_so_ops **ops = gdbarch_data (gdbarch, solib_data);
|
|
|
| return *ops;
|
| }
|
| @@ -73,9 +75,9 @@ solib_ops (struct gdbarch *gdbarch)
|
| /* Set the solib operations for GDBARCH to NEW_OPS. */
|
|
|
| void
|
| -set_solib_ops (struct gdbarch *gdbarch, struct target_so_ops *new_ops)
|
| +set_solib_ops (struct gdbarch *gdbarch, const struct target_so_ops *new_ops)
|
| {
|
| - struct target_so_ops **ops = gdbarch_data (gdbarch, solib_data);
|
| + const struct target_so_ops **ops = gdbarch_data (gdbarch, solib_data);
|
|
|
| *ops = new_ops;
|
| }
|
| @@ -142,12 +144,12 @@ show_solib_search_path (struct ui_file *file, int from_tty,
|
| char *
|
| solib_find (char *in_pathname, int *fd)
|
| {
|
| - struct target_so_ops *ops = solib_ops (target_gdbarch);
|
| + const struct target_so_ops *ops = solib_ops (target_gdbarch ());
|
| int found_file = -1;
|
| char *temp_pathname = NULL;
|
| int gdb_sysroot_is_empty;
|
| const char *solib_symbols_extension
|
| - = gdbarch_solib_symbols_extension (target_gdbarch);
|
| + = gdbarch_solib_symbols_extension (target_gdbarch ());
|
| const char *fskind = effective_target_file_system_kind ();
|
| struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
|
| char *sysroot = NULL;
|
| @@ -228,7 +230,25 @@ solib_find (char *in_pathname, int *fd)
|
| {
|
| int need_dir_separator;
|
|
|
| - need_dir_separator = !IS_DIR_SEPARATOR (in_pathname[0]);
|
| + /* 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 |
|
| + | remote: | | c:/foo/bar.dll |
|
| + | remote: | | /foo/bar.dll |
|
| + | remote:some/dir | / | c:/foo/bar.dll |
|
| + | remote:some/dir | | /foo/bar.dll |
|
| +
|
| + IOW, we don't need to add a separator if IN_PATHNAME already
|
| + has one, or when the the sysroot is exactly "remote:".
|
| + There's no need to check for drive spec explicitly, as we only
|
| + get here if IN_PATHNAME is considered an absolute path. */
|
| + need_dir_separator = !(IS_DIR_SEPARATOR (in_pathname[0])
|
| + || strcmp (REMOTE_SYSROOT_PREFIX, sysroot) == 0);
|
|
|
| /* Cat the prefixed pathname together. */
|
| temp_pathname = concat (sysroot,
|
| @@ -245,7 +265,7 @@ solib_find (char *in_pathname, int *fd)
|
| }
|
|
|
| /* Now see if we can open it. */
|
| - found_file = open (temp_pathname, O_RDONLY | O_BINARY, 0);
|
| + found_file = gdb_open_cloexec (temp_pathname, O_RDONLY | O_BINARY, 0);
|
| if (found_file < 0)
|
| xfree (temp_pathname);
|
|
|
| @@ -268,7 +288,7 @@ solib_find (char *in_pathname, int *fd)
|
| in_pathname + 2, (char *) NULL);
|
| xfree (drive);
|
|
|
| - found_file = open (temp_pathname, O_RDONLY | O_BINARY, 0);
|
| + found_file = gdb_open_cloexec (temp_pathname, O_RDONLY | O_BINARY, 0);
|
| if (found_file < 0)
|
| {
|
| xfree (temp_pathname);
|
| @@ -283,7 +303,7 @@ solib_find (char *in_pathname, int *fd)
|
| need_dir_separator ? SLASH_STRING : "",
|
| in_pathname + 2, (char *) NULL);
|
|
|
| - found_file = open (temp_pathname, O_RDONLY | O_BINARY, 0);
|
| + found_file = gdb_open_cloexec (temp_pathname, O_RDONLY | O_BINARY, 0);
|
| if (found_file < 0)
|
| xfree (temp_pathname);
|
| }
|
| @@ -299,11 +319,6 @@ solib_find (char *in_pathname, int *fd)
|
| if (found_file < 0)
|
| temp_pathname = NULL;
|
|
|
| - /* 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, &temp_pathname);
|
| -
|
| /* If the search in gdb_sysroot failed, and the path name is
|
| absolute at this point, make it relative. (openp will try and open the
|
| file according to its absolute path otherwise, which is not what we want.)
|
| @@ -321,14 +336,16 @@ solib_find (char *in_pathname, int *fd)
|
|
|
| /* 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,
|
| + found_file = openp (solib_search_path,
|
| + OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
|
| 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,
|
| + found_file = openp (solib_search_path,
|
| + OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
|
| target_lbasename (fskind, in_pathname),
|
| O_RDONLY | O_BINARY, &temp_pathname);
|
|
|
| @@ -341,16 +358,16 @@ solib_find (char *in_pathname, int *fd)
|
| if (found_file < 0 && gdb_sysroot_is_empty)
|
| found_file = openp (get_in_environ (current_inferior ()->environment,
|
| "PATH"),
|
| - OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY | O_BINARY,
|
| - &temp_pathname);
|
| + OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, 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 (current_inferior ()->environment,
|
| "LD_LIBRARY_PATH"),
|
| - OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY | O_BINARY,
|
| - &temp_pathname);
|
| + OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, in_pathname,
|
| + O_RDONLY | O_BINARY, &temp_pathname);
|
|
|
| *fd = found_file;
|
| return temp_pathname;
|
| @@ -360,9 +377,9 @@ solib_find (char *in_pathname, int *fd)
|
| 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). */
|
| + PATHNAME must be malloc'ed by the caller. It will be freed by this
|
| + function. If unsuccessful, the FD will be closed (unless FD was
|
| + -1). */
|
|
|
| bfd *
|
| solib_bfd_fopen (char *pathname, int fd)
|
| @@ -376,7 +393,7 @@ solib_bfd_fopen (char *pathname, int fd)
|
| }
|
| else
|
| {
|
| - abfd = bfd_fopen (pathname, gnutarget, FOPEN_RB, fd);
|
| + abfd = gdb_bfd_open (pathname, gnutarget, fd);
|
|
|
| if (abfd)
|
| bfd_set_cacheable (abfd, 1);
|
| @@ -389,6 +406,8 @@ solib_bfd_fopen (char *pathname, int fd)
|
| pathname, bfd_errmsg (bfd_get_error ()));
|
| }
|
|
|
| + xfree (pathname);
|
| +
|
| return abfd;
|
| }
|
|
|
| @@ -420,17 +439,16 @@ solib_bfd_open (char *pathname)
|
| /* Check bfd format. */
|
| if (!bfd_check_format (abfd, bfd_object))
|
| {
|
| - bfd_close (abfd);
|
| - make_cleanup (xfree, found_pathname);
|
| + make_cleanup_bfd_unref (abfd);
|
| error (_("`%s': not in executable format: %s"),
|
| - found_pathname, bfd_errmsg (bfd_get_error ()));
|
| + bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
|
| }
|
|
|
| /* Check bfd arch. */
|
| - b = gdbarch_bfd_arch_info (target_gdbarch);
|
| + 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,
|
| + "with target architecture %s."), bfd_get_filename (abfd),
|
| bfd_get_arch_info (abfd)->printable_name, b->printable_name);
|
|
|
| return abfd;
|
| @@ -451,7 +469,7 @@ solib_bfd_open (char *pathname)
|
| static int
|
| solib_map_sections (struct so_list *so)
|
| {
|
| - struct target_so_ops *ops = solib_ops (target_gdbarch);
|
| + const struct target_so_ops *ops = solib_ops (target_gdbarch ());
|
| char *filename;
|
| struct target_section *p;
|
| struct cleanup *old_chain;
|
| @@ -466,13 +484,7 @@ solib_map_sections (struct so_list *so)
|
| return 0;
|
|
|
| /* Leave bfd open, core_xfer_memory and "info files" need it. */
|
| - so->abfd = gdb_bfd_ref (abfd);
|
| -
|
| - /* copy full path name into so_name, so that later symbol_file_add
|
| - can find it. */
|
| - 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));
|
| + so->abfd = abfd;
|
|
|
| if (build_section_table (abfd, &so->sections, &so->sections_end))
|
| {
|
| @@ -502,22 +514,25 @@ solib_map_sections (struct so_list *so)
|
| 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->sections, so->sections_end);
|
| + add_target_sections (so, so->sections, so->sections_end);
|
|
|
| return 1;
|
| }
|
|
|
| -/* Free symbol-file related contents of SO. If we have opened a BFD
|
| - for SO, close it. If we have placed SO's sections in some target's
|
| - section table, the caller is responsible for removing them.
|
| +/* Free symbol-file related contents of SO and reset for possible reloading
|
| + of SO. If we have opened a BFD for SO, close it. If we have placed SO's
|
| + sections in some target's section table, the caller is responsible for
|
| + removing them.
|
|
|
| This function doesn't mess with objfiles at all. If there is an
|
| objfile associated with SO that needs to be removed, the caller is
|
| responsible for taking care of that. */
|
|
|
| static void
|
| -free_so_symbols (struct so_list *so)
|
| +clear_so (struct so_list *so)
|
| {
|
| + const struct target_so_ops *ops = solib_ops (target_gdbarch ());
|
| +
|
| if (so->sections)
|
| {
|
| xfree (so->sections);
|
| @@ -536,6 +551,10 @@ free_so_symbols (struct so_list *so)
|
| /* Restore the target-supplied file name. SO_NAME may be the path
|
| of the symbol file. */
|
| strcpy (so->so_name, so->so_original_name);
|
| +
|
| + /* Do the same for target-specific data. */
|
| + if (ops->clear_so != NULL)
|
| + ops->clear_so (so);
|
| }
|
|
|
| /* Free the storage associated with the `struct so_list' object SO.
|
| @@ -552,9 +571,9 @@ free_so_symbols (struct so_list *so)
|
| void
|
| free_so (struct so_list *so)
|
| {
|
| - struct target_so_ops *ops = solib_ops (target_gdbarch);
|
| + const struct target_so_ops *ops = solib_ops (target_gdbarch ());
|
|
|
| - free_so_symbols (so);
|
| + clear_so (so);
|
| ops->free_so (so);
|
|
|
| xfree (so);
|
| @@ -599,7 +618,7 @@ solib_read_symbols (struct so_list *so, int flags)
|
| /* Have we already loaded this shared object? */
|
| ALL_OBJFILES (so->objfile)
|
| {
|
| - if (filename_cmp (so->objfile->name, so->so_name) == 0
|
| + if (filename_cmp (objfile_name (so->objfile), so->so_name) == 0
|
| && so->objfile->addr_low == so->addr_low)
|
| break;
|
| }
|
| @@ -608,7 +627,7 @@ solib_read_symbols (struct so_list *so, int flags)
|
|
|
| sap = build_section_addr_info_from_section_table (so->sections,
|
| so->sections_end);
|
| - so->objfile = symbol_file_add_from_bfd (so->abfd,
|
| + so->objfile = symbol_file_add_from_bfd (so->abfd, so->so_name,
|
| flags, sap, OBJF_SHARED,
|
| NULL);
|
| so->objfile->addr_low = so->addr_low;
|
| @@ -671,7 +690,7 @@ solib_used (const struct so_list *const known)
|
| static void
|
| update_solib_list (int from_tty, struct target_ops *target)
|
| {
|
| - struct target_so_ops *ops = solib_ops (target_gdbarch);
|
| + const struct target_so_ops *ops = solib_ops (target_gdbarch ());
|
| struct so_list *inferior = ops->current_sos();
|
| struct so_list *gdb, **gdb_link;
|
|
|
| @@ -770,7 +789,7 @@ update_solib_list (int from_tty, struct target_ops *target)
|
|
|
| /* Some targets' section tables might be referring to
|
| sections from so->abfd; remove them. */
|
| - remove_target_sections (gdb->abfd);
|
| + remove_target_sections (gdb);
|
|
|
| free_so (gdb);
|
| gdb = *gdb_link;
|
| @@ -933,7 +952,7 @@ solib_add (char *pattern, int from_tty,
|
|
|
| if (loaded_any_symbols)
|
| {
|
| - struct target_so_ops *ops = solib_ops (target_gdbarch);
|
| + const struct target_so_ops *ops = solib_ops (target_gdbarch ());
|
|
|
| /* Getting new symbols may change our opinion about what is
|
| frameless. */
|
| @@ -957,7 +976,7 @@ info_sharedlibrary_command (char *pattern, int from_tty)
|
| int addr_width;
|
| int nr_libs;
|
| struct cleanup *table_cleanup;
|
| - struct gdbarch *gdbarch = target_gdbarch;
|
| + struct gdbarch *gdbarch = target_gdbarch ();
|
| struct ui_out *uiout = current_uiout;
|
|
|
| if (pattern)
|
| @@ -1106,7 +1125,7 @@ solib_name_from_address (struct program_space *pspace, CORE_ADDR address)
|
| int
|
| solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
|
| {
|
| - struct target_so_ops *ops = solib_ops (target_gdbarch);
|
| + const struct target_so_ops *ops = solib_ops (target_gdbarch ());
|
|
|
| if (ops->keep_data_in_core)
|
| return ops->keep_data_in_core (vaddr, size);
|
| @@ -1119,7 +1138,7 @@ solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
|
| void
|
| clear_solib (void)
|
| {
|
| - struct target_so_ops *ops = solib_ops (target_gdbarch);
|
| + const 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
|
| @@ -1151,8 +1170,7 @@ clear_solib (void)
|
|
|
| so_list_head = so->next;
|
| observer_notify_solib_unloaded (so);
|
| - if (so->abfd)
|
| - remove_target_sections (so->abfd);
|
| + remove_target_sections (so);
|
| free_so (so);
|
| }
|
|
|
| @@ -1167,7 +1185,7 @@ clear_solib (void)
|
| void
|
| solib_create_inferior_hook (int from_tty)
|
| {
|
| - struct target_so_ops *ops = solib_ops (target_gdbarch);
|
| + const struct target_so_ops *ops = solib_ops (target_gdbarch ());
|
|
|
| ops->solib_create_inferior_hook (from_tty);
|
| }
|
| @@ -1178,7 +1196,7 @@ solib_create_inferior_hook (int from_tty)
|
| int
|
| in_solib_dynsym_resolve_code (CORE_ADDR pc)
|
| {
|
| - struct target_so_ops *ops = solib_ops (target_gdbarch);
|
| + const struct target_so_ops *ops = solib_ops (target_gdbarch ());
|
|
|
| return ops->in_dynsym_resolve_code (pc);
|
| }
|
| @@ -1209,6 +1227,37 @@ no_shared_libraries (char *ignored, int from_tty)
|
| objfile_purge_solibs ();
|
| }
|
|
|
| +/* See solib.h. */
|
| +
|
| +void
|
| +update_solib_breakpoints (void)
|
| +{
|
| + const struct target_so_ops *ops = solib_ops (target_gdbarch ());
|
| +
|
| + if (ops->update_breakpoints != NULL)
|
| + ops->update_breakpoints ();
|
| +}
|
| +
|
| +/* See solib.h. */
|
| +
|
| +void
|
| +handle_solib_event (void)
|
| +{
|
| + const struct target_so_ops *ops = solib_ops (target_gdbarch ());
|
| +
|
| + if (ops->handle_event != NULL)
|
| + ops->handle_event ();
|
| +
|
| + clear_program_space_solib_cache (current_inferior ()->pspace);
|
| +
|
| + /* Check for any newly added shared libraries if we're supposed to
|
| + be adding them automatically. Switch terminal for any messages
|
| + produced by breakpoint_re_set. */
|
| + target_terminal_ours_for_output ();
|
| + solib_add (NULL, 0, ¤t_target, auto_solib_add);
|
| + target_terminal_inferior ();
|
| +}
|
| +
|
| /* Reload shared libraries, but avoid reloading the same symbol file
|
| we already have loaded. */
|
|
|
| @@ -1233,7 +1282,7 @@ reload_shared_libraries_1 (int from_tty)
|
| {
|
| found_pathname = xstrdup (bfd_get_filename (abfd));
|
| make_cleanup (xfree, found_pathname);
|
| - gdb_bfd_close_or_warn (abfd);
|
| + gdb_bfd_unref (abfd);
|
| }
|
|
|
| /* If this shared library is no longer associated with its previous
|
| @@ -1245,8 +1294,8 @@ reload_shared_libraries_1 (int from_tty)
|
| if (so->objfile && ! (so->objfile->flags & OBJF_USERLOADED)
|
| && !solib_used (so))
|
| free_objfile (so->objfile);
|
| - remove_target_sections (so->abfd);
|
| - free_so_symbols (so);
|
| + remove_target_sections (so);
|
| + clear_so (so);
|
| }
|
|
|
| /* If this shared library is now associated with a new symbol
|
| @@ -1276,11 +1325,11 @@ static void
|
| reload_shared_libraries (char *ignored, int from_tty,
|
| struct cmd_list_element *e)
|
| {
|
| - struct target_so_ops *ops;
|
| + const struct target_so_ops *ops;
|
|
|
| reload_shared_libraries_1 (from_tty);
|
|
|
| - ops = solib_ops (target_gdbarch);
|
| + ops = solib_ops (target_gdbarch ());
|
|
|
| /* Creating inferior hooks here has two purposes. First, if we reload
|
| shared libraries then the address of solib breakpoint we've computed
|
| @@ -1302,11 +1351,7 @@ reload_shared_libraries (char *ignored, int from_tty,
|
| we're not really starting up the inferior here. */
|
| remove_solib_event_breakpoints ();
|
|
|
| -#ifdef SOLIB_CREATE_INFERIOR_HOOK
|
| - SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
|
| -#else
|
| solib_create_inferior_hook (from_tty);
|
| -#endif
|
| }
|
|
|
| /* Sometimes the platform-specific hook loads initial shared
|
| @@ -1347,7 +1392,7 @@ solib_global_lookup (const struct objfile *objfile,
|
| const char *name,
|
| const domain_enum domain)
|
| {
|
| - struct target_so_ops *ops = solib_ops (target_gdbarch);
|
| + 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);
|
| @@ -1451,6 +1496,23 @@ gdb_bfd_lookup_symbol (bfd *abfd,
|
| 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. */
|
| +
|
| +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)
|
| + if (so->objfile == objfile)
|
| + so->objfile = NULL;
|
| + }
|
| +}
|
| +
|
| extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */
|
|
|
| void
|
| @@ -1458,6 +1520,8 @@ _initialize_solib (void)
|
| {
|
| solib_data = gdbarch_data_register_pre_init (solib_init);
|
|
|
| + observer_attach_free_objfile (remove_user_added_objfile);
|
| +
|
| add_com ("sharedlibrary", class_files, sharedlibrary_command,
|
| _("Load shared object library symbols for files matching REGEXP."));
|
| add_info ("sharedlibrary", info_sharedlibrary_command,
|
|
|