[PECOFF] Implement Win64 base relocations

Image Base field in the PE/COFF header is used as hint for the loader.
If the loader can load the executable at the specified address, that's
fine, but if not, it has to load it at a different address.

If that happens, the loader has to fix up the addresses in the
executable by adding the offset. The list of addresses that need to
be fixed is in .reloc section.

This patch is to emit x64 .reloc section contents.

llvm-svn: 216636
This commit is contained in:
Rui Ueyama 2014-08-28 00:47:11 +00:00
parent cbe875a507
commit f4b0d5e050
2 changed files with 17 additions and 9 deletions

View File

@ -249,6 +249,7 @@ private:
StringRef name, const std::vector<const DefinedAtom *> &atoms) const;
mutable llvm::BumpPtrAllocator _alloc;
bool is64;
};
/// A DataDirectoryChunk represents data directory entries that follows the PE
@ -446,7 +447,7 @@ AtomChunk::AtomChunk(const PECOFFLinkingContext &ctx, StringRef sectionName,
const std::vector<const DefinedAtom *> &atoms)
: SectionChunk(kindAtomChunk, sectionName,
computeCharacteristics(ctx, sectionName, atoms)),
_virtualAddress(0) {
_virtualAddress(0), is64(ctx.is64Bit()) {
for (auto *a : atoms)
appendAtom(a);
}
@ -633,11 +634,13 @@ void AtomChunk::addBaseRelocations(std::vector<uint64_t> &relocSites) const {
// should output debug messages with atom names and addresses so that we
// can inspect relocations, and fix the tests (base-reloc.test, maybe
// others) to use those messages.
int relType = is64 ? llvm::COFF::IMAGE_REL_AMD64_ADDR64
: llvm::COFF::IMAGE_REL_I386_DIR32;
for (const auto *layout : _atomLayouts) {
const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom);
for (const Reference *ref : *atom)
if ((ref->kindNamespace() == Reference::KindNamespace::COFF) &&
(ref->kindValue() == llvm::COFF::IMAGE_REL_I386_DIR32))
(ref->kindValue() == relType))
relocSites.push_back(layout->_virtualAddr + ref->offsetInAtom());
}
}
@ -822,10 +825,11 @@ std::vector<uint8_t> BaseRelocChunk::createBaseRelocBlock(
ptr += sizeof(ulittle32_t);
// The rest of the block consists of offsets in the page.
uint16_t type = _ctx.is64Bit() ? llvm::COFF::IMAGE_REL_BASED_DIR64
: llvm::COFF::IMAGE_REL_BASED_HIGHLOW;
for (uint16_t offset : offsets) {
assert(offset < _ctx.getPageSize());
uint16_t val = (llvm::COFF::IMAGE_REL_BASED_HIGHLOW << 12) | offset;
*reinterpret_cast<ulittle16_t *>(ptr) = val;
*reinterpret_cast<ulittle16_t *>(ptr) = (type << 12) | offset;
ptr += sizeof(ulittle16_t);
}
return contents;

View File

@ -3,9 +3,13 @@
# RUN: lld -flavor link /out:%t.exe /subsystem:console /machine:x64 \
# RUN: /entry:fn1 -- %t1.obj %t2.obj
# RUN: llvm-objdump -d %t.exe | FileCheck %s
# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=TEXT %s
# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=RELOC %s
CHECK: Disassembly of section .text:
CHECK-NEXT: .text:
CHECK-NEXT: 1000: e8 0b 00 00 00 callq 11
CHECK-NEXT: 1005: 48 b8 10 10 00 40 01 00 00 00 movabsq $5368713232, %rax
TEXT: Disassembly of section .text:
TEXT-NEXT: .text:
TEXT-NEXT: 1000: e8 0b 00 00 00 callq 11
TEXT-NEXT: 1005: 48 b8 10 10 00 40 01 00 00 00 movabsq $5368713232, %rax
RELOC: Contents of section .reloc:
RELOC-NEXT: 2000 00100000 0c000000 07a00000 00000000 ................