2424#include " llvm/ADT/STLExtras.h"
2525#include " llvm/ADT/StringSet.h"
2626#include " llvm/BinaryFormat/COFF.h"
27+ #include " llvm/MC/StringTableBuilder.h"
2728#include " llvm/Support/Endian.h"
2829#include " llvm/Support/FileOutputBuffer.h"
2930#include " llvm/Support/Parallel.h"
@@ -201,7 +202,8 @@ struct ChunkRange {
201202class Writer {
202203public:
203204 Writer (COFFLinkerContext &c)
204- : buffer(c.e.outputBuffer), delayIdata(c), ctx(c) {}
205+ : buffer(c.e.outputBuffer), strtab(StringTableBuilder::WinCOFF),
206+ delayIdata (c), ctx(c) {}
205207 void run ();
206208
207209private:
@@ -281,7 +283,7 @@ class Writer {
281283
282284 std::unique_ptr<FileOutputBuffer> &buffer;
283285 std::map<PartialSectionKey, PartialSection *> partialSections;
284- std::vector< char > strtab;
286+ StringTableBuilder strtab;
285287 std::vector<llvm::object::coff_symbol16> outputSymtab;
286288 std::vector<ECCodeMapEntry> codeMap;
287289 IdataContents idata;
@@ -1434,14 +1436,6 @@ void Writer::assignOutputSectionIndices() {
14341436 sc->setOutputSectionIdx (mc->getOutputSectionIdx ());
14351437}
14361438
1437- size_t Writer::addEntryToStringTable (StringRef str) {
1438- assert (str.size () > COFF::NameSize);
1439- size_t offsetOfEntry = strtab.size () + 4 ; // +4 for the size field
1440- strtab.insert (strtab.end (), str.begin (), str.end ());
1441- strtab.push_back (' \0 ' );
1442- return offsetOfEntry;
1443- }
1444-
14451439std::optional<coff_symbol16> Writer::createSymbol (Defined *def) {
14461440 coff_symbol16 sym;
14471441 switch (def->kind ()) {
@@ -1482,7 +1476,8 @@ std::optional<coff_symbol16> Writer::createSymbol(Defined *def) {
14821476 StringRef name = def->getName ();
14831477 if (name.size () > COFF::NameSize) {
14841478 sym.Name .Offset .Zeroes = 0 ;
1485- sym.Name .Offset .Offset = addEntryToStringTable (name);
1479+ sym.Name .Offset .Offset = 0 ; // Filled in later.
1480+ strtab.add (name);
14861481 } else {
14871482 memset (sym.Name .ShortName , 0 , COFF::NameSize);
14881483 memcpy (sym.Name .ShortName , name.data (), name.size ());
@@ -1514,6 +1509,7 @@ void Writer::createSymbolAndStringTable() {
15141509 // solution where discardable sections have long names preserved and
15151510 // non-discardable sections have their names truncated, to ensure that any
15161511 // section which is mapped at runtime also has its name mapped at runtime.
1512+ SmallVector<OutputSection *> longNameSections;
15171513 for (OutputSection *sec : ctx.outputSections ) {
15181514 if (sec->name .size () <= COFF::NameSize)
15191515 continue ;
@@ -1525,9 +1521,13 @@ void Writer::createSymbolAndStringTable() {
15251521 << " is longer than 8 characters and will use a non-standard string "
15261522 " table" ;
15271523 }
1528- sec->setStringTableOff (addEntryToStringTable (sec->name ));
1524+ // Put the section name in the begin of strtab so that its offset is less
1525+ // than Max7DecimalOffset otherwise lldb/gdb will not read it.
1526+ strtab.add (sec->name , /* Priority=*/ UINT8_MAX);
1527+ longNameSections.push_back (sec);
15291528 }
15301529
1530+ std::vector<std::pair<size_t , StringRef>> longNameSymbols;
15311531 if (ctx.config .writeSymtab ) {
15321532 for (ObjFile *file : ctx.objFileInstances ) {
15331533 for (Symbol *b : file->getSymbols ()) {
@@ -1542,15 +1542,22 @@ void Writer::createSymbolAndStringTable() {
15421542 continue ;
15431543 }
15441544
1545- if (std::optional<coff_symbol16> sym = createSymbol (d))
1545+ if (std::optional<coff_symbol16> sym = createSymbol (d)) {
1546+ if (d->getName ().size () > COFF::NameSize)
1547+ longNameSymbols.emplace_back (outputSymtab.size (), d->getName ());
15461548 outputSymtab.push_back (*sym);
1549+ }
15471550
15481551 if (auto *dthunk = dyn_cast<DefinedImportThunk>(d)) {
15491552 if (!dthunk->wrappedSym ->writtenToSymtab ) {
15501553 dthunk->wrappedSym ->writtenToSymtab = true ;
15511554 if (std::optional<coff_symbol16> sym =
1552- createSymbol (dthunk->wrappedSym ))
1555+ createSymbol (dthunk->wrappedSym )) {
1556+ if (d->getName ().size () > COFF::NameSize)
1557+ longNameSymbols.emplace_back (outputSymtab.size (),
1558+ dthunk->wrappedSym ->getName ());
15531559 outputSymtab.push_back (*sym);
1560+ }
15541561 }
15551562 }
15561563 }
@@ -1560,11 +1567,19 @@ void Writer::createSymbolAndStringTable() {
15601567 if (outputSymtab.empty () && strtab.empty ())
15611568 return ;
15621569
1570+ strtab.finalize ();
1571+ for (OutputSection *sec : longNameSections)
1572+ sec->setStringTableOff (strtab.getOffset (sec->name ));
1573+ for (auto P : longNameSymbols) {
1574+ coff_symbol16 &sym = outputSymtab[P.first ];
1575+ sym.Name .Offset .Offset = strtab.getOffset (P.second );
1576+ }
1577+
15631578 // We position the symbol table to be adjacent to the end of the last section.
15641579 uint64_t fileOff = fileSize;
15651580 pointerToSymbolTable = fileOff;
15661581 fileOff += outputSymtab.size () * sizeof (coff_symbol16);
1567- fileOff += 4 + strtab.size ();
1582+ fileOff += strtab.getSize ();
15681583 fileSize = alignTo (fileOff, ctx.config .fileAlign );
15691584}
15701585
@@ -1945,9 +1960,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
19451960 // Create the string table, it follows immediately after the symbol table.
19461961 // The first 4 bytes is length including itself.
19471962 buf = reinterpret_cast <uint8_t *>(&symbolTable[numberOfSymbols]);
1948- write32le (buf, strtab.size () + 4 );
1949- if (!strtab.empty ())
1950- memcpy (buf + 4 , strtab.data (), strtab.size ());
1963+ strtab.write (buf);
19511964}
19521965
19531966void Writer::openFile (StringRef path) {
0 commit comments