Skip to content

Commit 0929464

Browse files
committed
ELFObjectWriter: Make STT_FILE precede associated local symbols
1 parent 6042009 commit 0929464

File tree

4 files changed

+44
-26
lines changed

4 files changed

+44
-26
lines changed

llvm/include/llvm/MC/MCAssembler.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ class MCAssembler {
119119
std::vector<std::vector<std::string>> LinkerOptions;
120120

121121
/// List of declared file names
122-
std::vector<std::string> FileNames;
122+
std::vector<std::pair<std::string, size_t>> FileNames;
123123

124124
MCDwarfLineTableParams LTParams;
125125

@@ -445,11 +445,15 @@ class MCAssembler {
445445

446446
void registerSymbol(const MCSymbol &Symbol, bool *Created = nullptr);
447447

448-
ArrayRef<std::string> getFileNames() { return FileNames; }
448+
MutableArrayRef<std::pair<std::string, size_t>> getFileNames() {
449+
return FileNames;
450+
}
449451

450452
void addFileName(StringRef FileName) {
451-
if (!is_contained(FileNames, FileName))
452-
FileNames.push_back(std::string(FileName));
453+
for (const std::pair<std::string, size_t> &F : FileNames)
454+
if (F.first == FileName)
455+
return;
456+
FileNames.emplace_back(std::string(FileName), Symbols.size());
453457
}
454458

455459
/// Write the necessary bundle padding to \p OS.

llvm/lib/MC/ELFObjectWriter.cpp

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,9 @@ struct ELFWriter {
116116
/// Helper struct for containing some precomputed information on symbols.
117117
struct ELFSymbolData {
118118
const MCSymbolELF *Symbol;
119-
uint32_t SectionIndex;
120119
StringRef Name;
120+
uint32_t SectionIndex;
121+
uint32_t Order;
121122

122123
// Support lexicographic sorting.
123124
bool operator<(const ELFSymbolData &RHS) const {
@@ -626,11 +627,15 @@ void ELFWriter::computeSymbolTable(
626627

627628
std::vector<ELFSymbolData> LocalSymbolData;
628629
std::vector<ELFSymbolData> ExternalSymbolData;
630+
MutableArrayRef<std::pair<std::string, size_t>> FileNames =
631+
Asm.getFileNames();
632+
for (const std::pair<std::string, size_t> &F : FileNames)
633+
StrTabBuilder.add(F.first);
629634

630635
// Add the data for the symbols.
631636
bool HasLargeSectionIndex = false;
632-
for (const MCSymbol &S : Asm.symbols()) {
633-
const auto &Symbol = cast<MCSymbolELF>(S);
637+
for (auto It : llvm::enumerate(Asm.symbols())) {
638+
const auto &Symbol = cast<MCSymbolELF>(It.value());
634639
bool Used = Symbol.isUsedInReloc();
635640
bool WeakrefUsed = Symbol.isWeakrefUsedInReloc();
636641
bool isSignature = Symbol.isSignature();
@@ -646,6 +651,7 @@ void ELFWriter::computeSymbolTable(
646651

647652
ELFSymbolData MSD;
648653
MSD.Symbol = cast<MCSymbolELF>(&Symbol);
654+
MSD.Order = It.index();
649655

650656
bool Local = Symbol.getBinding() == ELF::STB_LOCAL;
651657
assert(Local || !Symbol.isTemporary());
@@ -716,34 +722,40 @@ void ELFWriter::computeSymbolTable(
716722
SymtabShndxSection->setAlignment(Align(4));
717723
}
718724

719-
ArrayRef<std::string> FileNames = Asm.getFileNames();
720-
for (const std::string &Name : FileNames)
721-
StrTabBuilder.add(Name);
722-
723725
StrTabBuilder.finalize();
724726

725-
// File symbols are emitted first and handled separately from normal symbols,
726-
// i.e. a non-STT_FILE symbol with the same name may appear.
727-
for (const std::string &Name : FileNames)
728-
Writer.writeSymbol(StrTabBuilder.getOffset(Name),
729-
ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,
730-
ELF::SHN_ABS, true);
731-
732727
// Symbols are required to be in lexicographic order.
733728
//array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end());
734729
array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
735730

736-
// Set the symbol indices. Local symbols must come before all other
737-
// symbols with non-local bindings.
738-
unsigned Index = FileNames.size() + 1;
731+
// Make the first STT_FILE precede previous local symbols.
732+
unsigned Index = 1;
733+
auto FileNameIt = FileNames.begin();
734+
if (!FileNames.empty())
735+
FileNames[0].second = 0;
739736

740737
for (ELFSymbolData &MSD : LocalSymbolData) {
738+
// Emit STT_FILE symbols before their associated local symbols.
739+
for (; FileNameIt != FileNames.end() && FileNameIt->second <= MSD.Order;
740+
++FileNameIt) {
741+
Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),
742+
ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,
743+
ELF::SHN_ABS, true);
744+
++Index;
745+
}
746+
741747
unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION
742748
? 0
743749
: StrTabBuilder.getOffset(MSD.Name);
744750
MSD.Symbol->setIndex(Index++);
745751
writeSymbol(Writer, StringIndex, MSD, Layout);
746752
}
753+
for (; FileNameIt != FileNames.end(); ++FileNameIt) {
754+
Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),
755+
ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,
756+
ELF::SHN_ABS, true);
757+
++Index;
758+
}
747759

748760
// Write the symbol table entries.
749761
LastLocalSymbolIndex = Index;

llvm/lib/MC/WinCOFFObjectWriter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -852,8 +852,9 @@ static std::time_t getTime() {
852852

853853
// Create .file symbols.
854854
void WinCOFFObjectWriter::createFileSymbols(MCAssembler &Asm) {
855-
for (const std::string &Name : Asm.getFileNames()) {
855+
for (const std::pair<std::string, size_t> &It : Asm.getFileNames()) {
856856
// round up to calculate the number of auxiliary symbols required
857+
const std::string &Name = It.first;
857858
unsigned SymbolSize = UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size;
858859
unsigned Count = (Name.size() + SymbolSize - 1) / SymbolSize;
859860

llvm/test/MC/ELF/file.s

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
# CHECK: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
44
# CHECK-NEXT: 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS foo.c
5-
# CHECK-NEXT: 2: 0000000000000000 0 FILE LOCAL DEFAULT ABS bar.c
6-
# CHECK-NEXT: 3: 0000000000000000 0 SECTION LOCAL DEFAULT 2 .text
7-
# CHECK-NEXT: 4: 0000000000000000 0 SECTION LOCAL DEFAULT 4 foo
8-
# CHECK-NEXT: 5: 0000000000000000 0 NOTYPE LOCAL DEFAULT 4 local0
5+
# CHECK-NEXT: 2: 0000000000000000 0 SECTION LOCAL DEFAULT 2 .text
6+
# CHECK-NEXT: 3: 0000000000000000 0 SECTION LOCAL DEFAULT 4 foo
7+
# CHECK-NEXT: 4: 0000000000000000 0 NOTYPE LOCAL DEFAULT 4 local0
8+
# CHECK-NEXT: 5: 0000000000000000 0 FILE LOCAL DEFAULT ABS bar.c
99
# CHECK-NEXT: 6: 0000000000000000 0 SECTION LOCAL DEFAULT 6 bar0
1010
# CHECK-NEXT: 7: 0000000000000000 0 NOTYPE LOCAL DEFAULT 6 local1
1111
# CHECK-NEXT: 8: 0000000000000000 0 SECTION LOCAL DEFAULT 8 bar1
@@ -23,6 +23,7 @@ foo.c:
2323
local0:
2424
.quad foo
2525

26+
## STT_FILE "bar.c" precedes subsequently defined local symbols.
2627
.file "bar.c"
2728
.section bar0,"a"
2829
.globl bar.c

0 commit comments

Comments
 (0)