diff options
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/elf-eh-frame.c | 34 |
2 files changed, 37 insertions, 4 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 99ada02..357feb7 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2010-11-24 Alan Modra <amodra@gmail.com> + + PR ld/12253 + * elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Correct + DW_EH_PE_datarel handling. Truncate .eh_frame_hdr address to + ptr_size. + 2010-11-23 Mingming Sun <mingm.sun@gmail.com> * elfxx-mips.c (mips_set_isa_flags): Move bfd_mach_loongson_3a diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c index 8380ef8..0a22138 100644 --- a/bfd/elf-eh-frame.c +++ b/bfd/elf-eh-frame.c @@ -1572,10 +1572,31 @@ _bfd_elf_write_section_eh_frame (bfd *abfd, break; case DW_EH_PE_datarel: { - asection *got = bfd_get_section_by_name (abfd, ".got"); - - BFD_ASSERT (got != NULL); - address += got->vma; + switch (abfd->arch_info->arch) + { + case bfd_arch_ia64: + BFD_ASSERT (elf_gp (abfd) != 0); + address += elf_gp (abfd); + break; + default: + (*info->callbacks->einfo) + (_("%P: DW_EH_PE_datarel unspecified" + " for this architecture.\n")); + /* Fall thru */ + case bfd_arch_frv: + case bfd_arch_i386: + BFD_ASSERT (htab->hgot != NULL + && ((htab->hgot->root.type + == bfd_link_hash_defined) + || (htab->hgot->root.type + == bfd_link_hash_defweak))); + address + += (htab->hgot->root.u.def.value + + htab->hgot->root.u.def.section->output_offset + + (htab->hgot->root.u.def.section->output_section + ->vma)); + break; + } } break; case DW_EH_PE_pcrel: @@ -1596,6 +1617,11 @@ _bfd_elf_write_section_eh_frame (bfd *abfd, if (hdr_info) { + /* The address calculation may overflow, giving us a + value greater than 4G on a 32-bit target when + dwarf_vma is 64-bit. */ + if (sizeof (address) > 4 && ptr_size == 4) + address &= 0xffffffff; hdr_info->array[hdr_info->array_count].initial_loc = address; hdr_info->array[hdr_info->array_count++].fde = (sec->output_section->vma |