Skip to content

Commit 5e80bde

Browse files
committed
COFF: Stop emitting a non-standard COFF symbol table into PEs.
Now that our support for PDB emission is reasonably good, there is no longer a need to emit a COFF symbol table. Also fix a bug where we would fail to emit a string table for long section names if /debug was not specified. Differential Revision: https://reviews.llvm.org/D40189 llvm-svn: 318548
1 parent d99ac29 commit 5e80bde

File tree

8 files changed

+34
-571
lines changed

8 files changed

+34
-571
lines changed

lld/COFF/Driver.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,8 +1012,6 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
10121012
Args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true);
10131013
Config->NxCompat = Args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true);
10141014
Config->TerminalServerAware = Args.hasFlag(OPT_tsaware, OPT_tsaware_no, true);
1015-
if (Args.hasArg(OPT_nosymtab))
1016-
Config->WriteSymtab = false;
10171015

10181016
Config->MapFile = getMapFile(Args);
10191017

lld/COFF/Options.td

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ def help_q : Flag<["/?", "-?"], "">, Alias<help>;
120120
def debug_dwarf : F<"debug:dwarf">;
121121
def export_all_symbols : F<"export-all-symbols">;
122122
def nopdb : F<"nopdb">, HelpText<"Disable PDB generation for DWARF users">;
123-
def nosymtab : F<"nosymtab">;
124123
def lldmingw : F<"lldmingw">;
125124
def msvclto : F<"msvclto">;
126125
def output_def : Joined<["/", "-"], "output-def:">;

lld/COFF/Writer.cpp

