Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
COFF 64bit relocation stubs
Redirect IMAGE_REL_AMD64_REL32_X type relocations in PE/COFF objects for 64bit builds, where address distances may exceed the 32bit integer range. Stubs are generated in the caller's section and emit a IMAGE_REL_AMD64_ADDR64 type relocation that allow branching to a 64bit absolute address callee.
  • Loading branch information
weliveindetail committed Oct 4, 2016
1 parent bd79d9a commit 97cd336
Showing 1 changed file with 67 additions and 12 deletions.
79 changes: 67 additions & 12 deletions lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h
Expand Up @@ -37,7 +37,7 @@ class RuntimeDyldCOFFX86_64 : public RuntimeDyldCOFF {
: RuntimeDyldCOFF(MM, Resolver) {}

unsigned getMaxStubSize() override {
return 6; // 2-byte jmp instruction + 32-bit relative address
return 14; // 2-byte jmp instruction + 32-bit relative address
}

// The target location for the relocation is described by RE.SectionID and
Expand Down Expand Up @@ -106,12 +106,43 @@ class RuntimeDyldCOFFX86_64 : public RuntimeDyldCOFF {
}
}

uint64_t generateRelocationStub(unsigned SectionID, StringRef TargetName,
uint64_t Offset, uint64_t RelType,
uint64_t Addend, StubMap &Stubs) {
RelocationValueRef OriginalRelValueRef;
OriginalRelValueRef.SectionID = SectionID;
OriginalRelValueRef.Offset = Offset;
OriginalRelValueRef.Addend = Addend;
OriginalRelValueRef.SymbolName = TargetName.data();

StubMap::const_iterator i = Stubs.find(OriginalRelValueRef);

if (i == Stubs.end()) {
DEBUG(dbgs() << " Create a new stub function for "
<< TargetName.data() << "\n");

SectionEntry &Section = Sections[SectionID];
uintptr_t StubOffset = Section.getStubOffset();

createStubFunction(Section.getAddressWithOffset(StubOffset));
Section.advanceStubOffset(getMaxStubSize());

Stubs[OriginalRelValueRef] = StubOffset;
return StubOffset;
}
else {
DEBUG(dbgs() << " Stub function found for "
<< TargetName.data() << "\n");

return i->second;
}
}

Expected<relocation_iterator>
processRelocationRef(unsigned SectionID,
relocation_iterator RelI,
const ObjectFile &Obj,
ObjSectionToIDMap &ObjSectionToID,
StubMap &Stubs) override {
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
const ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID,
StubMap &Stubs) override
{
// If possible, find the symbol referred to in the relocation,
// and the section that contains it.
symbol_iterator Symbol = RelI->getSymbol();
Expand All @@ -131,14 +162,43 @@ class RuntimeDyldCOFFX86_64 : public RuntimeDyldCOFF {
SectionEntry &Section = Sections[SectionID];
uintptr_t ObjTarget = Section.getObjAddress() + Offset;

Expected<StringRef> TargetNameOrErr = Symbol->getName();
if (!TargetNameOrErr)
return TargetNameOrErr.takeError();
StringRef TargetName = *TargetNameOrErr;

switch (RelType) {

case COFF::IMAGE_REL_AMD64_REL32:
case COFF::IMAGE_REL_AMD64_REL32_1:
case COFF::IMAGE_REL_AMD64_REL32_2:
case COFF::IMAGE_REL_AMD64_REL32_3:
case COFF::IMAGE_REL_AMD64_REL32_4:
case COFF::IMAGE_REL_AMD64_REL32_5:
case COFF::IMAGE_REL_AMD64_REL32_5: {
uint8_t *Displacement = (uint8_t *)ObjTarget;
Addend = readBytesUnaligned(Displacement, 4);

if (IsExtern)
{
uint64_t StubOffset = generateRelocationStub(
SectionID, TargetName, Offset, RelType, Addend, Stubs);

// Make the target call a call into the stub table.
RelocationEntry RE(SectionID, Offset, RelType, Addend);
uint8_t *StubAbsAddress = Section.getAddressWithOffset(StubOffset);
resolveRelocation(RE, reinterpret_cast<uint64_t>(StubAbsAddress));

// Let relocation resolution write the symbol pointer
// to the stub function as 64bit absolute address.
constexpr unsigned PointerOffsetInStub = 6;
Offset = StubOffset + PointerOffsetInStub;
RelType = COFF::IMAGE_REL_AMD64_ADDR64;
Addend = 0;
}

break;
}

case COFF::IMAGE_REL_AMD64_ADDR32NB: {
uint8_t *Displacement = (uint8_t *)ObjTarget;
Addend = readBytesUnaligned(Displacement, 4);
Expand All @@ -155,11 +215,6 @@ class RuntimeDyldCOFFX86_64 : public RuntimeDyldCOFF {
break;
}

Expected<StringRef> TargetNameOrErr = Symbol->getName();
if (!TargetNameOrErr)
return TargetNameOrErr.takeError();
StringRef TargetName = *TargetNameOrErr;

DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
<< " RelType: " << RelType << " TargetName: " << TargetName
<< " Addend " << Addend << "\n");
Expand Down

0 comments on commit 97cd336

Please sign in to comment.