Index: gdb/symfile.c |
diff --git a/gdb/symfile.c b/gdb/symfile.c |
index 45cd175b532641a292baf06b6b6e0734137b1382..175d61c2a8860c282f65a4d91ad0879c7649397f 100644 |
--- a/gdb/symfile.c |
+++ b/gdb/symfile.c |
@@ -147,23 +147,6 @@ DEF_VEC_P (sym_fns_ptr); |
static VEC (sym_fns_ptr) *symtab_fns = NULL; |
-/* Flag for whether user will be reloading symbols multiple times. |
- Defaults to ON for VxWorks, otherwise OFF. */ |
- |
-#ifdef SYMBOL_RELOADING_DEFAULT |
-int symbol_reloading = SYMBOL_RELOADING_DEFAULT; |
-#else |
-int symbol_reloading = 0; |
-#endif |
-static void |
-show_symbol_reloading (struct ui_file *file, int from_tty, |
- struct cmd_list_element *c, const char *value) |
-{ |
- fprintf_filtered (file, _("Dynamic symbol table reloading " |
- "multiple times in one run is %s.\n"), |
- value); |
-} |
- |
/* If non-zero, shared library symbols will be added automatically |
when the inferior is created, new libraries are loaded, or when |
attaching to the inferior. This is almost always what users will |
@@ -561,7 +544,7 @@ addrs_section_compar (const void *ap, const void *bp) |
{ |
const struct other_sections *a = *((struct other_sections **) ap); |
const struct other_sections *b = *((struct other_sections **) bp); |
- int retval, a_idx, b_idx; |
+ int retval; |
retval = strcmp (addr_section_name (a->name), addr_section_name (b->name)); |
if (retval) |
@@ -1246,14 +1229,17 @@ symbol_file_add_main (char *args, int from_tty) |
static void |
symbol_file_add_main_1 (char *args, int from_tty, int flags) |
{ |
- const int add_flags = SYMFILE_MAINLINE | (from_tty ? SYMFILE_VERBOSE : 0); |
+ const int add_flags = (current_inferior ()->symfile_flags |
+ | SYMFILE_MAINLINE | (from_tty ? SYMFILE_VERBOSE : 0)); |
+ |
symbol_file_add (args, add_flags, NULL, flags); |
/* Getting new symbols may change our opinion about |
what is frameless. */ |
reinit_frame_cache (); |
- set_initial_language (); |
+ if ((flags & SYMFILE_NO_READ) == 0) |
+ set_initial_language (); |
} |
void |
@@ -1441,118 +1427,174 @@ show_debug_file_directory (struct ui_file *file, int from_tty, |
#define DEBUG_SUBDIRECTORY ".debug" |
#endif |
-char * |
-find_separate_debug_file_by_debuglink (struct objfile *objfile) |
+/* Find a separate debuginfo file for OBJFILE, using DIR as the directory |
+ where the original file resides (may not be the same as |
+ dirname(objfile->name) due to symlinks), and DEBUGLINK as the file we are |
+ looking for. Returns the name of the debuginfo, of NULL. */ |
+ |
+static char * |
+find_separate_debug_file (const char *dir, |
+ const char *canon_dir, |
+ const char *debuglink, |
+ unsigned long crc32, struct objfile *objfile) |
{ |
- char *basename, *debugdir; |
- char *dir = NULL; |
- char *debugfile = NULL; |
- char *canon_name = NULL; |
- unsigned long crc32; |
+ char *debugdir; |
+ char *debugfile; |
int i; |
+ VEC (char_ptr) *debugdir_vec; |
+ struct cleanup *back_to; |
+ int ix; |
- basename = get_debug_link_info (objfile, &crc32); |
- |
- if (basename == NULL) |
- /* There's no separate debug info, hence there's no way we could |
- load it => no warning. */ |
- goto cleanup_return_debugfile; |
- |
- dir = xstrdup (objfile->name); |
- |
- /* Strip off the final filename part, leaving the directory name, |
- followed by a slash. The directory can be relative or absolute. */ |
- for (i = strlen(dir) - 1; i >= 0; i--) |
- { |
- if (IS_DIR_SEPARATOR (dir[i])) |
- break; |
- } |
- /* If I is -1 then no directory is present there and DIR will be "". */ |
- dir[i+1] = '\0'; |
- |
- /* Set I to max (strlen (canon_name), strlen (dir)). */ |
- canon_name = lrealpath (dir); |
+ /* Set I to max (strlen (canon_dir), strlen (dir)). */ |
i = strlen (dir); |
- if (canon_name && strlen (canon_name) > i) |
- i = strlen (canon_name); |
+ if (canon_dir != NULL && strlen (canon_dir) > i) |
+ i = strlen (canon_dir); |
debugfile = xmalloc (strlen (debug_file_directory) + 1 |
+ i |
+ strlen (DEBUG_SUBDIRECTORY) |
+ strlen ("/") |
- + strlen (basename) |
+ + strlen (debuglink) |
+ 1); |
/* First try in the same directory as the original file. */ |
strcpy (debugfile, dir); |
- strcat (debugfile, basename); |
+ strcat (debugfile, debuglink); |
if (separate_debug_file_exists (debugfile, crc32, objfile)) |
- goto cleanup_return_debugfile; |
+ return debugfile; |
/* Then try in the subdirectory named DEBUG_SUBDIRECTORY. */ |
strcpy (debugfile, dir); |
strcat (debugfile, DEBUG_SUBDIRECTORY); |
strcat (debugfile, "/"); |
- strcat (debugfile, basename); |
+ strcat (debugfile, debuglink); |
if (separate_debug_file_exists (debugfile, crc32, objfile)) |
- goto cleanup_return_debugfile; |
+ return debugfile; |
/* Then try in the global debugfile directories. |
- |
+ |
Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will |
cause "/..." lookups. */ |
- debugdir = debug_file_directory; |
- do |
- { |
- char *debugdir_end; |
- |
- while (*debugdir == DIRNAME_SEPARATOR) |
- debugdir++; |
- |
- debugdir_end = strchr (debugdir, DIRNAME_SEPARATOR); |
- if (debugdir_end == NULL) |
- debugdir_end = &debugdir[strlen (debugdir)]; |
+ debugdir_vec = dirnames_to_char_ptr_vec (debug_file_directory); |
+ back_to = make_cleanup_free_char_ptr_vec (debugdir_vec); |
- memcpy (debugfile, debugdir, debugdir_end - debugdir); |
- debugfile[debugdir_end - debugdir] = 0; |
+ for (ix = 0; VEC_iterate (char_ptr, debugdir_vec, ix, debugdir); ++ix) |
+ { |
+ strcpy (debugfile, debugdir); |
strcat (debugfile, "/"); |
strcat (debugfile, dir); |
- strcat (debugfile, basename); |
+ strcat (debugfile, debuglink); |
if (separate_debug_file_exists (debugfile, crc32, objfile)) |
- goto cleanup_return_debugfile; |
+ return debugfile; |
/* If the file is in the sysroot, try using its base path in the |
global debugfile directory. */ |
- if (canon_name |
- && filename_ncmp (canon_name, gdb_sysroot, |
+ if (canon_dir != NULL |
+ && filename_ncmp (canon_dir, gdb_sysroot, |
strlen (gdb_sysroot)) == 0 |
- && IS_DIR_SEPARATOR (canon_name[strlen (gdb_sysroot)])) |
+ && IS_DIR_SEPARATOR (canon_dir[strlen (gdb_sysroot)])) |
{ |
- memcpy (debugfile, debugdir, debugdir_end - debugdir); |
- debugfile[debugdir_end - debugdir] = 0; |
- strcat (debugfile, canon_name + strlen (gdb_sysroot)); |
+ strcpy (debugfile, debugdir); |
+ strcat (debugfile, canon_dir + strlen (gdb_sysroot)); |
strcat (debugfile, "/"); |
- strcat (debugfile, basename); |
+ strcat (debugfile, debuglink); |
if (separate_debug_file_exists (debugfile, crc32, objfile)) |
- goto cleanup_return_debugfile; |
+ return debugfile; |
} |
- |
- debugdir = debugdir_end; |
} |
- while (*debugdir != 0); |
- |
+ |
+ do_cleanups (back_to); |
xfree (debugfile); |
- debugfile = NULL; |
+ return NULL; |
+} |
+ |
+/* Modify PATH to contain only "directory/" part of PATH. |
+ If there were no directory separators in PATH, PATH will be empty |
+ string on return. */ |
+ |
+static void |
+terminate_after_last_dir_separator (char *path) |
+{ |
+ int i; |
+ |
+ /* Strip off the final filename part, leaving the directory name, |
+ followed by a slash. The directory can be relative or absolute. */ |
+ for (i = strlen(path) - 1; i >= 0; i--) |
+ if (IS_DIR_SEPARATOR (path[i])) |
+ break; |
+ |
+ /* If I is -1 then no directory is present there and DIR will be "". */ |
+ path[i + 1] = '\0'; |
+} |
+ |
+/* Find separate debuginfo for OBJFILE (using .gnu_debuglink section). |
+ Returns pathname, or NULL. */ |
+ |
+char * |
+find_separate_debug_file_by_debuglink (struct objfile *objfile) |
+{ |
+ char *debuglink; |
+ char *dir, *canon_dir; |
+ char *debugfile; |
+ unsigned long crc32; |
+ struct cleanup *cleanups; |
+ |
+ debuglink = get_debug_link_info (objfile, &crc32); |
+ |
+ if (debuglink == NULL) |
+ { |
+ /* There's no separate debug info, hence there's no way we could |
+ load it => no warning. */ |
+ return NULL; |
+ } |
+ |
+ cleanups = make_cleanup (xfree, debuglink); |
+ dir = xstrdup (objfile->name); |
+ make_cleanup (xfree, dir); |
+ terminate_after_last_dir_separator (dir); |
+ canon_dir = lrealpath (dir); |
+ |
+ debugfile = find_separate_debug_file (dir, canon_dir, debuglink, |
+ crc32, objfile); |
+ xfree (canon_dir); |
+ |
+ if (debugfile == NULL) |
+ { |
+#ifdef HAVE_LSTAT |
+ /* For PR gdb/9538, try again with realpath (if different from the |
+ original). */ |
+ |
+ struct stat st_buf; |
+ |
+ if (lstat (objfile->name, &st_buf) == 0 && S_ISLNK(st_buf.st_mode)) |
+ { |
+ char *symlink_dir; |
+ |
+ symlink_dir = lrealpath (objfile->name); |
+ if (symlink_dir != NULL) |
+ { |
+ make_cleanup (xfree, symlink_dir); |
+ terminate_after_last_dir_separator (symlink_dir); |
+ if (strcmp (dir, symlink_dir) != 0) |
+ { |
+ /* Different directory, so try using it. */ |
+ debugfile = find_separate_debug_file (symlink_dir, |
+ symlink_dir, |
+ debuglink, |
+ crc32, |
+ objfile); |
+ } |
+ } |
+ } |
+#endif /* HAVE_LSTAT */ |
+ } |
-cleanup_return_debugfile: |
- xfree (canon_name); |
- xfree (basename); |
- xfree (dir); |
+ do_cleanups (cleanups); |
return debugfile; |
} |
@@ -1631,7 +1673,7 @@ set_initial_language (void) |
else |
{ |
const char *filename; |
- |
+ |
filename = find_main_filename (); |
if (filename != NULL) |
lang = deduce_language_from_filename (filename); |
@@ -1723,7 +1765,6 @@ symfile_bfd_open (char *name) |
sym_bfd = bfd_fopen (name, gnutarget, FOPEN_RB, desc); |
if (!sym_bfd) |
{ |
- close (desc); |
make_cleanup (xfree, name); |
error (_("`%s': can't open to read symbols: %s."), name, |
bfd_errmsg (bfd_get_error ())); |
@@ -2369,15 +2410,22 @@ add_symbol_file_command (char *args, int from_tty) |
} |
+typedef struct objfile *objfilep; |
+ |
+DEF_VEC_P (objfilep); |
+ |
/* Re-read symbols if a symbol-file has changed. */ |
void |
reread_symbols (void) |
{ |
struct objfile *objfile; |
long new_modtime; |
- int reread_one = 0; |
struct stat new_statbuf; |
int res; |
+ VEC (objfilep) *new_objfiles = NULL; |
+ struct cleanup *all_cleanups; |
+ |
+ all_cleanups = make_cleanup (VEC_cleanup (objfilep), &new_objfiles); |
/* With the addition of shared libraries, this should be modified, |
the load time should be saved in the partial symbol tables, since |
@@ -2532,14 +2580,9 @@ reread_symbols (void) |
/* obstack_init also initializes the obstack so it is |
empty. We could use obstack_specify_allocation but |
- gdb_obstack.h specifies the alloc/dealloc |
- functions. */ |
+ gdb_obstack.h specifies the alloc/dealloc functions. */ |
obstack_init (&objfile->objfile_obstack); |
- if (build_objfile_section_table (objfile)) |
- { |
- error (_("Can't find the file sections in `%s': %s"), |
- objfile->name, bfd_errmsg (bfd_get_error ())); |
- } |
+ build_objfile_section_table (objfile); |
terminate_minimal_symbol_table (objfile); |
/* We use the same section offsets as from last time. I'm not |
@@ -2592,21 +2635,33 @@ reread_symbols (void) |
and now, we *want* this to be out of date, so don't call stat |
again now. */ |
objfile->mtime = new_modtime; |
- reread_one = 1; |
init_entry_point_info (objfile); |
+ |
+ VEC_safe_push (objfilep, new_objfiles, objfile); |
} |
} |
- if (reread_one) |
+ if (new_objfiles) |
{ |
+ int ix; |
+ |
/* Notify objfiles that we've modified objfile sections. */ |
objfiles_changed (); |
clear_symtab_users (0); |
+ |
+ /* clear_objfile_data for each objfile was called before freeing it and |
+ observer_notify_new_objfile (NULL) has been called by |
+ clear_symtab_users above. Notify the new files now. */ |
+ for (ix = 0; VEC_iterate (objfilep, new_objfiles, ix, objfile); ix++) |
+ observer_notify_new_objfile (objfile); |
+ |
/* At least one objfile has changed, so we can consider that |
the executable we're debugging has changed too. */ |
observer_notify_executable_changed (); |
} |
+ |
+ do_cleanups (all_cleanups); |
} |
@@ -2818,6 +2873,26 @@ allocate_symtab (const char *filename, struct objfile *objfile) |
symtab->next = objfile->symtabs; |
objfile->symtabs = symtab; |
+ if (symtab_create_debug) |
+ { |
+ /* Be a bit clever with debugging messages, and don't print objfile |
+ every time, only when it changes. */ |
+ static char *last_objfile_name = NULL; |
+ |
+ if (last_objfile_name == NULL |
+ || strcmp (last_objfile_name, objfile->name) != 0) |
+ { |
+ xfree (last_objfile_name); |
+ last_objfile_name = xstrdup (objfile->name); |
+ fprintf_unfiltered (gdb_stdlog, |
+ "Creating one or more symtabs for objfile %s ...\n", |
+ last_objfile_name); |
+ } |
+ fprintf_unfiltered (gdb_stdlog, |
+ "Created symtab %s for module %s.\n", |
+ host_address_to_string (symtab), filename); |
+ } |
+ |
return (symtab); |
} |
@@ -2923,7 +2998,7 @@ section_is_overlay (struct obj_section *section) |
{ |
bfd *abfd = section->objfile->obfd; |
asection *bfd_section = section->the_bfd_section; |
- |
+ |
if (bfd_section_lma (abfd, bfd_section) != 0 |
&& bfd_section_lma (abfd, bfd_section) |
!= bfd_section_vma (abfd, bfd_section)) |
@@ -3570,7 +3645,9 @@ bfd_byte * |
default_symfile_relocate (struct objfile *objfile, asection *sectp, |
bfd_byte *buf) |
{ |
- bfd *abfd = objfile->obfd; |
+ /* Use sectp->owner instead of objfile->obfd. sectp may point to a |
+ DWO file. */ |
+ bfd *abfd = sectp->owner; |
/* We're only interested in sections with relocation |
information. */ |
@@ -3753,14 +3830,6 @@ for access from GDB.\n\ |
A load OFFSET may also be given."), &cmdlist); |
set_cmd_completer (c, filename_completer); |
- add_setshow_boolean_cmd ("symbol-reloading", class_support, |
- &symbol_reloading, _("\ |
-Set dynamic symbol table reloading multiple times in one run."), _("\ |
-Show dynamic symbol table reloading multiple times in one run."), NULL, |
- NULL, |
- show_symbol_reloading, |
- &setlist, &showlist); |
- |
add_prefix_cmd ("overlay", class_support, overlay_command, |
_("Commands for debugging overlays."), &overlaylist, |
"overlay ", 0, &cmdlist); |