aboutsummaryrefslogtreecommitdiff
path: root/bfd/dwarf2.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/dwarf2.c')
-rw-r--r--bfd/dwarf2.c132
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++;
}