/*
-FIXME: Figure out how to get the frame pointer register number in the
-execution environment of the target. Remove R_FP kludge
-
-FIXME: Add generation of dependencies list to partial symtab code.
+FIXME: Do we need to generate dependencies in partial symtabs?
+(Perhaps we don't need to).
FIXME: Resolve minor differences between what information we put in the
partial symbol table and what dbxread puts in. For example, we don't yet
#include "gdbtypes.h"
#include "symfile.h"
#include "objfiles.h"
+#include <time.h> /* For time_t in libbfd.h. */
+#include <sys/types.h> /* For time_t, if not in time.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"
-#include <varargs.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
+
#ifndef NO_SYS_FILE
#include <sys/file.h>
#endif
#define L_SET 0
#endif
-#ifdef MAINTENANCE /* Define to 1 to compile in some maintenance stuff */
-#define SQUAWK(stuff) dwarfwarn stuff
-#else
-#define SQUAWK(stuff)
-#endif
+/* Some macros to provide DIE info for complaints. */
-#ifndef R_FP /* FIXME */
-#define R_FP 14 /* Kludge to get frame pointer register number */
-#endif
+#define DIE_ID (curdie!=NULL ? curdie->die_ref : 0)
+#define DIE_NAME (curdie!=NULL && curdie->at_name!=NULL) ? curdie->at_name : ""
+
+/* Complaints that can be issued during DWARF debug info reading. */
+
+struct complaint no_bfd_get_N =
+{
+ "DIE @ 0x%x \"%s\", no bfd support for %d byte data object", 0, 0
+};
+
+struct complaint malformed_die =
+{
+ "DIE @ 0x%x \"%s\", malformed DIE, bad length (%d bytes)", 0, 0
+};
+
+struct complaint bad_die_ref =
+{
+ "DIE @ 0x%x \"%s\", reference to DIE (0x%x) outside compilation unit", 0, 0
+};
+
+struct complaint unknown_attribute_form =
+{
+ "DIE @ 0x%x \"%s\", unknown attribute form (0x%x)", 0, 0
+};
+
+struct complaint unknown_attribute_length =
+{
+ "DIE @ 0x%x \"%s\", unknown attribute length, skipped remaining attributes", 0, 0
+};
+
+struct complaint unexpected_fund_type =
+{
+ "DIE @ 0x%x \"%s\", unexpected fundamental type 0x%x", 0, 0
+};
+
+struct complaint unknown_type_modifier =
+{
+ "DIE @ 0x%x \"%s\", unknown type modifier %u", 0, 0
+};
+
+struct complaint volatile_ignored =
+{
+ "DIE @ 0x%x \"%s\", type modifier 'volatile' ignored", 0, 0
+};
+
+struct complaint const_ignored =
+{
+ "DIE @ 0x%x \"%s\", type modifier 'const' ignored", 0, 0
+};
+
+struct complaint botched_modified_type =
+{
+ "DIE @ 0x%x \"%s\", botched modified type decoding (mtype 0x%x)", 0, 0
+};
+
+struct complaint op_deref2 =
+{
+ "DIE @ 0x%x \"%s\", OP_DEREF2 address 0x%x not handled", 0, 0
+};
+
+struct complaint op_deref4 =
+{
+ "DIE @ 0x%x \"%s\", OP_DEREF4 address 0x%x not handled", 0, 0
+};
+
+struct complaint basereg_not_handled =
+{
+ "DIE @ 0x%x \"%s\", BASEREG %d not handled", 0, 0
+};
+
+struct complaint dup_user_type_allocation =
+{
+ "DIE @ 0x%x \"%s\", internal error: duplicate user type allocation", 0, 0
+};
+
+struct complaint dup_user_type_definition =
+{
+ "DIE @ 0x%x \"%s\", internal error: duplicate user type definition", 0, 0
+};
+
+struct complaint missing_tag =
+{
+ "DIE @ 0x%x \"%s\", missing class, structure, or union tag", 0, 0
+};
+
+struct complaint bad_array_element_type =
+{
+ "DIE @ 0x%x \"%s\", bad array element type attribute 0x%x", 0, 0
+};
+
+struct complaint subscript_data_items =
+{
+ "DIE @ 0x%x \"%s\", can't decode subscript data items", 0, 0
+};
+
+struct complaint unhandled_array_subscript_format =
+{
+ "DIE @ 0x%x \"%s\", array subscript format 0x%x not handled yet", 0, 0
+};
+
+struct complaint unknown_array_subscript_format =
+{
+ "DIE @ 0x%x \"%s\", unknown array subscript format %x", 0, 0
+};
+
+struct complaint not_row_major =
+{
+ "DIE @ 0x%x \"%s\", array not row major; not handled correctly", 0, 0
+};
typedef unsigned int DIE_REF; /* Reference to a DIE */
#define LCC_PRODUCER "NCR C/C++"
#endif
-#ifndef CFRONT_PRODUCER
-#define CFRONT_PRODUCER "CFRONT " /* A wild a** guess... */
-#endif
-
-/* start-sanitize-chill */
#ifndef CHILL_PRODUCER
#define CHILL_PRODUCER "GNU Chill "
#endif
-/* end-sanitize-chill */
-
-#define STREQ(a,b) (strcmp(a,b)==0)
-#define STREQN(a,b,n) (strncmp(a,b,n)==0)
/* Flags to target_to_host() that tell whether or not the data object is
expected to be signed. Used, for example, when fetching a signed
static int dbroff; /* Relative offset from start of .debug section */
static char *lnbase; /* Base pointer to line section */
static int isreg; /* Kludge to identify register variables */
-static int offreg; /* Kludge to identify basereg references */
+/* Kludge to identify basereg references. Nonzero if we have an offset
+ relative to a basereg. */
+static int offreg;
+/* Which base register is it relative to? */
+static int basereg;
/* This value is added to each symbol value. FIXME: Generalize to
- the section_offsets structure used by dbxread. */
+ the section_offsets structure used by dbxread (once this is done,
+ pass the appropriate section number to end_symtab). */
static CORE_ADDR baseaddr; /* Add to each symbol value */
/* The section offsets used in the current psymtab or symtab. FIXME,
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
psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
-static struct symtab *
+static void
read_ofile_symtab PARAMS ((struct partial_symtab *));
static void
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));
+static void
+read_tag_string_type PARAMS ((struct dieinfo *dip));
+
static void
read_subroutine_type PARAMS ((struct dieinfo *, char *, char *));
static int
locval PARAMS ((char *));
-static void
-record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type,
- struct objfile *));
-
static void
set_cu_language PARAMS ((struct dieinfo *));
case LANG_C_PLUS_PLUS:
cu_language = language_cplus;
break;
- /* start-sanitize-chill */
case LANG_CHILL:
cu_language = language_chill;
break;
- /* end-sanitize-chill */
case LANG_MODULA2:
cu_language = language_m2;
break;
case LANG_FORTRAN77:
case LANG_FORTRAN90:
case LANG_PASCAL83:
- default:
+ /* 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);
}
current_objfile = NULL;
}
-
-/*
-
-LOCAL FUNCTION
-
- record_minimal_symbol -- add entry to gdb's minimal symbol table
-
-SYNOPSIS
-
- static void record_minimal_symbol (char *name, CORE_ADDR address,
- enum minimal_symbol_type ms_type,
- struct objfile *objfile)
-
-DESCRIPTION
-
- Given a pointer to the name of a symbol that should be added to the
- minimal symbol table, and the address associated with that
- symbol, records this information for later use in building the
- minimal symbol table.
-
- */
-
-static void
-record_minimal_symbol (name, address, ms_type, objfile)
- char *name;
- CORE_ADDR address;
- enum minimal_symbol_type ms_type;
- struct objfile *objfile;
-{
- name = obsavestring (name, strlen (name), &objfile -> symbol_obstack);
- prim_record_minimal_symbol (name, address, ms_type);
-}
-
-/*
-
-LOCAL FUNCTION
-
- dwarfwarn -- issue a DWARF related warning
-
-DESCRIPTION
-
- Issue warnings about DWARF related things that aren't serious enough
- to warrant aborting with an error, but should not be ignored either.
- This includes things like detectable corruption in DIE's, missing
- DIE's, unimplemented features, etc.
-
- In general, running across tags or attributes that we don't recognize
- is not considered to be a problem and we should not issue warnings
- about such.
-
-NOTES
-
- We mostly follow the example of the error() routine, but without
- returning to command level. It is arguable about whether warnings
- should be issued at all, and if so, where they should go (stdout or
- stderr).
-
- We assume that curdie is valid and contains at least the basic
- information for the DIE where the problem was noticed.
-*/
-
-static void
-dwarfwarn (va_alist)
- va_dcl
-{
- va_list ap;
- char *fmt;
-
- va_start (ap);
- fmt = va_arg (ap, char *);
- warning_setup ();
- fprintf (stderr, "warning: DWARF ref 0x%x: ", curdie -> die_ref);
- if (curdie -> at_name)
- {
- fprintf (stderr, "'%s': ", curdie -> at_name);
- }
- vfprintf (stderr, fmt, ap);
- fprintf (stderr, "\n");
- fflush (stderr);
- va_end (ap);
-}
-
/*
LOCAL FUNCTION
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
{
if ((utypeidx < 0) || (utypeidx >= numutypes))
{
utypep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
- dwarfwarn ("reference to DIE (0x%x) outside compilation unit", die_ref);
+ 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
{
struct nextfield *new;
int nfields = 0;
int n;
- char *tpart1;
struct dieinfo mbr;
char *nextdie;
+#if !BITS_BIG_ENDIAN
int anonymous_size;
+#endif
if ((type = lookup_utype (dip -> die_ref)) == NULL)
{
{
case TAG_class_type:
TYPE_CODE (type) = TYPE_CODE_CLASS;
- tpart1 = "class";
break;
case TAG_structure_type:
TYPE_CODE (type) = TYPE_CODE_STRUCT;
- tpart1 = "struct";
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 class, structure, or union tag"));
+ complain (&missing_tag, DIE_ID, DIE_NAME);
break;
}
/* Some compilers try to be helpful by inventing "fake" names for
&& *dip -> at_name != '~'
&& *dip -> at_name != '.')
{
- TYPE_NAME (type) = obconcat (&objfile -> type_obstack,
- tpart1, " ", dip -> at_name);
+ TYPE_TAG_NAME (type) = obconcat (&objfile -> type_obstack,
+ "", "", dip -> at_name);
}
/* Use whatever size is known. Zero is a valid size. We might however
wish to check has_at_byte_size to make sure that some byte size was
scan += SIZEOF_ATTRIBUTE;
if ((nbytes = attribute_size (attribute)) == -1)
{
- SQUAWK (("bad array element type attribute 0x%x", attribute));
+ complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
}
else
typep = decode_mod_u_d_type (scan);
break;
default:
- SQUAWK (("bad array element type attribute 0x%x", attribute));
+ complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
break;
}
LOCAL FUNCTION
- decode_subscr_data -- decode array subscript and element type data
+ decode_subscript_data_item -- decode array subscript item
SYNOPSIS
- static struct type *decode_subscr_data (char *scan, char *end)
+ static struct type *
+ decode_subscript_data_item (char *scan, char *end)
DESCRIPTION
source (I.E. leftmost dimension first, next to leftmost second,
etc).
+ The data items describing each array dimension consist of four
+ parts: (1) a format specifier, (2) type type of the subscript
+ index, (3) a description of the low bound of the array dimension,
+ and (4) a description of the high bound of the array dimension.
+
+ The last data item is the description of the type of each of
+ the array elements.
+
We are passed a pointer to the start of the block of bytes
- containing the data items, and a pointer to the first byte past
- the data. This function decodes the data and returns a type.
+ containing the remaining data items, and a pointer to the first
+ byte past the data. This function recursively decodes the
+ remaining data items and returns a type.
+
+ If we somehow fail to decode some data, we complain about it
+ and return a type "array of int".
BUGS
FIXME: This code only implements the forms currently used
*/
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;
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 = alloc_type (current_objfile);
- TYPE_CODE (typep) = TYPE_CODE_ARRAY;
- TYPE_LENGTH (typep) = TYPE_LENGTH (nexttype);
- TYPE_LENGTH (typep) *= (highbound - lowbound) + 1;
- TYPE_TARGET_TYPE (typep) = nexttype;
- }
+ /* Munged subscript data or other problem, fake it. */
+ complain (&subscript_data_items, DIE_ID, DIE_NAME);
+ nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
}
+ rangetype = create_range_type ((struct type *) NULL, indextype,
+ lowbound, highbound);
+ typep = create_array_type ((struct type *) NULL, nexttype, rangetype);
break;
case FMT_FT_C_X:
case FMT_FT_X_C:
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);
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)
{
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) =
- dwarf_fundamental_type (current_objfile, FT_INTEGER);
- TYPE_LENGTH (utype) = 1 * TYPE_LENGTH (TYPE_TARGET_TYPE (utype));
+ /* Install user defined type that has not been referenced yet. */
+ alloc_utype (dip -> die_ref, type);
+ }
+ else if (TYPE_CODE (utype) == TYPE_CODE_UNDEF)
+ {
+ /* Ick! A forward ref has already generated a blank type in our
+ slot, and this type probably already has things pointing to it
+ (which is what caused it to be created in the first place).
+ If it's just a place holder we can plop our fully defined type
+ on top of it. We can't recover the space allocated for our
+ new type since it might be on an obstack, but we could reuse
+ it if we kept a list of them, but it might not be worth it
+ (FIXME). */
+ *utype = *type;
}
else
{
- if ((utype = lookup_utype (dip -> die_ref)) == NULL)
- {
- alloc_utype (dip -> die_ref, type);
- }
- else
- {
- TYPE_CODE (utype) = TYPE_CODE_ARRAY;
- TYPE_LENGTH (utype) = TYPE_LENGTH (type);
- TYPE_TARGET_TYPE (utype) = TYPE_TARGET_TYPE (type);
- }
+ /* Double ick! Not only is a type already in our slot, but
+ someone has decorated it. Complain and leave it alone. */
+ complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
}
}
}
/*
+LOCAL FUNCTION
+
+ read_tag_string_type -- read TAG_string_type DIE
+
+SYNOPSIS
+
+ static void read_tag_string_type (struct dieinfo *dip)
+
+DESCRIPTION
+
+ Extract all information from a TAG_string_type DIE and add to
+ the user defined type vector. It isn't really a user defined
+ type, but it behaves like one, with other DIE's using an
+ AT_user_def_type attribute to reference it.
+ */
+
+static void
+read_tag_string_type (dip)
+ struct dieinfo *dip;
+{
+ struct type *utype;
+ struct type *indextype;
+ struct type *rangetype;
+ unsigned long lowbound = 0;
+ unsigned long highbound;
+
+ if (dip -> has_at_byte_size)
+ {
+ /* A fixed bounds string */
+ highbound = dip -> at_byte_size - 1;
+ }
+ else
+ {
+ /* A varying length string. Stub for now. (FIXME) */
+ highbound = 1;
+ }
+ indextype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ rangetype = create_range_type ((struct type *) NULL, indextype, lowbound,
+ highbound);
+
+ utype = lookup_utype (dip -> die_ref);
+ if (utype == NULL)
+ {
+ /* No type defined, go ahead and create a blank one to use. */
+ utype = alloc_utype (dip -> die_ref, (struct type *) NULL);
+ }
+ else
+ {
+ /* Already a type in our slot due to a forward reference. Make sure it
+ is a blank one. If not, complain and leave it alone. */
+ if (TYPE_CODE (utype) != TYPE_CODE_UNDEF)
+ {
+ complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
+ return;
+ }
+ }
+
+ /* Create the string type using the blank type we either found or created. */
+ utype = create_string_type (utype, rangetype);
+}
+
+/*
+
LOCAL FUNCTION
read_subroutine_type -- process TAG_subroutine_type dies
ftype = lookup_function_type (type);
alloc_utype (dip -> die_ref, ftype);
}
- else
+ else if (TYPE_CODE (ftype) == TYPE_CODE_UNDEF)
{
/* We have an existing partially constructed type, so bash it
into the correct type. */
TYPE_LENGTH (ftype) = 1;
TYPE_CODE (ftype) = TYPE_CODE_FUNC;
}
+ else
+ {
+ complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
+ }
}
/*
&& *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)
{
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;
processing_gcc_compilation =
STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))
- /* start-sanitize-chill */
|| STREQN (producer, CHILL_PRODUCER, strlen (CHILL_PRODUCER))
- /* end-sanitize-chill */
|| STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER));
/* Select a demangling style if we can identify the producer and if
is not auto. We also leave the demangling style alone if we find a
gcc (cc1) producer, as opposed to a g++ (cc1plus) producer. */
-#if 1 /* Works, but is experimental. -fnf */
if (AUTO_DEMANGLING)
{
if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)))
{
set_demangling_style (LUCID_DEMANGLING_STYLE_STRING);
}
- else if (STREQN (producer, CFRONT_PRODUCER, strlen (CFRONT_PRODUCER)))
- {
- set_demangling_style (CFRONT_DEMANGLING_STYLE_STRING);
- }
}
-#endif
}
start_symtab (dip -> at_name, dip -> at_comp_dir, dip -> at_low_pc);
decode_line_numbers (lnbase);
process_dies (thisdie + dip -> die_length, enddie, objfile);
- symtab = end_symtab (dip -> at_high_pc, 0, 0, objfile);
+
+ symtab = end_symtab (dip -> at_high_pc, 0, 0, objfile, 0);
if (symtab != NULL)
{
symtab -> language = cu_language;
case TAG_pointer_type:
read_tag_pointer_type (&di);
break;
+ case TAG_string_type:
+ read_tag_string_type (&di);
+ break;
default:
new_symbol (&di, objfile);
break;
auto long stack[64];
int stacki;
char *end;
- long regno;
int loc_atom_code;
int loc_value_size;
break;
case OP_BASEREG:
/* push value of register (number) */
- /* Actually, we compute the value as if register has 0 */
+ /* Actually, we compute the value as if register has 0, so the
+ value ends up being the offset from that register. */
offreg = 1;
- regno = target_to_host (loc, loc_value_size, GET_UNSIGNED,
- current_objfile);
+ basereg = target_to_host (loc, loc_value_size, GET_UNSIGNED,
+ current_objfile);
loc += loc_value_size;
- if (regno == R_FP)
- {
- stack[++stacki] = 0;
- }
- else
- {
- stack[++stacki] = 0;
- SQUAWK (("BASEREG %d not handled!", regno));
- }
+ stack[++stacki] = 0;
break;
case OP_ADDR:
/* push address (relocated address) */
break;
case OP_DEREF2:
/* pop, deref and push 2 bytes (as a long) */
- SQUAWK (("OP_DEREF2 address 0x%x not handled", stack[stacki]));
+ complain (&op_deref2, DIE_ID, DIE_NAME, stack[stacki]);
break;
case OP_DEREF4: /* pop, deref and push 4 bytes (as a long) */
- SQUAWK (("OP_DEREF4 address 0x%x not handled", stack[stacki]));
+ complain (&op_deref4, DIE_ID, DIE_NAME, stack[stacki]);
break;
case OP_ADD: /* pop top 2 items, add, push result */
stack[stacki - 1] += stack[stacki];
SYNOPSIS
- static struct symtab *read_ofile_symtab (struct partial_symtab *pst)
+ static void read_ofile_symtab (struct partial_symtab *pst)
DESCRIPTION
When expanding a partial symbol table entry to a full symbol table
entry, this is the function that gets called to read in the symbols
- for the compilation unit.
-
- Returns a pointer to the newly constructed symtab (which is now
- the new first one on the objfile's symtab list).
+ for the compilation unit. A pointer to the newly constructed symtab,
+ which is now the new first one on the objfile's symtab list, is
+ stashed in the partial symbol table entry.
*/
-static struct symtab *
+static void
read_ofile_symtab (pst)
struct partial_symtab *pst;
{
process_dies (dbbase, dbbase + dbsize, pst -> objfile);
do_cleanups (back_to);
current_objfile = NULL;
- return (pst -> objfile -> symtabs);
+ pst -> symtab = pst -> objfile -> symtabs;
}
/*
{
buildsym_init ();
old_chain = make_cleanup (really_free_pendings, 0);
- pst -> symtab = read_ofile_symtab (pst);
+ read_ofile_symtab (pst);
if (info_verbose)
{
printf_filtered ("%d DIE's, sorting...", diecount);
{
scan += TARGET_FT_LONG_SIZE (objfile);
ADD_PSYMBOL_TO_LIST (scan, strlen (scan), VAR_NAMESPACE, LOC_CONST,
- objfile -> static_psymbols, 0);
+ objfile -> static_psymbols, 0, cu_language,
+ objfile);
scan += strlen (scan) + 1;
}
}
switch (dip -> die_tag)
{
case TAG_global_subroutine:
- record_minimal_symbol (dip -> at_name, dip -> at_low_pc, mst_text,
- objfile);
ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
VAR_NAMESPACE, LOC_BLOCK,
objfile -> global_psymbols,
- dip -> at_low_pc);
+ dip -> at_low_pc, cu_language, objfile);
break;
case TAG_global_variable:
- record_minimal_symbol (dip -> at_name, locval (dip -> at_location),
- mst_data, objfile);
ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
VAR_NAMESPACE, LOC_STATIC,
objfile -> global_psymbols,
- 0);
+ 0, cu_language, objfile);
break;
case TAG_subroutine:
ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
VAR_NAMESPACE, LOC_BLOCK,
objfile -> static_psymbols,
- dip -> at_low_pc);
+ dip -> at_low_pc, cu_language, objfile);
break;
case TAG_local_variable:
ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
VAR_NAMESPACE, LOC_STATIC,
objfile -> static_psymbols,
- 0);
+ 0, cu_language, objfile);
break;
case TAG_typedef:
ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
VAR_NAMESPACE, LOC_TYPEDEF,
objfile -> static_psymbols,
- 0);
+ 0, cu_language, objfile);
break;
case TAG_class_type:
case TAG_structure_type:
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)
{
/* 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);
}
break;
}
temp = dbbase + di.at_sibling - dbroff;
if ((temp < thisdie) || (temp >= enddie))
{
- dwarfwarn ("reference to DIE (0x%x) outside compilation unit", di.at_sibling);
+ complain (&bad_die_ref, DIE_ID, DIE_NAME,
+ di.at_sibling);
}
else
{
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
SYMBOL_CLASS (sym) = LOC_STATIC;
SYMBOL_TYPE (sym) = decode_die_type (dip);
+
+ /* If this symbol is from a C++ compilation, then attempt to cache the
+ demangled form for future reference. This is a typical time versus
+ space tradeoff, that was decided in favor of time because it sped up
+ C++ symbol lookups by a factor of about 20. */
+
+ SYMBOL_LANGUAGE (sym) = cu_language;
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile -> symbol_obstack);
switch (dip -> die_tag)
{
case TAG_label:
}
else if (offreg)
{
- SYMBOL_CLASS (sym) = LOC_LOCAL;
+ SYMBOL_CLASS (sym) = LOC_BASEREG;
+ SYMBOL_BASEREG (sym) = basereg;
}
else
{
{
SYMBOL_CLASS (sym) = LOC_REGPARM;
}
+ else if (offreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
+ SYMBOL_BASEREG (sym) = basereg;
+ }
else
{
SYMBOL_CLASS (sym) = LOC_ARG;
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;
}
break;
default:
- SQUAWK (("botched modified type decoding (mtype 0x%x)", mtype));
+ complain (&botched_modified_type, DIE_ID, DIE_NAME, mtype);
typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
break;
}
typep = lookup_reference_type (typep);
break;
case MOD_const:
- SQUAWK (("type modifier 'const' ignored")); /* FIXME */
+ complain (&const_ignored, DIE_ID, DIE_NAME); /* FIXME */
break;
case MOD_volatile:
- SQUAWK (("type modifier 'volatile' ignored")); /* FIXME */
+ complain (&volatile_ignored, DIE_ID, DIE_NAME); /* FIXME */
break;
default:
if (!(MOD_lo_user <= (unsigned char) modifier
&& (unsigned char) modifier <= MOD_hi_user))
{
- SQUAWK (("unknown type modifier %u",
- (unsigned char) modifier));
+ complain (&unknown_type_modifier, DIE_ID, DIE_NAME, modifier);
}
break;
}
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 *
}
- if ((typep == NULL) && !(FT_lo_user <= fundtype && fundtype <= FT_hi_user))
+ if (typep == NULL)
{
- SQUAWK (("unexpected fundamental type 0x%x", fundtype));
- typep = dwarf_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);
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))
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;
}
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;
}
rtnval = bfd_get_8 (objfile -> obfd, (bfd_byte *) from);
break;
default:
- dwarfwarn ("no bfd support for %d byte data object", nbytes);
+ complain (&no_bfd_get_N, DIE_ID, DIE_NAME, nbytes);
rtnval = 0;
break;
}
nbytes = TARGET_FT_POINTER_SIZE (objfile);
break;
default:
- SQUAWK (("unknown attribute form (0x%x)", form));
+ complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form);
nbytes = -1;
break;
}