Remove IsExplicit. It was always false.
[oota-llvm.git] / lib / MC / ELFObjectWriter.cpp
index b979de9322ce728f9b5942da07f38a5d750ea338..313f2e20085b57984e7e35654d2dd8ed2e3074f0 100644 (file)
@@ -143,6 +143,7 @@ namespace {
     };
 
     SmallPtrSet<const MCSymbol *, 16> UsedInReloc;
+    SmallPtrSet<const MCSymbol *, 16> WeakrefUsedInReloc;
     DenseMap<const MCSymbol *, const MCSymbol *> Renames;
 
     llvm::DenseMap<const MCSectionData*,
@@ -164,6 +165,8 @@ namespace {
 
     bool NeedsGOT;
 
+    bool NeedsSymtabShndx;
+
     ELFObjectWriter *Writer;
 
     raw_ostream &OS;
@@ -180,6 +183,8 @@ namespace {
     unsigned LastLocalSymbolIndex;
     // This holds the .strtab section index.
     unsigned StringTableIndex;
+    // This holds the .symtab section index.
+    unsigned SymbolTableIndex;
 
     unsigned ShstrtabIndex;
 
@@ -187,7 +192,8 @@ namespace {
     ELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _Is64Bit,
                         uint16_t _EMachine, bool _HasRelAddend,
                         Triple::OSType _OSType)
-      : NeedsGOT(false), Writer(_Writer), OS(Writer->getStream()),
+      : NeedsGOT(false), NeedsSymtabShndx(false), Writer(_Writer),
+        OS(Writer->getStream()),
         Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelAddend),
         OSType(_OSType), EMachine(_EMachine) {
     }
@@ -265,14 +271,18 @@ namespace {
 
     void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections);
 
-    void WriteSymbolEntry(MCDataFragment *F, uint64_t name, uint8_t info,
+    void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
+                          uint64_t name, uint8_t info,
                           uint64_t value, uint64_t size,
-                          uint8_t other, uint16_t shndx);
+                          uint8_t other, uint32_t shndx,
+                          bool Reserved);
 
-    void WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD,
+    void WriteSymbol(MCDataFragment *SymtabF,  MCDataFragment *ShndxF,
+                     ELFSymbolData &MSD,
                      const MCAsmLayout &Layout);
 
-    void WriteSymbolTable(MCDataFragment *F, const MCAssembler &Asm,
+    void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *ShndxF,
+                          const MCAssembler &Asm,
                           const MCAsmLayout &Layout,
                           unsigned NumRegularSections);
 
@@ -377,56 +387,82 @@ void ELFObjectWriterImpl::WriteHeader(uint64_t SectionDataSize,
   Write16(Is64Bit ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr));
 
   // e_shnum     = # of section header ents
-  Write16(NumberOfSections);
+  if (NumberOfSections >= ELF::SHN_LORESERVE)
+    Write16(0);
+  else
+    Write16(NumberOfSections);
 
   // e_shstrndx  = Section # of '.shstrtab'
-  Write16(ShstrtabIndex);
+  if (NumberOfSections >= ELF::SHN_LORESERVE)
+    Write16(ELF::SHN_XINDEX);
+  else
+    Write16(ShstrtabIndex);
 }
 
