diff options
| author | Rui Ueyama <ruiu@google.com> | 2014-01-27 19:23:12 +0000 |
|---|---|---|
| committer | Rui Ueyama <ruiu@google.com> | 2014-01-27 19:23:12 +0000 |
| commit | 22291d2cbfc2d03ff5a3eba6d03f2c2eaba27ddc (patch) | |
| tree | 0f830b02b2013efea206cd730302d9877b5c45f7 | |
| parent | f08d658d48c61baaac9e4c6774f0b04bb2374038 (diff) | |
| download | bcm5719-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.cpp | 59 |
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> §ionRva) { + 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> §ionRva) { + 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> §ionRva, @@ -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"); |

