From 4c64256b516b1e29d354f0dee3b021fe7c5f6146 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 9 May 2019 21:21:22 +0000 Subject: [PATCH] [COFF] Simplify Chunk::writeTo and remove OutputSectionOff, NFC Summary: Prior to this change, every implementation of writeTo would add OutputSectionOff to the output section buffer start before writing data. Instead, do this math in the caller, so that it can be written once instead of many times. The output section offset is always equivalent to the difference between the chunk RVA and the output section RVA, so we can replace the one remaining usage of OutputSectionOff with that subtraction. This doesn't change the size of SectionChunk because of alignment requirements, but I will rearrange the fields in a follow-up change to accomplish that. Reviewers: ruiu, aganea Subscribers: llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D61696 llvm-svn: 360376 --- lld/COFF/Chunks.cpp | 53 ++++++++++++++--------------- lld/COFF/Chunks.h | 4 --- lld/COFF/DLL.cpp | 83 ++++++++++++++++++++++----------------------- lld/COFF/PDB.cpp | 10 +++--- lld/COFF/Writer.cpp | 11 +++--- 5 files changed, 78 insertions(+), 83 deletions(-) diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index 166912497a68..353d9d9ad7df 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -344,7 +344,7 @@ void SectionChunk::writeTo(uint8_t *Buf) const { // Copy section contents from source object file to output file. ArrayRef A = getContents(); if (!A.empty()) - memcpy(Buf + OutputSectionOff, A.data(), A.size()); + memcpy(Buf, A.data(), A.size()); // Apply relocations. size_t InputSize = getSize(); @@ -360,7 +360,7 @@ void SectionChunk::writeTo(uint8_t *Buf) const { continue; } - uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress; + uint8_t *Off = Buf + Rel.VirtualAddress; auto *Sym = dyn_cast_or_null(File->getSymbol(Rel.SymbolTableIndex)); @@ -649,8 +649,8 @@ uint32_t CommonChunk::getOutputCharacteristics() const { } void StringChunk::writeTo(uint8_t *Buf) const { - memcpy(Buf + OutputSectionOff, Str.data(), Str.size()); - Buf[OutputSectionOff + Str.size()] = '\0'; + memcpy(Buf, Str.data(), Str.size()); + Buf[Str.size()] = '\0'; } ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) { @@ -660,9 +660,9 @@ ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) { } void ImportThunkChunkX64::writeTo(uint8_t *Buf) const { - memcpy(Buf + OutputSectionOff, ImportThunkX86, sizeof(ImportThunkX86)); + memcpy(Buf, ImportThunkX86, sizeof(ImportThunkX86)); // The first two bytes is a JMP instruction. Fill its operand. - write32le(Buf + OutputSectionOff + 2, ImpSymbol->getRVA() - RVA - getSize()); + write32le(Buf + 2, ImpSymbol->getRVA() - RVA - getSize()); } void ImportThunkChunkX86::getBaserels(std::vector *Res) { @@ -670,9 +670,9 @@ void ImportThunkChunkX86::getBaserels(std::vector *Res) { } void ImportThunkChunkX86::writeTo(uint8_t *Buf) const { - memcpy(Buf + OutputSectionOff, ImportThunkX86, sizeof(ImportThunkX86)); + memcpy(Buf, ImportThunkX86, sizeof(ImportThunkX86)); // The first two bytes is a JMP instruction. Fill its operand. - write32le(Buf + OutputSectionOff + 2, + write32le(Buf + 2, ImpSymbol->getRVA() + Config->ImageBase); } @@ -681,16 +681,16 @@ void ImportThunkChunkARM::getBaserels(std::vector *Res) { } void ImportThunkChunkARM::writeTo(uint8_t *Buf) const { - memcpy(Buf + OutputSectionOff, ImportThunkARM, sizeof(ImportThunkARM)); + memcpy(Buf, ImportThunkARM, sizeof(ImportThunkARM)); // Fix mov.w and mov.t operands. - applyMOV32T(Buf + OutputSectionOff, ImpSymbol->getRVA() + Config->ImageBase); + applyMOV32T(Buf, ImpSymbol->getRVA() + Config->ImageBase); } void ImportThunkChunkARM64::writeTo(uint8_t *Buf) const { int64_t Off = ImpSymbol->getRVA() & 0xfff; - memcpy(Buf + OutputSectionOff, ImportThunkARM64, sizeof(ImportThunkARM64)); - applyArm64Addr(Buf + OutputSectionOff, ImpSymbol->getRVA(), RVA, 12); - applyArm64Ldr(Buf + OutputSectionOff + 4, Off); + memcpy(Buf, ImportThunkARM64, sizeof(ImportThunkARM64)); + applyArm64Addr(Buf, ImpSymbol->getRVA(), RVA, 12); + applyArm64Ldr(Buf + 4, Off); } // A Thumb2, PIC, non-interworking range extension thunk. @@ -708,8 +708,8 @@ size_t RangeExtensionThunkARM::getSize() const { void RangeExtensionThunkARM::writeTo(uint8_t *Buf) const { assert(Config->Machine == ARMNT); uint64_t Offset = Target->getRVA() - RVA - 12; - memcpy(Buf + OutputSectionOff, ArmThunk, sizeof(ArmThunk)); - applyMOV32T(Buf + OutputSectionOff, uint32_t(Offset)); + memcpy(Buf, ArmThunk, sizeof(ArmThunk)); + applyMOV32T(Buf, uint32_t(Offset)); } // A position independent ARM64 adrp+add thunk, with a maximum range of @@ -727,9 +727,9 @@ size_t RangeExtensionThunkARM64::getSize() const { void RangeExtensionThunkARM64::writeTo(uint8_t *Buf) const { assert(Config->Machine == ARM64); - memcpy(Buf + OutputSectionOff, Arm64Thunk, sizeof(Arm64Thunk)); - applyArm64Addr(Buf + OutputSectionOff + 0, Target->getRVA(), RVA, 12); - applyArm64Imm(Buf + OutputSectionOff + 4, Target->getRVA() & 0xfff, 0); + memcpy(Buf, Arm64Thunk, sizeof(Arm64Thunk)); + applyArm64Addr(Buf + 0, Target->getRVA(), RVA, 12); + applyArm64Imm(Buf + 4, Target->getRVA() & 0xfff, 0); } void LocalImportChunk::getBaserels(std::vector *Res) { @@ -740,14 +740,14 @@ size_t LocalImportChunk::getSize() const { return Config->Wordsize; } void LocalImportChunk::writeTo(uint8_t *Buf) const { if (Config->is64()) { - write64le(Buf + OutputSectionOff, Sym->getRVA() + Config->ImageBase); + write64le(Buf, Sym->getRVA() + Config->ImageBase); } else { - write32le(Buf + OutputSectionOff, Sym->getRVA() + Config->ImageBase); + write32le(Buf, Sym->getRVA() + Config->ImageBase); } } void RVATableChunk::writeTo(uint8_t *Buf) const { - ulittle32_t *Begin = reinterpret_cast(Buf + OutputSectionOff); + ulittle32_t *Begin = reinterpret_cast(Buf); size_t Cnt = 0; for (const ChunkAndOffset &CO : Syms) Begin[Cnt++] = CO.InputChunk->getRVA() + CO.Offset; @@ -768,7 +768,7 @@ void PseudoRelocTableChunk::writeTo(uint8_t *Buf) const { if (Relocs.empty()) return; - ulittle32_t *Table = reinterpret_cast(Buf + OutputSectionOff); + ulittle32_t *Table = reinterpret_cast(Buf); // This is the list header, to signal the runtime pseudo relocation v2 // format. Table[0] = 0; @@ -838,7 +838,7 @@ BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) { } void BaserelChunk::writeTo(uint8_t *Buf) const { - memcpy(Buf + OutputSectionOff, Data.data(), Data.size()); + memcpy(Buf, Data.data(), Data.size()); } uint8_t Baserel::getDefaultType() { @@ -883,7 +883,6 @@ void MergeChunk::finalizeContents() { size_t Off = Builder.getOffset(toStringRef(C->getContents())); C->setOutputSection(Out); C->setRVA(RVA + Off); - C->OutputSectionOff = OutputSectionOff + Off; } } @@ -896,7 +895,7 @@ size_t MergeChunk::getSize() const { } void MergeChunk::writeTo(uint8_t *Buf) const { - Builder.write(Buf + OutputSectionOff); + Builder.write(Buf); } // MinGW specific. @@ -904,9 +903,9 @@ size_t AbsolutePointerChunk::getSize() const { return Config->Wordsize; } void AbsolutePointerChunk::writeTo(uint8_t *Buf) const { if (Config->is64()) { - write64le(Buf + OutputSectionOff, Value); + write64le(Buf, Value); } else { - write32le(Buf + OutputSectionOff, Value); + write32le(Buf, Value); } } diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h index 223141bfc921..2b3bd29e1c23 100644 --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -121,10 +121,6 @@ protected: // The RVA of this chunk in the output. The writer sets a value. uint32_t RVA = 0; -public: - // The offset from beginning of the output section. The writer sets a value. - uint32_t OutputSectionOff = 0; - protected: // The output section for this chunk. OutputSection *Out = nullptr; diff --git a/lld/COFF/DLL.cpp b/lld/COFF/DLL.cpp index 6c31b787df11..815ba275ef2c 100644 --- a/lld/COFF/DLL.cpp +++ b/lld/COFF/DLL.cpp @@ -46,9 +46,9 @@ public: } void writeTo(uint8_t *Buf) const override { - memset(Buf + OutputSectionOff, 0, getSize()); - write16le(Buf + OutputSectionOff, Hint); - memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size()); + memset(Buf, 0, getSize()); + write16le(Buf, Hint); + memcpy(Buf + 2, Name.data(), Name.size()); } private: @@ -64,9 +64,9 @@ public: void writeTo(uint8_t *Buf) const override { if (Config->is64()) - write64le(Buf + OutputSectionOff, HintName->getRVA()); + write64le(Buf, HintName->getRVA()); else - write32le(Buf + OutputSectionOff, HintName->getRVA()); + write32le(Buf, HintName->getRVA()); } Chunk *HintName; @@ -86,9 +86,9 @@ public: // An import-by-ordinal slot has MSB 1 to indicate that // this is import-by-ordinal (and not import-by-name). if (Config->is64()) { - write64le(Buf + OutputSectionOff, (1ULL << 63) | Ordinal); + write64le(Buf, (1ULL << 63) | Ordinal); } else { - write32le(Buf + OutputSectionOff, (1ULL << 31) | Ordinal); + write32le(Buf, (1ULL << 31) | Ordinal); } } @@ -102,9 +102,9 @@ public: size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); } void writeTo(uint8_t *Buf) const override { - memset(Buf + OutputSectionOff, 0, getSize()); + memset(Buf, 0, getSize()); - auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff); + auto *E = (coff_import_directory_table_entry *)(Buf); E->ImportLookupTableRVA = LookupTab->getRVA(); E->NameRVA = DLLName->getRVA(); E->ImportAddressTableRVA = AddressTab->getRVA(); @@ -124,7 +124,7 @@ public: size_t getSize() const override { return Size; } void writeTo(uint8_t *Buf) const override { - memset(Buf + OutputSectionOff, 0, Size); + memset(Buf, 0, Size); } private: @@ -169,9 +169,9 @@ public: } void writeTo(uint8_t *Buf) const override { - memset(Buf + OutputSectionOff, 0, getSize()); + memset(Buf, 0, getSize()); - auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff); + auto *E = (delay_import_directory_table_entry *)(Buf); E->Attributes = 1; E->Name = DLLName->getRVA(); E->ModuleHandle = ModuleHandle->getRVA(); @@ -280,10 +280,10 @@ public: size_t getSize() const override { return sizeof(ThunkX64); } void writeTo(uint8_t *Buf) const override { - memcpy(Buf + OutputSectionOff, ThunkX64, sizeof(ThunkX64)); - write32le(Buf + OutputSectionOff + 36, Imp->getRVA() - RVA - 40); - write32le(Buf + OutputSectionOff + 43, Desc->getRVA() - RVA - 47); - write32le(Buf + OutputSectionOff + 48, Helper->getRVA() - RVA - 52); + memcpy(Buf, ThunkX64, sizeof(ThunkX64)); + write32le(Buf + 36, Imp->getRVA() - RVA - 40); + write32le(Buf + 43, Desc->getRVA() - RVA - 47); + write32le(Buf + 48, Helper->getRVA() - RVA - 52); } Defined *Imp = nullptr; @@ -299,10 +299,10 @@ public: size_t getSize() const override { return sizeof(ThunkX86); } void writeTo(uint8_t *Buf) const override { - memcpy(Buf + OutputSectionOff, ThunkX86, sizeof(ThunkX86)); - write32le(Buf + OutputSectionOff + 3, Imp->getRVA() + Config->ImageBase); - write32le(Buf + OutputSectionOff + 8, Desc->getRVA() + Config->ImageBase); - write32le(Buf + OutputSectionOff + 13, Helper->getRVA() - RVA - 17); + memcpy(Buf, ThunkX86, sizeof(ThunkX86)); + write32le(Buf + 3, Imp->getRVA() + Config->ImageBase); + write32le(Buf + 8, Desc->getRVA() + Config->ImageBase); + write32le(Buf + 13, Helper->getRVA() - RVA - 17); } void getBaserels(std::vector *Res) override { @@ -323,10 +323,10 @@ public: size_t getSize() const override { return sizeof(ThunkARM); } void writeTo(uint8_t *Buf) const override { - memcpy(Buf + OutputSectionOff, ThunkARM, sizeof(ThunkARM)); - applyMOV32T(Buf + OutputSectionOff + 0, Imp->getRVA() + Config->ImageBase); - applyMOV32T(Buf + OutputSectionOff + 22, Desc->getRVA() + Config->ImageBase); - applyBranch24T(Buf + OutputSectionOff + 30, Helper->getRVA() - RVA - 34); + memcpy(Buf, ThunkARM, sizeof(ThunkARM)); + applyMOV32T(Buf + 0, Imp->getRVA() + Config->ImageBase); + applyMOV32T(Buf + 22, Desc->getRVA() + Config->ImageBase); + applyBranch24T(Buf + 30, Helper->getRVA() - RVA - 34); } void getBaserels(std::vector *Res) override { @@ -347,13 +347,12 @@ public: size_t getSize() const override { return sizeof(ThunkARM64); } void writeTo(uint8_t *Buf) const override { - memcpy(Buf + OutputSectionOff, ThunkARM64, sizeof(ThunkARM64)); - applyArm64Addr(Buf + OutputSectionOff + 0, Imp->getRVA(), RVA + 0, 12); - applyArm64Imm(Buf + OutputSectionOff + 4, Imp->getRVA() & 0xfff, 0); - applyArm64Addr(Buf + OutputSectionOff + 52, Desc->getRVA(), RVA + 52, 12); - applyArm64Imm(Buf + OutputSectionOff + 56, Desc->getRVA() & 0xfff, 0); - applyArm64Branch26(Buf + OutputSectionOff + 60, - Helper->getRVA() - RVA - 60); + memcpy(Buf, ThunkARM64, sizeof(ThunkARM64)); + applyArm64Addr(Buf + 0, Imp->getRVA(), RVA + 0, 12); + applyArm64Imm(Buf + 4, Imp->getRVA() & 0xfff, 0); + applyArm64Addr(Buf + 52, Desc->getRVA(), RVA + 52, 12); + applyArm64Imm(Buf + 56, Desc->getRVA() & 0xfff, 0); + applyArm64Branch26(Buf + 60, Helper->getRVA() - RVA - 60); } Defined *Imp = nullptr; @@ -371,13 +370,13 @@ public: void writeTo(uint8_t *Buf) const override { if (Config->is64()) { - write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase); + write64le(Buf, Thunk->getRVA() + Config->ImageBase); } else { uint32_t Bit = 0; // Pointer to thumb code must have the LSB set, so adjust it. if (Config->Machine == ARMNT) Bit = 1; - write32le(Buf + OutputSectionOff, (Thunk->getRVA() + Config->ImageBase) | Bit); + write32le(Buf, (Thunk->getRVA() + Config->ImageBase) | Bit); } } @@ -403,9 +402,9 @@ public: } void writeTo(uint8_t *Buf) const override { - memset(Buf + OutputSectionOff, 0, getSize()); + memset(Buf, 0, getSize()); - auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff); + auto *E = (export_directory_table_entry *)(Buf); E->NameRVA = DLLName->getRVA(); E->OrdinalBase = 0; E->AddressTableEntries = MaxOrdinal + 1; @@ -429,10 +428,10 @@ public: size_t getSize() const override { return Size * 4; } void writeTo(uint8_t *Buf) const override { - memset(Buf + OutputSectionOff, 0, getSize()); + memset(Buf, 0, getSize()); for (const Export &E : Config->Exports) { - uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4; + uint8_t *P = Buf + E.Ordinal * 4; uint32_t Bit = 0; // Pointer to thumb code must have the LSB set, so adjust it. if (Config->Machine == ARMNT && !E.Data) @@ -455,10 +454,9 @@ public: size_t getSize() const override { return Chunks.size() * 4; } void writeTo(uint8_t *Buf) const override { - uint8_t *P = Buf + OutputSectionOff; for (Chunk *C : Chunks) { - write32le(P, C->getRVA()); - P += 4; + write32le(Buf, C->getRVA()); + Buf += 4; } } @@ -472,12 +470,11 @@ public: size_t getSize() const override { return Size * 2; } void writeTo(uint8_t *Buf) const override { - uint8_t *P = Buf + OutputSectionOff; for (Export &E : Config->Exports) { if (E.Noname) continue; - write16le(P, E.Ordinal); - P += 2; + write16le(Buf, E.Ordinal); + Buf += 2; } } diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp index a192724dd496..f237485c0bbe 100644 --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -1030,7 +1030,7 @@ void PDBLinker::mergeSymbolRecords(ObjFile *File, const CVIndexMap &IndexMap, static ArrayRef relocateDebugChunk(BumpPtrAllocator &Alloc, SectionChunk &DebugChunk) { uint8_t *Buffer = Alloc.Allocate(DebugChunk.getSize()); - assert(DebugChunk.OutputSectionOff == 0 && + assert(DebugChunk.getOutputSection() == nullptr && "debug sections should not be in output sections"); DebugChunk.writeTo(Buffer); return makeArrayRef(Buffer, DebugChunk.getSize()); @@ -1557,6 +1557,8 @@ void PDBLinker::addImportFilesToPDB(ArrayRef OutputSections) { } DefinedImportThunk *Thunk = cast(File->ThunkSym); + Chunk *ThunkChunk = Thunk->getChunk(); + OutputSection *ThunkOS = ThunkChunk->getOutputSection(); ObjNameSym ONS(SymbolRecordKind::ObjNameSym); Compile3Sym CS(SymbolRecordKind::Compile3Sym); @@ -1573,9 +1575,9 @@ void PDBLinker::addImportFilesToPDB(ArrayRef OutputSections) { TS.End = 0; TS.Next = 0; TS.Thunk = ThunkOrdinal::Standard; - TS.Length = Thunk->getChunk()->getSize(); - TS.Segment = Thunk->getChunk()->getOutputSection()->SectionIndex; - TS.Offset = Thunk->getChunk()->OutputSectionOff; + TS.Length = ThunkChunk->getSize(); + TS.Segment = ThunkOS->SectionIndex; + TS.Offset = ThunkChunk->getRVA() - ThunkOS->getRVA(); Mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol( ONS, Alloc, CodeViewContainer::Pdb)); diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 5918e7537514..46e8ee663931 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -91,7 +91,7 @@ public: } void writeTo(uint8_t *B) const override { - auto *D = reinterpret_cast(B + OutputSectionOff); + auto *D = reinterpret_cast(B); for (const Chunk *Record : Records) { OutputSection *OS = Record->getOutputSection(); @@ -145,10 +145,10 @@ public: void writeTo(uint8_t *B) const override { // Save off the DebugInfo entry to backfill the file signature (build id) // in Writer::writeBuildId - BuildId = reinterpret_cast(B + OutputSectionOff); + BuildId = reinterpret_cast(B); // variable sized field (PDB Path) - char *P = reinterpret_cast(B + OutputSectionOff + sizeof(*BuildId)); + char *P = reinterpret_cast(B + sizeof(*BuildId)); if (!Config->PDBAltPath.empty()) memcpy(P, Config->PDBAltPath.data(), Config->PDBAltPath.size()); P[Config->PDBAltPath.size()] = '\0'; @@ -1161,7 +1161,6 @@ void Writer::assignAddresses() { VirtualSize += Padding; VirtualSize = alignTo(VirtualSize, C->Alignment); C->setRVA(RVA + VirtualSize); - C->OutputSectionOff = VirtualSize; C->finalizeContents(); VirtualSize += C->getSize(); if (C->hasData()) @@ -1675,7 +1674,9 @@ void Writer::writeSections() { // ADD instructions). if (Sec->Header.Characteristics & IMAGE_SCN_CNT_CODE) memset(SecBuf, 0xCC, Sec->getRawSize()); - parallelForEach(Sec->Chunks, [&](Chunk *C) { C->writeTo(SecBuf); }); + parallelForEach(Sec->Chunks, [&](Chunk *C) { + C->writeTo(SecBuf + C->getRVA() - Sec->getRVA()); + }); } }