[llvm] 0929464 - ELFObjectWriter: Make STT_FILE precede associated local symbols

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 7 17:51:51 PST 2021


Author: Fangrui Song
Date: 2021-02-07T17:51:40-08:00
New Revision: 09294642bea177a45c2431b7f77781f3f898f30e

URL: https://github.com/llvm/llvm-project/commit/09294642bea177a45c2431b7f77781f3f898f30e
DIFF: https://github.com/llvm/llvm-project/commit/09294642bea177a45c2431b7f77781f3f898f30e.diff

LOG: ELFObjectWriter: Make STT_FILE precede associated local symbols

Added: 
    

Modified: 
    llvm/include/llvm/MC/MCAssembler.h
    llvm/lib/MC/ELFObjectWriter.cpp
    llvm/lib/MC/WinCOFFObjectWriter.cpp
    llvm/test/MC/ELF/file.s

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h
index 1b76559d33b3..cbda472d0bb5 100644
--- a/llvm/include/llvm/MC/MCAssembler.h
+++ b/llvm/include/llvm/MC/MCAssembler.h
@@ -119,7 +119,7 @@ class MCAssembler {
   std::vector<std::vector<std::string>> LinkerOptions;
 
   /// List of declared file names
-  std::vector<std::string> FileNames;
+  std::vector<std::pair<std::string, size_t>> FileNames;
 
   MCDwarfLineTableParams LTParams;
 
@@ -445,11 +445,15 @@ class MCAssembler {
 
   void registerSymbol(const MCSymbol &Symbol, bool *Created = nullptr);
 
-  ArrayRef<std::string> getFileNames() { return FileNames; }
+  MutableArrayRef<std::pair<std::string, size_t>> getFileNames() {
+    return FileNames;
+  }
 
   void addFileName(StringRef FileName) {
-    if (!is_contained(FileNames, FileName))
-      FileNames.push_back(std::string(FileName));
+    for (const std::pair<std::string, size_t> &F : FileNames)
+      if (F.first == FileName)
+        return;
+    FileNames.emplace_back(std::string(FileName), Symbols.size());
   }
 
   /// Write the necessary bundle padding to \p OS.

diff  --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index 74eb7b64c8a4..a21194f52da5 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -116,8 +116,9 @@ struct ELFWriter {
   /// Helper struct for containing some precomputed information on symbols.
   struct ELFSymbolData {
     const MCSymbolELF *Symbol;
-    uint32_t SectionIndex;
     StringRef Name;
+    uint32_t SectionIndex;
+    uint32_t Order;
 
     // Support lexicographic sorting.
     bool operator<(const ELFSymbolData &RHS) const {
@@ -626,11 +627,15 @@ void ELFWriter::computeSymbolTable(
 
   std::vector<ELFSymbolData> LocalSymbolData;
   std::vector<ELFSymbolData> ExternalSymbolData;
+  MutableArrayRef<std::pair<std::string, size_t>> FileNames =
+      Asm.getFileNames();
+  for (const std::pair<std::string, size_t> &F : FileNames)
+    StrTabBuilder.add(F.first);
 
   // Add the data for the symbols.
   bool HasLargeSectionIndex = false;
-  for (const MCSymbol &S : Asm.symbols()) {
-    const auto &Symbol = cast<MCSymbolELF>(S);
+  for (auto It : llvm::enumerate(Asm.symbols())) {
+    const auto &Symbol = cast<MCSymbolELF>(It.value());
     bool Used = Symbol.isUsedInReloc();
     bool WeakrefUsed = Symbol.isWeakrefUsedInReloc();
     bool isSignature = Symbol.isSignature();
@@ -646,6 +651,7 @@ void ELFWriter::computeSymbolTable(
 
     ELFSymbolData MSD;
     MSD.Symbol = cast<MCSymbolELF>(&Symbol);
+    MSD.Order = It.index();
 
     bool Local = Symbol.getBinding() == ELF::STB_LOCAL;
     assert(Local || !Symbol.isTemporary());
@@ -716,34 +722,40 @@ void ELFWriter::computeSymbolTable(
     SymtabShndxSection->setAlignment(Align(4));
   }
 
-  ArrayRef<std::string> FileNames = Asm.getFileNames();
-  for (const std::string &Name : FileNames)
-    StrTabBuilder.add(Name);
-
   StrTabBuilder.finalize();
 
-  // File symbols are emitted first and handled separately from normal symbols,
-  // i.e. a non-STT_FILE symbol with the same name may appear.
-  for (const std::string &Name : FileNames)
-    Writer.writeSymbol(StrTabBuilder.getOffset(Name),
-                       ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,
-                       ELF::SHN_ABS, true);
-
   // Symbols are required to be in lexicographic order.
   //array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end());
   array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
 
-  // Set the symbol indices. Local symbols must come before all other
-  // symbols with non-local bindings.
-  unsigned Index = FileNames.size() + 1;
+  // Make the first STT_FILE precede previous local symbols.
+  unsigned Index = 1;
+  auto FileNameIt = FileNames.begin();
+  if (!FileNames.empty())
+    FileNames[0].second = 0;
 
   for (ELFSymbolData &MSD : LocalSymbolData) {
+    // Emit STT_FILE symbols before their associated local symbols.
+    for (; FileNameIt != FileNames.end() && FileNameIt->second <= MSD.Order;
+         ++FileNameIt) {
+      Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),
+                         ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,
+                         ELF::SHN_ABS, true);
+      ++Index;
+    }
+
     unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION
                                ? 0
                                : StrTabBuilder.getOffset(MSD.Name);
     MSD.Symbol->setIndex(Index++);
     writeSymbol(Writer, StringIndex, MSD, Layout);
   }
+  for (; FileNameIt != FileNames.end(); ++FileNameIt) {
+    Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),
+                       ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,
+                       ELF::SHN_ABS, true);
+    ++Index;
+  }
 
   // Write the symbol table entries.
   LastLocalSymbolIndex = Index;

diff  --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp
index 901d2c06e716..2a69a30a86c7 100644
--- a/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -852,8 +852,9 @@ static std::time_t getTime() {
 
 // Create .file symbols.
 void WinCOFFObjectWriter::createFileSymbols(MCAssembler &Asm) {
-  for (const std::string &Name : Asm.getFileNames()) {
+  for (const std::pair<std::string, size_t> &It : Asm.getFileNames()) {
     // round up to calculate the number of auxiliary symbols required
+    const std::string &Name = It.first;
     unsigned SymbolSize = UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size;
     unsigned Count = (Name.size() + SymbolSize - 1) / SymbolSize;
 

diff  --git a/llvm/test/MC/ELF/file.s b/llvm/test/MC/ELF/file.s
index 6c8185b05577..9ede62948cfb 100644
--- a/llvm/test/MC/ELF/file.s
+++ b/llvm/test/MC/ELF/file.s
@@ -2,10 +2,10 @@
 
 # CHECK:       0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT   UND
 # CHECK-NEXT:  1: 0000000000000000     0 FILE    LOCAL  DEFAULT   ABS foo.c
-# CHECK-NEXT:  2: 0000000000000000     0 FILE    LOCAL  DEFAULT   ABS bar.c
-# CHECK-NEXT:  3: 0000000000000000     0 SECTION LOCAL  DEFAULT     2 .text
-# CHECK-NEXT:  4: 0000000000000000     0 SECTION LOCAL  DEFAULT     4 foo
-# CHECK-NEXT:  5: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT     4 local0
+# CHECK-NEXT:  2: 0000000000000000     0 SECTION LOCAL  DEFAULT     2 .text
+# CHECK-NEXT:  3: 0000000000000000     0 SECTION LOCAL  DEFAULT     4 foo
+# CHECK-NEXT:  4: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT     4 local0
+# CHECK-NEXT:  5: 0000000000000000     0 FILE    LOCAL  DEFAULT   ABS bar.c
 # CHECK-NEXT:  6: 0000000000000000     0 SECTION LOCAL  DEFAULT     6 bar0
 # CHECK-NEXT:  7: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT     6 local1
 # CHECK-NEXT:  8: 0000000000000000     0 SECTION LOCAL  DEFAULT     8 bar1
@@ -23,6 +23,7 @@ foo.c:
 local0:
 .quad foo
 
+## STT_FILE "bar.c" precedes subsequently defined local symbols.
 .file "bar.c"
 .section bar0,"a"
 .globl bar.c


        


More information about the llvm-commits mailing list