This is the mail archive of the
cygwin-apps
mailing list for the Cygwin project.
[rebase/patch] Support IMAGE_REL_BASED_DIR64 relocations
- From: Corinna Vinschen <corinna-cygwin at cygwin dot com>
- To: Jason Tishler <jason at tishler dot net>
- Cc: cygwin-apps at cygwin dot com
- Date: Tue, 15 Jan 2013 13:37:10 +0100
- Subject: [rebase/patch] Support IMAGE_REL_BASED_DIR64 relocations
- Reply-to: cygwin-apps at cygwin dot com
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