objcopy from binutils-20060817-1 cannot convert pe-i396 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 recently started a Cygwin port of GRUB2 ([Maybe ITP later]-).
(http://lists.gnu.org/archive/html/grub-devel/2007-10/msg00071.html)
GRUB2 loadable modules use ELF format, therefore, some PE to ELF
conversion is required to build on Cygwin.
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.
A patch is attached.
2007-10-21 Christian Franke <[EMAIL PROTECTED]>
* 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.
Christian
--- 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. */
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Problem reports: http://cygwin.com/problems.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/