diff --git a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp index 9935a91ee44f..7aee81baf467 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 &atomRva) const { atomRva[layout->_atom] = layout->_virtualAddr; } +static int getSectionIndex(uint64_t targetAddr, + const std::vector §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 §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 &atomRva, std::vector §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( - buffer + layout->_fileOffset + ref->offsetInAtom()); + uint8_t *loc = buffer + layout->_fileOffset + ref->offsetInAtom(); + auto relocSite16 = reinterpret_cast(loc); + auto relocSite32 = reinterpret_cast(loc); + auto relocSite64 = reinterpret_cast(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");