X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fdwarfread.c;h=98ceb490bc6038d19ee84199f69817b8f1fd9023;hb=271fef259aa12777142e60b4d94ca24d0282d8d6;hp=2e522956866ffc560b92c7153ef7cfbefb34deca;hpb=2d6d969c616d286076df1778db0d06a64f11251a;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/dwarfread.c b/gdb/dwarfread.c index 2e52295686..98ceb490bc 100644 --- a/gdb/dwarfread.c +++ b/gdb/dwarfread.c @@ -1,5 +1,6 @@ /* DWARF debugging format support for GDB. - Copyright (C) 1991, 1992 Free Software Foundation, Inc. + Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996 + Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support. Portions based on dbxread.c, mipsread.c, coffread.c, and dwarfread.c from a Data General SVR4 gdb port. @@ -17,14 +18,12 @@ 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. */ /* -FIXME: Figure out how to get the frame pointer register number in the -execution environment of the target. Remove R_FP kludge - -FIXME: Add generation of dependencies list to partial symtab code. +FIXME: Do we need to generate dependencies in partial symtabs? +(Perhaps we don't need to). FIXME: Resolve minor differences between what information we put in the partial symbol table and what dbxread puts in. For example, we don't yet @@ -41,28 +40,136 @@ other things to work on, if you get bored. :-) */ #include "defs.h" -#include -#include -#include - -#include "bfd.h" #include "symtab.h" #include "gdbtypes.h" #include "symfile.h" #include "objfiles.h" -#include "libbfd.h" /* FIXME Secret Internal BFD stuff (bfd_read) */ #include "elf/dwarf.h" #include "buildsym.h" +#include "demangle.h" +#include "expression.h" /* Needed for enum exp_opcode in language.h, sigh... */ +#include "language.h" +#include "complaints.h" -#ifdef MAINTENANCE /* Define to 1 to compile in some maintenance stuff */ -#define SQUAWK(stuff) dwarfwarn stuff -#else -#define SQUAWK(stuff) -#endif +#include +#include "gdb_string.h" -#ifndef R_FP /* FIXME */ -#define R_FP 14 /* Kludge to get frame pointer register number */ -#endif +/* Some macros to provide DIE info for complaints. */ + +#define DIE_ID (curdie!=NULL ? curdie->die_ref : 0) +#define DIE_NAME (curdie!=NULL && curdie->at_name!=NULL) ? curdie->at_name : "" + +/* Complaints that can be issued during DWARF debug info reading. */ + +struct complaint no_bfd_get_N = +{ + "DIE @ 0x%x \"%s\", no bfd support for %d byte data object", 0, 0 +}; + +struct complaint malformed_die = +{ + "DIE @ 0x%x \"%s\", malformed DIE, bad length (%d bytes)", 0, 0 +}; + +struct complaint bad_die_ref = +{ + "DIE @ 0x%x \"%s\", reference to DIE (0x%x) outside compilation unit", 0, 0 +}; + +struct complaint unknown_attribute_form = +{ + "DIE @ 0x%x \"%s\", unknown attribute form (0x%x)", 0, 0 +}; + +struct complaint unknown_attribute_length = +{ + "DIE @ 0x%x \"%s\", unknown attribute length, skipped remaining attributes", 0, 0 +}; + +struct complaint unexpected_fund_type = +{ + "DIE @ 0x%x \"%s\", unexpected fundamental type 0x%x", 0, 0 +}; + +struct complaint unknown_type_modifier = +{ + "DIE @ 0x%x \"%s\", unknown type modifier %u", 0, 0 +}; + +struct complaint volatile_ignored = +{ + "DIE @ 0x%x \"%s\", type modifier 'volatile' ignored", 0, 0 +}; + +struct complaint const_ignored = +{ + "DIE @ 0x%x \"%s\", type modifier 'const' ignored", 0, 0 +}; + +struct complaint botched_modified_type = +{ + "DIE @ 0x%x \"%s\", botched modified type decoding (mtype 0x%x)", 0, 0 +}; + +struct complaint op_deref2 = +{ + "DIE @ 0x%x \"%s\", OP_DEREF2 address 0x%x not handled", 0, 0 +}; + +struct complaint op_deref4 = +{ + "DIE @ 0x%x \"%s\", OP_DEREF4 address 0x%x not handled", 0, 0 +}; + +struct complaint basereg_not_handled = +{ + "DIE @ 0x%x \"%s\", BASEREG %d not handled", 0, 0 +}; + +struct complaint dup_user_type_allocation = +{ + "DIE @ 0x%x \"%s\", internal error: duplicate user type allocation", 0, 0 +}; + +struct complaint dup_user_type_definition = +{ + "DIE @ 0x%x \"%s\", internal error: duplicate user type definition", 0, 0 +}; + +struct complaint missing_tag = +{ + "DIE @ 0x%x \"%s\", missing class, structure, or union tag", 0, 0 +}; + +struct complaint bad_array_element_type = +{ + "DIE @ 0x%x \"%s\", bad array element type attribute 0x%x", 0, 0 +}; + +struct complaint subscript_data_items = +{ + "DIE @ 0x%x \"%s\", can't decode subscript data items", 0, 0 +}; + +struct complaint unhandled_array_subscript_format = +{ + "DIE @ 0x%x \"%s\", array subscript format 0x%x not handled yet", 0, 0 +}; + +struct complaint unknown_array_subscript_format = +{ + "DIE @ 0x%x \"%s\", unknown array subscript format %x", 0, 0 +}; + +struct complaint not_row_major = +{ + "DIE @ 0x%x \"%s\", array not row major; not handled correctly", 0, 0 +}; + +struct complaint missing_at_name = +{ + "DIE @ 0x%x, AT_name tag missing", 0, 0 +}; typedef unsigned int DIE_REF; /* Reference to a DIE */ @@ -70,8 +177,22 @@ typedef unsigned int DIE_REF; /* Reference to a DIE */ #define GCC_PRODUCER "GNU C " #endif -#define STREQ(a,b) (strcmp(a,b)==0) -#define STREQN(a,b,n) (strncmp(a,b,n)==0) +#ifndef GPLUS_PRODUCER +#define GPLUS_PRODUCER "GNU C++ " +#endif + +#ifndef LCC_PRODUCER +#define LCC_PRODUCER "NCR C/C++" +#endif + +#ifndef CHILL_PRODUCER +#define CHILL_PRODUCER "GNU Chill " +#endif + +/* Provide a default mapping from a DWARF register number to a gdb REGNUM. */ +#ifndef DWARF_REG_TO_REGNUM +#define DWARF_REG_TO_REGNUM(num) (num) +#endif /* Flags to target_to_host() that tell whether or not the data object is expected to be signed. Used, for example, when fetching a signed @@ -176,24 +297,22 @@ struct dieinfo { unsigned long at_bit_size; BLOCK * at_element_list; unsigned long at_stmt_list; - unsigned long at_low_pc; - unsigned long at_high_pc; + CORE_ADDR at_low_pc; + CORE_ADDR at_high_pc; unsigned long at_language; unsigned long at_member; unsigned long at_discr; BLOCK * at_discr_value; - unsigned short at_visibility; - unsigned long at_import; BLOCK * at_string_length; char * at_comp_dir; char * at_producer; - unsigned long at_frame_base; unsigned long at_start_scope; unsigned long at_stride_size; unsigned long at_src_info; char * at_prototyped; unsigned int has_at_low_pc:1; unsigned int has_at_stmt_list:1; + unsigned int has_at_byte_size:1; unsigned int short_element_list:1; }; @@ -201,44 +320,49 @@ static int diecount; /* Approximate count of dies for compilation unit */ 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 */ -static int offreg; /* Kludge to identify basereg references */ - +static int optimized_out; /* Kludge to identify optimized out variables */ +/* Kludge to identify basereg references. Nonzero if we have an offset + relative to a basereg. */ +static int offreg; +/* Which base register is it relative to? */ +static int basereg; + +/* This value is added to each symbol value. FIXME: Generalize to + the section_offsets structure used by dbxread (once this is done, + pass the appropriate section number to end_symtab). */ static CORE_ADDR baseaddr; /* Add to each symbol value */ -/* Each partial symbol table entry contains a pointer to private data for the - read_symtab() function to use when expanding a partial symbol table entry - to a full symbol table entry. For DWARF debugging info, this data is - contained in the following structure and macros are provided for easy - access to the members given a pointer to a partial symbol table entry. - - dbfoff Always the absolute file offset to the start of the ".debug" - section for the file containing the DIE's being accessed. - - dbroff Relative offset from the start of the ".debug" access to the - first DIE to be accessed. When building the partial symbol - table, this value will be zero since we are accessing the - entire ".debug" section. When expanding a partial symbol - table entry, this value will be the offset to the first - DIE for the compilation unit containing the symbol that - triggers the expansion. - - dblength The size of the chunk of DIE's being examined, in bytes. - - lnfoff The absolute file offset to the line table fragment. Ignored - when building partial symbol tables, but used when expanding - them, and contains the absolute file offset to the fragment - of the ".line" section containing the line numbers for the - current compilation unit. - */ +/* The section offsets used in the current psymtab or symtab. FIXME, + only used to pass one value (baseaddr) at the moment. */ +static struct section_offsets *base_section_offsets; + +/* We put a pointer to this structure in the read_symtab_private field + of the psymtab. */ struct dwfinfo { - int 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 */ + /* Always the absolute file offset to the start of the ".debug" + section for the file containing the DIE's being accessed. */ + file_ptr dbfoff; + /* Relative offset from the start of the ".debug" section to the + first DIE to be accessed. When building the partial symbol + table, this value will be zero since we are accessing the + entire ".debug" section. When expanding a partial symbol + table entry, this value will be the offset to the first + DIE for the compilation unit containing the symbol that + triggers the expansion. */ + int dbroff; + /* The size of the chunk of DIE's being examined, in bytes. */ + int dblength; + /* The absolute file offset to the line table fragment. Ignored + when building partial symbol tables, but used when expanding + them, and contains the absolute file offset to the fragment + of the ".line" section containing the line numbers for the + current compilation unit. */ + file_ptr lnfoff; }; #define DBFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbfoff) @@ -278,23 +402,57 @@ struct pending **list_in_scope = &file_symbols; we can divide any DIE offset by 4 to obtain a unique index into this fixed size array. Since each element is a 4 byte pointer, it takes exactly as much memory to hold this array as to hold the DWARF info for a given - compilation unit. But it gets freed as soon as we are done with it. */ + compilation unit. But it gets freed as soon as we are done with it. + This has worked well in practice, as a reasonable tradeoff between memory + consumption and speed, without having to resort to much more complicated + algorithms. */ static struct type **utypes; /* Pointer to array of user type pointers */ static int numutypes; /* Max number of user type pointers */ +/* Maintain an array of referenced fundamental types for the current + compilation unit being read. For DWARF version 1, we have to construct + the fundamental types on the fly, since no information about the + fundamental types is supplied. Each such fundamental type is created by + calling a language dependent routine to create the type, and then a + pointer to that type is then placed in the array at the index specified + by it's FT_ value. The array has a fixed size set by the + FT_NUM_MEMBERS compile time constant, which is the number of predefined + fundamental types gdb knows how to construct. */ + +static struct type *ftypes[FT_NUM_MEMBERS]; /* Fundamental types */ + +/* 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. We also need to get and save a pointer to the + language struct for this language, so we can call the language + dependent routines for doing things such as creating fundamental + types. */ + +static enum language cu_language; +static const struct language_defn *cu_language_defn; + /* Forward declarations of static functions so we don't have to worry about ordering within this file. */ +static void +free_utypes PARAMS ((PTR)); + static int attribute_size PARAMS ((unsigned int)); -static unsigned long +static CORE_ADDR target_to_host PARAMS ((char *, int, int, struct objfile *)); static void add_enum_psymbol PARAMS ((struct dieinfo *, struct objfile *)); +static void +handle_producer PARAMS ((char *)); + static void read_file_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *)); @@ -305,22 +463,16 @@ static void read_lexical_block_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *)); -static void -dwarfwarn (); - static void 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 void -init_psymbol_list PARAMS ((struct objfile *, int)); - static void basicdieinfo PARAMS ((struct dieinfo *, char *, struct objfile *)); @@ -333,7 +485,7 @@ dwarf_psymtab_to_symtab PARAMS ((struct partial_symtab *)); static void psymtab_to_symtab_1 PARAMS ((struct partial_symtab *)); -static struct symtab * +static void read_ofile_symtab PARAMS ((struct partial_symtab *)); static void @@ -347,7 +499,7 @@ static struct type * decode_array_element_type PARAMS ((char *)); static struct type * -decode_subscr_data PARAMS ((char *, char *)); +decode_subscript_data_item PARAMS ((char *, char *)); static void dwarf_read_array_type PARAMS ((struct dieinfo *)); @@ -355,6 +507,9 @@ dwarf_read_array_type PARAMS ((struct dieinfo *)); static void read_tag_pointer_type PARAMS ((struct dieinfo *dip)); +static void +read_tag_string_type PARAMS ((struct dieinfo *dip)); + static void read_subroutine_type PARAMS ((struct dieinfo *, char *, char *)); @@ -380,7 +535,7 @@ static struct type * decode_mod_u_d_type PARAMS ((char *)); static struct type * -decode_modified_type PARAMS ((unsigned char *, unsigned int, int)); +decode_modified_type PARAMS ((char *, unsigned int, int)); static struct type * decode_fund_type PARAMS ((unsigned int)); @@ -397,12 +552,134 @@ alloc_utype PARAMS ((DIE_REF, struct type *)); 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 *)); static void -record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type, - struct objfile *)); +set_cu_language PARAMS ((struct dieinfo *)); + +static struct type * +dwarf_fundamental_type PARAMS ((struct objfile *, int)); + + +/* + +LOCAL FUNCTION + + dwarf_fundamental_type -- lookup or create a fundamental type + +SYNOPSIS + + struct type * + dwarf_fundamental_type (struct objfile *objfile, int typeid) + +DESCRIPTION + + DWARF version 1 doesn't supply any fundamental type information, + so gdb has to construct such types. It has a fixed number of + fundamental types that it knows how to construct, which is the + union of all types that it knows how to construct for all languages + that it knows about. These are enumerated in gdbtypes.h. + + As an example, assume we find a DIE that references a DWARF + fundamental type of FT_integer. We first look in the ftypes + array to see if we already have such a type, indexed by the + gdb internal value of FT_INTEGER. If so, we simply return a + pointer to that type. If not, then we ask an appropriate + language dependent routine to create a type FT_INTEGER, using + defaults reasonable for the current target machine, and install + that type in ftypes for future reference. + +RETURNS + + Pointer to a fundamental type. + +*/ + +static struct type * +dwarf_fundamental_type (objfile, typeid) + struct objfile *objfile; + int typeid; +{ + if (typeid < 0 || typeid >= FT_NUM_MEMBERS) + { + error ("internal error - invalid fundamental type id %d", typeid); + } + + /* Look for this particular type in the fundamental type vector. If one is + not found, create and install one appropriate for the current language + and the current target machine. */ + + if (ftypes[typeid] == NULL) + { + ftypes[typeid] = cu_language_defn -> la_fund_type(objfile, typeid); + } + + return (ftypes[typeid]); +} + +/* + +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_CHILL: + cu_language = language_chill; + break; + case LANG_MODULA2: + cu_language = language_m2; + break; + case LANG_ADA83: + case LANG_COBOL74: + case LANG_COBOL85: + case LANG_FORTRAN77: + case LANG_FORTRAN90: + case LANG_PASCAL83: + /* We don't know anything special about these yet. */ + cu_language = language_unknown; + break; + default: + /* If no at_language, try to deduce one from the filename */ + cu_language = deduce_language_from_filename (dip -> at_name); + break; + } + cu_language_defn = language_def (cu_language); +} /* @@ -412,17 +689,17 @@ GLOBAL FUNCTION SYNOPSIS - void dwarf_build_psymtabs (int desc, char *filename, CORE_ADDR addr, - int mainline, unsigned int dbfoff, unsigned int dbsize, - unsigned int lnoffset, unsigned int lnsize, - struct objfile *objfile) + void dwarf_build_psymtabs (struct objfile *objfile, + struct section_offsets *section_offsets, + 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 @@ -437,28 +714,28 @@ RETURNS */ void -dwarf_build_psymtabs (desc, filename, addr, mainline, dbfoff, dbsize, - lnoffset, lnsize, objfile) - int desc; - char *filename; - CORE_ADDR addr; +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, SEEK_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); @@ -474,101 +751,19 @@ dwarf_build_psymtabs (desc, filename, addr, mainline, dbfoff, dbsize, /* Save the relocation factor where everybody can see it. */ - baseaddr = addr; + base_section_offsets = section_offsets; + baseaddr = ANOFFSET (section_offsets, 0); /* Follow the compilation unit sibling chain, building a partial symbol 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; } - -/* - -LOCAL FUNCTION - - record_minimal_symbol -- add entry to gdb's minimal symbol table - -SYNOPSIS - - static void record_minimal_symbol (char *name, CORE_ADDR address, - enum minimal_symbol_type ms_type, - struct objfile *objfile) - -DESCRIPTION - - Given a pointer to the name of a symbol that should be added to the - minimal symbol table, and the address associated with that - symbol, records this information for later use in building the - minimal symbol table. - - */ - -static void -record_minimal_symbol (name, address, ms_type, objfile) - char *name; - CORE_ADDR address; - enum minimal_symbol_type ms_type; - struct objfile *objfile; -{ - name = obsavestring (name, strlen (name), &objfile -> symbol_obstack); - prim_record_minimal_symbol (name, address, ms_type); -} - -/* - -LOCAL FUNCTION - - dwarfwarn -- issue a DWARF related warning - -DESCRIPTION - - Issue warnings about DWARF related things that aren't serious enough - to warrant aborting with an error, but should not be ignored either. - This includes things like detectable corruption in DIE's, missing - DIE's, unimplemented features, etc. - - In general, running across tags or attributes that we don't recognize - is not considered to be a problem and we should not issue warnings - about such. - -NOTES - - We mostly follow the example of the error() routine, but without - returning to command level. It is arguable about whether warnings - should be issued at all, and if so, where they should go (stdout or - stderr). - - We assume that curdie is valid and contains at least the basic - information for the DIE where the problem was noticed. -*/ - -static void -dwarfwarn (va_alist) - va_dcl -{ - va_list ap; - char *fmt; - - va_start (ap); - fmt = va_arg (ap, char *); - warning_setup (); - fprintf (stderr, "warning: DWARF ref 0x%x: ", curdie -> die_ref); - if (curdie -> at_name) - { - fprintf (stderr, "'%s': ", curdie -> at_name); - } - vfprintf (stderr, fmt, ap); - fprintf (stderr, "\n"); - fflush (stderr); - va_end (ap); -} - /* LOCAL FUNCTION @@ -596,7 +791,7 @@ read_lexical_block_scope (dip, thisdie, enddie, objfile) { register struct context_stack *new; - (void) push_context (0, dip -> at_low_pc); + push_context (0, dip -> at_low_pc); process_dies (thisdie + dip -> die_length, enddie, objfile); new = pop_context (); if (local_symbols != NULL) @@ -636,7 +831,7 @@ lookup_utype (die_ref) utypeidx = (die_ref - dbroff) / 4; if ((utypeidx < 0) || (utypeidx >= numutypes)) { - dwarfwarn ("reference to DIE (0x%x) outside compilation unit", die_ref); + complain (&bad_die_ref, DIE_ID, DIE_NAME); } else { @@ -679,29 +874,52 @@ alloc_utype (die_ref, utypep) typep = utypes + utypeidx; if ((utypeidx < 0) || (utypeidx >= numutypes)) { - utypep = lookup_fundamental_type (current_objfile, FT_INTEGER); - dwarfwarn ("reference to DIE (0x%x) outside compilation unit", die_ref); + utypep = dwarf_fundamental_type (current_objfile, FT_INTEGER); + complain (&bad_die_ref, DIE_ID, DIE_NAME); } else if (*typep != NULL) { utypep = *typep; - SQUAWK (("internal error: dup user type allocation")); + complain (&dup_user_type_allocation, DIE_ID, DIE_NAME); } else { if (utypep == NULL) { - utypep = (struct type *) - obstack_alloc (¤t_objfile -> type_obstack, - sizeof (struct type)); - (void) memset (utypep, 0, sizeof (struct type)); - TYPE_OBJFILE (utypep) = current_objfile; + utypep = alloc_type (current_objfile); } *typep = utypep; } return (utypep); } +/* + +LOCAL FUNCTION + + free_utypes -- free the utypes array and reset pointer & count + +SYNOPSIS + + static void free_utypes (PTR dummy) + +DESCRIPTION + + Called via do_cleanups to free the utypes array, reset the pointer to NULL, + and set numutypes back to zero. This ensures that the utypes does not get + referenced after being freed. + */ + +static void +free_utypes (dummy) + PTR dummy; +{ + free (utypes); + utypes = NULL; + numutypes = 0; +} + + /* LOCAL FUNCTION @@ -746,7 +964,7 @@ decode_die_type (dip) } else { - type = lookup_fundamental_type (current_objfile, FT_INTEGER); + type = dwarf_fundamental_type (current_objfile, FT_INTEGER); } return (type); } @@ -787,9 +1005,9 @@ struct_type (dip, thisdie, enddie, objfile) struct nextfield *new; int nfields = 0; int n; - char *tpart1; struct dieinfo mbr; char *nextdie; + int anonymous_size; if ((type = lookup_utype (dip -> die_ref)) == NULL) { @@ -799,19 +1017,19 @@ struct_type (dip, thisdie, enddie, objfile) INIT_CPLUS_SPECIFIC(type); switch (dip -> die_tag) { + case TAG_class_type: + TYPE_CODE (type) = TYPE_CODE_CLASS; + break; case TAG_structure_type: TYPE_CODE (type) = TYPE_CODE_STRUCT; - tpart1 = "struct"; break; case TAG_union_type: TYPE_CODE (type) = TYPE_CODE_UNION; - tpart1 = "union"; break; default: /* Should never happen */ TYPE_CODE (type) = TYPE_CODE_UNDEF; - tpart1 = "???"; - SQUAWK (("missing structure or union tag")); + complain (&missing_tag, DIE_ID, DIE_NAME); break; } /* Some compilers try to be helpful by inventing "fake" names for @@ -821,13 +1039,15 @@ struct_type (dip, thisdie, enddie, objfile) && *dip -> at_name != '~' && *dip -> at_name != '.') { - TYPE_NAME (type) = obconcat (&objfile -> type_obstack, - tpart1, " ", dip -> at_name); - } - if (dip -> at_byte_size != 0) - { - TYPE_LENGTH (type) = dip -> at_byte_size; + TYPE_TAG_NAME (type) = obconcat (&objfile -> type_obstack, + "", "", dip -> at_name); } + /* Use whatever size is known. Zero is a valid size. We might however + wish to check has_at_byte_size to make sure that some byte size was + given explicitly, but DWARF doesn't specify that explicit sizes of + zero have to present, so complaining about missing sizes should + probably not be the default. */ + TYPE_LENGTH (type) = dip -> at_byte_size; thisdie += dip -> die_length; while (thisdie < enddie) { @@ -853,10 +1073,54 @@ struct_type (dip, thisdie, enddie, objfile) new -> next = list; list = new; /* Save the data. */ - list -> field.name = savestring (mbr.at_name, strlen (mbr.at_name)); + list -> field.name = + obsavestring (mbr.at_name, strlen (mbr.at_name), + &objfile -> type_obstack); list -> field.type = decode_die_type (&mbr); list -> field.bitpos = 8 * locval (mbr.at_location); - list -> field.bitsize = 0; + /* Handle bit fields. */ + list -> field.bitsize = mbr.at_bit_size; + if (BITS_BIG_ENDIAN) + { + /* For big endian bits, the at_bit_offset gives the + additional bit offset from the MSB of the containing + anonymous object to the MSB of the field. We don't + have to do anything special since we don't need to + know the size of the anonymous object. */ + list -> field.bitpos += mbr.at_bit_offset; + } + else + { + /* For little endian bits, we need to have a non-zero + at_bit_size, so that we know we are in fact dealing + with a bitfield. Compute the bit offset to the MSB + of the anonymous object, subtract off the number of + bits from the MSB of the field to the MSB of the + object, and then subtract off the number of bits of + the field itself. The result is the bit offset of + the LSB of the field. */ + if (mbr.at_bit_size > 0) + { + if (mbr.has_at_byte_size) + { + /* The size of the anonymous object containing + the bit field is explicit, so use the + indicated size (in bytes). */ + anonymous_size = mbr.at_byte_size; + } + else + { + /* The size of the anonymous object containing + the bit field matches the size of an object + of the bit field's type. DWARF allows + at_byte_size to be left out in such cases, as + a debug information size optimization. */ + anonymous_size = TYPE_LENGTH (list -> field.type); + } + list -> field.bitpos += + anonymous_size * 8 - mbr.at_bit_offset - mbr.at_bit_size; + } + } nfields++; break; default: @@ -878,8 +1142,7 @@ struct_type (dip, thisdie, enddie, objfile) { 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) { @@ -936,9 +1199,14 @@ read_structure_scope (dip, thisdie, enddie, objfile) 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); + } } } } @@ -977,8 +1245,8 @@ decode_array_element_type (scan) scan += SIZEOF_ATTRIBUTE; if ((nbytes = attribute_size (attribute)) == -1) { - SQUAWK (("bad array element type attribute 0x%x", attribute)); - typep = lookup_fundamental_type (current_objfile, FT_INTEGER); + complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute); + typep = dwarf_fundamental_type (current_objfile, FT_INTEGER); } else { @@ -1004,8 +1272,8 @@ decode_array_element_type (scan) typep = decode_mod_u_d_type (scan); break; default: - SQUAWK (("bad array element type attribute 0x%x", attribute)); - typep = lookup_fundamental_type (current_objfile, FT_INTEGER); + complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute); + typep = dwarf_fundamental_type (current_objfile, FT_INTEGER); break; } } @@ -1016,11 +1284,12 @@ decode_array_element_type (scan) LOCAL FUNCTION - decode_subscr_data -- decode array subscript and element type data + decode_subscript_data_item -- decode array subscript item SYNOPSIS - static struct type *decode_subscr_data (char *scan, char *end) + static struct type * + decode_subscript_data_item (char *scan, char *end) DESCRIPTION @@ -1032,9 +1301,21 @@ DESCRIPTION source (I.E. leftmost dimension first, next to leftmost second, etc). + The data items describing each array dimension consist of four + parts: (1) a format specifier, (2) type type of the subscript + index, (3) a description of the low bound of the array dimension, + and (4) a description of the high bound of the array dimension. + + The last data item is the description of the type of each of + the array elements. + We are passed a pointer to the start of the block of bytes - containing the data items, and a pointer to the first byte past - the data. This function decodes the data and returns a type. + containing the remaining data items, and a pointer to the first + byte past the data. This function recursively decodes the + remaining data items and returns a type. + + If we somehow fail to decode some data, we complain about it + and return a type "array of int". BUGS FIXME: This code only implements the forms currently used @@ -1045,12 +1326,14 @@ BUGS */ static struct type * -decode_subscr_data (scan, end) +decode_subscript_data_item (scan, end) char *scan; char *end; { - struct type *typep = NULL; - struct type *nexttype; + struct type *typep = NULL; /* Array type we are building */ + struct type *nexttype; /* Type of each element (may be array) */ + struct type *indextype; /* Type of this index */ + struct type *rangetype; unsigned int format; unsigned short fundtype; unsigned long lowbound; @@ -1068,36 +1351,23 @@ decode_subscr_data (scan, end) case FMT_FT_C_C: fundtype = target_to_host (scan, SIZEOF_FMT_FT, GET_UNSIGNED, current_objfile); + indextype = decode_fund_type (fundtype); scan += SIZEOF_FMT_FT; - if (fundtype != FT_integer && fundtype != FT_signed_integer - && fundtype != FT_unsigned_integer) - { - SQUAWK (("array subscripts must be integral types, not type 0x%x", - fundtype)); - } - else + nbytes = TARGET_FT_LONG_SIZE (current_objfile); + lowbound = target_to_host (scan, nbytes, GET_UNSIGNED, current_objfile); + scan += nbytes; + highbound = target_to_host (scan, nbytes, GET_UNSIGNED, current_objfile); + scan += nbytes; + nexttype = decode_subscript_data_item (scan, end); + if (nexttype == NULL) { - nbytes = TARGET_FT_LONG_SIZE (current_objfile); - lowbound = target_to_host (scan, nbytes, GET_UNSIGNED, - current_objfile); - scan += nbytes; - highbound = target_to_host (scan, nbytes, GET_UNSIGNED, - current_objfile); - scan += nbytes; - nexttype = decode_subscr_data (scan, end); - if (nexttype != NULL) - { - typep = (struct type *) - obstack_alloc (¤t_objfile -> type_obstack, - sizeof (struct type)); - (void) memset (typep, 0, sizeof (struct type)); - TYPE_OBJFILE (typep) = current_objfile; - TYPE_CODE (typep) = TYPE_CODE_ARRAY; - TYPE_LENGTH (typep) = TYPE_LENGTH (nexttype); - TYPE_LENGTH (typep) *= lowbound + highbound + 1; - TYPE_TARGET_TYPE (typep) = nexttype; - } + /* Munged subscript data or other problem, fake it. */ + complain (&subscript_data_items, DIE_ID, DIE_NAME); + nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER); } + rangetype = create_range_type ((struct type *) NULL, indextype, + lowbound, highbound); + typep = create_array_type ((struct type *) NULL, nexttype, rangetype); break; case FMT_FT_C_X: case FMT_FT_X_C: @@ -1106,10 +1376,16 @@ decode_subscr_data (scan, end) case FMT_UT_C_X: case FMT_UT_X_C: case FMT_UT_X_X: - SQUAWK (("array subscript format 0x%x not handled yet", format)); + complain (&unhandled_array_subscript_format, DIE_ID, DIE_NAME, format); + nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER); + rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0); + typep = create_array_type ((struct type *) NULL, nexttype, rangetype); break; default: - SQUAWK (("unknown array subscript format %x", format)); + complain (&unknown_array_subscript_format, DIE_ID, DIE_NAME, format); + nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER); + rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0); + typep = create_array_type ((struct type *) NULL, nexttype, rangetype); break; } return (typep); @@ -1145,7 +1421,7 @@ dwarf_read_array_type (dip) if (dip -> at_ordering != ORD_row_major) { /* FIXME: Can gdb even handle column major arrays? */ - SQUAWK (("array not row major; not handled correctly")); + complain (¬_row_major, DIE_ID, DIE_NAME); } if ((sub = dip -> at_subscr_data) != NULL) { @@ -1153,30 +1429,29 @@ dwarf_read_array_type (dip) blocksz = target_to_host (sub, nbytes, GET_UNSIGNED, current_objfile); subend = sub + nbytes + blocksz; sub += nbytes; - type = decode_subscr_data (sub, subend); - if (type == NULL) + type = decode_subscript_data_item (sub, subend); + if ((utype = lookup_utype (dip -> die_ref)) == NULL) { - if ((utype = lookup_utype (dip -> die_ref)) == NULL) - { - utype = alloc_utype (dip -> die_ref, NULL); - } - TYPE_CODE (utype) = TYPE_CODE_ARRAY; - TYPE_TARGET_TYPE (utype) = - lookup_fundamental_type (current_objfile, FT_INTEGER); - TYPE_LENGTH (utype) = 1 * TYPE_LENGTH (TYPE_TARGET_TYPE (utype)); + /* Install user defined type that has not been referenced yet. */ + alloc_utype (dip -> die_ref, type); + } + else if (TYPE_CODE (utype) == TYPE_CODE_UNDEF) + { + /* Ick! A forward ref has already generated a blank type in our + slot, and this type probably already has things pointing to it + (which is what caused it to be created in the first place). + If it's just a place holder we can plop our fully defined type + on top of it. We can't recover the space allocated for our + new type since it might be on an obstack, but we could reuse + it if we kept a list of them, but it might not be worth it + (FIXME). */ + *utype = *type; } else { - if ((utype = lookup_utype (dip -> die_ref)) == NULL) - { - (void) alloc_utype (dip -> die_ref, type); - } - else - { - TYPE_CODE (utype) = TYPE_CODE_ARRAY; - TYPE_LENGTH (utype) = TYPE_LENGTH (type); - TYPE_TARGET_TYPE (utype) = TYPE_TARGET_TYPE (type); - } + /* Double ick! Not only is a type already in our slot, but + someone has decorated it. Complain and leave it alone. */ + complain (&dup_user_type_definition, DIE_ID, DIE_NAME); } } } @@ -1208,7 +1483,7 @@ read_tag_pointer_type (dip) if ((utype = lookup_utype (dip -> die_ref)) == NULL) { utype = lookup_pointer_type (type); - (void) alloc_utype (dip -> die_ref, utype); + alloc_utype (dip -> die_ref, utype); } else { @@ -1226,6 +1501,69 @@ read_tag_pointer_type (dip) /* +LOCAL FUNCTION + + read_tag_string_type -- read TAG_string_type DIE + +SYNOPSIS + + static void read_tag_string_type (struct dieinfo *dip) + +DESCRIPTION + + Extract all information from a TAG_string_type DIE and add to + the user defined type vector. It isn't really a user defined + type, but it behaves like one, with other DIE's using an + AT_user_def_type attribute to reference it. + */ + +static void +read_tag_string_type (dip) + struct dieinfo *dip; +{ + struct type *utype; + struct type *indextype; + struct type *rangetype; + unsigned long lowbound = 0; + unsigned long highbound; + + if (dip -> has_at_byte_size) + { + /* A fixed bounds string */ + highbound = dip -> at_byte_size - 1; + } + else + { + /* A varying length string. Stub for now. (FIXME) */ + highbound = 1; + } + indextype = dwarf_fundamental_type (current_objfile, FT_INTEGER); + rangetype = create_range_type ((struct type *) NULL, indextype, lowbound, + highbound); + + utype = lookup_utype (dip -> die_ref); + if (utype == NULL) + { + /* No type defined, go ahead and create a blank one to use. */ + utype = alloc_utype (dip -> die_ref, (struct type *) NULL); + } + else + { + /* Already a type in our slot due to a forward reference. Make sure it + is a blank one. If not, complain and leave it alone. */ + if (TYPE_CODE (utype) != TYPE_CODE_UNDEF) + { + complain (&dup_user_type_definition, DIE_ID, DIE_NAME); + return; + } + } + + /* Create the string type using the blank type we either found or created. */ + utype = create_string_type (utype, rangetype); +} + +/* + LOCAL FUNCTION read_subroutine_type -- process TAG_subroutine_type dies @@ -1272,17 +1610,20 @@ read_subroutine_type (dip, thisdie, enddie) /* This is the first reference to one of these types. Make a new one and place it in the user defined types. */ ftype = lookup_function_type (type); - (void) alloc_utype (dip -> die_ref, ftype); + alloc_utype (dip -> die_ref, ftype); } - else + else if (TYPE_CODE (ftype) == TYPE_CODE_UNDEF) { /* We have an existing partially constructed type, so bash it into the correct type. */ TYPE_TARGET_TYPE (ftype) = type; - TYPE_FUNCTION_TYPE (type) = ftype; TYPE_LENGTH (ftype) = 1; TYPE_CODE (ftype) = TYPE_CODE_FUNC; } + else + { + complain (&dup_user_type_definition, DIE_ID, DIE_NAME); + } } /* @@ -1319,9 +1660,14 @@ read_enumeration (dip, thisdie, enddie, objfile) 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); + } } } @@ -1375,6 +1721,7 @@ enum_type (dip, objfile) unsigned short blocksz; struct symbol *sym; int nbytes; + int unsigned_enum = 1; if ((type = lookup_utype (dip -> die_ref)) == NULL) { @@ -1389,8 +1736,8 @@ enum_type (dip, objfile) && *dip -> at_name != '~' && *dip -> at_name != '.') { - TYPE_NAME (type) = obconcat (&objfile -> type_obstack, "enum", - " ", dip -> at_name); + TYPE_TAG_NAME (type) = obconcat (&objfile -> type_obstack, + "", "", dip -> at_name); } if (dip -> at_byte_size != 0) { @@ -1420,28 +1767,34 @@ enum_type (dip, objfile) target_to_host (scan, TARGET_FT_LONG_SIZE (objfile), GET_SIGNED, objfile); scan += TARGET_FT_LONG_SIZE (objfile); - list -> field.name = savestring (scan, strlen (scan)); + list -> field.name = obsavestring (scan, strlen (scan), + &objfile -> type_obstack); scan += strlen (scan) + 1; nfields++; /* Handcraft a new symbol for this enum member. */ sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); - (void) memset (sym, 0, sizeof (struct symbol)); + memset (sym, 0, sizeof (struct symbol)); SYMBOL_NAME (sym) = create_name (list -> field.name, &objfile->symbol_obstack); + SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language); SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; SYMBOL_CLASS (sym) = LOC_CONST; SYMBOL_TYPE (sym) = type; SYMBOL_VALUE (sym) = list -> field.bitpos; + if (SYMBOL_VALUE (sym) < 0) + unsigned_enum = 0; add_symbol_to_list (sym, list_in_scope); } /* Now create the vector of fields, and record how big it is. This is - where we reverse the order, by pulling the members of the list in + where we reverse the order, by pulling the members off the list in reverse order from how they were inserted. If we have no fields (this is apparently possible in C++) then skip building a field vector. */ if (nfields > 0) { + if (unsigned_enum) + TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED; TYPE_NFIELDS (type) = nfields; TYPE_FIELDS (type) = (struct field *) obstack_alloc (&objfile->symbol_obstack, sizeof (struct field) * nfields); @@ -1485,6 +1838,16 @@ read_func_scope (dip, thisdie, enddie, objfile) { register struct context_stack *new; + /* AT_name is absent if the function is described with an + AT_abstract_origin tag. + Ignore the function description for now to avoid GDB core dumps. + FIXME: Add code to handle AT_abstract_origin tags properly. */ + if (dip -> at_name == NULL) + { + complain (&missing_at_name, DIE_ID); + return; + } + if (objfile -> ei.entry_point >= dip -> at_low_pc && objfile -> ei.entry_point < dip -> at_high_pc) { @@ -1507,6 +1870,52 @@ read_func_scope (dip, thisdie, enddie, objfile) list_in_scope = &file_symbols; } + +/* + +LOCAL FUNCTION + + handle_producer -- process the AT_producer attribute + +DESCRIPTION + + Perform any operations that depend on finding a particular + AT_producer attribute. + + */ + +static void +handle_producer (producer) + char *producer; +{ + + /* If this compilation unit was compiled with g++ or gcc, then set the + processing_gcc_compilation flag. */ + + processing_gcc_compilation = + STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)) + || STREQN (producer, CHILL_PRODUCER, strlen (CHILL_PRODUCER)) + || STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER)); + + /* Select a demangling style if we can identify the producer and if + the current style is auto. We leave the current style alone if it + is not auto. We also leave the demangling style alone if we find a + gcc (cc1) producer, as opposed to a g++ (cc1plus) producer. */ + + if (AUTO_DEMANGLING) + { + if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))) + { + set_demangling_style (GNU_DEMANGLING_STYLE_STRING); + } + else if (STREQN (producer, LCC_PRODUCER, strlen (LCC_PRODUCER))) + { + set_demangling_style (LUCID_DEMANGLING_STYLE_STRING); + } + } +} + + /* LOCAL FUNCTION @@ -1545,35 +1954,26 @@ read_file_scope (dip, thisdie, enddie, objfile) 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) { - processing_gcc_compilation = - STREQN (dip -> at_producer, GCC_PRODUCER, strlen (GCC_PRODUCER)); + handle_producer (dip -> at_producer); } numutypes = (enddie - thisdie) / 4; utypes = (struct type **) xmalloc (numutypes * sizeof (struct type *)); - back_to = make_cleanup (free, utypes); - (void) memset (utypes, 0, numutypes * sizeof (struct type *)); - start_symtab (dip -> at_name, NULL, dip -> at_low_pc); + back_to = make_cleanup (free_utypes, NULL); + memset (utypes, 0, numutypes * sizeof (struct type *)); + memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *)); + start_symtab (dip -> at_name, dip -> at_comp_dir, dip -> at_low_pc); decode_line_numbers (lnbase); process_dies (thisdie + dip -> die_length, enddie, objfile); - symtab = end_symtab (dip -> at_high_pc, 0, 0, objfile); - /* FIXME: The following may need to be expanded for other languages */ - switch (dip -> at_language) + + symtab = end_symtab (dip -> at_high_pc, objfile, 0); + if (symtab != NULL) { - 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; - numutypes = 0; } /* @@ -1624,10 +2024,21 @@ process_dies (thisdie, enddie, objfile) { nextdie = thisdie + di.die_length; } +#ifdef SMASH_TEXT_ADDRESS + /* I think that these are always text, not data, addresses. */ + SMASH_TEXT_ADDRESS (di.at_low_pc); + SMASH_TEXT_ADDRESS (di.at_high_pc); +#endif switch (di.die_tag) { case TAG_compile_unit: - read_file_scope (&di, thisdie, nextdie, objfile); + /* Skip Tag_compile_unit if we are already inside a compilation + unit, we are unable to handle nested compilation units + properly (FIXME). */ + if (current_subfile == NULL) + read_file_scope (&di, thisdie, nextdie, objfile); + else + nextdie = thisdie + di.die_length; break; case TAG_global_subroutine: case TAG_subroutine: @@ -1639,6 +2050,7 @@ process_dies (thisdie, enddie, objfile) 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); @@ -1655,8 +2067,11 @@ process_dies (thisdie, enddie, objfile) case TAG_pointer_type: read_tag_pointer_type (&di); break; + case TAG_string_type: + read_tag_string_type (&di); + break; default: - (void) new_symbol (&di, objfile); + new_symbol (&di, objfile); break; } } @@ -1777,6 +2192,9 @@ DESCRIPTION Given pointer to a string of bytes that define a location, compute the location and return the value. + A location description containing no atoms indicates that the + object is optimized out. The global optimized_out flag is set for + those, the return value is meaningless. When computing values involving the current value of the frame pointer, the value zero is used, which results in a value relative to the frame @@ -1804,7 +2222,6 @@ locval (loc) auto long stack[64]; int stacki; char *end; - long regno; int loc_atom_code; int loc_value_size; @@ -1816,9 +2233,11 @@ locval (loc) stack[stacki] = 0; isreg = 0; offreg = 0; + optimized_out = 1; loc_value_size = TARGET_FT_LONG_SIZE (current_objfile); while (loc < end) { + optimized_out = 0; loc_atom_code = target_to_host (loc, SIZEOF_LOC_ATOM_CODE, GET_UNSIGNED, current_objfile); loc += SIZEOF_LOC_ATOM_CODE; @@ -1830,27 +2249,22 @@ locval (loc) break; case OP_REG: /* push register (number) */ - stack[++stacki] = target_to_host (loc, loc_value_size, - GET_UNSIGNED, current_objfile); + stack[++stacki] + = DWARF_REG_TO_REGNUM (target_to_host (loc, loc_value_size, + GET_UNSIGNED, + current_objfile)); loc += loc_value_size; isreg = 1; break; case OP_BASEREG: /* push value of register (number) */ - /* Actually, we compute the value as if register has 0 */ + /* Actually, we compute the value as if register has 0, so the + value ends up being the offset from that register. */ offreg = 1; - regno = target_to_host (loc, loc_value_size, GET_UNSIGNED, - current_objfile); + basereg = target_to_host (loc, loc_value_size, GET_UNSIGNED, + current_objfile); loc += loc_value_size; - if (regno == R_FP) - { - stack[++stacki] = 0; - } - else - { - stack[++stacki] = 0; - SQUAWK (("BASEREG %d not handled!", regno)); - } + stack[++stacki] = 0; break; case OP_ADDR: /* push address (relocated address) */ @@ -1866,10 +2280,10 @@ locval (loc) break; case OP_DEREF2: /* pop, deref and push 2 bytes (as a long) */ - SQUAWK (("OP_DEREF2 address 0x%x not handled", stack[stacki])); + complain (&op_deref2, DIE_ID, DIE_NAME, stack[stacki]); break; case OP_DEREF4: /* pop, deref and push 4 bytes (as a long) */ - SQUAWK (("OP_DEREF4 address 0x%x not handled", stack[stacki])); + complain (&op_deref4, DIE_ID, DIE_NAME, stack[stacki]); break; case OP_ADD: /* pop top 2 items, add, push result */ stack[stacki - 1] += stack[stacki]; @@ -1888,25 +2302,24 @@ LOCAL FUNCTION SYNOPSIS - static struct symtab *read_ofile_symtab (struct partial_symtab *pst) + static void read_ofile_symtab (struct partial_symtab *pst) DESCRIPTION When expanding a partial symbol table entry to a full symbol table entry, this is the function that gets called to read in the symbols - for the compilation unit. - - Returns a pointer to the newly constructed symtab (which is now - the new first one on the objfile's symtab list). + for the compilation unit. A pointer to the newly constructed symtab, + which is now the new first one on the objfile's symtab list, is + stashed in the partial symbol table entry. */ -static struct symtab * +static void read_ofile_symtab (pst) struct partial_symtab *pst; { struct cleanup *back_to; unsigned long lnsize; - int foffset; + file_ptr foffset; bfd *abfd; char lnsizedata[SIZEOF_LINETBL_LENGTH]; @@ -1917,12 +2330,14 @@ read_ofile_symtab (pst) 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; - baseaddr = pst -> addr; - if (bfd_seek (abfd, foffset, 0) || - (bfd_read (dbbase, DBLENGTH(pst), 1, abfd) != DBLENGTH(pst))) + base_section_offsets = pst->section_offsets; + baseaddr = ANOFFSET (pst->section_offsets, 0); + if (bfd_seek (abfd, foffset, SEEK_SET) || + (bfd_read (dbbase, dbsize, 1, abfd) != dbsize)) { free (dbbase); error ("can't read DWARF data"); @@ -1937,7 +2352,7 @@ read_ofile_symtab (pst) lnbase = NULL; if (LNFOFF (pst)) { - if (bfd_seek (abfd, LNFOFF (pst), 0) || + if (bfd_seek (abfd, LNFOFF (pst), SEEK_SET) || (bfd_read ((PTR) lnsizedata, sizeof (lnsizedata), 1, abfd) != sizeof (lnsizedata))) { @@ -1946,7 +2361,7 @@ read_ofile_symtab (pst) 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), SEEK_SET) || (bfd_read (lnbase, lnsize, 1, abfd) != lnsize)) { free (lnbase); @@ -1955,10 +2370,10 @@ read_ofile_symtab (pst) 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); + pst -> symtab = pst -> objfile -> symtabs; } /* @@ -1983,6 +2398,7 @@ psymtab_to_symtab_1 (pst) struct partial_symtab *pst; { int i; + struct cleanup *old_chain; if (pst != NULL) { @@ -2001,28 +2417,31 @@ psymtab_to_symtab_1 (pst) /* Inform about additional files that need to be read in. */ if (info_verbose) { - fputs_filtered (" ", stdout); + fputs_filtered (" ", gdb_stdout); wrap_here (""); - fputs_filtered ("and ", stdout); + fputs_filtered ("and ", gdb_stdout); wrap_here (""); printf_filtered ("%s...", pst -> dependencies[i] -> filename); wrap_here (""); - fflush (stdout); /* Flush output */ + gdb_flush (gdb_stdout); /* Flush output */ } psymtab_to_symtab_1 (pst -> dependencies[i]); } } if (DBLENGTH (pst)) /* Otherwise it's a dummy */ { - pst -> symtab = read_ofile_symtab (pst); + buildsym_init (); + old_chain = make_cleanup (really_free_pendings, 0); + read_ofile_symtab (pst); if (info_verbose) { printf_filtered ("%d DIE's, sorting...", diecount); wrap_here (""); - fflush (stdout); + gdb_flush (gdb_stdout); } sort_symtab_syms (pst -> symtab); + do_cleanups (old_chain); } pst -> readin = 1; } @@ -2069,7 +2488,7 @@ dwarf_psymtab_to_symtab (pst) { printf_filtered ("Reading in symbols for %s...", pst -> filename); - fflush (stdout); + gdb_flush (gdb_stdout); } psymtab_to_symtab_1 (pst); @@ -2087,7 +2506,7 @@ dwarf_psymtab_to_symtab (pst) if (info_verbose) { printf_filtered ("done.\n"); - fflush (stdout); + gdb_flush (gdb_stdout); } } } @@ -2096,54 +2515,6 @@ dwarf_psymtab_to_symtab (pst) /* -LOCAL FUNCTION - - init_psymbol_list -- initialize storage for partial symbols - -SYNOPSIS - - static void init_psymbol_list (struct objfile *objfile, int total_symbols) - -DESCRIPTION - - Initializes storage for all of the partial symbols that will be - created by dwarf_build_psymtabs and subsidiaries. - */ - -static void -init_psymbol_list (objfile, total_symbols) - struct objfile *objfile; - int total_symbols; -{ - /* Free any previously allocated psymbol lists. */ - - if (objfile -> global_psymbols.list) - { - mfree (objfile -> md, (PTR)objfile -> global_psymbols.list); - } - if (objfile -> static_psymbols.list) - { - mfree (objfile -> md, (PTR)objfile -> static_psymbols.list); - } - - /* Current best guess is that there are 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)); -} - -/* - LOCAL FUNCTION add_enum_psymbol -- add enumeration members to partial symbol table @@ -2181,8 +2552,9 @@ add_enum_psymbol (dip, objfile) while (scan < listend) { scan += TARGET_FT_LONG_SIZE (objfile); - ADD_PSYMBOL_TO_LIST (scan, strlen (scan), VAR_NAMESPACE, LOC_CONST, - objfile -> static_psymbols, 0); + add_psymbol_to_list (scan, strlen (scan), VAR_NAMESPACE, LOC_CONST, + &objfile -> static_psymbols, 0, 0, cu_language, + objfile); scan += strlen (scan) + 1; } } @@ -2200,6 +2572,9 @@ DESCRIPTION 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 @@ -2210,55 +2585,54 @@ add_partial_symbol (dip, objfile) switch (dip -> die_tag) { case TAG_global_subroutine: - record_minimal_symbol (dip -> at_name, dip -> at_low_pc, mst_text, - objfile); - ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name), - VAR_NAMESPACE, LOC_BLOCK, - objfile -> global_psymbols, - dip -> at_low_pc); + add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name), + VAR_NAMESPACE, LOC_BLOCK, + &objfile -> global_psymbols, + 0, dip -> at_low_pc, cu_language, objfile); break; case TAG_global_variable: - record_minimal_symbol (dip -> at_name, locval (dip -> at_location), - mst_data, objfile); - ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name), + add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name), VAR_NAMESPACE, LOC_STATIC, - objfile -> global_psymbols, - 0); + &objfile -> global_psymbols, + 0, 0, cu_language, objfile); break; case TAG_subroutine: - ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name), - VAR_NAMESPACE, LOC_BLOCK, - objfile -> static_psymbols, - dip -> at_low_pc); + add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name), + VAR_NAMESPACE, LOC_BLOCK, + &objfile -> static_psymbols, + 0, dip -> at_low_pc, cu_language, objfile); break; case TAG_local_variable: - ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name), + add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name), VAR_NAMESPACE, LOC_STATIC, - objfile -> static_psymbols, - 0); + &objfile -> static_psymbols, + 0, 0, cu_language, objfile); break; case TAG_typedef: - ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name), + add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name), VAR_NAMESPACE, LOC_TYPEDEF, - objfile -> static_psymbols, - 0); + &objfile -> static_psymbols, + 0, 0, cu_language, objfile); break; + case TAG_class_type: case TAG_structure_type: case TAG_union_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) + /* Do not add opaque aggregate definitions to the psymtab. */ + if (!dip -> has_at_byte_size) + break; + add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name), + STRUCT_NAMESPACE, LOC_TYPEDEF, + &objfile -> static_psymbols, + 0, 0, cu_language, objfile); + if (cu_language == language_cplus) { - ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name), - STRUCT_NAMESPACE, LOC_TYPEDEF, - objfile -> static_psymbols, - 0); + /* For C++, these implicitly act as typedefs as well. */ + add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name), + VAR_NAMESPACE, LOC_TYPEDEF, + &objfile -> static_psymbols, + 0, 0, cu_language, objfile); } - add_enum_psymbol (dip, objfile); break; } } @@ -2273,15 +2647,50 @@ DESCRIPTION Process the DIE's within a single compilation unit, looking for interesting DIE's that contribute to the partial symbol table entry - for this compilation unit. Since we cannot follow any sibling - chains without reading the complete DIE info for every DIE, - it is probably faster to just sequentially check each one to - see if it is one of the types we are interested in, and if so, - then extract all the attributes info and generate a partial - symbol table entry. + for this compilation unit. NOTES + There are some DIE's that may appear both at file scope and within + the scope of a function. We are only interested in the ones at file + scope, and the only way to tell them apart is to keep track of the + scope. For example, consider the test case: + + static int i; + main () { int j; } + + for which the relevant DWARF segment has the structure: + + 0x51: + 0x23 global subrtn sibling 0x9b + name main + fund_type FT_integer + low_pc 0x800004cc + high_pc 0x800004d4 + + 0x74: + 0x23 local var sibling 0x97 + name j + fund_type FT_integer + location OP_BASEREG 0xe + OP_CONST 0xfffffffc + OP_ADD + 0x97: + 0x4 + + 0x9b: + 0x1d local var sibling 0xb8 + name i + fund_type FT_integer + location OP_ADDR 0x800025dc + + 0xb8: + 0x4 + + We want to include the symbol 'i' in the partial symbol table, but + not the symbol 'j'. In essence, we want to skip all the dies within + the scope of a TAG_global_subroutine DIE. + Don't attempt to add anonymous structures or unions since they have no name. Anonymous enumerations however are processed, because we want to extract their member names (the check for a tag name is @@ -2299,6 +2708,7 @@ scan_partial_symbols (thisdie, enddie, objfile) struct objfile *objfile; { char *nextdie; + char *temp; struct dieinfo di; while (thisdie < enddie) @@ -2317,6 +2727,29 @@ scan_partial_symbols (thisdie, enddie, objfile) { case TAG_global_subroutine: case TAG_subroutine: + completedieinfo (&di, objfile); + if (di.at_name && (di.has_at_low_pc || di.at_location)) + { + add_partial_symbol (&di, objfile); + /* If there is a sibling attribute, adjust the nextdie + pointer to skip the entire scope of the subroutine. + Apply some sanity checking to make sure we don't + overrun or underrun the range of remaining DIE's */ + if (di.at_sibling != 0) + { + temp = dbbase + di.at_sibling - dbroff; + if ((temp < thisdie) || (temp >= enddie)) + { + complain (&bad_die_ref, DIE_ID, DIE_NAME, + di.at_sibling); + } + else + { + nextdie = temp; + } + } + } + break; case TAG_global_variable: case TAG_local_variable: completedieinfo (&di, objfile); @@ -2326,6 +2759,7 @@ scan_partial_symbols (thisdie, enddie, objfile) } break; case TAG_typedef: + case TAG_class_type: case TAG_structure_type: case TAG_union_type: completedieinfo (&di, objfile); @@ -2336,7 +2770,11 @@ scan_partial_symbols (thisdie, enddie, 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; } } @@ -2388,12 +2826,11 @@ RETURNS */ 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; @@ -2401,7 +2838,7 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile) struct partial_symtab *pst; int culength; int curoff; - int curlnoffset; + file_ptr curlnoffset; while (thisdie < enddie) { @@ -2417,6 +2854,7 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile) else { completedieinfo (&di, objfile); + set_cu_language (&di); if (di.at_sibling != 0) { nextdie = dbbase + di.at_sibling - dbroff; @@ -2431,8 +2869,8 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile) /* First allocate a new partial symbol table structure */ - pst = start_psymtab_common (objfile, baseaddr, 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); @@ -2493,21 +2931,31 @@ new_symbol (dip, objfile) { sym = (struct symbol *) obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol)); - (void) memset (sym, 0, sizeof (struct symbol)); - SYMBOL_NAME (sym) = create_name (dip -> at_name, &objfile->symbol_obstack); + OBJSTAT (objfile, n_syms++); + memset (sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (sym) = create_name (dip -> at_name, + &objfile->symbol_obstack); /* default assumptions */ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; SYMBOL_CLASS (sym) = LOC_STATIC; SYMBOL_TYPE (sym) = decode_die_type (dip); + + /* If this symbol is from a C++ compilation, then attempt to cache the + demangled form for future reference. This is a typical time versus + space tradeoff, that was decided in favor of time because it sped up + C++ symbol lookups by a factor of about 20. */ + + SYMBOL_LANGUAGE (sym) = cu_language; + SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile -> symbol_obstack); switch (dip -> die_tag) { case TAG_label: - SYMBOL_VALUE (sym) = dip -> at_low_pc; + SYMBOL_VALUE_ADDRESS (sym) = dip -> at_low_pc; SYMBOL_CLASS (sym) = LOC_LABEL; break; case TAG_global_subroutine: case TAG_subroutine: - SYMBOL_VALUE (sym) = dip -> at_low_pc; + SYMBOL_VALUE_ADDRESS (sym) = dip -> at_low_pc; SYMBOL_TYPE (sym) = lookup_function_type (SYMBOL_TYPE (sym)); SYMBOL_CLASS (sym) = LOC_BLOCK; if (dip -> die_tag == TAG_global_subroutine) @@ -2533,13 +2981,18 @@ new_symbol (dip, objfile) { SYMBOL_VALUE (sym) = locval (dip -> at_location); add_symbol_to_list (sym, list_in_scope); - if (isreg) + if (optimized_out) + { + SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; + } + else if (isreg) { SYMBOL_CLASS (sym) = LOC_REGISTER; } else if (offreg) { - SYMBOL_CLASS (sym) = LOC_LOCAL; + SYMBOL_CLASS (sym) = LOC_BASEREG; + SYMBOL_BASEREG (sym) = basereg; } else { @@ -2558,6 +3011,11 @@ new_symbol (dip, objfile) { SYMBOL_CLASS (sym) = LOC_REGPARM; } + else if (offreg) + { + SYMBOL_CLASS (sym) = LOC_BASEREG_ARG; + SYMBOL_BASEREG (sym) = basereg; + } else { SYMBOL_CLASS (sym) = LOC_ARG; @@ -2567,6 +3025,7 @@ new_symbol (dip, objfile) /* 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: @@ -2591,6 +3050,52 @@ new_symbol (dip, objfile) /* +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)); + OBJSTAT (objfile, n_syms++); + memset (sym, 0, sizeof (struct symbol)); + SYMBOL_NAME (sym) = create_name (dip -> at_name, + &objfile->symbol_obstack); + SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language); + 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 @@ -2691,7 +3196,7 @@ LOCAL FUNCTION SYNOPSIS - static struct type *decode_modified_type (unsigned char *modifiers, + static struct type *decode_modified_type (char *modifiers, unsigned short modcount, int mtype) DESCRIPTION @@ -2725,14 +3230,14 @@ BUGS static struct type * decode_modified_type (modifiers, modcount, mtype) - unsigned char *modifiers; + char *modifiers; unsigned int modcount; int mtype; { struct type *typep = NULL; unsigned short fundtype; DIE_REF die_ref; - unsigned char modifier; + char modifier; int nbytes; if (modcount == 0) @@ -2755,8 +3260,8 @@ decode_modified_type (modifiers, modcount, mtype) } break; default: - SQUAWK (("botched modified type decoding (mtype 0x%x)", mtype)); - typep = lookup_fundamental_type (current_objfile, FT_INTEGER); + complain (&botched_modified_type, DIE_ID, DIE_NAME, mtype); + typep = dwarf_fundamental_type (current_objfile, FT_INTEGER); break; } } @@ -2773,15 +3278,16 @@ decode_modified_type (modifiers, modcount, mtype) typep = lookup_reference_type (typep); break; case MOD_const: - SQUAWK (("type modifier 'const' ignored")); /* FIXME */ + complain (&const_ignored, DIE_ID, DIE_NAME); /* FIXME */ break; case MOD_volatile: - SQUAWK (("type modifier 'volatile' ignored")); /* FIXME */ + complain (&volatile_ignored, DIE_ID, DIE_NAME); /* FIXME */ break; default: - if (!(MOD_lo_user <= modifier && modifier <= MOD_hi_user)) + if (!(MOD_lo_user <= (unsigned char) modifier + && (unsigned char) modifier <= MOD_hi_user)) { - SQUAWK (("unknown type modifier %u", modifier)); + complain (&unknown_type_modifier, DIE_ID, DIE_NAME, modifier); } break; } @@ -2803,10 +3309,12 @@ DESCRIPTION NOTES - If we encounter a fundamental type that we are unprepared to - deal with, and it is not in the range of those types defined - as application specific types, then we issue a warning and - treat the type as an "int". + For robustness, if we are asked to translate a fundamental + type that we are unprepared to deal with, we return int so + callers can always depend upon a valid type being returned, + and so gdb may at least do something reasonable by default. + If the type is not in the range of those types defined as + application specific types, we also issue a warning. */ static struct type * @@ -2819,108 +3327,111 @@ decode_fund_type (fundtype) { case FT_void: - typep = lookup_fundamental_type (current_objfile, FT_VOID); + typep = dwarf_fundamental_type (current_objfile, FT_VOID); break; case FT_boolean: /* Was FT_set in AT&T version */ - typep = lookup_fundamental_type (current_objfile, FT_BOOLEAN); + typep = dwarf_fundamental_type (current_objfile, FT_BOOLEAN); break; case FT_pointer: /* (void *) */ - typep = lookup_fundamental_type (current_objfile, FT_VOID); + typep = dwarf_fundamental_type (current_objfile, FT_VOID); typep = lookup_pointer_type (typep); break; case FT_char: - typep = lookup_fundamental_type (current_objfile, FT_CHAR); + typep = dwarf_fundamental_type (current_objfile, FT_CHAR); break; case FT_signed_char: - typep = lookup_fundamental_type (current_objfile, FT_SIGNED_CHAR); + typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_CHAR); break; case FT_unsigned_char: - typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_CHAR); + typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_CHAR); break; case FT_short: - typep = lookup_fundamental_type (current_objfile, FT_SHORT); + typep = dwarf_fundamental_type (current_objfile, FT_SHORT); break; case FT_signed_short: - typep = lookup_fundamental_type (current_objfile, FT_SIGNED_SHORT); + typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_SHORT); break; case FT_unsigned_short: - typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_SHORT); + typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_SHORT); break; case FT_integer: - typep = lookup_fundamental_type (current_objfile, FT_INTEGER); + typep = dwarf_fundamental_type (current_objfile, FT_INTEGER); break; case FT_signed_integer: - typep = lookup_fundamental_type (current_objfile, FT_SIGNED_INTEGER); + typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_INTEGER); break; case FT_unsigned_integer: - typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER); + typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER); break; case FT_long: - typep = lookup_fundamental_type (current_objfile, FT_LONG); + typep = dwarf_fundamental_type (current_objfile, FT_LONG); break; case FT_signed_long: - typep = lookup_fundamental_type (current_objfile, FT_SIGNED_LONG); + typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_LONG); break; case FT_unsigned_long: - typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG); + typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_LONG); break; case FT_long_long: - typep = lookup_fundamental_type (current_objfile, FT_LONG_LONG); + typep = dwarf_fundamental_type (current_objfile, FT_LONG_LONG); break; case FT_signed_long_long: - typep = lookup_fundamental_type (current_objfile, FT_SIGNED_LONG_LONG); + typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_LONG_LONG); break; case FT_unsigned_long_long: - typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG_LONG); + typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_LONG_LONG); break; case FT_float: - typep = lookup_fundamental_type (current_objfile, FT_FLOAT); + typep = dwarf_fundamental_type (current_objfile, FT_FLOAT); break; case FT_dbl_prec_float: - typep = lookup_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT); + typep = dwarf_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT); break; case FT_ext_prec_float: - typep = lookup_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT); + typep = dwarf_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT); break; case FT_complex: - typep = lookup_fundamental_type (current_objfile, FT_COMPLEX); + typep = dwarf_fundamental_type (current_objfile, FT_COMPLEX); break; case FT_dbl_prec_complex: - typep = lookup_fundamental_type (current_objfile, FT_DBL_PREC_COMPLEX); + typep = dwarf_fundamental_type (current_objfile, FT_DBL_PREC_COMPLEX); break; case FT_ext_prec_complex: - typep = lookup_fundamental_type (current_objfile, FT_EXT_PREC_COMPLEX); + typep = dwarf_fundamental_type (current_objfile, FT_EXT_PREC_COMPLEX); break; } - if ((typep == NULL) && !(FT_lo_user <= fundtype && fundtype <= FT_hi_user)) + if (typep == NULL) { - SQUAWK (("unexpected fundamental type 0x%x", fundtype)); - typep = lookup_fundamental_type (current_objfile, FT_VOID); + typep = dwarf_fundamental_type (current_objfile, FT_INTEGER); + if (!(FT_lo_user <= fundtype && fundtype <= FT_hi_user)) + { + complain (&unexpected_fund_type, DIE_ID, DIE_NAME, fundtype); + } } return (typep); @@ -2949,7 +3460,7 @@ create_name (name, obstackp) length = strlen (name) + 1; newname = (char *) obstack_alloc (obstackp, length); - (void) strcpy (newname, name); + strcpy (newname, name); return (newname); } @@ -2999,6 +3510,12 @@ NOTES 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 @@ -3008,14 +3525,16 @@ basicdieinfo (dip, diep, objfile) struct objfile *objfile; { curdie = dip; - (void) memset (dip, 0, sizeof (struct dieinfo)); + memset (dip, 0, sizeof (struct dieinfo)); dip -> die = diep; 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); + complain (&malformed_die, DIE_ID, DIE_NAME, dip -> die_length); + dip -> die_length = 0; } else if (dip -> die_length < (SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG)) { @@ -3082,7 +3601,7 @@ completedieinfo (dip, objfile) diep += SIZEOF_ATTRIBUTE; if ((nbytes = attribute_size (attr)) == -1) { - SQUAWK (("unknown attribute length, skipped remaining attributes"));; + complain (&unknown_attribute_length, DIE_ID, DIE_NAME); diep = end; continue; } @@ -3100,10 +3619,6 @@ completedieinfo (dip, objfile) dip -> at_bit_offset = target_to_host (diep, nbytes, GET_UNSIGNED, objfile); break; - case AT_visibility: - dip -> at_visibility = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); - break; case AT_sibling: dip -> at_sibling = target_to_host (diep, nbytes, GET_UNSIGNED, objfile); @@ -3135,6 +3650,7 @@ completedieinfo (dip, objfile) case AT_byte_size: dip -> at_byte_size = target_to_host (diep, nbytes, GET_UNSIGNED, objfile); + dip -> has_at_byte_size = 1; break; case AT_bit_size: dip -> at_bit_size = target_to_host (diep, nbytes, GET_UNSIGNED, @@ -3148,10 +3664,6 @@ completedieinfo (dip, objfile) dip -> at_discr = target_to_host (diep, nbytes, GET_UNSIGNED, objfile); break; - case AT_import: - dip -> at_import = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); - break; case AT_location: dip -> at_location = diep; break; @@ -3182,15 +3694,21 @@ completedieinfo (dip, objfile) dip -> at_name = diep; break; case AT_comp_dir: - dip -> at_comp_dir = diep; + /* For now, ignore any "hostname:" portion, since gdb doesn't + know how to deal with it. (FIXME). */ + dip -> at_comp_dir = strrchr (diep, ':'); + if (dip -> at_comp_dir != NULL) + { + dip -> at_comp_dir++; + } + else + { + dip -> at_comp_dir = diep; + } break; case AT_producer: dip -> at_producer = diep; break; - case AT_frame_base: - dip -> at_frame_base = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); - break; case AT_start_scope: dip -> at_start_scope = target_to_host (diep, nbytes, GET_UNSIGNED, objfile); @@ -3240,8 +3758,7 @@ completedieinfo (dip, objfile) diep += strlen (diep) + 1; break; default: - SQUAWK (("unknown attribute form (0x%x)", form)); - SQUAWK (("unknown attribute length, skipped remaining attributes"));; + complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form); diep = end; break; } @@ -3273,16 +3790,18 @@ NOTES use it as signed data, then we need to explicitly sign extend the result until the bfd library is able to do this for us. + FIXME: Would a 32 bit target ever need an 8 byte result? + */ -static unsigned long +static CORE_ADDR target_to_host (from, nbytes, signextend, objfile) char *from; int nbytes; int signextend; /* FIXME: Unused */ struct objfile *objfile; { - unsigned long rtnval; + CORE_ADDR rtnval; switch (nbytes) { @@ -3299,7 +3818,7 @@ target_to_host (from, nbytes, signextend, objfile) rtnval = bfd_get_8 (objfile -> obfd, (bfd_byte *) from); break; default: - dwarfwarn ("no bfd support for %d byte data object", nbytes); + complain (&no_bfd_get_N, DIE_ID, DIE_NAME, nbytes); rtnval = 0; break; } @@ -3355,7 +3874,7 @@ attribute_size (attr) nbytes = TARGET_FT_POINTER_SIZE (objfile); break; default: - SQUAWK (("unknown attribute form (0x%x)", form)); + complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form); nbytes = -1; break; }