diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index 5a151ea4d0ad..7d8fbafe342b 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -37,9 +37,16 @@ SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H, uint32_t SI) void SectionChunk::writeTo(uint8_t *Buf) { if (!hasData()) return; + // Copy section contents from source object file to output file. ArrayRef Data; File->getCOFFObj()->getSectionContents(Header, Data); memcpy(Buf + FileOff, Data.data(), Data.size()); + + // Apply relocations. + for (const auto &I : getSectionRef().relocations()) { + const coff_relocation *Rel = File->getCOFFObj()->getCOFFRelocation(I); + applyReloc(Buf, Rel); + } } // Returns true if this chunk should be considered as a GC root. @@ -80,13 +87,6 @@ void SectionChunk::addAssociative(SectionChunk *Child) { AssocChildren.push_back(Child); } -void SectionChunk::applyRelocations(uint8_t *Buf) { - for (const auto &I : getSectionRef().relocations()) { - const coff_relocation *Rel = File->getCOFFObj()->getCOFFRelocation(I); - applyReloc(Buf, Rel); - } -} - static void add16(uint8_t *P, int32_t V) { write16le(P, read16le(P) + V); } static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); } static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); } @@ -163,11 +163,8 @@ void StringChunk::writeTo(uint8_t *Buf) { void ImportThunkChunk::writeTo(uint8_t *Buf) { memcpy(Buf + FileOff, ImportThunkData, sizeof(ImportThunkData)); -} - -void ImportThunkChunk::applyRelocations(uint8_t *Buf) { + // The first two bytes is a JMP instruction. Fill its operand. uint32_t Operand = ImpSymbol->getRVA() - RVA - getSize(); - // The first two bytes are a JMP instruction. Fill its operand. write32le(Buf + FileOff + 2, Operand); } @@ -182,7 +179,7 @@ void HintNameChunk::writeTo(uint8_t *Buf) { memcpy(Buf + FileOff + 2, Name.data(), Name.size()); } -void LookupChunk::applyRelocations(uint8_t *Buf) { +void LookupChunk::writeTo(uint8_t *Buf) { write32le(Buf + FileOff, HintName->getRVA()); } @@ -192,7 +189,7 @@ void OrdinalOnlyChunk::writeTo(uint8_t *Buf) { write64le(Buf + FileOff, (uint64_t(1) << 63) | Ordinal); } -void DirectoryChunk::applyRelocations(uint8_t *Buf) { +void DirectoryChunk::writeTo(uint8_t *Buf) { auto *E = (coff_import_directory_table_entry *)(Buf + FileOff); E->ImportLookupTableRVA = LookupTab->getRVA(); E->NameRVA = DLLName->getRVA(); diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h index 967f94277209..b821a7f949ec 100644 --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -42,7 +42,10 @@ public: // Returns the size of this chunk (even if this is a common or BSS.) virtual size_t getSize() const = 0; - // Write this chunk to a mmap'ed file. Buf is pointing to beginning of file. + // Write this chunk to a mmap'ed file, assuming Buf is pointing to + // beginning of the file. Because this function may use RVA values + // of other chunks for relocations, you need to set them properly + // before calling this function. virtual void writeTo(uint8_t *Buf) {} // The writer sets and uses the addresses. @@ -52,12 +55,6 @@ public: void setRVA(uint64_t V) { RVA = V; } void setFileOff(uint64_t V) { FileOff = V; } - // Applies relocations, assuming Buffer points to beginning of an - // mmap'ed output file. Because this function uses file offsets and - // RVA values of other chunks, you need to set them properly before - // calling this function. - virtual void applyRelocations(uint8_t *Buf) {} - // Returns true if this has non-zero data. BSS chunks return // false. If false is returned, the space occupied by this chunk // will be filled with zeros. @@ -116,7 +113,6 @@ public: uint32_t SectionIndex); size_t getSize() const override { return Header->SizeOfRawData; } void writeTo(uint8_t *Buf) override; - void applyRelocations(uint8_t *Buf) override; bool hasData() const override; uint32_t getPermissions() const override; StringRef getSectionName() const override { return SectionName; } @@ -185,7 +181,6 @@ public: explicit ImportThunkChunk(Defined *S) : ImpSymbol(S) {} size_t getSize() const override { return sizeof(ImportThunkData); } void writeTo(uint8_t *Buf) override; - void applyRelocations(uint8_t *Buf) override; private: Defined *ImpSymbol; @@ -207,9 +202,8 @@ private: class LookupChunk : public Chunk { public: explicit LookupChunk(Chunk *C) : HintName(C) {} - bool hasData() const override { return false; } size_t getSize() const override { return sizeof(uint64_t); } - void applyRelocations(uint8_t *Buf) override; + void writeTo(uint8_t *Buf) override; Chunk *HintName; }; @@ -219,7 +213,6 @@ public: class OrdinalOnlyChunk : public Chunk { public: explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {} - bool hasData() const override { return true; } size_t getSize() const override { return sizeof(uint64_t); } void writeTo(uint8_t *Buf) override; uint16_t Ordinal; @@ -229,9 +222,8 @@ public: class DirectoryChunk : public Chunk { public: explicit DirectoryChunk(Chunk *N) : DLLName(N) {} - bool hasData() const override { return false; } size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); } - void applyRelocations(uint8_t *Buf) override; + void writeTo(uint8_t *Buf) override; Chunk *DLLName; Chunk *LookupTab; diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 6fd519779eef..482fa476cb3f 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -413,13 +413,6 @@ OutputSection *Writer::createSection(StringRef Name) { return Sec; } -void Writer::applyRelocations() { - uint8_t *Buf = Buffer->getBufferStart(); - for (OutputSection *Sec : OutputSections) - for (Chunk *C : Sec->getChunks()) - C->applyRelocations(Buf); -} - std::error_code Writer::write(StringRef OutputPath) { markLive(); createSections(); @@ -430,7 +423,6 @@ std::error_code Writer::write(StringRef OutputPath) { return EC; writeHeader(); writeSections(); - applyRelocations(); return Buffer->commit(); }