-void ELFObjectWriterImpl::WriteSymbolEntry(MCDataFragment *F, uint64_t name,
+void ELFObjectWriterImpl::WriteSymbolEntry(MCDataFragment *SymtabF,
+                                           MCDataFragment *ShndxF,
+                                           uint64_t name,
                                            uint8_t info, uint64_t value,
                                            uint64_t size, uint8_t other,
-                                           uint16_t shndx) {
+                                           uint32_t shndx,
+                                           bool Reserved) {
+  if (ShndxF) {
+    char buf[4];
+    if (shndx >= ELF::SHN_LORESERVE && !Reserved)
+      String32(buf, shndx);
+    else
+      String32(buf, 0);
+    ShndxF->getContents() += StringRef(buf, 4);
+  }
+
   if (Is64Bit) {
     char buf[8];
 
     String32(buf, name);
-    F->getContents() += StringRef(buf, 4); // st_name
+    SymtabF->getContents() += StringRef(buf, 4); // st_name
 
     String8(buf, info);
-    F->getContents() += StringRef(buf, 1);  // st_info
+    SymtabF->getContents() += StringRef(buf, 1);  // st_info
 
     String8(buf, other);
-    F->getContents() += StringRef(buf, 1); // st_other
+    SymtabF->getContents() += StringRef(buf, 1); // st_other
+
+    if (shndx >= ELF::SHN_LORESERVE && !Reserved)
+      String16(buf, ELF::SHN_XINDEX);
+    else
+      String16(buf, shndx);
 
-    String16(buf, shndx);
-    F->getContents() += StringRef(buf, 2); // st_shndx
+    SymtabF->getContents() += StringRef(buf, 2); // st_shndx
 
     String64(buf, value);
-    F->getContents() += StringRef(buf, 8); // st_value
+    SymtabF->getContents() += StringRef(buf, 8); // st_value
 
     String64(buf, size);
-    F->getContents() += StringRef(buf, 8);  // st_size
+    SymtabF->getContents() += StringRef(buf, 8);  // st_size
   } else {
     char buf[4];
 
     String32(buf, name);
-    F->getContents() += StringRef(buf, 4);  // st_name
+    SymtabF->getContents() += StringRef(buf, 4);  // st_name
 
     String32(buf, value);
-    F->getContents() += StringRef(buf, 4); // st_value
+    SymtabF->getContents() += StringRef(buf, 4); // st_value
 
     String32(buf, size);
-    F->getContents() += StringRef(buf, 4);  // st_size
+    SymtabF->getContents() += StringRef(buf, 4);  // st_size
 
     String8(buf, info);
-    F->getContents() += StringRef(buf, 1);  // st_info
+    SymtabF->getContents() += StringRef(buf, 1);  // st_info
 
     String8(buf, other);
-    F->getContents() += StringRef(buf, 1); // st_other
+    SymtabF->getContents() += StringRef(buf, 1); // st_other
 
-    String16(buf, shndx);
-    F->getContents() += StringRef(buf, 2); // st_shndx
+    if (shndx >= ELF::SHN_LORESERVE && !Reserved)
+      String16(buf, ELF::SHN_XINDEX);
+    else
+      String16(buf, shndx);
+
+    SymtabF->getContents() += StringRef(buf, 2); // st_shndx
   }
 }
 
@@ -438,10 +474,9 @@ static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout) {
   if (!Symbol.isInSection())
     return 0;
 
-  if (!Data.isCommon() && !(Data.getFlags() & ELF_STB_Weak))
-    if (MCFragment *FF = Data.getFragment())
-      return Layout.getSymbolAddress(&Data) -
-             Layout.getSectionAddress(FF->getParent());
+  if (MCFragment *FF = Data.getFragment())
+    return Layout.getSymbolAddress(&Data) -
+      Layout.getSectionAddress(FF->getParent());
 
   return 0;
 }
@@ -465,14 +500,32 @@ void ELFObjectWriterImpl::ExecutePostLayoutBinding(MCAssembler &Asm) {
   for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
          ie = Asm.symbol_end(); it != ie; ++it) {
     const MCSymbol &Alias = it->getSymbol();
-    if (!Alias.isVariable())
-      continue;
     const MCSymbol &Symbol = AliasedSymbol(Alias);
+    MCSymbolData &SD = Asm.getSymbolData(Symbol);
+
+    // Undefined symbols are global, but this is the first place we
+    // are able to set it.
+    if (Symbol.isUndefined() && !Symbol.isVariable()) {
+      if (GetBinding(SD) == ELF::STB_LOCAL) {
+        SetBinding(SD, ELF::STB_GLOBAL);
+        SetBinding(*it, ELF::STB_GLOBAL);
+      }
+    }
+
+    // Not an alias.
+    if (&Symbol == &Alias)
+      continue;
+
     StringRef AliasName = Alias.getName();
     size_t Pos = AliasName.find('@');
     if (Pos == StringRef::npos)
       continue;
 
+    // Aliases defined with .symvar copy the binding from the symbol they alias.
+    // This is the first place we are able to copy this information.
+    it->setExternal(SD.isExternal());
+    SetBinding(*it, GetBinding(SD));
+
     StringRef Rest = AliasName.substr(Pos);
     if (!Symbol.isUndefined() && !Rest.startswith("@@@"))
       continue;
@@ -486,12 +539,17 @@ void ELFObjectWriterImpl::ExecutePostLayoutBinding(MCAssembler &Asm) {
   }
 }
 
