This is the mail archive of the cygwin mailing list for the Cygwin 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] Convert PE relocatable modules to ELF with objcopy


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 <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.


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/

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