summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2014-01-27 19:23:12 +0000
committerRui Ueyama <ruiu@google.com>2014-01-27 19:23:12 +0000
commit22291d2cbfc2d03ff5a3eba6d03f2c2eaba27ddc (patch)
tree0f830b02b2013efea206cd730302d9877b5c45f7
parentf08d658d48c61baaac9e4c6774f0b04bb2374038 (diff)
downloadbcm5719-llvm-22291d2cbfc2d03ff5a3eba6d03f2c2eaba27ddc.tar.gz
bcm5719-llvm-22291d2cbfc2d03ff5a3eba6d03f2c2eaba27ddc.zip
[PECOFF] Implement some relocations for x86-64.
llvm-svn: 200240
-rw-r--r--lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp59
1 files changed, 40 insertions, 19 deletions
diff --git a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
index 9935a91ee44..7aee81baf46 100644
--- a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
@@ -48,6 +48,7 @@
using llvm::support::ulittle16_t;
using llvm::support::ulittle32_t;
+using llvm::support::ulittle64_t;
using llvm::COFF::DataDirectoryIndex;
namespace lld {
@@ -467,6 +468,25 @@ AtomChunk::buildAtomRvaMap(std::map<const Atom *, uint64_t> &atomRva) const {
atomRva[layout->_atom] = layout->_virtualAddr;
}
+static int getSectionIndex(uint64_t targetAddr,
+ const std::vector<uint64_t> &sectionRva) {
+ int i = 1;
+ for (uint64_t rva : sectionRva) {
+ if (targetAddr < rva)
+ return i;
+ ++i;
+ }
+ return i;
+}
+
+static uint32_t getSectionStartAddr(uint64_t targetAddr,
+ const std::vector<uint64_t> &sectionRva) {
+ for (int i = 0, e = sectionRva.size(); i < e; ++i)
+ if (i == e - 1 || (sectionRva[i] <= targetAddr && targetAddr <= sectionRva[i + 1]))
+ return sectionRva[i];
+ llvm_unreachable("Section missing");
+}
+
void AtomChunk::applyRelocations32(uint8_t *buffer,
std::map<const Atom *, uint64_t> &atomRva,
std::vector<uint64_t> &sectionRva,
@@ -504,28 +524,14 @@ void AtomChunk::applyRelocations32(uint8_t *buffer,
*relocSite32 = targetAddr - disp;
break;
}
- case llvm::COFF::IMAGE_REL_I386_SECTION: {
+ case llvm::COFF::IMAGE_REL_I386_SECTION:
// The 16-bit section index that contains the target symbol.
- uint16_t i = 1;
- for (uint64_t rva : sectionRva) {
- if (targetAddr < rva) {
- *relocSite16 = i;
- break;
- }
- ++i;
- }
+ *relocSite16 = getSectionIndex(targetAddr, sectionRva);
break;
- }
case llvm::COFF::IMAGE_REL_I386_SECREL:
// The 32-bit relative address from the beginning of the section that
// contains the target symbol.
- for (int i = 0, e = sectionRva.size(); i < e; ++i) {
- if (i == e - 1 || (sectionRva[i] <= targetAddr &&
- targetAddr <= sectionRva[i + 1])) {
- *relocSite32 = targetAddr - sectionRva[i];
- break;
- }
- }
+ *relocSite32 = targetAddr - getSectionStartAddr(targetAddr, sectionRva);
break;
default:
llvm_unreachable("Unsupported relocation kind");
@@ -545,11 +551,19 @@ void AtomChunk::applyRelocations64(uint8_t *buffer,
if (ref->kindNamespace() != Reference::KindNamespace::COFF)
continue;
- auto relocSite32 = reinterpret_cast<ulittle32_t *>(
- buffer + layout->_fileOffset + ref->offsetInAtom());
+ uint8_t *loc = buffer + layout->_fileOffset + ref->offsetInAtom();
+ auto relocSite16 = reinterpret_cast<ulittle16_t *>(loc);
+ auto relocSite32 = reinterpret_cast<ulittle32_t *>(loc);
+ auto relocSite64 = reinterpret_cast<ulittle64_t *>(loc);
uint64_t targetAddr = atomRva[ref->target()];
switch (ref->kindValue()) {
+ case llvm::COFF::IMAGE_REL_AMD64_ADDR64:
+ *relocSite64 = targetAddr;
+ break;
+ case llvm::COFF::IMAGE_REL_AMD64_ADDR32:
+ *relocSite32 = targetAddr;
+ break;
case llvm::COFF::IMAGE_REL_AMD64_ADDR32NB:
*relocSite32 = targetAddr - imageBase;
break;
@@ -569,6 +583,13 @@ void AtomChunk::applyRelocations64(uint8_t *buffer,
REL32(5);
#undef CASE
+ case llvm::COFF::IMAGE_REL_AMD64_SECTION:
+ *relocSite16 = getSectionIndex(targetAddr, sectionRva);
+ break;
+ case llvm::COFF::IMAGE_REL_AMD64_SECREL:
+ *relocSite32 = targetAddr - getSectionStartAddr(targetAddr, sectionRva);
+ break;
+
default:
llvm::errs() << "Kind: " << (int)ref->kindValue() << "\n";
llvm_unreachable("Unsupported relocation kind");
OpenPOWER on IntegriCloud