[PATCH] D11612: [lld][ELF2] Apply relocations.

Rafael EspĂ­ndola via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 26 13:26:31 PDT 2015


The attached patch fixes the build and runs git-clang-format.

On 26 August 2015 at 16:23, Rafael EspĂ­ndola <rafael.espindola at gmail.com> wrote:
> This doesn't even compile:
>
> /home/espindola/llvm/llvm/tools/lld/ELF/Symbols.h:135:12: error: use
> of undeclared identifier 'Sym'
>     return Sym.st_value;
>
> On 26 August 2015 at 02:09, Rui Ueyama <ruiu at google.com> wrote:
>> ruiu added a comment.
>>
>> Rafael should be the person who signs off.
>>
>>
>> http://reviews.llvm.org/D11612
>>
>>
>>
-------------- next part --------------
diff --git a/COFF/DriverUtils.cpp b/COFF/DriverUtils.cpp
index e50d3ce..ec5e919 100644
--- a/COFF/DriverUtils.cpp
+++ b/COFF/DriverUtils.cpp
@@ -483,18 +483,18 @@ static std::string writeToTempFile(StringRef Contents) {
 static std::string createModuleDefinitionFile() {
   std::string S;
   llvm::raw_string_ostream OS(S);
-  OS << "  LIBRARY \"" << llvm::sys::path::filename(Config->OutputFile) << "\"\n"
-     << "  EXPORTS\n";
+  OS << "LIBRARY \"" << llvm::sys::path::filename(Config->OutputFile) << "\"\n"
+     << "EXPORTS\n";
   for (Export &E : Config->Exports) {
-    OS << "    " << E.ExtLibName;
+    OS << "  " << E.ExtLibName;
     if (E.Ordinal > 0)
-      OS << "   @" << E.Ordinal;
+      OS << " @" << E.Ordinal;
     if (E.Noname)
-      OS << "   NONAME";
+      OS << " NONAME";
     if (E.Data)
-      OS << "   DATA";
+      OS << " DATA";
     if (E.Private)
-      OS << "   PRIVATE";
+      OS << " PRIVATE";
     OS << "\n";
   }
   OS.flush();
@@ -507,9 +507,6 @@ void writeImportLibrary() {
   std::string Def = writeToTempFile(Contents);
   llvm::FileRemover TempFile(Def);
 
-  if (Config->Verbose)
-    llvm::outs() << "Module-definition file:" << Contents;
-
   Executor E("lib.exe");
   E.add("/nologo");
   E.add("/machine:" + machineToStr(Config->Machine));
@@ -565,15 +562,6 @@ llvm::opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) {
   unsigned MissingCount;
   llvm::opt::InputArgList Args =
       Table.ParseArgs(Argv, MissingIndex, MissingCount);
-
-  // Print the real command line if response files are expanded.
-  if (Args.hasArg(OPT_verbose) && ArgsArr.size() != Argv.size()) {
-    llvm::outs() << "Command line:";
-    for (const char *S : Argv)
-      llvm::outs() << " " << S;
-    llvm::outs() << "\n";
-  }
-
   if (MissingCount)
     error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) +
           "\", expected " + Twine(MissingCount) +
diff --git a/COFF/InputFiles.h b/COFF/InputFiles.h
index a3a9bd9..0d11446 100644
--- a/COFF/InputFiles.h
+++ b/COFF/InputFiles.h
@@ -206,7 +206,7 @@ public:
   MachineTypes getMachineType() override;
 
   LTOModule *getModule() const { return M.get(); }
-  std::unique_ptr<LTOModule> takeModule() { return std::move(M); }
+  LTOModule *releaseModule() { return M.release(); }
 
 private:
   void parse() override;
diff --git a/COFF/SymbolTable.cpp b/COFF/SymbolTable.cpp
index 1fb450b..410179c 100644
--- a/COFF/SymbolTable.cpp
+++ b/COFF/SymbolTable.cpp
@@ -401,7 +401,7 @@ ObjectFile *SymbolTable::createLTOObject(LTOCodeGenerator *CG) {
       CG->addMustPreserveSymbol(S->getName());
   }
 
-  CG->setModule(BitcodeFiles[0]->takeModule());
+  CG->setModule(BitcodeFiles[0]->releaseModule());
   for (unsigned I = 1, E = BitcodeFiles.size(); I != E; ++I)
     CG->addModule(BitcodeFiles[I]->getModule());
 
diff --git a/ELF/Chunks.cpp b/ELF/Chunks.cpp
index 77b8fa1..8dec8ff 100644
--- a/ELF/Chunks.cpp
+++ b/ELF/Chunks.cpp
@@ -9,6 +9,7 @@
 
 #include "Chunks.h"
 #include "Error.h"
+#include "InputFiles.h"
 
 using namespace llvm;
 using namespace llvm::ELF;
@@ -17,23 +18,23 @@ using namespace lld;
 using namespace lld::elf2;
 
 template <class ELFT>
-SectionChunk<ELFT>::SectionChunk(object::ELFFile<ELFT> *Obj,
-                                 const Elf_Shdr *Header)
-    : Obj(Obj), Header(Header) {
+SectionChunk<ELFT>::SectionChunk(ObjectFile<ELFT> *F, const Elf_Shdr *Header)
+    : File(F), OS(nullptr), Header(Header) {
+  Align = Header->sh_addralign;
 }
 
 template <class ELFT> void SectionChunk<ELFT>::writeTo(uint8_t *Buf) {
   if (Header->sh_type == SHT_NOBITS)
     return;
   // Copy section contents from source object file to output file.
-  ArrayRef<uint8_t> Data = *Obj->getSectionContents(Header);
+  ArrayRef<uint8_t> Data = *File->getObj()->getSectionContents(Header);
   memcpy(Buf + OutputSectionOff, Data.data(), Data.size());
 
   // FIXME: Relocations
 }
 
 template <class ELFT> StringRef SectionChunk<ELFT>::getSectionName() const {
-  ErrorOr<StringRef> Name = Obj->getSectionName(Header);
+  ErrorOr<StringRef> Name = File->getObj()->getSectionName(Header);
   error(Name);
   return *Name;
 }
diff --git a/ELF/Chunks.h b/ELF/Chunks.h
index 4710182..f7bec41 100644
--- a/ELF/Chunks.h
+++ b/ELF/Chunks.h
@@ -24,10 +24,9 @@ template <class ELFT> class SectionChunk {
   typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
   typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
   typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
-  typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
 
 public:
-  SectionChunk(llvm::object::ELFFile<ELFT> *Obj, const Elf_Shdr *Header);
+  SectionChunk(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
 
   // Returns the size of this chunk (even if this is a common or BSS.)
   size_t getSize() const { return Header->sh_size; }
@@ -38,24 +37,28 @@ public:
 
   StringRef getSectionName() const;
   const Elf_Shdr *getSectionHdr() const { return Header; }
+  ObjectFile<ELFT> *getFile() { return File; }
+  void setOutputSection(OutputSection<ELFT> *S) { OS = S; }
+  OutputSection<ELFT> *getOutputSection() { return OS; }
 
   // The writer sets and uses the addresses.
-  uintX_t getOutputSectionOff() const { return OutputSectionOff; }
-  uintX_t getAlign() { return Header->sh_addralign; }
+  uint64_t getOutputSectionOff() { return OutputSectionOff; }
+  uint32_t getAlign() { return Align; }
   void setOutputSectionOff(uint64_t V) { OutputSectionOff = V; }
 
-  void setOutputSection(OutputSection<ELFT> *O) { Out = O; }
-  OutputSection<ELFT> *getOutputSection() const { return Out; }
-
 private:
   // The offset from beginning of the output sections this chunk was assigned
   // to. The writer sets a value.
   uint64_t OutputSectionOff = 0;
 
-  // A file this chunk was created from.
-  llvm::object::ELFFile<ELFT> *Obj;
+  // The alignment of this chunk. The writer uses the value.
+  uint32_t Align = 1;
+
+  // The file this chunk was created from.
+  ObjectFile<ELFT> *File;
 
-  OutputSection<ELFT> *Out = nullptr;
+  // The OutputSection this is assigned to.
+  OutputSection<ELFT> *OS;
 
   const Elf_Shdr *Header;
 };
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index 14566dc..3541ab7 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -39,30 +39,34 @@ template <class ELFT> void elf2::ObjectFile<ELFT>::parse() {
 
 template <class ELFT> void elf2::ObjectFile<ELFT>::initializeChunks() {
   uint64_t Size = ELFObj->getNumSections();
-  Chunks.resize(Size);
-  unsigned I = 0;
+  Chunks.reserve(Size);
+  SparseChunks.reserve(Size);
   for (const Elf_Shdr &Sec : ELFObj->sections()) {
+    SectionChunk<ELFT> *SC = nullptr;
     switch (Sec.sh_type) {
     case SHT_SYMTAB:
       Symtab = &Sec;
       break;
-    case SHT_SYMTAB_SHNDX: {
-      ErrorOr<ArrayRef<Elf_Word>> ErrorOrTable = ELFObj->getSHNDXTable(Sec);
-      error(ErrorOrTable);
-      SymtabSHNDX = *ErrorOrTable;
-      break;
-    }
     case SHT_STRTAB:
     case SHT_NULL:
+      break;
     case SHT_RELA:
-    case SHT_REL:
+    case SHT_REL: {
+      auto RelocatedSec = ELFObj->getSection(Sec.sh_info);
+      if (!RelocatedSec)
+        error(RelocatedSec);
+      RelocMap.emplace_back(*RelocatedSec, &Sec);
       break;
+    }
     default:
-      Chunks[I] = new (Alloc) SectionChunk<ELFT>(this->getObj(), &Sec);
+      SC = new (Alloc) SectionChunk<ELFT>(this, &Sec);
+      Chunks.push_back(SC);
       break;
     }
-    ++I;
+    SparseChunks.push_back(SC);
   }
+  assert(SparseChunks.size() == Size && "Not all chunks added to SparseChunks");
+  std::sort(RelocMap.begin(), RelocMap.end());
 }
 
 template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() {
@@ -76,10 +80,19 @@ template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() {
   uint32_t FirstNonLocal = Symtab->sh_info;
   if (FirstNonLocal > NumSymbols)
     error("Invalid sh_info in symbol table");
+  Elf_Sym_Range LocalSyms =
+      llvm::make_range(Syms.begin() + 1, Syms.begin() + FirstNonLocal);
   Syms = llvm::make_range(Syms.begin() + FirstNonLocal, Syms.end());
   SymbolBodies.reserve(NumSymbols);
-  for (const Elf_Sym &Sym : Syms)
-    SymbolBodies.push_back(createSymbolBody(StringTable, &Sym));
+  IndexedSymbolBodies.reserve(NumSymbols);
+  IndexedSymbolBodies.push_back(nullptr); // Skip the null entry.
+  for (const Elf_Sym &Sym : LocalSyms)
+    IndexedSymbolBodies.push_back(createSymbolBody(StringTable, &Sym));
+  for (const Elf_Sym &Sym : Syms) {
+    SymbolBody *S = createSymbolBody(StringTable, &Sym);
+    SymbolBodies.push_back(S);
+    IndexedSymbolBodies.push_back(S);
+  }
 }
 
 template <class ELFT>
@@ -88,26 +101,21 @@ SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
   ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable);
   error(NameOrErr.getError());
   StringRef Name = *NameOrErr;
-
-  uint32_t SecIndex = Sym->st_shndx;
-  if (SecIndex == SHN_XINDEX)
-    SecIndex = ELFObj->getExtendedSymbolTableIndex(Sym, Symtab, SymtabSHNDX);
-
-  if (SecIndex >= Chunks.size() ||
-      (SecIndex != 0 && !Chunks[SecIndex]))
-    error("Invalid section index");
-
   switch (Sym->getBinding()) {
   default:
     error("unexpected binding");
+  case STB_LOCAL:
+    return new (Alloc)
+        DefinedRegular<ELFT>(Name, *Sym, SparseChunks[Sym->st_shndx]);
   case STB_GLOBAL:
     if (Sym->isUndefined())
       return new (Alloc) Undefined<ELFT>(Name, *Sym);
-    return new (Alloc) DefinedRegular<ELFT>(Name, *Sym, *Chunks[SecIndex]);
+    return new (Alloc)
+        DefinedRegular<ELFT>(Name, *Sym, SparseChunks[Sym->st_shndx]);
   case STB_WEAK:
     if (Sym->isUndefined())
       return new (Alloc) UndefinedWeak<ELFT>(Name, *Sym);
-    return new (Alloc) DefinedWeak<ELFT>(Name, *Sym, *Chunks[SecIndex]);
+    return new (Alloc) DefinedWeak<ELFT>(Name, *Sym);
   }
 }
 
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index 774166c..9ec535b 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -11,6 +11,7 @@
 #define LLD_ELF_INPUT_FILES_H
 
 #include "Chunks.h"
+#include "Error.h"
 #include "lld/Core/LLVM.h"
 #include "llvm/Object/ELF.h"
 
@@ -65,9 +66,23 @@ template <class ELFT> class ObjectFile : public ObjectFileBase {
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
-  typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
 
 public:
+  struct RelocMapInfo {
+    RelocMapInfo(const Elf_Shdr *S, const Elf_Shdr *RS)
+        : Section(S), RelocSection(RS) {}
+
+    const Elf_Shdr *Section;
+    const Elf_Shdr *RelocSection;
+
+    bool operator<(const RelocMapInfo &Other) const {
+      // Pointer comparison is stable here as all pointers in a given RelocMap
+      // point to a single memory mapped file.
+      return std::tie(Section, RelocSection) <
+             std::tie(Other.Section, Other.RelocSection);
+    }
+  };
+
   bool isCompatibleWith(const ObjectFileBase &Other) const override;
 
   static Kind getKind() {
@@ -85,12 +100,21 @@ public:
 
   explicit ObjectFile(MemoryBufferRef M) : ObjectFileBase(getKind(), M) {}
   void parse() override;
+  const std::vector<RelocMapInfo> &getRelocations() const { return RelocMap; }
+
+  SymbolBody *getSymbolBody(uint32_t SymbolIndex) {
+    if (SymbolIndex >= IndexedSymbolBodies.size())
+      error("Invalid symbol table index.");
+    return IndexedSymbolBodies[SymbolIndex]->getReplacement();
+  }
 
   // Returns the underying ELF file.
   llvm::object::ELFFile<ELFT> *getObj() const { return ELFObj.get(); }
 
   ArrayRef<SectionChunk<ELFT> *> getChunks() { return Chunks; }
 
+  const Elf_Shdr *getSymtab() const { return Symtab; }
+
 private:
   void initializeChunks();
   void initializeSymbols();
@@ -103,7 +127,16 @@ private:
   std::vector<SectionChunk<ELFT> *> Chunks;
 
   const Elf_Shdr *Symtab = nullptr;
-  ArrayRef<Elf_Word> SymtabSHNDX;
+  // Section index to SectionChunk map. Unmapped sections are nullptr.
+  std::vector<SectionChunk<ELFT> *> SparseChunks;
+
+  // Symbol bodies indexed the same as the symbol table.
+  std::vector<SymbolBody *> IndexedSymbolBodies;
+
+  // This vector contains a sorted list of <section, relocation section that
+  // applies to section> pairs. This is used to quickly find and iterate over
+  // the relocations for a given section.
+  std::vector<RelocMapInfo> RelocMap;
 };
 
 } // namespace elf2
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
index 095940c..bb89a3f 100644
--- a/ELF/Symbols.cpp
+++ b/ELF/Symbols.cpp
@@ -43,3 +43,12 @@ int SymbolBody::compare(SymbolBody *Other) {
   }
   llvm_unreachable("unknown symbol kind");
 }
+
+namespace lld {
+namespace elf2 {
+template class DefinedRegular<llvm::object::ELF32LE>;
+template class DefinedRegular<llvm::object::ELF32BE>;
+template class DefinedRegular<llvm::object::ELF64LE>;
+template class DefinedRegular<llvm::object::ELF64BE>;
+}
+}
diff --git a/ELF/Symbols.h b/ELF/Symbols.h
index 296fd40..7a8fb3f 100644
--- a/ELF/Symbols.h
+++ b/ELF/Symbols.h
@@ -62,6 +62,7 @@ public:
   // has chosen the object among other objects having the same name,
   // you can access P->Backref->Body to get the resolver's result.
   void setBackref(Symbol *P) { Backref = P; }
+  SymbolBody *getReplacement() { return Backref ? Backref->Body : this; }
 
   // Decides which symbol should "win" in the symbol table, this or
   // the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if
@@ -108,16 +109,13 @@ template <class ELFT> class Defined : public ELFSymbolBody<ELFT> {
 public:
   typedef typename Base::Elf_Sym Elf_Sym;
 
-  explicit Defined(Kind K, StringRef N, const Elf_Sym &Sym,
-                   SectionChunk<ELFT> &Section)
-      : ELFSymbolBody<ELFT>(K, N, Sym), Section(Section) {}
+  explicit Defined(Kind K, StringRef N, const Elf_Sym &Sym)
+      : ELFSymbolBody<ELFT>(K, N, Sym) {}
 
   static bool classof(const SymbolBody *S) {
     Kind K = S->kind();
     return Base::DefinedFirst <= K && K <= Base::DefinedLast;
   }
-
-  const SectionChunk<ELFT> &Section;
 };
 
 // Regular defined symbols read from object file symbol tables.
@@ -126,13 +124,21 @@ template <class ELFT> class DefinedRegular : public Defined<ELFT> {
   typedef typename Base::Elf_Sym Elf_Sym;
 
 public:
-  explicit DefinedRegular(StringRef N, const Elf_Sym &Sym,
-                          SectionChunk<ELFT> &Section)
-      : Defined<ELFT>(Base::DefinedRegularKind, N, Sym, Section) {}
+  DefinedRegular(StringRef N, const Elf_Sym &Sym, SectionChunk<ELFT> *C)
+      : Defined<ELFT>(Base::DefinedRegularKind, N, Sym), Chunk(C) {}
 
   static bool classof(const SymbolBody *S) {
     return S->kind() == Base::DefinedRegularKind;
   }
+
+  typename llvm::object::ELFFile<ELFT>::uintX_t getValue() const {
+    return this->Sym.st_value;
+  }
+
+  SectionChunk<ELFT> *getChunk() const { return Chunk; }
+
+private:
+  SectionChunk<ELFT> *Chunk;
 };
 
 template <class ELFT> class DefinedWeak : public Defined<ELFT> {
@@ -140,9 +146,8 @@ template <class ELFT> class DefinedWeak : public Defined<ELFT> {
   typedef typename Base::Elf_Sym Elf_Sym;
 
 public:
-  explicit DefinedWeak(StringRef N, const Elf_Sym &Sym,
-                       SectionChunk<ELFT> &Section)
-      : Defined<ELFT>(Base::DefinedWeakKind, N, Sym, Section) {}
+  explicit DefinedWeak(StringRef N, const Elf_Sym &Sym)
+      : Defined<ELFT>(Base::DefinedWeakKind, N, Sym) {}
 
   static bool classof(const SymbolBody *S) {
     return S->kind() == Base::DefinedWeakKind;
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 430b9c1..3d0b1a4 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -10,6 +10,7 @@
 #include "Chunks.h"
 #include "Config.h"
 #include "Error.h"
+#include "Symbols.h"
 #include "SymbolTable.h"
 #include "Writer.h"
 #include "Symbols.h"
@@ -26,7 +27,8 @@ using namespace lld::elf2;
 
 static const int PageSize = 4096;
 
-namespace {
+namespace lld {
+namespace elf2 {
 // OutputSection represents a section in an output file. It's a
 // container of chunks. OutputSection and Chunk are 1:N relationship.
 // Chunks cannot belong to more than one OutputSections. The writer
@@ -52,9 +54,6 @@ public:
   StringRef getName() { return Name; }
   void setNameOffset(uintX_t Offset) { Header.sh_name = Offset; }
 
-  unsigned getSectionIndex() const { return SectionIndex; }
-  void setSectionIndex(unsigned I) { SectionIndex = I; }
-
   // Returns the size of the section in the output file.
   uintX_t getSize() { return Header.sh_size; }
   uintX_t getFlags() { return Header.sh_flags; }
@@ -67,14 +66,11 @@ public:
 protected:
   StringRef Name;
   HeaderT Header;
-  unsigned SectionIndex;
   ~OutputSectionBase() = default;
 };
-}
 
 template <class ELFT>
-class lld::elf2::OutputSection final
-    : public OutputSectionBase<ELFT::Is64Bits> {
+class OutputSection final : public OutputSectionBase<ELFT::Is64Bits> {
 public:
   typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
   OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags)
@@ -86,6 +82,8 @@ public:
 private:
   std::vector<SectionChunk<ELFT> *> Chunks;
 };
+} // end namespace elf2
+} // end namespace lld
 
 namespace {
 template <bool Is64Bits>
@@ -114,7 +112,6 @@ template <class ELFT>
 class SymbolTableSection final : public OutputSectionBase<ELFT::Is64Bits> {
 public:
   typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
-  typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
   SymbolTableSection(SymbolTable &Table)
       : OutputSectionBase<ELFT::Is64Bits>(".symtab", SHT_SYMTAB, 0),
         Table(Table) {
@@ -168,11 +165,6 @@ private:
   StringTableSection<ELFT::Is64Bits> StringTable;
 
   unsigned NumSections;
-
-  void addOutputSection(OutputSectionBase<ELFT::Is64Bits> *Sec) {
-    OutputSections.push_back(Sec);
-    Sec->setSectionIndex(OutputSections.size());
-  }
 };
 } // anonymous namespace
 
@@ -203,7 +195,6 @@ template <class ELFT> void Writer<ELFT>::run() {
 template <class ELFT>
 void OutputSection<ELFT>::addChunk(SectionChunk<ELFT> *C) {
   Chunks.push_back(C);
-  C->setOutputSection(this);
   uint32_t Align = C->getAlign();
   if (Align > this->Header.sh_addralign)
     this->Header.sh_addralign = Align;
@@ -215,9 +206,55 @@ void OutputSection<ELFT>::addChunk(SectionChunk<ELFT> *C) {
   this->Header.sh_size = Off;
 }
 
+template <class ELFT>
+typename llvm::object::ELFFile<ELFT>::uintX_t
+getSymVA(DefinedRegular<ELFT> *DR) {
+  SectionChunk<ELFT> *SC = DR->getChunk();
+  OutputSection<ELFT> *OS = SC->getOutputSection();
+  return OS->getVA() + SC->getOutputSectionOff() + DR->getValue();
+}
+
 template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
-  for (SectionChunk<ELFT> *C : Chunks)
+  for (SectionChunk<ELFT> *C : Chunks) {
     C->writeTo(Buf);
+    const std::vector<typename ObjectFile<ELFT>::RelocMapInfo> &Relocs =
+        C->getFile()->getRelocations();
+    auto Hdr = C->getSectionHdr();
+    auto EObj = C->getFile()->getObj();
+    uint8_t *Base = Buf + C->getOutputSectionOff();
+    // Iterate over all relocation sections that apply to this section.
+    for (auto I = std::lower_bound(
+             Relocs.begin(), Relocs.end(),
+             typename ObjectFile<ELFT>::RelocMapInfo(Hdr, nullptr)),
+              E = Relocs.end();
+         I != E && I->Section == Hdr; ++I) {
+      // Only support RELA for now.
+      if (I->RelocSection->sh_type != SHT_RELA)
+        continue;
+      for (auto &RI : EObj->relas(I->RelocSection)) {
+        SymbolBody *Body = C->getFile()
+                               ->getSymbolBody(RI.getSymbol(EObj->isMips64EL()))
+                               ->getReplacement();
+        // Skip undefined weak for now.
+        if (isa<UndefinedWeak<ELFT>>(Body))
+          continue;
+        if (!isa<DefinedRegular<ELFT>>(Body))
+          error(Twine("Can't relocate symbol ") + Body->getName());
+        uintX_t Offset = RI.r_offset;
+        uint32_t Type = RI.getType(EObj->isMips64EL());
+        uintX_t P = this->getVA() + C->getOutputSectionOff();
+        uintX_t SymVA = getSymVA<ELFT>(cast<DefinedRegular<ELFT>>(Body));
+        switch (Type) {
+        case llvm::ELF::R_X86_64_PC32:
+          support::endian::write32le(Base + Offset,
+                                     SymVA + (RI.r_addend - (P + Offset)));
+          break;
+        default:
+          error(Twine("unrecognized reloc ") + Twine(Type));
+        }
+      }
+    }
+  }
 }
 
 template <bool Is64Bits>
@@ -235,44 +272,25 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
 
     auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
     ESym->st_name = Builder.getOffset(Name);
-    uint8_t Binding = 0;
+    uint8_t Binding;
     SymbolBody *Body = Sym->Body;
     uint8_t Type = 0;
-
-    const SectionChunk<ELFT> *Section = nullptr;
-    const Elf_Sym *InputSym = nullptr;
-
     switch (Body->kind()) {
     case SymbolBody::UndefinedKind:
     case SymbolBody::UndefinedSyntheticKind:
       llvm_unreachable("Should be defined by now");
-    case SymbolBody::DefinedWeakKind:
-    case SymbolBody::DefinedRegularKind: {
-      auto *Def = cast<Defined<ELFT>>(Body);
-      InputSym = &Def->Sym;
-      Section = &Def->Section;
+    case SymbolBody::DefinedRegularKind:
+      Binding = STB_GLOBAL;
+      Type = cast<DefinedRegular<ELFT>>(Body)->Sym.getType();
       break;
-    }
+    case SymbolBody::DefinedWeakKind:
     case SymbolBody::UndefinedWeakKind:
-      InputSym = &cast<ELFSymbolBody<ELFT>>(Body)->Sym;
+      Binding = STB_WEAK;
+      Type = cast<ELFSymbolBody<ELFT>>(Body)->Sym.getType();
       break;
     }
-
-    if (InputSym) {
-      Type = InputSym->getType();
-      Binding = InputSym->getBinding();
-    }
     ESym->setBindingAndType(Binding, Type);
 
-    if (Section) {
-      OutputSection<ELFT> *Out = Section->getOutputSection();
-      ESym->st_shndx = Out->getSectionIndex();
-      uintX_t VA = Out->getVA();
-      VA += Section->getOutputSectionOff();
-      VA += InputSym->st_value;
-      ESym->st_value = VA;
-    }
-
     Buf += sizeof(Elf_Sym);
   }
 }
@@ -328,8 +346,6 @@ template <class ELFT> void Writer<ELFT>::createSections() {
   for (const std::unique_ptr<ObjectFileBase> &FileB : Symtab.ObjectFiles) {
     auto &File = cast<ObjectFile<ELFT>>(*FileB);
     for (SectionChunk<ELFT> *C : File.getChunks()) {
-      if (!C)
-        continue;
       const Elf_Shdr *H = C->getSectionHdr();
       SectionKey<ELFT::Is64Bits> Key{C->getSectionName(), H->sh_type,
                                      H->sh_flags};
@@ -337,9 +353,10 @@ template <class ELFT> void Writer<ELFT>::createSections() {
       if (!Sec) {
         Sec = new (CAlloc.Allocate())
             OutputSection<ELFT>(Key.Name, Key.sh_type, Key.sh_flags);
-        addOutputSection(Sec);
+        OutputSections.push_back(Sec);
       }
       Sec->addChunk(C);
+      C->setOutputSection(Sec);
     }
   }
 }
@@ -361,8 +378,8 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
   std::stable_sort(OutputSections.begin(), OutputSections.end(),
                    compSec<ELFT::Is64Bits>);
 
-  addOutputSection(&SymTable);
-  addOutputSection(&StringTable);
+  OutputSections.push_back(&SymTable);
+  OutputSections.push_back(&StringTable);
   StringTableIndex = OutputSections.size();
   SymTable.setStringTableIndex(StringTableIndex);
 
diff --git a/test/COFF/dllorder.test b/test/COFF/dllorder.test
index 0b373bc..e684e58 100644
--- a/test/COFF/dllorder.test
+++ b/test/COFF/dllorder.test
@@ -6,10 +6,10 @@
 # RUN: rm -f %tlib/lib2.lib
 
 # RUN: echo EXPORTS sym1 > %t1.def
-# RUN: lib /nologo /machine:amd64 /def:%t1.def /out:%tlib\\lib1.lib > /dev/null
+# RUN: lib /nologo /def:%t1.def /out:%tlib\\lib1.lib > /dev/null
 
 # RUN: echo EXPORTS sym2 > %t2.def
-# RUN: lib /nologo /machine:amd64 /def:%t2.def /out:%tlib\\lib2.lib > /dev/null
+# RUN: lib /nologo /def:%t2.def /out:%tlib\\lib2.lib > /dev/null
 
 # RUN: lld-link /out:%t1.exe /entry:main /libpath:%tlib %t.obj /defaultlib:lib1 /defaultlib:lib2
 # RUN: lld-link /out:%t2.exe /entry:main /libpath:%tlib %t.obj /defaultlib:lib2 /defaultlib:lib1
diff --git a/test/elf2/Inputs/invalid-section-index.elf b/test/elf2/Inputs/invalid-section-index.elf
deleted file mode 100644
index ec5adcf..0000000
Binary files a/test/elf2/Inputs/invalid-section-index.elf and /dev/null differ
diff --git a/test/elf2/invalid-elf.test b/test/elf2/invalid-elf.test
index 0085b27..5b2bea3 100644
--- a/test/elf2/invalid-elf.test
+++ b/test/elf2/invalid-elf.test
@@ -13,7 +13,3 @@ INVALID-SYMTAB-SHINFO: Invalid sh_info in symbol table
 RUN: not lld -flavor gnu2 %p/Inputs/invalid-binding.elf -o %t2 2>&1 | \
 RUN:   FileCheck --check-prefix=INVALID-BINDING %s
 INVALID-BINDING: unexpected binding
-
-RUN: not lld -flavor gnu2 %p/Inputs/invalid-section-index.elf -o %t2 2>&1 | \
-RUN:   FileCheck --check-prefix=INVALID-SECTION-INDEX %s
-INVALID-SECTION-INDEX: Invalid section index
diff --git a/test/elf2/many-sections.s b/test/elf2/many-sections.s
deleted file mode 100644
index c9c113c..0000000
--- a/test/elf2/many-sections.s
+++ /dev/null
@@ -1,113 +0,0 @@
-// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t
-// RUN: llvm-readobj -t %t | FileCheck --check-prefix=LINKED %s
-
-// Verify that the symbol _start is in a section with an index >= SHN_LORESERVE.
-// CHECK:      Name: _start
-// CHECK-NEXT: Value: 0x0
-// CHECK-NEXT: Size: 0
-// CHECK-NEXT: Binding: Global
-// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: dm (0xFF00)
-
-
-// RUN: lld -flavor gnu2 %t -o %t2
-// RUN: llvm-readobj -t %t2 | FileCheck --check-prefix=LINKED %s
-
-// Test that _start is in the correct section.
-// LINKED:      Name: _start
-// LINKED-NEXT: Value: 0x0
-// LINKED-NEXT: Size: 0
-// LINKED-NEXT: Binding: Global
-// LINKED-NEXT: Type: None
-// LINKED-NEXT: Other: 0
-// LINKED-NEXT: Section: dm
-
-.macro gen_sections4 x
-        .section a\x
-        .section b\x
-        .section c\x
-        .section d\x
-.endm
-
-.macro gen_sections8 x
-        gen_sections4 a\x
-        gen_sections4 b\x
-.endm
-
-.macro gen_sections16 x
-        gen_sections8 a\x
-        gen_sections8 b\x
-.endm
-
-.macro gen_sections32 x
-        gen_sections16 a\x
-        gen_sections16 b\x
-.endm
-
-.macro gen_sections64 x
-        gen_sections32 a\x
-        gen_sections32 b\x
-.endm
-
-.macro gen_sections128 x
-        gen_sections64 a\x
-        gen_sections64 b\x
-.endm
-
-.macro gen_sections256 x
-        gen_sections128 a\x
-        gen_sections128 b\x
-.endm
-
-.macro gen_sections512 x
-        gen_sections256 a\x
-        gen_sections256 b\x
-.endm
-
-.macro gen_sections1024 x
-        gen_sections512 a\x
-        gen_sections512 b\x
-.endm
-
-.macro gen_sections2048 x
-        gen_sections1024 a\x
-        gen_sections1024 b\x
-.endm
-
-.macro gen_sections4096 x
-        gen_sections2048 a\x
-        gen_sections2048 b\x
-.endm
-
-.macro gen_sections8192 x
-        gen_sections4096 a\x
-        gen_sections4096 b\x
-.endm
-
-.macro gen_sections16384 x
-        gen_sections8192 a\x
-        gen_sections8192 b\x
-.endm
-
-.macro gen_sections32768 x
-        gen_sections16384 a\x
-        gen_sections16384 b\x
-.endm
-
-gen_sections32768 a
-gen_sections16384 b
-gen_sections8192 c
-gen_sections4096 d
-gen_sections2048 e
-gen_sections1024 f
-gen_sections512 g
-gen_sections128 h
-gen_sections64 i
-gen_sections32 j
-gen_sections16 k
-gen_sections8 l
-gen_sections4 m
-
-.global _start
-_start:
diff --git a/test/elf2/relocation.s b/test/elf2/relocation.s
new file mode 100644
index 0000000..37c4431
--- /dev/null
+++ b/test/elf2/relocation.s
@@ -0,0 +1,15 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: lld -flavor gnu2 %t -o %t2
+// RUN: llvm-objdump -d %t2 | FileCheck %s
+// REQUIRES: x86
+
+
+.section       .text,"ax", at progbits,unique,1
+.global _start
+_start:
+  call lulz
+
+.section       .text,"ax", at progbits,unique,2
+lulz:
+
+// CHECK: e8 00 00 00 00  callq   0
diff --git a/test/elf2/symbols.s b/test/elf2/symbols.s
index e2b2996..21d1d39 100644
--- a/test/elf2/symbols.s
+++ b/test/elf2/symbols.s
@@ -1,6 +1,6 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
 // RUN: lld -flavor gnu2 %t -o %t2
-// RUN: llvm-readobj -symbols -sections %t2 | FileCheck %s
+// RUN: llvm-readobj -symbols %t2 | FileCheck %s
 // REQUIRES: x86
 
 .type _start, @function
@@ -15,33 +15,6 @@ foo:
 .weak bar
 .long bar
 
-.section        foobar,"a", at nobits,unique,1
-.globl zed
-zed:
-        .long 0
-.globl zed2
-zed2:
-.long 0
-
-.section        foobar,"a", at nobits,unique,2
-.globl zed3
-zed3:
-
-// CHECK:      Name: .text
-// CHECK-NEXT: Type: SHT_PROGBITS
-// CHECK-NEXT: Flags [
-// CHECK-NEXT:   SHF_ALLOC
-// CHECK-NEXT:   SHF_EXECINSTR
-// CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x1000
-
-// CHECK:      Name: foobar
-// CHECK-NEXT: Type: SHT_NOBITS
-// CHECK-NEXT: Flags [
-// CHECK-NEXT:   SHF_ALLOC
-// CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x1004
-
 // CHECK:      Symbols [
 // CHECK-NEXT:   Symbol {
 // CHECK-NEXT:     Name:  (0)
@@ -53,31 +26,13 @@ zed3:
 // CHECK-NEXT:     Section: Undefined (0x0)
 // CHECK-NEXT:   }
 // CHECK-NEXT:   Symbol {
-// CHECK-NEXT:     Name: zed
-// CHECK-NEXT:     Value: 0x1004
-// CHECK-NEXT:     Size: 0
-// CHECK-NEXT:     Binding: Global (0x1)
-// CHECK-NEXT:     Type: None
-// CHECK-NEXT:     Other: 0
-// CHECK-NEXT:     Section: foobar
-// CHECK-NEXT:   }
-// CHECK-NEXT:   Symbol {
-// CHECK-NEXT:     Name: zed3
-// CHECK-NEXT:     Value: 0x100C
-// CHECK-NEXT:     Size: 0
-// CHECK-NEXT:     Binding: Global
-// CHECK-NEXT:     Type: None
-// CHECK-NEXT:     Other: 0
-// CHECK-NEXT:     Section: foobar
-// CHECK-NEXT:   }
-// CHECK-NEXT:   Symbol {
 // CHECK-NEXT:     Name: _start
-// CHECK-NEXT:     Value: 0x1000
+// CHECK-NEXT:     Value: 0x0
 // CHECK-NEXT:     Size: 0
 // CHECK-NEXT:     Binding: Global (0x1)
 // CHECK-NEXT:     Type: Function
 // CHECK-NEXT:     Other: 0
-// CHECK-NEXT:     Section: .text
+// CHECK-NEXT:     Section: Undefined (0x0)
 // CHECK-NEXT:   }
 // CHECK-NEXT:   Symbol {
 // CHECK-NEXT:     Name: bar
@@ -90,20 +45,11 @@ zed3:
 // CHECK-NEXT:   }
 // CHECK-NEXT:   Symbol {
 // CHECK-NEXT:     Name: foo
-// CHECK-NEXT:     Value: 0x1000
+// CHECK-NEXT:     Value: 0x0
 // CHECK-NEXT:     Size: 0
 // CHECK-NEXT:     Binding: Weak (0x2)
 // CHECK-NEXT:     Type: Object
 // CHECK-NEXT:     Other: 0
-// CHECK-NEXT:     Section: .text
-// CHECK-NEXT:   }
-// CHECK-NEXT:   Symbol {
-// CHECK-NEXT:     Name: zed2
-// CHECK-NEXT:     Value: 0x1008
-// CHECK-NEXT:     Size: 0
-// CHECK-NEXT:     Binding: Global
-// CHECK-NEXT:     Type: None
-// CHECK-NEXT:     Other: 0
-// CHECK-NEXT:     Section: foobar
+// CHECK-NEXT:     Section: Undefined (0x0)
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]


More information about the llvm-commits mailing list