diff options
Diffstat (limited to 'bfd/dwarf2.c')
-rw-r--r-- | bfd/dwarf2.c | 132 |
1 files changed, 99 insertions, 33 deletions
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index c53fdf0..a4918ac 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -75,7 +75,7 @@ struct dwarf_block bfd_byte *data; }; -struct loadable_section +struct adjusted_section { asection *section; bfd_vma adj_vma; @@ -143,11 +143,11 @@ struct dwarf2_debug use. */ struct funcinfo *inliner_chain; - /* Number of loadable sections. */ - unsigned int loadable_section_count; + /* Number of sections whose VMA we must adjust. */ + unsigned int adjusted_section_count; - /* Array of loadable sections. */ - struct loadable_section *loadable_sections; + /* Array of sections with adjusted VMA. */ + struct adjusted_section *adjusted_sections; /* Number of times find_line is called. This is used in the heuristic for enabling the info hash tables. */ @@ -237,6 +237,9 @@ struct comp_unit /* Pointer to dwarf2_debug structure. */ struct dwarf2_debug *stash; + /* DWARF format version for this unit - from unit header. */ + int version; + /* Address size for this unit - from unit header. */ unsigned char addr_size; @@ -742,9 +745,20 @@ read_attribute_value (struct attribute *attr, switch (form) { - case DW_FORM_addr: - /* FIXME: DWARF3 draft says DW_FORM_ref_addr is offset_size. */ case DW_FORM_ref_addr: + /* DW_FORM_ref_addr is an address in DWARF2, and an offset in + DWARF3. */ + if (unit->version == 3) + { + if (unit->offset_size == 4) + attr->u.val = read_4_bytes (unit->abfd, info_ptr); + else + attr->u.val = read_8_bytes (unit->abfd, info_ptr); + info_ptr += unit->offset_size; + break; + } + /* FALLTHROUGH */ + case DW_FORM_addr: attr->u.val = read_address (unit, info_ptr); info_ptr += unit->addr_size; break; @@ -1705,16 +1719,30 @@ lookup_symbol_in_variable_table (struct comp_unit *unit, } static char * -find_abstract_instance_name (struct comp_unit *unit, bfd_uint64_t die_ref) +find_abstract_instance_name (struct comp_unit *unit, + struct attribute *attr_ptr) { bfd *abfd = unit->abfd; bfd_byte *info_ptr; unsigned int abbrev_number, bytes_read, i; struct abbrev_info *abbrev; + bfd_uint64_t die_ref = attr_ptr->u.val; struct attribute attr; char *name = 0; - info_ptr = unit->info_ptr_unit + die_ref; + /* DW_FORM_ref_addr can reference an entry in a different CU. It + is an offset from the .debug_info section, not the current CU. */ + if (attr_ptr->form == DW_FORM_ref_addr) + { + /* We only support DW_FORM_ref_addr within the same file, so + any relocations should be resolved already. */ + if (!die_ref) + abort (); + + info_ptr = unit->stash->sec_info_ptr + die_ref; + } + else + info_ptr = unit->info_ptr_unit + die_ref; abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); info_ptr += bytes_read; @@ -1740,7 +1768,7 @@ find_abstract_instance_name (struct comp_unit *unit, bfd_uint64_t die_ref) name = attr.u.str; break; case DW_AT_specification: - name = find_abstract_instance_name (unit, attr.u.val); + name = find_abstract_instance_name (unit, &attr); break; case DW_AT_MIPS_linkage_name: name = attr.u.str; @@ -1902,7 +1930,7 @@ scan_unit_for_symbols (struct comp_unit *unit) break; case DW_AT_abstract_origin: - func->name = find_abstract_instance_name (unit, attr.u.val); + func->name = find_abstract_instance_name (unit, &attr); break; case DW_AT_name: @@ -2070,9 +2098,9 @@ parse_comp_unit (struct dwarf2_debug *stash, addr_size = read_1_byte (abfd, info_ptr); info_ptr += 1; - if (version != 2) + if (version != 2 && version != 3) { - (*_bfd_error_handler) (_("Dwarf Error: found dwarf version '%u', this reader only handles version 2 information."), version); + (*_bfd_error_handler) (_("Dwarf Error: found dwarf version '%u', this reader only handles version 2 and 3 information."), version); bfd_set_error (bfd_error_bad_value); return 0; } @@ -2120,6 +2148,7 @@ parse_comp_unit (struct dwarf2_debug *stash, amt = sizeof (struct comp_unit); unit = bfd_zalloc (abfd, amt); unit->abfd = abfd; + unit->version = version; unit->addr_size = addr_size; unit->offset_size = offset_size; unit->abbrevs = abbrevs; @@ -2472,49 +2501,63 @@ find_debug_info (bfd *abfd, asection *after_sec) return NULL; } -/* Unset vmas for loadable sections in STASH. */ +/* Unset vmas for adjusted sections in STASH. */ static void unset_sections (struct dwarf2_debug *stash) { unsigned int i; - struct loadable_section *p; + struct adjusted_section *p; - i = stash->loadable_section_count; - p = stash->loadable_sections; + i = stash->adjusted_section_count; + p = stash->adjusted_sections; for (; i > 0; i--, p++) p->section->vma = 0; } -/* Set unique vmas for loadable sections in ABFD and save vmas in - STASH for unset_sections. */ +/* Set unique VMAs for loadable and DWARF sections in ABFD and save + VMAs in STASH for unset_sections. */ static bfd_boolean place_sections (bfd *abfd, struct dwarf2_debug *stash) { - struct loadable_section *p; + struct adjusted_section *p; unsigned int i; - if (stash->loadable_section_count != 0) + if (stash->adjusted_section_count != 0) { - i = stash->loadable_section_count; - p = stash->loadable_sections; + i = stash->adjusted_section_count; + p = stash->adjusted_sections; for (; i > 0; i--, p++) p->section->vma = p->adj_vma; } else { asection *sect; - bfd_vma last_vma = 0; + bfd_vma last_vma = 0, last_dwarf = 0; bfd_size_type amt; - struct loadable_section *p; + struct adjusted_section *p; i = 0; for (sect = abfd->sections; sect != NULL; sect = sect->next) { bfd_size_type sz; + int is_debug_info; + + if (sect->vma != 0) + continue; + + /* We need to adjust the VMAs of any .debug_info sections. + Skip compressed ones, since no relocations could target + them - they should not appear in object files anyway. */ + if (strcmp (sect->name, DWARF2_DEBUG_INFO) == 0) + is_debug_info = 1; + else if (CONST_STRNEQ (sect->name, GNU_LINKONCE_INFO)) + is_debug_info = 1; + else + is_debug_info = 0; - if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0) + if (!is_debug_info && (sect->flags & SEC_LOAD) == 0) continue; sz = sect->rawsize ? sect->rawsize : sect->size; @@ -2524,19 +2567,33 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash) i++; } - amt = i * sizeof (struct loadable_section); - p = (struct loadable_section *) bfd_zalloc (abfd, amt); + amt = i * sizeof (struct adjusted_section); + p = (struct adjusted_section *) bfd_zalloc (abfd, amt); if (! p) return FALSE; - stash->loadable_sections = p; - stash->loadable_section_count = i; + stash->adjusted_sections = p; + stash->adjusted_section_count = i; for (sect = abfd->sections; sect != NULL; sect = sect->next) { bfd_size_type sz; + int is_debug_info; - if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0) + if (sect->vma != 0) + continue; + + /* We need to adjust the VMAs of any .debug_info sections. + Skip compressed ones, since no relocations could target + them - they should not appear in object files anyway. */ + if (strcmp (sect->name, DWARF2_DEBUG_INFO) == 0) + is_debug_info = 1; + else if (CONST_STRNEQ (sect->name, GNU_LINKONCE_INFO)) + is_debug_info = 1; + else + is_debug_info = 0; + + if (!is_debug_info && (sect->flags & SEC_LOAD) == 0) continue; sz = sect->rawsize ? sect->rawsize : sect->size; @@ -2544,7 +2601,13 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash) continue; p->section = sect; - if (last_vma != 0) + if (is_debug_info) + { + BFD_ASSERT (sect->alignment_power == 0); + sect->vma = last_dwarf; + last_dwarf += sz; + } + else if (last_vma != 0) { /* Align the new address to the current section alignment. */ @@ -2552,9 +2615,12 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash) + ~((bfd_vma) -1 << sect->alignment_power)) & ((bfd_vma) -1 << sect->alignment_power)); sect->vma = last_vma; + last_vma += sect->vma + sz; } + else + last_vma += sect->vma + sz; + p->adj_vma = sect->vma; - last_vma += sect->vma + sz; p++; } |