On ELF we need to know which symbols are used in relocations to decide if
they should be in the symbol table or not. Instead of "guessing", just compute
the symbol table after the relocations are known.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115619 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index 6a2a6e5..b9d2ace 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/MC/ELFObjectWriter.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/Twine.h"
@@ -102,7 +103,9 @@
     struct ELFRelocationEntry {
       // Make these big enough for both 32-bit and 64-bit
       uint64_t r_offset;
-      uint64_t r_info;
+      int Index;
+      unsigned Type;
+      const MCSymbol *Symbol;
       uint64_t r_addend;
 
       // Support lexicographic sorting.
@@ -111,6 +114,8 @@
       }
     };
 
+    SmallPtrSet<const MCSymbol *, 16> UsedInReloc;
+
     llvm::DenseMap<const MCSectionData*,
                    std::vector<ELFRelocationEntry> > Relocations;
     DenseMap<const MCSection*, uint64_t> SectionStringTableIndex;
@@ -126,6 +131,8 @@
 
     /// @}
 
+    int NumRegularSections;
+
     ELFObjectWriter *Writer;
 
     raw_ostream &OS;
@@ -262,8 +269,6 @@
     void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout);
 
     void ExecutePostLayoutBinding(MCAssembler &Asm) {
-      // Compute symbol table information.
-      ComputeSymbolTable(Asm);
     }
 
     void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
@@ -279,7 +284,7 @@
                               bool IsPCRel,
                               const MCFragment *DF) const;
 
-    void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout);
+    void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
   };
 
 }
@@ -526,12 +531,13 @@
                                            MCValue Target,
                                            uint64_t &FixedValue) {
   int64_t Addend = 0;
-  unsigned Index = 0;
+  int Index = 0;
   int64_t Value = Target.getConstant();
+  const MCSymbol *Symbol = 0;
 
   bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
   if (!Target.isAbsolute()) {
-    const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
+    Symbol = &Target.getSymA()->getSymbol();
     MCSymbolData &SD = Asm.getSymbolData(*Symbol);
     MCFragment *F = SD.getFragment();
 
@@ -560,13 +566,15 @@
 
     bool RelocOnSymbol = ShouldRelocOnSymbol(SD, Target);
     if (!RelocOnSymbol) {
-      Index = F->getParent()->getOrdinal() + LocalSymbolData.size() + 1;
+      Index = F->getParent()->getOrdinal();
 
       MCSectionData *FSD = F->getParent();
       // Offset of the symbol in the section
       Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
-    } else
-      Index = getSymbolIndexInSymbolTable(Asm, Symbol);
+    } else {
+      UsedInReloc.insert(Symbol);
+      Index = -1;
+    }
     Addend = Value;
     // Compensate for the addend on i386.
     if (Is64Bit)
@@ -641,15 +649,9 @@
 
   ELFRelocationEntry ERE;
 
-  if (Is64Bit) {
-    struct ELF::Elf64_Rela ERE64;
-    ERE64.setSymbolAndType(Index, Type);
-    ERE.r_info = ERE64.r_info;
-  } else {
-    struct ELF::Elf32_Rela ERE32;
-    ERE32.setSymbolAndType(Index, Type);
-    ERE.r_info = ERE32.r_info;
-  }
+  ERE.Index = Index;
+  ERE.Type = Type;
+  ERE.Symbol = Symbol;
 
   ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
 
@@ -671,11 +673,12 @@
     return SD.getIndex() + /* empty symbol */ 1;
 
   // External or undefined symbol.
-  return SD.getIndex() + Asm.size() + /* empty symbol */ 1;
+  return SD.getIndex() + NumRegularSections + /* empty symbol */ 1;
 }
 
 void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
   // Build section lookup table.
+  NumRegularSections = Asm.size();
   DenseMap<const MCSection*, uint8_t> SectionIndexMap;
   unsigned Index = 1;
   for (MCAssembler::iterator it = Asm.begin(),
@@ -698,6 +701,9 @@
     if (it->isExternal() || Symbol.isUndefined())
       continue;
 
+    if (Symbol.isTemporary() && !UsedInReloc.count(&Symbol))
+      continue;
+
     uint64_t &Entry = StringIndexMap[Symbol.getName()];
     if (!Entry) {
       Entry = StringTable.size();
@@ -734,6 +740,10 @@
     if (Symbol.isVariable())
       continue;
 
+    if (Symbol.isUndefined() && !UsedInReloc.count(&Symbol)
+        && Symbol.isTemporary())
+      continue;
+
     uint64_t &Entry = StringIndexMap[Symbol.getName()];
     if (!Entry) {
       Entry = StringTable.size();
@@ -843,13 +853,19 @@
   for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
     ELFRelocationEntry entry = Relocs[e - i - 1];
 
+    if (entry.Index < 0)
+      entry.Index = getSymbolIndexInSymbolTable(Asm, entry.Symbol);
+    else
+      entry.Index += LocalSymbolData.size() + 1;
     if (Is64Bit) {
       char buf[8];
 
       String64(buf, entry.r_offset);
       F->getContents() += StringRef(buf, 8);
 
-      String64(buf, entry.r_info);
+      struct ELF::Elf64_Rela ERE64;
+      ERE64.setSymbolAndType(entry.Index, entry.Type);
+      String64(buf, ERE64.r_info);
       F->getContents() += StringRef(buf, 8);
 
       if (HasRelocationAddend) {
@@ -862,7 +878,9 @@
       String32(buf, entry.r_offset);
       F->getContents() += StringRef(buf, 4);
 
-      String32(buf, entry.r_info);
+      struct ELF::Elf32_Rela ERE32;
+      ERE32.setSymbolAndType(entry.Index, entry.Type);
+      String32(buf, ERE32.r_info);
       F->getContents() += StringRef(buf, 4);
 
       if (HasRelocationAddend) {
@@ -976,8 +994,11 @@
   return !SectionB && BaseSection == SectionA;
 }
 
-void ELFObjectWriterImpl::WriteObject(const MCAssembler &Asm,
+void ELFObjectWriterImpl::WriteObject(MCAssembler &Asm,
                                       const MCAsmLayout &Layout) {
+  // Compute symbol table information.
+  ComputeSymbolTable(Asm);
+
   CreateMetadataSections(const_cast<MCAssembler&>(Asm),
                          const_cast<MCAsmLayout&>(Layout));
 
@@ -1142,7 +1163,7 @@
                                                              IsPCRel, DF);
 }
 
-void ELFObjectWriter::WriteObject(const MCAssembler &Asm,
+void ELFObjectWriter::WriteObject(MCAssembler &Asm,
                                   const MCAsmLayout &Layout) {
   ((ELFObjectWriterImpl*) Impl)->WriteObject(Asm, Layout);
 }