[PATCH] [lld][PECOFF] Support IMAGE_REL_I386_DIR32 relocation.
Rui Ueyama
ruiu at google.com
Fri Jun 14 17:08:25 PDT 2013
- Renamed AtomChunk -> SectionChunk.
Hi Bigcheese,
http://llvm-reviews.chandlerc.com/D985
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D985?vs=2428&id=2429#toc
BRANCH
reloc
ARCANIST PROJECT
lld
Files:
lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
test/pecoff/reloc.test
Index: lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
===================================================================
--- lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
+++ lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
@@ -37,6 +37,7 @@
#include "llvm/Object/COFF.h"
#include "llvm/Support/COFF.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileOutputBuffer.h"
@@ -196,6 +197,7 @@
}
virtual void write(uint8_t *fileBuffer) {
+ fileBuffer += fileOffset();
std::memcpy(fileBuffer, llvm::COFF::PEMagic, sizeof(llvm::COFF::PEMagic));
fileBuffer += sizeof(llvm::COFF::PEMagic);
std::memcpy(fileBuffer, &_coffHeader, sizeof(_coffHeader));
@@ -235,6 +237,7 @@
}
virtual void write(uint8_t *fileBuffer) {
+ fileBuffer += fileOffset();
std::memcpy(fileBuffer, &_dirs, sizeof(_dirs));
}
@@ -255,8 +258,9 @@
std::vector<SectionChunk *> _sections;
};
-/// A SectionChunk represents a section in the output file. It consists of a
-/// section header and atoms which to be output as the content of the section.
+/// A SectionChunk represents a section containing atoms. It consists of a
+/// section header that to be written to PECOFF header and atoms which to be
+/// written to the raw data section.
class SectionChunk : public Chunk {
private:
llvm::object::coff_section
@@ -301,29 +305,61 @@
}
void appendAtom(const DefinedAtom *atom) {
- _atoms.push_back(atom);
+ auto *layout = new (_storage) AtomLayout(atom, _size, _size);
+ _atomLayouts.push_back(layout);
_size += atom->rawContent().size();
}
virtual void write(uint8_t *fileBuffer) {
- uint64_t offset = 0;
- for (const auto &atom : _atoms) {
+ for (const auto *layout : _atomLayouts) {
+ const DefinedAtom *atom = dyn_cast<const DefinedAtom>(layout->_atom);
ArrayRef<uint8_t> rawContent = atom->rawContent();
- std::memcpy(fileBuffer + offset, rawContent.data(), rawContent.size());
- offset += rawContent.size();
+ std::memcpy(fileBuffer + layout->_fileOffset, rawContent.data(),
+ rawContent.size());
}
}
- const std::vector<const DefinedAtom *> getAtoms() { return _atoms; }
+ /// Add all atoms to the given map. This data will be used to do relocation.
+ void
+ buildAtomToVirtualAddr(std::map<const Atom *, uint64_t> &atomToVirtualAddr) {
+ for (const auto *layout : _atomLayouts)
+ atomToVirtualAddr[layout->_atom] = layout->_virtualAddr;
+ }
+
+ void applyRelocations(uint8_t *fileBuffer,
+ std::map<const Atom *, uint64_t> &atomToVirtualAddr) {
+ for (const auto *layout : _atomLayouts) {
+ const DefinedAtom *atom = dyn_cast<const DefinedAtom>(layout->_atom);
+ for (const Reference *ref : *atom) {
+ auto relocSite = reinterpret_cast<llvm::support::ulittle32_t *>(
+ fileBuffer + layout->_fileOffset + ref->offsetInAtom());
+ uint64_t targetAddr = atomToVirtualAddr[ref->target()];
+ switch (ref->kind()) {
+ case llvm::COFF::IMAGE_REL_I386_DIR32:
+ *relocSite = targetAddr;
+ break;
+ case llvm::COFF::IMAGE_REL_I386_REL32:
+ // TODO: Implement this relocation
+ break;
+ default:
+ llvm_unreachable("Unsupported relocation kind");
+ }
+ }
+ }
+ }
// Set the file offset of the beginning of this section.
virtual void setFileOffset(uint64_t fileOffset) {
Chunk::setFileOffset(fileOffset);
_sectionHeader.PointerToRawData = fileOffset;
+ for (AtomLayout *layout : _atomLayouts)
+ layout->_fileOffset += fileOffset;
}
virtual void setVirtualAddress(uint32_t rva) {
_sectionHeader.VirtualAddress = rva;
+ for (AtomLayout *layout : _atomLayouts)
+ layout->_virtualAddr += rva;
}
virtual uint32_t getVirtualAddress() { return _sectionHeader.VirtualAddress; }
@@ -338,7 +374,8 @@
llvm::object::coff_section _sectionHeader;
private:
- std::vector<const DefinedAtom *> _atoms;
+ std::vector<AtomLayout *> _atomLayouts;
+ mutable llvm::BumpPtrAllocator _storage;
};
void SectionHeaderTableChunk::addSection(SectionChunk *chunk) {
@@ -351,6 +388,7 @@
void SectionHeaderTableChunk::write(uint8_t *fileBuffer) {
uint64_t offset = 0;
+ fileBuffer += fileOffset();
for (const auto &chunk : _sections) {
const llvm::object::coff_section &header = chunk->getSectionHeader();
std::memcpy(fileBuffer + offset, &header, sizeof(header));
@@ -481,6 +519,20 @@
imageSize = va - offset;
}
+ /// Apply relocations to the output file buffer. This two pass. In the first
+ /// pass, we visit all atoms to create a map from atom to its virtual
+ /// address. In the second pass, we visit all relocation references to fix
+ /// up addresses in the buffer.
+ void applyRelocations(uint8_t *bufferStart) {
+ std::map<const Atom *, uint64_t> atomToVirtualAddr;
+ for (auto &cp : _chunks)
+ if (SectionChunk *chunk = dyn_cast<SectionChunk>(&*cp))
+ chunk->buildAtomToVirtualAddr(atomToVirtualAddr);
+ for (auto &cp : _chunks)
+ if (SectionChunk *chunk = dyn_cast<SectionChunk>(&*cp))
+ chunk->applyRelocations(bufferStart, atomToVirtualAddr);
+ }
+
void addChunk(Chunk *chunk) {
_chunks.push_back(std::unique_ptr<Chunk>(chunk));
}
@@ -534,7 +586,8 @@
return ec;
for (const auto &chunk : _chunks)
- chunk->write(buffer->getBufferStart() + chunk->fileOffset());
+ chunk->write(buffer->getBufferStart());
+ applyRelocations(buffer->getBufferStart());
return buffer->commit();
}
Index: test/pecoff/reloc.test
===================================================================
--- /dev/null
+++ test/pecoff/reloc.test
@@ -0,0 +1,26 @@
+# RUN: llvm-objdump -d %p/Inputs/hello.obj | FileCheck -check-prefix=BEFORE %s
+#
+# RUN: lld -flavor link -out %t1 -subsystem console -force -- %p/Inputs/hello.obj \
+# RUN: && llvm-objdump -d %t1 | FileCheck -check-prefix=AFTER %s
+
+BEFORE: Disassembly of section .text:
+BEFORE: _main:
+BEFORE: 0: b8 00 00 00 00
+BEFORE: 5: 50
+BEFORE: 6: 68 00 00 00 00
+BEFORE: b: 68 00 00 00 00
+BEFORE: 10: 50
+BEFORE: 11: e8 00 00 00 00
+BEFORE: 16: 50
+BEFORE: 17: e8 00 00 00 00
+
+AFTER: Disassembly of section .text:
+AFTER: .text:
+AFTER: 1000: b8 00 00 00 00
+AFTER: 1005: 50
+AFTER: 1006: 68 00 20 00 00
+AFTER: 100b: 68 06 20 00 00
+AFTER: 1010: 50
+AFTER: 1011: e8 00 00 00 00
+AFTER: 1016: 50
+AFTER: 1017: e8 00 00 00 00
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D985.2.patch
Type: text/x-patch
Size: 6780 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130614/a8a8319a/attachment.bin>
More information about the llvm-commits
mailing list