This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PR ld/12253 DW_EH_PE_datarel
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org
- Cc: Jakub Jelinek <jakub at redhat dot com>
- Date: Wed, 24 Nov 2010 10:57:25 +1030
- Subject: PR ld/12253 DW_EH_PE_datarel
DW_EH_PE_datarel is quite horrible. Not only is its behaviour
architecture dependent, it is also context sensitive. When used in
.eh_frame_hdr, DW_EH_PE_datarel means relative to the .eh_frame_hdr
section. Elsewhere it is relative to a base address chosen
differently on different architectures, and unspecified on most. i386
defines the base as DT_PLTGOT, and frv as _GLOBAL_OFFSET_TABLE_ (see
gcc/unwind-dw2-fde-glibc.c). These two happen to be identical. ia64
defines the base as __gp.
Committed mainline, probably should go on branch too. Tristan?
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.
Index: bfd/elf-eh-frame.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-eh-frame.c,v
retrieving revision 1.84
diff -u -p -r1.84 elf-eh-frame.c
--- bfd/elf-eh-frame.c 9 Apr 2010 14:40:15 -0000 1.84
+++ bfd/elf-eh-frame.c 23 Nov 2010 22:37:08 -0000
@@ -1572,10 +1572,31 @@ _bfd_elf_write_section_eh_frame (bfd *ab
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 *ab
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
--
Alan Modra
Australia Development Lab, IBM