<div dir="ltr">Nice change. Thank you for doing this.<div class="gmail_extra"><br><div class="gmail_quote">On Mon, Apr 4, 2016 at 7:04 AM, Rafael Espindola via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rafael<br>
Date: Mon Apr  4 09:04:16 2016<br>
New Revision: 265293<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=265293&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=265293&view=rev</a><br>
Log:<br>
Don't store an Elf_Sym for most symbols.<br>
<br>
Our symbol representation was redundant, and some times would get out of<br>
sync. It had an Elf_Sym, but some fields were copied to SymbolBody.<br>
<br>
Different parts of the code were checking the bits in SymbolBody and<br>
others were checking Elf_Sym.<br>
<br>
There are two general approaches to fix this:<br>
* Copy the required information and don't store and Elf_Sym.<br>
* Don't copy the information and always use the Elf_Smy.<br>
<br>
The second way sounds tempting, but has a big problem: we would have to<br>
template SymbolBody. I started doing it, but it requires templeting<br>
*everything* and creates a bit chicken and egg problem at the driver<br>
where we have to find ELFT before we can create an ArchiveFile for<br>
example.<br>
<br>
As much as possible I compared the test differences with what gold and<br>
bfd produce to make sure they are still valid. In most cases we are just<br>
adding hidden visibility to a local symbol, which is harmless.<br>
<br>
In most tests this is a small speedup. The only slowdown was scylla<br>
(1.006X). The largest speedup was clang with no --build-id, -O3 or<br>
--gc-sections (i.e.: focus on the relocations): 1.019X.<br>
<br>
Modified:<br>
    lld/trunk/ELF/Driver.cpp<br>
    lld/trunk/ELF/ICF.cpp<br>
    lld/trunk/ELF/InputFiles.cpp<br>
    lld/trunk/ELF/InputFiles.h<br>
    lld/trunk/ELF/InputSection.cpp<br>
    lld/trunk/ELF/InputSection.h<br>
    lld/trunk/ELF/MarkLive.cpp<br>
    lld/trunk/ELF/OutputSections.cpp<br>
    lld/trunk/ELF/SymbolTable.cpp<br>
    lld/trunk/ELF/SymbolTable.h<br>
    lld/trunk/ELF/Symbols.cpp<br>
    lld/trunk/ELF/Symbols.h<br>
    lld/trunk/ELF/Target.cpp<br>
    lld/trunk/ELF/Writer.cpp<br>
    lld/trunk/test/ELF/aarch64-gnu-ifunc.s<br>
    lld/trunk/test/ELF/basic-mips.s<br>
    lld/trunk/test/ELF/global_offset_table_shared.s<br>
    lld/trunk/test/ELF/gnu-ifunc-i386.s<br>
    lld/trunk/test/ELF/gnu-ifunc.s<br>
    lld/trunk/test/ELF/mips-gp-disp.s<br>
    lld/trunk/test/ELF/mips-hilo-gp-disp.s<br>
<br>
Modified: lld/trunk/ELF/Driver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Driver.cpp (original)<br>
+++ lld/trunk/ELF/Driver.cpp Mon Apr  4 09:04:16 2016<br>
@@ -366,17 +366,7 @@ void LinkerDriver::createFiles(opt::Inpu<br>
     error("no input files.");<br>
 }<br>
<br>
-template <class ELFT> static void initSymbols() {<br>
-  ElfSym<ELFT>::Etext.setBinding(STB_GLOBAL);<br>
-  ElfSym<ELFT>::Edata.setBinding(STB_GLOBAL);<br>
-  ElfSym<ELFT>::End.setBinding(STB_GLOBAL);<br>
-  ElfSym<ELFT>::Ignored.setBinding(STB_WEAK);<br>
-  ElfSym<ELFT>::Ignored.setVisibility(STV_HIDDEN);<br>
-}<br>
-<br>
 template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {<br>
-  initSymbols<ELFT>();<br>
-<br>
   SymbolTable<ELFT> Symtab;<br>
   std::unique_ptr<TargetInfo> TI(createTarget());<br>
   Target = TI.get();<br>
@@ -390,21 +380,6 @@ template <class ELFT> void LinkerDriver:<br>
       Config->EMachine != EM_AMDGPU)<br>
     Config->Entry = Config->EMachine == EM_MIPS ? "__start" : "_start";<br>
<br>
-  // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol<br>
-  // is magical and is used to produce a R_386_GOTPC relocation.<br>
-  // The R_386_GOTPC relocation value doesn't actually depend on the<br>
-  // symbol value, so it could use an index of STN_UNDEF which, according<br>
-  // to the spec, means the symbol value is 0.<br>
-  // Unfortunately both gas and MC keep the _GLOBAL_OFFSET_TABLE_ symbol in<br>
-  // the object file.<br>
-  // The situation is even stranger on x86_64 where the assembly doesn't<br>
-  // need the magical symbol, but gas still puts _GLOBAL_OFFSET_TABLE_ as<br>
-  // an undefined symbol in the .o files.<br>
-  // Given that the symbol is effectively unused, we just create a dummy<br>
-  // hidden one to avoid the undefined symbol error.<br>
-  if (!Config->Relocatable)<br>
-    Symtab.addIgnored("_GLOBAL_OFFSET_TABLE_");<br>
-<br>
   if (!Config->Entry.empty()) {<br>
     // Set either EntryAddr (if S is a number) or EntrySym (otherwise).<br>
     StringRef S = Config->Entry;<br>
@@ -413,20 +388,11 @@ template <class ELFT> void LinkerDriver:<br>
   }<br>
<br>
   if (Config->EMachine == EM_MIPS) {<br>
-    // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between<br>
-    // start of function and 'gp' pointer into GOT.<br>
-    Config->MipsGpDisp = Symtab.addIgnored("_gp_disp");<br>
-    // The __gnu_local_gp is a magic symbol equal to the current value of 'gp'<br>
-    // pointer. This symbol is used in the code generated by .cpload pseudo-op<br>
-    // in case of using -mno-shared option.<br>
-    // <a href="https://sourceware.org/ml/binutils/2004-12/msg00094.html" rel="noreferrer" target="_blank">https://sourceware.org/ml/binutils/2004-12/msg00094.html</a><br>
-    Config->MipsLocalGp = Symtab.addIgnored("__gnu_local_gp");<br>
-<br>
     // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer<br>
     // so that it points to an absolute address which is relative to GOT.<br>
     // See "Global Data Symbols" in Chapter 6 in the following document:<br>
     // <a href="ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf" rel="noreferrer" target="_blank">ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf</a><br>
-    Symtab.addAbsolute("_gp", ElfSym<ELFT>::MipsGp);<br>
+    ElfSym<ELFT>::MipsGp = Symtab.addAbsolute("_gp", STV_DEFAULT);<br>
   }<br>
<br>
   for (std::unique_ptr<InputFile> &F : Files)<br>
