bfd_byte *data;
};
-struct loadable_section
+struct adjusted_section
{
asection *section;
bfd_vma adj_vma;
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. */
/* 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;
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;
}
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;
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;
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:
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;
}
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;
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;
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)
+ 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;
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. */
+ ~((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++;
}
symbols, 0,
&stash->info_ptr_memory, &total_size))
goto done;
- stash->info_ptr = stash->info_ptr_memory;
- stash->info_ptr_end = stash->info_ptr + total_size;
}
else
{
if (stash->info_ptr_memory == NULL)
goto done;
- stash->info_ptr = stash->info_ptr_memory;
- stash->info_ptr_end = stash->info_ptr;
-
+ total_size = 0;
for (msec = find_debug_info (debug_bfd, NULL);
msec;
msec = find_debug_info (debug_bfd, msec))
{
bfd_size_type size;
- bfd_size_type start;
size = msec->size;
if (size == 0)
continue;
- start = stash->info_ptr_end - stash->info_ptr;
-
- if ((bfd_simple_get_relocated_section_contents
- (debug_bfd, msec, stash->info_ptr + start, symbols))
- == NULL)
- continue;
+ if (!(bfd_simple_get_relocated_section_contents
+ (debug_bfd, msec, stash->info_ptr_memory + total_size,
+ symbols)))
+ goto done;
- stash->info_ptr_end = stash->info_ptr + start + size;
+ total_size += size;
}
-
- BFD_ASSERT (stash->info_ptr_end == stash->info_ptr + total_size);
}
else
{
/* Case 3: multiple sections, some or all compressed. */
- stash->info_ptr_memory = bfd_malloc (1);
- stash->info_ptr = stash->info_ptr_memory;
- stash->info_ptr_end = stash->info_ptr;
+ stash->info_ptr_memory = NULL;
+ total_size = 0;
for (msec = find_debug_info (debug_bfd, NULL);
msec;
msec = find_debug_info (debug_bfd, msec))
{
bfd_size_type size = msec->size;
- bfd_byte* buffer
- = (bfd_simple_get_relocated_section_contents
- (debug_bfd, msec, NULL, symbols));
- if (! buffer)
+ bfd_byte* buffer;
+
+ if (size == 0)
continue;
+
+ buffer = (bfd_simple_get_relocated_section_contents
+ (debug_bfd, msec, NULL, symbols));
+ if (! buffer)
+ goto done;
+
if (strcmp (msec->name, DWARF2_COMPRESSED_DEBUG_INFO) == 0)
{
if (! bfd_uncompress_section_contents (&buffer, &size))
- continue;
+ {
+ free (buffer);
+ goto done;
+ }
}
- stash->info_ptr = bfd_realloc (stash->info_ptr,
- stash->info_ptr_end
- - stash->info_ptr + size);
- memcpy (stash->info_ptr_end, buffer, size);
+ stash->info_ptr_memory = bfd_realloc (stash->info_ptr_memory,
+ total_size + size);
+ memcpy (stash->info_ptr_memory + total_size, buffer, size);
free (buffer);
- stash->info_ptr_end += size;
+ total_size += size;
}
}
}
+ stash->info_ptr = stash->info_ptr_memory;
+ stash->info_ptr_end = stash->info_ptr + total_size;
stash->sec = find_debug_info (debug_bfd, NULL);
stash->sec_info_ptr = stash->info_ptr;
stash->syms = symbols;
}
}
- free (stash->dwarf_abbrev_buffer);
- free (stash->dwarf_line_buffer);
- free (stash->dwarf_ranges_buffer);
- free (stash->info_ptr_memory);
+ if (stash->dwarf_abbrev_buffer)
+ free (stash->dwarf_abbrev_buffer);
+ if (stash->dwarf_line_buffer)
+ free (stash->dwarf_line_buffer);
+ if (stash->dwarf_str_buffer)
+ free (stash->dwarf_str_buffer);
+ if (stash->dwarf_ranges_buffer)
+ free (stash->dwarf_ranges_buffer);
+ if (stash->info_ptr_memory)
+ free (stash->info_ptr_memory);
}