-void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD,
+void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *SymtabF,
+                                      MCDataFragment *ShndxF,
+                                      ELFSymbolData &MSD,
                                       const MCAsmLayout &Layout) {
   MCSymbolData &OrigData = *MSD.SymbolData;
   MCSymbolData &Data =
     Layout.getAssembler().getSymbolData(AliasedSymbol(OrigData.getSymbol()));
 
+  bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() ||
+    Data.getSymbol().isVariable();
+
   uint8_t Binding = GetBinding(OrigData);
   uint8_t Visibility = GetVisibility(OrigData);
   uint8_t Type = GetType(Data);
@@ -524,11 +582,12 @@ void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD,
   }
 
   // Write out the symbol table entry
-  WriteSymbolEntry(F, MSD.StringIndex, Info, Value,
-                   Size, Other, MSD.SectionIndex);
+  WriteSymbolEntry(SymtabF, ShndxF, MSD.StringIndex, Info, Value,
+                   Size, Other, MSD.SectionIndex, IsReserved);
 }
 
-void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
+void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *SymtabF,
+                                           MCDataFragment *ShndxF,
                                            const MCAssembler &Asm,
                                            const MCAsmLayout &Layout,
                                            unsigned NumRegularSections) {
@@ -539,14 +598,13 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
   // FIXME: Make sure the start of the symbol table is aligned.
 
   // The first entry is the undefined symbol entry.
-  unsigned EntrySize = Is64Bit ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
-  F->getContents().append(EntrySize, '\x00');
+  WriteSymbolEntry(SymtabF, ShndxF, 0, 0, 0, 0, 0, 0, false);
 
   // Write the symbol table entries.
   LastLocalSymbolIndex = LocalSymbolData.size() + 1;
   for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) {
     ELFSymbolData &MSD = LocalSymbolData[i];
-    WriteSymbol(F, MSD, Layout);
+    WriteSymbol(SymtabF, ShndxF, MSD, Layout);
   }
 
   // Write out a symbol table entry for each regular section.
@@ -559,7 +617,8 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
     // the relocations messed up
     if (Section.getType() == ELF::SHT_RELA || Section.getType() == ELF::SHT_REL)
       continue;
-    WriteSymbolEntry(F, 0, ELF::STT_SECTION, 0, 0, ELF::STV_DEFAULT, Index);
+    WriteSymbolEntry(SymtabF, ShndxF, 0, ELF::STT_SECTION, 0, 0,
+                     ELF::STV_DEFAULT, Index, false);
     LastLocalSymbolIndex++;
   }
 
@@ -569,7 +628,7 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
     assert(((Data.getFlags() & ELF_STB_Global) ||
             (Data.getFlags() & ELF_STB_Weak)) &&
            "External symbol requires STB_GLOBAL or STB_WEAK flag");
-    WriteSymbol(F, MSD, Layout);
+    WriteSymbol(SymtabF, ShndxF, MSD, Layout);
     if (GetBinding(Data) == ELF::STB_LOCAL)
       LastLocalSymbolIndex++;
   }
@@ -577,7 +636,7 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
   for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) {
     ELFSymbolData &MSD = UndefinedSymbolData[i];
     MCSymbolData &Data = *MSD.SymbolData;
-    WriteSymbol(F, MSD, Layout);
+    WriteSymbol(SymtabF, ShndxF, MSD, Layout);
     if (GetBinding(Data) == ELF::STB_LOCAL)
       LastLocalSymbolIndex++;
   }
@@ -626,13 +685,14 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
   int Index = 0;
   int64_t Value = Target.getConstant();
   const MCSymbol *Symbol = 0;
