[RuntimeDyld][COFF] Build stubs for COFF dllimport symbols.

Summary:
Enables JIT-linking by RuntimeDyld of COFF objects that contain references to
dllimport symbols. This is done by recognizing symbols that start with the
reserved "__imp_" prefix and building a pointer entry to the target symbol in
the stubs area of the section. References to the "__imp_" symbol are updated to
point to this pointer.

Work in progress: The generic code is in place, but only RuntimeDyldCOFFX86_64
and RuntimeDyldCOFFI386 have been updated to look for and update references to
dllimport symbols.

Reviewers: compnerd

Subscribers: hiraditya, ributzka, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D75884
This commit is contained in:
Lang Hames 2020-03-09 16:56:07 -07:00
parent aed5712522
commit 337e131ca7
10 changed files with 221 additions and 127 deletions

View File

@ -18,6 +18,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/FormatVariadic.h"
using namespace llvm;
using namespace llvm::object;
@ -78,6 +79,41 @@ uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) {
return Sym.getValue();
}
uint64_t RuntimeDyldCOFF::getDLLImportOffset(unsigned SectionID, StubMap &Stubs,
StringRef Name,
bool SetSectionIDMinus1) {
LLVM_DEBUG(dbgs() << "Getting DLLImport entry for " << Name << "... ");
assert(Name.startswith(getImportSymbolPrefix()) && "Not a DLLImport symbol?");
RelocationValueRef Reloc;
Reloc.SymbolName = Name.data();
auto I = Stubs.find(Reloc);
if (I != Stubs.end()) {
LLVM_DEBUG(dbgs() << format("{0:x8}", I->second) << "\n");
return I->second;
}
assert(SectionID < Sections.size() && "SectionID out of range");
auto &Sec = Sections[SectionID];
auto EntryOffset = alignTo(Sec.getStubOffset(), PointerSize);
Sec.advanceStubOffset(EntryOffset + PointerSize - Sec.getStubOffset());
Stubs[Reloc] = EntryOffset;
RelocationEntry RE(SectionID, EntryOffset, PointerReloc, 0, false,
Log2_64(PointerSize));
// Hack to tell I386/Thumb resolveRelocation that this isn't section relative.
if (SetSectionIDMinus1)
RE.Sections.SectionA = -1;
addRelocationForSymbol(RE, Name.drop_front(getImportSymbolPrefix().size()));
LLVM_DEBUG({
dbgs() << "Creating entry at "
<< formatv("{0:x16} + {1:x8} ( {2:x16} )", Sec.getLoadAddress(),
EntryOffset, Sec.getLoadAddress() + EntryOffset)
<< "\n";
});
return EntryOffset;
}
bool RuntimeDyldCOFF::isCompatibleFile(const object::ObjectFile &Obj) const {
return Obj.isCOFF();
}

View File

@ -36,9 +36,22 @@ public:
protected:
RuntimeDyldCOFF(RuntimeDyld::MemoryManager &MemMgr,
JITSymbolResolver &Resolver)
: RuntimeDyldImpl(MemMgr, Resolver) {}
JITSymbolResolver &Resolver, unsigned PointerSize,
uint32_t PointerReloc)
: RuntimeDyldImpl(MemMgr, Resolver), PointerSize(PointerSize),
PointerReloc(PointerReloc) {
assert((PointerSize == 4 || PointerSize == 8) && "Unexpected pointer size");
}
uint64_t getSymbolOffset(const SymbolRef &Sym);
uint64_t getDLLImportOffset(unsigned SectionID, StubMap &Stubs,
StringRef Name, bool SetSectionIDMinus1 = false);
static constexpr StringRef getImportSymbolPrefix() { return "__imp_"; }
private:
unsigned PointerSize;
uint32_t PointerReloc;
};
} // end namespace llvm

View File

