/* Generic symbol file reading for the GNU debugger, GDB.
- Copyright (C) 1990-2014 Free Software Foundation, Inc.
+ Copyright (C) 1990-2015 Free Software Foundation, Inc.
Contributed by Cygnus Support, using pieces from other GDB modules.
#include "bcache.h"
#include "hashtab.h"
#include "readline/readline.h"
-#include "gdb_assert.h"
#include "block.h"
#include "observer.h"
#include "exec.h"
#include <sys/types.h>
#include <fcntl.h>
-#include <string.h>
#include <sys/stat.h>
#include <ctype.h>
#include <time.h>
static VEC (registered_sym_fns) *symtab_fns = NULL;
+/* Values for "set print symbol-loading". */
+
+const char print_symbol_loading_off[] = "off";
+const char print_symbol_loading_brief[] = "brief";
+const char print_symbol_loading_full[] = "full";
+static const char *print_symbol_loading_enums[] =
+{
+ print_symbol_loading_off,
+ print_symbol_loading_brief,
+ print_symbol_loading_full,
+ NULL
+};
+static const char *print_symbol_loading = print_symbol_loading_full;
+
/* 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
int auto_solib_add = 1;
\f
+/* Return non-zero if symbol-loading messages should be printed.
+ FROM_TTY is the standard from_tty argument to gdb commands.
+ If EXEC is non-zero the messages are for the executable.
+ Otherwise, messages are for shared libraries.
+ If FULL is non-zero then the caller is printing a detailed message.
+ E.g., the message includes the shared library name.
+ Otherwise, the caller is printing a brief "summary" message. */
+
+int
+print_symbol_loading_p (int from_tty, int exec, int full)
+{
+ if (!from_tty && !info_verbose)
+ return 0;
+
+ if (exec)
+ {
+ /* We don't check FULL for executables, there are few such
+ messages, therefore brief == full. */
+ return print_symbol_loading != print_symbol_loading_off;
+ }
+ if (full)
+ return print_symbol_loading == print_symbol_loading_full;
+ return print_symbol_loading == print_symbol_loading_brief;
+}
+
/* True if we are reading a symbol table. */
int currently_reading_symtab = 0;
symbols for a new objfile, or mapping in the symbols from a reusable
objfile. ADD_FLAGS is a bitmask of enum symfile_add_flags. */
-void
-new_symfile_objfile (struct objfile *objfile, int add_flags)
+static void
+finish_new_objfile (struct objfile *objfile, int add_flags)
{
/* If this is the main symbol file we have to clean up all users of the
old main symbol file. Otherwise it is sufficient to fixup all the
struct objfile *objfile;
const int from_tty = add_flags & SYMFILE_VERBOSE;
const int mainline = add_flags & SYMFILE_MAINLINE;
- const int should_print = ((from_tty || info_verbose)
+ const int should_print = (print_symbol_loading_p (from_tty, mainline, 1)
&& (readnow_symbol_files
|| (add_flags & SYMFILE_NO_READ) == 0));
return objfile; /* No symbols. */
}
- new_symfile_objfile (objfile, add_flags);
+ finish_new_objfile (objfile, add_flags);
observer_notify_new_objfile (objfile);
if (filename_cmp (name, objfile_name (parent_objfile)) == 0)
return 0;
- abfd = gdb_bfd_open_maybe_remote (name);
+ abfd = gdb_bfd_open (name, gnutarget, -1);
if (!abfd)
return 0;
Some operating systems, e.g. Windows, do not provide a meaningful
st_ino; they always set it to zero. (Windows does provide a
- meaningful st_dev.) Do not indicate a duplicate library in that
- case. While there is no guarantee that a system that provides
- meaningful inode numbers will never set st_ino to zero, this is
- merely an optimization, so we do not need to worry about false
- negatives. */
+ meaningful st_dev.) Files accessed from gdbservers that do not
+ support the vFile:fstat packet will also have st_ino set to zero.
+ Do not indicate a duplicate library in either case. While there
+ is no guarantee that a system that provides meaningful inode
+ numbers will never set st_ino to zero, this is merely an
+ optimization, so we do not need to worry about false negatives. */
if (bfd_stat (abfd, &abfd_stat) == 0
&& abfd_stat.st_ino != 0
{
unsigned long parent_crc;
- /* 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 the files could not be verified as different with
+ bfd_stat then we need to calculate the parent's CRC
+ to verify whether the files are different or not. */
if (!verified_as_different)
{
if (debugfile == NULL)
{
-#ifdef HAVE_LSTAT
/* For PR gdb/9538, try again with realpath (if different from the
original). */
}
}
}
-#endif /* HAVE_LSTAT */
}
do_cleanups (cleanups);
expected_language = current_language; /* Don't warn the user. */
}
-/* If NAME is a remote name open the file using remote protocol, otherwise
- open it normally. Returns a new reference to the BFD. On error,
- returns NULL with the BFD error set. */
-
-bfd *
-gdb_bfd_open_maybe_remote (const char *name)
-{
- bfd *result;
-
- if (remote_filename_p (name))
- result = remote_bfd_open (name, gnutarget);
- else
- result = gdb_bfd_open (name, gnutarget, -1);
-
- return result;
-}
-
/* Open the file specified by NAME and hand it off to BFD for
preliminary analysis. Return a newly initialized bfd *, which
includes a newly malloc'd` copy of NAME (tilde-expanded and made
absolute). In case of trouble, error() is called. */
bfd *
-symfile_bfd_open (const char *cname)
+symfile_bfd_open (const char *name)
{
bfd *sym_bfd;
- int desc;
- char *name, *absolute_name;
- struct cleanup *back_to;
+ int desc = -1;
+ struct cleanup *back_to = make_cleanup (null_cleanup, 0);
- if (remote_filename_p (cname))
+ if (!is_target_filename (name))
{
- sym_bfd = remote_bfd_open (cname, gnutarget);
- if (!sym_bfd)
- error (_("`%s': can't open to read symbols: %s."), cname,
- bfd_errmsg (bfd_get_error ()));
-
- if (!bfd_check_format (sym_bfd, bfd_object))
- {
- make_cleanup_bfd_unref (sym_bfd);
- error (_("`%s': can't read symbols: %s."), cname,
- bfd_errmsg (bfd_get_error ()));
- }
+ char *expanded_name, *absolute_name;
- return sym_bfd;
- }
-
- name = tilde_expand (cname); /* Returns 1st new malloc'd copy. */
+ expanded_name = tilde_expand (name); /* Returns 1st new malloc'd copy. */
- /* Look down path for it, allocate 2nd new malloc'd copy. */
- desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, name,
- O_RDONLY | O_BINARY, &absolute_name);
+ /* Look down path for it, allocate 2nd new malloc'd copy. */
+ desc = openp (getenv ("PATH"),
+ OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
+ expanded_name, O_RDONLY | O_BINARY, &absolute_name);
#if defined(__GO32__) || defined(_WIN32) || defined (__CYGWIN__)
- if (desc < 0)
- {
- char *exename = alloca (strlen (name) + 5);
+ if (desc < 0)
+ {
+ char *exename = alloca (strlen (expanded_name) + 5);
- strcat (strcpy (exename, name), ".exe");
- desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
- exename, O_RDONLY | O_BINARY, &absolute_name);
- }
+ strcat (strcpy (exename, expanded_name), ".exe");
+ desc = openp (getenv ("PATH"),
+ OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
+ exename, O_RDONLY | O_BINARY, &absolute_name);
+ }
#endif
- if (desc < 0)
- {
- make_cleanup (xfree, name);
- perror_with_name (name);
- }
+ if (desc < 0)
+ {
+ make_cleanup (xfree, expanded_name);
+ perror_with_name (expanded_name);
+ }
- xfree (name);
- name = absolute_name;
- back_to = make_cleanup (xfree, name);
+ xfree (expanded_name);
+ make_cleanup (xfree, absolute_name);
+ name = absolute_name;
+ }
sym_bfd = gdb_bfd_open (name, gnutarget, desc);
if (!sym_bfd)
error (_("`%s': can't open to read symbols: %s."), name,
bfd_errmsg (bfd_get_error ()));
- bfd_set_cacheable (sym_bfd, 1);
+
+ if (!gdb_bfd_has_target_filename (sym_bfd))
+ bfd_set_cacheable (sym_bfd, 1);
if (!bfd_check_format (sym_bfd, bfd_object))
{
}
void
-generic_load (char *args, int from_tty)
+generic_load (const char *args, int from_tty)
{
bfd *loadfile_bfd;
struct timeval start_time, end_time;
{
struct gdbarch *gdbarch = get_current_arch ();
char *filename = NULL;
- int flags = OBJF_USERLOADED;
+ int flags = OBJF_USERLOADED | OBJF_SHARED;
char *arg;
int section_index = 0;
int argcnt = 0;
ALL_OBJFILES (objf)
{
- if (objf != 0
- && objf->flags & OBJF_USERLOADED
+ if ((objf->flags & OBJF_USERLOADED) != 0
+ && (objf->flags & OBJF_SHARED) != 0
&& objf->pspace == pspace && is_addr_in_objfile (addr, objf))
break;
}
ALL_OBJFILES (objf)
{
- if (objf != 0
- && objf->flags & OBJF_USERLOADED
+ if ((objf->flags & OBJF_USERLOADED) != 0
+ && (objf->flags & OBJF_SHARED) != 0
&& objf->pspace == pspace
&& filename_cmp (filename, objfile_name (objf)) == 0)
break;
obfd_filename = bfd_get_filename (objfile->obfd);
/* Open the new BFD before freeing the old one, so that
the filename remains live. */
- objfile->obfd = gdb_bfd_open_maybe_remote (obfd_filename);
+ objfile->obfd = gdb_bfd_open (obfd_filename, gnutarget, -1);
if (objfile->obfd == NULL)
{
/* We have to make a cleanup and error here, rather
objfile->psymbol_cache = psymbol_bcache_init ();
obstack_free (&objfile->objfile_obstack, 0);
objfile->sections = NULL;
- objfile->symtabs = NULL;
+ objfile->compunit_symtabs = NULL;
objfile->psymtabs = NULL;
objfile->psymtabs_addrmap = NULL;
objfile->free_psymtabs = NULL;
return language_unknown;
}
\f
-/* allocate_symtab:
-
- Allocate and partly initialize a new symbol table. Return a pointer
- to it. error() if no space.
-
- Caller must set these fields:
- LINETABLE(symtab)
- symtab->blockvector
- symtab->dirname
- symtab->free_code
- symtab->free_ptr
- */
+/* Allocate and initialize a new symbol table.
+ CUST is from the result of allocate_compunit_symtab. */
struct symtab *
-allocate_symtab (const char *filename, struct objfile *objfile)
+allocate_symtab (struct compunit_symtab *cust, const char *filename)
{
- struct symtab *symtab;
+ struct objfile *objfile = cust->objfile;
+ struct symtab *symtab
+ = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct symtab);
- symtab = (struct symtab *)
- obstack_alloc (&objfile->objfile_obstack, sizeof (struct symtab));
- memset (symtab, 0, sizeof (*symtab));
symtab->filename = bcache (filename, strlen (filename) + 1,
objfile->per_bfd->filename_cache);
symtab->fullname = NULL;
symtab->language = deduce_language_from_filename (filename);
- symtab->debugformat = "unknown";
-
- /* Hook it to the objfile it comes from. */
-
- symtab->objfile = objfile;
- symtab->next = objfile->symtabs;
- objfile->symtabs = symtab;
/* This can be very verbose with lots of headers.
Only print at higher debug levels. */
host_address_to_string (symtab), filename);
}
- return (symtab);
+ /* Add it to CUST's list of symtabs. */
+ if (cust->filetabs == NULL)
+ {
+ cust->filetabs = symtab;
+ cust->last_filetab = symtab;
+ }
+ else
+ {
+ cust->last_filetab->next = symtab;
+ cust->last_filetab = symtab;
+ }
+
+ /* Backlink to the containing compunit symtab. */
+ symtab->compunit_symtab = cust;
+
+ return symtab;
+}
+
+/* Allocate and initialize a new compunit.
+ NAME is the name of the main source file, if there is one, or some
+ descriptive text if there are no source files. */
+
+struct compunit_symtab *
+allocate_compunit_symtab (struct objfile *objfile, const char *name)
+{
+ struct compunit_symtab *cu = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct compunit_symtab);
+ const char *saved_name;
+
+ cu->objfile = objfile;
+
+ /* The name we record here is only for display/debugging purposes.
+ Just save the basename to avoid path issues (too long for display,
+ relative vs absolute, etc.). */
+ saved_name = lbasename (name);
+ cu->name = obstack_copy0 (&objfile->objfile_obstack, saved_name,
+ strlen (saved_name));
+
+ COMPUNIT_DEBUGFORMAT (cu) = "unknown";
+
+ if (symtab_create_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "Created compunit symtab %s for %s.\n",
+ host_address_to_string (cu),
+ cu->name);
+ }
+
+ return cu;
+}
+
+/* Hook CU to the objfile it comes from. */
+
+void
+add_compunit_symtab_to_objfile (struct compunit_symtab *cu)
+{
+ cu->next = cu->objfile->compunit_symtabs;
+ cu->objfile->compunit_symtabs = cu;
}
\f
clear_current_source_symtab_and_line ();
clear_displays ();
- if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0)
- breakpoint_re_set ();
clear_last_displayed_sal ();
clear_pc_function_cache ();
observer_notify_new_objfile (NULL);
/* Varobj may refer to old symbols, perform a cleanup. */
varobj_invalidate ();
+ /* Now that the various caches have been cleared, we can re_set
+ our breakpoints without risking it using stale data. */
+ if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0)
+ breakpoint_re_set ();
}
static void
unmap_overlay_command (char *args, int from_tty)
{
struct objfile *objfile;
- struct obj_section *sec;
+ struct obj_section *sec = NULL;
if (!overlay_debugging)
error (_("Overlay debugging not enabled. "
{
printf_unfiltered
("\"overlay\" must be followed by the name of an overlay command.\n");
- help_list (overlaylist, "overlay ", -1, gdb_stdout);
+ help_list (overlaylist, "overlay ", all_commands, gdb_stdout);
}
/* Target Overlays for the "Simplest" overlay manager:
static void
symfile_free_objfile (struct objfile *objfile)
{
- /* Remove the target sections of user-added objfiles. */
- if (objfile != 0 && objfile->flags & OBJF_USERLOADED)
+ /* Remove the target sections owned by this objfile. */
+ if (objfile != NULL)
remove_target_sections ((void *) objfile);
}
void
expand_symtabs_matching (expand_symtabs_file_matcher_ftype *file_matcher,
expand_symtabs_symbol_matcher_ftype *symbol_matcher,
+ expand_symtabs_exp_notify_ftype *expansion_notify,
enum search_domain kind,
void *data)
{
{
if (objfile->sf)
objfile->sf->qf->expand_symtabs_matching (objfile, file_matcher,
- symbol_matcher, kind,
+ symbol_matcher,
+ expansion_notify, kind,
data);
}
}
NULL,
show_debug_file_directory,
&setlist, &showlist);
+
+ add_setshow_enum_cmd ("symbol-loading", no_class,
+ print_symbol_loading_enums, &print_symbol_loading,
+ _("\
+Set printing of symbol loading messages."), _("\
+Show printing of symbol loading messages."), _("\
+off == turn all messages off\n\
+brief == print messages for the executable,\n\
+ and brief messages for shared libraries\n\
+full == print messages for the executable,\n\
+ and messages for each shared library."),
+ NULL,
+ NULL,
+ &setprintlist, &showprintlist);
}