This is the mail archive of the cygwin-apps 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]

[rebase/patch] Support IMAGE_REL_BASED_DIR64 relocations


Hi Jason,

While looking into Marco's rebase problem I noticed that 64 bit support
in rebase was not complete.  64 bit uses IMAGE_REL_BASED_DIR64 relocation
entries, which were simply ignored since only the 32 bit variation
IMAGE_REL_BASED_HIGHLOW was supported at all.  Also, it would have been
impossible to relocate 64 bit DLLs to addresses beyond the 4GB border
since the offset difference was kept as an int value.  The below patch
fixes both oversight.

Ok to apply?


Thanks,
Corinna


	* objectfile.h (LinkedObjectFile::performRelocation): Change type of
	parameter to int64_t.
	* rebaseimage.cc (ReBaseImage64): Change type of local variable
	difference to int64_t.
	* sections.cc (Relocations::check): Fix formatting.
	(Relocations::relocate): Take difference parameter as int64_t.  Call
	cursec->debugprint rather than cursec->print and drop FIXME comment.
	Handle Windows relocation info types IMAGE_REL_BASED_ABSOLUTE,
	IMAGE_REL_BASED_HIGHLOW and IMAGE_REL_BASED_DIR64.  Print error
	output if another relocation type is found.  Fix formatting.
	* sections.h (Relocations::relocate): Change type of parameter to
	int64_t.


Index: imagehelper/objectfile.h
===================================================================
RCS file: /sourceware/projects/cygwin-apps-home/cvsfiles/rebase/imagehelper/objectfile.h,v
retrieving revision 1.6
diff -u -p -r1.6 objectfile.h
--- imagehelper/objectfile.h	19 Mar 2012 17:57:49 -0000	1.6
+++ imagehelper/objectfile.h	15 Jan 2013 12:35:45 -0000
@@ -125,7 +125,7 @@ class LinkedObjectFile : public ObjectFi
     {
       return relocs->fix();
     }
-    bool performRelocation(int difference)
+    bool performRelocation(int64_t difference)
     {
       return relocs->relocate(difference);
     }
Index: imagehelper/rebaseimage.cc
===================================================================
RCS file: /sourceware/projects/cygwin-apps-home/cvsfiles/rebase/imagehelper/rebaseimage.cc,v
retrieving revision 1.6
diff -u -p -r1.6 rebaseimage.cc
--- imagehelper/rebaseimage.cc	30 Apr 2012 13:37:16 -0000	1.6
+++ imagehelper/rebaseimage.cc	15 Jan 2013 12:35:45 -0000
@@ -118,7 +118,7 @@ BOOL ReBaseImage64 (
       ntheader32->FileHeader.TimeDateStamp = TimeStamp;
     }
 
-  int difference = *NewImageBase - *OldImageBase;
+  int64_t difference = *NewImageBase - *OldImageBase;
 
   if (!dll.performRelocation(difference))
     {
Index: imagehelper/sections.cc
===================================================================
RCS file: /sourceware/projects/cygwin-apps-home/cvsfiles/rebase/imagehelper/sections.cc,v
retrieving revision 1.4
diff -u -p -r1.4 sections.cc
--- imagehelper/sections.cc	8 Jul 2011 07:18:55 -0000	1.4
+++ imagehelper/sections.cc	15 Jan 2013 12:35:45 -0000
@@ -302,14 +302,15 @@ bool Relocations::check(void)
       int NumOfRelocs = (relocp->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof (WORD);
       int va = relocp->VirtualAddress;
       PWORD p = (PWORD)((uintptr_t)relocp + sizeof(IMAGE_BASE_RELOCATION));
-	    if (debug)
-	      	std::cerr << "debug: blocksize= " << std::dec << NumOfRelocs << std::endl;
+      if (debug)
+	  std::cerr << "debug: blocksize= " << std::dec << NumOfRelocs << std::endl;
 
       cursec = sections->find(va);
-	    if (debug) {
-	      	std::cerr << "debug: section= "; 
-	      	cursec->debugprint();
-      }
+      if (debug)
+        {
+	  std::cerr << "debug: section= "; 
+	  cursec->debugprint();
+	}
       if (!cursec)
         {
           if (debug)
@@ -319,11 +320,12 @@ bool Relocations::check(void)
           errors++;
           continue;
         }
-	    for (int i = 0; i < NumOfRelocs; i++,p++) {
-		    int location = (*p & 0x0fff) + va;
-	      if (debug)
-	      	std::cerr << "debug: location= 0x" << std::setw(8) << std::setfill('0') << std::hex << location << std::endl;
-		  }
+      if (debug)
+	for (int i = 0; i < NumOfRelocs; i++,p++)
+	  {
+	    int location = (*p & 0x0fff) + va;
+	    std::cerr << "debug: location= 0x" << std::setw(8) << std::setfill('0') << std::hex << location << std::endl;
+	  }
     }
   return errors == 0;
 }
