24
24
#include " llvm/ADT/STLExtras.h"
25
25
#include " llvm/ADT/StringSet.h"
26
26
#include " llvm/ADT/StringSwitch.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"
@@ -195,7 +196,9 @@ class PartialSectionKey {
195
196
// The writer writes a SymbolTable result to a file.
196
197
class Writer {
197
198
public:
198
- Writer (COFFLinkerContext &c) : buffer(errorHandler().outputBuffer), ctx(c) {}
199
+ Writer (COFFLinkerContext &c)
200
+ : buffer(errorHandler().outputBuffer),
201
+ strtab (StringTableBuilder::WinCOFF), ctx(c) {}
199
202
void run ();
200
203
201
204
private:
@@ -240,7 +243,6 @@ class Writer {
240
243
PartialSection *findPartialSection (StringRef name, uint32_t outChars);
241
244
242
245
llvm::Optional<coff_symbol16> createSymbol (Defined *d);
243
- size_t addEntryToStringTable (StringRef str);
244
246
245
247
OutputSection *findSection (StringRef name);
246
248
void addBaserels ();
@@ -250,7 +252,7 @@ class Writer {
250
252
251
253
std::unique_ptr<FileOutputBuffer> &buffer;
252
254
std::map<PartialSectionKey, PartialSection *> partialSections;
253
- std::vector< char > strtab;
255
+ StringTableBuilder strtab;
254
256
std::vector<llvm::object::coff_symbol16> outputSymtab;
255
257
IdataContents idata;
256
258
Chunk *importTableStart = nullptr ;
@@ -1120,14 +1122,6 @@ void Writer::assignOutputSectionIndices() {
1120
1122
sc->setOutputSectionIdx (mc->getOutputSectionIdx ());
1121
1123
}
1122
1124
1123
- size_t Writer::addEntryToStringTable (StringRef str) {
1124
- assert (str.size () > COFF::NameSize);
1125
- size_t offsetOfEntry = strtab.size () + 4 ; // +4 for the size field
1126
- strtab.insert (strtab.end (), str.begin (), str.end ());
1127
- strtab.push_back (' \0 ' );
1128
- return offsetOfEntry;
1129
- }
1130
-
1131
1125
Optional<coff_symbol16> Writer::createSymbol (Defined *def) {
1132
1126
coff_symbol16 sym;
1133
1127
switch (def->kind ()) {
@@ -1164,7 +1158,8 @@ Optional<coff_symbol16> Writer::createSymbol(Defined *def) {
1164
1158
StringRef name = def->getName ();
1165
1159
if (name.size () > COFF::NameSize) {
1166
1160
sym.Name .Offset .Zeroes = 0 ;
1167
- sym.Name .Offset .Offset = addEntryToStringTable (name);
1161
+ sym.Name .Offset .Offset = 0 ; // Filled in later
1162
+ strtab.add (name);
1168
1163
} else {
1169
1164
memset (sym.Name .ShortName , 0 , COFF::NameSize);
1170
1165
memcpy (sym.Name .ShortName , name.data (), name.size ());
@@ -1191,6 +1186,7 @@ void Writer::createSymbolAndStringTable() {
1191
1186
// solution where discardable sections have long names preserved and
1192
1187
// non-discardable sections have their names truncated, to ensure that any
1193
1188
// section which is mapped at runtime also has its name mapped at runtime.
1189
+ std::vector<OutputSection *> longNameSections;
1194
1190
for (OutputSection *sec : ctx.outputSections ) {
1195
1191
if (sec->name .size () <= COFF::NameSize)
1196
1192
continue ;
@@ -1201,9 +1197,12 @@ void Writer::createSymbolAndStringTable() {
1201
1197
" is longer than 8 characters and will use a non-standard string "
1202
1198
" table" );
1203
1199
}
1204
- sec->setStringTableOff (addEntryToStringTable (sec->name ));
1200
+
1201
+ strtab.add (sec->name );
1202
+ longNameSections.push_back (sec);
1205
1203
}
1206
1204
1205
+ std::vector<std::pair<size_t , StringRef>> longNameSymbols;
1207
1206
if (config->debugDwarf || config->debugSymtab ) {
1208
1207
for (ObjFile *file : ctx.objFileInstances ) {
1209
1208
for (Symbol *b : file->getSymbols ()) {
@@ -1218,20 +1217,33 @@ void Writer::createSymbolAndStringTable() {
1218
1217
continue ;
1219
1218
}
1220
1219
1221
- if (Optional<coff_symbol16> sym = createSymbol (d))
1220
+ if (Optional<coff_symbol16> sym = createSymbol (d)) {
1222
1221
outputSymtab.push_back (*sym);
1222
+ if (d->getName ().size () > COFF::NameSize)
1223
+ longNameSymbols.push_back ({outputSymtab.size () - 1 , d->getName ()});
1224
+ }
1223
1225
}
1224
1226
}
1225
1227
}
1226
1228
1227
- if (outputSymtab.empty () && strtab.empty ())
1229
+ strtab.finalize ();
1230
+
1231
+ for (OutputSection *sec : longNameSections)
1232
+ sec->setStringTableOff (strtab.getOffset (sec->name ));
1233
+
1234
+ for (auto P : longNameSymbols) {
1235
+ coff_symbol16 &sym = outputSymtab[P.first ];
1236
+ sym.Name .Offset .Offset = strtab.getOffset (P.second );
1237
+ }
1238
+
1239
+ if (outputSymtab.empty () && strtab.getSize () <= 4 )
1228
1240
return ;
1229
1241
1230
1242
// We position the symbol table to be adjacent to the end of the last section.
1231
1243
uint64_t fileOff = fileSize;
1232
1244
pointerToSymbolTable = fileOff;
1233
1245
fileOff += outputSymtab.size () * sizeof (coff_symbol16);
1234
- fileOff += 4 + strtab.size ();
1246
+ fileOff += strtab.getSize ();
1235
1247
fileSize = alignTo (fileOff, config->fileAlign );
1236
1248
}
1237
1249
@@ -1506,7 +1518,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
1506
1518
sectionTable = ArrayRef<uint8_t >(
1507
1519
buf - ctx.outputSections .size () * sizeof (coff_section), buf);
1508
1520
1509
- if (outputSymtab.empty () && strtab.empty () )
1521
+ if (outputSymtab.empty () && strtab.getSize () <= 4 )
1510
1522
return ;
1511
1523
1512
1524
coff->PointerToSymbolTable = pointerToSymbolTable;
@@ -1519,9 +1531,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
1519
1531
// Create the string table, it follows immediately after the symbol table.
1520
1532
// The first 4 bytes is length including itself.
1521
1533
buf = reinterpret_cast <uint8_t *>(&symbolTable[numberOfSymbols]);
1522
- write32le (buf, strtab.size () + 4 );
1523
- if (!strtab.empty ())
1524
- memcpy (buf + 4 , strtab.data (), strtab.size ());
1534
+ strtab.write (buf);
1525
1535
}
1526
1536
1527
1537
void Writer::openFile (StringRef path) {
0 commit comments