*/
#include "defs.h"
-#include <varargs.h>
-#include <fcntl.h>
-#include <string.h>
-
#include "bfd.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "buildsym.h"
#include "demangle.h"
+#include <varargs.h>
+#include <fcntl.h>
+#include <string.h>
+#ifndef NO_SYS_FILE
+#include <sys/file.h>
+#endif
+
+/* FIXME -- convert this to SEEK_SET a la POSIX, move to config files. */
+#ifndef L_SET
+#define L_SET 0
+#endif
+
#ifdef MAINTENANCE /* Define to 1 to compile in some maintenance stuff */
#define SQUAWK(stuff) dwarfwarn stuff
#else
static struct dieinfo *curdie; /* For warnings and such */
static char *dbbase; /* Base pointer to dwarf info */
+static int dbsize; /* Size of dwarf info in bytes */
static int dbroff; /* Relative offset from start of .debug section */
static char *lnbase; /* Base pointer to line section */
static int isreg; /* Kludge to identify register variables */
*/
struct dwfinfo {
- int dbfoff; /* Absolute file offset to start of .debug section */
+ file_ptr dbfoff; /* Absolute file offset to start of .debug section */
int dbroff; /* Relative offset from start of .debug section */
int dblength; /* Size of the chunk of DIE's being examined */
- int lnfoff; /* Absolute file offset to line table fragment */
+ file_ptr lnfoff; /* Absolute file offset to line table fragment */
};
#define DBFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbfoff)
static struct type **utypes; /* Pointer to array of user type pointers */
static int numutypes; /* Max number of user type pointers */
+/* Record the language for the compilation unit which is currently being
+ processed. We know it once we have seen the TAG_compile_unit DIE,
+ and we need it while processing the DIE's for that compilation unit.
+ It is eventually saved in the symtab structure, but we don't finalize
+ the symtab struct until we have processed all the DIE's for the
+ compilation unit. */
+
+static enum language cu_language;
+
/* Forward declarations of static functions so we don't have to worry
about ordering within this file. */
scan_partial_symbols PARAMS ((char *, char *, struct objfile *));
static void
-scan_compilation_units PARAMS ((char *, char *, char *, unsigned int,
- unsigned int, struct objfile *));
+scan_compilation_units PARAMS ((char *, char *, file_ptr,
+ file_ptr, struct objfile *));
static void
add_partial_symbol PARAMS ((struct dieinfo *, struct objfile *));
static struct symbol *
new_symbol PARAMS ((struct dieinfo *, struct objfile *));
+static void
+synthesize_typedef PARAMS ((struct dieinfo *, struct objfile *,
+ struct type *));
+
static int
locval PARAMS ((char *));
record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type,
struct objfile *));
+static void
+set_cu_language PARAMS ((struct dieinfo *));
+
+/*
+
+LOCAL FUNCTION
+
+ set_cu_language -- set local copy of language for compilation unit
+
+SYNOPSIS
+
+ void
+ set_cu_language (struct dieinfo *dip)
+
+DESCRIPTION
+
+ Decode the language attribute for a compilation unit DIE and
+ remember what the language was. We use this at various times
+ when processing DIE's for a given compilation unit.
+
+RETURNS
+
+ No return value.
+
+ */
+
+static void
+set_cu_language (dip)
+ struct dieinfo *dip;
+{
+ switch (dip -> at_language)
+ {
+ case LANG_C89:
+ case LANG_C:
+ cu_language = language_c;
+ break;
+ case LANG_C_PLUS_PLUS:
+ cu_language = language_cplus;
+ break;
+ case LANG_ADA83:
+ case LANG_COBOL74:
+ case LANG_COBOL85:
+ case LANG_FORTRAN77:
+ case LANG_FORTRAN90:
+ case LANG_PASCAL83:
+ case LANG_MODULA2:
+ default:
+ cu_language = language_unknown;
+ break;
+ }
+}
+
/*
GLOBAL FUNCTION
SYNOPSIS
- void dwarf_build_psymtabs (int desc, char *filename,
+ void dwarf_build_psymtabs (struct objfile *objfile,
struct section_offsets *section_offsets,
- int mainline, unsigned int dbfoff, unsigned int dbsize,
- unsigned int lnoffset, unsigned int lnsize,
- struct objfile *objfile)
+ int mainline, file_ptr dbfoff, unsigned int dbfsize,
+ file_ptr lnoffset, unsigned int lnsize)
DESCRIPTION
This function is called upon to build partial symtabs from files
containing DIE's (Dwarf Information Entries) and DWARF line numbers.
- It is passed a file descriptor for an open file containing the DIES
+ It is passed a bfd* containing the DIES
and line number information, the corresponding filename for that
file, a base address for relocating the symbols, a flag indicating
whether or not this debugging information is from a "main symbol
*/
void
-dwarf_build_psymtabs (desc, filename, section_offsets, mainline, dbfoff, dbsize,
- lnoffset, lnsize, objfile)
- int desc;
- char *filename;
+dwarf_build_psymtabs (objfile, section_offsets, mainline, dbfoff, dbfsize,
+ lnoffset, lnsize)
+ struct objfile *objfile;
struct section_offsets *section_offsets;
int mainline;
- unsigned int dbfoff;
- unsigned int dbsize;
- unsigned int lnoffset;
+ file_ptr dbfoff;
+ unsigned int dbfsize;
+ file_ptr lnoffset;
unsigned int lnsize;
- struct objfile *objfile;
{
+ bfd *abfd = objfile->obfd;
struct cleanup *back_to;
current_objfile = objfile;
+ dbsize = dbfsize;
dbbase = xmalloc (dbsize);
dbroff = 0;
- if ((lseek (desc, dbfoff, 0) != dbfoff) ||
- (read (desc, dbbase, dbsize) != dbsize))
+ if ((bfd_seek (abfd, dbfoff, L_SET) != 0) ||
+ (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
{
free (dbbase);
- error ("can't read DWARF data from '%s'", filename);
+ error ("can't read DWARF data from '%s'", bfd_get_filename (abfd));
}
back_to = make_cleanup (free, dbbase);
table entry for each one. Save enough information about each compilation
unit to locate the full DWARF information later. */
- scan_compilation_units (filename, dbbase, dbbase + dbsize,
- dbfoff, lnoffset, objfile);
+ scan_compilation_units (dbbase, dbbase + dbsize, dbfoff, lnoffset, objfile);
do_cleanups (back_to);
current_objfile = NULL;
INIT_CPLUS_SPECIFIC(type);
switch (dip -> die_tag)
{
+ case TAG_class_type:
+ TYPE_CODE (type) = TYPE_CODE_CLASS;
+ tpart1 = "class";
+ break;
case TAG_structure_type:
TYPE_CODE (type) = TYPE_CODE_STRUCT;
tpart1 = "struct";
/* Should never happen */
TYPE_CODE (type) = TYPE_CODE_UNDEF;
tpart1 = "???";
- SQUAWK (("missing structure or union tag"));
+ SQUAWK (("missing class, structure, or union tag"));
break;
}
/* Some compilers try to be helpful by inventing "fake" names for
{
TYPE_NFIELDS (type) = nfields;
TYPE_FIELDS (type) = (struct field *)
- obstack_alloc (&objfile -> type_obstack,
- sizeof (struct field) * nfields);
+ TYPE_ALLOC (type, sizeof (struct field) * nfields);
/* Copy the saved-up fields into the field vector. */
for (n = nfields; list; list = list -> next)
{
type = struct_type (dip, thisdie, enddie, objfile);
if (!(TYPE_FLAGS (type) & TYPE_FLAG_STUB))
{
- if ((sym = new_symbol (dip, objfile)) != NULL)
+ sym = new_symbol (dip, objfile);
+ if (sym != NULL)
{
SYMBOL_TYPE (sym) = type;
+ if (cu_language == language_cplus)
+ {
+ synthesize_typedef (dip, objfile, type);
+ }
}
}
}
struct symbol *sym;
type = enum_type (dip, objfile);
- if ((sym = new_symbol (dip, objfile)) != NULL)
+ sym = new_symbol (dip, objfile);
+ if (sym != NULL)
{
SYMBOL_TYPE (sym) = type;
+ if (cu_language == language_cplus)
+ {
+ synthesize_typedef (dip, objfile, type);
+ }
}
}
objfile -> ei.entry_file_lowpc = dip -> at_low_pc;
objfile -> ei.entry_file_highpc = dip -> at_high_pc;
}
+ set_cu_language (dip);
if (dip -> at_producer != NULL)
{
handle_producer (dip -> at_producer);
symtab = end_symtab (dip -> at_high_pc, 0, 0, objfile);
if (symtab != NULL)
{
- /* FIXME: The following may need to be expanded for other languages */
- switch (dip -> at_language)
- {
- case LANG_C89:
- case LANG_C:
- symtab -> language = language_c;
- break;
- case LANG_C_PLUS_PLUS:
- symtab -> language = language_cplus;
- break;
- default:
- ;
- }
+ symtab -> language = cu_language;
}
do_cleanups (back_to);
utypes = NULL;
case TAG_lexical_block:
read_lexical_block_scope (&di, thisdie, nextdie, objfile);
break;
+ case TAG_class_type:
case TAG_structure_type:
case TAG_union_type:
read_structure_scope (&di, thisdie, nextdie, objfile);
{
struct cleanup *back_to;
unsigned long lnsize;
- int foffset;
+ file_ptr foffset;
bfd *abfd;
char lnsizedata[SIZEOF_LINETBL_LENGTH];
unit, seek to the location in the file, and read in all the DIE's. */
diecount = 0;
- dbbase = xmalloc (DBLENGTH(pst));
+ dbsize = DBLENGTH (pst);
+ dbbase = xmalloc (dbsize);
dbroff = DBROFF(pst);
foffset = DBFOFF(pst) + dbroff;
base_section_offsets = pst->section_offsets;
baseaddr = ANOFFSET (pst->section_offsets, 0);
- if (bfd_seek (abfd, foffset, 0) ||
- (bfd_read (dbbase, DBLENGTH(pst), 1, abfd) != DBLENGTH(pst)))
+ if (bfd_seek (abfd, foffset, L_SET) ||
+ (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
{
free (dbbase);
error ("can't read DWARF data");
lnbase = NULL;
if (LNFOFF (pst))
{
- if (bfd_seek (abfd, LNFOFF (pst), 0) ||
+ if (bfd_seek (abfd, LNFOFF (pst), L_SET) ||
(bfd_read ((PTR) lnsizedata, sizeof (lnsizedata), 1, abfd) !=
sizeof (lnsizedata)))
{
lnsize = target_to_host (lnsizedata, SIZEOF_LINETBL_LENGTH,
GET_UNSIGNED, pst -> objfile);
lnbase = xmalloc (lnsize);
- if (bfd_seek (abfd, LNFOFF (pst), 0) ||
+ if (bfd_seek (abfd, LNFOFF (pst), L_SET) ||
(bfd_read (lnbase, lnsize, 1, abfd) != lnsize))
{
free (lnbase);
make_cleanup (free, lnbase);
}
- process_dies (dbbase, dbbase + DBLENGTH(pst), pst -> objfile);
+ process_dies (dbbase, dbbase + dbsize, pst -> objfile);
do_cleanups (back_to);
current_objfile = NULL;
return (pst -> objfile -> symtabs);
add to a partial symbol table, finish filling in the die info
and then add a partial symbol table entry for it.
+NOTES
+
+ The caller must ensure that the DIE has a valid name attribute.
*/
static void
objfile -> static_psymbols,
0);
break;
+ case TAG_class_type:
case TAG_structure_type:
case TAG_union_type:
+ case TAG_enumeration_type:
ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
STRUCT_NAMESPACE, LOC_TYPEDEF,
objfile -> static_psymbols,
0);
- break;
- case TAG_enumeration_type:
- if (dip -> at_name)
+ if (cu_language == language_cplus)
{
+ /* For C++, these implicitly act as typedefs as well. */
ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
- STRUCT_NAMESPACE, LOC_TYPEDEF,
+ VAR_NAMESPACE, LOC_TYPEDEF,
objfile -> static_psymbols,
0);
}
- add_enum_psymbol (dip, objfile);
break;
}
}
}
break;
case TAG_typedef:
+ case TAG_class_type:
case TAG_structure_type:
case TAG_union_type:
completedieinfo (&di, objfile);
break;
case TAG_enumeration_type:
completedieinfo (&di, objfile);
- add_partial_symbol (&di, objfile);
+ if (di.at_name)
+ {
+ add_partial_symbol (&di, objfile);
+ }
+ add_enum_psymbol (&di, objfile);
break;
}
}
*/
static void
-scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
- char *filename;
+scan_compilation_units (thisdie, enddie, dbfoff, lnoffset, objfile)
char *thisdie;
char *enddie;
- unsigned int dbfoff;
- unsigned int lnoffset;
+ file_ptr dbfoff;
+ file_ptr lnoffset;
struct objfile *objfile;
{
char *nextdie;
struct partial_symtab *pst;
int culength;
int curoff;
- int curlnoffset;
+ file_ptr curlnoffset;
while (thisdie < enddie)
{
else
{
completedieinfo (&di, objfile);
+ set_cu_language (&di);
if (di.at_sibling != 0)
{
nextdie = dbbase + di.at_sibling - dbroff;
/* First allocate a new partial symbol table structure */
- pst = start_psymtab_common (objfile, base_section_offsets, di.at_name,
- di.at_low_pc,
+ pst = start_psymtab_common (objfile, base_section_offsets,
+ di.at_name, di.at_low_pc,
objfile -> global_psymbols.next,
objfile -> static_psymbols.next);
sym = (struct symbol *) obstack_alloc (&objfile -> symbol_obstack,
sizeof (struct symbol));
memset (sym, 0, sizeof (struct symbol));
- SYMBOL_NAME (sym) = create_name (dip -> at_name, &objfile->symbol_obstack);
+ SYMBOL_NAME (sym) = create_name (dip -> at_name,
+ &objfile->symbol_obstack);
/* default assumptions */
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
SYMBOL_CLASS (sym) = LOC_STATIC;
/* From varargs functions; gdb doesn't seem to have any interest in
this information, so just ignore it for now. (FIXME?) */
break;
+ case TAG_class_type:
case TAG_structure_type:
case TAG_union_type:
case TAG_enumeration_type:
/*
+LOCAL FUNCTION
+
+ synthesize_typedef -- make a symbol table entry for a "fake" typedef
+
+SYNOPSIS
+
+ static void synthesize_typedef (struct dieinfo *dip,
+ struct objfile *objfile,
+ struct type *type);
+
+DESCRIPTION
+
+ Given a pointer to a DWARF information entry, synthesize a typedef
+ for the name in the DIE, using the specified type.
+
+ This is used for C++ class, structs, unions, and enumerations to
+ set up the tag name as a type.
+
+ */
+
+static void
+synthesize_typedef (dip, objfile, type)
+ struct dieinfo *dip;
+ struct objfile *objfile;
+ struct type *type;
+{
+ struct symbol *sym = NULL;
+
+ if (dip -> at_name != NULL)
+ {
+ sym = (struct symbol *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = create_name (dip -> at_name,
+ &objfile->symbol_obstack);
+ SYMBOL_TYPE (sym) = type;
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, list_in_scope);
+ }
+}
+
+/*
+
LOCAL FUNCTION
decode_mod_fund_type -- decode a modified fundamental type
that if a padding DIE is used for alignment and the amount needed is
less than SIZEOF_DIE_LENGTH, then the padding DIE has to be big
enough to align to the next alignment boundry.
+
+ We do some basic sanity checking here, such as verifying that the
+ length of the die would not cause it to overrun the recorded end of
+ the buffer holding the DIE info. If we find a DIE that is either
+ too small or too large, we force it's length to zero which should
+ cause the caller to take appropriate action.
*/
static void
dip -> die_ref = dbroff + (diep - dbbase);
dip -> die_length = target_to_host (diep, SIZEOF_DIE_LENGTH, GET_UNSIGNED,
objfile);
- if (dip -> die_length < SIZEOF_DIE_LENGTH)
+ if ((dip -> die_length < SIZEOF_DIE_LENGTH) ||
+ ((diep + dip -> die_length) > (dbbase + dbsize)))
{
dwarfwarn ("malformed DIE, bad length (%d bytes)", dip -> die_length);
+ dip -> die_length = 0;
}
else if (dip -> die_length < (SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG))
{