/* Generic symbol file reading for the GNU debugger, GDB.
- Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 1990-2012 Free Software Foundation, Inc.
Contributed by Cygnus Support, using pieces from other GDB modules.
#include "elf-bfd.h"
#include "solib.h"
#include "remote.h"
+#include "stack.h"
#include <sys/types.h>
#include <fcntl.h>
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
{
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)
struct cleanup *my_cleanups;
const char *name = bfd_get_filename (abfd);
const int from_tty = add_flags & SYMFILE_VERBOSE;
+ const int mainline = add_flags & SYMFILE_MAINLINE;
const int should_print = ((from_tty || info_verbose)
&& (readnow_symbol_files
|| (add_flags & SYMFILE_NO_READ) == 0));
interactively wiping out any existing symbols. */
if ((have_full_symbols () || have_partial_symbols ())
- && (add_flags & SYMFILE_MAINLINE)
+ && mainline
&& from_tty
&& !query (_("Load new symbol table from \"%s\"? "), name))
error (_("Not confirmed."));
- objfile = allocate_objfile (abfd, flags);
+ objfile = allocate_objfile (abfd, flags | (mainline ? OBJF_MAINLINE : 0));
discard_cleanups (my_cleanups);
if (parent)
time. */
gdb_flush (gdb_stdout);
- do_cleanups (my_cleanups);
-
if (objfile->sf == NULL)
{
observer_notify_new_objfile (objfile);
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
return contents;
}
+/* Return 32-bit CRC for ABFD. If successful store it to *FILE_CRC_RETURN and
+ return 1. Otherwise print a warning and return 0. ABFD seek position is
+ not preserved. */
+
+static int
+get_file_crc (bfd *abfd, unsigned long *file_crc_return)
+{
+ unsigned long file_crc = 0;
+
+ if (bfd_seek (abfd, 0, SEEK_SET) != 0)
+ {
+ warning (_("Problem reading \"%s\" for CRC: %s"),
+ bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
+ return 0;
+ }
+
+ for (;;)
+ {
+ gdb_byte buffer[8 * 1024];
+ bfd_size_type count;
+
+ count = bfd_bread (buffer, sizeof (buffer), abfd);
+ if (count == (bfd_size_type) -1)
+ {
+ warning (_("Problem reading \"%s\" for CRC: %s"),
+ bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
+ return 0;
+ }
+ if (count == 0)
+ break;
+ file_crc = gnu_debuglink_crc32 (file_crc, buffer, count);
+ }
+
+ *file_crc_return = file_crc;
+ return 1;
+}
+
static int
separate_debug_file_exists (const char *name, unsigned long crc,
struct objfile *parent_objfile)
{
- unsigned long file_crc = 0;
+ unsigned long file_crc;
+ int file_crc_p;
bfd *abfd;
- gdb_byte buffer[8*1024];
- int count;
struct stat parent_stat, abfd_stat;
+ int verified_as_different;
/* Find a separate debug info file as if symbols would be present in
PARENT_OBJFILE itself this function would not be called. .gnu_debuglink
negatives. */
if (bfd_stat (abfd, &abfd_stat) == 0
- && bfd_stat (parent_objfile->obfd, &parent_stat) == 0
- && abfd_stat.st_dev == parent_stat.st_dev
- && abfd_stat.st_ino == parent_stat.st_ino
- && abfd_stat.st_ino != 0)
+ && abfd_stat.st_ino != 0
+ && bfd_stat (parent_objfile->obfd, &parent_stat) == 0)
{
- bfd_close (abfd);
- return 0;
+ if (abfd_stat.st_dev == parent_stat.st_dev
+ && abfd_stat.st_ino == parent_stat.st_ino)
+ {
+ bfd_close (abfd);
+ return 0;
+ }
+ verified_as_different = 1;
}
+ else
+ verified_as_different = 0;
- while ((count = bfd_bread (buffer, sizeof (buffer), abfd)) > 0)
- file_crc = gnu_debuglink_crc32 (file_crc, buffer, count);
+ file_crc_p = get_file_crc (abfd, &file_crc);
bfd_close (abfd);
+ if (!file_crc_p)
+ return 0;
+
if (crc != file_crc)
{
- warning (_("the debug information found in \"%s\""
- " does not match \"%s\" (CRC mismatch).\n"),
- name, parent_objfile->name);
+ /* If one (or both) the files are accessed for example the via "remote:"
+ gdbserver way it does not support the bfd_stat operation. Verify
+ whether those two files are not the same manually. */
+
+ if (!verified_as_different && !parent_objfile->crc32_p)
+ {
+ parent_objfile->crc32_p = get_file_crc (parent_objfile->obfd,
+ &parent_objfile->crc32);
+ if (!parent_objfile->crc32_p)
+ return 0;
+ }
+
+ if (verified_as_different || parent_objfile->crc32 != file_crc)
+ warning (_("the debug information found in \"%s\""
+ " does not match \"%s\" (CRC mismatch).\n"),
+ name, parent_objfile->name);
+
return 0;
}
#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_vec = dirnames_to_char_ptr_vec (debug_file_directory);
+ back_to = make_cleanup_free_char_ptr_vec (debugdir_vec);
- debugdir_end = strchr (debugdir, DIRNAME_SEPARATOR);
- if (debugdir_end == NULL)
- debugdir_end = &debugdir[strlen (debugdir)];
-
- 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;
+ }
-cleanup_return_debugfile:
- xfree (canon_name);
- xfree (basename);
- xfree (dir);
+ 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 */
+ }
+
+ do_cleanups (cleanups);
return debugfile;
}
else
{
const char *filename;
-
+
filename = find_main_filename ();
if (filename != NULL)
lang = deduce_language_from_filename (filename);
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 ()));
}
else
error (_("USAGE: add-symbol-file <filename> <textaddress>"
- " [-mapped] [-readnow] [-s <secname> <addr>]*"));
+ " [-readnow] [-s <secname> <addr>]*"));
}
}
}
}
\f
+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
exec_file_attach (bfd_get_filename (objfile->obfd), 0);
}
+ /* Keep the calls order approx. the same as in free_objfile. */
+
+ /* Free the separate debug objfiles. It will be
+ automatically recreated by sym_read. */
+ free_objfile_separate_debug (objfile);
+
+ /* Remove any references to this objfile in the global
+ value lists. */
+ preserve_values (objfile);
+
+ /* Nuke all the state that we will re-read. Much of the following
+ code which sets things to NULL really is necessary to tell
+ other parts of GDB that there is nothing currently there.
+
+ Try to keep the freeing order compatible with free_objfile. */
+
+ if (objfile->sf != NULL)
+ {
+ (*objfile->sf->sym_finish) (objfile);
+ }
+
+ clear_objfile_data (objfile);
+
/* Clean up any state BFD has sitting around. We don't need
to close the descriptor but BFD lacks a way of closing the
BFD without closing the descriptor. */
memcpy (offsets, objfile->section_offsets,
SIZEOF_N_SECTION_OFFSETS (num_offsets));
- /* Remove any references to this objfile in the global
- value lists. */
- preserve_values (objfile);
-
- /* Nuke all the state that we will re-read. Much of the following
- code which sets things to NULL really is necessary to tell
- other parts of GDB that there is nothing currently there.
-
- Try to keep the freeing order compatible with free_objfile. */
-
- if (objfile->sf != NULL)
- {
- (*objfile->sf->sym_finish) (objfile);
- }
-
- clear_objfile_data (objfile);
-
- /* Free the separate debug objfiles. It will be
- automatically recreated by sym_read. */
- free_objfile_separate_debug (objfile);
-
/* FIXME: Do we have to free a whole linked list, or is this
enough? */
if (objfile->global_psymbols.list)
memset (&objfile->msymbol_demangled_hash, 0,
sizeof (objfile->msymbol_demangled_hash));
- objfile->psymbol_cache = psymbol_bcache_init ();
- objfile->macro_cache = bcache_xmalloc (NULL, NULL);
- objfile->filename_cache = bcache_xmalloc (NULL, NULL);
/* 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
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);
}
\f
clear_displays ();
if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0)
breakpoint_re_set ();
- set_default_breakpoint (0, NULL, 0, 0, 0);
+ clear_last_displayed_sal ();
clear_pc_function_cache ();
observer_notify_new_objfile (NULL);
{
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))
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. */
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);