This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]