+  const MCSymbol *Renamed = 0;
 
   bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
   if (!Target.isAbsolute()) {
     Symbol = &AliasedSymbol(Target.getSymA()->getSymbol());
-    const MCSymbol *Renamed = Renames.lookup(Symbol);
-    if (Renamed)
-      Symbol = Renamed;
+    Renamed = Renames.lookup(Symbol);
+    if (!Renamed)
+      Renamed = &Target.getSymA()->getSymbol();
     MCSymbolData &SD = Asm.getSymbolData(*Symbol);
     MCFragment *F = SD.getFragment();
 
@@ -667,7 +727,11 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
       // Offset of the symbol in the section
       Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD);
     } else {
-      UsedInReloc.insert(Symbol);
+      UsedInReloc.insert(Renamed);
+      MCSymbolData &RenamedSD = Asm.getSymbolData(*Renamed);
+      if (RenamedSD.getFlags() & ELF_Other_Weakref) {
+        WeakrefUsedInReloc.insert(Symbol);
+      }
       Index = -1;
     }
     Addend = Value;
@@ -815,7 +879,7 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
 
   ERE.Index = Index;
   ERE.Type = Type;
-  ERE.Symbol = Symbol;
+  ERE.Symbol = Renamed;
 
   ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
 
@@ -842,6 +906,9 @@ ELFObjectWriterImpl::getSymbolIndexInSymbolTable(const MCAssembler &Asm,
 
 static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data,
                        bool Used, bool Renamed) {
+  if (Data.getFlags() & ELF_Other_Weakref)
+    return false;
+
   if (Used)
     return true;
 
@@ -850,8 +917,11 @@ static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data,
 
   const MCSymbol &Symbol = Data.getSymbol();
 
+  if (Symbol.getName() == "_GLOBAL_OFFSET_TABLE_")
+    return true;
+
   const MCSymbol &A = AliasedSymbol(Symbol);
-  if (&A != &Symbol && A.isUndefined())
+  if (!A.isVariable() && A.isUndefined() && !Data.isCommon())
     return false;
 
   if (!Asm.isSymbolLinkerVisible(Symbol) && !Symbol.isUndefined())
@@ -881,6 +951,7 @@ void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
     MCSymbol *Sym = Asm.getContext().GetOrCreateSymbol(Name);
     MCSymbolData &Data = Asm.getOrCreateSymbolData(*Sym);
     Data.setExternal(true);
+    SetBinding(Data, ELF::STB_GLOBAL);
   }
 
   // Build section lookup table.
@@ -900,7 +971,9 @@ void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
          ie = Asm.symbol_end(); it != ie; ++it) {
     const MCSymbol &Symbol = it->getSymbol();
 
-    if (!isInSymtab(Asm, *it, UsedInReloc.count(&Symbol),
+    bool Used = UsedInReloc.count(&Symbol);
+    bool WeakrefUsed = WeakrefUsedInReloc.count(&Symbol);
+    if (!isInSymtab(Asm, *it, Used || WeakrefUsed,
                     Renames.count(&Symbol)))
       continue;
 
@@ -909,6 +982,9 @@ void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
     bool Local = isLocal(*it);
     const MCSymbol &RefSymbol = AliasedSymbol(Symbol);
 
+    if (RefSymbol.isUndefined() && !Used && WeakrefUsed)
+      SetBinding(*it, ELF::STB_WEAK);
+
     if (it->isCommon()) {
       assert(!Local);
       MSD.SectionIndex = ELF::SHN_COMMON;
@@ -916,12 +992,10 @@ void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
       MSD.SectionIndex = ELF::SHN_ABS;
     } else if (RefSymbol.isUndefined()) {
       MSD.SectionIndex = ELF::SHN_UNDEF;
-      // FIXME: Undefined symbols are global, but this is the first place we
-      // are able to set it.
-      if (GetBinding(*it) == ELF::STB_LOCAL)
-        SetBinding(*it, ELF::STB_GLOBAL);
     } else {
       MSD.SectionIndex = SectionIndexMap.lookup(&RefSymbol.getSection());
+      if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
+        NeedsSymtabShndx = true;
       assert(MSD.SectionIndex && "Invalid section index!");
     }
 
@@ -991,7 +1065,7 @@ void ELFObjectWriterImpl::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout,
     RelaSection = Ctx.getELFSection(RelaSectionName, HasRelocationAddend ?
                                     ELF::SHT_RELA : ELF::SHT_REL, 0,
                                     SectionKind::getReadOnly(),
-                                    false, EntrySize);
+                                    EntrySize);
 
     MCSectionData &RelaSD = Asm.getOrCreateSectionData(*RelaSection);
     RelaSD.setAlignment(Is64Bit ? 8 : 4);
@@ -1075,24 +1149,35 @@ void ELFObjectWriterImpl::CreateMetadataSections(MCAssembler &Asm,
   MCContext &Ctx = Asm.getContext();
   MCDataFragment *F;
 
-  const MCSection *SymtabSection;
   unsigned EntrySize = Is64Bit ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
 
   unsigned NumRegularSections = Asm.size();
 
   // We construct .shstrtab, .symtab and .strtab in this order to match gnu as.
-  const MCSection *ShstrtabSection;
-  ShstrtabSection = Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0,
-                                      SectionKind::getReadOnly(), false);
+  const MCSection *ShstrtabSection =
+    Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0,
+                      SectionKind::getReadOnly(), false);
   MCSectionData &ShstrtabSD = Asm.getOrCreateSectionData(*ShstrtabSection);
   ShstrtabSD.setAlignment(1);
   ShstrtabIndex = Asm.size();
 
-  SymtabSection = Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0,
-                                    SectionKind::getReadOnly(),
-                                    false, EntrySize);
+  const MCSection *SymtabSection =
+    Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0,
+                      SectionKind::getReadOnly(),
+                      EntrySize);
   MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection);
   SymtabSD.setAlignment(Is64Bit ? 8 : 4);
