diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -90,6 +90,7 @@ BitcodeFile::instances.clear(); memset(MergeChunk::instances, 0, sizeof(MergeChunk::instances)); TpiSource::clear(); + OutputSection::instances.clear(); return !errorCount(); } diff --git a/lld/COFF/Writer.h b/lld/COFF/Writer.h --- a/lld/COFF/Writer.h +++ b/lld/COFF/Writer.h @@ -74,6 +74,7 @@ std::vector origChunks; std::vector contribSections; + static std::vector instances; private: uint32_t stringTableOff = 0; diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -65,12 +65,11 @@ $ xxd -i /tmp/DOSProgram.bin */ static unsigned char dosProgram[] = { - 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, - 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, - 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, - 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, - 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x24, 0x00, 0x00 -}; + 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, + 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, + 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, + 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, + 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x24, 0x00, 0x00}; static_assert(sizeof(dosProgram) % 8 == 0, "DOSProgram size must be multiple of 8"); @@ -81,10 +80,10 @@ // Global vector of all output sections. After output sections are finalized, // this can be indexed by Chunk::getOutputSection. -static std::vector outputSections; +std::vector OutputSection::instances; OutputSection *Chunk::getOutputSection() const { - return osidx == 0 ? nullptr : outputSections[osidx - 1]; + return osidx == 0 ? nullptr : OutputSection::instances[osidx - 1]; } namespace { @@ -102,7 +101,7 @@ void writeTo(uint8_t *b) const override { auto *d = reinterpret_cast(b); - for (const std::pair& record : records) { + for (const std::pair &record : records) { Chunk *c = record.second; OutputSection *os = c->getOutputSection(); uint64_t offs = os->getFileOff() + (c->getRVA() - os->getRVA()); @@ -303,9 +302,7 @@ void lld::coff::writeResult() { Writer().run(); } -void OutputSection::addChunk(Chunk *c) { - chunks.push_back(c); -} +void OutputSection::addChunk(Chunk *c) { chunks.push_back(c); } void OutputSection::insertChunkAtStart(Chunk *c) { chunks.insert(chunks.begin(), c); @@ -540,7 +537,7 @@ return; size_t origNumChunks = 0; - for (OutputSection *sec : outputSections) { + for (OutputSection *sec : OutputSection::instances) { sec->origChunks = sec->chunks; origNumChunks += sec->chunks.size(); } @@ -552,7 +549,7 @@ // adding them turned out ok. bool rangesOk = true; size_t numChunks = 0; - for (OutputSection *sec : outputSections) { + for (OutputSection *sec : OutputSection::instances) { if (!verifyRanges(sec->chunks)) { rangesOk = false; break; @@ -573,7 +570,7 @@ // If the previous pass didn't work out, reset everything back to the // original conditions before retrying with a wider margin. This should // ideally never happen under real circumstances. - for (OutputSection *sec : outputSections) + for (OutputSection *sec : OutputSection::instances) sec->chunks = sec->origChunks; margin *= 2; } @@ -581,7 +578,7 @@ // Try adding thunks everywhere where it is needed, with a margin // to avoid things going out of range due to the added thunks. bool addressesChanged = false; - for (OutputSection *sec : outputSections) + for (OutputSection *sec : OutputSection::instances) addressesChanged |= createThunks(sec, margin); // If the verification above thought we needed thunks, we should have // added some. @@ -614,7 +611,7 @@ if (fileSize > UINT32_MAX) fatal("image size (" + Twine(fileSize) + ") " + - "exceeds maximum allowable size (" + Twine(UINT32_MAX) + ")"); + "exceeds maximum allowable size (" + Twine(UINT32_MAX) + ")"); openFile(config->outputFile); if (config->is64()) { @@ -629,12 +626,12 @@ if (!config->pdbPath.empty() && config->debug) { assert(buildId); - createPDB(symtab, outputSections, sectionTable, buildId->buildId); + createPDB(symtab, OutputSection::instances, sectionTable, buildId->buildId); } writeBuildId(); - writeLLDMapFile(outputSections); - writeMapFile(outputSections); + writeLLDMapFile(OutputSection::instances); + writeMapFile(OutputSection::instances); if (errorCount()) return; @@ -814,7 +811,7 @@ OutputSection *&sec = sections[{name, outChars}]; if (!sec) { sec = make(name, outChars); - outputSections.push_back(sec); + OutputSection::instances.push_back(sec); } return sec; }; @@ -845,8 +842,8 @@ StringRef name = c->getSectionName(); if (shouldStripSectionSuffix(sc, name)) name = name.split('$').first; - PartialSection *pSec = createPartialSection(name, - c->getOutputCharacteristics()); + PartialSection *pSec = + createPartialSection(name, c->getOutputCharacteristics()); pSec->chunks.push_back(c); } @@ -911,7 +908,7 @@ return 1; return 0; }; - llvm::stable_sort(outputSections, + llvm::stable_sort(OutputSection::instances, [&](const OutputSection *s, const OutputSection *t) { return sectionOrder(s) < sectionOrder(t); }); @@ -1062,25 +1059,27 @@ // later. Only remove sections that have no Chunks at all. return s->chunks.empty(); }; - outputSections.erase( - std::remove_if(outputSections.begin(), outputSections.end(), isUnused), - outputSections.end()); + OutputSection::instances.erase( + std::remove_if(OutputSection::instances.begin(), + OutputSection::instances.end(), isUnused), + OutputSection::instances.end()); } // The Windows loader doesn't seem to like empty sections, // so we remove them if any. void Writer::removeEmptySections() { auto isEmpty = [](OutputSection *s) { return s->getVirtualSize() == 0; }; - outputSections.erase( - std::remove_if(outputSections.begin(), outputSections.end(), isEmpty), - outputSections.end()); + OutputSection::instances.erase( + std::remove_if(OutputSection::instances.begin(), + OutputSection::instances.end(), isEmpty), + OutputSection::instances.end()); } void Writer::assignOutputSectionIndices() { // Assign final output section indices, and assign each chunk to its output // section. uint32_t idx = 1; - for (OutputSection *os : outputSections) { + for (OutputSection *os : OutputSection::instances) { os->sectionIndex = idx; for (Chunk *c : os->chunks) c->setOutputSectionIdx(idx); @@ -1167,7 +1166,7 @@ // solution where discardable sections have long names preserved and // non-discardable sections have their names truncated, to ensure that any // section which is mapped at runtime also has its name mapped at runtime. - for (OutputSection *sec : outputSections) { + for (OutputSection *sec : OutputSection::instances) { if (sec->name.size() <= COFF::NameSize) continue; if ((sec->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0) @@ -1241,7 +1240,7 @@ void Writer::assignAddresses() { sizeOfHeaders = dosStubSize + sizeof(PEMagic) + sizeof(coff_file_header) + sizeof(data_directory) * numberOfDataDirectory + - sizeof(coff_section) * outputSections.size(); + sizeof(coff_section) * OutputSection::instances.size(); sizeOfHeaders += config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header); sizeOfHeaders = alignTo(sizeOfHeaders, config->fileAlign); @@ -1250,7 +1249,7 @@ // The first page is kept unmapped. uint64_t rva = alignTo(sizeOfHeaders, config->align); - for (OutputSection *sec : outputSections) { + for (OutputSection *sec : OutputSection::instances) { if (sec == relocSec) addBaserels(); uint64_t rawSize = 0, virtualSize = 0; @@ -1320,7 +1319,7 @@ auto *coff = reinterpret_cast(buf); buf += sizeof(*coff); coff->Machine = config->machine; - coff->NumberOfSections = outputSections.size(); + coff->NumberOfSections = OutputSection::instances.size(); coff->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE; if (config->largeAddressAware) coff->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE; @@ -1469,12 +1468,12 @@ } // Write section table - for (OutputSection *sec : outputSections) { + for (OutputSection *sec : OutputSection::instances) { sec->writeHeaderTo(buf); buf += sizeof(coff_section); } sectionTable = ArrayRef( - buf - outputSections.size() * sizeof(coff_section), buf); + buf - OutputSection::instances.size() * sizeof(coff_section), buf); if (outputSymtab.empty() && strtab.empty()) return; @@ -1773,7 +1772,7 @@ for (auto &p : config->section) { StringRef name = p.first; uint32_t perm = p.second; - for (OutputSection *sec : outputSections) + for (OutputSection *sec : OutputSection::instances) if (sec->name == name) sec->setPermissions(perm); } @@ -1783,10 +1782,10 @@ void Writer::writeSections() { // Record the number of sections to apply section index relocations // against absolute symbols. See applySecIdx in Chunks.cpp.. - DefinedAbsolute::numOutputSections = outputSections.size(); + DefinedAbsolute::numOutputSections = OutputSection::instances.size(); uint8_t *buf = buffer->getBufferStart(); - for (OutputSection *sec : outputSections) { + for (OutputSection *sec : OutputSection::instances) { uint8_t *secBuf = buf + sec->getFileOff(); // Fill gaps between functions in .text with INT3 instructions // instead of leaving as NUL bytes (which can be interpreted as @@ -1863,14 +1862,18 @@ uint8_t *begin = bufAddr(firstPdata); uint8_t *end = bufAddr(lastPdata) + lastPdata->getSize(); if (config->machine == AMD64) { - struct Entry { ulittle32_t begin, end, unwind; }; + struct Entry { + ulittle32_t begin, end, unwind; + }; parallelSort( MutableArrayRef((Entry *)begin, (Entry *)end), [](const Entry &a, const Entry &b) { return a.begin < b.begin; }); return; } if (config->machine == ARMNT || config->machine == ARM64) { - struct Entry { ulittle32_t begin, unwind; }; + struct Entry { + ulittle32_t begin, unwind; + }; parallelSort( MutableArrayRef((Entry *)begin, (Entry *)end), [](const Entry &a, const Entry &b) { return a.begin < b.begin; }); @@ -1916,7 +1919,7 @@ } OutputSection *Writer::findSection(StringRef name) { - for (OutputSection *sec : outputSections) + for (OutputSection *sec : OutputSection::instances) if (sec->name == name) return sec; return nullptr; @@ -1924,7 +1927,7 @@ uint32_t Writer::getSizeOfInitializedData() { uint32_t res = 0; - for (OutputSection *s : outputSections) + for (OutputSection *s : OutputSection::instances) if (s->header.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) res += s->getRawSize(); return res; @@ -1936,7 +1939,7 @@ return; relocSec->chunks.clear(); std::vector v; - for (OutputSection *sec : outputSections) { + for (OutputSection *sec : OutputSection::instances) { if (sec->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) continue; // Collect all locations for base relocations.