<br>
Modified: lld/trunk/ELF/ICF.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ICF.cpp?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ICF.cpp?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/ICF.cpp (original)<br>
+++ lld/trunk/ELF/ICF.cpp Mon Apr  4 09:04:16 2016<br>
@@ -132,7 +132,7 @@ template <class ELFT> uint64_t ICF<ELFT><br>
<br>
 // Returns true if Sec is subject of ICF.<br>
 template <class ELFT> bool ICF<ELFT>::isEligible(InputSectionBase<ELFT> *Sec) {<br>
-  if (!Sec || Sec == InputSection<ELFT>::Discarded || !Sec->Live)<br>
+  if (!Sec || Sec == &InputSection<ELFT>::Discarded || !Sec->Live)<br>
     return false;<br>
   auto *S = dyn_cast<InputSection<ELFT>>(Sec);<br>
   if (!S)<br>
@@ -270,7 +270,7 @@ bool ICF<ELFT>::variableEq(const InputSe<br>
     auto *DB = dyn_cast<DefinedRegular<ELFT>>(&SB);<br>
     if (!DA || !DB)<br>
       return false;<br>
-    if (DA->Sym.st_value != DB->Sym.st_value)<br>
+    if (DA->Value != DB->Value)<br>
       return false;<br>
     InputSection<ELFT> *X = dyn_cast<InputSection<ELFT>>(DA->Section);<br>
     InputSection<ELFT> *Y = dyn_cast<InputSection<ELFT>>(DB->Section);<br>
<br>
Modified: lld/trunk/ELF/InputFiles.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/InputFiles.cpp (original)<br>
+++ lld/trunk/ELF/InputFiles.cpp Mon Apr  4 09:04:16 2016<br>
@@ -175,18 +175,18 @@ void elf::ObjectFile<ELFT>::initializeSe<br>
   const ELFFile<ELFT> &Obj = this->ELFObj;<br>
   for (const Elf_Shdr &Sec : Obj.sections()) {<br>
     ++I;<br>
-    if (Sections[I] == InputSection<ELFT>::Discarded)<br>
+    if (Sections[I] == &InputSection<ELFT>::Discarded)<br>
       continue;<br>
<br>
     switch (Sec.sh_type) {<br>
     case SHT_GROUP:<br>
-      Sections[I] = InputSection<ELFT>::Discarded;<br>
+      Sections[I] = &InputSection<ELFT>::Discarded;<br>
       if (ComdatGroups.insert(getShtGroupSignature(Sec)).second)<br>
         continue;<br>
       for (uint32_t SecIndex : getShtGroupEntries(Sec)) {<br>
         if (SecIndex >= Size)<br>
           fatal("invalid section index in group");<br>
-        Sections[SecIndex] = InputSection<ELFT>::Discarded;<br>
+        Sections[SecIndex] = &InputSection<ELFT>::Discarded;<br>
       }<br>
       break;<br>
     case SHT_SYMTAB:<br>
@@ -242,7 +242,7 @@ elf::ObjectFile<ELFT>::getRelocTarget(co<br>
   // Strictly speaking, a relocation section must be included in the<br>
   // group of the section it relocates. However, LLVM 3.3 and earlier<br>
   // would fail to do so, so we gracefully handle that case.<br>
-  if (Target == InputSection<ELFT>::Discarded)<br>
+  if (Target == &InputSection<ELFT>::Discarded)<br>
     return nullptr;<br>
<br>
   if (!Target)<br>
@@ -260,7 +260,7 @@ elf::ObjectFile<ELFT>::createInputSectio<br>
   // is controlled only by the command line option (-z execstack) in LLD,<br>
   // .note.GNU-stack is ignored.<br>
   if (Name == ".note.GNU-stack")<br>
-    return InputSection<ELFT>::Discarded;<br>
+    return &InputSection<ELFT>::Discarded;<br>
<br>
   if (Name == ".note.GNU-split-stack")<br>
     error("objects using splitstacks are not supported");<br>
@@ -299,19 +299,20 @@ elf::ObjectFile<ELFT>::getSection(const<br>
   if (Index >= Sections.size() || !Sections[Index])<br>
     fatal("invalid section index");<br>
   InputSectionBase<ELFT> *S = Sections[Index];<br>
-  if (S == InputSectionBase<ELFT>::Discarded)<br>
+  if (S == &InputSectionBase<ELFT>::Discarded)<br>
     return S;<br>
   return S->Repl;<br>
 }<br>
<br>
 template <class ELFT><br>
 SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {<br>
+  uint32_t NameOffset = Sym->st_name;<br>
   unsigned char Binding = Sym->getBinding();<br>
   InputSectionBase<ELFT> *Sec = getSection(*Sym);<br>
   if (Binding == STB_LOCAL) {<br>
-    if (Sec == InputSection<ELFT>::Discarded)<br>
-      Sec = nullptr;<br>
-    return new (Alloc) DefinedRegular<ELFT>("", *Sym, Sec);<br>
+    if (Sym->st_shndx == SHN_UNDEF)<br>
+      return new (Alloc) UndefinedElf<ELFT>(NameOffset, *Sym);<br>
+    return new (Alloc) DefinedRegular<ELFT>(NameOffset, *Sym, Sec);<br>
   }<br>
<br>
   StringRef Name = check(Sym->getName(this->StringTable));<br>
@@ -320,9 +321,8 @@ SymbolBody *elf::ObjectFile<ELFT>::creat<br>
   case SHN_UNDEF:<br>
     return new (Alloc) UndefinedElf<ELFT>(Name, *Sym);<br>
   case SHN_COMMON:<br>
-    return new (Alloc) DefinedCommon(Name, Sym->st_size, Sym->st_value,<br>
-                                     Sym->getBinding() == llvm::ELF::STB_WEAK,<br>
-                                     Sym->getVisibility());<br>
+    return new (Alloc) DefinedCommon(Name, Sym->st_size, Sym->st_value, Binding,<br>
+                                     Sym->st_other, Sym->getType());<br>
   }<br>
<br>
   switch (Binding) {<br>
@@ -331,7 +331,7 @@ SymbolBody *elf::ObjectFile<ELFT>::creat<br>
   case STB_GLOBAL:<br>
   case STB_WEAK:<br>
   case STB_GNU_UNIQUE:<br>
-    if (Sec == InputSection<ELFT>::Discarded)<br>
+    if (Sec == &InputSection<ELFT>::Discarded)<br>
       return new (Alloc) UndefinedElf<ELFT>(Name, *Sym);<br>
     return new (Alloc) DefinedRegular<ELFT>(Name, *Sym, Sec);<br>
   }<br>
@@ -426,6 +426,9 @@ template <class ELFT> void SharedFile<EL<br>
   uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());<br>
   SymbolBodies.reserve(NumSymbols);<br>
   for (const Elf_Sym &Sym : Syms) {<br>
+    // FIXME: We should probably just err if we get a local symbol in here.<br>
+    if (Sym.getBinding() == STB_LOCAL)<br>
+      continue;<br>
     StringRef Name = check(Sym.getName(this->StringTable));<br>
     if (Sym.isUndefined())<br>
       Undefs.push_back(Name);<br>
@@ -479,11 +482,13 @@ BitcodeFile::createSymbolBody(const Dens<br>
     const DataLayout &DL = M.getDataLayout();<br>
     uint64_t Size = DL.getTypeAllocSize(GV->getValueType());<br>
     Body = new (Alloc)<br>
-        DefinedCommon(NameRef, Size, GV->getAlignment(), IsWeak, Visibility);<br>
+        DefinedCommon(NameRef, Size, GV->getAlignment(),<br>
+                      IsWeak ? STB_WEAK : STB_GLOBAL, Visibility, /*Type*/ 0);<br>
   } else {<br>
     Body = new (Alloc) DefinedBitcode(NameRef, IsWeak, Visibility);<br>
   }<br>
-  Body->IsTls = GV->isThreadLocal();<br>
+  if (GV->isThreadLocal())<br>
+    Body->Type = STT_TLS;<br>
   return Body;<br>
 }<br>
<br>
<br>
Modified: lld/trunk/ELF/InputFiles.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/InputFiles.h (original)<br>
+++ lld/trunk/ELF/InputFiles.h Mon Apr  4 09:04:16 2016<br>
@@ -129,7 +129,7 @@ public:<br>
<br>
   // The number is the offset in the string table. It will be used as the<br>
   // st_name of the symbol.<br>
-  std::vector<std::pair<const Elf_Sym *, unsigned>> KeptLocalSyms;<br>
+  std::vector<std::pair<const DefinedRegular<ELFT> *, unsigned>> KeptLocalSyms;<br>
<br>
 private:<br>
   void initializeSections(llvm::DenseSet<StringRef> &ComdatGroups);<br>
<br>
Modified: lld/trunk/ELF/InputSection.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/InputSection.cpp (original)<br>
+++ lld/trunk/ELF/InputSection.cpp Mon Apr  4 09:04:16 2016<br>
@@ -72,8 +72,9 @@ typename ELFT::uint InputSectionBase<ELF<br>
 }<br>
<br>
 template <class ELFT><br>
-typename ELFT::uint InputSectionBase<ELFT>::getOffset(const Elf_Sym &Sym) {<br>
-  return getOffset(Sym.st_value);<br>
+typename ELFT::uint<br>
+InputSectionBase<ELFT>::getOffset(const DefinedRegular<ELFT> &Sym) {<br>
+  return getOffset(Sym.Value);<br>
 }<br>
<br>
 // Returns a section that Rel relocation is pointing to.<br>
@@ -305,7 +306,7 @@ void InputSectionBase<ELFT>::relocate(ui<br>
         SymVA = getMipsGotVA<ELFT>(Body, SymVA, BufLoc);<br>
       else<br>
         SymVA = Body.getGotVA<ELFT>() + A;<br>
-      if (Body.IsTls)<br>
+      if (Body.isTls())<br>
         Type = Target->getTlsGotRel(Type);<br>
     } else if (Target->isSizeRel(Type) && Body.isPreemptible()) {<br>
       // A SIZE relocation is supposed to set a symbol size, but if a symbol<br>
<br>
Modified: lld/trunk/ELF/InputSection.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/InputSection.h (original)<br>
+++ lld/trunk/ELF/InputSection.h Mon Apr  4 09:04:16 2016<br>
@@ -19,6 +19,7 @@ namespace lld {<br>
 namespace elf {<br>
<br>
 template <class ELFT> class ICF;<br>
+template <class ELFT> class DefinedRegular;<br>
 template <class ELFT> class ObjectFile;<br>
 template <class ELFT> class OutputSection;<br>
 template <class ELFT> class OutputSectionBase;<br>
@@ -40,6 +41,8 @@ public:<br>
   enum Kind { Regular, EHFrame, Merge, MipsReginfo };<br>
   Kind SectionKind;<br>
<br>
+  InputSectionBase() : Repl(this) {}<br>
+<br>
   InputSectionBase(ObjectFile<ELFT> *File, const Elf_Shdr *Header,<br>
                    Kind SectionKind);<br>
   OutputSectionBase<ELFT> *OutSec = nullptr;<br>
@@ -58,12 +61,12 @@ public:<br>
   // Returns the size of this section (even if this is a common or BSS.)<br>
   size_t getSize() const;<br>
<br>
-  static InputSectionBase<ELFT> *Discarded;<br>
+  static InputSectionBase<ELFT> Discarded;<br>
<br>
   StringRef getSectionName() const;<br>
   const Elf_Shdr *getSectionHdr() const { return Header; }<br>
   ObjectFile<ELFT> *getFile() const { return File; }<br>
-  uintX_t getOffset(const Elf_Sym &Sym);<br>
+  uintX_t getOffset(const DefinedRegular<ELFT> &Sym);<br>
<br>
   // Translate an offset in the input section to an offset in the output<br>
   // section.<br>
@@ -85,9 +88,7 @@ private:<br>
                                const RelTy *Rel, const RelTy *End);<br>
 };<br>
<br>
-template <class ELFT><br>
-InputSectionBase<ELFT> *<br>
-    InputSectionBase<ELFT>::Discarded = (InputSectionBase<ELFT> *)-1ULL;<br>
+template <class ELFT> InputSectionBase<ELFT> InputSectionBase<ELFT>::Discarded;<br>
<br>
 // Usually sections are copied to the output as atomic chunks of data,<br>
 // but some special types of sections are split into small pieces of data<br>
<br>
Modified: lld/trunk/ELF/MarkLive.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MarkLive.cpp?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MarkLive.cpp?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/MarkLive.cpp (original)<br>
+++ lld/trunk/ELF/MarkLive.cpp Mon Apr  4 09:04:16 2016<br>
@@ -124,7 +124,7 @@ template <class ELFT> void elf::markLive<br>
   // script KEEP command.<br>
   for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab->getObjectFiles())<br>
     for (InputSectionBase<ELFT> *Sec : F->getSections())<br>
-      if (Sec && Sec != InputSection<ELFT>::Discarded)<br>
+      if (Sec && Sec != &InputSection<ELFT>::Discarded)<br>
         if (isReserved(Sec) || Script->shouldKeep<ELFT>(Sec))<br>
           Enqueue(Sec);<br>
<br>
<br>
Modified: lld/trunk/ELF/OutputSections.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/OutputSections.cpp (original)<br>
+++ lld/trunk/ELF/OutputSections.cpp Mon Apr  4 09:04:16 2016<br>
@@ -1426,22 +1426,23 @@ void SymbolTableSection<ELFT>::writeLoca<br>
   // Iterate over all input object files to copy their local symbols<br>
   // to the output symbol table pointed by Buf.<br>
   for (const std::unique_ptr<ObjectFile<ELFT>> &File : Table.getObjectFiles()) {<br>
-    for (const std::pair<const Elf_Sym *, size_t> &P : File->KeptLocalSyms) {<br>
-      const Elf_Sym *Sym = P.first;<br>
-<br>
+    for (const std::pair<const DefinedRegular<ELFT> *, size_t> &P :<br>
+         File->KeptLocalSyms) {<br>
+      const DefinedRegular<ELFT> &Body = *P.first;<br>
+      InputSectionBase<ELFT> *Section = Body.Section;<br>
       auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);<br>
-      if (Sym->st_shndx == SHN_ABS) {<br>
+<br>
+      if (!Section) {<br>
         ESym->st_shndx = SHN_ABS;<br>
-        ESym->st_value = Sym->st_value;<br>
+        ESym->st_value = Body.Value;<br>
       } else {<br>
-        InputSectionBase<ELFT> *Section = File->getSection(*Sym);<br>
         const OutputSectionBase<ELFT> *OutSec = Section->OutSec;<br>
         ESym->st_shndx = OutSec->SectionIndex;<br>
-        ESym->st_value = OutSec->getVA() + Section->getOffset(*Sym);<br>
+        ESym->st_value = OutSec->getVA() + Section->getOffset(Body);<br>
       }<br>
       ESym->st_name = P.second;<br>
-      ESym->st_size = Sym->st_size;<br>
-      ESym->setBindingAndType(Sym->getBinding(), Sym->getType());<br>
+      ESym->st_size = Body.template getSize<ELFT>();<br>
+      ESym->setBindingAndType(Body.Binding, Body.Type);<br>
       Buf += sizeof(*ESym);<br>
     }<br>
   }<br>
@@ -1456,15 +1457,8 @@ void SymbolTableSection<ELFT>::writeGlob<br>
     SymbolBody *Body = P.first;<br>
     size_t StrOff = P.second;<br>
<br>
-    uint8_t Type = STT_NOTYPE;<br>
-    uintX_t Size = 0;<br>
-    if (const Elf_Sym *InputSym = Body->getElfSym<ELFT>()) {<br>
-      Type = InputSym->getType();<br>
-      Size = InputSym->st_size;<br>
-    } else if (auto *C = dyn_cast<DefinedCommon>(Body)) {<br>
-      Type = STT_OBJECT;<br>
-      Size = C->Size;<br>
-    }<br>
+    uint8_t Type = Body->Type;<br>
+    uintX_t Size = Body->getSize<ELFT>();<br>
<br>
     ESym->setBindingAndType(getSymbolBinding(Body), Type);<br>
     ESym->st_size = Size;<br>
@@ -1521,11 +1515,9 @@ uint8_t SymbolTableSection<ELFT>::getSym<br>
   uint8_t Visibility = Body->getVisibility();<br>
   if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)<br>
     return STB_LOCAL;<br>
-  if (const Elf_Sym *ESym = Body->getElfSym<ELFT>())<br>
-    return ESym->getBinding();<br>
   if (isa<DefinedSynthetic<ELFT>>(Body))<br>
     return STB_LOCAL;<br>
-  return Body->isWeak() ? STB_WEAK : STB_GLOBAL;<br>
+  return Body->Binding;<br>
 }<br>
<br>
 template <class ELFT><br>
<br>
Modified: lld/trunk/ELF/SymbolTable.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/SymbolTable.cpp (original)<br>
+++ lld/trunk/ELF/SymbolTable.cpp Mon Apr  4 09:04:16 2016<br>
@@ -135,9 +135,10 @@ SymbolBody *SymbolTable<ELFT>::addUndefi<br>
 }<br>
<br>
 template <class ELFT><br>
-SymbolBody *SymbolTable<ELFT>::addAbsolute(StringRef Name, Elf_Sym &ESym) {<br>
+DefinedRegular<ELFT> *SymbolTable<ELFT>::addAbsolute(StringRef Name,<br>
+                                                     uint8_t Visibility) {<br>
   // Pass nullptr because absolute symbols have no corresponding input sections.<br>
-  auto *Sym = new (Alloc) DefinedRegular<ELFT>(Name, ESym, nullptr);<br>
+  auto *Sym = new (Alloc) DefinedRegular<ELFT>(Name, STB_GLOBAL, Visibility);<br>
   resolve(Sym);<br>
   return Sym;<br>
 }<br>
@@ -152,11 +153,13 @@ SymbolBody *SymbolTable<ELFT>::addSynthe<br>
 }<br>
<br>
 // Add Name as an "ignored" symbol. An ignored symbol is a regular<br>
-// linker-synthesized defined symbol, but it is not recorded to the output<br>
-// file's symbol table. Such symbols are useful for some linker-defined symbols.<br>
+// linker-synthesized defined symbol, but is only defined if needed.<br>
 template <class ELFT><br>
-SymbolBody *SymbolTable<ELFT>::addIgnored(StringRef Name) {<br>
-  return addAbsolute(Name, ElfSym<ELFT>::Ignored);<br>
+DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name,<br>
+                                                    uint8_t Visibility) {<br>
+  if (!find(Name))<br>
+    return nullptr;<br>
+  return addAbsolute(Name, Visibility);<br>
 }<br>
<br>
 // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM.<br>
@@ -228,7 +231,7 @@ template <class ELFT> void SymbolTable<E<br>
     return;<br>
   }<br>
<br>
-  if (New->IsTls != Existing->IsTls) {<br>
+  if (New->isTls() != Existing->isTls()) {<br>
     error("TLS attribute mismatch for symbol: " + conflictMsg(Existing, New));<br>
     return;<br>
   }<br>
@@ -286,10 +289,10 @@ void SymbolTable<ELFT>::addMemberFile(Un<br>
   // symbols and copy information to reduce how many special cases are needed.<br>
   if (Undef->isWeak()) {<br>
     L->setUsedInRegularObj();<br>
-    L->setWeak();<br>
+    L->Binding = Undef->Binding;<br>
+    L->Type = Undef->Type;<br>
<br>
     // FIXME: Do we need to copy more?<br>
-    L->IsTls |= Undef->IsTls;<br>
     return;<br>
   }<br>
<br>
<br>
Modified: lld/trunk/ELF/SymbolTable.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/SymbolTable.h (original)<br>
+++ lld/trunk/ELF/SymbolTable.h Mon Apr  4 09:04:16 2016<br>
@@ -53,21 +53,23 @@ public:<br>
<br>
   SymbolBody *addUndefined(StringRef Name);<br>
   SymbolBody *addUndefinedOpt(StringRef Name);<br>
-  SymbolBody *addAbsolute(StringRef Name, Elf_Sym &ESym);<br>
+  DefinedRegular<ELFT> *addAbsolute(StringRef Name,<br>
+                                    uint8_t Visibility = llvm::ELF::STV_HIDDEN);<br>
   SymbolBody *addSynthetic(StringRef Name, OutputSectionBase<ELFT> &Section,<br>
                            uintX_t Value, uint8_t Visibility);<br>
-  SymbolBody *addIgnored(StringRef Name);<br>
+  DefinedRegular<ELFT> *addIgnored(StringRef Name,<br>
+                                   uint8_t Visibility = llvm::ELF::STV_HIDDEN);<br>
<br>
   void scanShlibUndefined();<br>
   SymbolBody *find(StringRef Name);<br>
   void wrap(StringRef Name);<br>
   InputFile *findFile(SymbolBody *B);<br>
+  void resolve(SymbolBody *Body);<br>
<br>
 private:<br>
   Symbol *insert(SymbolBody *New);<br>
   void addLazy(Lazy *New);<br>
   void addMemberFile(Undefined *Undef, Lazy *L);<br>
-  void resolve(SymbolBody *Body);<br></blockquote><div><br></div><div>Why did you change the visibility of resolve() function?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
   std::string conflictMsg(SymbolBody *Old, SymbolBody *New);<br>
<br>
   // The order the global symbols are in is not defined. We can use an arbitrary<br>
<br>
Modified: lld/trunk/ELF/Symbols.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Symbols.cpp (original)<br>
+++ lld/trunk/ELF/Symbols.cpp Mon Apr  4 09:04:16 2016<br>
@@ -31,7 +31,6 @@ using namespace lld::elf;<br>
 template <class ELFT><br>
 static typename ELFT::uint getSymVA(const SymbolBody &Body,<br>
                                     typename ELFT::uint &Addend) {<br>
-  typedef typename ELFT::Sym Elf_Sym;<br>
   typedef typename ELFT::uint uintX_t;<br>
<br>
   switch (Body.kind()) {<br>
@@ -45,18 +44,24 @@ static typename ELFT::uint getSymVA(cons<br>
     auto &D = cast<DefinedRegular<ELFT>>(Body);<br>
     InputSectionBase<ELFT> *SC = D.Section;<br>
<br>
+    // According to the ELF spec reference to a local symbol from outside<br>
+    // the group are not allowed. Unfortunately .eh_frame breaks that rule<br>
+    // and must be treated specially. For now we just replace the symbol with<br>
+    // 0.<br>
+    if (SC == &InputSection<ELFT>::Discarded)<br>
+      return 0;<br>
+<br>
     // This is an absolute symbol.<br>
     if (!SC)<br>
-      return D.Sym.st_value;<br>
+      return D.Value;<br>
<br>
-    const Elf_Sym &Sym = D.Sym;<br>
-    uintX_t Offset = Sym.st_value;<br>
-    if (Sym.getType() == STT_SECTION) {<br>
+    uintX_t Offset = D.Value;<br>
+    if (D.isSection()) {<br>
       Offset += Addend;<br>
       Addend = 0;<br>
     }<br>
     uintX_t VA = SC->OutSec->getVA() + SC->getOffset(Offset);<br>
-    if (Sym.getType() == STT_TLS)<br>
+    if (D.isTls())<br>
       return VA - Out<ELFT>::TlsPhdr->p_vaddr;<br>
     return VA;<br>
   }<br>
@@ -66,7 +71,7 @@ static typename ELFT::uint getSymVA(cons<br>
     auto &SS = cast<SharedSymbol<ELFT>>(Body);<br>
     if (!SS.NeedsCopyOrPltAddr)<br>
       return 0;<br>
-    if (SS.IsFunc)<br>
+    if (SS.isFunc())<br>
       return Body.getPltVA<ELFT>();<br>
     return Out<ELFT>::Bss->getVA() + SS.OffsetInBss;<br>
   }<br>
@@ -82,6 +87,13 @@ static typename ELFT::uint getSymVA(cons<br>
   llvm_unreachable("invalid symbol kind");<br>
 }<br>
<br>
+SymbolBody::SymbolBody(Kind K, uint32_t NameOffset, uint8_t Other, uint8_t Type)<br>
+    : SymbolKind(K), MustBeInDynSym(false), NeedsCopyOrPltAddr(false),<br>
+      Type(Type), Binding(STB_LOCAL), Other(Other), NameOffset(NameOffset) {<br>
+  IsUsedInRegularObj =<br>
+      K != SharedKind && K != LazyKind && K != DefinedBitcodeKind;<br>
+}<br>
+<br>
 // Returns true if a symbol can be replaced at load-time by a symbol<br>
 // with the same name defined in other ELF executable or DSO.<br>
 bool SymbolBody::isPreemptible() const {<br>
@@ -109,7 +121,7 @@ bool SymbolBody::isPreemptible() const {<br>
     return false;<br>
   if (getVisibility() != STV_DEFAULT)<br>
     return false;<br>
-  if (Config->Bsymbolic || (Config->BsymbolicFunctions && IsFunc))<br>
+  if (Config->Bsymbolic || (Config->BsymbolicFunctions && isFunc()))<br>
     return false;<br>
   return true;<br>
 }<br>
@@ -143,21 +155,17 @@ template <class ELFT> typename ELFT::uin<br>
 }<br>
<br>
 template <class ELFT> typename ELFT::uint SymbolBody::getSize() const {<br>
-  if (const typename ELFT::Sym *Sym = getElfSym<ELFT>())<br>
-    return Sym->st_size;<br>
+  if (const auto *C = dyn_cast<DefinedCommon>(this))<br>
+    return C->Size;<br>
+  if (const auto *DR = dyn_cast<DefinedRegular<ELFT>>(this))<br>
+    return DR->Size;<br>
+  if (const auto *S = dyn_cast<SharedSymbol<ELFT>>(this))<br>
+    return S->Sym.st_size;<br>
+  if (const auto *U = dyn_cast<UndefinedElf<ELFT>>(this))<br>
+    return U->Size;<br>
   return 0;<br>
 }<br>
<br>
-template <class ELFT> const typename ELFT::Sym *SymbolBody::getElfSym() const {<br>
-  if (auto *S = dyn_cast<DefinedRegular<ELFT>>(this))<br>
-    return &S->Sym;<br>
-  if (auto *S = dyn_cast<SharedSymbol<ELFT>>(this))<br>
-    return &S->Sym;<br>
-  if (auto *S = dyn_cast<UndefinedElf<ELFT>>(this))<br>
-    return &S->Sym;<br>
-  return nullptr;<br>
-}<br>
-<br>
 static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {<br>
   if (VA == STV_DEFAULT)<br>
     return VB;<br>
@@ -185,8 +193,9 @@ template <class ELFT> int SymbolBody::co<br>
   if (L > R)<br>
     return -Other->compare<ELFT>(this);<br>
<br>
-  Visibility = Other->Visibility =<br>
-      getMinVisibility(Visibility, Other->Visibility);<br>
+  uint8_t V = getMinVisibility(getVisibility(), Other->getVisibility());<br>
+  setVisibility(V);<br>
+  Other->setVisibility(V);<br>
<br>
   if (IsUsedInRegularObj || Other->IsUsedInRegularObj)<br>
     IsUsedInRegularObj = Other->IsUsedInRegularObj = true;<br>
@@ -212,48 +221,61 @@ template <class ELFT> int SymbolBody::co<br>
   return isCommon() ? -1 : 1;<br>
 }<br>
<br>
-Defined::Defined(Kind K, StringRef Name, bool IsWeak, bool IsLocal,<br>
-                 uint8_t Visibility, uint8_t Type)<br>
-    : SymbolBody(K, Name, IsWeak, IsLocal, Visibility, Type) {}<br>
+Defined::Defined(Kind K, StringRef Name, uint8_t Binding, uint8_t Visibility,<br>
+                 uint8_t Type)<br>
+    : SymbolBody(K, Name, Binding, Visibility, Type) {}<br>
+<br>
+Defined::Defined(Kind K, uint32_t NameOffset, uint8_t Visibility, uint8_t Type)<br>
+    : SymbolBody(K, NameOffset, Visibility, Type) {}<br>
<br>
 DefinedBitcode::DefinedBitcode(StringRef Name, bool IsWeak, uint8_t Visibility)<br>
-    : Defined(DefinedBitcodeKind, Name, IsWeak, false, Visibility,<br>
-              0 /* Type */) {}<br>
+    : Defined(DefinedBitcodeKind, Name, IsWeak ? STB_WEAK : STB_GLOBAL,<br>
+              Visibility, 0 /* Type */) {}<br>
<br>
 bool DefinedBitcode::classof(const SymbolBody *S) {<br>
   return S->kind() == DefinedBitcodeKind;<br>
 }<br>
<br>
-Undefined::Undefined(SymbolBody::Kind K, StringRef N, bool IsWeak,<br>
+Undefined::Undefined(SymbolBody::Kind K, StringRef N, uint8_t Binding,<br>
+                     uint8_t Other, uint8_t Type)<br>
+    : SymbolBody(K, N, Binding, Other, Type), CanKeepUndefined(false) {}<br>
+<br>
+Undefined::Undefined(SymbolBody::Kind K, uint32_t NameOffset,<br>
                      uint8_t Visibility, uint8_t Type)<br>
-    : SymbolBody(K, N, IsWeak, false, Visibility, Type),<br>
-      CanKeepUndefined(false) {}<br>
+    : SymbolBody(K, NameOffset, Visibility, Type), CanKeepUndefined(false) {}<br>
<br>
 Undefined::Undefined(StringRef N, bool IsWeak, uint8_t Visibility,<br>
                      bool CanKeepUndefined)<br>
-    : Undefined(SymbolBody::UndefinedKind, N, IsWeak, Visibility, 0 /* Type */) {<br>
+    : Undefined(SymbolBody::UndefinedKind, N, IsWeak ? STB_WEAK : STB_GLOBAL,<br>
+                Visibility, 0 /* Type */) {<br>
   this->CanKeepUndefined = CanKeepUndefined;<br>
 }<br>
<br>
 template <typename ELFT><br>
 UndefinedElf<ELFT>::UndefinedElf(StringRef N, const Elf_Sym &Sym)<br>
-    : Undefined(SymbolBody::UndefinedElfKind, N,<br>
-                Sym.getBinding() == llvm::ELF::STB_WEAK, Sym.getVisibility(),<br>
+    : Undefined(SymbolBody::UndefinedElfKind, N, Sym.getBinding(), Sym.st_other,<br>
                 Sym.getType()),<br>
-      Sym(Sym) {}<br>
+      Size(Sym.st_size) {}<br>
+<br>
+template <typename ELFT><br>
+UndefinedElf<ELFT>::UndefinedElf(uint32_t NameOffset, const Elf_Sym &Sym)<br>
+    : Undefined(SymbolBody::UndefinedElfKind, NameOffset, Sym.st_other,<br>
+                Sym.getType()),<br>
+      Size(Sym.st_size) {<br>
+  assert(Sym.getBinding() == STB_LOCAL);<br>
+}<br>
<br>
 template <typename ELFT><br>
 DefinedSynthetic<ELFT>::DefinedSynthetic(StringRef N, uintX_t Value,<br>
                                          OutputSectionBase<ELFT> &Section,<br>
                                          uint8_t Visibility)<br>
-    : Defined(SymbolBody::DefinedSyntheticKind, N, false, false, Visibility,<br>
+    : Defined(SymbolBody::DefinedSyntheticKind, N, STB_GLOBAL, Visibility,<br>
               0 /* Type */),<br>
       Value(Value), Section(Section) {}<br>
<br>
 DefinedCommon::DefinedCommon(StringRef N, uint64_t Size, uint64_t Alignment,<br>
-                             bool IsWeak, uint8_t Visibility)<br>
-    : Defined(SymbolBody::DefinedCommonKind, N, IsWeak, false, Visibility,<br>
-              0 /* Type */),<br>
+                             uint8_t Binding, uint8_t Visibility, uint8_t Type)<br>
+    : Defined(SymbolBody::DefinedCommonKind, N, Binding, Visibility, Type),<br>
       Alignment(Alignment), Size(Size) {}<br>
<br>
 std::unique_ptr<InputFile> Lazy::getMember() {<br>
@@ -317,11 +339,6 @@ template uint32_t SymbolBody::template g<br>
 template uint64_t SymbolBody::template getSize<ELF64LE>() const;<br>
 template uint64_t SymbolBody::template getSize<ELF64BE>() const;<br>
<br>
-template const ELF32LE::Sym *SymbolBody::template getElfSym<ELF32LE>() const;<br>
-template const ELF32BE::Sym *SymbolBody::template getElfSym<ELF32BE>() const;<br>
-template const ELF64LE::Sym *SymbolBody::template getElfSym<ELF64LE>() const;<br>
-template const ELF64BE::Sym *SymbolBody::template getElfSym<ELF64BE>() const;<br>
-<br>
 template uint32_t SymbolBody::template getThunkVA<ELF32LE>() const;<br>
 template uint32_t SymbolBody::template getThunkVA<ELF32BE>() const;<br>
 template uint64_t SymbolBody::template getThunkVA<ELF64LE>() const;<br>
<br>
Modified: lld/trunk/ELF/Symbols.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Symbols.h (original)<br>
+++ lld/trunk/ELF/Symbols.h Mon Apr  4 09:04:16 2016<br>
@@ -62,7 +62,7 @@ public:<br>
<br>
   Kind kind() const { return static_cast<Kind>(SymbolKind); }<br>
<br>
-  bool isWeak() const { return IsWeak; }<br>
+  bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; }<br>
   bool isUndefined() const {<br>
     return SymbolKind == UndefinedKind || SymbolKind == UndefinedElfKind;<br>
   }<br>
@@ -70,14 +70,21 @@ public:<br>
   bool isCommon() const { return SymbolKind == DefinedCommonKind; }<br>
   bool isLazy() const { return SymbolKind == LazyKind; }<br>
   bool isShared() const { return SymbolKind == SharedKind; }<br>
-  bool isLocal() const { return IsLocal; }<br>
+  bool isLocal() const { return Binding == llvm::ELF::STB_LOCAL; }<br>
   bool isUsedInRegularObj() const { return IsUsedInRegularObj; }<br>
   bool isPreemptible() const;<br>
<br>
   // Returns the symbol name.<br>
-  StringRef getName() const { return Name; }<br>
+  StringRef getName() const {<br>
+    assert(!isLocal());<br>
+    return Name;<br>
+  }<br>
+  uint32_t getNameOffset() const {<br>
+    assert(isLocal());<br>
+    return NameOffset;<br>
+  }<br>
<br>
-  uint8_t getVisibility() const { return Visibility; }<br>
+  uint8_t getVisibility() const { return Other & 0x3; }<br>
<br>
   unsigned DynsymIndex = 0;<br>
   uint32_t GlobalDynIndex = -1;<br>
@@ -100,7 +107,6 @@ public:<br>
   template <class ELFT> typename ELFT::uint getPltVA() const;<br>
   template <class ELFT> typename ELFT::uint getThunkVA() const;<br>
   template <class ELFT> typename ELFT::uint getSize() const;<br>
-  template <class ELFT> const typename ELFT::Sym *getElfSym() const;<br>
<br>
   // A SymbolBody has a backreference to a Symbol. Originally they are<br>
   // doubly-linked. A backreference will never change. But the pointer<br>
@@ -118,21 +124,18 @@ public:<br>
   template <class ELFT> int compare(SymbolBody *Other);<br>
<br>
 protected:<br>
-  SymbolBody(Kind K, StringRef Name, bool IsWeak, bool IsLocal,<br>
-             uint8_t Visibility, uint8_t Type)<br>
-      : SymbolKind(K), IsWeak(IsWeak), IsLocal(IsLocal), Visibility(Visibility),<br>
-        MustBeInDynSym(false), NeedsCopyOrPltAddr(false), Name(Name) {<br>
-    IsFunc = Type == llvm::ELF::STT_FUNC;<br>
-    IsTls = Type == llvm::ELF::STT_TLS;<br>
-    IsGnuIFunc = Type == llvm::ELF::STT_GNU_IFUNC;<br>
+  SymbolBody(Kind K, StringRef Name, uint8_t Binding, uint8_t Other,<br>
+             uint8_t Type)<br>
+      : SymbolKind(K), MustBeInDynSym(false), NeedsCopyOrPltAddr(false),<br>
+        Type(Type), Binding(Binding), Other(Other), Name(Name) {<br>
+    assert(!isLocal());<br>
     IsUsedInRegularObj =<br>
         K != SharedKind && K != LazyKind && K != DefinedBitcodeKind;<br>
   }<br>
<br>
+  SymbolBody(Kind K, uint32_t NameOffset, uint8_t Other, uint8_t Type);<br>
+<br>
   const unsigned SymbolKind : 8;<br>
-  unsigned IsWeak : 1;<br>
-  unsigned IsLocal : 1;<br>
-  unsigned Visibility : 2;<br>
<br>
   // True if the symbol was used for linking and thus need to be<br>
   // added to the output file's symbol table. It is usually true,<br>
@@ -148,34 +151,44 @@ public:<br>
   // symbol or if the symbol should point to its plt entry.<br>
   unsigned NeedsCopyOrPltAddr : 1;<br>
<br>
-  unsigned IsTls : 1;<br>
-  unsigned IsFunc : 1;<br>
-  unsigned IsGnuIFunc : 1;<br>
+  uint8_t Type;<br>
+  uint8_t Binding;<br>
+  uint8_t Other;<br>
+  bool isSection() const { return Type == llvm::ELF::STT_SECTION; }<br>
+  bool isTls() const { return Type == llvm::ELF::STT_TLS; }<br>
+  bool isFunc() const { return Type == llvm::ELF::STT_FUNC; }<br>
+  bool isGnuIFunc() const { return Type == llvm::ELF::STT_GNU_IFUNC; }<br>
+  bool isObject() const { return Type == llvm::ELF::STT_OBJECT; }<br>
+  bool isFile() const { return Type == llvm::ELF::STT_FILE; }<br>
+  void setVisibility(uint8_t V) { Other = (Other & ~0x3) | V; }<br>
<br>
 protected:<br>
-  StringRef Name;<br>
+  union {<br>
+    StringRef Name;<br>
+    uint32_t NameOffset;<br>
+  };<br>
   Symbol *Backref = nullptr;<br>
 };<br>
<br>
 // The base class for any defined symbols.<br>
 class Defined : public SymbolBody {<br>
 public:<br>
-  Defined(Kind K, StringRef Name, bool IsWeak, bool IsLocal, uint8_t Visibility,<br>
-          uint8_t Type);<br>
+  Defined(Kind K, StringRef Name, uint8_t Binding, uint8_t Other, uint8_t Type);<br>
+  Defined(Kind K, uint32_t NameOffset, uint8_t Other, uint8_t Type);<br>
   static bool classof(const SymbolBody *S) { return S->isDefined(); }<br>
 };<br>
<br>
 // The defined symbol in LLVM bitcode files.<br>
 class DefinedBitcode : public Defined {<br>
 public:<br>
-  DefinedBitcode(StringRef Name, bool IsWeak, uint8_t Visibility);<br>
+  DefinedBitcode(StringRef Name, bool IsWeak, uint8_t Other);<br>
   static bool classof(const SymbolBody *S);<br>
 };<br>
<br>
 class DefinedCommon : public Defined {<br>
 public:<br>
-  DefinedCommon(StringRef N, uint64_t Size, uint64_t Alignment, bool IsWeak,<br>
-                uint8_t Visibility);<br>
+  DefinedCommon(StringRef N, uint64_t Size, uint64_t Alignment, uint8_t Binding,<br>
+                uint8_t Other, uint8_t Type);<br>
<br>
   static bool classof(const SymbolBody *S) {<br>
     return S->kind() == SymbolBody::DefinedCommonKind;<br>
@@ -194,21 +207,36 @@ public:<br>
 // Regular defined symbols read from object file symbol tables.<br>
 template <class ELFT> class DefinedRegular : public Defined {<br>
   typedef typename ELFT::Sym Elf_Sym;<br>
+  typedef typename ELFT::uint uintX_t;<br>
<br>
 public:<br>
   DefinedRegular(StringRef Name, const Elf_Sym &Sym,<br>
                  InputSectionBase<ELFT> *Section)<br>
-      : Defined(SymbolBody::DefinedRegularKind, Name,<br>
-                Sym.getBinding() == llvm::ELF::STB_WEAK,<br>
-                Sym.getBinding() == llvm::ELF::STB_LOCAL,<br>
-                Sym.getVisibility(), Sym.getType()),<br>
-        Sym(Sym), Section(Section ? Section->Repl : NullInputSection) {}<br>
+      : Defined(SymbolBody::DefinedRegularKind, Name, Sym.getBinding(),<br>
+                Sym.st_other, Sym.getType()),<br>
+        Value(Sym.st_value), Size(Sym.st_size),<br>
+        Section(Section ? Section->Repl : NullInputSection) {}<br>
+<br>
+  DefinedRegular(uint32_t NameOffset, const Elf_Sym &Sym,<br>
+                 InputSectionBase<ELFT> *Section)<br>
+      : Defined(SymbolBody::DefinedRegularKind, NameOffset, Sym.st_other,<br>
+                Sym.getType()),<br>
+        Value(Sym.st_value), Size(Sym.st_size),<br>
+        Section(Section ? Section->Repl : NullInputSection) {<br>
+    assert(isLocal());<br>
+  }<br>
+<br>
+  DefinedRegular(StringRef Name, uint8_t Binding, uint8_t Other)<br>
+      : Defined(SymbolBody::DefinedRegularKind, Name, Binding, Other,<br>
+                llvm::ELF::STT_NOTYPE),<br>
+        Value(0), Size(0), Section(NullInputSection) {}<br>
<br>
   static bool classof(const SymbolBody *S) {<br>
     return S->kind() == SymbolBody::DefinedRegularKind;<br>
   }<br>
<br>
-  const Elf_Sym &Sym;<br>
+  uintX_t Value;<br>
+  uintX_t Size;<br>
<br>
   // The input section this symbol belongs to. Notice that this is<br>
   // a reference to a pointer. We are using two levels of indirections<br>
@@ -231,10 +259,9 @@ InputSectionBase<ELFT> *DefinedRegular<E<br>
 // takes an output section to calculate output VA, etc.<br>
 template <class ELFT> class DefinedSynthetic : public Defined {<br>
 public:<br>
-  typedef typename ELFT::Sym Elf_Sym;<br>
   typedef typename ELFT::uint uintX_t;<br>
   DefinedSynthetic(StringRef N, uintX_t Value, OutputSectionBase<ELFT> &Section,<br>
-                   uint8_t Visibility);<br>
+                   uint8_t Other);<br>
<br>
   static bool classof(const SymbolBody *S) {<br>
     return S->kind() == SymbolBody::DefinedSyntheticKind;<br>
@@ -254,11 +281,11 @@ class Undefined : public SymbolBody {<br>
   bool CanKeepUndefined;<br>
<br>
 protected:<br>
-  Undefined(Kind K, StringRef N, bool IsWeak, uint8_t Visibility, uint8_t Type);<br>
+  Undefined(Kind K, StringRef N, uint8_t Binding, uint8_t Other, uint8_t Type);<br>
+  Undefined(Kind K, uint32_t NameOffset, uint8_t Other, uint8_t Type);<br>
<br>
 public:<br>
-  Undefined(StringRef N, bool IsWeak, uint8_t Visibility,<br>
-            bool CanKeepUndefined);<br>
+  Undefined(StringRef N, bool IsWeak, uint8_t Other, bool CanKeepUndefined);<br>
<br>
   static bool classof(const SymbolBody *S) { return S->isUndefined(); }<br>
<br>
@@ -266,11 +293,14 @@ public:<br>
 };<br>
<br>
 template <class ELFT> class UndefinedElf : public Undefined {<br>
+  typedef typename ELFT::uint uintX_t;<br>
   typedef typename ELFT::Sym Elf_Sym;<br>
<br>
 public:<br>
   UndefinedElf(StringRef N, const Elf_Sym &Sym);<br>
-  const Elf_Sym &Sym;<br>
+  UndefinedElf(uint32_t NameOffset, const Elf_Sym &Sym);<br>
+<br>
+  uintX_t Size;<br>
<br>
   static bool classof(const SymbolBody *S) {<br>
     return S->kind() == SymbolBody::UndefinedElfKind;<br>
@@ -287,10 +317,8 @@ public:<br>
   }<br>
<br>
   SharedSymbol(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym)<br>
-      : Defined(SymbolBody::SharedKind, Name,<br>
-                Sym.getBinding() == llvm::ELF::STB_WEAK,<br>
-                Sym.getBinding() == llvm::ELF::STB_LOCAL,<br>
-                Sym.getVisibility(), Sym.getType()),<br>
+      : Defined(SymbolBody::SharedKind, Name, Sym.getBinding(), Sym.st_other,<br>
+                Sym.getType()),<br>
         File(F), Sym(Sym) {}<br>
<br>
   SharedFile<ELFT> *File;<br>
@@ -299,7 +327,7 @@ public:<br>
   // OffsetInBss is significant only when needsCopy() is true.<br>
   uintX_t OffsetInBss = 0;<br>
<br>
-  bool needsCopy() const { return this->NeedsCopyOrPltAddr && !this->IsFunc; }<br>
+  bool needsCopy() const { return this->NeedsCopyOrPltAddr && !this->isFunc(); }<br>
 };<br>
<br>
 // This class represents a symbol defined in an archive file. It is<br>
@@ -310,8 +338,8 @@ public:<br>
 class Lazy : public SymbolBody {<br>
 public:<br>
   Lazy(ArchiveFile *F, const llvm::object::Archive::Symbol S)<br>
-      : SymbolBody(LazyKind, S.getName(), false, false, llvm::ELF::STV_DEFAULT,<br>
-                   /* Type */ 0),<br>
+      : SymbolBody(LazyKind, S.getName(), llvm::ELF::STB_GLOBAL,<br>
+                   llvm::ELF::STV_DEFAULT, /* Type */ 0),<br>
         File(F), Sym(S) {}<br>
<br>
   static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; }<br>
@@ -320,48 +348,44 @@ public:<br>
   // was already returned.<br>
   std::unique_ptr<InputFile> getMember();<br>
<br>
-  void setWeak() { IsWeak = true; }<br>
-<br>
 private:<br>
   ArchiveFile *File;<br>
   const llvm::object::Archive::Symbol Sym;<br>
 };<br>
<br>
 // Some linker-generated symbols need to be created as<br>
-// DefinedRegular symbols, so they need Elf_Sym symbols.<br>
-// Here we allocate such Elf_Sym symbols statically.<br>
+// DefinedRegular symbols.<br>
 template <class ELFT> struct ElfSym {<br>
-  typedef typename ELFT::Sym Elf_Sym;<br>
-<br>
-  // Used to represent an undefined symbol which we don't want to add to the<br>
-  // output file's symbol table. It has weak binding and can be substituted.<br>
-  static Elf_Sym Ignored;<br>
-<br>
   // The content for _etext and etext symbols.<br>
-  static Elf_Sym Etext;<br>
+  static DefinedRegular<ELFT> *Etext;<br>
+  static DefinedRegular<ELFT> *Etext2;<br>
<br>
   // The content for _edata and edata symbols.<br>
-  static Elf_Sym Edata;<br>
+  static DefinedRegular<ELFT> *Edata;<br>
+  static DefinedRegular<ELFT> *Edata2;<br>
<br>
   // The content for _end and end symbols.<br>
-  static Elf_Sym End;<br>
+  static DefinedRegular<ELFT> *End;<br>
+  static DefinedRegular<ELFT> *End2;<br>
<br>
   // The content for _gp symbol for MIPS target.<br>
-  static Elf_Sym MipsGp;<br>
+  static DefinedRegular<ELFT> *MipsGp;<br>
<br>
   // __rel_iplt_start/__rel_iplt_end for signaling<br>
   // where R_[*]_IRELATIVE relocations do live.<br>
-  static Elf_Sym RelaIpltStart;<br>
-  static Elf_Sym RelaIpltEnd;<br>
+  static DefinedRegular<ELFT> *RelaIpltStart;<br>
+  static DefinedRegular<ELFT> *RelaIpltEnd;<br>
 };<br>
<br>
-template <class ELFT> typename ELFT::Sym ElfSym<ELFT>::Ignored;<br>
-template <class ELFT> typename ELFT::Sym ElfSym<ELFT>::Etext;<br>
-template <class ELFT> typename ELFT::Sym ElfSym<ELFT>::Edata;<br>
-template <class ELFT> typename ELFT::Sym ElfSym<ELFT>::End;<br>
-template <class ELFT> typename ELFT::Sym ElfSym<ELFT>::MipsGp;<br>
-template <class ELFT> typename ELFT::Sym ElfSym<ELFT>::RelaIpltStart;<br>
-template <class ELFT> typename ELFT::Sym ElfSym<ELFT>::RelaIpltEnd;<br>
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Etext;<br>
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Etext2;<br>
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Edata;<br>
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Edata2;<br>
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::End;<br>
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::End2;<br>
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::MipsGp;<br>
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::RelaIpltStart;<br>
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::RelaIpltEnd;<br>
<br>
 } // namespace elf<br>
 } // namespace lld<br>
<br>
Modified: lld/trunk/ELF/Target.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Target.cpp (original)<br>
+++ lld/trunk/ELF/Target.cpp Mon Apr  4 09:04:16 2016<br>
@@ -248,7 +248,7 @@ uint64_t TargetInfo::getImplicitAddend(c<br>
 }<br>
<br>
 bool TargetInfo::canRelaxTls(uint32_t Type, const SymbolBody *S) const {<br>
-  if (Config->Shared || (S && !S->IsTls))<br>
+  if (Config->Shared || (S && !S->isTls()))<br>
     return false;<br>
<br>
   // We know we are producing an executable.<br>
@@ -280,7 +280,7 @@ template <typename ELFT> static bool may<br>
   auto *SS = dyn_cast<SharedSymbol<ELFT>>(&S);<br>
   if (!SS)<br>
     return false;<br>
-  return SS->Sym.getType() == STT_OBJECT;<br>
+  return SS->isObject();<br>
 }<br>
<br>
 template <class ELFT><br>
@@ -303,7 +303,7 @@ bool TargetInfo::refersToGotEntry(uint32<br>
<br>
 TargetInfo::PltNeed TargetInfo::needsPlt(uint32_t Type,<br>
                                          const SymbolBody &S) const {<br>
-  if (S.IsGnuIFunc)<br>
+  if (S.isGnuIFunc())<br>
     return Plt_Explicit;<br>
   if (S.isPreemptible() && needsPltImpl(Type))<br>
     return Plt_Explicit;<br>
@@ -330,7 +330,7 @@ TargetInfo::PltNeed TargetInfo::needsPlt<br>
   // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,<br>
   // R_386_JMP_SLOT, etc).<br>
   if (S.isShared())<br>
-    if (!Config->Pic && S.IsFunc && !refersToGotEntry(Type))<br>
+    if (!Config->Pic && S.isFunc() && !refersToGotEntry(Type))<br>
       return Plt_Implicit;<br>
<br>
   return Plt_No;<br>
@@ -500,7 +500,7 @@ bool X86TargetInfo::needsCopyRelImpl(uin<br>
 }<br>
<br>
 bool X86TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {<br>
-  if (S.IsTls && Type == R_386_TLS_GD)<br>
+  if (S.isTls() && Type == R_386_TLS_GD)<br>
     return Target->canRelaxTls(Type, &S) && S.isPreemptible();<br>
   if (Type == R_386_TLS_GOTIE || Type == R_386_TLS_IE)<br>
     return !canRelaxTls(Type, &S);<br>
@@ -1762,7 +1762,7 @@ bool MipsTargetInfo<ELFT>::needsThunk(ui<br>
   // LA25 is required if target file has PIC code<br>
   // or target symbol is a PIC symbol.<br>
   return (D->Section->getFile()->getObj().getHeader()->e_flags & EF_MIPS_PIC) ||<br>
-         (D->Sym.st_other & STO_MIPS_MIPS16) == STO_MIPS_PIC;<br>
+         (D->Other & STO_MIPS_MIPS16) == STO_MIPS_PIC;<br>
 }<br>
<br>
 template <class ELFT><br>
<br>
Modified: lld/trunk/ELF/Writer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Writer.cpp (original)<br>
+++ lld/trunk/ELF/Writer.cpp Mon Apr  4 09:04:16 2016<br>
@@ -287,7 +287,7 @@ static unsigned handleTlsRelocation(uint<br>
     return 1;<br>
   }<br>
<br>
-  if (!Body.IsTls)<br>
+  if (!Body.isTls())<br>
     return 0;<br>
<br>
   if (Target->isTlsGlobalDynamicRel(Type)) {<br>
@@ -403,7 +403,7 @@ void Writer<ELFT>::scanRelocs(InputSecti<br>
       Out<ELFT>::Plt->addEntry(Body);<br>
<br>
       uint32_t Rel;<br>
-      if (Body.IsGnuIFunc)<br>
+      if (Body.isGnuIFunc())<br>
         Rel = Preemptible ? Target->PltRel : Target->IRelativeRel;<br>
       else<br>
         Rel = Target->UseLazyBinding ? Target->PltRel : Target->GotRel;<br>
@@ -440,7 +440,7 @@ void Writer<ELFT>::scanRelocs(InputSecti<br>
                     !Target->isSizeRel(Type);<br>
       if (Preemptible || Dynrel) {<br>
         uint32_t DynType;<br>
-        if (Body.IsTls)<br>
+        if (Body.isTls())<br>
           DynType = Target->TlsGotRel;<br>
         else if (Preemptible)<br>
           DynType = Target->GotRel;<br>
@@ -525,23 +525,17 @@ static void reportUndefined(SymbolTable<<br>
 }<br>
<br>
 template <class ELFT><br>
-static bool shouldKeepInSymtab(const elf::ObjectFile<ELFT> &File,<br>
-                               StringRef SymName,<br>
-                               const typename ELFT::Sym &Sym) {<br>
-  if (Sym.getType() == STT_FILE)<br>
+static bool shouldKeepInSymtab(InputSectionBase<ELFT> *Sec, StringRef SymName,<br>
+                               const SymbolBody &B) {<br>
+  if (B.isFile())<br>
     return false;<br>
<br>
   // We keep sections in symtab for relocatable output.<br>
-  if (Sym.getType() == STT_SECTION)<br>
+  if (B.isSection())<br>
     return Config->Relocatable;<br>
<br>
-  // No reason to keep local undefined symbol in symtab.<br>
-  if (Sym.st_shndx == SHN_UNDEF)<br>
-    return false;<br>
-<br>
-  InputSectionBase<ELFT> *Sec = File.getSection(Sym);<br>
   // If sym references a section in a discarded group, don't keep it.<br>
-  if (Sec == InputSection<ELFT>::Discarded)<br>
+  if (Sec == &InputSection<ELFT>::Discarded)<br>
     return false;<br>
<br>
   if (Config->DiscardNone)<br>
@@ -568,18 +562,23 @@ template <class ELFT> void Writer<ELFT>:<br>
     return;<br>
   for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :<br>
        Symtab.getObjectFiles()) {<br>
+    const char *StrTab = F->getStringTable().data();<br>
     for (SymbolBody *B : F->getLocalSymbols()) {<br>
-      const Elf_Sym &Sym = cast<DefinedRegular<ELFT>>(B)->Sym;<br>
-      StringRef SymName = check(Sym.getName(F->getStringTable()));<br>
-      if (!shouldKeepInSymtab<ELFT>(*F, SymName, Sym))<br>
+      auto *DR = dyn_cast<DefinedRegular<ELFT>>(B);<br>
+      // No reason to keep local undefined symbol in symtab.<br>
+      if (!DR)<br>
         continue;<br>
-      if (Sym.st_shndx != SHN_ABS && !F->getSection(Sym)->Live)<br>
+      StringRef SymName(StrTab + B->getNameOffset());<br>
+      InputSectionBase<ELFT> *Sec = DR->Section;<br>
+      if (!shouldKeepInSymtab<ELFT>(Sec, SymName, *B))<br>
+        continue;<br>
+      if (Sec && !Sec->Live)<br>
         continue;<br>
       ++Out<ELFT>::SymTab->NumLocals;<br>
       if (Config->Relocatable)<br>
         B->DynsymIndex = Out<ELFT>::SymTab->NumLocals;<br>
-      F->KeptLocalSyms.push_back(std::make_pair(<br>
-          &Sym, Out<ELFT>::SymTab->StrTabSec.addString(SymName)));<br>
+      F->KeptLocalSyms.push_back(<br>
+          std::make_pair(DR, Out<ELFT>::SymTab->StrTabSec.addString(SymName)));<br>
     }<br>
   }<br>
 }<br>
@@ -754,7 +753,7 @@ void Writer<ELFT>::addCopyRelSymbols(std<br>
     uintX_t Align = getAlignment(SS);<br>
     Off = alignTo(Off, Align);<br>
     SS->OffsetInBss = Off;<br>
-    Off += SS->Sym.st_size;<br>
+    Off += SS->template getSize<ELFT>();<br>
     MaxAlign = std::max(MaxAlign, Align);<br>
   }<br>
   Out<ELFT>::Bss->setSize(Off);<br>
@@ -787,7 +786,7 @@ void reportDiscarded(InputSectionBase<EL<br>
<br>
 template <class ELFT><br>
 bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) const {<br>
-  return !S || S == InputSection<ELFT>::Discarded || !S->Live ||<br>
+  return !S || S == &InputSection<ELFT>::Discarded || !S->Live ||<br>
          Script->isDiscarded(S);<br>
 }<br>
<br>
@@ -802,12 +801,10 @@ void Writer<ELFT>::addRelIpltSymbols() {<br>
   if (isOutputDynamic() || !Out<ELFT>::RelaPlt)<br>
     return;<br>
   StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start";<br>
-  if (Symtab.find(S))<br>
-    Symtab.addAbsolute(S, ElfSym<ELFT>::RelaIpltStart);<br>
+  ElfSym<ELFT>::RelaIpltStart = Symtab.addIgnored(S);<br>
<br>
   S = Config->Rela ? "__rela_iplt_end" : "__rel_iplt_end";<br>
-  if (Symtab.find(S))<br>
-    Symtab.addAbsolute(S, ElfSym<ELFT>::RelaIpltEnd);<br>
+  ElfSym<ELFT>::RelaIpltEnd = Symtab.addIgnored(S);<br>
 }<br>
<br>
 template <class ELFT> static bool includeInSymtab(const SymbolBody &B) {<br>
@@ -815,9 +812,6 @@ template <class ELFT> static bool includ<br>
     return false;<br>
<br>
   if (auto *D = dyn_cast<DefinedRegular<ELFT>>(&B)) {<br>
-    // Don't include synthetic symbols like __init_array_start in every output.<br>
-    if (&D->Sym == &ElfSym<ELFT>::Ignored)<br>
-      return false;<br>
     // Exclude symbols pointing to garbage-collected sections.<br>
     if (D->Section && !D->Section->Live)<br>
       return false;<br>
@@ -922,6 +916,32 @@ OutputSectionFactory<ELFT>::createKey(In<br>
 // The linker is expected to define some symbols depending on<br>
 // the linking result. This function defines such symbols.<br>
 template <class ELFT> void Writer<ELFT>::addReservedSymbols() {<br>
+  if (Config->EMachine == EM_MIPS) {<br>
+    // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between<br>
+    // start of function and 'gp' pointer into GOT.<br>
+    Config->MipsGpDisp = Symtab.addIgnored("_gp_disp");<br>
+    // The __gnu_local_gp is a magic symbol equal to the current value of 'gp'<br>
+    // pointer. This symbol is used in the code generated by .cpload pseudo-op<br>
+    // in case of using -mno-shared option.<br>
+    // <a href="https://sourceware.org/ml/binutils/2004-12/msg00094.html" rel="noreferrer" target="_blank">https://sourceware.org/ml/binutils/2004-12/msg00094.html</a><br>
+    Config->MipsLocalGp = Symtab.addIgnored("__gnu_local_gp");<br>
+  }<br>
+<br>
+  // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol<br>
+  // is magical and is used to produce a R_386_GOTPC relocation.<br>
+  // The R_386_GOTPC relocation value doesn't actually depend on the<br>
+  // symbol value, so it could use an index of STN_UNDEF which, according<br>
+  // to the spec, means the symbol value is 0.<br>
+  // Unfortunately both gas and MC keep the _GLOBAL_OFFSET_TABLE_ symbol in<br>
+  // the object file.<br>
+  // The situation is even stranger on x86_64 where the assembly doesn't<br>
+  // need the magical symbol, but gas still puts _GLOBAL_OFFSET_TABLE_ as<br>
+  // an undefined symbol in the .o files.<br>
+  // Given that the symbol is effectively unused, we just create a dummy<br>
+  // hidden one to avoid the undefined symbol error.<br>
+  if (!Config->Relocatable)<br>
+    Symtab.addIgnored("_GLOBAL_OFFSET_TABLE_");<br>
+<br>
   // __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For<br>
   // static linking the linker is required to optimize away any references to<br>
   // __tls_get_addr, so it's not defined anywhere. Create a hidden definition<br>
@@ -929,9 +949,9 @@ template <class ELFT> void Writer<ELFT>:<br>
   if (!isOutputDynamic())<br>
     Symtab.addIgnored("__tls_get_addr");<br>
<br>
-  auto Define = [this](StringRef S, Elf_Sym &Sym) {<br>
-    if (Symtab.find(S))<br>
-      Symtab.addAbsolute(S, Sym);<br>
+  auto Define = [this](StringRef S, DefinedRegular<ELFT> *&Sym,<br>
+                       DefinedRegular<ELFT> *&Sym2) {<br>
+    Sym = Symtab.addIgnored(S, STV_DEFAULT);<br>
<br>
     // The name without the underscore is not a reserved name,<br>
     // so it is defined only when there is a reference against it.<br>
@@ -939,12 +959,12 @@ template <class ELFT> void Writer<ELFT>:<br>
     S = S.substr(1);<br>
     if (SymbolBody *B = Symtab.find(S))<br>
       if (B->isUndefined())<br>
-        Symtab.addAbsolute(S, Sym);<br>
+        Sym2 = Symtab.addAbsolute(S, STV_DEFAULT);<br>
   };<br>
<br>
-  Define("_end", ElfSym<ELFT>::End);<br>
-  Define("_etext", ElfSym<ELFT>::Etext);<br>
-  Define("_edata", ElfSym<ELFT>::Edata);<br>
+  Define("_end", ElfSym<ELFT>::End, ElfSym<ELFT>::End2);<br>
+  Define("_etext", ElfSym<ELFT>::Etext, ElfSym<ELFT>::Etext2);<br>
+  Define("_edata", ElfSym<ELFT>::Edata, ElfSym<ELFT>::Edata2);<br>
 }<br>
<br>
 // Sort input sections by section name suffixes for<br>
@@ -1467,13 +1487,15 @@ template <class ELFT> void Writer<ELFT>:<br>
   // to beginning or ending of .rela.plt section, respectively.<br>
   if (Out<ELFT>::RelaPlt) {<br>
     uintX_t Start = Out<ELFT>::RelaPlt->getVA();<br>
-    ElfSym<ELFT>::RelaIpltStart.st_value = Start;<br>
-    ElfSym<ELFT>::RelaIpltEnd.st_value = Start + Out<ELFT>::RelaPlt->getSize();<br>
+    if (ElfSym<ELFT>::RelaIpltStart)<br>
+      ElfSym<ELFT>::RelaIpltStart->Value = Start;<br>
+    if (ElfSym<ELFT>::RelaIpltEnd)<br>
+      ElfSym<ELFT>::RelaIpltEnd->Value = Start + Out<ELFT>::RelaPlt->getSize();<br>
   }<br>
<br>
   // Update MIPS _gp absolute symbol so that it points to the static data.<br>
   if (Config->EMachine == EM_MIPS)<br>
-    ElfSym<ELFT>::MipsGp.st_value = getMipsGpAddr<ELFT>();<br>
+    ElfSym<ELFT>::MipsGp->Value = getMipsGpAddr<ELFT>();<br>
<br>
   // _etext is the first location after the last read-only loadable segment.<br>
   // _edata is the first location after the last read-write loadable segment.<br>
@@ -1482,12 +1504,24 @@ template <class ELFT> void Writer<ELFT>:<br>
     Elf_Phdr &H = P.H;<br>
     if (H.p_type != PT_LOAD)<br>
       continue;<br>
-    ElfSym<ELFT>::End.st_value = H.p_vaddr + H.p_memsz;<br>
-    uintX_t Val = H.p_vaddr + H.p_filesz;<br>
-    if (H.p_flags & PF_W)<br>
-      ElfSym<ELFT>::Edata.st_value = Val;<br>
-    else<br>
-      ElfSym<ELFT>::Etext.st_value = Val;<br>
+    uintX_t Val = H.p_vaddr + H.p_memsz;<br>
+    if (ElfSym<ELFT>::End)<br>
+      ElfSym<ELFT>::End->Value = Val;<br>
+    if (ElfSym<ELFT>::End2)<br>
+      ElfSym<ELFT>::End2->Value = Val;<br>
+<br>
+    Val = H.p_vaddr + H.p_filesz;<br>
+    if (H.p_flags & PF_W) {<br>
+      if (ElfSym<ELFT>::Edata)<br>
+        ElfSym<ELFT>::Edata->Value = Val;<br>
+      if (ElfSym<ELFT>::Edata2)<br>
+        ElfSym<ELFT>::Edata2->Value = Val;<br>
+    } else {<br>
+      if (ElfSym<ELFT>::Etext)<br>
+        ElfSym<ELFT>::Etext->Value = Val;<br>
+      if (ElfSym<ELFT>::Etext2)<br>
+        ElfSym<ELFT>::Etext2->Value = Val;<br>
+    }<br>
   }<br>
 }<br>
<br>
<br>
Modified: lld/trunk/test/ELF/aarch64-gnu-ifunc.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-gnu-ifunc.s?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-gnu-ifunc.s?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/aarch64-gnu-ifunc.s (original)<br>
+++ lld/trunk/test/ELF/aarch64-gnu-ifunc.s Mon Apr  4 09:04:16 2016<br>
@@ -51,7 +51,9 @@<br>
 // CHECK-NEXT:    Size: 0<br>
 // CHECK-NEXT:    Binding: Local<br>
 // CHECK-NEXT:    Type: None<br>
-// CHECK-NEXT:    Other: 0<br>
+// CHECK-NEXT:    Other [<br>
+// CHECK-NEXT:      STV_HIDDEN<br>
+// CHECK-NEXT:    ]<br>
 // CHECK-NEXT:    Section: Absolute<br>
 // CHECK-NEXT:  }<br>
 // CHECK-NEXT:  Symbol {<br>
@@ -60,7 +62,9 @@<br>
 // CHECK-NEXT:    Size: 0<br>
 // CHECK-NEXT:    Binding: Local<br>
 // CHECK-NEXT:    Type: None<br>
-// CHECK-NEXT:    Other: 0<br>
+// CHECK-NEXT:    Other [<br>
+// CHECK-NEXT:      STV_HIDDEN<br>
+// CHECK-NEXT:    ]<br>
 // CHECK-NEXT:    Section: Absolute<br>
 // CHECK-NEXT:  }<br>
 // CHECK-NEXT:  Symbol {<br>
<br>
Modified: lld/trunk/test/ELF/basic-mips.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/basic-mips.s?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/basic-mips.s?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/basic-mips.s (original)<br>
+++ lld/trunk/test/ELF/basic-mips.s Mon Apr  4 09:04:16 2016<br>
@@ -187,22 +187,22 @@ __start:<br>
 # CHECK-NEXT:     Section: Undefined (0x0)<br>
 # CHECK-NEXT:   }<br>
 # CHECK-NEXT:   Symbol {<br>
-# CHECK-NEXT:     Name: _gp<br>
-# CHECK-NEXT:     Value: 0x0<br>
+# CHECK-NEXT:     Name: __start<br>
+# CHECK-NEXT:     Value: 0x20000<br>
 # CHECK-NEXT:     Size: 0<br>
-# CHECK-NEXT:     Binding: Local (0x0)<br>
+# CHECK-NEXT:     Binding: Global (0x1)<br>
 # CHECK-NEXT:     Type: None (0x0)<br>
 # CHECK-NEXT:     Other: 0<br>
-# CHECK-NEXT:     Section: Absolute (0xFFF1)<br>
+# CHECK-NEXT:     Section: .text<br>
 # CHECK-NEXT:   }<br>
 # CHECK-NEXT:   Symbol {<br>
-# CHECK-NEXT:     Name: __start<br>
-# CHECK-NEXT:     Value: 0x20000<br>
+# CHECK-NEXT:     Name: _gp<br>
+# CHECK-NEXT:     Value: 0x0<br>
 # CHECK-NEXT:     Size: 0<br>
-# CHECK-NEXT:     Binding: Global (0x1)<br>
+# CHECK-NEXT:     Binding: Global<br>
 # CHECK-NEXT:     Type: None (0x0)<br>
 # CHECK-NEXT:     Other: 0<br>
-# CHECK-NEXT:     Section: .text<br>
+# CHECK-NEXT:     Section: Absolute (0xFFF1)<br>
 # CHECK-NEXT:   }<br>
 # CHECK-NEXT: ]<br>
 # CHECK-NEXT: ProgramHeaders [<br>
<br>
Modified: lld/trunk/test/ELF/global_offset_table_shared.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/global_offset_table_shared.s?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/global_offset_table_shared.s?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/global_offset_table_shared.s (original)<br>
+++ lld/trunk/test/ELF/global_offset_table_shared.s Mon Apr  4 09:04:16 2016<br>
@@ -3,4 +3,7 @@<br>
 // RUN: llvm-readobj -t %t2 | FileCheck %s<br>
 .long _GLOBAL_OFFSET_TABLE_<br>
<br>
-// CHECK-NOT: Name: _GLOBAL_OFFSET_TABLE_<br>
+// CHECK:      Name: _GLOBAL_OFFSET_TABLE_<br>
+// CHECK-NEXT: Value:<br>
+// CHECK-NEXT: Size: 0<br>
+// CHECK-NEXT: Binding: Local<br>
<br>
Modified: lld/trunk/test/ELF/gnu-ifunc-i386.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gnu-ifunc-i386.s?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gnu-ifunc-i386.s?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/gnu-ifunc-i386.s (original)<br>
+++ lld/trunk/test/ELF/gnu-ifunc-i386.s Mon Apr  4 09:04:16 2016<br>
@@ -43,7 +43,9 @@<br>
 // CHECK-NEXT:   Size: 0<br>
 // CHECK-NEXT:   Binding: Local<br>
 // CHECK-NEXT:   Type: None<br>
-// CHECK-NEXT:   Other: 0<br>
+// CHECK-NEXT:   Other [<br>
+// CHECK-NEXT:     STV_HIDDEN<br>
+// CHECK-NEXT:   ]<br>
 // CHECK-NEXT:   Section: Absolute<br>
 // CHECK-NEXT: }<br>
 // CHECK-NEXT: Symbol {<br>
@@ -52,7 +54,9 @@<br>
 // CHECK-NEXT:   Size: 0<br>
 // CHECK-NEXT:   Binding: Local<br>
 // CHECK-NEXT:   Type: None<br>
-// CHECK-NEXT:   Other: 0<br>
+// CHECK-NEXT:   Other [<br>
+// CHECK-NEXT:     STV_HIDDEN<br>
+// CHECK-NEXT:   ]<br>
 // CHECK-NEXT:   Section: Absolute<br>
 // CHECK-NEXT: }<br>
 // CHECK-NEXT: Symbol {<br>
<br>
Modified: lld/trunk/test/ELF/gnu-ifunc.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gnu-ifunc.s?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gnu-ifunc.s?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/gnu-ifunc.s (original)<br>
+++ lld/trunk/test/ELF/gnu-ifunc.s Mon Apr  4 09:04:16 2016<br>
@@ -42,7 +42,9 @@<br>
 // CHECK-NEXT:    Size: 0<br>
 // CHECK-NEXT:    Binding: Local<br>
 // CHECK-NEXT:    Type: None<br>
-// CHECK-NEXT:    Other: 0<br>
+// CHECK-NEXT:    Other [<br>
+// CHECK-NEXT:      STV_HIDDEN<br>
+// CHECK-NEXT:    ]<br>
 // CHECK-NEXT:    Section: Absolute<br>
 // CHECK-NEXT:  }<br>
 // CHECK-NEXT:  Symbol {<br>
@@ -51,7 +53,9 @@<br>
 // CHECK-NEXT:    Size: 0<br>
 // CHECK-NEXT:    Binding: Local<br>
 // CHECK-NEXT:    Type: None<br>
-// CHECK-NEXT:    Other: 0<br>
+// CHECK-NEXT:    Other [<br>
+// CHECK-NEXT:      STV_HIDDEN<br>
+// CHECK-NEXT:    ]<br>
 // CHECK-NEXT:    Section: Absolute<br>
 // CHECK-NEXT:  }<br>
 // CHECK-NEXT:  Symbol {<br>
<br>
Modified: lld/trunk/test/ELF/mips-gp-disp.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-gp-disp.s?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-gp-disp.s?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/mips-gp-disp.s (original)<br>
+++ lld/trunk/test/ELF/mips-gp-disp.s Mon Apr  4 09:04:16 2016<br>
@@ -11,7 +11,10 @@<br>
<br>
 # REQUIRES: mips<br>
<br>
-# INT-SO-NOT:  Name: _gp_disp<br>
+# INT-SO:      Name: _gp_disp<br>
+# INT-SO-NEXT: Value:<br>
+# INT-SO-NEXT: Size:<br>
+# INT-SO-NEXT: Binding: Local<br>
<br>
 # EXT-SO:      Name: _gp_disp<br>
 # EXT-SO-NEXT: Value: 0x20010<br>
<br>
Modified: lld/trunk/test/ELF/mips-hilo-gp-disp.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-hilo-gp-disp.s?rev=265293&r1=265292&r2=265293&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-hilo-gp-disp.s?rev=265293&r1=265292&r2=265293&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/mips-hilo-gp-disp.s (original)<br>
+++ lld/trunk/test/ELF/mips-hilo-gp-disp.s Mon Apr  4 09:04:16 2016<br>
@@ -25,8 +25,8 @@ __start:<br>
 #                                                  ^-- %lo(0x37ff0-0x20004+4)<br>
<br>
 # EXE: SYMBOL TABLE:<br>
-# EXE: 00037ff0     *ABS*   00000000 _gp<br>
 # EXE: 00020000     .text   00000000 __start<br>
+# EXE: 00037ff0     *ABS*   00000000 _gp<br>
 # EXE: 00020010     .text   00000000 _foo<br>
<br>
 # SO:      Disassembly of section .text:<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>