summaryrefslogtreecommitdiff
path: root/bfd/elf-eh-frame.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2010-11-23 23:30:03 +0000
committerAlan Modra <amodra@bigpond.net.au>2010-11-23 23:30:03 +0000
commitcdb2275c9ffb41cacdcee078cf43718ab66c091e (patch)
tree279c8d9045bffb6d91d1372e02d88eab3e6cbf0a /bfd/elf-eh-frame.c
parentcdf41f2aaa9fc0ce1d3d70b5a044365853bb45b7 (diff)
downloadbinutils-redhat-cdb2275c9ffb41cacdcee078cf43718ab66c091e.tar.gz
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.
Diffstat (limited to 'bfd/elf-eh-frame.c')
-rw-r--r--bfd/elf-eh-frame.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index 8380ef8600..0a22138147 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