/* 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
{
"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 *,
struct type *, struct objfile *);
static void dwarf2_add_member_fn (struct field_info *,
- struct die_info *, struct objfile *objfile,
+ struct die_info *, struct type *,
+ struct objfile *objfile,
const struct comp_unit_head *);
static void dwarf2_attach_fn_fields_to_type (struct field_info *,
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,
static void
dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
- struct objfile *objfile,
+ struct type *type, struct objfile *objfile,
const struct comp_unit_head *cu_header)
{
struct attribute *attr;
struct type *return_type = TYPE_TARGET_TYPE (die->type);
int nparams = TYPE_NFIELDS (die->type);
- smash_to_method_type (fnp->type, die->type,
+ /* 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),
{
/* C++ member function. */
process_die (child_die, objfile, cu_header);
- dwarf2_add_member_fn (&fi, child_die, objfile, cu_header);
+ dwarf2_add_member_fn (&fi, child_die, type, objfile, cu_header);
}
else if (child_die->tag == DW_TAG_inheritance)
{
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);
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 "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>";
}