+  SymbolTableIndex = Asm.size();
+
+  MCSectionData *SymtabShndxSD = NULL;
+
+  if (NeedsSymtabShndx) {
+    const MCSection *SymtabShndxSection =
+      Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0,
+                        SectionKind::getReadOnly(), 4);
+    SymtabShndxSD = &Asm.getOrCreateSectionData(*SymtabShndxSection);
+    SymtabShndxSD->setAlignment(4);
+  }
 
   const MCSection *StrtabSection;
   StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0,
@@ -1105,7 +1190,12 @@ void ELFObjectWriterImpl::CreateMetadataSections(MCAssembler &Asm,
 
   // Symbol table
   F = new MCDataFragment(&SymtabSD);
-  WriteSymbolTable(F, Asm, Layout, NumRegularSections);
+  MCDataFragment *ShndxF = NULL;
+  if (NeedsSymtabShndx) {
+    ShndxF = new MCDataFragment(SymtabShndxSD);
+    Asm.AddSectionToTheEnd(*Writer, *SymtabShndxSD, Layout);
+  }
+  WriteSymbolTable(F, ShndxF, Asm, Layout, NumRegularSections);
   Asm.AddSectionToTheEnd(*Writer, SymtabSD, Layout);
 
   F = new MCDataFragment(&StrtabSD);
@@ -1237,7 +1327,11 @@ void ELFObjectWriterImpl::WriteObject(MCAssembler &Asm,
   // Should we align the section header table?
   //
   // Null section first.
-  WriteSecHdrEntry(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+  uint64_t FirstSectionSize =
+    NumSections >= ELF::SHN_LORESERVE ? NumSections : 0;
+  uint32_t FirstSectionLink =
+    ShstrtabIndex >= ELF::SHN_LORESERVE ? ShstrtabIndex : 0;
+  WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, FirstSectionLink, 0, 0, 0);
 
   for (MCAssembler::const_iterator it = Asm.begin(),
          ie = Asm.end(); it != ie; ++it) {
@@ -1282,6 +1376,10 @@ void ELFObjectWriterImpl::WriteObject(MCAssembler &Asm,
       sh_info = LastLocalSymbolIndex;
       break;
 
+    case ELF::SHT_SYMTAB_SHNDX:
+      sh_link = SymbolTableIndex;
+      break;
+
     case ELF::SHT_PROGBITS:
     case ELF::SHT_STRTAB:
     case ELF::SHT_NOBITS: