X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fdwarfread.c;h=aebe6bffeb3524b42efeaaa9dd516427995c1d37;hb=d360e1e0a19bef5bc552835e53a9f69aafcde455;hp=82ee4167cc19f6eba02eb1bd7099c3031c9de3b7;hpb=50055e94a1d558f9f8edce1c07e90560d7161b76;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/dwarfread.c b/gdb/dwarfread.c index 82ee4167cc..aebe6bffeb 100644 --- a/gdb/dwarfread.c +++ b/gdb/dwarfread.c @@ -1,5 +1,5 @@ /* DWARF debugging format support for GDB. - Copyright (C) 1991, 1992 Free Software Foundation, Inc. + Copyright (C) 1991, 1992, 1993, 1994 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. @@ -21,10 +21,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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,30 +39,141 @@ 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) +#include +#include + +#ifndef NO_SYS_FILE +#include #endif -#ifndef R_FP /* FIXME */ -#define R_FP 14 /* Kludge to get frame pointer register number */ +/* FIXME -- convert this to SEEK_SET a la POSIX, move to config files. */ +#ifndef L_SET +#define L_SET 0 #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 +}; + typedef unsigned int DIE_REF; /* Reference to a DIE */ #ifndef GCC_PRODUCER @@ -76,16 +185,13 @@ typedef unsigned int DIE_REF; /* Reference to a DIE */ #endif #ifndef LCC_PRODUCER -#define LCC_PRODUCER "NCR C/C++ " +#define LCC_PRODUCER "NCR C/C++" #endif -#ifndef CFRONT_PRODUCER -#define CFRONT_PRODUCER "CFRONT " /* A wild a** guess... */ +#ifndef CHILL_PRODUCER +#define CHILL_PRODUCER "GNU Chill " #endif -#define STREQ(a,b) (strcmp(a,b)==0) -#define STREQN(a,b,n) (strncmp(a,b,n)==0) - /* 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 integer in the target environment which is used as a signed integer @@ -212,13 +318,19 @@ 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 */ +/* 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. */ + 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 */ /* The section offsets used in the current psymtab or symtab. FIXME, @@ -252,10 +364,10 @@ static struct section_offsets *base_section_offsets; */ 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) @@ -295,11 +407,39 @@ 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. */ @@ -325,15 +465,12 @@ 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 *)); @@ -353,7 +490,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 @@ -367,7 +504,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 *)); @@ -375,6 +512,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 *)); @@ -417,12 +557,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); +} /* @@ -432,18 +694,17 @@ 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 @@ -458,28 +719,28 @@ RETURNS */ 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); @@ -502,95 +763,12 @@ dwarf_build_psymtabs (desc, filename, section_offsets, mainline, dbfoff, dbsize, 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 @@ -658,7 +836,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 { @@ -701,13 +879,13 @@ 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 { @@ -764,7 +942,7 @@ decode_die_type (dip) } else { - type = lookup_fundamental_type (current_objfile, FT_INTEGER); + type = dwarf_fundamental_type (current_objfile, FT_INTEGER); } return (type); } @@ -805,7 +983,6 @@ struct_type (dip, thisdie, enddie, objfile) struct nextfield *new; int nfields = 0; int n; - char *tpart1; struct dieinfo mbr; char *nextdie; int anonymous_size; @@ -818,19 +995,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 @@ -840,8 +1017,8 @@ struct_type (dip, thisdie, enddie, objfile) && *dip -> at_name != '~' && *dip -> at_name != '.') { - TYPE_NAME (type) = obconcat (&objfile -> type_obstack, - tpart1, " ", dip -> at_name); + 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 @@ -881,39 +1058,47 @@ struct_type (dip, thisdie, enddie, objfile) list -> field.bitpos = 8 * locval (mbr.at_location); /* 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 (BITS_BIG_ENDIAN) { - 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 + /* 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) { - /* 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); + 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; } - list -> field.bitpos += - anonymous_size * 8 - mbr.at_bit_offset - mbr.at_bit_size; } -#endif nfields++; break; default: @@ -935,8 +1120,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) { @@ -993,9 +1177,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); + } } } } @@ -1034,8 +1223,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 { @@ -1061,8 +1250,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; } } @@ -1073,11 +1262,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 @@ -1089,9 +1279,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 @@ -1102,12 +1304,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; @@ -1125,32 +1329,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) + 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) { - 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_subscr_data (scan, end); - if (nexttype != NULL) - { - typep = alloc_type (current_objfile); - TYPE_CODE (typep) = TYPE_CODE_ARRAY; - TYPE_LENGTH (typep) = TYPE_LENGTH (nexttype); - TYPE_LENGTH (typep) *= (highbound - lowbound) + 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: @@ -1159,10 +1354,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); @@ -1198,7 +1399,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) { @@ -1206,30 +1407,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) - { - 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); } } } @@ -1279,6 +1479,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 @@ -1327,7 +1590,7 @@ read_subroutine_type (dip, thisdie, enddie) ftype = lookup_function_type (type); 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. */ @@ -1336,6 +1599,10 @@ read_subroutine_type (dip, thisdie, enddie) TYPE_LENGTH (ftype) = 1; TYPE_CODE (ftype) = TYPE_CODE_FUNC; } + else + { + complain (&dup_user_type_definition, DIE_ID, DIE_NAME); + } } /* @@ -1372,9 +1639,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); + } } } @@ -1442,8 +1714,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) { @@ -1483,6 +1755,7 @@ enum_type (dip, objfile) 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; @@ -1585,6 +1858,7 @@ handle_producer (producer) 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 @@ -1592,8 +1866,7 @@ handle_producer (producer) 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 1 /* Works, but is experimental. -fnf */ - if (current_demangling_style == auto_demangling) + if (AUTO_DEMANGLING) { if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))) { @@ -1603,12 +1876,7 @@ handle_producer (producer) { set_demangling_style (LUCID_DEMANGLING_STYLE_STRING); } - else if (STREQN (producer, CFRONT_PRODUCER, strlen (CFRONT_PRODUCER))) - { - set_demangling_style (CFRONT_DEMANGLING_STYLE_STRING); - } } -#endif } @@ -1650,6 +1918,7 @@ 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) { handle_producer (dip -> at_producer); @@ -1658,23 +1927,16 @@ read_file_scope (dip, thisdie, enddie, objfile) utypes = (struct type **) xmalloc (numutypes * sizeof (struct type *)); back_to = make_cleanup (free, utypes); 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, 0, 0, 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; @@ -1728,10 +1990,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: @@ -1743,6 +2016,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); @@ -1759,6 +2033,9 @@ 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: new_symbol (&di, objfile); break; @@ -1908,7 +2185,6 @@ locval (loc) auto long stack[64]; int stacki; char *end; - long regno; int loc_atom_code; int loc_value_size; @@ -1941,20 +2217,13 @@ locval (loc) 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) */ @@ -1970,10 +2239,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]; @@ -1992,25 +2261,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]; @@ -2021,13 +2289,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; 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"); @@ -2042,7 +2311,7 @@ read_ofile_symtab (pst) 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))) { @@ -2051,7 +2320,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), L_SET) || (bfd_read (lnbase, lnsize, 1, abfd) != lnsize)) { free (lnbase); @@ -2060,10 +2329,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; } /* @@ -2107,14 +2376,14 @@ 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]); } @@ -2123,12 +2392,12 @@ psymtab_to_symtab_1 (pst) { buildsym_init (); old_chain = make_cleanup (really_free_pendings, 0); - pst -> symtab = read_ofile_symtab (pst); + 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); @@ -2178,7 +2447,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); @@ -2196,7 +2465,7 @@ dwarf_psymtab_to_symtab (pst) if (info_verbose) { printf_filtered ("done.\n"); - fflush (stdout); + gdb_flush (gdb_stdout); } } } @@ -2291,7 +2560,8 @@ add_enum_psymbol (dip, objfile) { scan += TARGET_FT_LONG_SIZE (objfile); ADD_PSYMBOL_TO_LIST (scan, strlen (scan), VAR_NAMESPACE, LOC_CONST, - objfile -> static_psymbols, 0); + objfile -> static_psymbols, 0, cu_language, + objfile); scan += strlen (scan) + 1; } } @@ -2309,6 +2579,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 @@ -2319,55 +2592,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); + 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), VAR_NAMESPACE, LOC_STATIC, 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); + dip -> at_low_pc, cu_language, objfile); break; case TAG_local_variable: ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name), VAR_NAMESPACE, LOC_STATIC, objfile -> static_psymbols, - 0); + 0, cu_language, objfile); break; case TAG_typedef: ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name), VAR_NAMESPACE, LOC_TYPEDEF, objfile -> static_psymbols, - 0); + 0, cu_language, objfile); break; + case TAG_class_type: case TAG_structure_type: case TAG_union_type: + case TAG_enumeration_type: + /* 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); - break; - case TAG_enumeration_type: - if (dip -> at_name) + 0, cu_language, objfile); + 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); + 0, cu_language, objfile); } - add_enum_psymbol (dip, objfile); break; } } @@ -2382,15 +2654,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 @@ -2408,6 +2715,7 @@ scan_partial_symbols (thisdie, enddie, objfile) struct objfile *objfile; { char *nextdie; + char *temp; struct dieinfo di; while (thisdie < enddie) @@ -2426,6 +2734,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); @@ -2435,6 +2766,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); @@ -2445,7 +2777,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; } } @@ -2497,12 +2833,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; @@ -2510,7 +2845,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) { @@ -2526,6 +2861,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; @@ -2540,8 +2876,8 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile) /* 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); @@ -2603,11 +2939,20 @@ new_symbol (dip, objfile) 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; 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: @@ -2648,7 +2993,8 @@ new_symbol (dip, objfile) } else if (offreg) { - SYMBOL_CLASS (sym) = LOC_LOCAL; + SYMBOL_CLASS (sym) = LOC_BASEREG; + SYMBOL_BASEREG (sym) = basereg; } else { @@ -2667,6 +3013,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; @@ -2676,6 +3027,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: @@ -2700,6 +3052,51 @@ 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)); + 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 @@ -2864,8 +3261,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; } } @@ -2882,17 +3279,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 <= (unsigned char) modifier && (unsigned char) modifier <= MOD_hi_user)) { - SQUAWK (("unknown type modifier %u", - (unsigned char) modifier)); + complain (&unknown_type_modifier, DIE_ID, DIE_NAME, modifier); } break; } @@ -2914,10 +3310,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 * @@ -2930,108 +3328,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); @@ -3110,6 +3511,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 @@ -3124,9 +3531,11 @@ basicdieinfo (dip, diep, objfile) 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)) { @@ -3193,7 +3602,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; } @@ -3350,8 +3759,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; } @@ -3409,7 +3817,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; } @@ -3465,7 +3873,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; }