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, |