@ -191,13 +191,11 @@ public:
class RelocationValueRef {
public:
unsigned SectionID;
uint64_t Offset;
int64_t Addend;
const char *SymbolName;
unsigned SectionID = 0;
uint64_t Offset = 0;
int64_t Addend = 0;
const char *SymbolName = nullptr;
bool IsStubThumb = false;
RelocationValueRef() : SectionID(0), Offset(0), Addend(0),
SymbolName(nullptr) {}
inline bool operator==(const RelocationValueRef &Other) const {
return SectionID == Other.SectionID && Offset == Other.Offset &&

View File

@ -89,7 +89,8 @@ private:
public:
RuntimeDyldCOFFAArch64(RuntimeDyld::MemoryManager &MM,
JITSymbolResolver &Resolver)
: RuntimeDyldCOFF(MM, Resolver), ImageBase(0) {}
: RuntimeDyldCOFF(MM, Resolver, 8, COFF::IMAGE_REL_ARM64_ADDR64),
ImageBase(0) {}
unsigned getStubAlignment() override { return 8; }
@ -161,7 +162,7 @@ public:
uint64_t Offset = RelI->getOffset();
// If there is no section, this must be an external reference.
const bool IsExtern = Section == Obj.section_end();
bool IsExtern = Section == Obj.section_end();
// Determine the Addend used to adjust the relocation value.
uint64_t Addend = 0;
@ -169,6 +170,24 @@ public:
uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
uint8_t *Displacement = (uint8_t *)ObjTarget;
unsigned TargetSectionID = -1;
uint64_t TargetOffset = -1;
if (TargetName.startswith(getImportSymbolPrefix())) {
TargetSectionID = SectionID;
TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName);
TargetName = StringRef();
IsExtern = false;
} else if (!IsExtern) {
if (auto TargetSectionIDOrErr = findOrEmitSection(
Obj, *Section, Section->isText(), ObjSectionToID))
TargetSectionID = *TargetSectionIDOrErr;
else
return TargetSectionIDOrErr.takeError();
TargetOffset = getSymbolOffset(*Symbol);
}
switch (RelType) {
case COFF::IMAGE_REL_ARM64_ADDR32:
case COFF::IMAGE_REL_ARM64_ADDR32NB:
@ -224,18 +243,10 @@ public:
<< TargetName << " Addend " << Addend << "\n");
#endif
unsigned TargetSectionID = -1;
if (IsExtern) {
RelocationEntry RE(SectionID, Offset, RelType, Addend);
addRelocationForSymbol(RE, TargetName);
} else {
if (auto TargetSectionIDOrErr = findOrEmitSection(
Obj, *Section, Section->isText(), ObjSectionToID)) {
TargetSectionID = *TargetSectionIDOrErr;
} else
return TargetSectionIDOrErr.takeError();
uint64_t TargetOffset = getSymbolOffset(*Symbol);
RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend);
addRelocationForSection(RE, TargetSectionID);
}

View File

