diff options
| -rw-r--r-- | lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp | 80 | ||||
| -rw-r--r-- | lld/test/pecoff/Inputs/reloc64-1.asm | 8 | ||||
| -rw-r--r-- | lld/test/pecoff/Inputs/reloc64-1.obj | bin | 0 -> 448 bytes | |||
| -rw-r--r-- | lld/test/pecoff/Inputs/reloc64-2.asm | 5 | ||||
| -rw-r--r-- | lld/test/pecoff/Inputs/reloc64-2.obj | bin | 0 -> 416 bytes | |||
| -rw-r--r-- | lld/test/pecoff/reloc64.test | 7 |
6 files changed, 88 insertions, 12 deletions
diff --git a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp index a0760fbeca0..9935a91ee44 100644 --- a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp +++ b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp @@ -22,6 +22,7 @@ #define DEBUG_TYPE "WriterPECOFF" #include <algorithm> +#include <cstdlib> #include <map> #include <time.h> #include <vector> @@ -209,10 +210,16 @@ public: void appendAtom(const DefinedAtom *atom); void buildAtomRvaMap(std::map<const Atom *, uint64_t> &atomRva) const; - void applyRelocations(uint8_t *buffer, - std::map<const Atom *, uint64_t> &atomRva, - std::vector<uint64_t> §ionRva, - uint64_t imageBaseAddress); + + void applyRelocations32(uint8_t *buffer, + std::map<const Atom *, uint64_t> &atomRva, + std::vector<uint64_t> §ionRva, + uint64_t imageBaseAddress); + void applyRelocations64(uint8_t *buffer, + std::map<const Atom *, uint64_t> &atomRva, + std::vector<uint64_t> §ionRva, + uint64_t imageBaseAddress); + void printAtomAddresses(uint64_t baseAddr) const; void addBaseRelocations(std::vector<uint64_t> &relocSites) const; @@ -460,10 +467,10 @@ AtomChunk::buildAtomRvaMap(std::map<const Atom *, uint64_t> &atomRva) const { atomRva[layout->_atom] = layout->_virtualAddr; } -void AtomChunk::applyRelocations(uint8_t *buffer, - std::map<const Atom *, uint64_t> &atomRva, - std::vector<uint64_t> §ionRva, - uint64_t imageBaseAddress) { +void AtomChunk::applyRelocations32(uint8_t *buffer, + std::map<const Atom *, uint64_t> &atomRva, + std::vector<uint64_t> §ionRva, + uint64_t imageBaseAddress) { buffer += _fileOffset; for (const auto *layout : _atomLayouts) { const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom); @@ -527,6 +534,49 @@ void AtomChunk::applyRelocations(uint8_t *buffer, } } +void AtomChunk::applyRelocations64(uint8_t *buffer, + std::map<const Atom *, uint64_t> &atomRva, + std::vector<uint64_t> §ionRva, + uint64_t imageBase) { + buffer += _fileOffset; + for (const auto *layout : _atomLayouts) { + const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom); + for (const Reference *ref : *atom) { + if (ref->kindNamespace() != Reference::KindNamespace::COFF) + continue; + + auto relocSite32 = reinterpret_cast<ulittle32_t *>( + buffer + layout->_fileOffset + ref->offsetInAtom()); + uint64_t targetAddr = atomRva[ref->target()]; + + switch (ref->kindValue()) { + case llvm::COFF::IMAGE_REL_AMD64_ADDR32NB: + *relocSite32 = targetAddr - imageBase; + break; + case llvm::COFF::IMAGE_REL_AMD64_REL32: + *relocSite32 = targetAddr - atomRva[atom] + ref->offsetInAtom() + 4; + break; + +#define REL32(x) \ + case llvm::COFF::IMAGE_REL_AMD64_REL32_ ## x: { \ + uint32_t off = targetAddr - atomRva[atom] + ref->offsetInAtom() + 4; \ + *relocSite32 = off + x; \ + } + REL32(1); + REL32(2); + REL32(3); + REL32(4); + REL32(5); +#undef CASE + + default: + llvm::errs() << "Kind: " << (int)ref->kindValue() << "\n"; + llvm_unreachable("Unsupported relocation kind"); + } + } + } +} + /// Print atom VAs. Used only for debugging. void AtomChunk::printAtomAddresses(uint64_t baseAddr) const { for (const auto *layout : _atomLayouts) { @@ -965,10 +1015,16 @@ void PECOFFWriter::applyAllRelocations(uint8_t *bufferStart) { chunk->buildAtomRvaMap(atomRva); // Pass 2 - for (auto &cp : _chunks) - if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp)) - chunk->applyRelocations(bufferStart, atomRva, sectionRva, - _ctx.getBaseAddress()); + uint64_t base = _ctx.getBaseAddress(); + for (auto &cp : _chunks) { + if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp)) { + if (_ctx.is64Bit()) { + chunk->applyRelocations64(bufferStart, atomRva, sectionRva, base); + } else { + chunk->applyRelocations32(bufferStart, atomRva, sectionRva, base); + } + } + } } /// Print atom VAs. Used only for debugging. diff --git a/lld/test/pecoff/Inputs/reloc64-1.asm b/lld/test/pecoff/Inputs/reloc64-1.asm new file mode 100644 index 00000000000..6e253f429d8 --- /dev/null +++ b/lld/test/pecoff/Inputs/reloc64-1.asm @@ -0,0 +1,8 @@ +extern fn2 : PROC + +.code +fn1 PROC + call fn2 + ret +fn1 ENDP +End diff --git a/lld/test/pecoff/Inputs/reloc64-1.obj b/lld/test/pecoff/Inputs/reloc64-1.obj Binary files differnew file mode 100644 index 00000000000..cb04d2562f3 --- /dev/null +++ b/lld/test/pecoff/Inputs/reloc64-1.obj diff --git a/lld/test/pecoff/Inputs/reloc64-2.asm b/lld/test/pecoff/Inputs/reloc64-2.asm new file mode 100644 index 00000000000..b854482bf1e --- /dev/null +++ b/lld/test/pecoff/Inputs/reloc64-2.asm @@ -0,0 +1,5 @@ +.code +fn2 PROC + ret +fn2 ENDP +End diff --git a/lld/test/pecoff/Inputs/reloc64-2.obj b/lld/test/pecoff/Inputs/reloc64-2.obj Binary files differnew file mode 100644 index 00000000000..ba022c27147 --- /dev/null +++ b/lld/test/pecoff/Inputs/reloc64-2.obj diff --git a/lld/test/pecoff/reloc64.test b/lld/test/pecoff/reloc64.test new file mode 100644 index 00000000000..980d9a15932 --- /dev/null +++ b/lld/test/pecoff/reloc64.test @@ -0,0 +1,7 @@ +# RUN: lld -flavor link /out:%t.exe /subsystem:console /machine:x64 \ +# RUN: /entry:fn1 -- %p/Inputs/reloc64-1.obj %p/Inputs/reloc64-2.obj +# RUN: llvm-objdump -d %t.exe | FileCheck %s + +CHECK: Disassembly of section .text: +CHECK-NEXT: .text: +CHECK-NEXT: 2000: e8 15 00 00 00 callq 21 |

