/* local data types */
+/* We hold several abbreviation tables in memory at the same time. */
+#ifndef ABBREV_HASH_SIZE
+#define ABBREV_HASH_SIZE 121
+#endif
+
/* The data in a compilation unit header, after target2host
translation, looks like this. */
struct comp_unit_head
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 */
+
+ /* Offset to the first byte of this compilation unit header in the
+ * .debug_info section, for resolving relative reference dies. */
+
+ unsigned int offset;
+
+ /* Pointer to this compilation unit header in the .debug_info
+ * section */
+
+ char *cu_head_ptr;
+
+ /* Pointer to the first die of this compilatio unit. This will
+ * be the first byte following the compilation unit header. */
+
+ char *first_die_ptr;
+
+ /* Pointer to the next compilation unit header in the program. */
+
+ struct comp_unit_head *next;
+
+ /* DWARF abbreviation table associated with this compilation unit */
+
+ struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
};
/* The line number information for a compilation unit (found in the
char *data;
};
-/* We only hold one compilation unit's abbrevs in
- memory at any one time. */
-#ifndef ABBREV_HASH_SIZE
-#define ABBREV_HASH_SIZE 121
-#endif
#ifndef ATTR_ALLOC_CHUNK
#define ATTR_ALLOC_CHUNK 4
#endif
-static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
-
/* A hash table of die offsets for following references. */
#ifndef REF_HASH_SIZE
#define REF_HASH_SIZE 1021
{
"macro definition contains spaces in formal argument list:\n`%s'", 0, 0
};
+static struct complaint dwarf2_invalid_attrib_class =
+{
+ "invalid attribute class or form for '%s' in '%s'", 0, 0
+};
+static struct complaint dwarf2_invalid_pointer_size =
+{
+ "invalid pointer size %d", 0, 0
+};
/* local function prototypes */
char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int);
-static void dwarf2_read_abbrevs (bfd *, unsigned int);
+static void dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header);
static void dwarf2_empty_abbrev_table (PTR);
-static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int);
+static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int,
+ const struct comp_unit_head *cu_header);
static char *read_partial_die (struct partial_die_info *,
bfd *, char *,
char *, bfd *, const struct comp_unit_head *,
struct objfile *);
+static int attr_form_is_block (struct attribute *);
+
/* Try to locate the sections we need for DWARF 2 debugging
information and return true if we have enough to do something. */
dwarf_abbrev_buffer = dwarf2_read_section (objfile,
dwarf_abbrev_offset,
dwarf_abbrev_size);
- dwarf_line_buffer = dwarf2_read_section (objfile,
- dwarf_line_offset,
- dwarf_line_size);
+
+ if (dwarf_line_offset)
+ dwarf_line_buffer = dwarf2_read_section (objfile,
+ dwarf_line_offset,
+ dwarf_line_size);
+ else
+ dwarf_line_buffer = NULL;
if (dwarf_str_offset)
dwarf_str_buffer = dwarf2_read_section (objfile,
(long) (beg_of_comp_unit - dwarf_info_buffer));
return;
}
+ /* Complete the cu_header */
+ cu_header.offset = beg_of_comp_unit - dwarf_info_buffer;
+ cu_header.first_die_ptr = info_ptr;
+ cu_header.cu_head_ptr = beg_of_comp_unit;
+
/* Read the abbrevs for this compilation unit into a table */
- dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
- make_cleanup (dwarf2_empty_abbrev_table, NULL);
+ dwarf2_read_abbrevs (abfd, &cu_header);
+ make_cleanup (dwarf2_empty_abbrev_table, cu_header.dwarf2_abbrevs);
/* Read the compilation unit die */
info_ptr = read_partial_die (&comp_unit_die, abfd, info_ptr,
info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd);
/* Read the abbrevs for this compilation unit */
- dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
- make_cleanup (dwarf2_empty_abbrev_table, NULL);
+ dwarf2_read_abbrevs (abfd, &cu_header);
+ make_cleanup (dwarf2_empty_abbrev_table, cu_header.dwarf2_abbrevs);
dies = read_comp_unit (info_ptr, abfd, &cu_header);
header, so we can only read it if we've read the header
successfully. */
attr = dwarf_attr (die, DW_AT_macro_info);
- if (attr)
+ if (attr && line_header)
{
unsigned int macro_offset = DW_UNSND (attr);
dwarf_decode_macros (line_header, macro_offset,
attr = dwarf_attr (die, DW_AT_frame_base);
if (attr)
{
- CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ CORE_ADDR addr;
+
+ /* Support the .debug_loc offsets */
+ if (attr_form_is_block (attr))
+ {
+ addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ }
+ else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+ {
+ complain (&dwarf2_complex_location_expr);
+ addr = 0;
+ }
+ else
+ {
+ complain (&dwarf2_invalid_attrib_class, "DW_AT_frame_base", name);
+ addr = 0;
+ }
+
if (isderef)
complain (&dwarf2_unsupported_at_frame_base, name);
else if (isreg)
if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC)
{
struct type *return_type = TYPE_TARGET_TYPE (die->type);
- struct type **arg_types;
int nparams = TYPE_NFIELDS (die->type);
- int iparams;
- /* Copy argument types from the subroutine type. */
- arg_types = (struct type **)
- TYPE_ALLOC (fnp->type, (nparams + 1) * sizeof (struct type *));
- for (iparams = 0; iparams < nparams; iparams++)
- arg_types[iparams] = TYPE_FIELD_TYPE (die->type, iparams);
-
- /* Set last entry in argument type vector. */
- if (TYPE_VARARGS (die->type))
- arg_types[nparams] = NULL;
- else
- arg_types[nparams] = dwarf2_fundamental_type (objfile, FT_VOID);
-
- smash_to_method_type (fnp->type, type, return_type, arg_types);
+ /* TYPE is the domain of this method, and DIE->TYPE is the type
+ of the method itself (TYPE_CODE_METHOD). */
+ smash_to_method_type (fnp->type, type,
+ TYPE_TARGET_TYPE (die->type),
+ TYPE_FIELDS (die->type),
+ TYPE_NFIELDS (die->type),
+ TYPE_VARARGS (die->type));
/* Handle static member functions.
Dwarf2 has no clean way to discern C++ static and non-static
/* Get index in virtual function table if it is a virtual member function. */
attr = dwarf_attr (die, DW_AT_vtable_elem_location);
if (attr)
- fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2;
+ {
+ /* Support the .debug_loc offsets */
+ if (attr_form_is_block (attr))
+ {
+ fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2;
+ }
+ else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+ {
+ complain (&dwarf2_complex_location_expr);
+ }
+ else
+ {
+ complain (&dwarf2_invalid_attrib_class, "DW_AT_vtable_elem_location",
+ fieldname);
+ }
+ }
}
/* Create the vector of member function fields, and attach it to the type. */
attr = dwarf_attr (die, DW_AT_location);
if (attr)
{
- base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ /* Support the .debug_loc offsets */
+ if (attr_form_is_block (attr))
+ {
+ base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ }
+ else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+ {
+ complain (&dwarf2_complex_location_expr);
+ }
+ else
+ {
+ complain (&dwarf2_invalid_attrib_class, "DW_AT_location",
+ "common block member");
+ }
}
if (die->has_children)
{
const struct comp_unit_head *cu_header)
{
struct type *type;
- struct attribute *attr;
+ struct attribute *attr_byte_size;
+ struct attribute *attr_address_class;
+ int byte_size, addr_class;
if (die->type)
{
}
type = lookup_pointer_type (die_type (die, objfile, cu_header));
- attr = dwarf_attr (die, DW_AT_byte_size);
- if (attr)
- {
- TYPE_LENGTH (type) = DW_UNSND (attr);
- }
+
+ attr_byte_size = dwarf_attr (die, DW_AT_byte_size);
+ if (attr_byte_size)
+ byte_size = DW_UNSND (attr_byte_size);
else
+ byte_size = cu_header->addr_size;
+
+ attr_address_class = dwarf_attr (die, DW_AT_address_class);
+ if (attr_address_class)
+ addr_class = DW_UNSND (attr_address_class);
+ else
+ addr_class = DW_ADDR_none;
+
+ /* If the pointer size or address class is different than the
+ default, create a type variant marked as such and set the
+ length accordingly. */
+ if (TYPE_LENGTH (type) != byte_size || addr_class != DW_ADDR_none)
{
- TYPE_LENGTH (type) = cu_header->addr_size;
+ if (ADDRESS_CLASS_TYPE_FLAGS_P ())
+ {
+ int type_flags;
+
+ type_flags = ADDRESS_CLASS_TYPE_FLAGS (byte_size, addr_class);
+ gdb_assert ((type_flags & ~TYPE_FLAG_ADDRESS_CLASS_ALL) == 0);
+ type = make_type_with_address_space (type, type_flags);
+ }
+ else if (TYPE_LENGTH (type) != byte_size)
+ {
+ complain (&dwarf2_invalid_pointer_size, byte_size);
+ }
+ else {
+ /* Should we also complain about unhandled address classes? */
+ }
}
+
+ TYPE_LENGTH (type) = byte_size;
die->type = type;
}
in a hash table. */
static void
-dwarf2_read_abbrevs (bfd *abfd, unsigned int offset)
+dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header)
{
char *abbrev_ptr;
struct abbrev_info *cur_abbrev;
unsigned int abbrev_number, bytes_read, abbrev_name;
unsigned int abbrev_form, hash_number;
- /* empty the table */
- dwarf2_empty_abbrev_table (NULL);
+ /* Initialize dwarf2 abbrevs */
+ memset (cu_header->dwarf2_abbrevs, 0,
+ ABBREV_HASH_SIZE*sizeof (struct abbrev_info *));
- abbrev_ptr = dwarf_abbrev_buffer + offset;
+ abbrev_ptr = dwarf_abbrev_buffer + cu_header->abbrev_offset;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
}
hash_number = abbrev_number % ABBREV_HASH_SIZE;
- cur_abbrev->next = dwarf2_abbrevs[hash_number];
- dwarf2_abbrevs[hash_number] = cur_abbrev;
+ cur_abbrev->next = cu_header->dwarf2_abbrevs[hash_number];
+ cu_header->dwarf2_abbrevs[hash_number] = cur_abbrev;
/* Get next abbreviation.
Under Irix6 the abbreviations for a compilation unit are not
break;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
- if (dwarf2_lookup_abbrev (abbrev_number) != NULL)
+ if (dwarf2_lookup_abbrev (abbrev_number, cu_header) != NULL)
break;
}
}
/* ARGSUSED */
static void
-dwarf2_empty_abbrev_table (PTR ignore)
+dwarf2_empty_abbrev_table (PTR ptr_to_abbrevs_table)
{
int i;
struct abbrev_info *abbrev, *next;
+ struct abbrev_info **abbrevs;
+
+ abbrevs = (struct abbrev_info **)ptr_to_abbrevs_table;
for (i = 0; i < ABBREV_HASH_SIZE; ++i)
{
next = NULL;
- abbrev = dwarf2_abbrevs[i];
+ abbrev = abbrevs[i];
while (abbrev)
{
next = abbrev->next;
xfree (abbrev);
abbrev = next;
}
- dwarf2_abbrevs[i] = NULL;
+ abbrevs[i] = NULL;
}
}
/* Lookup an abbrev_info structure in the abbrev hash table. */
static struct abbrev_info *
-dwarf2_lookup_abbrev (unsigned int number)
+dwarf2_lookup_abbrev (unsigned int number, const struct comp_unit_head *cu_header)
{
unsigned int hash_number;
struct abbrev_info *abbrev;
hash_number = number % ABBREV_HASH_SIZE;
- abbrev = dwarf2_abbrevs[hash_number];
+ abbrev = cu_header->dwarf2_abbrevs[hash_number];
while (abbrev)
{
if (!abbrev_number)
return info_ptr;
- abbrev = dwarf2_lookup_abbrev (abbrev_number);
+ abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header);
if (!abbrev)
{
error ("Dwarf Error: Could not find abbrev number %d.", abbrev_number);
part_die->highpc = DW_ADDR (&attr);
break;
case DW_AT_location:
- part_die->locdesc = DW_BLOCK (&attr);
+ /* Support the .debug_loc offsets */
+ if (attr_form_is_block (&attr))
+ {
+ part_die->locdesc = DW_BLOCK (&attr);
+ }
+ else if (attr.form == DW_FORM_data4 || attr.form == DW_FORM_data8)
+ {
+ complain (&dwarf2_complex_location_expr);
+ }
+ else
+ {
+ complain (&dwarf2_invalid_attrib_class, "DW_AT_location",
+ "partial symbol information");
+ }
break;
case DW_AT_language:
part_die->language = DW_UNSND (&attr);
return info_ptr;
}
- abbrev = dwarf2_lookup_abbrev (abbrev_number);
+ abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header);
if (!abbrev)
{
error ("Dwarf Error: could not find abbrev number %d.", abbrev_number);
return retval;
}
-/* Reads the initial length from a section. The (draft) DWARF 2.1
+/* Read the initial length from a section. The (draft) DWARF 3
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.
+ An older, non-standard 64-bit format is also handled by this
+ function. The older format in question stores the initial length
+ as an 8-byte quantity without an escape value. Lengths greater
+ than 2^32 aren't very common which means that the initial 4 bytes
+ is almost always zero. Since a length value of zero doesn't make
+ sense for the 32-bit format, this initial zero can be considered to
+ be an escape value which indicates the presence of the older 64-bit
+ format. As written, the code can't detect (old format) lengths
+ greater than 4GB. If it becomes necessary to handle lengths somewhat
+ larger than 4GB, we could allow other small values (such as the
+ non-sensical values of 1, 2, and 3) to also be used as escape values
+ indicating the presence of the old format.
+
The value returned via bytes_read should be used to increment
the relevant pointer after calling read_initial_length().
[ 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
+ 3, draft 8, dated November 19, 2001. This document was obtained
from:
- http://reality.sgi.com/dehnert_engr/dwarf/dwarf2p1-draft4-000720.pdf
+ http://reality.sgiweb.org/davea/dwarf3-draft8-011125.pdf
This document is only a draft and is subject to change. (So beware.)
- - Kevin, Aug 4, 2000
+ Details regarding the older, non-standard 64-bit format were
+ determined empirically by examining 64-bit ELF files produced
+ by the SGI toolchain on an IRIX 6.5 machine.
+
+ - Kevin, July 16, 2002
] */
static LONGEST
cu_header->offset_size = 8;
}
}
+ else if (retval == 0)
+ {
+ /* Handle (non-standard) 64-bit DWARF2 formats such as that used
+ by IRIX. */
+ retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ *bytes_read = 8;
+ if (cu_header != NULL)
+ {
+ cu_header->initial_length_size = 8;
+ cu_header->offset_size = 8;
+ }
+ }
else
{
*bytes_read = 4;
cu_language = language_java;
break;
case DW_LANG_Ada83:
+ case DW_LANG_Ada95:
case DW_LANG_Cobol74:
case DW_LANG_Cobol85:
case DW_LANG_Pascal83:
free_line_header (struct line_header *lh)
{
if (lh->standard_opcode_lengths)
- free (lh->standard_opcode_lengths);
+ xfree (lh->standard_opcode_lengths);
/* Remember that all the lh->file_names[i].name pointers are
pointers into debug_line_buffer, and don't need to be freed. */
if (lh->file_names)
- free (lh->file_names);
+ xfree (lh->file_names);
/* Similarly for the include directory names. */
if (lh->include_dirs)
- free (lh->include_dirs);
+ xfree (lh->include_dirs);
- free (lh);
+ xfree (lh);
}
char *name;
struct attribute *attr = NULL;
struct attribute *attr2 = NULL;
- CORE_ADDR addr;
+ CORE_ADDR addr = 0;
name = dwarf2_linkage_name (die);
if (name)
attr2 = dwarf_attr (die, DW_AT_external);
if (attr2 && (DW_UNSND (attr2) != 0))
{
- SYMBOL_VALUE_ADDRESS (sym) =
- decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ /* Support the .debug_loc offsets */
+ if (attr_form_is_block (attr))
+ {
+ SYMBOL_VALUE_ADDRESS (sym) =
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ }
+ else if (attr->form == DW_FORM_data4
+ || attr->form == DW_FORM_data8)
+ {
+ complain (&dwarf2_complex_location_expr);
+ }
+ else
+ {
+ complain (&dwarf2_invalid_attrib_class, "DW_AT_location",
+ "external variable");
+ }
add_symbol_to_list (sym, &global_symbols);
/* In shared libraries the address of the variable
}
else
{
- SYMBOL_VALUE (sym) = addr =
- decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ /* Support the .debug_loc offsets */
+ if (attr_form_is_block (attr))
+ {
+ SYMBOL_VALUE (sym) = addr =
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ }
+ else if (attr->form == DW_FORM_data4
+ || attr->form == DW_FORM_data8)
+ {
+ complain (&dwarf2_complex_location_expr);
+ }
+ else
+ {
+ complain (&dwarf2_invalid_attrib_class, "DW_AT_location",
+ "external variable");
+ addr = 0;
+ }
add_symbol_to_list (sym, list_in_scope);
if (optimized_out)
{
return "DW_OP_xderef_size";
case DW_OP_nop:
return "DW_OP_nop";
+ /* DWARF 3 extensions. */
+ case DW_OP_push_object_address:
+ return "DW_OP_push_object_address";
+ case DW_OP_call2:
+ return "DW_OP_call2";
+ case DW_OP_call4:
+ return "DW_OP_call4";
+ case DW_OP_call_ref:
+ return "DW_OP_call_ref";
+ /* GNU extensions. */
+ case DW_OP_GNU_push_tls_address:
+ return "DW_OP_GNU_push_tls_address";
default:
return "OP_<unknown>";
}
isreg = 1;
unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
i += bytes_read;
-#if defined(HARRIS_TARGET) && defined(_M88K)
- /* The Harris 88110 gdb ports have long kept their special reg
- numbers between their gp-regs and their x-regs. This is
- not how our dwarf is generated. Punt. */
- unsnd += 6;
-#endif
stack[++stacki] = unsnd;
break;
at all until we actually get a filename. */
if (! pending_macros)
pending_macros = new_macro_table (&objfile->symbol_obstack,
- &objfile->macro_cache);
+ objfile->macro_cache);
if (! current_file)
/* If we have no current file, then this must be the start_file
}
}
}
+
+/* Check if the attribute's form is a DW_FORM_block*
+ if so return true else false. */
+static int
+attr_form_is_block (struct attribute *attr)
+{
+ return (attr == NULL ? 0 :
+ attr->form == DW_FORM_block1
+ || attr->form == DW_FORM_block2
+ || attr->form == DW_FORM_block4
+ || attr->form == DW_FORM_block);
+}