@ -25,7 +25,7 @@ class RuntimeDyldCOFFI386 : public RuntimeDyldCOFF {
public:
RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM,
JITSymbolResolver &Resolver)
: RuntimeDyldCOFF(MM, Resolver) {}
: RuntimeDyldCOFF(MM, Resolver, 4, COFF::IMAGE_REL_I386_DIR32) {}
unsigned getMaxStubSize() const override {
return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad
@ -53,10 +53,28 @@ public:
if (!SectionOrErr)
return SectionOrErr.takeError();
auto Section = *SectionOrErr;
bool IsExtern = Section == Obj.section_end();
uint64_t RelType = RelI->getType();
uint64_t Offset = RelI->getOffset();
unsigned TargetSectionID = -1;
uint64_t TargetOffset = -1;
if (TargetName.startswith(getImportSymbolPrefix())) {
TargetSectionID = SectionID;
TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName, true);
TargetName = StringRef();
IsExtern = false;
} else if (!IsExtern) {
if (auto TargetSectionIDOrErr = findOrEmitSection(
Obj, *Section, Section->isText(), ObjSectionToID))
TargetSectionID = *TargetSectionIDOrErr;
else
return TargetSectionIDOrErr.takeError();
if (RelType != COFF::IMAGE_REL_I386_SECTION)
TargetOffset = getSymbolOffset(*Symbol);
}
// Determine the Addend used to adjust the relocation value.
uint64_t Addend = 0;
SectionEntry &AddendSection = Sections[SectionID];
@ -83,16 +101,10 @@ public:
<< " RelType: " << RelTypeName << " TargetName: "
<< TargetName << " Addend " << Addend << "\n");
unsigned TargetSectionID = -1;
if (Section == Obj.section_end()) {
if (IsExtern) {
RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
addRelocationForSymbol(RE, TargetName);
} else {
if (auto TargetSectionIDOrErr =
findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID))
TargetSectionID = *TargetSectionIDOrErr;
else
return TargetSectionIDOrErr.takeError();
switch (RelType) {
case COFF::IMAGE_REL_I386_ABSOLUTE:
@ -103,7 +115,7 @@ public:
case COFF::IMAGE_REL_I386_REL32: {
RelocationEntry RE =
RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
getSymbolOffset(*Symbol), 0, 0, false, 0);
TargetOffset, 0, 0, false, 0);
addRelocationForSection(RE, TargetSectionID);
break;
}
@ -114,15 +126,14 @@ public:
break;
}
case COFF::IMAGE_REL_I386_SECREL: {
RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
getSymbolOffset(*Symbol) + Addend);
RelocationEntry RE =
RelocationEntry(SectionID, Offset, RelType, TargetOffset + Addend);
addRelocationForSection(RE, TargetSectionID);
break;
}
default:
llvm_unreachable("unsupported relocation type");
}
}
return ++RelI;

View File

