#include "gdb_string.h"
#include <sys/types.h>
+#ifndef DWARF2_REG_TO_REGNUM
+#define DWARF2_REG_TO_REGNUM(REG) (REG)
+#endif
+
#if 0
/* .debug_info header for a compilation unit
Because of alignment constraints, this structure has padding and cannot
translation, looks like this. */
struct comp_unit_head
{
- unsigned int length;
+ unsigned long length;
short version;
unsigned int abbrev_offset;
unsigned char addr_size;
unsigned char signed_addr_p;
+ unsigned int offset_size; /* size of file offsets; either 4 or 8 */
+ unsigned int initial_length_size; /* size of the length field; either
+ 4 or 12 */
};
/* The data in the .debug_line statement prologue looks like this. */
static struct die_info *die_ref_table[REF_HASH_SIZE];
-#ifndef TYPE_HASH_SIZE
-#define TYPE_HASH_SIZE 4096
-#endif
-static struct type *dwarf2_cached_types[TYPE_HASH_SIZE];
-
/* Obstack for allocating temporary storage used during symbol reading. */
static struct obstack dwarf2_tmp_obstack;
static CORE_ADDR read_address (bfd *, char *ptr, const struct comp_unit_head *,
int *bytes_read);
+static LONGEST read_initial_length (bfd *, char *,
+ struct comp_unit_head *, int *bytes_read);
+
+static LONGEST read_offset (bfd *, char *, const struct comp_unit_head *,
+ int *bytes_read);
+
static char *read_n_bytes (bfd *, char *, unsigned int);
static char *read_string (bfd *, char *, unsigned int *);
pubnames_ptr = pubnames_buffer;
while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
{
- entry_length = read_4_bytes (abfd, pubnames_ptr);
- pubnames_ptr += 4;
+ struct comp_unit_head cu_header;
+ int bytes_read;
+
+ entry_length = read_initial_length (abfd, pubnames_ptr, &cu_header,
+ &bytes_read);
+ pubnames_ptr += bytes_read;
version = read_1_byte (abfd, pubnames_ptr);
pubnames_ptr += 1;
info_offset = read_4_bytes (abfd, pubnames_ptr);
char *info_ptr, bfd *abfd)
{
int signed_addr;
- cu_header->length = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
+ int bytes_read;
+ cu_header->length = read_initial_length (abfd, info_ptr, cu_header,
+ &bytes_read);
+ info_ptr += bytes_read;
cu_header->version = read_2_bytes (abfd, info_ptr);
info_ptr += 2;
- cu_header->abbrev_offset = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
+ cu_header->abbrev_offset = read_offset (abfd, info_ptr, cu_header,
+ &bytes_read);
+ info_ptr += bytes_read;
cu_header->addr_size = read_1_byte (abfd, info_ptr);
info_ptr += 1;
signed_addr = bfd_get_sign_extend_vma (abfd);
if (signed_addr < 0)
- internal_error ("dwarf2_build_psymtabs_hard: dwarf from non elf file");
+ internal_error ("read_comp_unit_head: dwarf from non elf file");
cu_header->signed_addr_p = signed_addr;
return info_ptr;
}
(long) (beg_of_comp_unit - dwarf_info_buffer));
return;
}
- if (beg_of_comp_unit + cu_header.length + 4
+ if (beg_of_comp_unit + cu_header.length + cu_header.initial_length_size
> dwarf_info_buffer + dwarf_info_size)
{
error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).",
DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer;
DWARF_ABBREV_SIZE (pst) = dwarf_abbrev_size;
DWARF_LINE_BUFFER (pst) = dwarf_line_buffer;
- baseaddr = ANOFFSET (objfile->section_offsets, 0);
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
/* Store the function that reads in the rest of the symbol table */
pst->read_symtab = dwarf2_psymtab_to_symtab;
also happen.) This happens in VxWorks. */
free_named_symtabs (pst->filename);
- info_ptr = beg_of_comp_unit + cu_header.length + 4;
+ info_ptr = beg_of_comp_unit + cu_header.length
+ + cu_header.initial_length_size;
}
do_cleanups (back_to);
}
dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER (pst);
dwarf_abbrev_size = DWARF_ABBREV_SIZE (pst);
dwarf_line_buffer = DWARF_LINE_BUFFER (pst);
- baseaddr = ANOFFSET (pst->section_offsets, 0);
+ baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
cu_header_offset = offset;
info_ptr = dwarf_info_buffer + offset;
}
}
}
- symtab = end_symtab (highpc + baseaddr, objfile, 0);
+ symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
/* Set symtab language to language from DW_AT_language.
If the compilation is from a C file generated by language preprocessors,
/* Allocate a new field list entry and link it in. */
new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
- make_cleanup (free, new_field);
+ make_cleanup (xfree, new_field);
memset (new_field, 0, sizeof (struct nextfield));
new_field->next = fip->fields;
fip->fields = new_field;
/* Create a new member function field and chain it to the field list
entry. */
new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield));
- make_cleanup (free, new_fnfield);
+ make_cleanup (xfree, new_fnfield);
memset (new_fnfield, 0, sizeof (struct nextfnfield));
new_fnfield->next = flp->head;
flp->head = new_fnfield;
TYPE_ALLOC (type, sizeof (struct field) * num_fields);
memcpy (TYPE_FIELDS (type), fields,
sizeof (struct field) * num_fields);
- free (fields);
+ xfree (fields);
}
if (unsigned_enum)
TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
char *cur_ptr;
int nesting_level;
- /* Reset die reference table and cached types table; we are
+ /* Reset die reference table; we are
building new ones now. */
dwarf2_empty_hash_tables ();
while (die)
{
next = die->next;
- free (die->attrs);
- free (die);
+ xfree (die->attrs);
+ xfree (die);
die = next;
}
}
while (abbrev)
{
next = abbrev->next;
- free (abbrev->attrs);
- free (abbrev);
+ xfree (abbrev->attrs);
+ xfree (abbrev);
abbrev = next;
}
dwarf2_abbrevs[i] = NULL;
DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
info_ptr += 4;
break;
+ case DW_FORM_ref8:
+ DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
+ info_ptr += 8;
+ break;
case DW_FORM_ref_udata:
DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
return retval;
}
+/* Reads the initial length from a section. The (draft) DWARF 2.1
+ specification allows the initial length to take up either 4 bytes
+ or 12 bytes. If the first 4 bytes are 0xffffffff, then the next 8
+ bytes describe the length and all offsets will be 8 bytes in length
+ instead of 4.
+
+ The value returned via bytes_read should be used to increment
+ the relevant pointer after calling read_initial_length().
+
+ As a side effect, this function sets the fields initial_length_size
+ and offset_size in cu_header to the values appropriate for the
+ length field. (The format of the initial length field determines
+ the width of file offsets to be fetched later with fetch_offset().)
+
+ [ Note: read_initial_length() and read_offset() are based on the
+ document entitled "DWARF Debugging Information Format", revision
+ 2.1, draft 4, dated July 20, 2000. This document was obtained
+ from:
+
+ http://reality.sgi.com/dehnert_engr/dwarf/dwarf2p1-draft4-000720.pdf
+
+ This document is only a draft and is subject to change. (So beware.)
+
+ - Kevin, Aug 4, 2000
+ ] */
+
+static LONGEST
+read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header,
+ int *bytes_read)
+{
+ LONGEST retval = 0;
+
+ retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+
+ if (retval == 0xffffffff)
+ {
+ retval = bfd_get_64 (abfd, (bfd_byte *) buf + 4);
+ *bytes_read = 12;
+ if (cu_header != NULL)
+ {
+ cu_header->initial_length_size = 12;
+ cu_header->offset_size = 8;
+ }
+ }
+ else
+ {
+ *bytes_read = 4;
+ if (cu_header != NULL)
+ {
+ cu_header->initial_length_size = 4;
+ cu_header->offset_size = 4;
+ }
+ }
+
+ return retval;
+}
+
+/* Read an offset from the data stream. The size of the offset is
+ given by cu_header->offset_size. */
+
+static LONGEST
+read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
+ int *bytes_read)
+{
+ LONGEST retval = 0;
+
+ switch (cu_header->offset_size)
+ {
+ case 4:
+ retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+ *bytes_read = 4;
+ break;
+ case 8:
+ retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ *bytes_read = 8;
+ break;
+ default:
+ internal_error ("read_offset: bad switch");
+ }
+
+ return retval;
+}
+
static char *
read_n_bytes (bfd *abfd, char *buf, unsigned int size)
{
line_ptr = dwarf_line_buffer + offset;
/* read in the prologue */
- lh.total_length = read_4_bytes (abfd, line_ptr);
- line_ptr += 4;
+ lh.total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
+ line_ptr += bytes_read;
line_end = line_ptr + lh.total_length;
lh.version = read_2_bytes (abfd, line_ptr);
line_ptr += 2;
- lh.prologue_length = read_4_bytes (abfd, line_ptr);
- line_ptr += 4;
+ lh.prologue_length = read_offset (abfd, line_ptr, cu_header, &bytes_read);
+ line_ptr += bytes_read;
lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
line_ptr += 1;
lh.default_is_stmt = read_1_byte (abfd, line_ptr);
if (STREQ (subfile->name, fullname))
{
current_subfile = subfile;
- free (fullname);
+ xfree (fullname);
return;
}
}
- free (fullname);
+ xfree (fullname);
}
start_subfile (filename, dirname);
}
the variable is referenced. */
if (SYMBOL_VALUE_ADDRESS (sym))
{
- SYMBOL_VALUE_ADDRESS (sym) += baseaddr;
+ fixup_symbol_section (sym, objfile);
+ SYMBOL_VALUE_ADDRESS (sym) +=
+ ANOFFSET (objfile->section_offsets,
+ SYMBOL_SECTION (sym));
SYMBOL_CLASS (sym) = LOC_STATIC;
}
else
else if (isreg)
{
SYMBOL_CLASS (sym) = LOC_REGISTER;
+ SYMBOL_VALUE (sym) =
+ DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
}
else if (offreg)
{
SYMBOL_CLASS (sym) = LOC_BASEREG;
- SYMBOL_BASEREG (sym) = basereg;
+ SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
}
else if (islocal)
{
}
else
{
+ fixup_symbol_section (sym, objfile);
+ SYMBOL_VALUE_ADDRESS (sym) =
+ addr + ANOFFSET (objfile->section_offsets,
+ SYMBOL_SECTION (sym));
SYMBOL_CLASS (sym) = LOC_STATIC;
- SYMBOL_VALUE_ADDRESS (sym) = addr + baseaddr;
}
}
}
if (isreg)
{
SYMBOL_CLASS (sym) = LOC_REGPARM;
+ SYMBOL_VALUE (sym) =
+ DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
}
else if (offreg)
{
else
{
SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
- SYMBOL_BASEREG (sym) = basereg;
+ SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
}
}
else
}
else
{
- struct attribute *attr;
- attr = dwarf_attr (die, DW_AT_name);
- if (attr && DW_STRING (attr))
- {
- char *attrname=DW_STRING (attr);
- unsigned long hashval=hash(attrname, strlen(attrname)) % TYPE_HASH_SIZE;
-
- if (dwarf2_cached_types[hashval] != NULL)
- {
- const char *nameoftype;
- nameoftype = TYPE_NAME(dwarf2_cached_types[hashval]) == NULL ? TYPE_TAG_NAME(dwarf2_cached_types[hashval]) : TYPE_NAME(dwarf2_cached_types[hashval]);
- if (strcmp(attrname, nameoftype) == 0)
- {
- die->type=dwarf2_cached_types[hashval];
- }
- else
- {
- read_type_die (die, objfile, cu_header);
- dwarf2_cached_types[hashval] = die->type;
- }
- }
- else
- {
- read_type_die (die, objfile, cu_header);
- dwarf2_cached_types[hashval] = die->type;
- }
- }
- else
- {
- read_type_die (die, objfile, cu_header);
- }
-
+ read_type_die (die, objfile, cu_header);
if (!die->type)
{
dump_die (die);
dwarf2_empty_hash_tables (void)
{
memset (die_ref_table, 0, sizeof (die_ref_table));
- memset (dwarf2_cached_types, 0, sizeof(dwarf2_cached_types));
}
static unsigned int
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
+ case DW_FORM_ref8:
case DW_FORM_ref_udata:
result = cu_header_offset + DW_UNSND (attr);
break;