This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] fix objcopy PE -> ELF conversion
- From: Christian Franke <Christian dot Franke at t-online dot de>
- To: binutils at sourceware dot org
- Date: Mon, 22 Oct 2007 21:02:39 +0200
- Subject: [PATCH] fix objcopy PE -> ELF conversion
Objcopy cannot convert pe-i386 to elf32-i386. The offsets of the
pc-relative relocation entries are not converted properly.
(http://sourceware.org/bugzilla/show_bug.cgi?id=970)
I need some PE to ELF conversion for the Cygwin port of GRUB2. The first
working Cygwin patch for GRUB2 includes a workaround to load the broken
ELF modules produced by objcopy. It would be desirable to fix this in
objcopy itself.
The attached patch was tested with latest Cygwin binutils-20060817-1.
Also applies to current CVS without conflict (but was not actually
tested with this version).
Christian
2007-10-21 Christian Franke <franke@computer.org>
* objcopy.c (fix_relocation): New function to
fix pc-relative relocation offset, for PE to ELF only.
(copy_section): Call fix_relocation for section data.
--- binutils-20060817-1.orig/binutils/objcopy.c 2006-08-17 07:01:02.001000000 +0200
+++ binutils-20060817-1/binutils/objcopy.c 2007-10-21 21:51:11.468750000 +0200
@@ -2202,6 +2202,31 @@ loser:
status = 1;
}
+
+/* Fix pc-relative relocation.
+ When converting from PE to ELF, the pc-relative
+ relocation offset is off by 4.
+ (http://sourceware.org/bugzilla/show_bug.cgi?id=970) */
+
+static void
+fix_relocation (bfd *ibfd, arelent **relpp, long relcount, void *data, bfd *obfd)
+{
+ arelent **p;
+ long i;
+ /* For now, handle only the pe-i386 -> elf32-i386 case */
+ if (!(!strcmp (ibfd->xvec->name, "pe-i386") && !strcmp (obfd->xvec->name, "elf32-i386")))
+ return;
+ for (i = 0, p = relpp; i < relcount && *p; i++, p++)
+ {
+ arelent *q = *p;
+ if (q->howto->pc_relative && q->howto->size == 2)
+ /* elf32-i386 does not support addent in relocation info,
+ apply it to the section data */
+ *(long *)((char *)data+q->address) -= 4;
+ }
+}
+
+
/* Copy the data of input section ISECTION of IBFD
to an output section with the same name in OBFD.
If stripping then don't copy any relocation info. */
@@ -2255,6 +2280,7 @@ copy_section (bfd *ibfd, sec_ptr isectio
}
}
+ relpp = 0; relcount = 0;
if (relsize == 0)
bfd_set_reloc (obfd, osection, NULL, 0);
else
@@ -2295,6 +2321,9 @@ copy_section (bfd *ibfd, sec_ptr isectio
if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
RETURN_NONFATAL (bfd_get_filename (ibfd));
+ if (relcount > 0)
+ fix_relocation (ibfd, relpp, relcount, memhunk, obfd);
+
if (copy_byte >= 0)
{
/* Keep only every `copy_byte'th byte in MEMHUNK. */