@ -48,7 +48,7 @@ class RuntimeDyldCOFFThumb : public RuntimeDyldCOFF {
public:
RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM,
JITSymbolResolver &Resolver)
: RuntimeDyldCOFF(MM, Resolver) {}
: RuntimeDyldCOFF(MM, Resolver, 4, COFF::IMAGE_REL_ARM_ADDR32) {}
unsigned getMaxStubSize() const override {
return 16; // 8-byte load instructions, 4-byte jump, 4-byte padding
@ -103,16 +103,29 @@ public:
<< " RelType: " << RelTypeName << " TargetName: "
<< TargetName << " Addend " << Addend << "\n");
bool IsExtern = Section == Obj.section_end();
unsigned TargetSectionID = -1;
if (Section == Obj.section_end()) {
RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
addRelocationForSymbol(RE, TargetName);
} else {
uint64_t TargetOffset = -1;
if (TargetName.startswith(getImportSymbolPrefix())) {
TargetSectionID = SectionID;
TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName, true);
TargetName = StringRef();
IsExtern = false;
} else if (!IsExtern) {
if (auto TargetSectionIDOrErr =
findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID))
TargetSectionID = *TargetSectionIDOrErr;
else
return TargetSectionIDOrErr.takeError();
if (RelType != COFF::IMAGE_REL_ARM_SECTION)
TargetOffset = getSymbolOffset(*Symbol);
}
if (IsExtern) {
RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
addRelocationForSymbol(RE, TargetName);
} else {
// We need to find out if the relocation is relative to a thumb function
// so that we include the ISA selection bit when resolve the relocation
@ -124,16 +137,16 @@ public:
// This relocation is ignored.
break;
case COFF::IMAGE_REL_ARM_ADDR32: {
RelocationEntry RE = RelocationEntry(
SectionID, Offset, RelType, Addend, TargetSectionID,
getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc);
RelocationEntry RE =
RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
TargetOffset, 0, 0, false, 0, IsTargetThumbFunc);
addRelocationForSection(RE, TargetSectionID);
break;
}
case COFF::IMAGE_REL_ARM_ADDR32NB: {
RelocationEntry RE =
RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
getSymbolOffset(*Symbol), 0, 0, false, 0);
TargetOffset, 0, 0, false, 0);
addRelocationForSection(RE, TargetSectionID);
break;
}
@ -144,24 +157,23 @@ public:
break;
}
case COFF::IMAGE_REL_ARM_SECREL: {
RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
getSymbolOffset(*Symbol) + Addend);
RelocationEntry RE =
RelocationEntry(SectionID, Offset, RelType, TargetOffset + Addend);
addRelocationForSection(RE, TargetSectionID);
break;
}
case COFF::IMAGE_REL_ARM_MOV32T: {
RelocationEntry RE = RelocationEntry(
SectionID, Offset, RelType, Addend, TargetSectionID,
getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc);
RelocationEntry RE =
RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
TargetOffset, 0, 0, false, 0, IsTargetThumbFunc);
addRelocationForSection(RE, TargetSectionID);
break;
}
case COFF::IMAGE_REL_ARM_BRANCH20T:
case COFF::IMAGE_REL_ARM_BRANCH24T:
case COFF::IMAGE_REL_ARM_BLX23T: {
RelocationEntry RE =
RelocationEntry(SectionID, Offset, RelType,
getSymbolOffset(*Symbol) + Addend, true, 0);
RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
TargetOffset + Addend, true, 0);
addRelocationForSection(RE, TargetSectionID);
break;
}
@ -256,7 +268,6 @@ public:
EncodeImmediate(&Target[0],
(static_cast<uint32_t>(Result) >> 00) | ISASelectionBit);
EncodeImmediate(&Target[4], static_cast<uint32_t>(Result) >> 16);
break;
}
case COFF::IMAGE_REL_ARM_BRANCH20T: {

View File

@ -56,7 +56,8 @@ private:
public:
RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM,
JITSymbolResolver &Resolver)
: RuntimeDyldCOFF(MM, Resolver), ImageBase(0) {}
: RuntimeDyldCOFF(MM, Resolver, 8, COFF::IMAGE_REL_AMD64_ADDR64),
ImageBase(0) {}
unsigned getStubAlignment() override { return 1; }
@ -202,7 +203,7 @@ public:
return SectionOrError.takeError();
object::section_iterator SecI = *SectionOrError;
// If there is no section, this must be an external reference.
const bool IsExtern = SecI == Obj.section_end();
bool IsExtern = SecI == Obj.section_end();
// Determine the Addend used to adjust the relocation value.
uint64_t RelType = RelI->getType();
@ -214,7 +215,25 @@ public:
Expected<StringRef> TargetNameOrErr = Symbol->getName();
if (!TargetNameOrErr)
return TargetNameOrErr.takeError();
StringRef TargetName = *TargetNameOrErr;
unsigned TargetSectionID = 0;
uint64_t TargetOffset = 0;
if (TargetName.startswith(getImportSymbolPrefix())) {
assert(IsExtern && "DLLImport not marked extern?");
TargetSectionID = SectionID;
TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName);
TargetName = StringRef();
IsExtern = false;
} else if (!IsExtern) {
if (auto TargetSectionIDOrErr =
findOrEmitSection(Obj, *SecI, SecI->isText(), ObjSectionToID))
TargetSectionID = *TargetSectionIDOrErr;
else
return TargetSectionIDOrErr.takeError();
TargetOffset = getSymbolOffset(*Symbol);
}
switch (RelType) {
@ -253,14 +272,6 @@ public:
RelocationEntry RE(SectionID, Offset, RelType, Addend);
addRelocationForSymbol(RE, TargetName);
} else {
bool IsCode = SecI->isText();
unsigned TargetSectionID;
if (auto TargetSectionIDOrErr =
findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID))
TargetSectionID = *TargetSectionIDOrErr;
else
return TargetSectionIDOrErr.takeError();
uint64_t TargetOffset = getSymbolOffset(*Symbol);
RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend);
addRelocationForSection(RE, TargetSectionID);
}

View File

@ -1,5 +1,8 @@
// RUN: llvm-mc -triple thumbv7-windows-itanium -filetype obj -o %t.obj %s
// RUN: llvm-rtdyld -triple thumbv7-windows -dummy-extern OutputDebugStringW=0x01310061 -dummy-extern OutputDebugStringA=0x78563413 -dummy-extern ExitProcess=0x54769891 -dummy-extern unnamed_addr=0x00001024 -verify -check %s %t.obj
# RUN: rm -rf %t && mkdir -p %t
# RUN: llvm-mc -triple thumbv7-windows-itanium -filetype obj -o %t/COFF_Thumb.o %s
# RUN: llvm-rtdyld -triple thumbv7-windows \
# RUN: -dummy-extern ExitProcess=0x54769891 \
# RUN: -dummy-extern unnamed_addr=0x00001024 -verify -check %s %t/COFF_Thumb.o
.text
.syntax unified
@ -33,23 +36,26 @@ branch24t:
function:
push.w {r11, lr}
mov r11, sp
rel2: @ IMAGE_REL_ARM_MOV32T
movw r0, :lower16:__imp_OutputDebugStringA
# rtdyld-check: decode_operand(rel2, 1) = (__imp_OutputDebugStringA&0x0000ffff)
movt r0, :upper16:__imp_OutputDebugStringA
# TODO rtdyld-check: decode_operand(rel2, 1) = (__imp_OutputDebugStringA&0xffff0000>>16)
ldr r1, [r0]
rel3: @ IMAGE_REL_ARM_MOV32T
movw r0, :lower16:string
# rtdyld-check: decode_operand(rel3, 1) = (string&0x0000ffff)
movt r0, :upper16:string
# TODO rtdyld-check: decode_operand(rel3, 1) = (string&0xffff0000>>16)
blx r1
rel4: @ IMAGE_REL_ARM_MOV32T
load_from_dllimport_lo: @ IMAGE_REL_ARM_MOV32T
movw r0, :lower16:__imp_ExitProcess
# rtdyld-check: decode_operand(rel4, 1) = (__imp_ExitProcess&0x0000ffff)
# (1) Check stub content.
# rtdyld-check: *{4}(stub_addr(COFF_Thumb.o/.text, __imp_ExitProcess)) = \
# rtdyld-check: ExitProcess
#
# (2) Check lo bits of stub address.
# rtdyld-check: decode_operand(load_from_dllimport_lo, 1) = \
# rtdyld-check: stub_addr(COFF_Thumb.o/.text, __imp_ExitProcess)[15:0]
load_from_dllimport_hi:
movt r0, :upper16:__imp_ExitProcess
# TODO rtdyld-check: decode_operand(rel4, 1) = (__imp_ExitProcess&0xffff0000>>16)
# (3) Check hi bits of stub address.
# rtdyld-check: decode_operand(load_from_dllimport_hi, 2) = \
# rtdyld-check: stub_addr(COFF_Thumb.o/.text, __imp_ExitProcess)[31:16]
ldr r1, [r0]
movs r0, #0
pop.w {r11, lr}
@ -78,48 +84,25 @@ string:
.data
.p2align 2
__imp_OutputDebugStringA:
@ rel6:
.long OutputDebugStringA @ IMAGE_REL_ARM_ADDR32
# rtdyld-check: *{4}__imp_OutputDebugStringA = 0x78563413
.p2align 2
__imp_ExitProcess:
@ rel7:
.long ExitProcess @ IMAGE_REL_ARM_ADDR32
# rtdyld-check: *{4}__imp_ExitProcess = 0x54769891
.global relocations
relocations:
@ rel8:
.long function(imgrel) @ IMAGE_REL_ARM_ADDR32NB
# rtdyld-check: *{4}relocations = function - section_addr(COFF_Thumb.s.tmp.obj, .text)
# rtdyld-check: *{4}relocations = function - section_addr(COFF_Thumb.o, .text)
rel9:
.secidx __imp_OutputDebugStringA @ IMAGE_REL_ARM_SECTION
# rtdyld-check: *{2}rel9 = 1
.secidx __imp_ExitProcess @ IMAGE_REL_ARM_SECTION
# rtdyld-check: *{2}rel9 = 2
rel10:
.long relocations(secrel32) @ IMAGE_REL_ARM_SECREL
# rtdyld-check: *{4}rel10 = relocations - section_addr(COFF_Thumb.s.tmp.obj, .data)
# rtdyld-check: *{4}rel10 = relocations - section_addr(COFF_Thumb.o, .data)
rel11:
.secrel32 relocations @ IMAGE_REL_ARM_SECREL
# rtdyld-check: *{4}rel11 = relocations - section_addr(COFF_Thumb.s.tmp.obj, .data)
rel12: @ IMAGE_REL_ARM_MOV32T
movw r0, :lower16:__imp_OutputDebugStringW
# rtdyld-check: decode_operand(rel12, 1) = (__imp_OutputDebugStringW&0x0000ffff)
movt r0, :upper16:__imp_OutputDebugStringW
# TODO rtdyld-check: decode_operand(rel12, 1) = (__imp_OutputDebugStringW&0xffff0000>>16)
# rtdyld-check: *{4}rel11 = relocations - section_addr(COFF_Thumb.o, .data)
bx r0
trap
.data
.p2align 2
__imp_OutputDebugStringW:
@ rel13:
.long OutputDebugStringW @ IMAGE_REL_ARM_ADDR32
# rtdyld-check: *{4}__imp_OutputDebugStringW = 0x01310061
.p2align 2
branch_to_thumb_func:

View File

@ -1,5 +1,8 @@
// RUN: llvm-mc -triple i686-windows -filetype obj -o %t.obj %s
// RUN: llvm-rtdyld -triple i686-windows -dummy-extern _printf=0x7ffffffd -dummy-extern _OutputDebugStringA@4=0x7ffffffe -dummy-extern _ExitProcess@4=0x7fffffff -verify -check=%s %t.obj
// RUN: rm -rf %t && mkdir -p %t
// RUN: llvm-mc -triple i686-windows -filetype obj -o %t/COFF_i386.o %s
// RUN: llvm-rtdyld -triple i686-windows -dummy-extern _printf=0x7ffffffd \
// RUN: -dummy-extern _ExitProcess=0x7fffffff \
// RUN: -verify -check=%s %t/COFF_i386.o
.text
@ -24,41 +27,25 @@ rel12:
_function:
rel2:
pushl string
# rtdyld-check: decode_operand(rel3, 3) = \
# rtdyld-check: stub_addr(COFF_i386.o/.text, __imp__ExitProcess)
# rtdyld-check: *{4}(stub_addr(COFF_i386.o/.text, __imp__ExitProcess)) = \
# rtdyld-check: _ExitProcess
rel3:
calll *__imp__OutputDebugStringA // IMAGE_REL_I386_DIR32
# rtdyld-check: decode_operand(rel3, 3) = __imp__OutputDebugStringA
addl $4, %esp
pushl $0
rel4:
calll *__imp__ExitProcess // IMAGE_REL_I386_DIR32
# rtdyld-check: decode_operand(rel4, 3) = __imp__ExitProcess
addl $4, %esp
retl
calll *__imp__ExitProcess // IMAGE_REL_I386_DIR32
.data
.global __imp__OutputDebugStringA
.align 4
__imp__OutputDebugStringA:
.long "_OutputDebugStringA@4" // IMAGE_REL_I386_DIR32
# rtdyld-check: *{4}__imp__OutputDebugStringA = 0x7ffffffe
.global __imp__ExitProcess
.align 4
__imp__ExitProcess:
.long "_ExitProcess@4" // IMAGE_REL_I386_DIR32
# rtdyld-check: *{4}__imp__ExitProcess = 0x7fffffff
.global relocations
relocations:
rel5:
.long _function@imgrel // IMAGE_REL_I386_DIR32NB
# rtdyld-check: *{4}rel5 = _function - section_addr(COFF_i386.s.tmp.obj, .text)
# rtdyld-check: *{4}rel5 = _function - section_addr(COFF_i386.o, .text)
rel6:
# rtdyld-check: *{2}rel6 = 1
.secidx __imp__OutputDebugStringA // IMAGE_REL_I386_SECTION
.secidx rel5 // IMAGE_REL_I386_SECTION
rel7:
# rtdyld-check: *{4}rel7 = string - section_addr(COFF_i386.s.tmp.obj, .data)
# rtdyld-check: *{4}rel7 = string - section_addr(COFF_i386.o, .data)
.secrel32 string // IMAGE_REL_I386_SECREL
# Test that addends work.
@ -69,10 +56,10 @@ rel9:
# rtdyld-check: *{4}rel9 = string+1
.long string+1 // IMAGE_REL_I386_DIR32
rel10:
# rtdyld-check: *{4}rel10 = string - section_addr(COFF_i386.s.tmp.obj, .text) + 1
# rtdyld-check: *{4}rel10 = string - section_addr(COFF_i386.o, .text) + 1
.long string@imgrel+1 // IMAGE_REL_I386_DIR32NB
rel11:
# rtdyld-check: *{4}rel11 = string - section_addr(COFF_i386.s.tmp.obj, .data) + 1
# rtdyld-check: *{4}rel11 = string - section_addr(COFF_i386.o, .data) + 1
.long string@SECREL32+1 // IMAGE_REL_I386_SECREL
# We explicitly add padding to put string outside of the 16bit address space

