X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fdwarf2read.c;h=16a1c4225d6ed4ae160c7383867539a762edd9de;hb=8b2dbe47f314187de7089f4ffeb26c100b7d4c3e;hp=9fa8fb3c4639da03f832a8cb66493d470872a4fd;hpb=ad2f7632f9c475a71481499715635ea3344b92d8;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 9fa8fb3c46..16a1c4225d 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -162,6 +162,11 @@ unsigned int dwarf_eh_frame_size; /* 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 @@ -174,6 +179,29 @@ 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 @@ -312,17 +340,10 @@ struct dwarf_block 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 @@ -658,6 +679,14 @@ static struct complaint dwarf2_macro_spaces_in_definition = { "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 */ @@ -682,11 +711,12 @@ static void psymtab_to_symtab_1 (struct partial_symtab *); 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 *, @@ -799,7 +829,8 @@ static void dwarf2_attach_fields_to_type (struct field_info *, 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 *, @@ -906,6 +937,8 @@ static void dwarf_decode_macros (struct line_header *, unsigned int, 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. */ @@ -1003,9 +1036,13 @@ dwarf2_build_psymtabs (struct objfile *objfile, int mainline) 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, @@ -1200,9 +1237,14 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) (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, @@ -1549,8 +1591,8 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) 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); @@ -1802,7 +1844,7 @@ read_file_scope (struct die_info *die, struct objfile *objfile, 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, @@ -1870,7 +1912,24 @@ read_func_scope (struct die_info *die, struct objfile *objfile, 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) @@ -2232,7 +2291,7 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type, 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; @@ -2300,7 +2359,9 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, 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), @@ -2348,7 +2409,22 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, /* 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. */ @@ -2474,7 +2550,7 @@ read_structure_scope (struct die_info *die, struct objfile *objfile, { /* 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) { @@ -2812,7 +2888,20 @@ read_common_block (struct die_info *die, struct objfile *objfile, 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) { @@ -2840,7 +2929,9 @@ read_tag_pointer_type (struct die_info *die, struct objfile *objfile, 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) { @@ -2848,15 +2939,42 @@ read_tag_pointer_type (struct die_info *die, struct objfile *objfile, } 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; } @@ -3287,17 +3405,18 @@ dwarf2_read_section (struct objfile *objfile, file_ptr offset, 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; @@ -3336,8 +3455,8 @@ dwarf2_read_abbrevs (bfd *abfd, unsigned int offset) } 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 @@ -3351,7 +3470,7 @@ dwarf2_read_abbrevs (bfd *abfd, unsigned int offset) 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; } } @@ -3360,15 +3479,18 @@ dwarf2_read_abbrevs (bfd *abfd, unsigned int offset) /* 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; @@ -3376,20 +3498,20 @@ dwarf2_empty_abbrev_table (PTR ignore) 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) { @@ -3421,7 +3543,7 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd, 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); @@ -3458,7 +3580,20 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd, 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); @@ -3552,7 +3687,7 @@ read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr, 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); @@ -3799,12 +3934,25 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, 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(). @@ -3815,14 +3963,18 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, [ 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 @@ -3843,6 +3995,18 @@ read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header, 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; @@ -4017,6 +4181,7 @@ set_cu_language (unsigned int lang) 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: @@ -4522,7 +4687,7 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, char *name; struct attribute *attr = NULL; struct attribute *attr2 = NULL; - CORE_ADDR addr; + CORE_ADDR addr = 0; name = dwarf2_linkage_name (die); if (name) @@ -4606,8 +4771,22 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, 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 @@ -4630,8 +4809,23 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, } 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) { @@ -5831,6 +6025,18 @@ dwarf_stack_op_name (register unsigned op) 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_"; } @@ -6235,12 +6441,6 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile, 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; @@ -6482,7 +6682,7 @@ macro_start_file (int file, int line, 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 @@ -6800,3 +7000,15 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, } } } + +/* 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); +}