| 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);
|
|
|