/* Generic symbol file reading for the GNU debugger, GDB.
- Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
Contributed by Cygnus Support, using pieces from other GDB modules.
This file is part of GDB.
#include "target.h"
#include "value.h"
#include "symfile.h"
+#include "objfiles.h"
#include "gdbcmd.h"
#include "breakpoint.h"
+#include "language.h"
+#include "complaints.h"
+#include "demangle.h"
+#include "inferior.h" /* for write_pc */
#include <obstack.h>
#include <assert.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
+#include <ctype.h>
-/* Global variables owned by this file */
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
-CORE_ADDR entry_point; /* Where execution starts in symfile */
+/* Global variables owned by this file */
int readnow_symbol_files; /* Read full symbols immediately */
+struct complaint oldsyms_complaint = {
+ "Replacing old symbols for `%s'", 0, 0
+};
+
+struct complaint empty_symtab_complaint = {
+ "Empty symbol table found for `%s'", 0, 0
+};
+
/* External variables and functions referenced. */
extern int info_verbose;
-extern CORE_ADDR startup_file_start; /* From blockframe.c */
-extern CORE_ADDR startup_file_end; /* From blockframe.c */
-
/* Functions this file defines */
+static void
+set_initial_language PARAMS ((void));
+
static void
load_command PARAMS ((char *, int));
static void
add_symbol_file_command PARAMS ((char *, int));
+static void
+add_shared_symbol_files_command PARAMS ((char *, int));
+
static void
cashier_psymtab PARAMS ((struct partial_symtab *));
static void
find_sym_fns PARAMS ((struct objfile *));
-static void
-clear_symtab_users_once 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
prepared to read. */
static struct sym_fns *symtab_fns = NULL;
-/* When we need to allocate a new type, we need to know which type_obstack
- to allocate the type on, since there is one for each objfile. The places
- where types are allocated are deeply buried in function call hierarchies
- which know nothing about objfiles, so rather than trying to pass a
- particular objfile down to them, we just do an end run around them and
- set current_objfile to be whatever objfile we expect to be using at the
- time types are being allocated. For instance, when we start reading
- symbols for a particular objfile, we set current_objfile to point to that
- objfile, and when we are done, we set it back to NULL, to ensure that we
- never put a type someplace other than where we are expecting to put it.
- FIXME: Maybe we should review the entire type handling system and
- see if there is a better way to avoid this problem. */
-
-struct objfile *current_objfile = NULL;
-
-/* The object file that the main symbol table was loaded from (e.g. the
- argument to the "symbol-file" or "file" command). */
-
-struct objfile *symfile_objfile = NULL;
-
/* Structures with which to manage partial symbol allocation. */
struct psymbol_allocation_list global_psymbols = {0}, static_psymbols = {0};
int symbol_reloading = 0;
#endif
-/* Structure to manage complaints about symbol file contents. */
-
-struct complaint complaint_root[1] = {
- {(char *) 0, 0, complaint_root},
-};
-
-/* Some actual complaints. */
-
-struct complaint oldsyms_complaint = {
- "Replacing old symbols for `%s'", 0, 0 };
-
-struct complaint empty_symtab_complaint = {
- "Empty symbol table found for `%s'", 0, 0 };
-
\f
-/* 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).
-
- Since this function is called from within qsort, in an ANSI environment
+/* 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. */
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)));
}
/*
}
else
{
- return (strcmp (st1 + 2, st2 + 2));
+ return (STRCMP (st1 + 2, st2 + 2));
}
}
}
}
-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. */
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;
return pst->symtab;
}
+/* Initialize entry point information for this objfile. */
+
+void
+init_entry_point_info (objfile)
+ struct objfile *objfile;
+{
+ /* Save startup file's range of PC addresses to help blockframe.c
+ decide where the bottom of the stack is. */
+
+ if (bfd_get_file_flags (objfile -> obfd) & EXEC_P)
+ {
+ /* 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);
+ }
+ else
+ {
+ /* Examination of non-executable.o files. Short-circuit this stuff. */
+ objfile -> ei.entry_point = INVALID_ENTRY_POINT;
+ objfile -> ei.entry_file_lowpc = INVALID_ENTRY_LOWPC;
+ objfile -> ei.entry_file_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. */
+
+#if 0 /* Not used yet */
+static void
+find_lowest_section (abfd, sect, obj)
+ bfd *abfd;
+ asection *sect;
+ PTR obj;
+{
+ asection **lowest = (asection **)obj;
+
+ if (0 == (bfd_get_section_flags (abfd, sect) & SEC_LOAD))
+ return;
+ if (!*lowest)
+ *lowest = sect; /* First loadable section */
+ else if (bfd_section_vma (abfd, *lowest) >= bfd_section_vma (abfd, sect))
+ *lowest = sect; /* A lower loadable section */
+}
+#endif
+
/* Process a symbol file, as either the main file or as a dynamically
loaded file.
int mainline;
int verbo;
{
- asection *text_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). */
-
- if (!(bfd_get_file_flags (objfile -> obfd) & HAS_SYMS))
- return;
-
- /* Save startup file's range of PC addresses to help blockframe.c
- decide where the bottom of the stack is. */
-
- if (bfd_get_file_flags (objfile -> obfd) & EXEC_P)
- {
- /* Executable file -- record its entry point so we'll recognize
- the startup file because it contains the entry point. */
- entry_point = bfd_get_start_address (objfile -> obfd);
- }
- else
- {
- /* Examination of non-executable.o files. Short-circuit this stuff. */
- /* ~0 will not be in any file, we hope. */
- entry_point = ~0;
- /* set the startup file to be an empty range. */
- startup_file_start = 0;
- startup_file_end = 0;
- }
+ struct section_offsets *section_offsets;
+ asection *lowest_sect;
+ 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)
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);
+ }
- /* For mainline, caller didn't know the specified address of the
- text section. We fix that here. */
+ /* 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. */
- text_sect = bfd_get_section_by_name (objfile -> obfd, ".text");
- addr = bfd_section_vma (objfile -> obfd, text_sect);
+ if (mainline)
+ {
+ addr = 0; /* No offset from objfile addresses. */
+ }
+ 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 == 0)
+ 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)))
+ /* 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),
+ (unsigned long) bfd_section_vma (objfile->obfd, lowest_sect));
+
+ if (lowest_sect)
+ addr -= bfd_section_vma (objfile->obfd, lowest_sect);
}
/* Initialize symbol reading routines for this objfile, allow complaints to
(*objfile -> sf -> sym_init) (objfile);
clear_complaints (1, verbo);
- (*objfile -> sf -> sym_read) (objfile, addr, 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. */
+ 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);
+
+ 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;
+ /* Mark the objfile has having had initial symbol read attempted. Note
+ that this does not mean we found any symbols... */
+
+ objfile -> flags |= OBJF_SYMS;
+
+ /* Discard cleanups as symbol reading was successful. */
+
+ discard_cleanups (old_chain);
+}
+
+/* Perform required actions after either reading in the initial
+ symbols for a new objfile, or mapping in the symbols from a reusable
+ objfile. */
+
+void
+new_symfile_objfile (objfile, mainline, verbo)
+ struct objfile *objfile;
+ 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
struct objfile *objfile;
struct partial_symtab *psymtab;
bfd *abfd;
- int mapped_it;
-
- /* 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.");
-
+
objfile = allocate_objfile (abfd, mapped);
/* If the objfile uses a mapped symbol file, and we have a psymtab for
it, then skip reading any symbols at this time. */
- if ((objfile -> flags & OBJF_MAPPED) && (objfile -> psymtabs != NULL))
+ if ((objfile -> flags & OBJF_MAPPED) && (objfile -> flags & OBJF_SYMS))
{
/* We mapped in an existing symbol table file that already has had
- the psymbols read in. So we can skip that part. Notify the user
- that instead of reading the symbols, they have been mapped. */
+ initial symbol reading performed, so we can skip that part. Notify
+ the user that instead of reading the symbols, they have been mapped.
+ */
if (from_tty || info_verbose)
{
printf_filtered ("Mapped symbols for %s...", name);
wrap_here ("");
- fflush (stdout);
+ gdb_flush (gdb_stdout);
}
+ init_entry_point_info (objfile);
+ find_sym_fns (objfile);
}
else
{
/* We either created a new mapped symbol table, mapped an existing
- symbol table file with no partial symbols, or need to read an
- unmapped symbol table. */
+ symbol table file which has not had initial symbol reading
+ performed, or need to read an unmapped symbol table. */
if (from_tty || info_verbose)
{
printf_filtered ("Reading symbols from %s...", name);
wrap_here ("");
- fflush (stdout);
+ gdb_flush (gdb_stdout);
}
syms_from_objfile (objfile, addr, mainline, from_tty);
}
the gdb startup command line or on a per symbol file basis. Expand
all partial symbol tables for this objfile if so. */
- readnow |= readnow_symbol_files;
- if (readnow)
+ if (readnow || readnow_symbol_files)
{
if (from_tty || info_verbose)
{
printf_filtered ("expanding to full symbols...");
wrap_here ("");
- fflush (stdout);
+ gdb_flush (gdb_stdout);
}
for (psymtab = objfile -> psymtabs;
psymtab != NULL;
psymtab = psymtab -> next)
{
- (void) psymtab_to_symtab (psymtab);
+ psymtab_to_symtab (psymtab);
}
}
if (from_tty || info_verbose)
{
printf_filtered ("done.\n");
- fflush (stdout);
+ gdb_flush (gdb_stdout);
}
+ new_symfile_objfile (objfile, mainline, from_tty);
+
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)
{
char **argv;
char *name = NULL;
+ CORE_ADDR text_relocation = 0; /* text_relocation */
struct cleanup *cleanups;
- struct objfile *objfile;
int mapped = 0;
int readnow = 0;
error ("Not confirmed.");
free_all_objfiles ();
symfile_objfile = NULL;
+ if (from_tty)
+ {
+ printf_unfiltered ("No symbol file now.\n");
+ }
}
else
{
cleanups = make_cleanup (freeargv, (char *) argv);
while (*argv != NULL)
{
- if (strcmp (*argv, "-mapped") == 0)
+ if (STREQ (*argv, "-mapped"))
{
mapped = 1;
}
- else if (strcmp (*argv, "-readnow") == 0)
+ else if (STREQ (*argv, "-readnow"))
{
readnow = 1;
}
}
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++;
}
{
error ("no symbol file name was specified");
}
- else
+ do_cleanups (cleanups);
+ }
+}
+
+/* Set the initial language.
+
+ A better solution would be to record the language in the psymtab when reading
+ partial symbols, and then use it (if known) to set the language. This would
+ be a win for formats that encode the language in an easily discoverable place,
+ such as DWARF. For stabs, we can jump through hoops looking for specially
+ named symbols or try to intuit the language from the specific type of stabs
+ we find, but we can't do that until later when we read in full symbols.
+ FIXME. */
+
+static void
+set_initial_language ()
+{
+ struct partial_symtab *pst;
+ enum language lang = language_unknown;
+
+ pst = find_main_psymtab ();
+ if (pst != NULL)
+ {
+ if (pst -> filename != NULL)
{
- /* Getting new symbols may change our opinion about what is
- frameless. */
- reinit_frame_cache ();
- objfile = symbol_file_add (name, from_tty, (CORE_ADDR)0, 1,
- mapped, readnow);
+ lang = deduce_language_from_filename (pst -> filename);
+ }
+ if (lang == language_unknown)
+ {
+ /* Make C the default language */
+ lang = language_c;
}
- do_cleanups (cleanups);
+ set_language (lang);
+ expected_language = current_language; /* Don't warn the user */
}
}
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);
}
free (name); /* Free 1st new malloc'd copy */
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))
{
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);
find_sym_fns (objfile)
struct objfile *objfile;
{
- struct sym_fns *sf, *sf2;
+ 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. See xcoffread.c. */
+ if (STREQ (our_target, "aixcoff-rs6000"))
+ 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;
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;
+
+ loadfile_bfd = bfd_openr (filename, gnutarget);
+ if (loadfile_bfd == NULL)
+ {
+ perror_with_name (filename);
+ return;
+ }
+ 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 ()));
+ }
+
+ 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;
+
+ buffer = xmalloc (size);
+ old_chain = make_cleanup (free, buffer);
+
+ vma = bfd_get_section_vma (loadfile_bfd, s);
+
+ /* 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);
+ }
+ }
+ }
+
+ /* 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. */
+
+ do_cleanups (old_cleanups);
+}
+
/* This function allows the addition of incrementally linked object files.
It does not modify any state in the target, only in the debugger. */
char *name = NULL;
CORE_ADDR text_addr;
char *arg;
- int readnow;
- int mapped;
+ int readnow = 0;
+ int mapped = 0;
dont_repeat ();
{
name = arg;
}
- else if (strcmp (arg, "-mapped") == 0)
+ else if (STREQ (arg, "-mapped"))
{
mapped = 1;
}
- else if (strcmp (arg, "-readnow") == 0)
+ else if (STREQ (arg, "-readnow"))
{
readnow = 1;
}
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 ();
-
- (void) symbol_file_add (name, 0, text_addr, 0, mapped, readnow);
+}
+\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. */
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
+#ifdef IBM6000_TARGET
/* If this object is from a shared library, then you should
stat on the library name, not member name. */
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 (reread_one)
- breakpoint_re_set ();
-}
-\f
-/* Functions to handle complaints during symbol reading. */
-
-/* How many complaints about a particular thing should be printed before
- we stop whining about it? Default is no whining at all, since so many
- systems have ill-constructed symbol files. */
-
-static unsigned stop_whining = 0;
+ 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.", objfile->name);
+ 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);
+ objfile->global_psymbols.list = NULL;
+ objfile->global_psymbols.next = NULL;
+ objfile->global_psymbols.size = 0;
+ 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;
+
+ /* Free the obstacks for non-reusable objfiles */
+ 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);
+ }
-/* Should each complaint be self explanatory, or should we assume that
- a series of complaints is being produced?
- case 0: self explanatory message.
- case 1: First message of a series that must start off with explanation.
- case 2: Subsequent message, when user already knows we are reading
- symbols and we can just state our piece. */
+ /* 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_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 ()));
+ }
-static int complaint_series = 0;
+ /* 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;
-/* Print a complaint about the input symbols, and link the complaint block
- into a chain for later handling. */
+ /* We're done reading the symbol file; finish off complaints. */
+ clear_complaints (0, 1);
-void
-complain (complaint, val)
- struct complaint *complaint;
- char *val;
-{
- complaint->counter++;
- if (complaint->next == 0) {
- complaint->next = complaint_root->next;
- complaint_root->next = complaint;
- }
- if (complaint->counter > stop_whining)
- return;
- wrap_here ("");
-
- switch (complaint_series + (info_verbose << 1)) {
-
- /* Isolated messages, must be self-explanatory. */
- case 0:
- puts_filtered ("During symbol reading, ");
- wrap_here("");
- printf_filtered (complaint->message, val);
- puts_filtered (".\n");
- break;
-
- /* First of a series, without `set verbose'. */
- case 1:
- puts_filtered ("During symbol reading...");
- printf_filtered (complaint->message, val);
- puts_filtered ("...");
- wrap_here("");
- complaint_series++;
- break;
-
- /* Subsequent messages of a series, or messages under `set verbose'.
- (We'll already have produced a "Reading in symbols for XXX..." message
- and will clean up at the end with a newline.) */
- default:
- printf_filtered (complaint->message, val);
- puts_filtered ("...");
- wrap_here("");
- }
-}
-
-/* Clear out all complaint counters that have ever been incremented.
- If sym_reading is 1, be less verbose about successive complaints,
- since the messages are appearing all together during a command that
- reads symbols (rather than scattered around as psymtabs get fleshed
- out into symtabs at random times). If noisy is 1, we are in a
- noisy symbol reading command, and our caller will print enough
- context for the user to figure it out. */
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
-void
-clear_complaints (sym_reading, noisy)
- int sym_reading;
- int noisy;
-{
- struct complaint *p;
+ reinit_frame_cache ();
- for (p = complaint_root->next; p != complaint_root; p = p->next)
- p->counter = 0;
+ /* Discard cleanups as symbol reading was successful. */
+ discard_cleanups (old_cleanups);
- if (!sym_reading && !noisy && complaint_series > 1) {
- /* Terminate previous series, since caller won't. */
- puts_filtered ("\n");
+ /* 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;
+ }
+ }
}
- complaint_series = sym_reading? 1 + noisy: 0;
+ if (reread_one)
+ clear_symtab_users ();
}
+
\f
enum language
deduce_language_from_filename (filename)
char *filename;
{
- char *c = strrchr (filename, '.');
+ char *c;
- if (!c) ; /* Get default. */
- else if(!strcmp(c,".mod"))
- return language_m2;
- else if(!strcmp(c,".c"))
- return language_c;
- else if(!strcmp(c,".cc") || !strcmp(c,".C"))
- return language_cplus;
+ 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"))
+ 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 */
}
symtab = (struct symtab *)
obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symtab));
- (void) memset (symtab, 0, sizeof (*symtab));
+ memset (symtab, 0, sizeof (*symtab));
symtab -> filename = obsavestring (filename, strlen (filename),
&objfile -> symbol_obstack);
symtab -> fullname = NULL;
obstack_alloc (&objfile -> psymbol_obstack,
sizeof (struct partial_symtab));
- (void) memset (psymtab, 0, sizeof (struct partial_symtab));
+ memset (psymtab, 0, sizeof (struct partial_symtab));
psymtab -> filename = obsavestring (filename, strlen (filename),
&objfile -> psymbol_obstack);
psymtab -> symtab = NULL;
}
\f
+/* 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 ();
+}
+
/* clear_symtab_users_once:
This function is run after symbol reading, or from a cleanup.
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;
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. */
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 */
free_named_symtabs (name)
char *name;
{
- register struct symtab *s;
- register struct symtab *prev;
- register struct partial_symtab *ps;
- struct blockvector *bv;
- int blewit = 0;
-
#if 0
/* FIXME: With the new method of each objfile having it's own
psymtab list, this function needs serious rethinking. In particular,
why was it ever necessary to toss psymtabs with specific compilation
unit filenames, as opposed to all psymtabs from a particular symbol
- file. */
+ file? -- fnf
+ Well, the answer is that some systems permit reloading of particular
+ compilation units. We want to blow away any old info about these
+ compilation units, regardless of which objfiles they arrived in. --gnu. */
+
+ register struct symtab *s;
+ register struct symtab *prev;
+ register struct partial_symtab *ps;
+ struct blockvector *bv;
+ int blewit = 0;
/* We only wack things if the symbol-reload switch is set. */
if (!symbol_reloading)
again2:
for (ps = partial_symtab_list; ps; ps = ps->next) {
- if (!strcmp (name, ps->filename)) {
+ if (STREQ (name, ps->filename)) {
cashier_psymtab (ps); /* Blow it away...and its little dog, too. */
goto again2; /* Must restart, chain has been munged */
}
for (s = symtab_list; s; s = s->next)
{
- if (!strcmp (name, s->filename))
+ if (STREQ (name, s->filename))
break;
prev = s;
}
struct partial_symtab *
-start_psymtab_common (objfile, addr,
+start_psymtab_common (objfile, section_offsets,
filename, textlow, global_syms, static_syms)
struct objfile *objfile;
- CORE_ADDR addr;
+ struct section_offsets *section_offsets;
char *filename;
CORE_ADDR textlow;
struct partial_symbol *global_syms;
struct partial_symtab *psymtab;
psymtab = allocate_psymtab (filename, objfile);
- psymtab -> addr = addr;
+ psymtab -> section_offsets = section_offsets;
psymtab -> textlow = textlow;
psymtab -> texthigh = psymtab -> textlow; /* default */
psymtab -> globals_offset = global_syms - objfile -> global_psymbols.list;
psymtab -> statics_offset = static_syms - objfile -> static_psymbols.list;
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)
+ char *name;
+ int namelength;
+ enum namespace namespace;
+ enum address_class class;
+ struct psymbol_allocation_list *list;
+ long val;
+ enum language language;
+ struct objfile *objfile;
+{
+ register struct partial_symbol *psym;
+ register char *demangled_name;
+
+ if (list->next >= list->list + list->size)
+ {
+ 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_LANGUAGE_SPECIFIC (psym, language);
+}
+
+/* Add a symbol with a CORE_ADDR value to a psymtab. */
+
+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;
+ struct objfile *objfile;
+{
+ register struct partial_symbol *psym;
+ register char *demangled_name;
+
+ if (list->next >= list->list + list->size)
+ {
+ 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_ADDRESS (psym) = val;
+ SYMBOL_LANGUAGE (psym) = language;
+ PSYMBOL_NAMESPACE (psym) = namespace;
+ PSYMBOL_CLASS (psym) = class;
+ SYMBOL_INIT_LANGUAGE_SPECIFIC (psym, language);
+}
+
+#endif /* !INLINE_ADD_PSYMBOL */
\f
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.");
-
- add_show_from_set
- (add_set_cmd ("complaints", class_support, var_zinteger,
- (char *)&stop_whining,
- "Set max number of complaints about incorrect symbols.",
- &setlist),
- &showlist);
+for access from GDB.", &cmdlist);
+ c->completer = filename_completer;
add_show_from_set
(add_set_cmd ("symbol-reloading", class_support, var_boolean,