/* Generic symbol file reading for the GNU debugger, GDB.
- Copyright (C) 1990-2013 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 "gdb_string.h"
-#include "gdb_stat.h"
+#include <sys/stat.h>
#include <ctype.h>
#include <time.h>
-#include <sys/time.h>
+#include "gdb_sys_time.h"
#include "psymtab.h"
calls add_symtab_fns() to register information on each format it is
prepared to read. */
-typedef const struct sym_fns *sym_fns_ptr;
-DEF_VEC_P (sym_fns_ptr);
+typedef struct
+{
+ /* BFD flavour that we handle. */
+ enum bfd_flavour sym_flavour;
+
+ /* The "vtable" of symbol functions. */
+ const struct sym_fns *sym_fns;
+} registered_sym_fns;
-static VEC (sym_fns_ptr) *symtab_fns = NULL;
+DEF_VEC_O (registered_sym_fns);
+
+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
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;
int i;
/* `+ 1' for the NULL terminator. */
- array = xmalloc (sizeof (*array) * (addrs->num_sections + 1));
+ array = XNEWVEC (struct other_sections *, addrs->num_sections + 1);
for (i = 0; i < addrs->num_sections; i++)
array[i] = &addrs->other[i];
array[i] = NULL;
/* Now create ADDRS_TO_ABFD_ADDRS from ADDRS_SORTED and
ABFD_ADDRS_SORTED. */
- addrs_to_abfd_addrs = xzalloc (sizeof (*addrs_to_abfd_addrs)
- * addrs->num_sections);
+ addrs_to_abfd_addrs = XCNEWVEC (struct other_sections *, addrs->num_sections);
make_cleanup (xfree, addrs_to_abfd_addrs);
while (*addrs_sorted)
low = bfd_get_section_vma (abfd, sect);
high = low + bfd_get_section_size (sect);
- data = XZALLOC (struct symfile_segment_data);
+ data = XCNEW (struct symfile_segment_data);
data->num_segments = 1;
- data->segment_bases = XCALLOC (1, CORE_ADDR);
- data->segment_sizes = XCALLOC (1, CORE_ADDR);
+ data->segment_bases = XCNEW (CORE_ADDR);
+ data->segment_sizes = XCNEW (CORE_ADDR);
num_sections = bfd_count_sections (abfd);
- data->segment_info = XCALLOC (num_sections, int);
+ data->segment_info = XCNEWVEC (int, num_sections);
for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
{
read_symbols (struct objfile *objfile, int add_flags)
{
(*objfile->sf->sym_read) (objfile, add_flags);
+ objfile->per_bfd->minsyms_read = 1;
/* find_separate_debug_file_in_section should be called only if there is
single binary with no existing separate debug info file. */
static void
init_entry_point_info (struct objfile *objfile)
{
+ struct entry_info *ei = &objfile->per_bfd->ei;
+
+ if (ei->initialized)
+ return;
+ ei->initialized = 1;
+
/* Save startup file's range of PC addresses to help blockframe.c
decide where the bottom of the stack is. */
{
/* Executable file -- record its entry point so we'll recognize
the startup file because it contains the entry point. */
- objfile->ei.entry_point = bfd_get_start_address (objfile->obfd);
- objfile->ei.entry_point_p = 1;
+ ei->entry_point = bfd_get_start_address (objfile->obfd);
+ ei->entry_point_p = 1;
}
else if (bfd_get_file_flags (objfile->obfd) & DYNAMIC
&& bfd_get_start_address (objfile->obfd) != 0)
/* Some shared libraries may have entry points set and be
runnable. There's no clear way to indicate this, so just check
for values other than zero. */
- objfile->ei.entry_point = bfd_get_start_address (objfile->obfd);
- objfile->ei.entry_point_p = 1;
+ ei->entry_point = bfd_get_start_address (objfile->obfd);
+ ei->entry_point_p = 1;
}
else
{
/* Examination of non-executable.o files. Short-circuit this stuff. */
- objfile->ei.entry_point_p = 0;
+ ei->entry_point_p = 0;
}
- if (objfile->ei.entry_point_p)
+ if (ei->entry_point_p)
{
- CORE_ADDR entry_point = objfile->ei.entry_point;
+ struct obj_section *osect;
+ CORE_ADDR entry_point = ei->entry_point;
+ int found;
/* Make certain that the address points at real code, and not a
function descriptor. */
/* Remove any ISA markers, so that this matches entries in the
symbol table. */
- objfile->ei.entry_point
+ ei->entry_point
= gdbarch_addr_bits_remove (get_objfile_arch (objfile), entry_point);
+
+ found = 0;
+ ALL_OBJFILE_OSECTIONS (objfile, osect)
+ {
+ struct bfd_section *sect = osect->the_bfd_section;
+
+ if (entry_point >= bfd_get_section_vma (objfile->obfd, sect)
+ && entry_point < (bfd_get_section_vma (objfile->obfd, sect)
+ + bfd_get_section_size (sect)))
+ {
+ ei->the_bfd_section_index
+ = gdb_bfd_section_index (objfile->obfd, sect);
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ ei->the_bfd_section_index = SECT_OFF_TEXT (objfile);
}
}
struct cleanup *old_chain;
const int mainline = add_flags & SYMFILE_MAINLINE;
- objfile->sf = find_sym_fns (objfile->obfd);
+ objfile_set_sym_fns (objfile, find_sym_fns (objfile->obfd));
if (objfile->sf == NULL)
{
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);
void
set_initial_language (void)
{
- enum language lang = language_unknown;
+ enum language lang = main_language ();
- if (language_of_main != language_unknown)
- lang = language_of_main;
- else
+ if (lang == language_unknown)
{
char *name = main_name ();
- struct symbol *sym = lookup_symbol (name, NULL, VAR_DOMAIN, NULL);
+ struct symbol *sym = lookup_symbol (name, NULL, VAR_DOMAIN, NULL).symbol;
if (sym != NULL)
lang = SYMBOL_LANGUAGE (sym);
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 ()));
+ char *expanded_name, *absolute_name;
- 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 ()));
- }
+ expanded_name = tilde_expand (name); /* Returns 1st new malloc'd copy. */
- return sym_bfd;
- }
-
- name = tilde_expand (cname); /* 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))
{
return -1;
}
-/* Link SF into the global symtab_fns list. Called on startup by the
- _initialize routine in each object file format reader, to register
- information about each format the reader is prepared to handle. */
+/* Link SF into the global symtab_fns list.
+ FLAVOUR is the file format that SF handles.
+ Called on startup by the _initialize routine in each object file format
+ reader, to register information about each format the reader is prepared
+ to handle. */
void
-add_symtab_fns (const struct sym_fns *sf)
+add_symtab_fns (enum bfd_flavour flavour, const struct sym_fns *sf)
{
- VEC_safe_push (sym_fns_ptr, symtab_fns, sf);
+ registered_sym_fns fns = { flavour, sf };
+
+ VEC_safe_push (registered_sym_fns, symtab_fns, &fns);
}
/* Initialize OBJFILE to read symbols from its associated BFD. It
static const struct sym_fns *
find_sym_fns (bfd *abfd)
{
- const struct sym_fns *sf;
+ registered_sym_fns *rsf;
enum bfd_flavour our_flavour = bfd_get_flavour (abfd);
int i;
|| our_flavour == bfd_target_tekhex_flavour)
return NULL; /* No symbols. */
- for (i = 0; VEC_iterate (sym_fns_ptr, symtab_fns, i, sf); ++i)
- if (our_flavour == sf->sym_flavour)
- return sf;
+ for (i = 0; VEC_iterate (registered_sym_fns, symtab_fns, i, rsf); ++i)
+ if (our_flavour == rsf->sym_flavour)
+ return rsf->sym_fns;
error (_("I'm sorry, Dave, I can't do that. Symbol format `%s' unknown."),
bfd_get_target (abfd));
new_request = VEC_safe_push (memory_write_request_s,
args->requests, NULL);
memset (new_request, 0, sizeof (struct memory_write_request));
- section_data = xcalloc (1, sizeof (struct load_progress_section_data));
+ section_data = XCNEW (struct load_progress_section_data);
new_request->begin = bfd_section_lma (abfd, asec) + args->load_offset;
new_request->end = new_request->begin + size; /* FIXME Should size
be in instead? */
}
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;
int expecting_sec_name = 0;
int expecting_sec_addr = 0;
char **argv;
+ struct objfile *objf;
struct sect_opt
{
struct cleanup *my_cleanups = make_cleanup (null_cleanup, NULL);
num_sect_opts = 16;
- sect_opts = (struct sect_opt *) xmalloc (num_sect_opts
- * sizeof (struct sect_opt));
+ sect_opts = XNEWVEC (struct sect_opt, num_sect_opts);
dont_repeat ();
if (from_tty && (!query ("%s", "")))
error (_("Not confirmed."));
- symbol_file_add (filename, from_tty ? SYMFILE_VERBOSE : 0,
- section_addrs, flags);
+ objf = symbol_file_add (filename, from_tty ? SYMFILE_VERBOSE : 0,
+ section_addrs, flags);
+
+ add_target_sections_of_objfile (objf);
/* Getting new symbols may change our opinion about what is
frameless. */
}
\f
+/* This function removes a symbol file that was added via add-symbol-file. */
+
+static void
+remove_symbol_file_command (char *args, int from_tty)
+{
+ char **argv;
+ struct objfile *objf = NULL;
+ struct cleanup *my_cleanups;
+ struct program_space *pspace = current_program_space;
+ struct gdbarch *gdbarch = get_current_arch ();
+
+ dont_repeat ();
+
+ if (args == NULL)
+ error (_("remove-symbol-file: no symbol file provided"));
+
+ my_cleanups = make_cleanup (null_cleanup, NULL);
+
+ argv = gdb_buildargv (args);
+
+ if (strcmp (argv[0], "-a") == 0)
+ {
+ /* Interpret the next argument as an address. */
+ CORE_ADDR addr;
+
+ if (argv[1] == NULL)
+ error (_("Missing address argument"));
+
+ if (argv[2] != NULL)
+ error (_("Junk after %s"), argv[1]);
+
+ addr = parse_and_eval_address (argv[1]);
+
+ ALL_OBJFILES (objf)
+ {
+ if ((objf->flags & OBJF_USERLOADED) != 0
+ && (objf->flags & OBJF_SHARED) != 0
+ && objf->pspace == pspace && is_addr_in_objfile (addr, objf))
+ break;
+ }
+ }
+ else if (argv[0] != NULL)
+ {
+ /* Interpret the current argument as a file name. */
+ char *filename;
+
+ if (argv[1] != NULL)
+ error (_("Junk after %s"), argv[0]);
+
+ filename = tilde_expand (argv[0]);
+ make_cleanup (xfree, filename);
+
+ ALL_OBJFILES (objf)
+ {
+ if ((objf->flags & OBJF_USERLOADED) != 0
+ && (objf->flags & OBJF_SHARED) != 0
+ && objf->pspace == pspace
+ && filename_cmp (filename, objfile_name (objf)) == 0)
+ break;
+ }
+ }
+
+ if (objf == NULL)
+ error (_("No symbol file found"));
+
+ if (from_tty
+ && !query (_("Remove symbol table from file \"%s\"? "),
+ objfile_name (objf)))
+ error (_("Not confirmed."));
+
+ free_objfile (objf);
+ clear_symtab_users (0);
+
+ do_cleanups (my_cleanups);
+}
+
typedef struct objfile *objfilep;
DEF_VEC_P (objfilep);
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
/* Free the obstacks for non-reusable objfiles. */
psymbol_bcache_free (objfile->psymbol_cache);
objfile->psymbol_cache = psymbol_bcache_init ();
- if (objfile->demangled_names_hash != NULL)
- {
- htab_delete (objfile->demangled_names_hash);
- objfile->demangled_names_hash = NULL;
- }
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;
objfile->template_symbols = NULL;
- objfile->msymbols = NULL;
- objfile->minimal_symbol_count = 0;
- memset (&objfile->msymbol_hash, 0,
- sizeof (objfile->msymbol_hash));
- memset (&objfile->msymbol_demangled_hash, 0,
- sizeof (objfile->msymbol_demangled_hash));
-
- set_objfile_per_bfd (objfile);
/* 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. */
obstack_init (&objfile->objfile_obstack);
+ /* set_objfile_per_bfd potentially allocates the per-bfd
+ data on the objfile's obstack (if sharing data across
+ multiple users is not possible), so it's important to
+ do it *after* the obstack has been initialized. */
+ set_objfile_per_bfd (objfile);
+
objfile->original_name = obstack_copy0 (&objfile->objfile_obstack,
original_name,
strlen (original_name));
/* Reset the sym_fns pointer. The ELF reader can change it
based on whether .gdb_index is present, and we need it to
start over. PR symtab/15885 */
- objfile->sf = find_sym_fns (objfile->obfd);
+ objfile_set_sym_fns (objfile, find_sym_fns (objfile->obfd));
build_objfile_section_table (objfile);
terminate_minimal_symbol_table (objfile);
{
fl_table_size = 20;
fl_table_next = 0;
- filename_language_table =
- xmalloc (fl_table_size * sizeof (*filename_language_table));
+ filename_language_table = XNEWVEC (filename_language, fl_table_size);
+
add_filename_language (".c", language_c);
add_filename_language (".d", language_d);
add_filename_language (".C", language_cplus);
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 = (char *) bcache (filename, strlen (filename) + 1,
- objfile->per_bfd->filename_cache);
+ 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;
-
- if (symtab_create_debug)
+ /* This can be very verbose with lots of headers.
+ Only print at higher debug levels. */
+ if (symtab_create_debug >= 2)
{
/* Be a bit clever with debugging messages, and don't print objfile
every time, only when it changes. */
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:
In this simple implementation, the target data structures are as follows:
unsigned _novlys; /# number of overlay sections #/
unsigned _ovly_table[_novlys][4] = {
- {VMA, SIZE, LMA, MAPPED}, /# one entry per overlay section #/
+ {VMA, OSIZE, LMA, MAPPED}, /# one entry per overlay section #/
{..., ..., ..., ...},
}
unsigned _novly_regions; /# number of overlay regions #/
unsigned _ovly_region_table[_novly_regions][3] = {
- {VMA, SIZE, MAPPED_TO_LMA}, /# one entry per overlay region #/
+ {VMA, OSIZE, MAPPED_TO_LMA}, /# one entry per overlay region #/
{..., ..., ...},
}
These functions will attempt to update GDB's mappedness state in the
static CORE_ADDR cache_ovly_table_base = 0;
enum ovly_index
{
- VMA, SIZE, LMA, MAPPED
+ VMA, OSIZE, LMA, MAPPED
};
/* Throw away the cached copy of _ovly_table. */
static int
simple_read_overlay_table (void)
{
- struct minimal_symbol *novlys_msym;
+ struct bound_minimal_symbol novlys_msym;
struct bound_minimal_symbol ovly_table_msym;
struct gdbarch *gdbarch;
int word_size;
simple_free_overlay_table ();
novlys_msym = lookup_minimal_symbol ("_novlys", NULL, NULL);
- if (! novlys_msym)
+ if (! novlys_msym.minsym)
{
error (_("Error reading inferior's overlay table: "
"couldn't find `_novlys' variable\n"
word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
byte_order = gdbarch_byte_order (gdbarch);
- cache_novlys = read_memory_integer (SYMBOL_VALUE_ADDRESS (novlys_msym),
+ cache_novlys = read_memory_integer (BMSYMBOL_VALUE_ADDRESS (novlys_msym),
4, byte_order);
cache_ovly_table
= (void *) xmalloc (cache_novlys * sizeof (*cache_ovly_table));
- cache_ovly_table_base = SYMBOL_VALUE_ADDRESS (ovly_table_msym.minsym);
+ cache_ovly_table_base = BMSYMBOL_VALUE_ADDRESS (ovly_table_msym);
read_target_long_array (cache_ovly_table_base,
(unsigned int *) cache_ovly_table,
cache_novlys * 4, word_size, byte_order);
for (i = 0; i < cache_novlys; i++)
if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect)
&& cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect)
- /* && cache_ovly_table[i][SIZE] == size */ )
+ /* && cache_ovly_table[i][OSIZE] == size */ )
{
read_target_long_array (cache_ovly_table_base + i * word_size,
(unsigned int *) cache_ovly_table[i],
4, word_size, byte_order);
if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect)
&& cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect)
- /* && cache_ovly_table[i][SIZE] == size */ )
+ /* && cache_ovly_table[i][OSIZE] == size */ )
{
osect->ovly_mapped = cache_ovly_table[i][MAPPED];
return 1;
{
/* Does its cached location match what's currently in the
symtab? */
- struct minimal_symbol *minsym
+ struct bound_minimal_symbol minsym
= lookup_minimal_symbol ("_ovly_table", NULL, NULL);
- if (minsym == NULL)
+ if (minsym.minsym == NULL)
error (_("Error reading inferior's overlay table: couldn't "
"find `_ovly_table' array\n"
"in inferior. Use `overlay manual' mode."));
- if (cache_ovly_table_base == SYMBOL_VALUE_ADDRESS (minsym))
+ if (cache_ovly_table_base == BMSYMBOL_VALUE_ADDRESS (minsym))
/* Then go ahead and try to look up this single section in
the cache. */
if (simple_overlay_update_1 (osect))
for (i = 0; i < cache_novlys; i++)
if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect)
&& cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect)
- /* && cache_ovly_table[i][SIZE] == size */ )
+ /* && cache_ovly_table[i][OSIZE] == size */ )
{ /* obj_section matches i'th entry in ovly_table. */
osect->ovly_mapped = cache_ovly_table[i][MAPPED];
break; /* finished with inner for loop: break out. */
free_symfile_segment_data (data);
}
+/* Listen for free_objfile events. */
+
+static void
+symfile_free_objfile (struct objfile *objfile)
+{
+ /* Remove the target sections owned by this objfile. */
+ if (objfile != NULL)
+ remove_target_sections ((void *) objfile);
+}
+
+/* Wrapper around the quick_symbol_functions expand_symtabs_matching "method".
+ Expand all symtabs that match the specified criteria.
+ See quick_symbol_functions.expand_symtabs_matching for details. */
+
+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)
+{
+ struct objfile *objfile;
+
+ ALL_OBJFILES (objfile)
+ {
+ if (objfile->sf)
+ objfile->sf->qf->expand_symtabs_matching (objfile, file_matcher,
+ symbol_matcher,
+ expansion_notify, kind,
+ data);
+ }
+}
+
+/* Wrapper around the quick_symbol_functions map_symbol_filenames "method".
+ Map function FUN over every file.
+ See quick_symbol_functions.map_symbol_filenames for details. */
+
+void
+map_symbol_filenames (symbol_filename_ftype *fun, void *data,
+ int need_fullname)
+{
+ struct objfile *objfile;
+
+ ALL_OBJFILES (objfile)
+ {
+ if (objfile->sf)
+ objfile->sf->qf->map_symbol_filenames (objfile, fun, data,
+ need_fullname);
+ }
+}
+
void
_initialize_symfile (void)
{
struct cmd_list_element *c;
+ observer_attach_free_objfile (symfile_free_objfile);
+
c = add_cmd ("symbol-file", class_files, symbol_file_command, _("\
Load symbol table from executable file FILE.\n\
The `file' command can also load symbol tables, as well as setting the file\n\
&cmdlist);
set_cmd_completer (c, filename_completer);
+ c = add_cmd ("remove-symbol-file", class_files,
+ remove_symbol_file_command, _("\
+Remove a symbol file added via the add-symbol-file command.\n\
+Usage: remove-symbol-file FILENAME\n\
+ remove-symbol-file -a ADDRESS\n\
+The file to remove can be identified by its filename or by an address\n\
+that lies within the boundaries of this symbol file in memory."),
+ &cmdlist);
+
c = add_cmd ("load", class_files, load_command, _("\
Dynamically load FILE into the running program, and record its symbols\n\
for access from GDB.\n\
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);
}