#include "defs.h"
#include "bfd.h"
+#include "elf-bfd.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "symfile.h"
/* The data in a compilation unit header looks like this. */
struct comp_unit_head
{
- int length;
+ unsigned int length;
short version;
- int abbrev_offset;
+ unsigned int abbrev_offset;
unsigned char addr_size;
};
whatever scope is currently getting read. */
static int address_size;
+/* Some elf32 object file formats while linked for a 32 bit address
+ space contain debug information that has assumed 64 bit
+ addresses. Eg 64 bit MIPS target produced by GCC/GAS/LD where the
+ symbol table contains 32bit address values while its .debug_info
+ section contains 64 bit address values.
+ ADDRESS_SIGNIFICANT_SIZE specifies the number significant bits in
+ the ADDRESS_SIZE bytes read from the file */
+static int address_significant_size;
+
/* Externals references. */
extern int info_verbose; /* From main.c; nonzero => verbose */
static void process_die PARAMS ((struct die_info *, struct objfile *));
+static char *dwarf2_linkage_name PARAMS ((struct die_info *));
+
static char *dwarf_tag_name PARAMS ((unsigned int));
static char *dwarf_attr_name PARAMS ((unsigned int));
int comp_unit_has_pc_info;
CORE_ADDR lowpc, highpc;
+ /* Number of bytes of any addresses that are signficant */
+ address_significant_size = get_elf_backend_data (abfd)->s->arch_size / 8;
+
info_ptr = dwarf_info_buffer;
abbrev_ptr = dwarf_abbrev_buffer;
error ("Dwarf Error: wrong version in compilation unit header.");
return;
}
+ if (cu_header.abbrev_offset >= dwarf_abbrev_size)
+ {
+ error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6).",
+ (long) cu_header.abbrev_offset,
+ (long) (beg_of_comp_unit - dwarf_info_buffer));
+ return;
+ }
+ if (beg_of_comp_unit + cu_header.length + 4
+ > dwarf_info_buffer + dwarf_info_size)
+ {
+ error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).",
+ (long) cu_header.length,
+ (long) (beg_of_comp_unit - dwarf_info_buffer));
+ return;
+ }
+ if (address_size < address_significant_size)
+ {
+ error ("Dwarf Error: bad address size (%ld) in compilation unit header (offset 0x%lx + 11).",
+ (long) cu_header.addr_size,
+ (long) (beg_of_comp_unit - dwarf_info_buffer));
+ }
/* Read the abbrevs for this compilation unit into a table */
dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
/* Store the function that reads in the rest of the symbol table */
pst->read_symtab = dwarf2_psymtab_to_symtab;
- /* Read the rest of the partial symbols from this comp unit */
- info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc);
+ /* Check if comp unit has_children.
+ If so, read the rest of the partial symbols from this comp unit.
+ If not, there's no more debug_info for this comp unit. */
+ if (comp_unit_die.has_children)
+ info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc);
/* If the compilation unit didn't have an explicit address range,
then use the information extracted from its child dies. */
{
bfd *abfd = objfile->obfd;
struct partial_die_info pdi;
- int nesting_level = 1; /* we've already read in comp_unit_die */
- int has_pc_info;
+ /* This function is called after we've read in the comp_unit_die in
+ order to read its children. We start the nesting level at 1 since
+ we have pushed 1 level down in order to read the comp unit's children.
+ The comp unit itself is at level 0, so we stop reading when we pop
+ back to that level. */
+
+ int nesting_level = 1;
+ int has_pc_info;
+
*lowpc = ((CORE_ADDR) -1);
*highpc = ((CORE_ADDR) 0);
memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
start_symtab (name, comp_dir, lowpc);
+ record_debugformat ("DWARF 2");
/* Decode line number information if present. */
attr = dwarf_attr (die, DW_AT_stmt_list);
CORE_ADDR highpc;
struct die_info *child_die;
struct attribute *attr;
- char *name = NULL;
+ char *name;
- attr = dwarf_attr (die, DW_AT_name);
- if (attr)
- {
- name = DW_STRING (attr);
- }
+ name = dwarf2_linkage_name (die);
/* Ignore functions with missing or empty names and functions with
missing or invalid low and high pc attributes. */
attr = dwarf_attr (die, DW_AT_bit_size);
if (attr)
{
- fp->bitsize = DW_UNSND (attr);
+ FIELD_BITSIZE (*fp) = DW_UNSND (attr);
}
else
{
- fp->bitsize = 0;
+ FIELD_BITSIZE (*fp) = 0;
}
/* Get bit offset of field. */
attr = dwarf_attr (die, DW_AT_data_member_location);
if (attr)
{
- fp->bitpos =
+ FIELD_BITPOS (*fp) =
decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
}
else
- fp->bitpos = 0;
+ FIELD_BITPOS (*fp) = 0;
attr = dwarf_attr (die, DW_AT_bit_offset);
if (attr)
{
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. */
- fp->bitpos += DW_UNSND (attr);
+ FIELD_BITPOS (*fp) += DW_UNSND (attr);
}
else
{
bit field. */
anonymous_size = TYPE_LENGTH (fp->type);
}
- fp->bitpos +=
- anonymous_size * bits_per_byte - bit_offset - fp->bitsize;
+ FIELD_BITPOS (*fp) += anonymous_size * bits_per_byte
+ - bit_offset - FIELD_BITSIZE (*fp);
}
}
}
else if (die->tag == DW_TAG_variable)
{
- char *physname = "";
+ char *physname;
+ char *cp;
/* C++ static member.
Get physical name, extract field name from physical name. */
- attr = dwarf_attr (die, DW_AT_name);
- if (attr && DW_STRING (attr))
- {
- char *cp;
-
- physname = DW_STRING (attr);
+ physname = dwarf2_linkage_name (die);
+ if (physname == NULL)
+ return;
- cp = physname;
- while (*cp && !is_cplus_marker (*cp))
- cp++;
- if (*cp)
- fieldname = cp + 1;
- }
- if (*physname == '\0' || *fieldname == '\0')
+ cp = physname;
+ while (*cp && !is_cplus_marker (*cp))
+ cp++;
+ if (*cp)
+ fieldname = cp + 1;
+ if (*fieldname == '\0')
{
complain (&dwarf2_bad_static_member_name, physname);
}
- fp->bitpos = -1;
- fp->bitsize = (long) obsavestring (physname, strlen (physname),
- &objfile->type_obstack);
- fp->type = die_type (die, objfile);
- fp->name = obsavestring (fieldname, strlen (fieldname),
+ SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname),
+ &objfile->type_obstack));
+ FIELD_TYPE (*fp) = die_type (die, objfile);
+ FIELD_NAME (*fp) = obsavestring (fieldname, strlen (fieldname),
&objfile->type_obstack);
}
else if (die->tag == DW_TAG_inheritance)
/* C++ base class field. */
attr = dwarf_attr (die, DW_AT_data_member_location);
if (attr)
- fp->bitpos = decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
- fp->bitsize = 0;
- fp->type = die_type (die, objfile);
- fp->name = type_name_no_tag (fp->type);
+ FIELD_BITPOS (*fp) = decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
+ FIELD_BITSIZE (*fp) = 0;
+ FIELD_TYPE (*fp) = die_type (die, objfile);
+ FIELD_NAME (*fp) = type_name_no_tag (fp->type);
fip->nbaseclasses++;
}
}
int i;
struct fn_field *fnp;
char *fieldname;
- char *physname = "";
+ char *physname;
struct nextfnfield *new_fnfield;
/* Extract member function name from mangled name. */
- attr = dwarf_attr (die, DW_AT_name);
- if (attr && DW_STRING (attr))
- {
- physname = DW_STRING (attr);
- }
+ physname = dwarf2_linkage_name (die);
+ if (physname == NULL)
+ return;
if ((physname[0] == '_' && physname[1] == '_'
&& strchr ("0123456789Qt", physname[2]))
|| DESTRUCTOR_PREFIX_P (physname))
/* Fill in the member function field info. */
fnp = &new_fnfield->fnfield;
- fnp->physname = physname;
+ fnp->physname = obsavestring (physname, strlen (physname),
+ &objfile->type_obstack);
fnp->type = alloc_type (objfile);
if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC)
{
* sizeof (struct field));
}
- fields[num_fields].name = SYMBOL_NAME (sym);
- fields[num_fields].type = NULL;
- fields[num_fields].bitpos = SYMBOL_VALUE (sym);
- fields[num_fields].bitsize = 0;
+ FIELD_NAME (fields[num_fields]) = SYMBOL_NAME (sym);
+ FIELD_TYPE (fields[num_fields]) = NULL;
+ FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym);
+ FIELD_BITSIZE (fields[num_fields]) = 0;
num_fields++;
}
/* Default bounds to an array with unspecified length. */
low = 0;
high = -1;
- if (cu_language == DW_LANG_Fortran77
- || cu_language == DW_LANG_Fortran90)
+ if (cu_language == language_fortran)
{
/* FORTRAN implies a lower bound of 1, if not given. */
low = 1;
switch (attr.name)
{
case DW_AT_name:
+
+ /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name. */
+ if (part_die->name == NULL)
+ part_die->name = DW_STRING (&attr);
+ break;
+ case DW_AT_MIPS_linkage_name:
part_die->name = DW_STRING (&attr);
break;
case DW_AT_low_pc:
{
CORE_ADDR retval = 0;
- if (address_size == 4)
+ switch (address_size)
{
+ case 4:
retval = bfd_get_32 (abfd, (bfd_byte *) buf);
- } else { /* *THE* alternative is 8, right? */
+ break;
+ case 8:
retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ break;
+ default:
+ /* *THE* alternative is 8, right? */
+ abort ();
+ }
+ /* If the address being read is larger than the address that is
+ applicable for the object file format then mask it down to the
+ correct size. Take care to avoid unnecessary shift or shift
+ overflow */
+ if (address_size > address_significant_size
+ && address_significant_size < sizeof (CORE_ADDR))
+ {
+ CORE_ADDR mask = ((CORE_ADDR) 0) - 1;
+ retval &= ~(mask << (address_significant_size * 8));
}
return retval;
}
{
case DW_LANG_C89:
case DW_LANG_C:
- case DW_LANG_Fortran77:
cu_language = language_c;
break;
case DW_LANG_C_plus_plus:
cu_language = language_cplus;
break;
+ case DW_LANG_Fortran77:
+ case DW_LANG_Fortran90:
+ cu_language = language_fortran;
+ break;
case DW_LANG_Mips_Assembler:
cu_language = language_asm;
break;
case DW_LANG_Ada83:
case DW_LANG_Cobol74:
case DW_LANG_Cobol85:
-#if 0
- case DW_LANG_Fortran77: /* moved up top for now */
-#endif
- case DW_LANG_Fortran90:
case DW_LANG_Pascal83:
case DW_LANG_Modula2:
default:
while (line_ptr < line_end)
{
/* state machine registers */
- unsigned int address = 0;
+ CORE_ADDR address = 0;
unsigned int file = 1;
unsigned int line = 1;
unsigned int column = 0;
struct objfile *objfile;
{
struct symbol *sym = NULL;
+ char *name;
struct attribute *attr = NULL;
struct attribute *attr2 = NULL;
CORE_ADDR addr;
- attr = dwarf_attr (die, DW_AT_name);
- if (attr && DW_STRING (attr))
+ name = dwarf2_linkage_name (die);
+ if (name)
{
sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
sizeof (struct symbol));
OBJSTAT (objfile, n_syms++);
memset (sym, 0, sizeof (struct symbol));
- SYMBOL_NAME (sym) = obsavestring (DW_STRING (attr),
- strlen (DW_STRING (attr)),
+ SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
&objfile->symbol_obstack);
/* Default assumptions.
}
}
+/* Get linkage name of a die, return NULL if not found. */
+
+static char *
+dwarf2_linkage_name (die)
+ struct die_info *die;
+{
+ struct attribute *attr;
+
+ attr = dwarf_attr (die, DW_AT_MIPS_linkage_name);
+ if (attr && DW_STRING (attr))
+ return DW_STRING (attr);
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ return DW_STRING (attr);
+ return NULL;
+}
+
/* Convert a DIE tag into its string name. */
static char *