@@ -365,7 +367,7 @@ bool Relocations::fix(void)
 }
 
 
-bool Relocations::relocate(int difference)
+bool Relocations::relocate(int64_t difference)
 {
   PIMAGE_BASE_RELOCATION relocp = relocs;
   int WholeNumOfRelocs = 0;
@@ -386,8 +388,6 @@ bool Relocations::relocate(int differenc
         }
       WholeNumOfRelocs += NumOfRelocs;
 
-      int adjust;
-
       Section *cursec = sections->find(va);
       if (!cursec)
         {
@@ -398,29 +398,55 @@ bool Relocations::relocate(int differenc
         	return false;
         }
       else if (debug)
-        // FIXME: this goes to cout but debug message should go to cerr
-        cursec->print("currently relocated section");
-      adjust = cursec->getAdjust();
+        cursec->debugprint("currently relocated section");
+
+      int adjust = cursec->getAdjust();
 
       for (int i = 0; i < NumOfRelocs; i++,p++)
         {
-          if ((*p & 0xf000) == 0x3000)
-            {
-              int location = (*p & 0x0fff) + va;
-              if (debug)
-                {
-                  std::cerr << "0x" \
-                  << std::setw(8) << std::setfill('0') << std::hex << location << std::dec \
-                  << " - ";
-                  std::cerr << "0x" \
-                  << std::setw(8) << std::setfill('0') << std::hex << location + adjust + 3 << std::dec \
-                  << std::endl;
-                }
-              int *patch_adr = (int *)cursec->rva2real(location);
-              *patch_adr += difference;
-            }
+	  WORD rel_type = (*p & 0xf000) >> 12;
+	  int location = (*p & 0x0fff) + va;
+
+	  switch (rel_type)
+	    {
+	    case IMAGE_REL_BASED_ABSOLUTE:
+	      break;
+	    case IMAGE_REL_BASED_HIGHLOW:
+	      {
+		if (debug)
+		  {
+		    std::cerr << "HIGHLOW: 0x" \
+		    << std::setw(8) << std::setfill('0') << std::hex << location << std::dec \
+		    << " - ";
+		    std::cerr << "0x" \
+		    << std::setw(8) << std::setfill('0') << std::hex << location + adjust + 3 << std::dec \
+		    << std::endl;
+		  }
+		int32_t *patch_adr = (int *)cursec->rva2real(location);
+		*patch_adr += difference;
+	      }
+	      break;
+	    case IMAGE_REL_BASED_DIR64:
+	      {
+		if (debug)
+		  {
+		    std::cerr << "  DIR64: 0x" \
+		    << std::setw(16) << std::setfill('0') << std::hex << location << std::dec \
+		    << " - ";
+		    std::cerr << "0x" \
+		    << std::setw(16) << std::setfill('0') << std::hex << location + adjust + 7 << std::dec \
+		    << std::endl;
+		  }
+		int64_t *patch_adr = (int64_t *)cursec->rva2real(location);
+		*patch_adr += difference;
+	      }
+	      break;
+	    default:
+	      std::cerr << "Unsupported relocation type " << rel_type << std::endl;
+	      break;
+	    }
         }
     }
-	return true;
+  return true;
 }
 
Index: imagehelper/sections.h
===================================================================
RCS file: /sourceware/projects/cygwin-apps-home/cvsfiles/rebase/imagehelper/sections.h,v
retrieving revision 1.5
diff -u -p -r1.5 sections.h
--- imagehelper/sections.h	29 Jul 2011 13:17:44 -0000	1.5
+++ imagehelper/sections.h	15 Jan 2013 12:35:45 -0000
@@ -210,7 +210,7 @@ class Relocations : SectionBase
     bool fix(void);
 
     // precondition: fixed dll
-    bool relocate(int difference);
+    bool relocate(int64_t difference);
 
   private:
     PIMAGE_BASE_RELOCATION relocs;


-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat


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