View File

@ -1,7 +1,10 @@
# RUN: rm -rf %t && mkdir -p %t
# RUN: llvm-mc -triple=x86_64-pc-win32 -filetype=obj -o %t/COFF_x86_64.o %s
# RUN: llvm-rtdyld -triple=x86_64-pc-win32 -verify -check=%s %t/COFF_x86_64.o
.text
# RUN: llvm-rtdyld -triple=x86_64-pc-win32 -dummy-extern external_func=0x1 \
# RUN: -dummy-extern external_data=0x2 -verify -check=%s %t/COFF_x86_64.o
.text
.def F;
.scl 2;
.type 32;
@ -29,6 +32,36 @@ inst1:
.Ltmp2:
.seh_endproc
.globl call_to_dllimport
.p2align 4, 0x90
# Check calls to dllimports.
#
# (1) Check that callq argument points to synthesized stub addr.
# rtdyld-check: decode_operand(call_to_dllimport, 3) = \
# rtdyld-check: stub_addr(COFF_x86_64.o/.text, __imp_external_func) - \
# rtdyld-check: next_pc(call_to_dllimport)
#
# (2) Check that synthesized stub entry points to call target.
# rtdyld-check: *{8}(stub_addr(COFF_x86_64.o/.text, __imp_external_func)) = \
# rtdyld-check: external_func
call_to_dllimport:
callq *__imp_external_func(%rip)
.globl load_from_dllimport
.p2align 4, 0x90
# Check loads from dllimports.
#
# (1) Check that the movq argument points to synthesized stub addr.
# rtdyld-check: decode_operand(load_from_dllimport, 4) = \
# rtdyld-check: stub_addr(COFF_x86_64.o/.text, __imp_external_data) - \
# rtdyld-check: next_pc(load_from_dllimport)
#
# (2) Check that synthesized stub entry points to datao target.
# rtdyld-check: *{8}(stub_addr(COFF_x86_64.o/.text, __imp_external_data)) = \
# rtdyld-check: external_data
load_from_dllimport:
movq __imp_external_data(%rip), %rax
.data
.globl x # @x
# rtdyld-check: *{8}x = F