diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -103,8 +103,9 @@ // An output section has pointers to chunks in the section, and each // chunk has a back pointer to an output section. - void setOutputSection(OutputSection *O) { Out = O; } - OutputSection *getOutputSection() const { return Out; } + void setOutputSectionIdx(uint16_t O) { OSIdx = O; } + uint16_t getOutputSectionIdx() const { return OSIdx; } + OutputSection *getOutputSection() const; // Windows-specific. // Collect all locations that contain absolute addresses for base relocations. @@ -125,11 +126,12 @@ // value. uint8_t P2Align = 0; + // The output section index for this chunk. The first valid section number is + // one. + uint16_t OSIdx = 0; + // The RVA of this chunk in the output. The writer sets a value. uint32_t RVA = 0; - - // The output section for this chunk. - OutputSection *Out = nullptr; }; // A chunk corresponding a section of an input file. diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -53,7 +53,7 @@ // SectionChunk is one of the most frequently allocated classes, so it is // important to keep it as compact as possible. As of this writing, the number // below is the size of this class on x64 platforms. -static_assert(sizeof(SectionChunk) <= 104, "SectionChunk grew unexpectedly"); +static_assert(sizeof(SectionChunk) <= 96, "SectionChunk grew unexpectedly"); static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); } static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); } @@ -858,7 +858,7 @@ MergeChunk *MergeChunk::Instances[Log2MaxSectionAlignment + 1] = {}; MergeChunk::MergeChunk(uint32_t Alignment) - : Builder(StringTableBuilder::RAW, Alignment) { + : Chunk(OtherKind), Builder(StringTableBuilder::RAW, Alignment) { setAlignment(Alignment); } @@ -886,7 +886,6 @@ if (!C->Live) continue; size_t Off = Builder.getOffset(toStringRef(C->getContents())); - C->setOutputSection(Out); C->setRVA(RVA + Off); } } diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -1030,7 +1030,7 @@ static ArrayRef relocateDebugChunk(BumpPtrAllocator &Alloc, SectionChunk &DebugChunk) { uint8_t *Buffer = Alloc.Allocate(DebugChunk.getSize()); - assert(DebugChunk.getOutputSection() == nullptr && + assert(DebugChunk.getOutputSectionIdx() == 0 && "debug sections should not be in output sections"); DebugChunk.writeTo(Buffer); return makeArrayRef(Buffer, DebugChunk.getSize()); diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -79,6 +79,14 @@ static const int NumberOfDataDirectory = 16; +// Global vector of all output sections. After output sections are finalized, +// this can be indexed by Chunk::getOutputSection. +static std::vector OutputSections; + +OutputSection *Chunk::getOutputSection() const { + return OSIdx == 0 ? nullptr : OutputSections[OSIdx - 1]; +} + namespace { class DebugDirectoryChunk : public Chunk { @@ -193,6 +201,7 @@ void assignAddresses(); void finalizeAddresses(); void removeEmptySections(); + void assignOutputSectionIndices(); void createSymbolAndStringTable(); void openFile(StringRef OutputPath); template void writeHeader(); @@ -226,7 +235,6 @@ std::unique_ptr &Buffer; std::map PartialSections; - std::vector OutputSections; std::vector Strtab; std::vector OutputSymtab; IdataContents Idata; @@ -285,12 +293,10 @@ void OutputSection::addChunk(Chunk *C) { Chunks.push_back(C); - C->setOutputSection(this); } void OutputSection::insertChunkAtStart(Chunk *C) { Chunks.insert(Chunks.begin(), C); - C->setOutputSection(this); } void OutputSection::setPermissions(uint32_t C) { @@ -299,8 +305,6 @@ } void OutputSection::merge(OutputSection *Other) { - for (Chunk *C : Other->Chunks) - C->setOutputSection(this); Chunks.insert(Chunks.end(), Other->Chunks.begin(), Other->Chunks.end()); Other->Chunks.clear(); ContribSections.insert(ContribSections.end(), Other->ContribSections.begin(), @@ -445,7 +449,6 @@ Chunk *ThunkChunk = Thunk->getChunk(); ThunkChunk->setRVA( ThunkInsertionRVA); // Estimate of where it will be located. - ThunkChunk->setOutputSection(OS); OS->Chunks.insert(OS->Chunks.begin() + ThunkInsertionSpot, ThunkChunk); ThunkInsertionSpot++; ThunksSize += ThunkChunk->getSize(); @@ -596,6 +599,7 @@ removeUnusedSections(); finalizeAddresses(); removeEmptySections(); + assignOutputSectionIndices(); setSectionPermissions(); createSymbolAndStringTable(); @@ -1001,9 +1005,26 @@ OutputSections.erase( std::remove_if(OutputSections.begin(), OutputSections.end(), IsEmpty), OutputSections.end()); +} + +void Writer::assignOutputSectionIndices() { + // Assign final output section indices, and assign each chunk to its output + // section. uint32_t Idx = 1; - for (OutputSection *Sec : OutputSections) - Sec->SectionIndex = Idx++; + for (OutputSection *OS : OutputSections) { + OS->SectionIndex = Idx; + for (Chunk *C : OS->Chunks) + C->setOutputSectionIdx(Idx); + ++Idx; + } + + // Merge chunks are containers of chunks, so assign those an output section + // too. + for (MergeChunk *MC : MergeChunk::Instances) + if (MC) + for (SectionChunk *SC : MC->Sections) + if (SC && SC->Live) + SC->setOutputSectionIdx(MC->getOutputSectionIdx()); } size_t Writer::addEntryToStringTable(StringRef Str) { @@ -1464,9 +1485,9 @@ // section. auto *D = cast(S); if (D->getCOFFSymbol().getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { - Chunk *RefChunk = D->getChunk(); - OutputSection *OS = RefChunk ? RefChunk->getOutputSection() : nullptr; - if (OS && OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE) + SectionChunk *SC = dyn_cast(D->getChunk()); + if (SC && SC->Live && + SC->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) addSymbolToRVASet(AddressTakenSyms, D); } break; @@ -1745,8 +1766,9 @@ return; // We assume .pdata contains function table entries only. auto BufAddr = [&](Chunk *C) { - return Buffer->getBufferStart() + C->getOutputSection()->getFileOff() + - C->getRVA() - C->getOutputSection()->getRVA(); + OutputSection *OS = C->getOutputSection(); + return Buffer->getBufferStart() + OS->getFileOff() + C->getRVA() - + OS->getRVA(); }; uint8_t *Begin = BufAddr(FirstPdata); uint8_t *End = BufAddr(LastPdata) + LastPdata->getSize(); diff --git a/lld/test/COFF/strtab-size.s b/lld/test/COFF/strtab-size.s --- a/lld/test/COFF/strtab-size.s +++ b/lld/test/COFF/strtab-size.s @@ -13,7 +13,7 @@ # or disk full, cannot seek to 0x1602"). # RUN: llvm-readobj --file-headers %t.exe | FileCheck %s -# CHECK: SymbolCount: 199 +# CHECK: SymbolCount: 197 .global main .text