summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp80
-rw-r--r--lld/test/pecoff/Inputs/reloc64-1.asm8
-rw-r--r--lld/test/pecoff/Inputs/reloc64-1.objbin0 -> 448 bytes
-rw-r--r--lld/test/pecoff/Inputs/reloc64-2.asm5
-rw-r--r--lld/test/pecoff/Inputs/reloc64-2.objbin0 -> 416 bytes
-rw-r--r--lld/test/pecoff/reloc64.test7
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> &sectionRva,
- uint64_t imageBaseAddress);
+
+ void applyRelocations32(uint8_t *buffer,
+ std::map<const Atom *, uint64_t> &atomRva,
+ std::vector<uint64_t> &sectionRva,
+ uint64_t imageBaseAddress);
+ void applyRelocations64(uint8_t *buffer,
+ std::map<const Atom *, uint64_t> &atomRva,
+ std::vector<uint64_t> &sectionRva,
+ 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> &sectionRva,
- uint64_t imageBaseAddress) {
+void AtomChunk::applyRelocations32(uint8_t *buffer,
+ std::map<const Atom *, uint64_t> &atomRva,
+ std::vector<uint64_t> &sectionRva,
+ 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> &sectionRva,
+ 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
new file mode 100644
index 00000000000..cb04d2562f3
--- /dev/null
+++ b/lld/test/pecoff/Inputs/reloc64-1.obj
Binary files differ
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
new file mode 100644
index 00000000000..ba022c27147
--- /dev/null
+++ b/lld/test/pecoff/Inputs/reloc64-2.obj
Binary files differ
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
OpenPOWER on IntegriCloud