/* Generic symbol file reading for the GNU debugger, GDB.
- Copyright 1990, 1991, 1992, 1993 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.
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"
#include "complaints.h"
#include "demangle.h"
#include "inferior.h" /* for write_pc */
+#include "gdb-stabs.h"
+#include "obstack.h"
-#include <obstack.h>
#include <assert.h>
-
#include <sys/types.h>
#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
+#include "gdb_string.h"
+#include "gdb_stat.h"
#include <ctype.h>
+#include <time.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#ifndef O_BINARY
#define O_BINARY 0
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 *));
+
+static void find_sym_fns PARAMS ((struct objfile *));
+
+static void decrement_reading_symtab PARAMS ((void *));
/* 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
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. */
int symbol_reloading = 0;
#endif
+/* 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. */
+
+int auto_solib_add = 1;
+
\f
/* Since this function is called from within qsort, in an ANSI environment
it must conform to the prototype for qsort, which specifies that the
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
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])
{
/* 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);
}
}
}
-/* 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. */
+/* Make a null terminated copy of the string at PTR with SIZE characters in
+ the obstack pointed to by OBSTACKP . Returns the address of the copy.
+ Note that the string at PTR does not have to be null terminated, I.E. it
+ may be part of a larger string and we are only saving a substring. */
char *
obsavestring (ptr, size, obstackp)
struct obstack *obstackp;
{
register char *p = (char *) obstack_alloc (obstackp, size + 1);
- /* Open-coded memcpy--saves function call time.
- These strings are usually short. */
+ /* Open-coded memcpy--saves function call time. These strings are usually
+ short. FIXME: Is this really still true with a compiler that can
+ inline memcpy? */
{
register char *p1 = ptr;
register char *p2 = p;
return p;
}
-/* Concatenate strings S1, S2 and S3; return the new string.
- Space is found in the symbol_obstack. */
+/* Concatenate strings S1, S2 and S3; return the new string. Space is found
+ in the obstack pointed to by OBSTACKP. */
char *
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
/* 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;
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. */
}
/* 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;
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;
+}
+
+/* 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;
}
-#endif
+
/* Process a symbol file, as either the main file or as a dynamically
loaded file.
/* 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 <addr> 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)
{
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)))
+ 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,
(*objfile -> sf -> sym_read) (objfile, section_offsets, mainline);
+ 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
/* 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 after either reading in the initial
}
new_symfile_objfile (objfile, mainline, from_tty);
-
- /* Getting new symbols may change our opinion about what is
- frameless. */
- reinit_frame_cache ();
+ 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)
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++;
/* Look down path for it, allocate 2nd new malloc'd copy. */
desc = openp (getenv ("PATH"), 1, name, O_RDONLY | O_BINARY, 0, &absolute_name);
+#if defined(__GO32__) || defined(__WIN32__)
+ if (desc < 0)
+ {
+ char *exename = alloca (strlen (name) + 5);
+ strcat (strcpy (exename, name), ".exe");
+ desc = openp (getenv ("PATH"), 1, exename, O_RDONLY | O_BINARY,
+ 0, &absolute_name);
+ }
+#endif
if (desc < 0)
{
make_cleanup (free, name);
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,
enum bfd_flavour our_flavour = bfd_get_flavour (objfile -> obfd);
char *our_target = bfd_get_target (objfile -> obfd);
- /* Special kludge for RS/6000. See xcoffread.c. */
- if (STREQ (our_target, "aixcoff-rs6000"))
+ /* 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. */
char *arg;
int from_tty;
{
+ if (arg == NULL)
+ arg = get_exec_file (1);
target_load (arg, from_tty);
}
struct cleanup *old_cleanups;
asection *s;
bfd *loadfile_bfd;
-
- if (filename == NULL)
- filename = get_exec_file (1);
+ 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%lx", 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))
bfd_errmsg (bfd_get_error ()));
}
+ start_time = time (NULL);
+
for (s = loadfile_bfd->sections; s; s = s->next)
{
if (s->flags & SEC_LOAD)
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, gdb_stdout);
+ print_address_numeric (vma, 1, gdb_stdout);
printf_filtered ("\n");
bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size);
}
}
+ 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);
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. */
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 ();
+}
+\f
+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
}
\f
/* Re-read symbols if a symbol-file has changed. */
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);
/* 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.", objfile->name);
- objfile->obfd = bfd_openr (objfile->name, gnutarget);
+ 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. */
enough? */
if (objfile->global_psymbols.list)
mfree (objfile->md, objfile->global_psymbols.list);
- objfile->global_psymbols.list = NULL;
- objfile->global_psymbols.next = NULL;
- objfile->global_psymbols.size = 0;
+ memset (&objfile -> global_psymbols, 0,
+ sizeof (objfile -> global_psymbols));
if (objfile->static_psymbols.list)
mfree (objfile->md, objfile->static_psymbols.list);
- objfile->static_psymbols.list = NULL;
- objfile->static_psymbols.next = NULL;
- objfile->static_psymbols.size = 0;
+ 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 -> 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,
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. */
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);
}
}
}
; /* Get default */
else if (0 == (c = strrchr (filename, '.')))
; /* Get default. */
- else if (STREQ(c,".mod"))
- return language_m2;
- else if (STREQ(c,".c"))
+ else if (STREQ (c, ".c"))
return language_c;
- else if (STREQ (c,".cc") || STREQ (c,".C") || STREQ (c, ".cxx")
- || STREQ (c, ".cpp"))
+ 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"))
+ 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 */
}
current_source_symtab = 0;
current_source_line = 0;
clear_pc_function_cache ();
+ target_new_objfile (NULL);
}
/* clear_symtab_users_once:
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;
return (psymtab);
}
\f
-/* 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;
- SYMBOL_INIT_DEMANGLED_NAME (psym, &objfile->psymbol_obstack);
+ *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++;
+ if (objfile -> static_psymbols.list)
+ {
+ 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 */
- 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;
- SYMBOL_INIT_DEMANGLED_NAME (psym, &objfile->psymbol_obstack);
+ 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 */
-
\f
void
_initialize_symfile ()
c->completer = filename_completer;
c = add_cmd ("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.",
+ "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.", &cmdlist);