forked from OSchip/llvm-project
[PECOFF] Emit x64 delay-import wrapper function
Previously we supported x86 only. This patch is to support x64. The array of pointers to delay-loaded functions points the DLL delay loading function at start-up. When a function is called for the first time, the delay loading function gets called and then rewrite the function pointer array. llvm-svn: 220096
This commit is contained in:
parent
39e4bb3bc5
commit
2845fb29d8
|
@ -187,17 +187,28 @@ void DelayImportDirectoryAtom::addRelocations(
|
|||
for (int i = 0, e = sharedAtoms.size(); i < e; ++i) {
|
||||
const DefinedAtom *loader = new (_alloc) DelayLoaderAtom(
|
||||
context, addrTable[i], this, delayLoadHelper);
|
||||
addDir32Reloc(addrTable[i], loader, context.ctx.getMachineType(), 0);
|
||||
addDir64Reloc(addrTable[i], loader, context.ctx.getMachineType(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
DelayLoaderAtom::DelayLoaderAtom(IdataContext &context, const Atom *impAtom,
|
||||
const Atom *descAtom, const Atom *delayLoadHelperAtom)
|
||||
: IdataAtom(context, createContent()) {
|
||||
: IdataAtom(context, createContent(context.ctx.getMachineType())) {
|
||||
MachineTypes machine = context.ctx.getMachineType();
|
||||
addDir32Reloc(this, impAtom, machine, 3);
|
||||
addDir32Reloc(this, descAtom, machine, 8);
|
||||
addRel32Reloc(this, delayLoadHelperAtom, machine, 13);
|
||||
switch (machine) {
|
||||
case llvm::COFF::IMAGE_FILE_MACHINE_I386:
|
||||
addDir32Reloc(this, impAtom, machine, 3);
|
||||
addDir32Reloc(this, descAtom, machine, 8);
|
||||
addRel32Reloc(this, delayLoadHelperAtom, machine, 13);
|
||||
break;
|
||||
case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
|
||||
addRel32Reloc(this, impAtom, machine, 36);
|
||||
addRel32Reloc(this, descAtom, machine, 43);
|
||||
addRel32Reloc(this, delayLoadHelperAtom, machine, 48);
|
||||
break;
|
||||
default:
|
||||
llvm::report_fatal_error("unsupported machine type");
|
||||
}
|
||||
}
|
||||
|
||||
// DelayLoaderAtom contains a wrapper function for __delayLoadHelper2.
|
||||
|
@ -213,9 +224,9 @@ DelayLoaderAtom::DelayLoaderAtom(IdataContext &context, const Atom *impAtom,
|
|||
// function.
|
||||
//
|
||||
// __delayLoadHelper2 is defined in delayimp.lib.
|
||||
std::vector<uint8_t> DelayLoaderAtom::createContent() const {
|
||||
// NB: x86 only for now. ECX and EDX are caller-save.
|
||||
static const uint8_t array[] = {
|
||||
std::vector<uint8_t>
|
||||
DelayLoaderAtom::createContent(MachineTypes machine) const {
|
||||
static const uint8_t x86[] = {
|
||||
0x51, // push ecx
|
||||
0x52, // push edx
|
||||
0x68, 0, 0, 0, 0, // push offset ___imp__<FUNCNAME>
|
||||
|
@ -225,7 +236,38 @@ std::vector<uint8_t> DelayLoaderAtom::createContent() const {
|
|||
0x59, // pop ecx
|
||||
0xFF, 0xE0, // jmp eax
|
||||
};
|
||||
return std::vector<uint8_t>(array, array + sizeof(array));
|
||||
static const uint8_t x64[] = {
|
||||
0x51, // push rcx
|
||||
0x52, // push rdx
|
||||
0x41, 0x50, // push r8
|
||||
0x41, 0x51, // push r9
|
||||
0x48, 0x83, 0xEC, 0x48, // sub rsp, 48h
|
||||
0x66, 0x0F, 0x7F, 0x04, 0x24, // movdqa xmmword ptr [rsp], xmm0
|
||||
0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1
|
||||
0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2
|
||||
0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3
|
||||
0x48, 0x8D, 0x15, 0, 0, 0, 0, // lea rdx, [__imp_<FUNCNAME>]
|
||||
0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...]
|
||||
0xE8, 0, 0, 0, 0, // call __delayLoadHelper2
|
||||
0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp]
|
||||
0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa xmm1, xmmword ptr [rsp+10h]
|
||||
0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa xmm2, xmmword ptr [rsp+20h]
|
||||
0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa xmm3, xmmword ptr [rsp+30h]
|
||||
0x48, 0x83, 0xC4, 0x48, // add rsp, 48h
|
||||
0x41, 0x59, // pop r9
|
||||
0x41, 0x58, // pop r8
|
||||
0x5A, // pop rdx
|
||||
0x59, // pop rcx
|
||||
0xFF, 0xE0, // jmp rax
|
||||
};
|
||||
switch (machine) {
|
||||
case llvm::COFF::IMAGE_FILE_MACHINE_I386:
|
||||
return std::vector<uint8_t>(x86, x86 + sizeof(x86));
|
||||
case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
|
||||
return std::vector<uint8_t>(x64, x64 + sizeof(x64));
|
||||
default:
|
||||
llvm::report_fatal_error("unsupported machine type");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace idata
|
||||
|
|
|
@ -185,7 +185,7 @@ public:
|
|||
Alignment alignment() const override { return Alignment(0); }
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> createContent() const;
|
||||
std::vector<uint8_t> createContent(MachineTypes machine) const;
|
||||
};
|
||||
|
||||
} // namespace idata
|
||||
|
|
|
@ -23,6 +23,22 @@ static void addReloc(COFFBaseDefinedAtom *atom, const Atom *target,
|
|||
target, offsetInAtom, relType, arch));
|
||||
}
|
||||
|
||||
void addDir64Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
|
||||
llvm::COFF::MachineTypes machine, size_t offsetInAtom) {
|
||||
switch (machine) {
|
||||
case llvm::COFF::IMAGE_FILE_MACHINE_I386:
|
||||
addReloc(atom, target, offsetInAtom, Reference::KindArch::x86,
|
||||
llvm::COFF::IMAGE_REL_I386_DIR32);
|
||||
return;
|
||||
case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
|
||||
addReloc(atom, target, offsetInAtom, Reference::KindArch::x86_64,
|
||||
llvm::COFF::IMAGE_REL_AMD64_ADDR64);
|
||||
return;
|
||||
default:
|
||||
llvm_unreachable("unsupported machine type");
|
||||
}
|
||||
}
|
||||
|
||||
void addDir32Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
|
||||
llvm::COFF::MachineTypes machine, size_t offsetInAtom) {
|
||||
switch (machine) {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
namespace lld {
|
||||
namespace pecoff {
|
||||
|
||||
void addDir64Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
|
||||
llvm::COFF::MachineTypes machine, size_t offsetInAtom);
|
||||
|
||||
void addDir32Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
|
||||
llvm::COFF::MachineTypes machine, size_t offsetInAtom);
|
||||
|
||||
|
|
Loading…
Reference in New Issue