Lines changed: 23 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class Writer {
118118
void createExportTable();
119119
void assignAddresses();
120120
void removeEmptySections();
121-
void createSymbolAndStringTable();
121+
void createStringTable();
122122
void openFile(StringRef OutputPath);
123123
template <typename PEHeaderTy> void writeHeader();
124124
void createSEHTable(OutputSection *RData);
@@ -127,9 +127,6 @@ class Writer {
127127
void writeBuildId();
128128
void sortExceptionTable();
129129

130-
llvm::Optional<coff_symbol16> createSymbol(Defined *D);
131-
size_t addEntryToStringTable(StringRef Str);
132-
133130
OutputSection *findSection(StringRef Name);
134131
OutputSection *createSection(StringRef Name);
135132
void addBaserels(OutputSection *Dest);
@@ -154,7 +151,7 @@ class Writer {
154151
ArrayRef<uint8_t> SectionTable;
155152

156153
uint64_t FileSize;
157-
uint32_t PointerToSymbolTable = 0;
154+
uint32_t PointerToStringTable = 0;
158155
uint64_t SizeOfImage;
159156
uint64_t SizeOfHeaders;
160157
};
@@ -293,7 +290,7 @@ void Writer::run() {
293290
assignAddresses();
294291
removeEmptySections();
295292
setSectionPermissions();
296-
createSymbolAndStringTable();
293+
createStringTable();
297294

298295
// We must do this before opening the output file, as it depends on being able
299296
// to read the contents of the existing output file.
@@ -470,72 +467,7 @@ void Writer::removeEmptySections() {
470467
Sec->SectionIndex = Idx++;
471468
}
472469

473-
size_t Writer::addEntryToStringTable(StringRef Str) {
474-
assert(Str.size() > COFF::NameSize);
475-
size_t OffsetOfEntry = Strtab.size() + 4; // +4 for the size field
476-
Strtab.insert(Strtab.end(), Str.begin(), Str.end());
477-
Strtab.push_back('\0');
478-
return OffsetOfEntry;
479-
}
480-
481-
Optional<coff_symbol16> Writer::createSymbol(Defined *Def) {
482-
// Relative symbols are unrepresentable in a COFF symbol table.
483-
if (isa<DefinedSynthetic>(Def))
484-
return None;
485-
486-
// Don't write dead symbols or symbols in codeview sections to the symbol
487-
// table.
488-
if (!Def->isLive())
489-
return None;
490-
if (auto *D = dyn_cast<DefinedRegular>(Def))
491-
if (D->getChunk()->isCodeView())
492-
return None;
493-
494-
coff_symbol16 Sym;
495-
StringRef Name = Def->getName();
496-
if (Name.size() > COFF::NameSize) {
497-
Sym.Name.Offset.Zeroes = 0;
498-
Sym.Name.Offset.Offset = addEntryToStringTable(Name);
499-
} else {
500-
memset(Sym.Name.ShortName, 0, COFF::NameSize);
501-
memcpy(Sym.Name.ShortName, Name.data(), Name.size());
502-
}
503-
504-
if (auto *D = dyn_cast<DefinedCOFF>(Def)) {
505-
COFFSymbolRef Ref = D->getCOFFSymbol();
506-
Sym.Type = Ref.getType();
507-
Sym.StorageClass = Ref.getStorageClass();
508-
} else {
509-
Sym.Type = IMAGE_SYM_TYPE_NULL;
510-
Sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
511-
}
512-
Sym.NumberOfAuxSymbols = 0;
513-
514-
switch (Def->kind()) {
515-
case Symbol::DefinedAbsoluteKind:
516-
Sym.Value = Def->getRVA();
517-
Sym.SectionNumber = IMAGE_SYM_ABSOLUTE;
518-
break;
519-
default: {
520-
uint64_t RVA = Def->getRVA();
521-
OutputSection *Sec = nullptr;
522-
for (OutputSection *S : OutputSections) {
523-
if (S->getRVA() > RVA)
524-
break;
525-
Sec = S;
526-
}
527-
Sym.Value = RVA - Sec->getRVA();
528-
Sym.SectionNumber = Sec->SectionIndex;
529-
break;
530-
}
531-
}
532-
return Sym;
533-
}
534-
535-
void Writer::createSymbolAndStringTable() {
536-
if (!Config->Debug || !Config->WriteSymtab)
537-
return;
538-
470+
void Writer::createStringTable() {
539471
// Name field in the section table is 8 byte long. Longer names need
540472
// to be written to the string table. First, construct string table.
541473
for (OutputSection *Sec : OutputSections) {
@@ -549,31 +481,19 @@ void Writer::createSymbolAndStringTable() {
549481
// to libunwind.
550482
if ((Sec->getPermissions() & IMAGE_SCN_MEM_DISCARDABLE) == 0)
551483
continue;
552-
Sec->setStringTableOff(addEntryToStringTable(Name));
484+
Sec->setStringTableOff(Strtab.size() + 4); // +4 for the size field
485+
Strtab.insert(Strtab.end(), Name.begin(), Name.end());
486+
Strtab.push_back('\0');
553487
}
554488

555-
for (ObjFile *File : ObjFile::Instances) {
556-
for (Symbol *B : File->getSymbols()) {
557-
auto *D = dyn_cast<Defined>(B);
558-
if (!D || D->WrittenToSymtab)
559-
continue;
560-
D->WrittenToSymtab = true;
561-
562-
if (Optional<coff_symbol16> Sym = createSymbol(D))
563-
OutputSymtab.push_back(*Sym);
564-
}
565-
}
489+
if (Strtab.empty())
490+
return;
566491

567492
OutputSection *LastSection = OutputSections.back();
568-
// We position the symbol table to be adjacent to the end of the last section.
569-
uint64_t FileOff = LastSection->getFileOff() +
570-
alignTo(LastSection->getRawSize(), SectorSize);
571-
if (!OutputSymtab.empty()) {
572-
PointerToSymbolTable = FileOff;
573-
FileOff += OutputSymtab.size() * sizeof(coff_symbol16);
574-
}
575-
FileOff += Strtab.size() + 4;
576-
FileSize = alignTo(FileOff, SectorSize);
493+
// We position the string table to be adjacent to the end of the last section.
494+
PointerToStringTable = LastSection->getFileOff() +
495+
alignTo(LastSection->getRawSize(), SectorSize);
496+
FileSize = alignTo(PointerToStringTable + Strtab.size() + 4, SectorSize);
577497
}
578498

579499
// Visits all sections to assign incremental, non-overlapping RVAs and
@@ -760,22 +680,18 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
760680
SectionTable = ArrayRef<uint8_t>(
761681
Buf - OutputSections.size() * sizeof(coff_section), Buf);
762682

763-
if (OutputSymtab.empty())
683+
// The string table normally follows the symbol table, but because we always
684+
// emit an empty symbol table, the string table appears at the location of the
685+
// symbol table.
686+
COFF->PointerToSymbolTable = PointerToStringTable;
687+
COFF->NumberOfSymbols = 0;
688+
if (Strtab.empty())
764689
return;
765690

766-
COFF->PointerToSymbolTable = PointerToSymbolTable;
767-
uint32_t NumberOfSymbols = OutputSymtab.size();
768-
COFF->NumberOfSymbols = NumberOfSymbols;
769-
auto *SymbolTable = reinterpret_cast<coff_symbol16 *>(
770-
Buffer->getBufferStart() + COFF->PointerToSymbolTable);
771-
for (size_t I = 0; I != NumberOfSymbols; ++I)
772-
SymbolTable[I] = OutputSymtab[I];
773-
// Create the string table, it follows immediately after the symbol table.
774-
// The first 4 bytes is length including itself.
775-
Buf = reinterpret_cast<uint8_t *>(&SymbolTable[NumberOfSymbols]);
776-
write32le(Buf, Strtab.size() + 4);
777-
if (!Strtab.empty())
778-
memcpy(Buf + 4, Strtab.data(), Strtab.size());
691+
auto *StringTable = Buffer->getBufferStart() + PointerToStringTable;
692+
// Create the string table. The first 4 bytes is length including itself.
693+
write32le(StringTable, Strtab.size() + 4);
694+
memcpy(StringTable + 4, Strtab.data(), Strtab.size());
779695
}
780696

781697
void Writer::openFile(StringRef Path) {

lld/test/COFF/delayimports32.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,15 @@ BASEREL-NEXT: ]
7373

7474
DISASM: 202b: 68 20 10 40 00 pushl $4198432
7575
DISASM-NEXT: 2030: 68 00 40 40 00 pushl $4210688
76-
DISASM-NEXT: 2035: e8 c6 ff ff ff calll -58 <_main@0>
76+
DISASM-NEXT: 2035: e8 c6 ff ff ff calll -58 <.text>
7777
DISASM-NEXT: 203a: 5a popl %edx
7878
DISASM-NEXT: 203b: 59 popl %ecx
7979
DISASM-NEXT: 203c: ff e0 jmpl *%eax
8080
DISASM-NEXT: 203e: 51 pushl %ecx
8181
DISASM-NEXT: 203f: 52 pushl %edx
8282
DISASM-NEXT: 2040: 68 24 10 40 00 pushl $4198436
8383
DISASM-NEXT: 2045: 68 00 40 40 00 pushl $4210688
84-
DISASM-NEXT: 204a: e8 b1 ff ff ff calll -79 <_main@0>
84+
DISASM-NEXT: 204a: e8 b1 ff ff ff calll -79 <.text>
8585
DISASM-NEXT: 204f: 5a popl %edx
8686
DISASM-NEXT: 2050: 59 popl %ecx
8787
DISASM-NEXT: 2051: ff e0 jmpl *%eax

lld/test/COFF/long-section-name.test

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# RUN: yaml2obj < %s > %t.obj
2-
# RUN: lld-link /debug /out:%t.exe /entry:main %t.obj
2+
# RUN: lld-link /out:%t.exe /entry:main %t.obj
33
# RUN: llvm-readobj -sections %t.exe | FileCheck %s
4+
# RUN: lld-link /debug /out:%t2.exe /entry:main %t.obj
5+
# RUN: llvm-readobj -sections %t2.exe | FileCheck %s
46

57
# CHECK: Name: .eh_fram (
68
# CHECK: Name: .data_long_section_name

lld/test/COFF/lto-opt-level.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
; RUN: llvm-as -o %t.obj %s
2-
; RUN: lld-link /out:%t0.exe /entry:main /subsystem:console /opt:lldlto=0 /debug %t.obj
3-
; RUN: llvm-nm %t0.exe | FileCheck --check-prefix=CHECK-O0 %s
4-
; RUN: lld-link /out:%t2.exe /entry:main /subsystem:console /opt:lldlto=2 /debug %t.obj
5-
; RUN: llvm-nm %t2.exe | FileCheck --check-prefix=CHECK-O2 %s
6-
; RUN: lld-link /out:%t2a.exe /entry:main /subsystem:console /debug %t.obj
7-
; RUN: llvm-nm %t2a.exe | FileCheck --check-prefix=CHECK-O2 %s
2+
; RUN: lld-link /out:%t0.exe /entry:main /subsystem:console /opt:lldlto=0 /lldmap:%t0.map %t.obj
3+
; RUN: FileCheck --check-prefix=CHECK-O0 %s < %t0.map
4+
; RUN: lld-link /out:%t2.exe /entry:main /subsystem:console /opt:lldlto=2 /lldmap:%t2.map %t.obj
5+
; RUN: FileCheck --check-prefix=CHECK-O2 %s < %t2.map
6+
; RUN: lld-link /out:%t2a.exe /entry:main /subsystem:console /lldmap:%t2a.map %t.obj
7+
; RUN: FileCheck --check-prefix=CHECK-O2 %s < %t2a.map
88

99
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
1010
target triple = "x86_64-pc-windows-msvc"

0 commit comments

Comments
 (0)