24
24
#include " llvm/ADT/STLExtras.h"
25
25
#include " llvm/ADT/StringSet.h"
26
26
#include " llvm/BinaryFormat/COFF.h"
27
+ #include " llvm/MC/StringTableBuilder.h"
27
28
#include " llvm/Support/BinaryStreamReader.h"
28
29
#include " llvm/Support/Debug.h"
29
30
#include " llvm/Support/Endian.h"
@@ -204,7 +205,8 @@ struct ChunkRange {
204
205
class Writer {
205
206
public:
206
207
Writer (COFFLinkerContext &c)
207
- : buffer(c.e.outputBuffer), delayIdata(c), ctx(c) {}
208
+ : buffer(c.e.outputBuffer), strtab(StringTableBuilder::WinCOFF),
209
+ delayIdata (c), ctx(c) {}
208
210
void run ();
209
211
210
212
private:
@@ -284,8 +286,7 @@ class Writer {
284
286
285
287
std::unique_ptr<FileOutputBuffer> &buffer;
286
288
std::map<PartialSectionKey, PartialSection *> partialSections;
287
- std::vector<char > strtab;
288
- StringMap<size_t > strtabMap;
289
+ StringTableBuilder strtab;
289
290
std::vector<llvm::object::coff_symbol16> outputSymtab;
290
291
std::vector<ECCodeMapEntry> codeMap;
291
292
IdataContents idata;
@@ -1438,17 +1439,6 @@ void Writer::assignOutputSectionIndices() {
1438
1439
sc->setOutputSectionIdx (mc->getOutputSectionIdx ());
1439
1440
}
1440
1441
1441
- size_t Writer::addEntryToStringTable (StringRef str) {
1442
- assert (str.size () > COFF::NameSize);
1443
- size_t newOffsetOfEntry = strtab.size () + 4 ; // +4 for the size field
1444
- auto res = strtabMap.try_emplace (str, newOffsetOfEntry);
1445
- if (res.second ) {
1446
- strtab.insert (strtab.end (), str.begin (), str.end ());
1447
- strtab.push_back (' \0 ' );
1448
- }
1449
- return res.first ->getValue ();
1450
- }
1451
-
1452
1442
std::optional<coff_symbol16> Writer::createSymbol (Defined *def) {
1453
1443
coff_symbol16 sym;
1454
1444
switch (def->kind ()) {
@@ -1489,7 +1479,8 @@ std::optional<coff_symbol16> Writer::createSymbol(Defined *def) {
1489
1479
StringRef name = def->getName ();
1490
1480
if (name.size () > COFF::NameSize) {
1491
1481
sym.Name .Offset .Zeroes = 0 ;
1492
- sym.Name .Offset .Offset = addEntryToStringTable (name);
1482
+ sym.Name .Offset .Offset = 0 ; // Filled in later.
1483
+ strtab.add (name);
1493
1484
} else {
1494
1485
memset (sym.Name .ShortName , 0 , COFF::NameSize);
1495
1486
memcpy (sym.Name .ShortName , name.data (), name.size ());
@@ -1521,6 +1512,7 @@ void Writer::createSymbolAndStringTable() {
1521
1512
// solution where discardable sections have long names preserved and
1522
1513
// non-discardable sections have their names truncated, to ensure that any
1523
1514
// section which is mapped at runtime also has its name mapped at runtime.
1515
+ SmallVector<OutputSection *> longNameSections;
1524
1516
for (OutputSection *sec : ctx.outputSections ) {
1525
1517
if (sec->name .size () <= COFF::NameSize)
1526
1518
continue ;
@@ -1532,9 +1524,13 @@ void Writer::createSymbolAndStringTable() {
1532
1524
<< " is longer than 8 characters and will use a non-standard string "
1533
1525
" table" ;
1534
1526
}
1535
- sec->setStringTableOff (addEntryToStringTable (sec->name ));
1527
+ // Put the section name in the begin of strtab so that its offset is less
1528
+ // than Max7DecimalOffset otherwise lldb/gdb will not read it.
1529
+ strtab.add (sec->name , /* Priority=*/ UINT8_MAX);
1530
+ longNameSections.push_back (sec);
1536
1531
}
1537
1532
1533
+ std::vector<std::pair<size_t , StringRef>> longNameSymbols;
1538
1534
if (ctx.config .writeSymtab ) {
1539
1535
for (ObjFile *file : ctx.objFileInstances ) {
1540
1536
for (Symbol *b : file->getSymbols ()) {
@@ -1549,15 +1545,22 @@ void Writer::createSymbolAndStringTable() {
1549
1545
continue ;
1550
1546
}
1551
1547
1552
- if (std::optional<coff_symbol16> sym = createSymbol (d))
1548
+ if (std::optional<coff_symbol16> sym = createSymbol (d)) {
1549
+ if (d->getName ().size () > COFF::NameSize)
1550
+ longNameSymbols.emplace_back (outputSymtab.size (), d->getName ());
1553
1551
outputSymtab.push_back (*sym);
1552
+ }
1554
1553
1555
1554
if (auto *dthunk = dyn_cast<DefinedImportThunk>(d)) {
1556
1555
if (!dthunk->wrappedSym ->writtenToSymtab ) {
1557
1556
dthunk->wrappedSym ->writtenToSymtab = true ;
1558
1557
if (std::optional<coff_symbol16> sym =
1559
- createSymbol (dthunk->wrappedSym ))
1558
+ createSymbol (dthunk->wrappedSym )) {
1559
+ if (d->getName ().size () > COFF::NameSize)
1560
+ longNameSymbols.emplace_back (outputSymtab.size (),
1561
+ dthunk->wrappedSym ->getName ());
1560
1562
outputSymtab.push_back (*sym);
1563
+ }
1561
1564
}
1562
1565
}
1563
1566
}
@@ -1567,11 +1570,19 @@ void Writer::createSymbolAndStringTable() {
1567
1570
if (outputSymtab.empty () && strtab.empty ())
1568
1571
return ;
1569
1572
1573
+ strtab.finalize ();
1574
+ for (OutputSection *sec : longNameSections)
1575
+ sec->setStringTableOff (strtab.getOffset (sec->name ));
1576
+ for (auto P : longNameSymbols) {
1577
+ coff_symbol16 &sym = outputSymtab[P.first ];
1578
+ sym.Name .Offset .Offset = strtab.getOffset (P.second );
1579
+ }
1580
+
1570
1581
// We position the symbol table to be adjacent to the end of the last section.
1571
1582
uint64_t fileOff = fileSize;
1572
1583
pointerToSymbolTable = fileOff;
1573
1584
fileOff += outputSymtab.size () * sizeof (coff_symbol16);
1574
- fileOff += 4 + strtab.size ();
1585
+ fileOff += strtab.getSize ();
1575
1586
fileSize = alignTo (fileOff, ctx.config .fileAlign );
1576
1587
}
1577
1588
@@ -1952,9 +1963,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
1952
1963
// Create the string table, it follows immediately after the symbol table.
1953
1964
// The first 4 bytes is length including itself.
1954
1965
buf = reinterpret_cast <uint8_t *>(&symbolTable[numberOfSymbols]);
1955
- write32le (buf, strtab.size () + 4 );
1956
- if (!strtab.empty ())
1957
- memcpy (buf + 4 , strtab.data (), strtab.size ());
1966
+ strtab.write (buf);
1958
1967
}
1959
1968
1960
1969
void Writer::openFile (StringRef path) {
0 commit comments