X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fsymfile.c;h=2850af3c54d6e6b88c06ca78da2ec8559a07681e;hb=e74acce48c1b4efc29fd1e9e84639b77383aa002;hp=2265693bc3961960ff9510eaa7a39e55b3da0375;hpb=b8ef816335ed97ac644f527f12edc8aa8e9fac56;p=binutils-gdb.git diff --git a/gdb/symfile.c b/gdb/symfile.c index 2265693bc39..2850af3c54d 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -1,5 +1,6 @@ /* Generic symbol file reading for the GNU debugger, GDB. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996 + Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. This file is part of GDB. @@ -16,7 +17,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "defs.h" #include "symtab.h" @@ -32,18 +33,26 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "language.h" #include "complaints.h" #include "demangle.h" +#include "inferior.h" /* for write_pc */ +#include "gdb-stabs.h" +#include "obstack.h" -#include #include - #include #include -#include -#include +#include "gdb_string.h" +#include "gdb_stat.h" #include +#include +#ifdef HAVE_UNISTD_H +#include +#endif -/* Global variables owned by this file */ +#ifndef O_BINARY +#define O_BINARY 0 +#endif +/* Global variables owned by this file */ int readnow_symbol_files; /* Read full symbols immediately */ struct complaint oldsyms_complaint = { @@ -58,34 +67,28 @@ struct complaint empty_symtab_complaint = { extern int info_verbose; +extern void report_transfer_performance PARAMS ((unsigned long, + time_t, time_t)); + /* Functions this file defines */ -static void -set_initial_language PARAMS ((void)); +static void set_initial_language PARAMS ((void)); -static void -load_command PARAMS ((char *, int)); +static void load_command PARAMS ((char *, int)); -static void -add_symbol_file_command PARAMS ((char *, int)); +static void add_symbol_file_command PARAMS ((char *, int)); -static void -cashier_psymtab PARAMS ((struct partial_symtab *)); +static void add_shared_symbol_files_command PARAMS ((char *, int)); -static int -compare_psymbols PARAMS ((const void *, const void *)); +static void cashier_psymtab PARAMS ((struct partial_symtab *)); -static int -compare_symbols PARAMS ((const void *, const void *)); +static int compare_psymbols PARAMS ((const void *, const void *)); -static bfd * -symfile_bfd_open PARAMS ((char *)); +static int compare_symbols PARAMS ((const void *, const void *)); -static void -find_sym_fns PARAMS ((struct objfile *)); +static bfd *symfile_bfd_open PARAMS ((char *)); -void -clear_symtab_users_once PARAMS ((void)); +static void find_sym_fns PARAMS ((struct objfile *)); /* List of all available sym_fns. On gdb startup, each object file reader calls add_symtab_fns() to register information on each format it is @@ -93,10 +96,6 @@ clear_symtab_users_once PARAMS ((void)); static struct sym_fns *symtab_fns = NULL; -/* Structures with which to manage partial symbol allocation. */ - -struct psymbol_allocation_list global_psymbols = {0}, static_psymbols = {0}; - /* Flag for whether user will be reloading symbols multiple times. Defaults to ON for VxWorks, otherwise OFF. */ @@ -106,13 +105,20 @@ int symbol_reloading = SYMBOL_RELOADING_DEFAULT; int symbol_reloading = 0; #endif - -/* In the following sort, we always make sure that - register debug symbol declarations always come before regular - debug symbol declarations (as might happen when parameters are - then put into registers by the compiler). +/* If true, then 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 want to have happen; but for very large programs, the startup + time will be excessive, and so if this is a problem, the user can + clear this flag and then add the shared library symbols as needed. + Note that there is a potential for confusion, since if the shared + library symbols are not loaded, commands like "info fun" will *not* + report all the functions that are actually present. */ - Since this function is called from within qsort, in an ANSI environment +int auto_solib_add = 1; + + +/* Since this function is called from within qsort, in an ANSI environment it must conform to the prototype for qsort, which specifies that the comparison function takes two "void *" pointers. */ @@ -122,22 +128,11 @@ compare_symbols (s1p, s2p) const PTR s2p; { register struct symbol **s1, **s2; - register int namediff; s1 = (struct symbol **) s1p; s2 = (struct symbol **) s2p; - /* Compare the initial characters. */ - namediff = SYMBOL_NAME (*s1)[0] - SYMBOL_NAME (*s2)[0]; - if (namediff != 0) return namediff; - - /* If they match, compare the rest of the names. */ - namediff = STRCMP (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2)); - if (namediff != 0) return namediff; - - /* For symbols of the same name, registers should come first. */ - return ((SYMBOL_CLASS (*s2) == LOC_REGISTER) - - (SYMBOL_CLASS (*s1) == LOC_REGISTER)); + return (STRCMP (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2))); } /* @@ -148,9 +143,9 @@ LOCAL FUNCTION DESCRIPTION - Given pointer to two partial symbol table entries, compare - them by name and return -N, 0, or +N (ala strcmp). Typically - used by sorting routines like qsort(). + Given pointers to pointers to two partial symbol table entries, + compare them by name and return -N, 0, or +N (ala strcmp). + Typically used by sorting routines like qsort(). NOTES @@ -167,8 +162,8 @@ compare_psymbols (s1p, s2p) const PTR s1p; const PTR s2p; { - register char *st1 = SYMBOL_NAME ((struct partial_symbol *) s1p); - register char *st2 = SYMBOL_NAME ((struct partial_symbol *) s2p); + register char *st1 = SYMBOL_NAME (*(struct partial_symbol **) s1p); + register char *st2 = SYMBOL_NAME (*(struct partial_symbol **) s2p); if ((st1[0] - st2[0]) || !st1[0]) { @@ -191,7 +186,7 @@ sort_pst_symbols (pst) /* Sort the global list; don't sort the static list */ qsort (pst -> objfile -> global_psymbols.list + pst -> globals_offset, - pst -> n_global_syms, sizeof (struct partial_symbol), + pst -> n_global_syms, sizeof (struct partial_symbol *), compare_psymbols); } @@ -229,21 +224,6 @@ sort_symtab_syms (s) } } -void -sort_all_symtab_syms () -{ - register struct symtab *s; - register struct objfile *objfile; - - for (objfile = object_files; objfile != NULL; objfile = objfile -> next) - { - for (s = objfile -> symtabs; s != NULL; s = s -> next) - { - sort_symtab_syms (s); - } - } -} - /* Make a copy of the string at PTR with SIZE characters in the symbol obstack (and add a null character at the end in the copy). Returns the address of the copy. */ @@ -255,7 +235,7 @@ obsavestring (ptr, size, obstackp) struct obstack *obstackp; { register char *p = (char *) obstack_alloc (obstackp, size + 1); - /* Open-coded bcopy--saves function call time. + /* Open-coded memcpy--saves function call time. These strings are usually short. */ { register char *p1 = ptr; @@ -284,6 +264,17 @@ obconcat (obstackp, s1, s2, s3) return val; } +/* True if we are nested inside psymtab_to_symtab. */ + +int currently_reading_symtab = 0; + +static void +decrement_reading_symtab (dummy) + void *dummy; +{ + currently_reading_symtab--; +} + /* Get the symbol table that corresponds to a partial_symtab. This is fast after the first time you do it. In fact, there is an even faster macro PSYMTAB_TO_SYMTAB that does the fast @@ -300,7 +291,10 @@ psymtab_to_symtab (pst) /* If it has not yet been read in, read it. */ if (!pst->readin) { + struct cleanup *back_to = make_cleanup (decrement_reading_symtab, NULL); + currently_reading_symtab++; (*pst->read_symtab) (pst); + do_cleanups (back_to); } return pst->symtab; @@ -324,19 +318,34 @@ init_entry_point_info (objfile) else { /* Examination of non-executable.o files. Short-circuit this stuff. */ - /* ~0 will not be in any file, we hope. */ - objfile -> ei.entry_point = ~0; - /* set the startup file to be an empty range. */ - objfile -> ei.entry_file_lowpc = 0; - objfile -> ei.entry_file_highpc = 0; + objfile -> ei.entry_point = INVALID_ENTRY_POINT; } + objfile -> ei.entry_file_lowpc = INVALID_ENTRY_LOWPC; + objfile -> ei.entry_file_highpc = INVALID_ENTRY_HIGHPC; + objfile -> ei.entry_func_lowpc = INVALID_ENTRY_LOWPC; + objfile -> ei.entry_func_highpc = INVALID_ENTRY_HIGHPC; + objfile -> ei.main_func_lowpc = INVALID_ENTRY_LOWPC; + objfile -> ei.main_func_highpc = INVALID_ENTRY_HIGHPC; +} + +/* Get current entry point address. */ + +CORE_ADDR +entry_point_address() +{ + return symfile_objfile ? symfile_objfile->ei.entry_point : 0; } /* Remember the lowest-addressed loadable section we've seen. - This function is called via bfd_map_over_sections. */ + This function is called via bfd_map_over_sections. -#if 0 /* Not used yet */ -static void + In case of equal vmas, the section with the largest size becomes the + lowest-addressed loadable section. + + If the vmas and sizes are equal, the last section is considered the + lowest-addressed loadable section. */ + +void find_lowest_section (abfd, sect, obj) bfd *abfd; asection *sect; @@ -348,10 +357,38 @@ find_lowest_section (abfd, sect, obj) return; if (!*lowest) *lowest = sect; /* First loadable section */ - else if (bfd_section_vma (abfd, *lowest) >= bfd_section_vma (abfd, sect)) + else if (bfd_section_vma (abfd, *lowest) > bfd_section_vma (abfd, sect)) *lowest = sect; /* A lower loadable section */ + else if (bfd_section_vma (abfd, *lowest) == bfd_section_vma (abfd, sect) + && (bfd_section_size (abfd, (*lowest)) + <= bfd_section_size (abfd, sect))) + *lowest = sect; } -#endif + +/* Parse the user's idea of an offset for dynamic linking, into our idea + of how to represent it for fast symbol reading. This is the default + version of the sym_fns.sym_offsets function for symbol readers that + don't need to do anything special. It allocates a section_offsets table + for the objectfile OBJFILE and stuffs ADDR into all of the offsets. */ + +struct section_offsets * +default_symfile_offsets (objfile, addr) + struct objfile *objfile; + CORE_ADDR addr; +{ + struct section_offsets *section_offsets; + int i; + + objfile->num_sections = SECT_OFF_MAX; + section_offsets = (struct section_offsets *) + obstack_alloc (&objfile -> psymbol_obstack, SIZEOF_SECTION_OFFSETS); + + for (i = 0; i < SECT_OFF_MAX; i++) + ANOFFSET (section_offsets, i) = addr; + + return section_offsets; +} + /* Process a symbol file, as either the main file or as a dynamically loaded file. @@ -374,27 +411,21 @@ syms_from_objfile (objfile, addr, mainline, verbo) { struct section_offsets *section_offsets; asection *lowest_sect; - - /* There is a distinction between having no symbol table - (we refuse to read the file, leaving the old set of symbols around) - and having no debugging symbols in your symbol table (we read - the file and end up with a mostly empty symbol table). - - FIXME: This strategy works correctly when the debugging symbols are - intermixed with "normal" symbols. However, when the debugging symbols - are separate, such as with ELF/DWARF, it is perfectly plausible for - the symbol table to be missing but still have all the DWARF info - intact. Thus in general it is wrong to assume that having no symbol - table implies no debugging information. */ - - if (!(bfd_get_file_flags (objfile -> obfd) & HAS_SYMS)) - return; + struct cleanup *old_chain; init_entry_point_info (objfile); find_sym_fns (objfile); + /* Make sure that partially constructed symbol tables will be cleaned up + if an error occurs during symbol reading. */ + old_chain = make_cleanup (free_objfile, objfile); + if (mainline) { + /* We will modify the main symbol table, make sure that all its users + will be cleaned up if an error occurs during symbol reading. */ + make_cleanup (clear_symtab_users, 0); + /* Since no error yet, throw away the old symbol table. */ if (symfile_objfile != NULL) @@ -403,14 +434,18 @@ syms_from_objfile (objfile, addr, mainline, verbo) symfile_objfile = NULL; } + /* Currently we keep symbols from the add-symbol-file command. + If the user wants to get rid of them, they should do "symbol-file" + without arguments first. Not sure this is the best behavior + (PR 2207). */ + (*objfile -> sf -> sym_new_init) (objfile); } /* Convert addr into an offset rather than an absolute address. We find the lowest address of a loaded segment in the objfile, and assume that is where that got loaded. Due to historical - precedent, we warn if that doesn't happen to be the ".text" - segment. */ + precedent, we warn if that doesn't happen to be a text segment. */ if (mainline) { @@ -419,73 +454,82 @@ syms_from_objfile (objfile, addr, mainline, verbo) else { lowest_sect = bfd_get_section_by_name (objfile->obfd, ".text"); -#if 0 - lowest_sect = 0; - bfd_map_over_sections (objfile->obfd, find_lowest_section, - (PTR) &lowest_sect); -#endif + if (lowest_sect == NULL) + bfd_map_over_sections (objfile->obfd, find_lowest_section, + (PTR) &lowest_sect); - if (lowest_sect == 0) + if (lowest_sect == NULL) warning ("no loadable sections found in added symbol-file %s", objfile->name); - else if (0 == bfd_get_section_name (objfile->obfd, lowest_sect) - || !STREQ (".text", - bfd_get_section_name (objfile->obfd, lowest_sect))) - warning ("Lowest section in %s is %s at 0x%x", + else if ((bfd_get_section_flags (objfile->obfd, lowest_sect) & SEC_CODE) + == 0) + /* FIXME-32x64--assumes bfd_vma fits in long. */ + warning ("Lowest section in %s is %s at 0x%lx", objfile->name, bfd_section_name (objfile->obfd, lowest_sect), - bfd_section_vma (objfile->obfd, lowest_sect)); + (unsigned long) bfd_section_vma (objfile->obfd, lowest_sect)); if (lowest_sect) addr -= bfd_section_vma (objfile->obfd, lowest_sect); } - { - /* Debugging check inserted for testing elimination of NAMES_HAVE_UNDERSCORE. - Complain if the dynamic setting of NAMES_HAVE_UNDERSCORE from BFD - doesn't match the static setting from the GDB config files, but only - if we are using the first BFD target (the default target selected by - the same configuration that decided whether NAMES_HAVE_UNDERSCORE is - defined or not). For other targets (such as when the user sets GNUTARGET - or we are reading a "foreign" object file), it is likely that the value - of bfd_get_symbol_leading_char has no relation to the value of - NAMES_HAVE_UNDERSCORE for the target for which this gdb was built. - Hack alert: the only way to currently do this with bfd is to ask it to - produce a list of known target names and compare the first one in the - list with the one for the bfd we are using. - FIXME: Remove this check after a round of testing. - -- gnu@cygnus.com, 16dec92 */ - CONST char **targets = bfd_target_list (); - if (targets != NULL && *targets != NULL) - { - if (bfd_get_symbol_leading_char (objfile->obfd) != -#ifdef NAMES_HAVE_UNDERSCORE - '_' -#else - 0 -#endif - && STREQ (bfd_get_target (objfile->obfd), *targets)) - { - fprintf (stderr, "GDB internal error! NAMES_HAVE_UNDERSCORE set wrong for %s BFD:\n%s\n", - bfd_get_target (objfile->obfd), - bfd_get_filename (objfile->obfd)); - } - free (targets); - } - /* End of debugging check. FIXME. */ - } - /* Initialize symbol reading routines for this objfile, allow complaints to appear for this new file, and record how verbose to be, then do the initial symbol reading for this file. */ (*objfile -> sf -> sym_init) (objfile); clear_complaints (1, verbo); + section_offsets = (*objfile -> sf -> sym_offsets) (objfile, addr); + objfile->section_offsets = section_offsets; + +#ifndef IBM6000_TARGET + /* This is a SVR4/SunOS specific hack, I think. In any event, it + screws RS/6000. sym_offsets should be doing this sort of thing, + because it knows the mapping between bfd sections and + section_offsets. */ + /* This is a hack. As far as I can tell, section offsets are not + target dependent. They are all set to addr with a couple of + exceptions. The exceptions are sysvr4 shared libraries, whose + offsets are kept in solib structures anyway and rs6000 xcoff + which handles shared libraries in a completely unique way. + + Section offsets are built similarly, except that they are built + by adding addr in all cases because there is no clear mapping + from section_offsets into actual sections. Note that solib.c + has a different algorythm for finding section offsets. + + These should probably all be collapsed into some target + independent form of shared library support. FIXME. */ + + if (addr) + { + struct obj_section *s; + + for (s = objfile->sections; s < objfile->sections_end; ++s) + { + s->addr -= s->offset; + s->addr += addr; + s->endaddr -= s->offset; + s->endaddr += addr; + s->offset += addr; + } + } +#endif /* not IBM6000_TARGET */ + (*objfile -> sf -> sym_read) (objfile, section_offsets, mainline); - /* Don't allow char * to have a typename (else would get caddr_t.) */ - /* Ditto void *. FIXME should do this for all the builtin types. */ + if (!have_partial_symbols () && !have_full_symbols ()) + { + wrap_here (""); + printf_filtered ("(no debugging symbols found)..."); + wrap_here (""); + } + + /* Don't allow char * to have a typename (else would get caddr_t). + Ditto void *. FIXME: Check whether this is now done by all the + symbol readers themselves (many of them now do), and if so remove + it from here. */ TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0; TYPE_NAME (lookup_pointer_type (builtin_type_void)) = 0; @@ -494,9 +538,20 @@ syms_from_objfile (objfile, addr, mainline, verbo) that this does not mean we found any symbols... */ objfile -> flags |= OBJF_SYMS; + + /* Discard cleanups as symbol reading was successful. */ + + discard_cleanups (old_chain); + +/* Call this after reading in a new symbol table to give target dependant code + a crack at the new symbols. For instance, this could be used to update the + values of target-specific symbols GDB needs to keep track of (such as + _sigtramp, or whatever). */ + + TARGET_SYMFILE_POSTREAD (objfile); } -/* Perform required actions immediately after either reading in the initial +/* Perform required actions after either reading in the initial symbols for a new objfile, or mapping in the symbols from a reusable objfile. */ @@ -506,22 +561,24 @@ new_symfile_objfile (objfile, mainline, verbo) int mainline; int verbo; { + + /* 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 + breakpoints that may have been redefined by this symbol file. */ if (mainline) { /* OK, make it the "real" symbol file. */ symfile_objfile = objfile; - } - /* If we have wiped out any old symbol tables, clean up. */ - clear_symtab_users_once (); + clear_symtab_users (); + } + else + { + breakpoint_re_set (); + } /* We're done reading the symbol file; finish off complaints. */ clear_complaints (0, verbo); - - /* Fixup all the breakpoints that may have been redefined by this - symbol file. */ - - breakpoint_re_set (); } /* Process a symbol file, as either the main file or as a dynamically @@ -550,37 +607,16 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow) struct partial_symtab *psymtab; bfd *abfd; - /* Open a bfd for the file and then check to see if the file has a - symbol table. There is a distinction between having no symbol table - (we refuse to read the file, leaving the old set of symbols around) - and having no debugging symbols in the symbol table (we read the file - and end up with a mostly empty symbol table, but with lots of stuff in - the minimal symbol table). We need to make the decision about whether - to continue with the file before allocating and building a objfile. - - FIXME: This strategy works correctly when the debugging symbols are - intermixed with "normal" symbols. However, when the debugging symbols - are separate, such as with ELF/DWARF, it is perfectly plausible for - the symbol table to be missing but still have all the DWARF info - intact. Thus in general it is wrong to assume that having no symbol - table implies no debugging information. */ + /* Open a bfd for the file, and give user a chance to burp if we'd be + interactively wiping out any existing symbols. */ abfd = symfile_bfd_open (name); - if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) - { - error ("%s has no symbol-table", name); - } if ((have_full_symbols () || have_partial_symbols ()) && mainline && from_tty && !query ("Load new symbol table from \"%s\"? ", name)) error ("Not confirmed."); - - /* Getting new symbols may change our opinion about what is - frameless. */ - - reinit_frame_cache (); objfile = allocate_objfile (abfd, mapped); @@ -597,7 +633,7 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow) { printf_filtered ("Mapped symbols for %s...", name); wrap_here (""); - fflush (stdout); + gdb_flush (gdb_stdout); } init_entry_point_info (objfile); find_sym_fns (objfile); @@ -611,13 +647,11 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow) { printf_filtered ("Reading symbols from %s...", name); wrap_here (""); - fflush (stdout); + gdb_flush (gdb_stdout); } syms_from_objfile (objfile, addr, mainline, from_tty); } - new_symfile_objfile (objfile, mainline, from_tty); - /* We now have at least a partial symbol table. Check to see if the user requested that all symbols be read on initial access via either the gdb startup command line or on a per symbol file basis. Expand @@ -629,7 +663,7 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow) { printf_filtered ("expanding to full symbols..."); wrap_here (""); - fflush (stdout); + gdb_flush (gdb_stdout); } for (psymtab = objfile -> psymtabs; @@ -643,14 +677,25 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow) if (from_tty || info_verbose) { printf_filtered ("done.\n"); - fflush (stdout); + gdb_flush (gdb_stdout); } + new_symfile_objfile (objfile, mainline, from_tty); + + target_new_objfile (objfile); + return (objfile); } -/* This is the symbol-file command. Read the file, analyze its symbols, - and add a struct symtab to a symtab list. */ +/* This is the symbol-file command. Read the file, analyze its + symbols, and add a struct symtab to a symtab list. The syntax of + the command is rather bizarre--(1) buildargv implements various + quoting conventions which are undocumented and have little or + nothing in common with the way things are quoted (or not quoted) + elsewhere in GDB, (2) options are used, which are not generally + used in GDB (perhaps "set mapped on", "set readnow on" would be + better), (3) the order of options matters, which is contrary to GNU + conventions (because it is confusing and inconvenient). */ void symbol_file_command (args, from_tty) @@ -659,6 +704,7 @@ symbol_file_command (args, from_tty) { char **argv; char *name = NULL; + CORE_ADDR text_relocation = 0; /* text_relocation */ struct cleanup *cleanups; int mapped = 0; int readnow = 0; @@ -674,11 +720,9 @@ symbol_file_command (args, from_tty) error ("Not confirmed."); free_all_objfiles (); symfile_objfile = NULL; - current_source_symtab = NULL; - current_source_line = 0; if (from_tty) { - printf ("No symbol file now.\n"); + printf_unfiltered ("No symbol file now.\n"); } } else @@ -704,7 +748,32 @@ symbol_file_command (args, from_tty) } else { - name = *argv; + char *p; + + name = *argv; + + /* this is for rombug remote only, to get the text relocation by + using link command */ + p = strrchr(name, '/'); + if (p != NULL) p++; + else p = name; + + target_link(p, &text_relocation); + + if (text_relocation == (CORE_ADDR)0) + return; + else if (text_relocation == (CORE_ADDR)-1) + symbol_file_add (name, from_tty, (CORE_ADDR)0, 1, mapped, + readnow); + else + symbol_file_add (name, from_tty, (CORE_ADDR)text_relocation, + 0, mapped, readnow); + + /* Getting new symbols may change our opinion about what is + frameless. */ + reinit_frame_cache (); + + set_initial_language (); } argv++; } @@ -713,11 +782,6 @@ symbol_file_command (args, from_tty) { error ("no symbol file name was specified"); } - else - { - symbol_file_add (name, from_tty, (CORE_ADDR)0, 1, mapped, readnow); - set_initial_language (); - } do_cleanups (cleanups); } } @@ -771,7 +835,7 @@ symfile_bfd_open (name) 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"), 1, name, O_RDONLY, 0, &absolute_name); + desc = openp (getenv ("PATH"), 1, name, O_RDONLY | O_BINARY, 0, &absolute_name); if (desc < 0) { make_cleanup (free, name); @@ -781,22 +845,25 @@ symfile_bfd_open (name) name = absolute_name; /* Keep 2nd malloc'd copy in bfd */ /* It'll be freed in free_objfile(). */ - sym_bfd = bfd_fdopenr (name, NULL, desc); + sym_bfd = bfd_fdopenr (name, gnutarget, desc); if (!sym_bfd) { close (desc); make_cleanup (free, name); error ("\"%s\": can't open to read symbols: %s.", name, - bfd_errmsg (bfd_error)); + bfd_errmsg (bfd_get_error ())); } sym_bfd->cacheable = true; if (!bfd_check_format (sym_bfd, bfd_object)) { + /* FIXME: should be checking for errors from bfd_close (for one thing, + on error it does not free all the storage associated with the + bfd). */ bfd_close (sym_bfd); /* This also closes desc */ make_cleanup (free, name); error ("\"%s\": can't read symbols: %s.", name, - bfd_errmsg (bfd_error)); + bfd_errmsg (bfd_get_error ())); } return (sym_bfd); @@ -826,11 +893,21 @@ find_sym_fns (objfile) struct objfile *objfile; { struct sym_fns *sf; + enum bfd_flavour our_flavour = bfd_get_flavour (objfile -> obfd); + char *our_target = bfd_get_target (objfile -> obfd); + + /* Special kludge for RS/6000 and PowerMac. See xcoffread.c. */ + if (STREQ (our_target, "aixcoff-rs6000") || + STREQ (our_target, "xcoff-powermac")) + our_flavour = (enum bfd_flavour)-1; + + /* Special kludge for apollo. See dstread.c. */ + if (STREQN (our_target, "apollo", 6)) + our_flavour = (enum bfd_flavour)-2; for (sf = symtab_fns; sf != NULL; sf = sf -> next) { - if (strncmp (bfd_get_target (objfile -> obfd), - sf -> sym_name, sf -> sym_namelen) == 0) + if (our_flavour == sf -> sym_flavour) { objfile -> sf = sf; return; @@ -847,9 +924,132 @@ load_command (arg, from_tty) char *arg; int from_tty; { + if (arg == NULL) + arg = get_exec_file (1); target_load (arg, from_tty); } +/* This version of "load" should be usable for any target. Currently + it is just used for remote targets, not inftarg.c or core files, + on the theory that only in that case is it useful. + + Avoiding xmodem and the like seems like a win (a) because we don't have + to worry about finding it, and (b) On VMS, fork() is very slow and so + we don't want to run a subprocess. On the other hand, I'm not sure how + performance compares. */ +void +generic_load (filename, from_tty) + char *filename; + int from_tty; +{ + struct cleanup *old_cleanups; + asection *s; + bfd *loadfile_bfd; + time_t start_time, end_time; /* Start and end times of download */ + unsigned long data_count = 0; /* Number of bytes transferred to memory */ + int n; + unsigned long load_offset = 0; /* offset to add to vma for each section */ + char buf[128]; + + /* enable user to specify address for downloading as 2nd arg to load */ + n = sscanf(filename, "%s 0x%x", buf, &load_offset); + if (n > 1 ) + filename = buf; + else + load_offset = 0; + + loadfile_bfd = bfd_openr (filename, gnutarget); + if (loadfile_bfd == NULL) + { + perror_with_name (filename); + return; + } + /* FIXME: should be checking for errors from bfd_close (for one thing, + on error it does not free all the storage associated with the + bfd). */ + old_cleanups = make_cleanup (bfd_close, loadfile_bfd); + + if (!bfd_check_format (loadfile_bfd, bfd_object)) + { + error ("\"%s\" is not an object file: %s", filename, + bfd_errmsg (bfd_get_error ())); + } + + start_time = time (NULL); + + for (s = loadfile_bfd->sections; s; s = s->next) + { + if (s->flags & SEC_LOAD) + { + bfd_size_type size; + + size = bfd_get_section_size_before_reloc (s); + if (size > 0) + { + char *buffer; + struct cleanup *old_chain; + bfd_vma vma; + + data_count += size; + + buffer = xmalloc (size); + old_chain = make_cleanup (free, buffer); + + vma = bfd_get_section_vma (loadfile_bfd, s); + vma += load_offset; + + /* Is this really necessary? I guess it gives the user something + to look at during a long download. */ + printf_filtered ("Loading section %s, size 0x%lx vma ", + bfd_get_section_name (loadfile_bfd, s), + (unsigned long) size); + print_address_numeric (vma, 1, gdb_stdout); + printf_filtered ("\n"); + + bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size); + + target_write_memory (vma, buffer, size); + + do_cleanups (old_chain); + } + } + } + + end_time = time (NULL); + + printf_filtered ("Start address 0x%lx\n", loadfile_bfd->start_address); + + /* We were doing this in remote-mips.c, I suspect it is right + for other targets too. */ + write_pc (loadfile_bfd->start_address); + + /* FIXME: are we supposed to call symbol_file_add or not? According to + a comment from remote-mips.c (where a call to symbol_file_add was + commented out), making the call confuses GDB if more than one file is + loaded in. remote-nindy.c had no call to symbol_file_add, but remote-vx.c + does. */ + + report_transfer_performance (data_count, start_time, end_time); + + do_cleanups (old_cleanups); +} + +/* Report how fast the transfer went. */ + +void +report_transfer_performance (data_count, start_time, end_time) +unsigned long data_count; +time_t start_time, end_time; +{ + printf_filtered ("Transfer rate: "); + if (end_time != start_time) + printf_filtered ("%d bits/sec", + (data_count * 8) / (end_time - start_time)); + else + printf_filtered ("%d bits in <1 sec", (data_count * 8)); + printf_filtered (".\n"); +} + /* This function allows the addition of incrementally linked object files. It does not modify any state in the target, only in the debugger. */ @@ -910,20 +1110,46 @@ add_symbol_file_command (args, from_tty) left pointing at the remainder of the command line, which should be the address expression to evaluate. */ - if ((name == NULL) || (*args == '\000') ) + if (name == NULL) { - error ("add-symbol-file takes a file name and an address"); + error ("add-symbol-file takes a file name"); } name = tilde_expand (name); make_cleanup (free, name); - text_addr = parse_and_eval_address (args); + if (*args != '\000') + { + text_addr = parse_and_eval_address (args); + } + else + { + target_link(name, &text_addr); + if (text_addr == (CORE_ADDR)-1) + error("Don't know how to get text start location for this file"); + } + /* FIXME-32x64: Assumes text_addr fits in a long. */ if (!query ("add symbol table from file \"%s\" at text_addr = %s?\n", - name, local_hex_string (text_addr))) + name, local_hex_string ((unsigned long)text_addr))) error ("Not confirmed."); symbol_file_add (name, 0, text_addr, 0, mapped, readnow); + + /* Getting new symbols may change our opinion about what is + frameless. */ + reinit_frame_cache (); +} + +static void +add_shared_symbol_files_command (args, from_tty) + char *args; + int from_tty; +{ +#ifdef ADD_SHARED_SYMBOL_FILES + ADD_SHARED_SYMBOL_FILES (args, from_tty); +#else + error ("This command is not available in this configuration of GDB."); +#endif } /* Re-read symbols if a symbol-file has changed. */ @@ -942,7 +1168,6 @@ reread_symbols () This routine should then walk down each partial symbol table and see if the symbol table that it originates from has been changed */ -the_big_top: for (objfile = object_files; objfile; objfile = objfile->next) { if (objfile->obfd) { #ifdef IBM6000_TARGET @@ -961,24 +1186,163 @@ the_big_top: continue; } new_modtime = new_statbuf.st_mtime; - if (new_modtime != objfile->mtime) { - printf_filtered ("`%s' has changed; re-reading symbols.\n", - objfile->name); - /* FIXME, this should use a different command...that would only - affect this objfile's symbols, and would reset objfile->mtime. - (objfile->mtime = new_modtime;) - HOWEVER, that command isn't written yet -- so call symbol_file_ - command, and restart the scan from the top, because it munges - the object_files list. */ - symbol_file_command (objfile->name, 0); - reread_one = 1; - goto the_big_top; /* Start over. */ - } + if (new_modtime != objfile->mtime) + { + struct cleanup *old_cleanups; + struct section_offsets *offsets; + int num_offsets; + int section_offsets_size; + char *obfd_filename; + + printf_filtered ("`%s' has changed; re-reading symbols.\n", + objfile->name); + + /* There are various functions like symbol_file_add, + symfile_bfd_open, syms_from_objfile, etc., which might + appear to do what we want. But they have various other + effects which we *don't* want. So we just do stuff + ourselves. We don't worry about mapped files (for one thing, + any mapped file will be out of date). */ + + /* If we get an error, blow away this objfile (not sure if + that is the correct response for things like shared + libraries). */ + old_cleanups = make_cleanup (free_objfile, objfile); + /* We need to do this whenever any symbols go away. */ + make_cleanup (clear_symtab_users, 0); + + /* 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. */ + obfd_filename = bfd_get_filename (objfile->obfd); + if (!bfd_close (objfile->obfd)) + error ("Can't close BFD for %s: %s", objfile->name, + bfd_errmsg (bfd_get_error ())); + objfile->obfd = bfd_openr (obfd_filename, gnutarget); + if (objfile->obfd == NULL) + error ("Can't open %s to read symbols.", objfile->name); + /* bfd_openr sets cacheable to true, which is what we want. */ + if (!bfd_check_format (objfile->obfd, bfd_object)) + error ("Can't read symbols from %s: %s.", objfile->name, + bfd_errmsg (bfd_get_error ())); + + /* Save the offsets, we will nuke them with the rest of the + psymbol_obstack. */ + num_offsets = objfile->num_sections; + section_offsets_size = + sizeof (struct section_offsets) + + sizeof (objfile->section_offsets->offsets) * num_offsets; + offsets = (struct section_offsets *) alloca (section_offsets_size); + memcpy (offsets, objfile->section_offsets, section_offsets_size); + + /* 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. */ + + /* FIXME: Do we have to free a whole linked list, or is this + enough? */ + if (objfile->global_psymbols.list) + mfree (objfile->md, objfile->global_psymbols.list); + memset (&objfile -> global_psymbols, 0, + sizeof (objfile -> global_psymbols)); + if (objfile->static_psymbols.list) + mfree (objfile->md, objfile->static_psymbols.list); + memset (&objfile -> static_psymbols, 0, + sizeof (objfile -> static_psymbols)); + + /* Free the obstacks for non-reusable objfiles */ + obstack_free (&objfile -> psymbol_cache.cache, 0); + memset (&objfile -> psymbol_cache, 0, + sizeof (objfile -> psymbol_cache)); + obstack_free (&objfile -> psymbol_obstack, 0); + obstack_free (&objfile -> symbol_obstack, 0); + obstack_free (&objfile -> type_obstack, 0); + objfile->sections = NULL; + objfile->symtabs = NULL; + objfile->psymtabs = NULL; + objfile->free_psymtabs = NULL; + objfile->msymbols = NULL; + objfile->minimal_symbol_count= 0; + objfile->fundamental_types = NULL; + if (objfile -> sf != NULL) + { + (*objfile -> sf -> sym_finish) (objfile); + } + + /* We never make this a mapped file. */ + objfile -> md = NULL; + /* obstack_specify_allocation also initializes the obstack so + it is empty. */ + obstack_specify_allocation (&objfile -> psymbol_cache.cache, 0, 0, + xmalloc, free); + obstack_specify_allocation (&objfile -> psymbol_obstack, 0, 0, + xmalloc, free); + obstack_specify_allocation (&objfile -> symbol_obstack, 0, 0, + xmalloc, free); + obstack_specify_allocation (&objfile -> type_obstack, 0, 0, + xmalloc, free); + if (build_objfile_section_table (objfile)) + { + error ("Can't find the file sections in `%s': %s", + objfile -> name, bfd_errmsg (bfd_get_error ())); + } + + /* We use the same section offsets as from last time. I'm not + sure whether that is always correct for shared libraries. */ + objfile->section_offsets = (struct section_offsets *) + obstack_alloc (&objfile -> psymbol_obstack, section_offsets_size); + memcpy (objfile->section_offsets, offsets, section_offsets_size); + objfile->num_sections = num_offsets; + + /* What the hell is sym_new_init for, anyway? The concept of + distinguishing between the main file and additional files + in this way seems rather dubious. */ + if (objfile == symfile_objfile) + (*objfile->sf->sym_new_init) (objfile); + + (*objfile->sf->sym_init) (objfile); + clear_complaints (1, 1); + /* The "mainline" parameter is a hideous hack; I think leaving it + zero is OK since dbxread.c also does what it needs to do if + objfile->global_psymbols.size is 0. */ + (*objfile->sf->sym_read) (objfile, objfile->section_offsets, 0); + if (!have_partial_symbols () && !have_full_symbols ()) + { + wrap_here (""); + printf_filtered ("(no debugging symbols found)\n"); + wrap_here (""); + } + objfile -> flags |= OBJF_SYMS; + + /* We're done reading the symbol file; finish off complaints. */ + clear_complaints (0, 1); + + /* Getting new symbols may change our opinion about what is + frameless. */ + + reinit_frame_cache (); + + /* Discard cleanups as symbol reading was successful. */ + discard_cleanups (old_cleanups); + + /* If the mtime has changed between the time we set new_modtime + and now, we *want* this to be out of date, so don't call stat + again now. */ + objfile->mtime = new_modtime; + reread_one = 1; + + /* Call this after reading in a new symbol table to give target + dependant code a crack at the new symbols. For instance, this + could be used to update the values of target-specific symbols GDB + needs to keep track of (such as _sigtramp, or whatever). */ + + TARGET_SYMFILE_POSTREAD (objfile); + } } } if (reread_one) - breakpoint_re_set (); + clear_symtab_users (); } @@ -986,19 +1350,25 @@ enum language deduce_language_from_filename (filename) char *filename; { - char *c = strrchr (filename, '.'); + char *c; - if (!c) ; /* Get default. */ - else if(STREQ(c,".mod")) - return language_m2; - else if(STREQ(c,".c")) - return language_c; - else if(STREQ(c,".cc") || STREQ(c,".C")) - return language_cplus; - /* start-sanitize-chill */ - else if(STREQ(c,".ch") || STREQ(c,".c186") || STREQ(c,".c286")) - return language_chill; - /* end-sanitize-chill */ + if (0 == filename) + ; /* Get default */ + else if (0 == (c = strrchr (filename, '.'))) + ; /* Get default. */ + else if (STREQ (c, ".c")) + return language_c; + else if (STREQ (c, ".cc") || STREQ (c, ".C") || STREQ (c, ".cxx") + || STREQ (c, ".cpp") || STREQ (c, ".cp") || STREQ (c, ".c++")) + return language_cplus; + else if (STREQ (c, ".ch") || STREQ (c, ".c186") || STREQ (c, ".c286")) + return language_chill; + else if (STREQ (c, ".f") || STREQ (c, ".F")) + return language_fortran; + else if (STREQ (c, ".mod")) + return language_m2; + else if (STREQ (c, ".s") || STREQ (c, ".S")) + return language_asm; return language_unknown; /* default */ } @@ -1078,6 +1448,25 @@ allocate_psymtab (filename, objfile) } +/* Reset all data structures in gdb which may contain references to symbol + table date. */ + +void +clear_symtab_users () +{ + /* Someday, we should do better than this, by only blowing away + the things that really need to be blown. */ + clear_value_history (); + clear_displays (); + clear_internalvars (); + breakpoint_re_set (); + set_default_breakpoint (0, 0, 0, 0); + current_source_symtab = 0; + current_source_line = 0; + clear_pc_function_cache (); + target_new_objfile (NULL); +} + /* clear_symtab_users_once: This function is run after symbol reading, or from a cleanup. @@ -1103,10 +1492,16 @@ allocate_psymtab (filename, objfile) reading, is because the cleanup protects us in case of errors, but is discarded if symbol reading is successful. */ +#if 0 +/* FIXME: As free_named_symtabs is currently a big noop this function + is no longer needed. */ +static void +clear_symtab_users_once PARAMS ((void)); + static int clear_symtab_users_queued; static int clear_symtab_users_done; -void +static void clear_symtab_users_once () { /* Enforce once-per-`do_cleanups'-semantics */ @@ -1114,17 +1509,9 @@ clear_symtab_users_once () return; clear_symtab_users_done = clear_symtab_users_queued; - printf ("Resetting debugger state after updating old symbol tables\n"); - - /* Someday, we should do better than this, by only blowing away - the things that really need to be blown. */ - clear_value_history (); - clear_displays (); - clear_internalvars (); - breakpoint_re_set (); - set_default_breakpoint (0, 0, 0, 0); - current_source_symtab = 0; + clear_symtab_users (); } +#endif /* Delete the specified psymtab, and any others that reference it. */ @@ -1132,7 +1519,7 @@ static void cashier_psymtab (pst) struct partial_symtab *pst; { - struct partial_symtab *ps, *pprev; + struct partial_symtab *ps, *pprev = NULL; int i; /* Find its previous psymtab in the chain */ @@ -1294,8 +1681,8 @@ start_psymtab_common (objfile, section_offsets, struct section_offsets *section_offsets; char *filename; CORE_ADDR textlow; - struct partial_symbol *global_syms; - struct partial_symbol *static_syms; + struct partial_symbol **global_syms; + struct partial_symbol **static_syms; { struct partial_symtab *psymtab; @@ -1308,129 +1695,123 @@ start_psymtab_common (objfile, section_offsets, return (psymtab); } -/* Debugging versions of functions that are usually inline macros - (see symfile.h). */ - -#if !INLINE_ADD_PSYMBOL - /* Add a symbol with a long value to a psymtab. Since one arg is a struct, we pass in a ptr and deref it (sigh). */ void -add_psymbol_to_list (name, namelength, namespace, class, list, val, language, - objfile) +add_psymbol_to_list (name, namelength, namespace, class, list, val, coreaddr, + language, objfile) char *name; int namelength; - enum namespace namespace; + namespace_enum namespace; enum address_class class; struct psymbol_allocation_list *list; - long val; + long val; /* Value as a long */ + CORE_ADDR coreaddr; /* Value as a CORE_ADDR */ enum language language; struct objfile *objfile; { register struct partial_symbol *psym; - register char *demangled_name; + char *buf = alloca (namelength + 1); + /* psymbol is static so that there will be no uninitialized gaps in the + structure which might contain random data, causing cache misses in + bcache. */ + static struct partial_symbol psymbol; + + /* Create local copy of the partial symbol */ + memcpy (buf, name, namelength); + buf[namelength] = '\0'; + SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache); + /* val and coreaddr are mutually exclusive, one of them *will* be zero */ + if (val != 0) + { + SYMBOL_VALUE (&psymbol) = val; + } + else + { + SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr; + } + SYMBOL_SECTION (&psymbol) = 0; + SYMBOL_LANGUAGE (&psymbol) = language; + PSYMBOL_NAMESPACE (&psymbol) = namespace; + PSYMBOL_CLASS (&psymbol) = class; + SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language); + /* Stash the partial symbol away in the cache */ + psym = bcache (&psymbol, sizeof (struct partial_symbol), &objfile->psymbol_cache); + + /* Save pointer to partial symbol in psymtab, growing symtab if needed. */ if (list->next >= list->list + list->size) { - extend_psymbol_list (list,objfile); + extend_psymbol_list (list, objfile); } - psym = list->next++; - - SYMBOL_NAME (psym) = - (char *) obstack_alloc (&objfile->psymbol_obstack, namelength + 1); - memcpy (SYMBOL_NAME (psym), name, namelength); - SYMBOL_NAME (psym)[namelength] = '\0'; - SYMBOL_VALUE (psym) = val; - SYMBOL_LANGUAGE (psym) = language; - PSYMBOL_NAMESPACE (psym) = namespace; - PSYMBOL_CLASS (psym) = class; - if (language == language_cplus) - { - demangled_name = - cplus_demangle (SYMBOL_NAME (psym), DMGL_PARAMS | DMGL_ANSI); - if (demangled_name == NULL) - { - SYMBOL_DEMANGLED_NAME (psym) = NULL; - } - else - { - SYMBOL_DEMANGLED_NAME (psym) = - obsavestring (demangled_name, strlen (demangled_name), - &objfile->psymbol_obstack); - free (demangled_name); - } - } + *list->next++ = psym; + OBJSTAT (objfile, n_psyms++); } -/* Add a symbol with a CORE_ADDR value to a psymtab. */ +/* Initialize storage for partial symbols. */ void -add_psymbol_addr_to_list (name, namelength, namespace, class, list, val, - language, objfile) - char *name; - int namelength; - enum namespace namespace; - enum address_class class; - struct psymbol_allocation_list *list; - CORE_ADDR val; - enum language language; +init_psymbol_list (objfile, total_symbols) struct objfile *objfile; + int total_symbols; { - register struct partial_symbol *psym; - register char *demangled_name; - - if (list->next >= list->list + list->size) + /* Free any previously allocated psymbol lists. */ + + if (objfile -> global_psymbols.list) { - extend_psymbol_list (list,objfile); + mfree (objfile -> md, (PTR)objfile -> global_psymbols.list); } - psym = list->next++; - - SYMBOL_NAME (psym) = - (char *) obstack_alloc (&objfile->psymbol_obstack, namelength + 1); - memcpy (SYMBOL_NAME (psym), name, namelength); - SYMBOL_NAME (psym)[namelength] = '\0'; - SYMBOL_VALUE_ADDRESS (psym) = val; - SYMBOL_LANGUAGE (psym) = language; - PSYMBOL_NAMESPACE (psym) = namespace; - PSYMBOL_CLASS (psym) = class; - if (language == language_cplus) + if (objfile -> static_psymbols.list) { - demangled_name = - cplus_demangle (SYMBOL_NAME (psym), DMGL_PARAMS | DMGL_ANSI); - if (demangled_name == NULL) - { - SYMBOL_DEMANGLED_NAME (psym) = NULL; - } - else - { - SYMBOL_DEMANGLED_NAME (psym) = - obsavestring (demangled_name, strlen (demangled_name), - &objfile->psymbol_obstack); - free (demangled_name); - } - } + mfree (objfile -> md, (PTR)objfile -> static_psymbols.list); + } + + /* Current best guess is that approximately a twentieth + of the total symbols (in a debugging file) are global or static + oriented symbols */ + + objfile -> global_psymbols.size = total_symbols / 10; + objfile -> static_psymbols.size = total_symbols / 10; + objfile -> global_psymbols.next = + objfile -> global_psymbols.list = (struct partial_symbol **) + xmmalloc (objfile -> md, objfile -> global_psymbols.size + * sizeof (struct partial_symbol *)); + objfile -> static_psymbols.next = + objfile -> static_psymbols.list = (struct partial_symbol **) + xmmalloc (objfile -> md, objfile -> static_psymbols.size + * sizeof (struct partial_symbol *)); } - -#endif /* !INLINE_ADD_PSYMBOL */ - void _initialize_symfile () { - - add_com ("symbol-file", class_files, symbol_file_command, + struct cmd_list_element *c; + + 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\ -to execute."); - - add_com ("add-symbol-file", class_files, add_symbol_file_command, - "Load the symbols from FILE, assuming FILE has been dynamically loaded.\n\ -The second argument provides the starting address of the file's text."); - - add_com ("load", class_files, load_command, +to execute.", &cmdlist); + c->completer = filename_completer; + + c = add_cmd ("add-symbol-file", class_files, add_symbol_file_command, + "Usage: add-symbol-file FILE ADDR\n\ +Load the symbols from FILE, assuming FILE has been dynamically loaded.\n\ +ADDR is the starting address of the file's text.", + &cmdlist); + c->completer = filename_completer; + + c = add_cmd ("add-shared-symbol-files", class_files, + add_shared_symbol_files_command, + "Load the symbols from shared objects in the dynamic linker's link map.", + &cmdlist); + c = add_alias_cmd ("assf", "add-shared-symbol-files", class_files, 1, + &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."); +for access from GDB.", &cmdlist); + c->completer = filename_completer; add_show_from_set (add_set_cmd ("symbol-reloading", class_support, var_boolean,