X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fdwarfread.c;h=13599fae35f045b3ee90503c225bb64278c535d8;hb=feb129926a8d12656f1ca4b7a8bb10268d3af4fb;hp=1cd34cd3c3beb6fb2c3efd602ce3b4c9b54ca790;hpb=4db8e515c4db19f91a671c81fcc87bbc2b48c242;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/dwarfread.c b/gdb/dwarfread.c index 1cd34cd3c3..13599fae35 100644 --- a/gdb/dwarfread.c +++ b/gdb/dwarfread.c @@ -1,68 +1,175 @@ /* DWARF debugging format support for GDB. - Copyright (C) 1991, 1992 Free Software Foundation, Inc. + Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1998 + 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. -This file is part of GDB. + This file is part of GDB. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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. */ + 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., 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: Do we need to generate dependencies in partial symtabs? + (Perhaps we don't need to). -FIXME: Add generation of dependencies list to partial symtab code. + 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 + put enum constants there. And dbxread seems to invent a lot of typedefs + we never see. Use the new printpsym command to see the partial symbol table + contents. -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 -put enum constants there. And dbxread seems to invent a lot of typedefs -we never see. Use the new printpsym command to see the partial symbol table -contents. + FIXME: Figure out a better way to tell gdb about the name of the function + contain the user's entry point (I.E. main()) -FIXME: Figure out a better way to tell gdb about the name of the function -contain the user's entry point (I.E. main()) + FIXME: See other FIXME's and "ifdef 0" scattered throughout the code for + other things to work on, if you get bored. :-) -FIXME: See other FIXME's and "ifdef 0" scattered throughout the code for -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 @@ -124,8 +245,8 @@ typedef unsigned int DIE_REF; /* Reference to a DIE */ /* External variables referenced. */ -extern int info_verbose; /* From main.c; nonzero => verbose */ -extern char *warning_pre_print; /* From utils.c */ +extern int info_verbose; /* From main.c; nonzero => verbose */ +extern char *warning_pre_print; /* From utils.c */ /* The DWARF debugging information consists of two major pieces, one is a block of DWARF Information Entries (DIE's) and the other @@ -151,95 +272,110 @@ extern char *warning_pre_print; /* From utils.c */ we may want to test for the presence of some attributes in the DIE, such as AT_low_pc, without restricting the values of the field, we need someway to note that we found such an attribute. - + */ - + typedef char BLOCK; -struct dieinfo { - char * die; /* Pointer to the raw DIE data */ - unsigned long die_length; /* Length of the raw DIE data */ - DIE_REF die_ref; /* Offset of this DIE */ - unsigned short die_tag; /* Tag for this DIE */ - unsigned long at_padding; - unsigned long at_sibling; - BLOCK * at_location; - char * at_name; - unsigned short at_fund_type; - BLOCK * at_mod_fund_type; - unsigned long at_user_def_type; - BLOCK * at_mod_u_d_type; - unsigned short at_ordering; - BLOCK * at_subscr_data; - unsigned long at_byte_size; - unsigned short at_bit_offset; - unsigned long at_bit_size; - BLOCK * at_element_list; - unsigned long at_stmt_list; - unsigned long at_low_pc; - unsigned long 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 short_element_list:1; -}; +struct dieinfo + { + char *die; /* Pointer to the raw DIE data */ + unsigned long die_length; /* Length of the raw DIE data */ + DIE_REF die_ref; /* Offset of this DIE */ + unsigned short die_tag; /* Tag for this DIE */ + unsigned long at_padding; + unsigned long at_sibling; + BLOCK *at_location; + char *at_name; + unsigned short at_fund_type; + BLOCK *at_mod_fund_type; + unsigned long at_user_def_type; + BLOCK *at_mod_u_d_type; + unsigned short at_ordering; + BLOCK *at_subscr_data; + unsigned long at_byte_size; + unsigned short at_bit_offset; + unsigned long at_bit_size; + BLOCK *at_element_list; + unsigned long at_stmt_list; + 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; + BLOCK *at_string_length; + char *at_comp_dir; + char *at_producer; + 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; + + /* Kludge to identify register variables */ + + unsigned int isreg; + + /* Kludge to identify optimized out variables */ + + unsigned int optimized_out; + + /* Kludge to identify basereg references. + Nonzero if we have an offset relative to a basereg. */ + + unsigned int offreg; + + /* Kludge to identify which base register is it relative to. */ + + unsigned int basereg; + }; -static int diecount; /* Approximate count of dies for compilation unit */ +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 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 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 */ +/* 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. - */ - -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 */ -}; +/* 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 + { + /* 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) #define DBROFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbroff) @@ -278,23 +414,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 -target_to_host PARAMS ((char *, int, int, struct objfile *)); +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 +475,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 +497,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 @@ -344,16 +508,19 @@ read_structure_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *)); static struct type * -decode_array_element_type PARAMS ((char *)); + 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 *)); static void -read_tag_pointer_type PARAMS ((struct dieinfo *dip)); +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 *)); @@ -362,228 +529,270 @@ static void read_enumeration PARAMS ((struct dieinfo *, char *, char *, struct objfile *)); static struct type * -struct_type PARAMS ((struct dieinfo *, char *, char *, struct objfile *)); + struct_type PARAMS ((struct dieinfo *, char *, char *, struct objfile *)); static struct type * -enum_type PARAMS ((struct dieinfo *, struct objfile *)); + enum_type PARAMS ((struct dieinfo *, struct objfile *)); static void decode_line_numbers PARAMS ((char *)); static struct type * -decode_die_type PARAMS ((struct dieinfo *)); + decode_die_type PARAMS ((struct dieinfo *)); static struct type * -decode_mod_fund_type PARAMS ((char *)); + decode_mod_fund_type PARAMS ((char *)); static struct type * -decode_mod_u_d_type PARAMS ((char *)); + 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)); + decode_fund_type PARAMS ((unsigned int)); static char * -create_name PARAMS ((char *, struct obstack *)); + create_name PARAMS ((char *, struct obstack *)); static struct type * -lookup_utype PARAMS ((DIE_REF)); + lookup_utype PARAMS ((DIE_REF)); static struct type * -alloc_utype PARAMS ((DIE_REF, struct type *)); + alloc_utype PARAMS ((DIE_REF, struct type *)); static struct symbol * -new_symbol PARAMS ((struct dieinfo *, struct objfile *)); + new_symbol PARAMS ((struct dieinfo *, struct objfile *)); + +static void +synthesize_typedef PARAMS ((struct dieinfo *, struct objfile *, + struct type *)); static int -locval PARAMS ((char *)); +locval PARAMS ((struct dieinfo *)); 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)); + /* -GLOBAL FUNCTION + LOCAL FUNCTION - dwarf_build_psymtabs -- build partial symtabs from DWARF debug info + dwarf_fundamental_type -- lookup or create a fundamental type -SYNOPSIS + 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) + struct type * + dwarf_fundamental_type (struct objfile *objfile, int typeid) -DESCRIPTION + DESCRIPTION - This function is called upon to build partial symtabs from files - containing DIE's (Dwarf Information Entries) and DWARF line numbers. + 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. - It is passed a file descriptor for an open file 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 - table" rather than a shared library or dynamically linked file, - and file offset/size pairs for the DIE information and line number - information. + 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 + RETURNS - No return value. + Pointer to a fundamental type. */ -void -dwarf_build_psymtabs (desc, filename, addr, mainline, dbfoff, dbsize, - lnoffset, lnsize, objfile) - int desc; - char *filename; - CORE_ADDR addr; - int mainline; - unsigned int dbfoff; - unsigned int dbsize; - unsigned int lnoffset; - unsigned int lnsize; +static struct type * +dwarf_fundamental_type (objfile, typeid) struct objfile *objfile; + int typeid; { - struct cleanup *back_to; - - current_objfile = objfile; - dbbase = xmalloc (dbsize); - dbroff = 0; - if ((lseek (desc, dbfoff, 0) != dbfoff) || - (read (desc, dbbase, dbsize) != dbsize)) + if (typeid < 0 || typeid >= FT_NUM_MEMBERS) { - free (dbbase); - error ("can't read DWARF data from '%s'", filename); + error ("internal error - invalid fundamental type id %d", typeid); } - back_to = make_cleanup (free, dbbase); - - /* If we are reinitializing, or if we have never loaded syms yet, init. - Since we have no idea how many DIES we are looking at, we just guess - some arbitrary value. */ - - if (mainline || objfile -> global_psymbols.size == 0 || - objfile -> static_psymbols.size == 0) + + /* 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) { - init_psymbol_list (objfile, 1024); + ftypes[typeid] = cu_language_defn->la_fund_type (objfile, typeid); } - - /* Save the relocation factor where everybody can see it. */ - baseaddr = addr; - - /* 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); - - do_cleanups (back_to); - current_objfile = NULL; + return (ftypes[typeid]); } - /* -LOCAL FUNCTION + LOCAL FUNCTION - record_minimal_symbol -- add entry to gdb's minimal symbol table + set_cu_language -- set local copy of language for compilation unit -SYNOPSIS + SYNOPSIS - static void record_minimal_symbol (char *name, CORE_ADDR address, - enum minimal_symbol_type ms_type, - struct objfile *objfile) + void + set_cu_language (struct dieinfo *dip) -DESCRIPTION + 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. - 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. + RETURNS + + No return value. */ static void -record_minimal_symbol (name, address, ms_type, objfile) - char *name; - CORE_ADDR address; - enum minimal_symbol_type ms_type; - struct objfile *objfile; +set_cu_language (dip) + struct dieinfo *dip; { - name = obsavestring (name, strlen (name), &objfile -> symbol_obstack); - prim_record_minimal_symbol (name, address, ms_type); + 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_FORTRAN77: + case LANG_FORTRAN90: + cu_language = language_fortran; + break; + case LANG_ADA83: + case LANG_COBOL74: + case LANG_COBOL85: + 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); } /* -LOCAL FUNCTION + GLOBAL FUNCTION - dwarfwarn -- issue a DWARF related warning + dwarf_build_psymtabs -- build partial symtabs from DWARF debug info -DESCRIPTION + SYNOPSIS - 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. + 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) - 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. + DESCRIPTION -NOTES + This function is called upon to build partial symtabs from files + containing DIE's (Dwarf Information Entries) and DWARF line numbers. - 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). + 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 + table" rather than a shared library or dynamically linked file, + and file offset/size pairs for the DIE information and line number + information. - We assume that curdie is valid and contains at least the basic - information for the DIE where the problem was noticed. -*/ + RETURNS -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); + No return value. + + */ + +void +dwarf_build_psymtabs (objfile, section_offsets, mainline, dbfoff, dbfsize, + lnoffset, lnsize) + struct objfile *objfile; + struct section_offsets *section_offsets; + int mainline; + file_ptr dbfoff; + unsigned int dbfsize; + file_ptr lnoffset; + unsigned int lnsize; +{ + bfd *abfd = objfile->obfd; + struct cleanup *back_to; + + current_objfile = objfile; + dbsize = dbfsize; + dbbase = xmalloc (dbsize); + dbroff = 0; + 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'", bfd_get_filename (abfd)); + } + back_to = make_cleanup (free, dbbase); + + /* If we are reinitializing, or if we have never loaded syms yet, init. + Since we have no idea how many DIES we are looking at, we just guess + some arbitrary value. */ + + if (mainline || objfile->global_psymbols.size == 0 || + objfile->static_psymbols.size == 0) + { + init_psymbol_list (objfile, 1024); + } + + /* Save the relocation factor where everybody can see it. */ + + 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 (dbbase, dbbase + dbsize, dbfoff, lnoffset, objfile); + + do_cleanups (back_to); + current_objfile = NULL; } /* -LOCAL FUNCTION + LOCAL FUNCTION - read_lexical_block_scope -- process all dies in a lexical block + read_lexical_block_scope -- process all dies in a lexical block -SYNOPSIS + SYNOPSIS - static void read_lexical_block_scope (struct dieinfo *dip, - char *thisdie, char *enddie) + static void read_lexical_block_scope (struct dieinfo *dip, + char *thisdie, char *enddie) -DESCRIPTION + DESCRIPTION - Process all the DIES contained within a lexical block scope. - Start a new scope, process the dies, and then close the scope. + Process all the DIES contained within a lexical block scope. + Start a new scope, process the dies, and then close the scope. */ @@ -596,34 +805,34 @@ read_lexical_block_scope (dip, thisdie, enddie, objfile) { register struct context_stack *new; - (void) push_context (0, dip -> at_low_pc); - process_dies (thisdie + dip -> die_length, enddie, objfile); + push_context (0, dip->at_low_pc); + process_dies (thisdie + dip->die_length, enddie, objfile); new = pop_context (); if (local_symbols != NULL) { - finish_block (0, &local_symbols, new -> old_blocks, new -> start_addr, - dip -> at_high_pc, objfile); + finish_block (0, &local_symbols, new->old_blocks, new->start_addr, + dip->at_high_pc, objfile); } - local_symbols = new -> locals; + local_symbols = new->locals; } /* -LOCAL FUNCTION + LOCAL FUNCTION - lookup_utype -- look up a user defined type from die reference + lookup_utype -- look up a user defined type from die reference -SYNOPSIS + SYNOPSIS - static type *lookup_utype (DIE_REF die_ref) + static type *lookup_utype (DIE_REF die_ref) -DESCRIPTION + DESCRIPTION - Given a DIE reference, lookup the user defined type associated with - that DIE, if it has been registered already. If not registered, then - return NULL. Alloc_utype() can be called to register an empty - type for this reference, which will be filled in later when the - actual referenced DIE is processed. + Given a DIE reference, lookup the user defined type associated with + that DIE, if it has been registered already. If not registered, then + return NULL. Alloc_utype() can be called to register an empty + type for this reference, which will be filled in later when the + actual referenced DIE is processed. */ static struct type * @@ -632,11 +841,11 @@ lookup_utype (die_ref) { struct type *type = NULL; int utypeidx; - + 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 { @@ -648,23 +857,23 @@ lookup_utype (die_ref) /* -LOCAL FUNCTION + LOCAL FUNCTION - alloc_utype -- add a user defined type for die reference + alloc_utype -- add a user defined type for die reference -SYNOPSIS + SYNOPSIS - static type *alloc_utype (DIE_REF die_ref, struct type *utypep) + static type *alloc_utype (DIE_REF die_ref, struct type *utypep) -DESCRIPTION + DESCRIPTION - Given a die reference DIE_REF, and a possible pointer to a user - defined type UTYPEP, register that this reference has a user - defined type and either use the specified type in UTYPEP or - make a new empty type that will be filled in later. + Given a die reference DIE_REF, and a possible pointer to a user + defined type UTYPEP, register that this reference has a user + defined type and either use the specified type in UTYPEP or + make a new empty type that will be filled in later. - We should only be called after calling lookup_utype() to verify that - there is not currently a type registered for DIE_REF. + We should only be called after calling lookup_utype() to verify that + there is not currently a type registered for DIE_REF. */ static struct type * @@ -674,28 +883,24 @@ alloc_utype (die_ref, utypep) { struct type **typep; int utypeidx; - + utypeidx = (die_ref - dbroff) / 4; 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; } @@ -704,19 +909,46 @@ alloc_utype (die_ref, utypep) /* -LOCAL FUNCTION + LOCAL FUNCTION - decode_die_type -- return a type for a specified die + free_utypes -- free the utypes array and reset pointer & count -SYNOPSIS + SYNOPSIS - static struct type *decode_die_type (struct dieinfo *dip) + static void free_utypes (PTR dummy) -DESCRIPTION + DESCRIPTION - Given a pointer to a die information structure DIP, decode the - type of the die and return a pointer to the decoded type. All - dies without specific types default to type int. + 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 + + decode_die_type -- return a type for a specified die + + SYNOPSIS + + static struct type *decode_die_type (struct dieinfo *dip) + + DESCRIPTION + + Given a pointer to a die information structure DIP, decode the + type of the die and return a pointer to the decoded type. All + dies without specific types default to type int. */ static struct type * @@ -724,51 +956,51 @@ decode_die_type (dip) struct dieinfo *dip; { struct type *type = NULL; - - if (dip -> at_fund_type != 0) + + if (dip->at_fund_type != 0) { - type = decode_fund_type (dip -> at_fund_type); + type = decode_fund_type (dip->at_fund_type); } - else if (dip -> at_mod_fund_type != NULL) + else if (dip->at_mod_fund_type != NULL) { - type = decode_mod_fund_type (dip -> at_mod_fund_type); + type = decode_mod_fund_type (dip->at_mod_fund_type); } - else if (dip -> at_user_def_type) + else if (dip->at_user_def_type) { - if ((type = lookup_utype (dip -> at_user_def_type)) == NULL) + if ((type = lookup_utype (dip->at_user_def_type)) == NULL) { - type = alloc_utype (dip -> at_user_def_type, NULL); + type = alloc_utype (dip->at_user_def_type, NULL); } } - else if (dip -> at_mod_u_d_type) + else if (dip->at_mod_u_d_type) { - type = decode_mod_u_d_type (dip -> at_mod_u_d_type); + type = decode_mod_u_d_type (dip->at_mod_u_d_type); } else { - type = lookup_fundamental_type (current_objfile, FT_INTEGER); + type = dwarf_fundamental_type (current_objfile, FT_VOID); } return (type); } /* -LOCAL FUNCTION + LOCAL FUNCTION - struct_type -- compute and return the type for a struct or union + struct_type -- compute and return the type for a struct or union -SYNOPSIS + SYNOPSIS - static struct type *struct_type (struct dieinfo *dip, char *thisdie, - char *enddie, struct objfile *objfile) + static struct type *struct_type (struct dieinfo *dip, char *thisdie, + char *enddie, struct objfile *objfile) -DESCRIPTION + DESCRIPTION - Given pointer to a die information structure for a die which - defines a union or structure (and MUST define one or the other), - and pointers to the raw die data that define the range of dies which - define the members, compute and return the user defined type for the - structure or union. + Given pointer to a die information structure for a die which + defines a union or structure (and MUST define one or the other), + and pointers to the raw die data that define the range of dies which + define the members, compute and return the user defined type for the + structure or union. */ static struct type * @@ -779,56 +1011,59 @@ struct_type (dip, thisdie, enddie, objfile) struct objfile *objfile; { struct type *type; - struct nextfield { - struct nextfield *next; - struct field field; - }; + struct nextfield + { + struct nextfield *next; + struct field field; + }; struct nextfield *list = NULL; struct nextfield *new; int nfields = 0; int n; - char *tpart1; struct dieinfo mbr; char *nextdie; - - if ((type = lookup_utype (dip -> die_ref)) == NULL) + int anonymous_size; + + if ((type = lookup_utype (dip->die_ref)) == NULL) { /* No forward references created an empty type, so install one now */ - type = alloc_utype (dip -> die_ref, NULL); + type = alloc_utype (dip->die_ref, NULL); } - INIT_CPLUS_SPECIFIC(type); - switch (dip -> die_tag) + INIT_CPLUS_SPECIFIC (type); + switch (dip->die_tag) { - 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")); - break; + case TAG_class_type: + TYPE_CODE (type) = TYPE_CODE_CLASS; + break; + case TAG_structure_type: + TYPE_CODE (type) = TYPE_CODE_STRUCT; + break; + case TAG_union_type: + TYPE_CODE (type) = TYPE_CODE_UNION; + break; + default: + /* Should never happen */ + TYPE_CODE (type) = TYPE_CODE_UNDEF; + complain (&missing_tag, DIE_ID, DIE_NAME); + break; } /* Some compilers try to be helpful by inventing "fake" names for anonymous enums, structures, and unions, like "~0fake" or ".0fake". Thanks, but no thanks... */ - if (dip -> at_name != NULL - && *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; - } - thisdie += dip -> die_length; + if (dip->at_name != NULL + && *dip->at_name != '~' + && *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 + 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) { basicdieinfo (&mbr, thisdie, objfile); @@ -850,33 +1085,57 @@ struct_type (dip, thisdie, enddie, objfile) case TAG_member: /* Get space to record the next field's data. */ new = (struct nextfield *) alloca (sizeof (struct nextfield)); - new -> next = list; + new->next = list; list = new; /* Save the data. */ - list -> field.name = savestring (mbr.at_name, strlen (mbr.at_name)); - list -> field.type = decode_die_type (&mbr); - list -> field.bitpos = 8 * locval (mbr.at_location); + list->field.name = + obsavestring (mbr.at_name, strlen (mbr.at_name), + &objfile->type_obstack); + FIELD_TYPE (list->field) = decode_die_type (&mbr); + FIELD_BITPOS (list->field) = 8 * locval (&mbr); /* 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) + FIELD_BITSIZE (list->field) = mbr.at_bit_size; + if (BITS_BIG_ENDIAN) { - list -> field.bitpos += - mbr.at_byte_size * 8 - mbr.at_bit_offset - mbr.at_bit_size; + /* 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. */ + FIELD_BITPOS (list->field) += 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); + } + FIELD_BITPOS (list->field) += + anonymous_size * 8 - mbr.at_bit_offset - mbr.at_bit_size; + } } -#endif nfields++; break; default: @@ -898,49 +1157,48 @@ 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) + for (n = nfields; list; list = list->next) { - TYPE_FIELD (type, --n) = list -> field; - } + TYPE_FIELD (type, --n) = list->field; + } } return (type); } /* -LOCAL FUNCTION + LOCAL FUNCTION - read_structure_scope -- process all dies within struct or union + read_structure_scope -- process all dies within struct or union -SYNOPSIS + SYNOPSIS - static void read_structure_scope (struct dieinfo *dip, - char *thisdie, char *enddie, struct objfile *objfile) + static void read_structure_scope (struct dieinfo *dip, + char *thisdie, char *enddie, struct objfile *objfile) -DESCRIPTION + DESCRIPTION - Called when we find the DIE that starts a structure or union - scope (definition) to process all dies that define the members - of the structure or union. DIP is a pointer to the die info - struct for the DIE that names the structure or union. + Called when we find the DIE that starts a structure or union + scope (definition) to process all dies that define the members + of the structure or union. DIP is a pointer to the die info + struct for the DIE that names the structure or union. -NOTES + NOTES + + Note that we need to call struct_type regardless of whether or not + the DIE has an at_name attribute, since it might be an anonymous + structure or union. This gets the type entered into our set of + user defined types. + + However, if the structure is incomplete (an opaque struct/union) + then suppress creating a symbol table entry for it since gdb only + wants to find the one with the complete definition. Note that if + it is complete, we just call new_symbol, which does it's own + checking about whether the struct/union is anonymous or not (and + suppresses creating a symbol table entry itself). - Note that we need to call struct_type regardless of whether or not - the DIE has an at_name attribute, since it might be an anonymous - structure or union. This gets the type entered into our set of - user defined types. - - However, if the structure is incomplete (an opaque struct/union) - then suppress creating a symbol table entry for it since gdb only - wants to find the one with the complete definition. Note that if - it is complete, we just call new_symbol, which does it's own - checking about whether the struct/union is anonymous or not (and - suppresses creating a symbol table entry itself). - */ static void @@ -952,34 +1210,39 @@ read_structure_scope (dip, thisdie, enddie, objfile) { struct type *type; struct symbol *sym; - + 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); + } } } } /* -LOCAL FUNCTION + LOCAL FUNCTION - decode_array_element_type -- decode type of the array elements + decode_array_element_type -- decode type of the array elements -SYNOPSIS + SYNOPSIS - static struct type *decode_array_element_type (char *scan, char *end) + static struct type *decode_array_element_type (char *scan, char *end) -DESCRIPTION + DESCRIPTION - As the last step in decoding the array subscript information for an - array DIE, we need to decode the type of the array elements. We are - passed a pointer to this last part of the subscript information and - must return the appropriate type. If the type attribute is not - recognized, just warn about the problem and return type int. + As the last step in decoding the array subscript information for an + array DIE, we need to decode the type of the array elements. We are + passed a pointer to this last part of the subscript information and + must return the appropriate type. If the type attribute is not + recognized, just warn about the problem and return type int. */ static struct type * @@ -991,92 +1254,107 @@ decode_array_element_type (scan) unsigned short attribute; unsigned short fundtype; int nbytes; - + attribute = target_to_host (scan, SIZEOF_ATTRIBUTE, GET_UNSIGNED, current_objfile); 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 { switch (attribute) { - case AT_fund_type: - fundtype = target_to_host (scan, nbytes, GET_UNSIGNED, - current_objfile); - typep = decode_fund_type (fundtype); - break; - case AT_mod_fund_type: - typep = decode_mod_fund_type (scan); - break; - case AT_user_def_type: - die_ref = target_to_host (scan, nbytes, GET_UNSIGNED, - current_objfile); - if ((typep = lookup_utype (die_ref)) == NULL) - { - typep = alloc_utype (die_ref, NULL); - } - break; - case AT_mod_u_d_type: - 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); - break; - } + case AT_fund_type: + fundtype = target_to_host (scan, nbytes, GET_UNSIGNED, + current_objfile); + typep = decode_fund_type (fundtype); + break; + case AT_mod_fund_type: + typep = decode_mod_fund_type (scan); + break; + case AT_user_def_type: + die_ref = target_to_host (scan, nbytes, GET_UNSIGNED, + current_objfile); + if ((typep = lookup_utype (die_ref)) == NULL) + { + typep = alloc_utype (die_ref, NULL); + } + break; + case AT_mod_u_d_type: + typep = decode_mod_u_d_type (scan); + break; + default: + complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute); + typep = dwarf_fundamental_type (current_objfile, FT_INTEGER); + break; + } } return (typep); } /* -LOCAL FUNCTION + LOCAL FUNCTION - decode_subscr_data -- decode array subscript and element type data + decode_subscript_data_item -- decode array subscript item -SYNOPSIS + SYNOPSIS - static struct type *decode_subscr_data (char *scan, char *end) + static struct type * + decode_subscript_data_item (char *scan, char *end) -DESCRIPTION + DESCRIPTION - The array subscripts and the data type of the elements of an - array are described by a list of data items, stored as a block - of contiguous bytes. There is a data item describing each array - dimension, and a final data item describing the element type. - The data items are ordered the same as their appearance in the - source (I.E. leftmost dimension first, next to leftmost second, - etc). + The array subscripts and the data type of the elements of an + array are described by a list of data items, stored as a block + of contiguous bytes. There is a data item describing each array + dimension, and a final data item describing the element type. + The data items are ordered the same as their appearance in the + source (I.E. leftmost dimension first, next to leftmost second, + etc). - 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. + 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. -BUGS - FIXME: This code only implements the forms currently used - by the AT&T and GNU C compilers. + The last data item is the description of the type of each of + the array elements. - The end pointer is supplied for error checking, maybe we should - use it for that... + We are passed a pointer to the start of the block of bytes + 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 + by the AT&T and GNU C compilers. + + The end pointer is supplied for error checking, maybe we should + use it for that... */ 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; unsigned long highbound; int nbytes; - + format = target_to_host (scan, SIZEOF_FORMAT_SPECIFIER, GET_UNSIGNED, current_objfile); scan += SIZEOF_FORMAT_SPECIFIER; @@ -1088,36 +1366,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: @@ -1126,10 +1391,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); @@ -1137,18 +1408,18 @@ decode_subscr_data (scan, end) /* -LOCAL FUNCTION + LOCAL FUNCTION - dwarf_read_array_type -- read TAG_array_type DIE + dwarf_read_array_type -- read TAG_array_type DIE -SYNOPSIS + SYNOPSIS - static void dwarf_read_array_type (struct dieinfo *dip) + static void dwarf_read_array_type (struct dieinfo *dip) -DESCRIPTION + DESCRIPTION - Extract all information from a TAG_array_type DIE and add to - the user defined type vector. + Extract all information from a TAG_array_type DIE and add to + the user defined type vector. */ static void @@ -1161,60 +1432,59 @@ dwarf_read_array_type (dip) char *subend; unsigned short blocksz; int nbytes; - - if (dip -> at_ordering != ORD_row_major) + + 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) + if ((sub = dip->at_subscr_data) != NULL) { nbytes = attribute_size (AT_subscr_data); 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); } } } /* -LOCAL FUNCTION + LOCAL FUNCTION - read_tag_pointer_type -- read TAG_pointer_type DIE + read_tag_pointer_type -- read TAG_pointer_type DIE -SYNOPSIS + SYNOPSIS - static void read_tag_pointer_type (struct dieinfo *dip) + static void read_tag_pointer_type (struct dieinfo *dip) -DESCRIPTION + DESCRIPTION - Extract all information from a TAG_pointer_type DIE and add to - the user defined type vector. + Extract all information from a TAG_pointer_type DIE and add to + the user defined type vector. */ static void @@ -1223,12 +1493,12 @@ read_tag_pointer_type (dip) { struct type *type; struct type *utype; - + type = decode_die_type (dip); - if ((utype = lookup_utype (dip -> die_ref)) == NULL) + 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 { @@ -1236,39 +1506,100 @@ read_tag_pointer_type (dip) TYPE_POINTER_TYPE (type) = utype; /* We assume the machine has only one representation for pointers! */ - /* FIXME: This confuses host<->target data representations, and is a - poor assumption besides. */ - - TYPE_LENGTH (utype) = sizeof (char *); + /* FIXME: Possably a poor assumption */ + TYPE_LENGTH (utype) = TARGET_PTR_BIT / TARGET_CHAR_BIT; TYPE_CODE (utype) = TYPE_CODE_PTR; } } /* -LOCAL FUNCTION + LOCAL FUNCTION - read_subroutine_type -- process TAG_subroutine_type dies + read_tag_string_type -- read TAG_string_type DIE -SYNOPSIS + SYNOPSIS - static void read_subroutine_type (struct dieinfo *dip, char thisdie, - char *enddie) + static void read_tag_string_type (struct dieinfo *dip) -DESCRIPTION + DESCRIPTION - Handle DIES due to C code like: + 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. + */ - struct foo { - int (*funcp)(int a, long l); (Generates TAG_subroutine_type DIE) - int b; - }; +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; -NOTES + 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); - The parameter DIES are currently ignored. See if gdb has a way to - include this info in it's type system, and decode them if so. Is - this what the type structure's "arg_types" field is for? (FIXME) + 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 + + SYNOPSIS + + static void read_subroutine_type (struct dieinfo *dip, char thisdie, + char *enddie) + + DESCRIPTION + + Handle DIES due to C code like: + + struct foo { + int (*funcp)(int a, long l); (Generates TAG_subroutine_type DIE) + int b; + }; + + NOTES + + The parameter DIES are currently ignored. See if gdb has a way to + include this info in it's type system, and decode them if so. Is + this what the type structure's "arg_types" field is for? (FIXME) */ static void @@ -1279,7 +1610,7 @@ read_subroutine_type (dip, thisdie, enddie) { struct type *type; /* Type that this function returns */ struct type *ftype; /* Function that returns above type */ - + /* Decode the type that this subroutine returns */ type = decode_die_type (dip); @@ -1287,45 +1618,48 @@ read_subroutine_type (dip, thisdie, enddie) /* Check to see if we already have a partially constructed user defined type for this DIE, from a forward reference. */ - if ((ftype = lookup_utype (dip -> die_ref)) == NULL) + if ((ftype = lookup_utype (dip->die_ref)) == NULL) { /* This is the first reference to one of these types. Make - a new one and place it in the user defined types. */ + 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. */ + 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); + } } /* -LOCAL FUNCTION + LOCAL FUNCTION - read_enumeration -- process dies which define an enumeration + read_enumeration -- process dies which define an enumeration -SYNOPSIS + SYNOPSIS - static void read_enumeration (struct dieinfo *dip, char *thisdie, - char *enddie, struct objfile *objfile) + static void read_enumeration (struct dieinfo *dip, char *thisdie, + char *enddie, struct objfile *objfile) -DESCRIPTION + DESCRIPTION - Given a pointer to a die which begins an enumeration, process all - the dies that define the members of the enumeration. + Given a pointer to a die which begins an enumeration, process all + the dies that define the members of the enumeration. -NOTES + NOTES - Note that we need to call enum_type regardless of whether or not we - have a symbol, since we might have an enum without a tag name (thus - no symbol for the tagname). + Note that we need to call enum_type regardless of whether or not we + have a symbol, since we might have an enum without a tag name (thus + no symbol for the tagname). */ static void @@ -1337,43 +1671,48 @@ read_enumeration (dip, thisdie, enddie, objfile) { struct type *type; struct symbol *sym; - + type = enum_type (dip, objfile); - if ((sym = new_symbol (dip, objfile)) != NULL) + sym = new_symbol (dip, objfile); + if (sym != NULL) { SYMBOL_TYPE (sym) = type; + if (cu_language == language_cplus) + { + synthesize_typedef (dip, objfile, type); + } } } /* -LOCAL FUNCTION + LOCAL FUNCTION - enum_type -- decode and return a type for an enumeration + enum_type -- decode and return a type for an enumeration -SYNOPSIS + SYNOPSIS - static type *enum_type (struct dieinfo *dip, struct objfile *objfile) + static type *enum_type (struct dieinfo *dip, struct objfile *objfile) -DESCRIPTION + DESCRIPTION - Given a pointer to a die information structure for the die which - starts an enumeration, process all the dies that define the members - of the enumeration and return a type pointer for the enumeration. + Given a pointer to a die information structure for the die which + starts an enumeration, process all the dies that define the members + of the enumeration and return a type pointer for the enumeration. - At the same time, for each member of the enumeration, create a - symbol for it with namespace VAR_NAMESPACE and class LOC_CONST, - and give it the type of the enumeration itself. + At the same time, for each member of the enumeration, create a + symbol for it with namespace VAR_NAMESPACE and class LOC_CONST, + and give it the type of the enumeration itself. -NOTES + NOTES - Note that the DWARF specification explicitly mandates that enum - constants occur in reverse order from the source program order, - for "consistency" and because this ordering is easier for many - compilers to generate. (Draft 6, sec 3.8.5, Enumeration type - Entries). Because gdb wants to see the enum members in program - source order, we have to ensure that the order gets reversed while - we are processing them. + Note that the DWARF specification explicitly mandates that enum + constants occur in reverse order from the source program order, + for "consistency" and because this ordering is easier for many + compilers to generate. (Draft 6, sec 3.8.5, Enumeration type + Entries). Because gdb wants to see the enum members in program + source order, we have to ensure that the order gets reversed while + we are processing them. */ static struct type * @@ -1382,10 +1721,11 @@ enum_type (dip, objfile) struct objfile *objfile; { struct type *type; - struct nextfield { - struct nextfield *next; - struct field field; - }; + struct nextfield + { + struct nextfield *next; + struct field field; + }; struct nextfield *list = NULL; struct nextfield *new; int nfields = 0; @@ -1395,30 +1735,31 @@ enum_type (dip, objfile) unsigned short blocksz; struct symbol *sym; int nbytes; - - if ((type = lookup_utype (dip -> die_ref)) == NULL) + int unsigned_enum = 1; + + if ((type = lookup_utype (dip->die_ref)) == NULL) { /* No forward references created an empty type, so install one now */ - type = alloc_utype (dip -> die_ref, NULL); + type = alloc_utype (dip->die_ref, NULL); } TYPE_CODE (type) = TYPE_CODE_ENUM; /* Some compilers try to be helpful by inventing "fake" names for anonymous enums, structures, and unions, like "~0fake" or ".0fake". Thanks, but no thanks... */ - if (dip -> at_name != NULL - && *dip -> at_name != '~' - && *dip -> at_name != '.') + if (dip->at_name != NULL + && *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) + if (dip->at_byte_size != 0) { - TYPE_LENGTH (type) = dip -> at_byte_size; + TYPE_LENGTH (type) = dip->at_byte_size; } - if ((scan = dip -> at_element_list) != NULL) + if ((scan = dip->at_element_list) != NULL) { - if (dip -> short_element_list) + if (dip->short_element_list) { nbytes = attribute_size (AT_short_element_list); } @@ -1432,44 +1773,50 @@ enum_type (dip, objfile) while (scan < listend) { new = (struct nextfield *) alloca (sizeof (struct nextfield)); - new -> next = list; + new->next = list; list = new; - list -> field.type = NULL; - list -> field.bitsize = 0; - list -> field.bitpos = + FIELD_TYPE (list->field) = NULL; + FIELD_BITSIZE (list->field) = 0; + FIELD_BITPOS (list->field) = 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)); - SYMBOL_NAME (sym) = create_name (list -> field.name, + 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; + SYMBOL_VALUE (sym) = FIELD_BITPOS (list->field); + 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 - reverse order from how they were inserted. If we have no fields - (this is apparently possible in C++) then skip building a field - vector. */ + 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); /* Copy the saved-up fields into the field vector. */ - for (n = 0; (n < nfields) && (list != NULL); list = list -> next) + for (n = 0; (n < nfields) && (list != NULL); list = list->next) { - TYPE_FIELD (type, n++) = list -> field; - } + TYPE_FIELD (type, n++) = list->field; + } } } return (type); @@ -1477,23 +1824,23 @@ enum_type (dip, objfile) /* -LOCAL FUNCTION + LOCAL FUNCTION - read_func_scope -- process all dies within a function scope + read_func_scope -- process all dies within a function scope -DESCRIPTION + DESCRIPTION + + Process all dies within a given function scope. We are passed + a die information structure pointer DIP for the die which + starts the function scope, and pointers into the raw die data + that define the dies within the function scope. - Process all dies within a given function scope. We are passed - a die information structure pointer DIP for the die which - starts the function scope, and pointers into the raw die data - that define the dies within the function scope. - - For now, we ignore lexical block scopes within the function. - The problem is that AT&T cc does not define a DWARF lexical - block scope for the function itself, while gcc defines a - lexical block scope for the function. We need to think about - how to handle this difference, or if it is even a problem. - (FIXME) + For now, we ignore lexical block scopes within the function. + The problem is that AT&T cc does not define a DWARF lexical + block scope for the function itself, while gcc defines a + lexical block scope for the function. We need to think about + how to handle this difference, or if it is even a problem. + (FIXME) */ static void @@ -1504,49 +1851,112 @@ read_func_scope (dip, thisdie, enddie, objfile) struct objfile *objfile; { register struct context_stack *new; - - if (objfile -> ei.entry_point >= dip -> at_low_pc && - objfile -> ei.entry_point < dip -> at_high_pc) + + /* 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) { - objfile -> ei.entry_func_lowpc = dip -> at_low_pc; - objfile -> ei.entry_func_highpc = dip -> at_high_pc; + objfile->ei.entry_func_lowpc = dip->at_low_pc; + objfile->ei.entry_func_highpc = dip->at_high_pc; } - if (STREQ (dip -> at_name, "main")) /* FIXME: hardwired name */ + if (STREQ (dip->at_name, "main")) /* FIXME: hardwired name */ { - objfile -> ei.main_func_lowpc = dip -> at_low_pc; - objfile -> ei.main_func_highpc = dip -> at_high_pc; + objfile->ei.main_func_lowpc = dip->at_low_pc; + objfile->ei.main_func_highpc = dip->at_high_pc; } - new = push_context (0, dip -> at_low_pc); - new -> name = new_symbol (dip, objfile); + new = push_context (0, dip->at_low_pc); + new->name = new_symbol (dip, objfile); list_in_scope = &local_symbols; - process_dies (thisdie + dip -> die_length, enddie, objfile); + process_dies (thisdie + dip->die_length, enddie, objfile); new = pop_context (); /* Make a block for the local symbols within. */ - finish_block (new -> name, &local_symbols, new -> old_blocks, - new -> start_addr, dip -> at_high_pc, objfile); + finish_block (new->name, &local_symbols, new->old_blocks, + new->start_addr, dip->at_high_pc, objfile); list_in_scope = &file_symbols; } + /* -LOCAL FUNCTION + LOCAL FUNCTION - read_file_scope -- process all dies within a file scope + 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. */ + + if (STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER))) + { + char version = producer[strlen (GCC_PRODUCER)]; + processing_gcc_compilation = (version == '2' ? 2 : 1); + } + else + { + processing_gcc_compilation = + STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)) + || STREQN (producer, CHILL_PRODUCER, strlen (CHILL_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); + } + } +} -DESCRIPTION - Process all dies within a given file scope. We are passed a - pointer to the die information structure for the die which - starts the file scope, and pointers into the raw die data which - mark the range of dies within the file scope. - - When the partial symbol table is built, the file offset for the line - number table for each compilation unit is saved in the partial symbol - table entry for that compilation unit. As the symbols for each - compilation unit are read, the line number table is read into memory - and the variable lnbase is set to point to it. Thus all we have to - do is use lnbase to access the line number table for the current - compilation unit. +/* + + LOCAL FUNCTION + + read_file_scope -- process all dies within a file scope + + DESCRIPTION + + Process all dies within a given file scope. We are passed a + pointer to the die information structure for the die which + starts the file scope, and pointers into the raw die data which + mark the range of dies within the file scope. + + When the partial symbol table is built, the file offset for the line + number table for each compilation unit is saved in the partial symbol + table entry for that compilation unit. As the symbols for each + compilation unit are read, the line number table is read into memory + and the variable lnbase is set to point to it. Thus all we have to + do is use lnbase to access the line number table for the current + compilation unit. */ static void @@ -1558,59 +1968,51 @@ read_file_scope (dip, thisdie, enddie, objfile) { struct cleanup *back_to; struct symtab *symtab; - - if (objfile -> ei.entry_point >= dip -> at_low_pc && - objfile -> ei.entry_point < dip -> at_high_pc) + + if (objfile->ei.entry_point >= dip->at_low_pc && + objfile->ei.entry_point < dip->at_high_pc) { - objfile -> ei.entry_file_lowpc = dip -> at_low_pc; - objfile -> ei.entry_file_highpc = dip -> at_high_pc; + objfile->ei.entry_file_lowpc = dip->at_low_pc; + objfile->ei.entry_file_highpc = dip->at_high_pc; } - if (dip -> at_producer != NULL) + 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); + record_debugformat ("DWARF 1"); 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) - { - case LANG_C89: - case LANG_C: - symtab -> language = language_c; - break; - case LANG_C_PLUS_PLUS: - symtab -> language = language_cplus; - break; - default: - ; + process_dies (thisdie + dip->die_length, enddie, objfile); + + symtab = end_symtab (dip->at_high_pc, objfile, 0); + if (symtab != NULL) + { + symtab->language = cu_language; } do_cleanups (back_to); - utypes = NULL; - numutypes = 0; } /* -LOCAL FUNCTION + LOCAL FUNCTION - process_dies -- process a range of DWARF Information Entries + process_dies -- process a range of DWARF Information Entries -SYNOPSIS + SYNOPSIS - static void process_dies (char *thisdie, char *enddie, - struct objfile *objfile) + static void process_dies (char *thisdie, char *enddie, + struct objfile *objfile) -DESCRIPTION + DESCRIPTION - Process all DIE's in a specified range. May be (and almost - certainly will be) called recursively. + Process all DIE's in a specified range. May be (and almost + certainly will be) called recursively. */ static void @@ -1621,7 +2023,7 @@ process_dies (thisdie, enddie, objfile) { char *nextdie; struct dieinfo di; - + while (thisdie < enddie) { basicdieinfo (&di, thisdie, objfile); @@ -1644,10 +2046,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: @@ -1659,6 +2072,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); @@ -1675,8 +2089,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; } } @@ -1686,62 +2103,62 @@ process_dies (thisdie, enddie, objfile) /* -LOCAL FUNCTION + LOCAL FUNCTION - decode_line_numbers -- decode a line number table fragment + decode_line_numbers -- decode a line number table fragment -SYNOPSIS + SYNOPSIS - static void decode_line_numbers (char *tblscan, char *tblend, - long length, long base, long line, long pc) + static void decode_line_numbers (char *tblscan, char *tblend, + long length, long base, long line, long pc) -DESCRIPTION + DESCRIPTION - Translate the DWARF line number information to gdb form. + Translate the DWARF line number information to gdb form. - The ".line" section contains one or more line number tables, one for - each ".line" section from the objects that were linked. + The ".line" section contains one or more line number tables, one for + each ".line" section from the objects that were linked. - The AT_stmt_list attribute for each TAG_source_file entry in the - ".debug" section contains the offset into the ".line" section for the - start of the table for that file. + The AT_stmt_list attribute for each TAG_source_file entry in the + ".debug" section contains the offset into the ".line" section for the + start of the table for that file. - The table itself has the following structure: + The table itself has the following structure: - - 4 bytes 4 bytes 10 bytes +
+ 4 bytes 4 bytes 10 bytes - The table length is the total size of the table, including the 4 bytes - for the length information. + The table length is the total size of the table, including the 4 bytes + for the length information. - The base address is the address of the first instruction generated - for the source file. + The base address is the address of the first instruction generated + for the source file. - Each source statement entry has the following structure: + Each source statement entry has the following structure: -
- 4 bytes 2 bytes 4 bytes +
+ 4 bytes 2 bytes 4 bytes - The line number is relative to the start of the file, starting with - line 1. + The line number is relative to the start of the file, starting with + line 1. - The statement position either -1 (0xFFFF) or the number of characters - from the beginning of the line to the beginning of the statement. + The statement position either -1 (0xFFFF) or the number of characters + from the beginning of the line to the beginning of the statement. - The address delta is the difference between the base address and - the address of the first instruction for the statement. + The address delta is the difference between the base address and + the address of the first instruction for the statement. - Note that we must copy the bytes from the packed table to our local - variables before attempting to use them, to avoid alignment problems - on some machines, particularly RISC processors. + Note that we must copy the bytes from the packed table to our local + variables before attempting to use them, to avoid alignment problems + on some machines, particularly RISC processors. -BUGS + BUGS - Does gdb expect the line numbers to be sorted? They are now by - chance/luck, but are not required to be. (FIXME) + Does gdb expect the line numbers to be sorted? They are now by + chance/luck, but are not required to be. (FIXME) - The line with number 0 is unused, gdb apparently can discover the - span of the last line some other way. How? (FIXME) + The line with number 0 is unused, gdb apparently can discover the + span of the last line some other way. How? (FIXME) */ static void @@ -1754,7 +2171,7 @@ decode_line_numbers (linetable) unsigned long base; unsigned long line; unsigned long pc; - + if (linetable != NULL) { tblscan = tblend = linetable; @@ -1785,116 +2202,117 @@ decode_line_numbers (linetable) /* -LOCAL FUNCTION + LOCAL FUNCTION - locval -- compute the value of a location attribute + locval -- compute the value of a location attribute -SYNOPSIS + SYNOPSIS - static int locval (char *loc) + static int locval (struct dieinfo *dip) -DESCRIPTION + DESCRIPTION - Given pointer to a string of bytes that define a location, compute - the location and return the value. + 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 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 - pointer, rather than the absolute value. This is what GDB wants - anyway. - - When the result is a register number, the global isreg flag is set, - otherwise it is cleared. This is a kludge until we figure out a better - way to handle the problem. Gdb's design does not mesh well with the - DWARF notion of a location computing interpreter, which is a shame - because the flexibility goes unused. + 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 + pointer, rather than the absolute value. This is what GDB wants + anyway. -NOTES + When the result is a register number, the isreg flag is set, otherwise + it is cleared. This is a kludge until we figure out a better + way to handle the problem. Gdb's design does not mesh well with the + DWARF notion of a location computing interpreter, which is a shame + because the flexibility goes unused. - Note that stack[0] is unused except as a default error return. - Note that stack overflow is not yet handled. + NOTES + + Note that stack[0] is unused except as a default error return. + Note that stack overflow is not yet handled. */ static int -locval (loc) - char *loc; +locval (dip) + struct dieinfo *dip; { unsigned short nbytes; unsigned short locsize; auto long stack[64]; int stacki; + char *loc; char *end; - long regno; int loc_atom_code; int loc_value_size; - + + loc = dip->at_location; nbytes = attribute_size (AT_location); locsize = target_to_host (loc, nbytes, GET_UNSIGNED, current_objfile); loc += nbytes; end = loc + locsize; stacki = 0; stack[stacki] = 0; - isreg = 0; - offreg = 0; + dip->isreg = 0; + dip->offreg = 0; + dip->optimized_out = 1; loc_value_size = TARGET_FT_LONG_SIZE (current_objfile); while (loc < end) { + dip->optimized_out = 0; loc_atom_code = target_to_host (loc, SIZEOF_LOC_ATOM_CODE, GET_UNSIGNED, current_objfile); loc += SIZEOF_LOC_ATOM_CODE; switch (loc_atom_code) { - case 0: - /* error */ - loc = end; - break; - case OP_REG: - /* push register (number) */ - stack[++stacki] = 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 */ - offreg = 1; - regno = 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)); - } - break; - case OP_ADDR: - /* push address (relocated address) */ - stack[++stacki] = target_to_host (loc, loc_value_size, - GET_UNSIGNED, current_objfile); - loc += loc_value_size; - break; - case OP_CONST: - /* push constant (number) FIXME: signed or unsigned! */ - stack[++stacki] = target_to_host (loc, loc_value_size, - GET_SIGNED, current_objfile); - loc += loc_value_size; - break; - case OP_DEREF2: - /* pop, deref and push 2 bytes (as a long) */ - SQUAWK (("OP_DEREF2 address 0x%x not handled", 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])); - break; - case OP_ADD: /* pop top 2 items, add, push result */ - stack[stacki - 1] += stack[stacki]; - stacki--; - break; + case 0: + /* error */ + loc = end; + break; + case OP_REG: + /* push register (number) */ + stack[++stacki] + = DWARF_REG_TO_REGNUM (target_to_host (loc, loc_value_size, + GET_UNSIGNED, + current_objfile)); + loc += loc_value_size; + dip->isreg = 1; + break; + case OP_BASEREG: + /* push value of register (number) */ + /* Actually, we compute the value as if register has 0, so the + value ends up being the offset from that register. */ + dip->offreg = 1; + dip->basereg = target_to_host (loc, loc_value_size, GET_UNSIGNED, + current_objfile); + loc += loc_value_size; + stack[++stacki] = 0; + break; + case OP_ADDR: + /* push address (relocated address) */ + stack[++stacki] = target_to_host (loc, loc_value_size, + GET_UNSIGNED, current_objfile); + loc += loc_value_size; + break; + case OP_CONST: + /* push constant (number) FIXME: signed or unsigned! */ + stack[++stacki] = target_to_host (loc, loc_value_size, + GET_SIGNED, current_objfile); + loc += loc_value_size; + break; + case OP_DEREF2: + /* pop, deref and push 2 bytes (as a long) */ + complain (&op_deref2, DIE_ID, DIE_NAME, stack[stacki]); + break; + case OP_DEREF4: /* pop, deref and push 4 bytes (as a long) */ + 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]; + stacki--; + break; } } return (stack[stacki]); @@ -1902,47 +2320,48 @@ locval (loc) /* -LOCAL FUNCTION - - read_ofile_symtab -- build a full symtab entry from chunk of DIE's + LOCAL FUNCTION -SYNOPSIS + read_ofile_symtab -- build a full symtab entry from chunk of DIE's - static struct symtab *read_ofile_symtab (struct partial_symtab *pst) + SYNOPSIS -DESCRIPTION + static void read_ofile_symtab (struct partial_symtab *pst) - 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. + DESCRIPTION - Returns a pointer to the newly constructed symtab (which is now - the new first one on the objfile's symtab list). + 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. 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]; - abfd = pst -> objfile -> obfd; - current_objfile = pst -> objfile; + abfd = pst->objfile->obfd; + current_objfile = pst->objfile; /* Allocate a buffer for the entire chunk of DIE's for this compilation unit, seek to the location in the file, and read in all the DIE's. */ diecount = 0; - dbbase = xmalloc (DBLENGTH(pst)); - 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))) + 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, SEEK_SET) || + (bfd_read (dbbase, dbsize, 1, abfd) != dbsize)) { free (dbbase); error ("can't read DWARF data"); @@ -1957,16 +2376,16 @@ 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))) { error ("can't read DWARF line number table size"); } lnsize = target_to_host (lnsizedata, SIZEOF_LINETBL_LENGTH, - GET_UNSIGNED, pst -> objfile); + 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); @@ -1975,97 +2394,101 @@ 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; } /* -LOCAL FUNCTION + LOCAL FUNCTION - psymtab_to_symtab_1 -- do grunt work for building a full symtab entry + psymtab_to_symtab_1 -- do grunt work for building a full symtab entry -SYNOPSIS + SYNOPSIS - static void psymtab_to_symtab_1 (struct partial_symtab *pst) + static void psymtab_to_symtab_1 (struct partial_symtab *pst) -DESCRIPTION + DESCRIPTION - Called once for each partial symbol table entry that needs to be - expanded into a full symbol table entry. + Called once for each partial symbol table entry that needs to be + expanded into a full symbol table entry. -*/ + */ static void psymtab_to_symtab_1 (pst) struct partial_symtab *pst; { int i; - + struct cleanup *old_chain; + if (pst != NULL) { if (pst->readin) { warning ("psymtab for %s already read in. Shouldn't happen.", - pst -> filename); + pst->filename); } else { /* Read in all partial symtabs on which this one is dependent */ - for (i = 0; i < pst -> number_of_dependencies; i++) + for (i = 0; i < pst->number_of_dependencies; i++) { - if (!pst -> dependencies[i] -> readin) + if (!pst->dependencies[i]->readin) { /* 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); + pst->dependencies[i]->filename); wrap_here (""); - fflush (stdout); /* Flush output */ + gdb_flush (gdb_stdout); /* Flush output */ } - psymtab_to_symtab_1 (pst -> dependencies[i]); + psymtab_to_symtab_1 (pst->dependencies[i]); } - } - if (DBLENGTH (pst)) /* Otherwise it's a dummy */ + } + 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); + sort_symtab_syms (pst->symtab); + do_cleanups (old_chain); } - pst -> readin = 1; + pst->readin = 1; } } } /* -LOCAL FUNCTION + LOCAL FUNCTION - dwarf_psymtab_to_symtab -- build a full symtab entry from partial one + dwarf_psymtab_to_symtab -- build a full symtab entry from partial one -SYNOPSIS + SYNOPSIS - static void dwarf_psymtab_to_symtab (struct partial_symtab *pst) + static void dwarf_psymtab_to_symtab (struct partial_symtab *pst) -DESCRIPTION + DESCRIPTION - This is the DWARF support entry point for building a full symbol - table entry from a partial symbol table entry. We are passed a - pointer to the partial symbol table entry that needs to be expanded. + This is the DWARF support entry point for building a full symbol + table entry from a partial symbol table entry. We are passed a + pointer to the partial symbol table entry that needs to be expanded. -*/ + */ static void dwarf_psymtab_to_symtab (pst) @@ -2074,40 +2497,40 @@ dwarf_psymtab_to_symtab (pst) if (pst != NULL) { - if (pst -> readin) + if (pst->readin) { warning ("psymtab for %s already read in. Shouldn't happen.", - pst -> filename); + pst->filename); } else { - if (DBLENGTH (pst) || pst -> number_of_dependencies) + if (DBLENGTH (pst) || pst->number_of_dependencies) { /* Print the message now, before starting serious work, to avoid - disconcerting pauses. */ + disconcerting pauses. */ if (info_verbose) { printf_filtered ("Reading in symbols for %s...", - pst -> filename); - fflush (stdout); + pst->filename); + gdb_flush (gdb_stdout); } - + psymtab_to_symtab_1 (pst); - -#if 0 /* FIXME: Check to see what dbxread is doing here and see if - we need to do an equivalent or is this something peculiar to - stabs/a.out format. - Match with global symbols. This only needs to be done once, - after all of the symtabs and dependencies have been read in. - */ - scan_file_globals (pst -> objfile); + +#if 0 /* FIXME: Check to see what dbxread is doing here and see if + we need to do an equivalent or is this something peculiar to + stabs/a.out format. + Match with global symbols. This only needs to be done once, + after all of the symtabs and dependencies have been read in. + */ + scan_file_globals (pst->objfile); #endif - + /* Finish up the verbose info message. */ if (info_verbose) { printf_filtered ("done.\n"); - fflush (stdout); + gdb_flush (gdb_stdout); } } } @@ -2116,65 +2539,17 @@ dwarf_psymtab_to_symtab (pst) /* -LOCAL FUNCTION - - init_psymbol_list -- initialize storage for partial symbols - -SYNOPSIS + LOCAL FUNCTION - static void init_psymbol_list (struct objfile *objfile, int total_symbols) + add_enum_psymbol -- add enumeration members to partial symbol table -DESCRIPTION + DESCRIPTION - Initializes storage for all of the partial symbols that will be - created by dwarf_build_psymtabs and subsidiaries. + Given pointer to a DIE that is known to be for an enumeration, + extract the symbolic names of the enumeration members and add + partial symbols for them. */ -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 - -DESCRIPTION - - Given pointer to a DIE that is known to be for an enumeration, - extract the symbolic names of the enumeration members and add - partial symbols for them. -*/ - static void add_enum_psymbol (dip, objfile) struct dieinfo *dip; @@ -2184,10 +2559,10 @@ add_enum_psymbol (dip, objfile) char *listend; unsigned short blocksz; int nbytes; - - if ((scan = dip -> at_element_list) != NULL) + + if ((scan = dip->at_element_list) != NULL) { - if (dip -> short_element_list) + if (dip->short_element_list) { nbytes = attribute_size (AT_short_element_list); } @@ -2201,8 +2576,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; } } @@ -2210,79 +2586,81 @@ add_enum_psymbol (dip, objfile) /* -LOCAL FUNCTION + LOCAL FUNCTION - add_partial_symbol -- add symbol to partial symbol table + add_partial_symbol -- add symbol to partial symbol table -DESCRIPTION + DESCRIPTION - Given a DIE, if it is one of the types that we want to - add to a partial symbol table, finish filling in the die info - and then add a partial symbol table entry for it. + Given a DIE, if it is one of the types that we want to + 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 add_partial_symbol (dip, objfile) struct dieinfo *dip; struct objfile *objfile; { - switch (dip -> die_tag) + 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), + add_psymbol_to_list (dip->at_name, strlen (dip->at_name), VAR_NAMESPACE, LOC_BLOCK, - objfile -> global_psymbols, - dip -> at_low_pc); + &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), + add_psymbol_to_list (dip->at_name, strlen (dip->at_name), VAR_NAMESPACE, LOC_BLOCK, - objfile -> static_psymbols, - dip -> at_low_pc); + &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; } } - +/* *INDENT-OFF* */ /* LOCAL FUNCTION @@ -2293,15 +2671,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 @@ -2311,6 +2724,9 @@ NOTES where the actual definition occurs, rather than just a reference to an external. */ +/* *INDENT-ON* */ + + static void scan_partial_symbols (thisdie, enddie, objfile) @@ -2319,8 +2735,9 @@ scan_partial_symbols (thisdie, enddie, objfile) struct objfile *objfile; { char *nextdie; + char *temp; struct dieinfo di; - + while (thisdie < enddie) { basicdieinfo (&di, thisdie, objfile); @@ -2337,6 +2754,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); @@ -2346,6 +2786,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); @@ -2356,7 +2797,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; } } @@ -2366,54 +2811,53 @@ scan_partial_symbols (thisdie, enddie, objfile) /* -LOCAL FUNCTION + LOCAL FUNCTION - scan_compilation_units -- build a psymtab entry for each compilation + scan_compilation_units -- build a psymtab entry for each compilation -DESCRIPTION + DESCRIPTION - This is the top level dwarf parsing routine for building partial - symbol tables. - - It scans from the beginning of the DWARF table looking for the first - TAG_compile_unit DIE, and then follows the sibling chain to locate - each additional TAG_compile_unit DIE. - - For each TAG_compile_unit DIE it creates a partial symtab structure, - calls a subordinate routine to collect all the compilation unit's - global DIE's, file scope DIEs, typedef DIEs, etc, and then links the - new partial symtab structure into the partial symbol table. It also - records the appropriate information in the partial symbol table entry - to allow the chunk of DIE's and line number table for this compilation - unit to be located and re-read later, to generate a complete symbol - table entry for the compilation unit. - - Thus it effectively partitions up a chunk of DIE's for multiple - compilation units into smaller DIE chunks and line number tables, - and associates them with a partial symbol table entry. + This is the top level dwarf parsing routine for building partial + symbol tables. -NOTES + It scans from the beginning of the DWARF table looking for the first + TAG_compile_unit DIE, and then follows the sibling chain to locate + each additional TAG_compile_unit DIE. - If any compilation unit has no line number table associated with - it for some reason (a missing at_stmt_list attribute, rather than - just one with a value of zero, which is valid) then we ensure that - the recorded file offset is zero so that the routine which later - reads line number table fragments knows that there is no fragment - to read. + For each TAG_compile_unit DIE it creates a partial symtab structure, + calls a subordinate routine to collect all the compilation unit's + global DIE's, file scope DIEs, typedef DIEs, etc, and then links the + new partial symtab structure into the partial symbol table. It also + records the appropriate information in the partial symbol table entry + to allow the chunk of DIE's and line number table for this compilation + unit to be located and re-read later, to generate a complete symbol + table entry for the compilation unit. -RETURNS + Thus it effectively partitions up a chunk of DIE's for multiple + compilation units into smaller DIE chunks and line number tables, + and associates them with a partial symbol table entry. - Returns no value. + NOTES + + If any compilation unit has no line number table associated with + it for some reason (a missing at_stmt_list attribute, rather than + just one with a value of zero, which is valid) then we ensure that + the recorded file offset is zero so that the routine which later + reads line number table fragments knows that there is no fragment + to read. + + RETURNS + + Returns no value. */ 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; @@ -2421,7 +2865,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) { @@ -2437,6 +2881,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; @@ -2451,55 +2896,55 @@ 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, - objfile -> global_psymbols.next, - objfile -> static_psymbols.next); + pst = start_psymtab_common (objfile, base_section_offsets, + di.at_name, di.at_low_pc, + objfile->global_psymbols.next, + objfile->static_psymbols.next); - pst -> texthigh = di.at_high_pc; - pst -> read_symtab_private = (char *) - obstack_alloc (&objfile -> psymbol_obstack, - sizeof (struct dwfinfo)); + pst->texthigh = di.at_high_pc; + pst->read_symtab_private = (char *) + obstack_alloc (&objfile->psymbol_obstack, + sizeof (struct dwfinfo)); DBFOFF (pst) = dbfoff; DBROFF (pst) = curoff; DBLENGTH (pst) = culength; - LNFOFF (pst) = curlnoffset; - pst -> read_symtab = dwarf_psymtab_to_symtab; + LNFOFF (pst) = curlnoffset; + pst->read_symtab = dwarf_psymtab_to_symtab; /* Now look for partial symbols */ scan_partial_symbols (thisdie + di.die_length, nextdie, objfile); - pst -> n_global_syms = objfile -> global_psymbols.next - - (objfile -> global_psymbols.list + pst -> globals_offset); - pst -> n_static_syms = objfile -> static_psymbols.next - - (objfile -> static_psymbols.list + pst -> statics_offset); + pst->n_global_syms = objfile->global_psymbols.next - + (objfile->global_psymbols.list + pst->globals_offset); + pst->n_static_syms = objfile->static_psymbols.next - + (objfile->static_psymbols.list + pst->statics_offset); sort_pst_symbols (pst); /* If there is already a psymtab or symtab for a file of this name, remove it. (If there is a symtab, more drastic things also happen.) This happens in VxWorks. */ - free_named_symtabs (pst -> filename); + free_named_symtabs (pst->filename); } - thisdie = nextdie; + thisdie = nextdie; } } /* -LOCAL FUNCTION + LOCAL FUNCTION - new_symbol -- make a symbol table entry for a new symbol + new_symbol -- make a symbol table entry for a new symbol -SYNOPSIS + SYNOPSIS - static struct symbol *new_symbol (struct dieinfo *dip, - struct objfile *objfile) + static struct symbol *new_symbol (struct dieinfo *dip, + struct objfile *objfile) -DESCRIPTION + DESCRIPTION - Given a pointer to a DWARF information entry, figure out if we need - to make a symbol table entry for it, and if so, create a new entry - and return a pointer to it. + Given a pointer to a DWARF information entry, figure out if we need + to make a symbol table entry for it, and if so, create a new entry + and return a pointer to it. */ static struct symbol * @@ -2508,29 +2953,41 @@ new_symbol (dip, objfile) struct objfile *objfile; { struct symbol *sym = NULL; - - if (dip -> at_name != NULL) + + if (dip->at_name != NULL) { - sym = (struct symbol *) obstack_alloc (&objfile -> symbol_obstack, + 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); - switch (dip -> die_tag) + + /* 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)); + if (dip->at_prototyped) + TYPE_FLAGS (SYMBOL_TYPE (sym)) |= TYPE_FLAG_PROTOTYPED; SYMBOL_CLASS (sym) = LOC_BLOCK; - if (dip -> die_tag == TAG_global_subroutine) + if (dip->die_tag == TAG_global_subroutine) { add_symbol_to_list (sym, &global_symbols); } @@ -2540,44 +2997,64 @@ new_symbol (dip, objfile) } break; case TAG_global_variable: - if (dip -> at_location != NULL) + if (dip->at_location != NULL) { - SYMBOL_VALUE (sym) = locval (dip -> at_location); + SYMBOL_VALUE_ADDRESS (sym) = locval (dip); add_symbol_to_list (sym, &global_symbols); SYMBOL_CLASS (sym) = LOC_STATIC; SYMBOL_VALUE (sym) += baseaddr; } break; case TAG_local_variable: - if (dip -> at_location != NULL) + if (dip->at_location != NULL) { - SYMBOL_VALUE (sym) = locval (dip -> at_location); - add_symbol_to_list (sym, list_in_scope); - if (isreg) + int loc = locval (dip); + if (dip->optimized_out) + { + SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; + } + else if (dip->isreg) { SYMBOL_CLASS (sym) = LOC_REGISTER; } - else if (offreg) + else if (dip->offreg) { - SYMBOL_CLASS (sym) = LOC_LOCAL; + SYMBOL_CLASS (sym) = LOC_BASEREG; + SYMBOL_BASEREG (sym) = dip->basereg; } else { SYMBOL_CLASS (sym) = LOC_STATIC; SYMBOL_VALUE (sym) += baseaddr; } + if (SYMBOL_CLASS (sym) == LOC_STATIC) + { + /* LOC_STATIC address class MUST use SYMBOL_VALUE_ADDRESS, + which may store to a bigger location than SYMBOL_VALUE. */ + SYMBOL_VALUE_ADDRESS (sym) = loc; + } + else + { + SYMBOL_VALUE (sym) = loc; + } + add_symbol_to_list (sym, list_in_scope); } break; case TAG_formal_parameter: - if (dip -> at_location != NULL) + if (dip->at_location != NULL) { - SYMBOL_VALUE (sym) = locval (dip -> at_location); + SYMBOL_VALUE (sym) = locval (dip); } add_symbol_to_list (sym, list_in_scope); - if (isreg) + if (dip->isreg) { SYMBOL_CLASS (sym) = LOC_REGPARM; } + else if (dip->offreg) + { + SYMBOL_CLASS (sym) = LOC_BASEREG_ARG; + SYMBOL_BASEREG (sym) = dip->basereg; + } else { SYMBOL_CLASS (sym) = LOC_ARG; @@ -2587,6 +3064,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: @@ -2611,26 +3089,72 @@ new_symbol (dip, objfile) /* -LOCAL FUNCTION + LOCAL FUNCTION - decode_mod_fund_type -- decode a modified fundamental type + synthesize_typedef -- make a symbol table entry for a "fake" typedef -SYNOPSIS + SYNOPSIS - static struct type *decode_mod_fund_type (char *typedata) + static void synthesize_typedef (struct dieinfo *dip, + struct objfile *objfile, + struct type *type); -DESCRIPTION + 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 + + SYNOPSIS + + static struct type *decode_mod_fund_type (char *typedata) - Decode a block of data containing a modified fundamental - type specification. TYPEDATA is a pointer to the block, - which starts with a length containing the size of the rest - of the block. At the end of the block is a fundmental type - code value that gives the fundamental type. Everything - in between are type modifiers. + DESCRIPTION - We simply compute the number of modifiers and call the general - function decode_modified_type to do the actual work. -*/ + Decode a block of data containing a modified fundamental + type specification. TYPEDATA is a pointer to the block, + which starts with a length containing the size of the rest + of the block. At the end of the block is a fundmental type + code value that gives the fundamental type. Everything + in between are type modifiers. + + We simply compute the number of modifiers and call the general + function decode_modified_type to do the actual work. + */ static struct type * decode_mod_fund_type (typedata) @@ -2639,7 +3163,7 @@ decode_mod_fund_type (typedata) struct type *typep = NULL; unsigned short modcount; int nbytes; - + /* Get the total size of the block, exclusive of the size itself */ nbytes = attribute_size (AT_mod_fund_type); @@ -2658,26 +3182,26 @@ decode_mod_fund_type (typedata) /* -LOCAL FUNCTION + LOCAL FUNCTION - decode_mod_u_d_type -- decode a modified user defined type + decode_mod_u_d_type -- decode a modified user defined type -SYNOPSIS + SYNOPSIS - static struct type *decode_mod_u_d_type (char *typedata) + static struct type *decode_mod_u_d_type (char *typedata) -DESCRIPTION + DESCRIPTION - Decode a block of data containing a modified user defined - type specification. TYPEDATA is a pointer to the block, - which consists of a two byte length, containing the size - of the rest of the block. At the end of the block is a - four byte value that gives a reference to a user defined type. - Everything in between are type modifiers. + Decode a block of data containing a modified user defined + type specification. TYPEDATA is a pointer to the block, + which consists of a two byte length, containing the size + of the rest of the block. At the end of the block is a + four byte value that gives a reference to a user defined type. + Everything in between are type modifiers. - We simply compute the number of modifiers and call the general - function decode_modified_type to do the actual work. -*/ + We simply compute the number of modifiers and call the general + function decode_modified_type to do the actual work. + */ static struct type * decode_mod_u_d_type (typedata) @@ -2686,7 +3210,7 @@ decode_mod_u_d_type (typedata) struct type *typep = NULL; unsigned short modcount; int nbytes; - + /* Get the total size of the block, exclusive of the size itself */ nbytes = attribute_size (AT_mod_u_d_type); @@ -2705,56 +3229,56 @@ decode_mod_u_d_type (typedata) /* -LOCAL FUNCTION + LOCAL FUNCTION - decode_modified_type -- decode modified user or fundamental type + decode_modified_type -- decode modified user or fundamental type -SYNOPSIS + SYNOPSIS - static struct type *decode_modified_type (unsigned char *modifiers, - unsigned short modcount, int mtype) + static struct type *decode_modified_type (char *modifiers, + unsigned short modcount, int mtype) -DESCRIPTION + DESCRIPTION - Decode a modified type, either a modified fundamental type or - a modified user defined type. MODIFIERS is a pointer to the - block of bytes that define MODCOUNT modifiers. Immediately - following the last modifier is a short containing the fundamental - type or a long containing the reference to the user defined - type. Which one is determined by MTYPE, which is either - AT_mod_fund_type or AT_mod_u_d_type to indicate what modified - type we are generating. - - We call ourself recursively to generate each modified type,` - until MODCOUNT reaches zero, at which point we have consumed - all the modifiers and generate either the fundamental type or - user defined type. When the recursion unwinds, each modifier - is applied in turn to generate the full modified type. + Decode a modified type, either a modified fundamental type or + a modified user defined type. MODIFIERS is a pointer to the + block of bytes that define MODCOUNT modifiers. Immediately + following the last modifier is a short containing the fundamental + type or a long containing the reference to the user defined + type. Which one is determined by MTYPE, which is either + AT_mod_fund_type or AT_mod_u_d_type to indicate what modified + type we are generating. -NOTES + We call ourself recursively to generate each modified type,` + until MODCOUNT reaches zero, at which point we have consumed + all the modifiers and generate either the fundamental type or + user defined type. When the recursion unwinds, each modifier + is applied in turn to generate the full modified type. - If we find a modifier that we don't recognize, and it is not one - of those reserved for application specific use, then we issue a - warning and simply ignore the modifier. + NOTES -BUGS + If we find a modifier that we don't recognize, and it is not one + of those reserved for application specific use, then we issue a + warning and simply ignore the modifier. - We currently ignore MOD_const and MOD_volatile. (FIXME) + BUGS + + We currently ignore MOD_const and MOD_volatile. (FIXME) */ 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) { switch (mtype) @@ -2775,8 +3299,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; } } @@ -2786,24 +3310,25 @@ decode_modified_type (modifiers, modcount, mtype) typep = decode_modified_type (modifiers, --modcount, mtype); switch (modifier) { - case MOD_pointer_to: - typep = lookup_pointer_type (typep); - break; - case MOD_reference_to: - typep = lookup_reference_type (typep); - break; - case MOD_const: - SQUAWK (("type modifier 'const' ignored")); /* FIXME */ - break; - case MOD_volatile: - SQUAWK (("type modifier 'volatile' ignored")); /* FIXME */ - break; - default: - if (!(MOD_lo_user <= modifier && modifier <= MOD_hi_user)) - { - SQUAWK (("unknown type modifier %u", modifier)); - } - break; + case MOD_pointer_to: + typep = lookup_pointer_type (typep); + break; + case MOD_reference_to: + typep = lookup_reference_type (typep); + break; + case MOD_const: + complain (&const_ignored, DIE_ID, DIE_NAME); /* FIXME */ + break; + case MOD_volatile: + complain (&volatile_ignored, DIE_ID, DIE_NAME); /* FIXME */ + break; + default: + if (!(MOD_lo_user <= (unsigned char) modifier + && (unsigned char) modifier <= MOD_hi_user)) + { + complain (&unknown_type_modifier, DIE_ID, DIE_NAME, modifier); + } + break; } } return (typep); @@ -2811,153 +3336,158 @@ decode_modified_type (modifiers, modcount, mtype) /* -LOCAL FUNCTION + LOCAL FUNCTION - decode_fund_type -- translate basic DWARF type to gdb base type + decode_fund_type -- translate basic DWARF type to gdb base type -DESCRIPTION + DESCRIPTION - Given an integer that is one of the fundamental DWARF types, - translate it to one of the basic internal gdb types and return - a pointer to the appropriate gdb type (a "struct type *"). + Given an integer that is one of the fundamental DWARF types, + translate it to one of the basic internal gdb types and return + a pointer to the appropriate gdb type (a "struct type *"). -NOTES + 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 * decode_fund_type (fundtype) unsigned int fundtype; { struct type *typep = NULL; - + switch (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); } /* -LOCAL FUNCTION + LOCAL FUNCTION - create_name -- allocate a fresh copy of a string on an obstack + create_name -- allocate a fresh copy of a string on an obstack -DESCRIPTION + DESCRIPTION - Given a pointer to a string and a pointer to an obstack, allocates - a fresh copy of the string on the specified obstack. + Given a pointer to a string and a pointer to an obstack, allocates + a fresh copy of the string on the specified obstack. -*/ + */ static char * create_name (name, obstackp) @@ -2969,56 +3499,62 @@ create_name (name, obstackp) length = strlen (name) + 1; newname = (char *) obstack_alloc (obstackp, length); - (void) strcpy (newname, name); + strcpy (newname, name); return (newname); } /* -LOCAL FUNCTION + LOCAL FUNCTION - basicdieinfo -- extract the minimal die info from raw die data + basicdieinfo -- extract the minimal die info from raw die data -SYNOPSIS + SYNOPSIS - void basicdieinfo (char *diep, struct dieinfo *dip, - struct objfile *objfile) + void basicdieinfo (char *diep, struct dieinfo *dip, + struct objfile *objfile) -DESCRIPTION + DESCRIPTION - Given a pointer to raw DIE data, and a pointer to an instance of a - die info structure, this function extracts the basic information - from the DIE data required to continue processing this DIE, along - with some bookkeeping information about the DIE. + Given a pointer to raw DIE data, and a pointer to an instance of a + die info structure, this function extracts the basic information + from the DIE data required to continue processing this DIE, along + with some bookkeeping information about the DIE. - The information we absolutely must have includes the DIE tag, - and the DIE length. If we need the sibling reference, then we - will have to call completedieinfo() to process all the remaining - DIE information. + The information we absolutely must have includes the DIE tag, + and the DIE length. If we need the sibling reference, then we + will have to call completedieinfo() to process all the remaining + DIE information. - Note that since there is no guarantee that the data is properly - aligned in memory for the type of access required (indirection - through anything other than a char pointer), and there is no - guarantee that it is in the same byte order as the gdb host, - we call a function which deals with both alignment and byte - swapping issues. Possibly inefficient, but quite portable. + Note that since there is no guarantee that the data is properly + aligned in memory for the type of access required (indirection + through anything other than a char pointer), and there is no + guarantee that it is in the same byte order as the gdb host, + we call a function which deals with both alignment and byte + swapping issues. Possibly inefficient, but quite portable. - We also take care of some other basic things at this point, such - as ensuring that the instance of the die info structure starts - out completely zero'd and that curdie is initialized for use - in error reporting if we have a problem with the current die. + We also take care of some other basic things at this point, such + as ensuring that the instance of the die info structure starts + out completely zero'd and that curdie is initialized for use + in error reporting if we have a problem with the current die. -NOTES + NOTES - All DIE's must have at least a valid length, thus the minimum - DIE size is SIZEOF_DIE_LENGTH. In order to have a valid tag, the - DIE size must be at least SIZEOF_DIE_TAG larger, otherwise they - are forced to be TAG_padding DIES. + All DIE's must have at least a valid length, thus the minimum + DIE size is SIZEOF_DIE_LENGTH. In order to have a valid tag, the + DIE size must be at least SIZEOF_DIE_TAG larger, otherwise they + are forced to be TAG_padding DIES. - Padding DIES must be at least SIZEOF_DIE_LENGTH in length, implying - 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. + Padding DIES must be at least SIZEOF_DIE_LENGTH in length, implying + 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 @@ -3028,56 +3564,58 @@ basicdieinfo (dip, diep, objfile) struct objfile *objfile; { curdie = dip; - (void) 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) + 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) || + ((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)) + else if (dip->die_length < (SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG)) { - dip -> die_tag = TAG_padding; + dip->die_tag = TAG_padding; } else { diep += SIZEOF_DIE_LENGTH; - dip -> die_tag = target_to_host (diep, SIZEOF_DIE_TAG, GET_UNSIGNED, - objfile); + dip->die_tag = target_to_host (diep, SIZEOF_DIE_TAG, GET_UNSIGNED, + objfile); } } /* -LOCAL FUNCTION + LOCAL FUNCTION - completedieinfo -- finish reading the information for a given DIE + completedieinfo -- finish reading the information for a given DIE -SYNOPSIS + SYNOPSIS - void completedieinfo (struct dieinfo *dip, struct objfile *objfile) + void completedieinfo (struct dieinfo *dip, struct objfile *objfile) -DESCRIPTION + DESCRIPTION - Given a pointer to an already partially initialized die info structure, - scan the raw DIE data and finish filling in the die info structure - from the various attributes found. - - Note that since there is no guarantee that the data is properly - aligned in memory for the type of access required (indirection - through anything other than a char pointer), and there is no - guarantee that it is in the same byte order as the gdb host, - we call a function which deals with both alignment and byte - swapping issues. Possibly inefficient, but quite portable. + Given a pointer to an already partially initialized die info structure, + scan the raw DIE data and finish filling in the die info structure + from the various attributes found. -NOTES + Note that since there is no guarantee that the data is properly + aligned in memory for the type of access required (indirection + through anything other than a char pointer), and there is no + guarantee that it is in the same byte order as the gdb host, + we call a function which deals with both alignment and byte + swapping issues. Possibly inefficient, but quite portable. - Each time we are called, we increment the diecount variable, which - keeps an approximate count of the number of dies processed for - each compilation unit. This information is presented to the user - if the info_verbose flag is set. + NOTES + + Each time we are called, we increment the diecount variable, which + keeps an approximate count of the number of dies processed for + each compilation unit. This information is presented to the user + if the info_verbose flag is set. */ @@ -3091,10 +3629,10 @@ completedieinfo (dip, objfile) unsigned short attr; /* Current attribute being scanned */ unsigned short form; /* Form of the attribute */ int nbytes; /* Size of next field to read */ - + diecount++; - diep = dip -> die; - end = diep + dip -> die_length; + diep = dip->die; + end = diep + dip->die_length; diep += SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG; while (diep < end) { @@ -3102,129 +3640,128 @@ 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; } switch (attr) { case AT_fund_type: - dip -> at_fund_type = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); + dip->at_fund_type = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); break; case AT_ordering: - dip -> at_ordering = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); + dip->at_ordering = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); break; case AT_bit_offset: - 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); + dip->at_bit_offset = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); break; case AT_sibling: - dip -> at_sibling = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); + dip->at_sibling = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); break; case AT_stmt_list: - dip -> at_stmt_list = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); - dip -> has_at_stmt_list = 1; + dip->at_stmt_list = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + dip->has_at_stmt_list = 1; break; case AT_low_pc: - dip -> at_low_pc = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); - dip -> at_low_pc += baseaddr; - dip -> has_at_low_pc = 1; + dip->at_low_pc = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + dip->at_low_pc += baseaddr; + dip->has_at_low_pc = 1; break; case AT_high_pc: - dip -> at_high_pc = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); - dip -> at_high_pc += baseaddr; + dip->at_high_pc = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); + dip->at_high_pc += baseaddr; break; case AT_language: - dip -> at_language = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); + dip->at_language = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); break; case AT_user_def_type: - dip -> at_user_def_type = target_to_host (diep, nbytes, - GET_UNSIGNED, objfile); + dip->at_user_def_type = target_to_host (diep, nbytes, + GET_UNSIGNED, objfile); break; case AT_byte_size: - dip -> at_byte_size = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); + 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, - objfile); + dip->at_bit_size = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); break; case AT_member: - dip -> at_member = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); + dip->at_member = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); break; case AT_discr: - 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); + dip->at_discr = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); break; case AT_location: - dip -> at_location = diep; + dip->at_location = diep; break; case AT_mod_fund_type: - dip -> at_mod_fund_type = diep; + dip->at_mod_fund_type = diep; break; case AT_subscr_data: - dip -> at_subscr_data = diep; + dip->at_subscr_data = diep; break; case AT_mod_u_d_type: - dip -> at_mod_u_d_type = diep; + dip->at_mod_u_d_type = diep; break; case AT_element_list: - dip -> at_element_list = diep; - dip -> short_element_list = 0; + dip->at_element_list = diep; + dip->short_element_list = 0; break; case AT_short_element_list: - dip -> at_element_list = diep; - dip -> short_element_list = 1; + dip->at_element_list = diep; + dip->short_element_list = 1; break; case AT_discr_value: - dip -> at_discr_value = diep; + dip->at_discr_value = diep; break; case AT_string_length: - dip -> at_string_length = diep; + dip->at_string_length = diep; break; case AT_name: - dip -> at_name = diep; + 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); + dip->at_producer = diep; break; case AT_start_scope: - dip -> at_start_scope = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); + dip->at_start_scope = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); break; case AT_stride_size: - dip -> at_stride_size = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); + dip->at_stride_size = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); break; case AT_src_info: - dip -> at_src_info = target_to_host (diep, nbytes, GET_UNSIGNED, - objfile); + dip->at_src_info = target_to_host (diep, nbytes, GET_UNSIGNED, + objfile); break; case AT_prototyped: - dip -> at_prototyped = diep; + dip->at_prototyped = diep; break; default: /* Found an attribute that we are unprepared to handle. However @@ -3260,8 +3797,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; } @@ -3270,79 +3806,81 @@ completedieinfo (dip, objfile) /* -LOCAL FUNCTION + LOCAL FUNCTION - target_to_host -- swap in target data to host + target_to_host -- swap in target data to host -SYNOPSIS + SYNOPSIS - target_to_host (char *from, int nbytes, int signextend, - struct objfile *objfile) + target_to_host (char *from, int nbytes, int signextend, + struct objfile *objfile) -DESCRIPTION + DESCRIPTION - Given pointer to data in target format in FROM, a byte count for - the size of the data in NBYTES, a flag indicating whether or not - the data is signed in SIGNEXTEND, and a pointer to the current - objfile in OBJFILE, convert the data to host format and return - the converted value. + Given pointer to data in target format in FROM, a byte count for + the size of the data in NBYTES, a flag indicating whether or not + the data is signed in SIGNEXTEND, and a pointer to the current + objfile in OBJFILE, convert the data to host format and return + the converted value. -NOTES + NOTES - FIXME: If we read data that is known to be signed, and expect to - 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: If we read data that is known to be signed, and expect to + 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) { - case 8: - rtnval = bfd_get_64 (objfile -> obfd, (bfd_byte *) from); - break; - case 4: - rtnval = bfd_get_32 (objfile -> obfd, (bfd_byte *) from); - break; - case 2: - rtnval = bfd_get_16 (objfile -> obfd, (bfd_byte *) from); - break; - case 1: - rtnval = bfd_get_8 (objfile -> obfd, (bfd_byte *) from); - break; - default: - dwarfwarn ("no bfd support for %d byte data object", nbytes); - rtnval = 0; - break; + case 8: + rtnval = bfd_get_64 (objfile->obfd, (bfd_byte *) from); + break; + case 4: + rtnval = bfd_get_32 (objfile->obfd, (bfd_byte *) from); + break; + case 2: + rtnval = bfd_get_16 (objfile->obfd, (bfd_byte *) from); + break; + case 1: + rtnval = bfd_get_8 (objfile->obfd, (bfd_byte *) from); + break; + default: + complain (&no_bfd_get_N, DIE_ID, DIE_NAME, nbytes); + rtnval = 0; + break; } return (rtnval); } /* -LOCAL FUNCTION + LOCAL FUNCTION - attribute_size -- compute size of data for a DWARF attribute + attribute_size -- compute size of data for a DWARF attribute -SYNOPSIS + SYNOPSIS - static int attribute_size (unsigned int attr) + static int attribute_size (unsigned int attr) -DESCRIPTION + DESCRIPTION - Given a DWARF attribute in ATTR, compute the size of the first - piece of data associated with this attribute and return that - size. + Given a DWARF attribute in ATTR, compute the size of the first + piece of data associated with this attribute and return that + size. - Returns -1 for unrecognized attributes. + Returns -1 for unrecognized attributes. */ @@ -3356,28 +3894,28 @@ attribute_size (attr) form = FORM_FROM_ATTR (attr); switch (form) { - case FORM_STRING: /* A variable length field is next */ - nbytes = 0; - break; - case FORM_DATA2: /* Next 2 byte field is the data itself */ - case FORM_BLOCK2: /* Next 2 byte field is a block length */ - nbytes = 2; - break; - case FORM_DATA4: /* Next 4 byte field is the data itself */ - case FORM_BLOCK4: /* Next 4 byte field is a block length */ - case FORM_REF: /* Next 4 byte field is a DIE offset */ - nbytes = 4; - break; - case FORM_DATA8: /* Next 8 byte field is the data itself */ - nbytes = 8; - break; - case FORM_ADDR: /* Next field size is target sizeof(void *) */ - nbytes = TARGET_FT_POINTER_SIZE (objfile); - break; - default: - SQUAWK (("unknown attribute form (0x%x)", form)); - nbytes = -1; - break; - } + case FORM_STRING: /* A variable length field is next */ + nbytes = 0; + break; + case FORM_DATA2: /* Next 2 byte field is the data itself */ + case FORM_BLOCK2: /* Next 2 byte field is a block length */ + nbytes = 2; + break; + case FORM_DATA4: /* Next 4 byte field is the data itself */ + case FORM_BLOCK4: /* Next 4 byte field is a block length */ + case FORM_REF: /* Next 4 byte field is a DIE offset */ + nbytes = 4; + break; + case FORM_DATA8: /* Next 8 byte field is the data itself */ + nbytes = 8; + break; + case FORM_ADDR: /* Next field size is target sizeof(void *) */ + nbytes = TARGET_FT_POINTER_SIZE (objfile); + break; + default: + complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form); + nbytes = -1; + break; + } return (nbytes); }