<div dir="ltr">This patch surprised me. I personally believe this is a right direction, but what's the future plan of this "v2" ELF linker? I think we had to have a discuss before landing this important patch.<div><br></div><div>This is pretty much a direct translation of my COFF linker, and it contains many COFF-isms that don't fit to ELF. Not sure if you actually intended to submit this at this moment?<br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jul 13, 2015 at 4:48 PM, Michael J. Spencer <span dir="ltr"><<a href="mailto:bigcheesegs@gmail.com" target="_blank">bigcheesegs@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: mspencer<br>
Date: Mon Jul 13 18:48:06 2015<br>
New Revision: 242088<br>
<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D242088-26view-3Drev&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=jk4w8tujetTUY7lAMeyj1EwB0Kxc72-weWoKpBJrzmM&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=242088&view=rev</a><br>
Log:<br>
Initial ELF port.<br>
<br>
This is a direct port of the new PE/COFF linker to ELF.<br>
<br>
It can take a single object file and generate a valid executable that executes at the first byte in the text section.<br>
<br>
Added:<br>
    lld/trunk/ELF/<br>
    lld/trunk/ELF/CMakeLists.txt<br>
    lld/trunk/ELF/Chunks.cpp<br>
    lld/trunk/ELF/Chunks.h<br>
    lld/trunk/ELF/Config.h<br>
    lld/trunk/ELF/Driver.cpp<br>
    lld/trunk/ELF/Driver.h<br>
    lld/trunk/ELF/DriverUtils.cpp<br>
    lld/trunk/ELF/Error.h<br>
    lld/trunk/ELF/InputFiles.cpp<br>
    lld/trunk/ELF/InputFiles.h<br>
    lld/trunk/ELF/Options.td<br>
    lld/trunk/ELF/README.md<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/Writer.cpp<br>
    lld/trunk/ELF/Writer.h<br>
    lld/trunk/test/elfv2/<br>
    lld/trunk/test/elfv2/basic.test<br>
Modified:<br>
    lld/trunk/CMakeLists.txt<br>
    lld/trunk/include/lld/Driver/Driver.h<br>
    lld/trunk/lib/Driver/UniversalDriver.cpp<br>
    lld/trunk/tools/lld/CMakeLists.txt<br>
    lld/trunk/unittests/DriverTests/CMakeLists.txt<br>
<br>
Modified: lld/trunk/CMakeLists.txt<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_CMakeLists.txt-3Frev-3D242088-26r1-3D242087-26r2-3D242088-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=DMHhawrNcCMDxqWnoqmlnrlGMpH3nSuAX0mW69a9gGY&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/CMakeLists.txt?rev=242088&r1=242087&r2=242088&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/CMakeLists.txt (original)<br>
+++ lld/trunk/CMakeLists.txt Mon Jul 13 18:48:06 2015<br>
@@ -97,3 +97,4 @@ endif()<br>
<br>
 add_subdirectory(docs)<br>
 add_subdirectory(COFF)<br>
+add_subdirectory(ELF)<br>
<br>
Added: lld/trunk/ELF/CMakeLists.txt<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_CMakeLists.txt-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=GtcKcLZrX4volJqUD2khWTH6FWDAlGzeNyFrkti8pYQ&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/CMakeLists.txt (added)<br>
+++ lld/trunk/ELF/CMakeLists.txt Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,23 @@<br>
+set(LLVM_TARGET_DEFINITIONS Options.td)<br>
+tablegen(LLVM Options.inc -gen-opt-parser-defs)<br>
+add_public_tablegen_target(ELFOptionsTableGen)<br>
+<br>
+add_llvm_library(lldELF2<br>
+  Chunks.cpp<br>
+  Driver.cpp<br>
+  DriverUtils.cpp<br>
+  InputFiles.cpp<br>
+  SymbolTable.cpp<br>
+  Symbols.cpp<br>
+  Writer.cpp<br>
+<br>
+  LINK_COMPONENTS<br>
+  ${LLVM_TARGETS_TO_BUILD}<br>
+  Core<br>
+  LTO<br>
+  MC<br>
+  MCDisassembler<br>
+  Support<br>
+  )<br>
+<br>
+add_dependencies(lldELF2 ELFOptionsTableGen)<br>
<br>
Added: lld/trunk/ELF/Chunks.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_Chunks.cpp-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=B2tfmncNsRoVKhKIMJ0mTg-bOCH-7khbgt16nQoC47E&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Chunks.cpp?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Chunks.cpp (added)<br>
+++ lld/trunk/ELF/Chunks.cpp Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,125 @@<br>
+//===- Chunks.cpp ---------------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "Chunks.h"<br>
+#include "InputFiles.h"<br>
+#include "Writer.h"<br>
+#include "llvm/ADT/STLExtras.h"<br>
+#include "llvm/Support/Debug.h"<br>
+#include "llvm/Support/Endian.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+<br>
+using namespace llvm;<br>
+using namespace llvm::object;<br>
+using namespace llvm::support::endian;<br>
+using namespace llvm::ELF;<br>
+<br>
+using namespace lld;<br>
+using namespace lld::elfv2;<br>
+<br>
+template <class ELFT><br>
+SectionChunk<ELFT>::SectionChunk(elfv2::ObjectFile<ELFT> *F, const Elf_Shdr *H,<br>
+                                 uint32_t SI)<br>
+    : File(F), Header(H), SectionIndex(SI) {<br>
+  // Initialize SectionName.<br>
+  SectionName = *File->getObj()->getSectionName(Header);<br>
+<br>
+  Align = Header->sh_addralign;<br>
+<br>
+  // When a new chunk is created, we don't if if it's going to make it<br>
+  // to the final output. Initially all sections are unmarked in terms<br>
+  // of garbage collection. The writer will call markLive() to mark<br>
+  // all reachable section chunks.<br>
+  Live = false;<br>
+<br>
+  Root = true;<br>
+}<br>
+<br>
+template <class ELFT> void SectionChunk<ELFT>::writeTo(uint8_t *Buf) {<br>
+  if (!hasData())<br>
+    return;<br>
+  // Copy section contents from source object file to output file.<br>
+  ArrayRef<uint8_t> Data = *File->getObj()->getSectionContents(Header);<br>
+  memcpy(Buf + FileOff, Data.data(), Data.size());<br>
+<br>
+  // FIXME: Relocations<br>
+}<br>
+<br>
+template <class ELFT> void SectionChunk<ELFT>::mark() {<br>
+  assert(!Live);<br>
+  Live = true;<br>
+<br>
+  // Mark all symbols listed in the relocation table for this section.<br>
+  // FIXME: Relocations<br>
+}<br>
+<br>
+static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); }<br>
+static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }<br>
+static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); }<br>
+<br>
+template <class ELFT><br>
+void SectionChunk<ELFT>::applyReloc(uint8_t *Buf, const Elf_Rela *Rel) {<br>
+  // FIXME: Relocations<br>
+}<br>
+<br>
+template <class ELFT><br>
+void SectionChunk<ELFT>::applyReloc(uint8_t *Buf, const Elf_Rel *Rel) {}<br>
+<br>
+template <class ELFT> bool SectionChunk<ELFT>::hasData() const {<br>
+  return Header->sh_type != SHT_NOBITS;<br>
+}<br>
+<br>
+template <class ELFT> uint32_t SectionChunk<ELFT>::getFlags() const {<br>
+  return Header->sh_flags;<br>
+}<br>
+<br>
+// Prints "Discarded <symbol>" for all external function symbols.<br>
+template <class ELFT> void SectionChunk<ELFT>::printDiscardedMessage() {<br>
+  auto Obj = File->getObj();<br>
+<br>
+  for (auto &&Sym : Obj->symbols()) {<br>
+    auto Sec = Obj->getSection(&Sym);<br>
+    if (Sec && *Sec != Header)<br>
+      continue;<br>
+    if (Sym.getType() != STT_FUNC)<br>
+      continue;<br>
+    if (auto Name = Obj->getStaticSymbolName(&Sym)) {<br>
+      llvm::outs() << "Discarded " << *Name << " from " << File->getShortName()<br>
+                   << "\n";<br>
+    }<br>
+  }<br>
+}<br>
+<br>
+template <class ELFT><br>
+const llvm::object::Elf_Shdr_Impl<ELFT> *SectionChunk<ELFT>::getSectionHdr() {<br>
+  return Header;<br>
+}<br>
+<br>
+template <class ELFT><br>
+CommonChunk<ELFT>::CommonChunk(const Elf_Sym *S)<br>
+    : Sym(S) {<br>
+  // Alignment is a section attribute, but common symbols don't<br>
+  // belong to any section. How do we know common data alignments?<br>
+  // Needs investigating. For now, we set a large number as an alignment.<br>
+  Align = 16;<br>
+}<br>
+<br>
+template <class ELFT> uint32_t CommonChunk<ELFT>::getFlags() const {<br>
+  return PF_R | PF_W;<br>
+}<br>
+<br>
+template class SectionChunk<llvm::object::ELF32LE>;<br>
+template class SectionChunk<llvm::object::ELF32BE>;<br>
+template class SectionChunk<llvm::object::ELF64LE>;<br>
+template class SectionChunk<llvm::object::ELF64BE>;<br>
+<br>
+template class CommonChunk<llvm::object::ELF32LE>;<br>
+template class CommonChunk<llvm::object::ELF32BE>;<br>
+template class CommonChunk<llvm::object::ELF64LE>;<br>
+template class CommonChunk<llvm::object::ELF64BE>;<br>
<br>
Added: lld/trunk/ELF/Chunks.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_Chunks.h-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=TRQSeAh0wwnHANYP-XN7BQsvFkQX4NxsaV8W3SGvEGU&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Chunks.h?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Chunks.h (added)<br>
+++ lld/trunk/ELF/Chunks.h Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,152 @@<br>
+//===- Chunks.h -----------------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLD_ELF_CHUNKS_H<br>
+#define LLD_ELF_CHUNKS_H<br>
+<br>
+#include "lld/Core/LLVM.h"<br>
+#include "llvm/ADT/ArrayRef.h"<br>
+#include "llvm/Object/ELF.h"<br>
+#include <map><br>
+#include <vector><br>
+<br>
+namespace lld {<br>
+namespace elfv2 {<br>
+<br>
+class Defined;<br>
+template <class ELFT> class ObjectFile;<br>
+class OutputSection;<br>
+<br>
+// A Chunk represents a chunk of data that will occupy space in the<br>
+// output (if the resolver chose that). It may or may not be backed by<br>
+// a section of an input file. It could be linker-created data, or<br>
+// doesn't even have actual data (if common or bss).<br>
+class Chunk {<br>
+public:<br>
+  virtual ~Chunk() = default;<br>
+<br>
+  // Returns the size of this chunk (even if this is a common or BSS.)<br>
+  virtual size_t getSize() const = 0;<br>
+<br>
+  // Write this chunk to a mmap'ed file, assuming Buf is pointing to<br>
+  // beginning of the file. Because this function may use VA values<br>
+  // of other chunks for relocations, you need to set them properly<br>
+  // before calling this function.<br>
+  virtual void writeTo(uint8_t *Buf) {}<br>
+<br>
+  // The writer sets and uses the addresses.<br>
+  uint64_t getVA() { return VA; }<br>
+  uint64_t getFileOff() { return FileOff; }<br>
+  uint32_t getAlign() { return Align; }<br>
+  void setVA(uint64_t V) { VA = V; }<br>
+  void setFileOff(uint64_t V) { FileOff = V; }<br>
+<br>
+  // Returns true if this has non-zero data. BSS chunks return<br>
+  // false. If false is returned, the space occupied by this chunk<br>
+  // will be filled with zeros.<br>
+  virtual bool hasData() const { return true; }<br>
+<br>
+  // Returns readable/writable/executable bits.<br>
+  virtual uint32_t getFlags() const { return 0; }<br>
+<br>
+  // Returns the section name if this is a section chunk.<br>
+  // It is illegal to call this function on non-section chunks.<br>
+  virtual StringRef getSectionName() const {<br>
+    llvm_unreachable("unimplemented getSectionName");<br>
+  }<br>
+<br>
+  // Called if the garbage collector decides to not include this chunk<br>
+  // in a final output. It's supposed to print out a log message to stdout.<br>
+  // It is illegal to call this function on non-section chunks because<br>
+  // only section chunks are subject of garbage collection.<br>
+  virtual void printDiscardedMessage() {<br>
+    llvm_unreachable("unimplemented printDiscardedMessage");<br>
+  }<br>
+<br>
+  // Used by the garbage collector.<br>
+  bool isRoot() { return Root; }<br>
+  bool isLive() { return Live; }<br>
+  void markLive() {<br>
+    if (!Live)<br>
+      mark();<br>
+  }<br>
+<br>
+  // An output section has pointers to chunks in the section, and each<br>
+  // chunk has a back pointer to an output section.<br>
+  void setOutputSection(OutputSection *O) { Out = O; }<br>
+  OutputSection *getOutputSection() { return Out; }<br>
+<br>
+protected:<br>
+  // The VA of this chunk in the output. The writer sets a value.<br>
+  uint64_t VA = 0;<br>
+<br>
+  // The offset from beginning of the output file. The writer sets a value.<br>
+  uint64_t FileOff = 0;<br>
+<br>
+  // The output section for this chunk.<br>
+  OutputSection *Out = nullptr;<br>
+<br>
+  // The alignment of this chunk. The writer uses the value.<br>
+  uint32_t Align = 1;<br>
+<br>
+  // Used by the garbage collector.<br>
+  virtual void mark() {}<br>
+  bool Live = true;<br>
+  bool Root = false;<br>
+};<br>
+<br>
+// A chunk corresponding a section of an input file.<br>
+template <class ELFT> class SectionChunk : public Chunk {<br>
+  typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;<br>
+  typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;<br>
+  typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;<br>
+<br>
+public:<br>
+  SectionChunk(ObjectFile<ELFT> *File, const Elf_Shdr *Header,<br>
+               uint32_t SectionIndex);<br>
+  size_t getSize() const override { return Header->sh_size; }<br>
+  void writeTo(uint8_t *Buf) override;<br>
+  bool hasData() const override;<br>
+  uint32_t getFlags() const override;<br>
+  StringRef getSectionName() const override { return SectionName; }<br>
+  void printDiscardedMessage() override;<br>
+<br>
+private:<br>
+  void mark() override;<br>
+  const Elf_Shdr *getSectionHdr();<br>
+  void applyReloc(uint8_t *Buf, const Elf_Rela *Rel);<br>
+  void applyReloc(uint8_t *Buf, const Elf_Rel *Rel);<br>
+<br>
+  // A file this chunk was created from.<br>
+  ObjectFile<ELFT> *File;<br>
+<br>
+  const Elf_Shdr *Header;<br>
+  uint32_t SectionIndex;<br>
+  StringRef SectionName;<br>
+};<br>
+<br>
+// A chunk for common symbols. Common chunks don't have actual data.<br>
+template <class ELFT> class CommonChunk : public Chunk {<br>
+  typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;<br>
+<br>
+public:<br>
+  CommonChunk(const Elf_Sym *Sym);<br>
+  size_t getSize() const override { return Sym->getValue(); }<br>
+  bool hasData() const override { return false; }<br>
+  uint32_t getFlags() const override;<br>
+  StringRef getSectionName() const override { return ".bss"; }<br>
+<br>
+private:<br>
+  const Elf_Sym *Sym;<br>
+};<br>
+<br>
+} // namespace elfv2<br>
+} // namespace lld<br>
+<br>
+#endif<br>
<br>
Added: lld/trunk/ELF/Config.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_Config.h-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=d4nQWyIOr4_Yo0KV1cEQWDD8zZYskZZe2JMh5eeqUTE&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Config.h (added)<br>
+++ lld/trunk/ELF/Config.h Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,40 @@<br>
+//===- Config.h -----------------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLD_ELF_CONFIG_H<br>
+#define LLD_ELF_CONFIG_H<br>
+<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/Object/ELF.h"<br>
+#include <set><br>
+#include <string><br>
+<br>
+namespace lld {<br>
+namespace elfv2 {<br>
+<br>
+using llvm::StringRef;<br>
+<br>
+class Configuration {<br>
+public:<br>
+  int MachineArchitecture = llvm::ELF::EM_X86_64;<br>
+  bool Verbose = false;<br>
+  StringRef EntryName;<br>
+  std::string OutputFile;<br>
+  bool DoGC = true;<br>
+<br>
+  // Symbols in this set are considered as live by the garbage collector.<br>
+  std::set<StringRef> GCRoots;<br>
+};<br>
+<br>
+extern Configuration *Config;<br>
+<br>
+} // namespace elfv2<br>
+} // namespace lld<br>
+<br>
+#endif<br>
<br>
Added: lld/trunk/ELF/Driver.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_Driver.cpp-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=14waZ6ERA7sWBhN_7r98lsm6F1VhnKBv0s0pTQim2Yc&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Driver.cpp (added)<br>
+++ lld/trunk/ELF/Driver.cpp Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,240 @@<br>
+//===- Driver.cpp ---------------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "Config.h"<br>
+#include "Driver.h"<br>
+#include "InputFiles.h"<br>
+#include "SymbolTable.h"<br>
+#include "Writer.h"<br>
+#include "llvm/ADT/Optional.h"<br>
+#include "llvm/ADT/STLExtras.h"<br>
+#include "llvm/ADT/StringSwitch.h"<br>
+#include "llvm/LibDriver/LibDriver.h"<br>
+#include "llvm/Option/Arg.h"<br>
+#include "llvm/Option/ArgList.h"<br>
+#include "llvm/Option/Option.h"<br>
+#include "llvm/Support/CommandLine.h"<br>
+#include "llvm/Support/Debug.h"<br>
+#include "llvm/Support/Path.h"<br>
+#include "llvm/Support/Process.h"<br>
+#include "llvm/Support/TargetSelect.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+#include <algorithm><br>
+#include <memory><br>
+<br>
+using namespace llvm;<br>
+using llvm::sys::fs::file_magic;<br>
+using llvm::sys::fs::identify_magic;<br>
+<br>
+using namespace lld;<br>
+using namespace lld::elfv2;<br>
+<br>
+namespace lld {<br>
+namespace elfv2 {<br>
+Configuration *Config;<br>
+LinkerDriver *Driver;<br>
+<br>
+bool link(llvm::ArrayRef<const char *> Args) {<br>
+  auto C = make_unique<Configuration>();<br>
+  Config = C.get();<br>
+  auto D = make_unique<LinkerDriver>();<br>
+  Driver = D.get();<br>
+  return Driver->link(Args);<br>
+}<br>
+}<br>
+}<br>
+<br>
+// Drop directory components and replace extension with ".exe".<br>
+static std::string getOutputPath(StringRef Path) {<br>
+  auto P = Path.find_last_of("\\/");<br>
+  StringRef S = (P == StringRef::npos) ? Path : Path.substr(P + 1);<br>
+  return (S.substr(0, S.rfind('.')) + ".exe").str();<br>
+}<br>
+<br>
+// Opens a file. Path has to be resolved already.<br>
+// Newly created memory buffers are owned by this driver.<br>
+ErrorOr<MemoryBufferRef> LinkerDriver::openFile(StringRef Path) {<br>
+  auto MBOrErr = MemoryBuffer::getFile(Path);<br>
+  if (auto EC = MBOrErr.getError())<br>
+    return EC;<br>
+  std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get());<br>
+  MemoryBufferRef MBRef = MB->getMemBufferRef();<br>
+  OwningMBs.push_back(std::move(MB)); // take ownership<br>
+  return MBRef;<br>
+}<br>
+<br>
+static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB) {<br>
+  // File type is detected by contents, not by file extension.<br>
+  file_magic Magic = identify_magic(MB.getBuffer());<br>
+  if (Magic == file_magic::archive)<br>
+    return std::unique_ptr<InputFile>(new ArchiveFile(MB));<br>
+  if (Magic == file_magic::bitcode)<br>
+    return std::unique_ptr<InputFile>(new BitcodeFile(MB));<br>
+  if (Config->OutputFile == "")<br>
+    Config->OutputFile = getOutputPath(MB.getBufferIdentifier());<br>
+  return std::unique_ptr<InputFile>(new ObjectFile<llvm::object::ELF64LE>(MB));<br>
+}<br>
+<br>
+// Find file from search paths. You can omit ".obj", this function takes<br>
+// care of that. Note that the returned path is not guaranteed to exist.<br>
+StringRef LinkerDriver::doFindFile(StringRef Filename) {<br>
+  bool hasPathSep = (Filename.find_first_of("/\\") != StringRef::npos);<br>
+  if (hasPathSep)<br>
+    return Filename;<br>
+  bool hasExt = (Filename.find('.') != StringRef::npos);<br>
+  for (StringRef Dir : SearchPaths) {<br>
+    SmallString<128> Path = Dir;<br>
+    llvm::sys::path::append(Path, Filename);<br>
+    if (llvm::sys::fs::exists(Path.str()))<br>
+      return Alloc.save(Path.str());<br>
+    if (!hasExt) {<br>
+      Path.append(".obj");<br>
+      if (llvm::sys::fs::exists(Path.str()))<br>
+        return Alloc.save(Path.str());<br>
+    }<br>
+  }<br>
+  return Filename;<br>
+}<br>
+<br>
+// Resolves a file path. This never returns the same path<br>
+// (in that case, it returns None).<br>
+Optional<StringRef> LinkerDriver::findFile(StringRef Filename) {<br>
+  StringRef Path = doFindFile(Filename);<br>
+  bool Seen = !VisitedFiles.insert(Path.lower()).second;<br>
+  if (Seen)<br>
+    return None;<br>
+  return Path;<br>
+}<br>
+<br>
+// Find library file from search path.<br>
+StringRef LinkerDriver::doFindLib(StringRef Filename) {<br>
+  // Add ".lib" to Filename if that has no file extension.<br>
+  bool hasExt = (Filename.find('.') != StringRef::npos);<br>
+  if (!hasExt)<br>
+    Filename = Alloc.save(Filename + ".lib");<br>
+  return doFindFile(Filename);<br>
+}<br>
+<br>
+// Resolves a library path. /nodefaultlib options are taken into<br>
+// consideration. This never returns the same path (in that case,<br>
+// it returns None).<br>
+Optional<StringRef> LinkerDriver::findLib(StringRef Filename) {<br>
+  StringRef Path = doFindLib(Filename);<br>
+  bool Seen = !VisitedFiles.insert(Path.lower()).second;<br>
+  if (Seen)<br>
+    return None;<br>
+  return Path;<br>
+}<br>
+<br>
+bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {<br>
+  // Needed for LTO.<br>
+  llvm::InitializeAllTargetInfos();<br>
+  llvm::InitializeAllTargets();<br>
+  llvm::InitializeAllTargetMCs();<br>
+  llvm::InitializeAllAsmParsers();<br>
+  llvm::InitializeAllAsmPrinters();<br>
+  llvm::InitializeAllDisassemblers();<br>
+<br>
+  // Parse command line options.<br>
+  auto ArgsOrErr = Parser.parse(ArgsArr);<br>
+  if (auto EC = ArgsOrErr.getError()) {<br>
+    llvm::errs() << EC.message() << "\n";<br>
+    return false;<br>
+  }<br>
+  llvm::opt::InputArgList Args = std::move(ArgsOrErr.get());<br>
+<br>
+  // Handle /help<br>
+  if (Args.hasArg(OPT_help)) {<br>
+    printHelp(ArgsArr[0]);<br>
+    return true;<br>
+  }<br>
+<br>
+  if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end()) {<br>
+    llvm::errs() << "no input files.\n";<br>
+    return false;<br>
+  }<br>
+<br>
+  // Construct search path list.<br>
+  SearchPaths.push_back("");<br>
+  for (auto *Arg : Args.filtered(OPT_L))<br>
+    SearchPaths.push_back(Arg->getValue());<br>
+<br>
+  // Handle /out<br>
+  if (auto *Arg = Args.getLastArg(OPT_output))<br>
+    Config->OutputFile = Arg->getValue();<br>
+<br>
+  // Handle /entry<br>
+  if (auto *Arg = Args.getLastArg(OPT_e))<br>
+    Config->EntryName = Arg->getValue();<br>
+<br>
+  // Create a list of input files. Files can be given as arguments<br>
+  // for /defaultlib option.<br>
+  std::vector<StringRef> InputPaths;<br>
+  std::vector<MemoryBufferRef> Inputs;<br>
+  for (auto *Arg : Args.filtered(OPT_INPUT))<br>
+    if (Optional<StringRef> Path = findFile(Arg->getValue()))<br>
+      InputPaths.push_back(*Path);<br>
+<br>
+  for (StringRef Path : InputPaths) {<br>
+    ErrorOr<MemoryBufferRef> MBOrErr = openFile(Path);<br>
+    if (auto EC = MBOrErr.getError()) {<br>
+      llvm::errs() << "cannot open " << Path << ": " << EC.message() << "\n";<br>
+      return false;<br>
+    }<br>
+    Inputs.push_back(MBOrErr.get());<br>
+  }<br>
+<br>
+  // Create a symbol table.<br>
+  SymbolTable<llvm::object::ELF64LE> Symtab;<br>
+<br>
+  // Parse all input files and put all symbols to the symbol table.<br>
+  // The symbol table will take care of name resolution.<br>
+  for (MemoryBufferRef MB : Inputs) {<br>
+    std::unique_ptr<InputFile> File = createFile(MB);<br>
+    if (Config->Verbose)<br>
+      llvm::outs() << "Reading " << File->getName() << "\n";<br>
+    if (auto EC = Symtab.addFile(std::move(File))) {<br>
+      llvm::errs() << MB.getBufferIdentifier() << ": " << EC.message() << "\n";<br>
+      return false;<br>
+    }<br>
+  }<br>
+<br>
+  // Resolve auxiliary symbols until converge.<br>
+  // (Trying to resolve a symbol may trigger a Lazy symbol to load a new file.<br>
+  // A new file may contain a directive section to add new command line options.<br>
+  // That's why we have to repeat until converge.)<br>
+  /*for (;;) {<br>
+    size_t Ver = Symtab.getVersion();<br>
+<br>
+    if (Ver == Symtab.getVersion())<br>
+      break;<br>
+  }*/<br>
+<br>
+  // Make sure we have resolved all symbols.<br>
+  if (Symtab.reportRemainingUndefines())<br>
+    return false;<br>
+<br>
+  // Initialize a list of GC root.<br>
+  Config->GCRoots.insert(Config->EntryName);<br>
+<br>
+  // Do LTO by compiling bitcode input files to a native ELF file<br>
+  // then link that file.<br>
+  if (auto EC = Symtab.addCombinedLTOObject()) {<br>
+    llvm::errs() << EC.message() << "\n";<br>
+    return false;<br>
+  }<br>
+<br>
+  // Write the result.<br>
+  Writer<llvm::object::ELF64LE> Out(&Symtab);<br>
+  if (auto EC = Out.write(Config->OutputFile)) {<br>
+    llvm::errs() << EC.message() << "\n";<br>
+    return false;<br>
+  }<br>
+  return true;<br>
+}<br>
<br>
Added: lld/trunk/ELF/Driver.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_Driver.h-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=cPp3zC2JlIdVODuOWnvF6tqdUo7vQq1EYtnNp5pBZYA&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.h?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Driver.h (added)<br>
+++ lld/trunk/ELF/Driver.h Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,102 @@<br>
+//===- Driver.h -----------------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLD_ELF_DRIVER_H<br>
+#define LLD_ELF_DRIVER_H<br>
+<br>
+#include "lld/Core/LLVM.h"<br>
+#include "llvm/ADT/Optional.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/Object/ELF.h"<br>
+#include "llvm/Option/Arg.h"<br>
+#include "llvm/Option/ArgList.h"<br>
+#include "llvm/Support/StringSaver.h"<br>
+#include <memory><br>
+#include <set><br>
+#include <system_error><br>
+#include <vector><br>
+<br>
+namespace lld {<br>
+namespace elfv2 {<br>
+<br>
+class LinkerDriver;<br>
+extern LinkerDriver *Driver;<br>
+<br>
+using llvm::Optional;<br>
+class InputFile;<br>
+<br>
+// Entry point of the ELF linker.<br>
+bool link(llvm::ArrayRef<const char *> Args);<br>
+<br>
+class ArgParser {<br>
+public:<br>
+  ArgParser() : Alloc(AllocAux) {}<br>
+  // Parses command line options.<br>
+  ErrorOr<llvm::opt::InputArgList> parse(llvm::ArrayRef<const char *> Args);<br>
+<br>
+  // Tokenizes a given string and then parses as command line options.<br>
+  ErrorOr<llvm::opt::InputArgList> parse(StringRef S) {<br>
+    return parse(tokenize(S));<br>
+  }<br>
+<br>
+private:<br>
+  ErrorOr<llvm::opt::InputArgList> parse(std::vector<const char *> Argv);<br>
+<br>
+  std::vector<const char *> tokenize(StringRef S);<br>
+<br>
+  ErrorOr<std::vector<const char *>><br>
+  replaceResponseFiles(std::vector<const char *>);<br>
+<br>
+  llvm::BumpPtrAllocator AllocAux;<br>
+  llvm::BumpPtrStringSaver Alloc;<br>
+};<br>
+<br>
+class LinkerDriver {<br>
+public:<br>
+  LinkerDriver() : Alloc(AllocAux) {}<br>
+  bool link(llvm::ArrayRef<const char *> Args);<br>
+<br>
+private:<br>
+  llvm::BumpPtrAllocator AllocAux;<br>
+  llvm::BumpPtrStringSaver Alloc;<br>
+  ArgParser Parser;<br>
+<br>
+  // Opens a file. Path has to be resolved already.<br>
+  ErrorOr<MemoryBufferRef> openFile(StringRef Path);<br>
+<br>
+  // Searches a file from search paths.<br>
+  Optional<StringRef> findFile(StringRef Filename);<br>
+  Optional<StringRef> findLib(StringRef Filename);<br>
+  StringRef doFindFile(StringRef Filename);<br>
+  StringRef doFindLib(StringRef Filename);<br>
+<br>
+  std::vector<StringRef> SearchPaths;<br>
+  std::set<std::string> VisitedFiles;<br>
+<br>
+  // Driver is the owner of all opened files.<br>
+  // InputFiles have MemoryBufferRefs to them.<br>
+  std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;<br>
+};<br>
+<br>
+// Functions below this line are defined in DriverUtils.cpp.<br>
+<br>
+void printHelp(const char *Argv0);<br>
+<br>
+// Create enum with OPT_xxx values for each option in Options.td<br>
+enum {<br>
+  OPT_INVALID = 0,<br>
+#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID,<br>
+#include "Options.inc"<br>
+#undef OPTION<br>
+};<br>
+<br>
+} // namespace elfv2<br>
+} // namespace lld<br>
+<br>
+#endif<br>
<br>
Added: lld/trunk/ELF/DriverUtils.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_DriverUtils.cpp-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=UgKhxZlDLqZytSWOaGTSUO7__BXY6IeCGbpXZpMDTPU&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/DriverUtils.cpp?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/DriverUtils.cpp (added)<br>
+++ lld/trunk/ELF/DriverUtils.cpp Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,121 @@<br>
+//===- DriverUtils.cpp ----------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file contains utility functions for the driver. Because there<br>
+// are so many small functions, we created this separate file to make<br>
+// Driver.cpp less cluttered.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "Config.h"<br>
+#include "Driver.h"<br>
+#include "Error.h"<br>
+#include "llvm/ADT/Optional.h"<br>
+#include "llvm/ADT/STLExtras.h"<br>
+#include "llvm/ADT/StringSwitch.h"<br>
+#include "llvm/Option/Arg.h"<br>
+#include "llvm/Option/ArgList.h"<br>
+#include "llvm/Option/Option.h"<br>
+#include "llvm/Support/CommandLine.h"<br>
+#include "llvm/Support/Process.h"<br>
+#include "llvm/Support/Program.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+#include <memory><br>
+<br>
+using namespace llvm;<br>
+using llvm::cl::ExpandResponseFiles;<br>
+using llvm::cl::TokenizeWindowsCommandLine;<br>
+using llvm::sys::Process;<br>
+<br>
+using namespace lld;<br>
+using namespace lld::elfv2;<br>
+<br>
+// Create OptTable<br>
+<br>
+// Create prefix string literals used in Options.td<br>
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;<br>
+#include "Options.inc"<br>
+#undef PREFIX<br>
+<br>
+// Create table mapping all options defined in Options.td<br>
+static const llvm::opt::OptTable::Info infoTable[] = {<br>
+#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10)            \<br>
+  {                                                                            \<br>
+    X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7,         \<br>
+        OPT_##GROUP, OPT_##ALIAS, X6                                           \<br>
+  }                                                                            \<br>
+  ,<br>
+#include "Options.inc"<br>
+#undef OPTION<br>
+};<br>
+<br>
+class ELFOptTable : public llvm::opt::OptTable {<br>
+public:<br>
+  ELFOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)) {}<br>
+};<br>
+<br>
+// Parses a given list of options.<br>
+ErrorOr<llvm::opt::InputArgList><br>
+ArgParser::parse(std::vector<const char *> Argv) {<br>
+  // First, replace respnose files (@<file>-style options).<br>
+  auto ArgvOrErr = replaceResponseFiles(Argv);<br>
+  if (auto EC = ArgvOrErr.getError()) {<br>
+    llvm::errs() << "error while reading response file: " << EC.message()<br>
+                 << "\n";<br>
+    return EC;<br>
+  }<br>
+  Argv = std::move(ArgvOrErr.get());<br>
+<br>
+  // Make InputArgList from string vectors.<br>
+  ELFOptTable Table;<br>
+  unsigned MissingIndex;<br>
+  unsigned MissingCount;<br>
+<br>
+  llvm::opt::InputArgList Args =<br>
+      Table.ParseArgs(Argv, MissingIndex, MissingCount);<br>
+  if (MissingCount) {<br>
+    llvm::errs() << "missing arg value for \""<br>
+                 << Args.getArgString(MissingIndex) << "\", expected "<br>
+                 << MissingCount<br>
+                 << (MissingCount == 1 ? " argument.\n" : " arguments.\n");<br>
+    return make_error_code(LLDError::InvalidOption);<br>
+  }<br>
+  for (auto *Arg : Args.filtered(OPT_UNKNOWN))<br>
+    llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n";<br>
+  return std::move(Args);<br>
+}<br>
+<br>
+ErrorOr<llvm::opt::InputArgList><br>
+ArgParser::parse(llvm::ArrayRef<const char *> Args) {<br>
+  Args = Args.slice(1);<br>
+  std::vector<const char *> V(Args.begin(), Args.end());<br>
+  return parse(V);<br>
+}<br>
+<br>
+std::vector<const char *> ArgParser::tokenize(StringRef S) {<br>
+  SmallVector<const char *, 16> Tokens;<br>
+  BumpPtrStringSaver Saver(AllocAux);<br>
+  llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens);<br>
+  return std::vector<const char *>(Tokens.begin(), Tokens.end());<br>
+}<br>
+<br>
+// Creates a new command line by replacing options starting with '@'<br>
+// character. '@<filename>' is replaced by the file's contents.<br>
+ErrorOr<std::vector<const char *>><br>
+ArgParser::replaceResponseFiles(std::vector<const char *> Argv) {<br>
+  SmallVector<const char *, 256> Tokens(Argv.data(), Argv.data() + Argv.size());<br>
+  BumpPtrStringSaver Saver(AllocAux);<br>
+  ExpandResponseFiles(Saver, TokenizeWindowsCommandLine, Tokens);<br>
+  return std::vector<const char *>(Tokens.begin(), Tokens.end());<br>
+}<br>
+<br>
+void lld::elfv2::printHelp(const char *Argv0) {<br>
+  ELFOptTable Table;<br>
+  Table.PrintHelp(llvm::outs(), Argv0, "LLVM Linker", false);<br>
+}<br>
<br>
Added: lld/trunk/ELF/Error.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_Error.h-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=iaJmjsEIzfaockPOOa_y7TrY1iwLzh4b4mJ5ATYqL7s&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Error.h?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Error.h (added)<br>
+++ lld/trunk/ELF/Error.h Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,54 @@<br>
+//===- Error.h ------------------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLD_ELF_ERROR_H<br>
+#define LLD_ELF_ERROR_H<br>
+<br>
+#include <string><br>
+#include <system_error><br>
+#include "llvm/Support/ErrorHandling.h"<br>
+<br>
+namespace lld {<br>
+namespace elfv2 {<br>
+<br>
+enum class LLDError {<br>
+  InvalidOption = 1,<br>
+  InvalidFile,<br>
+  BrokenFile,<br>
+  DuplicateSymbols,<br>
+};<br>
+<br>
+class LLDErrorCategory : public std::error_category {<br>
+public:<br>
+  const char *name() const LLVM_NOEXCEPT override { return "lld"; }<br>
+<br>
+  std::string message(int EV) const override {<br>
+    switch (static_cast<LLDError>(EV)) {<br>
+    case LLDError::InvalidOption:<br>
+      return "Invalid option";<br>
+    case LLDError::InvalidFile:<br>
+      return "Invalid file";<br>
+    case LLDError::BrokenFile:<br>
+      return "Broken file";<br>
+    case LLDError::DuplicateSymbols:<br>
+      return "Duplicate symbols";<br>
+    }<br>
+    llvm_unreachable("unknown error");<br>
+  }<br>
+};<br>
+<br>
+inline std::error_code make_error_code(LLDError Err) {<br>
+  static LLDErrorCategory C;<br>
+  return std::error_code(static_cast<int>(Err), C);<br>
+}<br>
+<br>
+} // namespace elfv2<br>
+} // namespace lld<br>
+<br>
+#endif<br>
<br>
Added: lld/trunk/ELF/InputFiles.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_InputFiles.cpp-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=0zbaiOpdzJ5cyrkm_NDgNCjqFVI_9MFZ_0PPN_uJlF4&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/InputFiles.cpp (added)<br>
+++ lld/trunk/ELF/InputFiles.cpp Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,212 @@<br>
+//===- InputFiles.cpp -----------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "Chunks.h"<br>
+#include "Error.h"<br>
+#include "InputFiles.h"<br>
+#include "Writer.h"<br>
+#include "llvm/ADT/STLExtras.h"<br>
+#include "llvm/LTO/LTOModule.h"<br>
+#include "llvm/Object/ELF.h"<br>
+#include "llvm/Support/ELF.h"<br>
+#include "llvm/Support/Debug.h"<br>
+#include "llvm/Support/Endian.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+<br>
+using namespace llvm::ELF;<br>
+using namespace llvm::object;<br>
+using namespace llvm::support::endian;<br>
+using llvm::RoundUpToAlignment;<br>
+using llvm::sys::fs::identify_magic;<br>
+using llvm::sys::fs::file_magic;<br>
+<br>
+using namespace lld;<br>
+using namespace lld::elfv2;<br>
+<br>
+// Returns the last element of a path, which is supposed to be a filename.<br>
+static StringRef getBasename(StringRef Path) {<br>
+  size_t Pos = Path.rfind('\\');<br>
+  if (Pos == StringRef::npos)<br>
+    return Path;<br>
+  return Path.substr(Pos + 1);<br>
+}<br>
+<br>
+// Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)".<br>
+std::string InputFile::getShortName() {<br>
+  if (ParentName == "")<br>
+    return getName().lower();<br>
+  std::string Res =<br>
+      (getBasename(ParentName) + "(" + getBasename(getName()) + ")").str();<br>
+  return StringRef(Res).lower();<br>
+}<br>
+<br>
+std::error_code ArchiveFile::parse() {<br>
+  // Parse a MemoryBufferRef as an archive file.<br>
+  auto ArchiveOrErr = Archive::create(MB);<br>
+  if (auto EC = ArchiveOrErr.getError())<br>
+    return EC;<br>
+  File = std::move(ArchiveOrErr.get());<br>
+<br>
+  // Allocate a buffer for Lazy objects.<br>
+  size_t BufSize = File->getNumberOfSymbols() * sizeof(Lazy);<br>
+  Lazy *Buf = (Lazy *)Alloc.Allocate(BufSize, llvm::alignOf<Lazy>());<br>
+<br>
+  // Read the symbol table to construct Lazy objects.<br>
+  uint32_t I = 0;<br>
+  for (const Archive::Symbol &Sym : File->symbols()) {<br>
+    SymbolBodies.push_back(new (&Buf[I++]) Lazy(this, Sym));<br>
+  }<br>
+  return std::error_code();<br>
+}<br>
+<br>
+// Returns a buffer pointing to a member file containing a given symbol.<br>
+ErrorOr<MemoryBufferRef> ArchiveFile::getMember(const Archive::Symbol *Sym) {<br>
+  auto ItOrErr = Sym->getMember();<br>
+  if (auto EC = ItOrErr.getError())<br>
+    return EC;<br>
+  Archive::child_iterator It = ItOrErr.get();<br>
+<br>
+  // Return an empty buffer if we have already returned the same buffer.<br>
+  const char *StartAddr = It->getBuffer().data();<br>
+  auto Pair = Seen.insert(StartAddr);<br>
+  if (!Pair.second)<br>
+    return MemoryBufferRef();<br>
+  return It->getMemoryBufferRef();<br>
+}<br>
+<br>
+template <class ELFT> std::error_code elfv2::ObjectFile<ELFT>::parse() {<br>
+  // Parse a memory buffer as a ELF file.<br>
+  std::error_code EC;<br>
+  ELFObj = llvm::make_unique<ELFFile<ELFT>>(MB.getBuffer(), EC);<br>
+<br>
+  if (EC) {<br>
+    llvm::errs() << getName() << " is not an ELF file.\n";<br>
+    return EC;<br>
+  }<br>
+<br>
+  // Read section and symbol tables.<br>
+  if (EC = initializeChunks())<br>
+    return EC;<br>
+  return initializeSymbols();<br>
+}<br>
+<br>
+template <class ELFT><br>
+SymbolBody *elfv2::ObjectFile<ELFT>::getSymbolBody(uint32_t SymbolIndex) {<br>
+  return SparseSymbolBodies[SymbolIndex]->getReplacement();<br>
+}<br>
+<br>
+static bool isIgnoredSectionType(unsigned Type) {<br>
+  switch (Type) {<br>
+  case SHT_NULL:<br>
+  case SHT_SYMTAB:<br>
+  case SHT_STRTAB:<br>
+  case SHT_RELA:<br>
+  case SHT_HASH:<br>
+  case SHT_DYNAMIC:<br>
+  case SHT_NOTE:<br>
+  case SHT_REL:<br>
+  case SHT_DYNSYM:<br>
+  case SHT_SYMTAB_SHNDX:<br>
+    return true;<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
+template <class ELFT><br>
+std::error_code elfv2::ObjectFile<ELFT>::initializeChunks() {<br>
+  auto Size = ELFObj->getNumSections();<br>
+  Chunks.reserve(Size);<br>
+  SparseChunks.resize(Size);<br>
+  int I = 0;<br>
+  for (auto &&Sec : ELFObj->sections()) {<br>
+    if (isIgnoredSectionType(Sec.sh_type) || Sec.sh_addralign == 0) {<br>
+      ++I;<br>
+      continue;<br>
+    }<br>
+    auto *C = new (Alloc) SectionChunk<ELFT>(this, &Sec, I);<br>
+    Chunks.push_back(C);<br>
+    SparseChunks[I] = C;<br>
+    ++I;<br>
+  }<br>
+  return std::error_code();<br>
+}<br>
+<br>
+template <class ELFT><br>
+std::error_code elfv2::ObjectFile<ELFT>::initializeSymbols() {<br>
+  auto Syms = ELFObj->symbols();<br>
+  Syms = ELFFile<ELFT>::Elf_Sym_Range(Syms.begin() + 1, Syms.end());<br>
+  auto NumSymbols = std::distance(Syms.begin(), Syms.end());<br>
+  SymbolBodies.reserve(NumSymbols + 1);<br>
+  SparseSymbolBodies.resize(NumSymbols + 1);<br>
+  int I = 1;<br>
+  for (auto &&Sym : Syms) {<br>
+    SymbolBody *Body = createSymbolBody(&Sym);<br>
+    if (Body) {<br>
+      SymbolBodies.push_back(Body);<br>
+      SparseSymbolBodies[I] = Body;<br>
+    }<br>
+    ++I;<br>
+  }<br>
+<br>
+  return std::error_code();<br>
+}<br>
+<br>
+template <class ELFT><br>
+SymbolBody *elfv2::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {<br>
+  StringRef Name;<br>
+  if (Sym->isUndefined()) {<br>
+    Name = *ELFObj->getStaticSymbolName(Sym);<br>
+    return new (Alloc) Undefined(Name);<br>
+  }<br>
+  if (Sym->isCommon()) {<br>
+    Chunk *C = new (Alloc) CommonChunk<ELFT>(Sym);<br>
+    Chunks.push_back(C);<br>
+    return new (Alloc) DefinedRegular<ELFT>(ELFObj.get(), Sym, C);<br>
+  }<br>
+  if (Sym->isAbsolute()) {<br>
+    Name = *ELFObj->getStaticSymbolName(Sym);<br>
+    return new (Alloc) DefinedAbsolute(Name, Sym->getValue());<br>
+  }<br>
+  if (Chunk *C = SparseChunks[Sym->st_shndx])<br>
+    return new (Alloc) DefinedRegular<ELFT>(ELFObj.get(), Sym, C);<br>
+  return nullptr;<br>
+}<br>
+<br>
+std::error_code BitcodeFile::parse() {<br>
+  std::string Err;<br>
+  M.reset(LTOModule::createFromBuffer(MB.getBufferStart(), MB.getBufferSize(),<br>
+                                      llvm::TargetOptions(), Err));<br>
+  if (!Err.empty()) {<br>
+    llvm::errs() << Err << '\n';<br>
+    return make_error_code(LLDError::BrokenFile);<br>
+  }<br>
+<br>
+  for (unsigned I = 0, E = M->getSymbolCount(); I != E; ++I) {<br>
+    lto_symbol_attributes Attrs = M->getSymbolAttributes(I);<br>
+    if ((Attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL)<br>
+      continue;<br>
+<br>
+    StringRef SymName = M->getSymbolName(I);<br>
+    int SymbolDef = Attrs & LTO_SYMBOL_DEFINITION_MASK;<br>
+    if (SymbolDef == LTO_SYMBOL_DEFINITION_UNDEFINED) {<br>
+      SymbolBodies.push_back(new (Alloc) Undefined(SymName));<br>
+    } else {<br>
+      bool Replaceable = (SymbolDef == LTO_SYMBOL_DEFINITION_TENTATIVE ||<br>
+                          (Attrs & LTO_SYMBOL_COMDAT));<br>
+      SymbolBodies.push_back(new (Alloc) DefinedBitcode(SymName, Replaceable));<br>
+    }<br>
+  }<br>
+<br>
+  return std::error_code();<br>
+}<br>
+<br>
+template class elfv2::ObjectFile<llvm::object::ELF32LE>;<br>
+template class elfv2::ObjectFile<llvm::object::ELF32BE>;<br>
+template class elfv2::ObjectFile<llvm::object::ELF64LE>;<br>
+template class elfv2::ObjectFile<llvm::object::ELF64BE>;<br>
<br>
Added: lld/trunk/ELF/InputFiles.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_InputFiles.h-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=_KWHRcxOfbZ92K_SvdP1jRF1Ivrq_tkBGdEsv530rMc&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/InputFiles.h (added)<br>
+++ lld/trunk/ELF/InputFiles.h Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,158 @@<br>
+//===- InputFiles.h -------------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLD_ELF_INPUT_FILES_H<br>
+#define LLD_ELF_INPUT_FILES_H<br>
+<br>
+#include "Chunks.h"<br>
+#include "Symbols.h"<br>
+#include "lld/Core/LLVM.h"<br>
+#include "llvm/ADT/ArrayRef.h"<br>
+#include "llvm/LTO/LTOModule.h"<br>
+#include "llvm/Object/Archive.h"<br>
+#include "llvm/Object/ELF.h"<br>
+#include "llvm/Support/StringSaver.h"<br>
+#include <memory><br>
+#include <set><br>
+#include <vector><br>
+<br>
+namespace lld {<br>
+namespace elfv2 {<br>
+<br>
+using llvm::LTOModule;<br>
+using llvm::object::Archive;<br>
+using llvm::object::ELFFile;<br>
+<br>
+// The root class of input files.<br>
+class InputFile {<br>
+public:<br>
+  enum Kind { ArchiveKind, ObjectKind, ImportKind, BitcodeKind };<br>
+  Kind kind() const { return FileKind; }<br>
+  virtual ~InputFile() {}<br>
+<br>
+  // Returns the filename.<br>
+  StringRef getName() { return MB.getBufferIdentifier(); }<br>
+<br>
+  // Returns symbols defined by this file.<br>
+  virtual std::vector<SymbolBody *> &getSymbols() = 0;<br>
+<br>
+  // Reads a file (constructors don't do that). Returns an error if a<br>
+  // file is broken.<br>
+  virtual std::error_code parse() = 0;<br>
+<br>
+  // Returns a short, human-friendly filename. If this is a member of<br>
+  // an archive file, a returned value includes parent's filename.<br>
+  // Used for logging or debugging.<br>
+  std::string getShortName();<br>
+<br>
+  // Sets a parent filename if this file is created from an archive.<br>
+  void setParentName(StringRef N) { ParentName = N; }<br>
+<br>
+protected:<br>
+  explicit InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}<br>
+  MemoryBufferRef MB;<br>
+<br>
+private:<br>
+  const Kind FileKind;<br>
+  StringRef ParentName;<br>
+};<br>
+<br>
+// .lib or .a file.<br>
+class ArchiveFile : public InputFile {<br>
+public:<br>
+  explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}<br>
+  static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }<br>
+  std::error_code parse() override;<br>
+<br>
+  // Returns a memory buffer for a given symbol. An empty memory buffer<br>
+  // is returned if we have already returned the same memory buffer.<br>
+  // (So that we don't instantiate same members more than once.)<br>
+  ErrorOr<MemoryBufferRef> getMember(const Archive::Symbol *Sym);<br>
+<br>
+  // NB: All symbols returned by ArchiveFiles are of Lazy type.<br>
+  std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }<br>
+<br>
+private:<br>
+  std::unique_ptr<Archive> File;<br>
+  std::string Filename;<br>
+  std::vector<SymbolBody *> SymbolBodies;<br>
+  std::set<const char *> Seen;<br>
+  llvm::MallocAllocator Alloc;<br>
+};<br>
+<br>
+// .obj or .o file. This may be a member of an archive file.<br>
+template <class ELFT> class ObjectFile : public InputFile {<br>
+  typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;<br>
+<br>
+public:<br>
+  explicit ObjectFile(MemoryBufferRef M) : InputFile(ObjectKind, M) {}<br>
+  static bool classof(const InputFile *F) { return F->kind() == ObjectKind; }<br>
+  std::error_code parse() override;<br>
+  std::vector<Chunk *> &getChunks() { return Chunks; }<br>
+  std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }<br>
+<br>
+  // Returns a SymbolBody object for the SymbolIndex'th symbol in the<br>
+  // underlying object file.<br>
+  SymbolBody *getSymbolBody(uint32_t SymbolIndex);<br>
+<br>
+  // Returns the underying ELF file.<br>
+  ELFFile<ELFT> *getObj() { return ELFObj.get(); }<br>
+<br>
+private:<br>
+  std::error_code initializeChunks();<br>
+  std::error_code initializeSymbols();<br>
+<br>
+  SymbolBody *createSymbolBody(const Elf_Sym *Sym);<br>
+<br>
+  std::unique_ptr<ELFFile<ELFT>> ELFObj;<br>
+  llvm::BumpPtrAllocator Alloc;<br>
+<br>
+  // List of all chunks defined by this file. This includes both section<br>
+  // chunks and non-section chunks for common symbols.<br>
+  std::vector<Chunk *> Chunks;<br>
+<br>
+  // This vector contains the same chunks as Chunks, but they are<br>
+  // indexed such that you can get a SectionChunk by section index.<br>
+  // Nonexistent section indices are filled with null pointers.<br>
+  // (Because section number is 1-based, the first slot is always a<br>
+  // null pointer.)<br>
+  std::vector<Chunk *> SparseChunks;<br>
+<br>
+  // List of all symbols referenced or defined by this file.<br>
+  std::vector<SymbolBody *> SymbolBodies;<br>
+<br>
+  // This vector contains the same symbols as SymbolBodies, but they<br>
+  // are indexed such that you can get a SymbolBody by symbol<br>
+  // index. Nonexistent indices (which are occupied by auxiliary<br>
+  // symbols in the real symbol table) are filled with null pointers.<br>
+  std::vector<SymbolBody *> SparseSymbolBodies;<br>
+};<br>
+<br>
+// Used for LTO.<br>
+class BitcodeFile : public InputFile {<br>
+public:<br>
+  explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {}<br>
+  static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; }<br>
+  std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }<br>
+<br>
+  LTOModule *getModule() const { return M.get(); }<br>
+  LTOModule *releaseModule() { return M.release(); }<br>
+<br>
+private:<br>
+  std::error_code parse() override;<br>
+<br>
+  std::vector<SymbolBody *> SymbolBodies;<br>
+  llvm::BumpPtrAllocator Alloc;<br>
+  std::unique_ptr<LTOModule> M;<br>
+};<br>
+<br>
+} // namespace elfv2<br>
+} // namespace lld<br>
+<br>
+#endif<br>
<br>
Added: lld/trunk/ELF/Options.td<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_Options.td-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=w0I9cFXBrc2gepgZltHH0M2uPwmiBqz9vzw_2gigSuQ&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Options.td (added)<br>
+++ lld/trunk/ELF/Options.td Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,54 @@<br>
+include "llvm/Option/OptParser.td"<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+/// Utility Functions<br>
+//===----------------------------------------------------------------------===//<br>
+// Single and multiple dash options combined<br>
+multiclass smDash<string opt1, string opt2, string help> {<br>
+  // Option<br>
+  def "" : Separate<["-"], opt1>, HelpText<help>;<br>
+  def opt1_eq : Joined<["-"], opt1#"=">,<br>
+      Alias<!cast<Option>(opt1)>;<br>
+  // Compatibility aliases<br>
+  def opt2_dashdash : Separate<["--"], opt2>,<br>
+      Alias<!cast<Option>(opt1)>;<br>
+  def opt2_dashdash_eq : Joined<["--"], opt2#"=">,<br>
+      Alias<!cast<Option>(opt1)>;<br>
+}<br>
+<br>
+// Support -<option>,-<option>=<br>
+multiclass dashEq<string opt1, string opt2, string help> {<br>
+  // Option<br>
+  def "" : Separate<["-"], opt1>, HelpText<help>;<br>
+  // Compatibility aliases<br>
+  def opt2_eq : Joined<["-"], opt2#"=">,<br>
+      Alias<!cast<Option>(opt1)>;<br>
+}<br>
+<br>
+// Support --<option>,--<option>=<br>
+multiclass mDashEq<string opt1, string help> {<br>
+  // Option<br>
+  def "" : Separate<["--"], opt1>, HelpText<help>;<br>
+  // Compatibility aliases<br>
+  def opt2_eq : Joined<["--"], opt1#"=">,<br>
+      Alias<!cast<Option>(opt1)>;<br>
+}<br>
+<br>
+def output : Separate<["-"], "o">, MetaVarName<"<path>">,<br>
+     HelpText<"Path to file to write output">;<br>
+<br>
+def L : Joined<["-"], "L">, MetaVarName<"<dir>">,<br>
+     HelpText<"Directory to search for libraries">;<br>
+def l : Joined<["-"], "l">, MetaVarName<"<libName>">,<br>
+     HelpText<"Root name of library to use">;<br>
+def noinhibit_exec : Flag<["--"], "noinhibit-exec">,<br>
+     HelpText<"Retain the executable output file whenever"<br>
+              " it is still usable">;<br>
+defm e : smDash<"e", "entry",<br>
+      "Name of entry point symbol">;<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+/// Help<br>
+//===----------------------------------------------------------------------===//<br>
+def help : Flag<["--"], "help">,<br>
+     HelpText<"Display this help message">;<br>
<br>
Added: lld/trunk/ELF/README.md<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_README.md-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=Jyvluvb6zc7VSrEnxbNDMJvFH3eg8C--Pl2en-Ll9s0&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/README.md?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/README.md (added)<br>
+++ lld/trunk/ELF/README.md Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,12 @@<br>
+The New ELF Linker<br>
+==================<br>
+This directory contains a port of the new PE/COFF linker for ELF.<br>
+<br>
+Overall Design<br>
+--------------<br>
+See COFF/README.md for details on the design.<br>
+<br>
+Capabilities<br>
+------------<br>
+This linker can currently generate a valid ELF file that can be run on linux<br>
+from a single input file.<br>
<br>
Added: lld/trunk/ELF/SymbolTable.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_SymbolTable.cpp-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=qRVcjQ3zwc9ZkOXZJ27SvbkC4zszBjizcY3dUmzBbJ8&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/SymbolTable.cpp (added)<br>
+++ lld/trunk/ELF/SymbolTable.cpp Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,302 @@<br>
+//===- SymbolTable.cpp ----------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "Config.h"<br>
+#include "Driver.h"<br>
+#include "Error.h"<br>
+#include "SymbolTable.h"<br>
+#include "llvm/ADT/STLExtras.h"<br>
+#include "llvm/LTO/LTOCodeGenerator.h"<br>
+#include "llvm/Support/Debug.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+<br>
+using namespace llvm;<br>
+<br>
+using namespace lld;<br>
+using namespace lld::elfv2;<br>
+<br>
+template <class ELFT> SymbolTable<ELFT>::SymbolTable() {<br>
+  if (!Config->EntryName.empty())<br>
+    resolve(new (Alloc) Undefined(Config->EntryName));<br>
+}<br>
+<br>
+template <class ELFT><br>
+std::error_code SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {<br>
+  if (auto EC = File->parse())<br>
+    return EC;<br>
+  InputFile *FileP = File.release();<br>
+  if (auto *P = dyn_cast<ObjectFile<ELFT>>(FileP))<br>
+    return addObject(P);<br>
+  if (auto *P = dyn_cast<ArchiveFile>(FileP))<br>
+    return addArchive(P);<br>
+  if (auto *P = dyn_cast<BitcodeFile>(FileP))<br>
+    return addBitcode(P);<br>
+  llvm_unreachable("Unknown file");<br>
+}<br>
+<br>
+template <class ELFT><br>
+std::error_code SymbolTable<ELFT>::addObject(ObjectFile<ELFT> *File) {<br>
+  ObjectFiles.emplace_back(File);<br>
+  for (SymbolBody *Body : File->getSymbols())<br>
+    if (Body->isExternal())<br>
+      if (auto EC = resolve(Body))<br>
+        return EC;<br>
+  return std::error_code();<br>
+}<br>
+<br>
+template <class ELFT><br>
+std::error_code SymbolTable<ELFT>::addArchive(ArchiveFile *File) {<br>
+  ArchiveFiles.emplace_back(File);<br>
+  for (SymbolBody *Body : File->getSymbols())<br>
+    if (auto EC = resolve(Body))<br>
+      return EC;<br>
+  return std::error_code();<br>
+}<br>
+<br>
+template <class ELFT><br>
+std::error_code SymbolTable<ELFT>::addBitcode(BitcodeFile *File) {<br>
+  BitcodeFiles.emplace_back(File);<br>
+  for (SymbolBody *Body : File->getSymbols())<br>
+    if (Body->isExternal())<br>
+      if (auto EC = resolve(Body))<br>
+        return EC;<br>
+  return std::error_code();<br>
+}<br>
+<br>
+template <class ELFT> bool SymbolTable<ELFT>::reportRemainingUndefines() {<br>
+  bool Ret = false;<br>
+  for (auto &I : Symtab) {<br>
+    Symbol *Sym = I.second;<br>
+    auto *Undef = dyn_cast<Undefined>(Sym->Body);<br>
+    if (!Undef)<br>
+      continue;<br>
+    if (SymbolBody *Alias = Undef->getWeakAlias()) {<br>
+      Sym->Body = Alias->getReplacement();<br>
+      if (!isa<Defined>(Sym->Body)) {<br>
+        // Aliases are yet another symbols pointed by other symbols<br>
+        // that could also remain undefined.<br>
+        llvm::errs() << "undefined symbol: " << Undef->getName() << "\n";<br>
+        Ret = true;<br>
+      }<br>
+      continue;<br>
+    }<br>
+    llvm::errs() << "undefined symbol: " << Undef->getName() << "\n";<br>
+    Ret = true;<br>
+  }<br>
+  return Ret;<br>
+}<br>
+<br>
+// This function resolves conflicts if there's an existing symbol with<br>
+// the same name. Decisions are made based on symbol type.<br>
+template <class ELFT><br>
+std::error_code SymbolTable<ELFT>::resolve(SymbolBody *New) {<br>
+  // Find an existing Symbol or create and insert a new one.<br>
+  StringRef Name = New->getName();<br>
+  Symbol *&Sym = Symtab[Name];<br>
+  if (!Sym) {<br>
+    Sym = new (Alloc) Symbol(New);<br>
+    New->setBackref(Sym);<br>
+    return std::error_code();<br>
+  }<br>
+  New->setBackref(Sym);<br>
+<br>
+  // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,<br>
+  // equivalent (conflicting), or more preferable, respectively.<br>
+  SymbolBody *Existing = Sym->Body;<br>
+  int comp = Existing->compare(New);<br>
+  if (comp < 0)<br>
+    Sym->Body = New;<br>
+  if (comp == 0) {<br>
+    llvm::errs() << "duplicate symbol: " << Name << "\n";<br>
+    return make_error_code(LLDError::DuplicateSymbols);<br>
+  }<br>
+<br>
+  // If we have an Undefined symbol for a Lazy symbol, we need<br>
+  // to read an archive member to replace the Lazy symbol with<br>
+  // a Defined symbol.<br>
+  if (isa<Undefined>(Existing) || isa<Undefined>(New))<br>
+    if (auto *B = dyn_cast<Lazy>(Sym->Body))<br>
+      return addMemberFile(B);<br>
+  return std::error_code();<br>
+}<br>
+<br>
+// Reads an archive member file pointed by a given symbol.<br>
+template <class ELFT><br>
+std::error_code SymbolTable<ELFT>::addMemberFile(Lazy *Body) {<br>
+  auto FileOrErr = Body->getMember();<br>
+  if (auto EC = FileOrErr.getError())<br>
+    return EC;<br>
+  std::unique_ptr<InputFile> File = std::move(FileOrErr.get());<br>
+<br>
+  // getMember returns an empty buffer if the member was already<br>
+  // read from the library.<br>
+  if (!File)<br>
+    return std::error_code();<br>
+  if (Config->Verbose)<br>
+    llvm::outs() << "Loaded " << File->getShortName() << " for "<br>
+                 << Body->getName() << "\n";<br>
+  return addFile(std::move(File));<br>
+}<br>
+<br>
+template <class ELFT> std::vector<Chunk *> SymbolTable<ELFT>::getChunks() {<br>
+  std::vector<Chunk *> Res;<br>
+  for (std::unique_ptr<ObjectFile<ELFT>> &File : ObjectFiles) {<br>
+    std::vector<Chunk *> &V = File->getChunks();<br>
+    Res.insert(Res.end(), V.begin(), V.end());<br>
+  }<br>
+  return Res;<br>
+}<br>
+<br>
+template <class ELFT> Defined *SymbolTable<ELFT>::find(StringRef Name) {<br>
+  auto It = Symtab.find(Name);<br>
+  if (It == Symtab.end())<br>
+    return nullptr;<br>
+  if (auto *Def = dyn_cast<Defined>(It->second->Body))<br>
+    return Def;<br>
+  return nullptr;<br>
+}<br>
+<br>
+template <class ELFT><br>
+std::error_code SymbolTable<ELFT>::addUndefined(StringRef Name) {<br>
+  return resolve(new (Alloc) Undefined(Name));<br>
+}<br>
+<br>
+// Resolve To, and make From an alias to To.<br>
+template <class ELFT><br>
+std::error_code SymbolTable<ELFT>::rename(StringRef From, StringRef To) {<br>
+  SymbolBody *Body = new (Alloc) Undefined(To);<br>
+  if (auto EC = resolve(Body))<br>
+    return EC;<br>
+  Symtab[From]->Body = Body->getReplacement();<br>
+  return std::error_code();<br>
+}<br>
+<br>
+template <class ELFT> void SymbolTable<ELFT>::dump() {<br>
+  for (auto &P : Symtab) {<br>
+    Symbol *Ref = P.second;<br>
+    if (auto *Body = dyn_cast<Defined>(Ref->Body))<br>
+      llvm::dbgs() << Twine::utohexstr(Body->getVA()) << " " << Body->getName()<br>
+                   << "\n";<br>
+  }<br>
+}<br>
+<br>
+template <class ELFT><br>
+std::error_code SymbolTable<ELFT>::addCombinedLTOObject() {<br>
+  if (BitcodeFiles.empty())<br>
+    return std::error_code();<br>
+<br>
+  // Create an object file and add it to the symbol table by replacing any<br>
+  // DefinedBitcode symbols with the definitions in the object file.<br>
+  LTOCodeGenerator CG;<br>
+  auto FileOrErr = createLTOObject(&CG);<br>
+  if (auto EC = FileOrErr.getError())<br>
+    return EC;<br>
+  ObjectFile<ELFT> *Obj = FileOrErr.get();<br>
+<br>
+  for (SymbolBody *Body : Obj->getSymbols()) {<br>
+    if (!Body->isExternal())<br>
+      continue;<br>
+    // Find an existing Symbol. We should not see any new undefined symbols at<br>
+    // this point.<br>
+    StringRef Name = Body->getName();<br>
+    Symbol *&Sym = Symtab[Name];<br>
+    if (!Sym) {<br>
+      if (!isa<Defined>(Body)) {<br>
+        llvm::errs() << "LTO: undefined symbol: " << Name << '\n';<br>
+        return make_error_code(LLDError::BrokenFile);<br>
+      }<br>
+      Sym = new (Alloc) Symbol(Body);<br>
+      Body->setBackref(Sym);<br>
+      continue;<br>
+    }<br>
+    Body->setBackref(Sym);<br>
+<br>
+    if (isa<DefinedBitcode>(Sym->Body)) {<br>
+      // The symbol should now be defined.<br>
+      if (!isa<Defined>(Body)) {<br>
+        llvm::errs() << "LTO: undefined symbol: " << Name << '\n';<br>
+        return make_error_code(LLDError::BrokenFile);<br>
+      }<br>
+      Sym->Body = Body;<br>
+    } else {<br>
+      int comp = Sym->Body->compare(Body);<br>
+      if (comp < 0)<br>
+        Sym->Body = Body;<br>
+      if (comp == 0) {<br>
+        llvm::errs() << "LTO: unexpected duplicate symbol: " << Name << "\n";<br>
+        return make_error_code(LLDError::BrokenFile);<br>
+      }<br>
+    }<br>
+<br>
+    // We may see new references to runtime library symbols such as __chkstk<br>
+    // here. These symbols must be wholly defined in non-bitcode files.<br>
+    if (auto *B = dyn_cast<Lazy>(Sym->Body)) {<br>
+      size_t NumBitcodeFiles = BitcodeFiles.size();<br>
+      if (auto EC = addMemberFile(B))<br>
+        return EC;<br>
+      if (BitcodeFiles.size() != NumBitcodeFiles) {<br>
+        llvm::errs()<br>
+            << "LTO: late loaded symbol created new bitcode reference: " << Name<br>
+            << "\n";<br>
+        return make_error_code(LLDError::BrokenFile);<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+  // New runtime library symbol references may have created undefined<br>
+  // references.<br>
+  if (reportRemainingUndefines())<br>
+    return make_error_code(LLDError::BrokenFile);<br>
+  return std::error_code();<br>
+}<br>
+<br>
+// Combine and compile bitcode files and then return the result<br>
+// as a regular ELF object file.<br>
+template <class ELFT><br>
+ErrorOr<ObjectFile<ELFT> *><br>
+SymbolTable<ELFT>::createLTOObject(LTOCodeGenerator *CG) {<br>
+  // All symbols referenced by non-bitcode objects must be preserved.<br>
+  for (std::unique_ptr<ObjectFile<ELFT>> &File : ObjectFiles)<br>
+    for (SymbolBody *Body : File->getSymbols())<br>
+      if (auto *S = dyn_cast<DefinedBitcode>(Body->getReplacement()))<br>
+        CG->addMustPreserveSymbol(S->getName());<br>
+<br>
+  // Likewise for bitcode symbols which we initially resolved to non-bitcode.<br>
+  for (std::unique_ptr<BitcodeFile> &File : BitcodeFiles)<br>
+    for (SymbolBody *Body : File->getSymbols())<br>
+      if (isa<DefinedBitcode>(Body) &&<br>
+          !isa<DefinedBitcode>(Body->getReplacement()))<br>
+        CG->addMustPreserveSymbol(Body->getName());<br>
+<br>
+  // Likewise for other symbols that must be preserved.<br>
+  for (StringRef Name : Config->GCRoots)<br>
+    if (isa<DefinedBitcode>(Symtab[Name]->Body))<br>
+      CG->addMustPreserveSymbol(Name);<br>
+<br>
+  CG->setModule(BitcodeFiles[0]->releaseModule());<br>
+  for (unsigned I = 1, E = BitcodeFiles.size(); I != E; ++I)<br>
+    CG->addModule(BitcodeFiles[I]->getModule());<br>
+<br>
+  std::string ErrMsg;<br>
+  LTOMB = CG->compile(false, false, false, ErrMsg); // take MB ownership<br>
+  if (!LTOMB) {<br>
+    llvm::errs() << ErrMsg << '\n';<br>
+    return make_error_code(LLDError::BrokenFile);<br>
+  }<br>
+  auto Obj = new ObjectFile<ELFT>(LTOMB->getMemBufferRef());<br>
+  ObjectFiles.emplace_back(Obj);<br>
+  if (auto EC = Obj->parse())<br>
+    return EC;<br>
+  return Obj;<br>
+}<br>
+<br>
+template class SymbolTable<llvm::object::ELF32LE>;<br>
+template class SymbolTable<llvm::object::ELF32BE>;<br>
+template class SymbolTable<llvm::object::ELF64LE>;<br>
+template class SymbolTable<llvm::object::ELF64BE>;<br>
<br>
Added: lld/trunk/ELF/SymbolTable.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_SymbolTable.h-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=vlcGP95UeCxCE5QsahnNIp8p11fpQbmFoSK5EfpPjV4&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/SymbolTable.h (added)<br>
+++ lld/trunk/ELF/SymbolTable.h Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,88 @@<br>
+//===- SymbolTable.h ------------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLD_ELF_SYMBOL_TABLE_H<br>
+#define LLD_ELF_SYMBOL_TABLE_H<br>
+<br>
+#include "InputFiles.h"<br>
+#include "llvm/Support/Allocator.h"<br>
+#include <unordered_map><br>
+<br>
+namespace llvm {<br>
+struct LTOCodeGenerator;<br>
+}<br>
+<br>
+namespace lld {<br>
+namespace elfv2 {<br>
+<br>
+// SymbolTable is a bucket of all known symbols, including defined,<br>
+// undefined, or lazy symbols (the last one is symbols in archive<br>
+// files whose archive members are not yet loaded).<br>
+//<br>
+// We put all symbols of all files to a SymbolTable, and the<br>
+// SymbolTable selects the "best" symbols if there are name<br>
+// conflicts. For example, obviously, a defined symbol is better than<br>
+// an undefined symbol. Or, if there's a conflict between a lazy and a<br>
+// undefined, it'll read an archive member to read a real definition<br>
+// to replace the lazy symbol. The logic is implemented in resolve().<br>
+template <class ELFT> class SymbolTable {<br>
+public:<br>
+  SymbolTable();<br>
+<br>
+  std::error_code addFile(std::unique_ptr<InputFile> File);<br>
+<br>
+  // Print an error message on undefined symbols.<br>
+  bool reportRemainingUndefines();<br>
+<br>
+  // Returns a list of chunks of selected symbols.<br>
+  std::vector<Chunk *> getChunks();<br>
+<br>
+  // Returns a symbol for a given name. It's not guaranteed that the<br>
+  // returned symbol actually has the same name (because of various<br>
+  // mechanisms to allow aliases, a name can be resolved to a<br>
+  // different symbol). Returns a nullptr if not found.<br>
+  Defined *find(StringRef Name);<br>
+<br>
+  // Dump contents of the symbol table to stderr.<br>
+  void dump();<br>
+<br>
+  // Build an ELF object representing the combined contents of BitcodeFiles<br>
+  // and add it to the symbol table. Called after all files are added and<br>
+  // before the writer writes results to a file.<br>
+  std::error_code addCombinedLTOObject();<br>
+<br>
+  // The writer needs to infer the machine type from the object files.<br>
+  std::vector<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles;<br>
+<br>
+  // Creates an Undefined symbol for a given name.<br>
+  std::error_code addUndefined(StringRef Name);<br>
+<br>
+  // Rename From -> To in the symbol table.<br>
+  std::error_code rename(StringRef From, StringRef To);<br>
+<br>
+private:<br>
+  std::error_code addObject(ObjectFile<ELFT> *File);<br>
+  std::error_code addArchive(ArchiveFile *File);<br>
+  std::error_code addBitcode(BitcodeFile *File);<br>
+<br>
+  std::error_code resolve(SymbolBody *Body);<br>
+  std::error_code addMemberFile(Lazy *Body);<br>
+  ErrorOr<ObjectFile<ELFT> *> createLTOObject(llvm::LTOCodeGenerator *CG);<br>
+<br>
+  std::unordered_map<StringRef, Symbol *> Symtab;<br>
+  std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;<br>
+  std::vector<std::unique_ptr<BitcodeFile>> BitcodeFiles;<br>
+  std::unique_ptr<MemoryBuffer> LTOMB;<br>
+  llvm::BumpPtrAllocator Alloc;<br>
+};<br>
+<br>
+} // namespace elfv2<br>
+} // namespace lld<br>
+<br>
+#endif<br>
<br>
Added: lld/trunk/ELF/Symbols.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_Symbols.cpp-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=SoZwOfgZdky-sG4qYnXHXy6f-5diZe61UzBTdqxwpeU&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Symbols.cpp (added)<br>
+++ lld/trunk/ELF/Symbols.cpp Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,141 @@<br>
+//===- Symbols.cpp --------------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "Error.h"<br>
+#include "InputFiles.h"<br>
+#include "Symbols.h"<br>
+#include "llvm/ADT/STLExtras.h"<br>
+#include "llvm/Support/Debug.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+<br>
+using namespace llvm::object;<br>
+using llvm::sys::fs::identify_magic;<br>
+using llvm::sys::fs::file_magic;<br>
+<br>
+using namespace lld;<br>
+using namespace lld::elfv2;<br>
+<br>
+// Returns 1, 0 or -1 if this symbol should take precedence<br>
+// over the Other, tie or lose, respectively.<br>
+template <class ELFT> int DefinedRegular<ELFT>::compare(SymbolBody *Other) {<br>
+  if (Other->kind() < kind())<br>
+    return -Other->compare(this);<br>
+  auto *R = dyn_cast<DefinedRegular>(Other);<br>
+  if (!R)<br>
+    return 1;<br>
+<br>
+  // Common symbols are weaker than other types of defined symbols.<br>
+  if (isCommon() && R->isCommon())<br>
+    return (getCommonSize() < R->getCommonSize()) ? -1 : 1;<br>
+  // TODO: we are not sure if regular defined symbol and common<br>
+  // symbols are allowed to have the same name.<br>
+  if (isCommon())<br>
+    return -1;<br>
+  if (R->isCommon())<br>
+    return 1;<br>
+  return 0;<br>
+}<br>
+<br>
+int DefinedBitcode::compare(SymbolBody *Other) {<br>
+  assert(Other->kind() >= kind());<br>
+  if (!isa<Defined>(Other))<br>
+    return 1;<br>
+<br>
+  if (auto *B = dyn_cast<DefinedBitcode>(Other)) {<br>
+    if (!Replaceable && !B->Replaceable)<br>
+      return 0;<br>
+    // Non-replaceable symbols win.<br>
+    return Replaceable ? -1 : 1;<br>
+  }<br>
+<br>
+  // As an approximation, regular symbols win over bitcode symbols,<br>
+  // but we definitely have a conflict if the regular symbol is not<br>
+  // replaceable and neither is the bitcode symbol. We do not<br>
+  // replicate the rest of the symbol resolution logic here; symbol<br>
+  // resolution will be done accurately after lowering bitcode symbols<br>
+  // to regular symbols in addCombinedLTOObject().<br>
+  if (auto *R = dyn_cast<DefinedRegular<llvm::object::ELF64LE>>(Other)) {<br>
+    if (!R->isCommon() && !Replaceable)<br>
+      return 0;<br>
+    return -1;<br>
+  }<br>
+  return 0;<br>
+}<br>
+<br>
+int Defined::compare(SymbolBody *Other) {<br>
+  if (Other->kind() < kind())<br>
+    return -Other->compare(this);<br>
+  if (isa<Defined>(Other))<br>
+    return 0;<br>
+  return 1;<br>
+}<br>
+<br>
+int Lazy::compare(SymbolBody *Other) {<br>
+  if (Other->kind() < kind())<br>
+    return -Other->compare(this);<br>
+<br>
+  // Undefined symbols with weak aliases will turn into defined<br>
+  // symbols if they remain undefined, so we don't need to resolve<br>
+  // such symbols.<br>
+  if (auto *U = dyn_cast<Undefined>(Other))<br>
+    if (U->getWeakAlias())<br>
+      return -1;<br>
+  return 1;<br>
+}<br>
+<br>
+int Undefined::compare(SymbolBody *Other) {<br>
+  if (Other->kind() < kind())<br>
+    return -Other->compare(this);<br>
+  if (cast<Undefined>(Other)->getWeakAlias())<br>
+    return -1;<br>
+  return 1;<br>
+}<br>
+<br>
+template <class ELFT> StringRef DefinedRegular<ELFT>::getName() {<br>
+  // DefinedSymbol's name is read lazily for a performance reason.<br>
+  // Non-external symbol names are never used by the linker<br>
+  // except for logging or debugging.<br>
+  // Their internal references are resolved not by name but by symbol index.<br>
+  // And because they are not external, no one can refer them by name.<br>
+  // Object files contain lots of non-external symbols, and creating<br>
+  // StringRefs for them (which involves lots of strlen() on the string table)<br>
+  // is a waste of time.<br>
+  if (Name.empty())<br>
+    Name = *File->getStaticSymbolName(Sym);<br>
+  return Name;<br>
+}<br>
+<br>
+ErrorOr<std::unique_ptr<InputFile>> Lazy::getMember() {<br>
+  auto MBRefOrErr = File->getMember(&Sym);<br>
+  if (auto EC = MBRefOrErr.getError())<br>
+    return EC;<br>
+  MemoryBufferRef MBRef = MBRefOrErr.get();<br>
+<br>
+  // getMember returns an empty buffer if the member was already<br>
+  // read from the library.<br>
+  if (MBRef.getBuffer().empty())<br>
+    return std::unique_ptr<InputFile>(nullptr);<br>
+<br>
+  file_magic Magic = identify_magic(MBRef.getBuffer());<br>
+  if (Magic == file_magic::bitcode)<br>
+    return std::unique_ptr<InputFile>(new BitcodeFile(MBRef));<br>
+  if (Magic != file_magic::elf_relocatable) {<br>
+    llvm::errs() << File->getName() << ": unknown file type\n";<br>
+    return make_error_code(LLDError::InvalidFile);<br>
+  }<br>
+<br>
+  std::unique_ptr<InputFile> Obj(new ObjectFile<llvm::object::ELF64LE>(MBRef));<br>
+  Obj->setParentName(File->getName());<br>
+  return std::move(Obj);<br>
+}<br>
+<br>
+template class DefinedRegular<llvm::object::ELF32LE>;<br>
+template class DefinedRegular<llvm::object::ELF32BE>;<br>
+template class DefinedRegular<llvm::object::ELF64LE>;<br>
+template class DefinedRegular<llvm::object::ELF64BE>;<br>
<br>
Added: lld/trunk/ELF/Symbols.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_Symbols.h-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=GgCoGvQhq8UxgICOoI4lWu_8gcSDHo9SjWYh8iElYxE&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Symbols.h (added)<br>
+++ lld/trunk/ELF/Symbols.h Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,232 @@<br>
+//===- Symbols.h ----------------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLD_ELF_SYMBOLS_H<br>
+#define LLD_ELF_SYMBOLS_H<br>
+<br>
+#include "Chunks.h"<br>
+#include "Config.h"<br>
+#include "lld/Core/LLVM.h"<br>
+#include "llvm/ADT/ArrayRef.h"<br>
+#include "llvm/Object/Archive.h"<br>
+#include "llvm/Object/ELF.h"<br>
+#include <memory><br>
+#include <vector><br>
+<br>
+namespace lld {<br>
+namespace elfv2 {<br>
+<br>
+using llvm::object::Archive;<br>
+using llvm::object::ELFFile;<br>
+<br>
+class ArchiveFile;<br>
+class InputFile;<br>
+class SymbolBody;<br>
+<br>
+// A real symbol object, SymbolBody, is usually accessed indirectly<br>
+// through a Symbol. There's always one Symbol for each symbol name.<br>
+// The resolver updates SymbolBody pointers as it resolves symbols.<br>
+struct Symbol {<br>
+  explicit Symbol(SymbolBody *P) : Body(P) {}<br>
+  SymbolBody *Body;<br>
+};<br>
+<br>
+// The base class for real symbol classes.<br>
+class SymbolBody {<br>
+public:<br>
+  enum Kind {<br>
+    DefinedFirst,<br>
+    DefinedBitcodeKind,<br>
+    DefinedAbsoluteKind,<br>
+    DefinedRegularKind,<br>
+    DefinedLast,<br>
+    LazyKind,<br>
+    UndefinedKind,<br>
+  };<br>
+<br>
+  Kind kind() const { return SymbolKind; }<br>
+  virtual ~SymbolBody() {}<br>
+<br>
+  // Returns true if this is an external symbol.<br>
+  virtual bool isExternal() { return true; }<br>
+<br>
+  // Returns the symbol name.<br>
+  virtual StringRef getName() = 0;<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>
+  // in the Symbol may be mutated by the resolver. If you have a<br>
+  // pointer P to a SymbolBody and are not sure whether the resolver<br>
+  // has chosen the object among other objects having the same name,<br>
+  // you can access P->Backref->Body to get the resolver's result.<br>
+  void setBackref(Symbol *P) { Backref = P; }<br>
+  SymbolBody *getReplacement() { return Backref ? Backref->Body : this; }<br>
+<br>
+  // Decides which symbol should "win" in the symbol table, this or<br>
+  // the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if<br>
+  // they are duplicate (conflicting) symbols.<br>
+  virtual int compare(SymbolBody *Other) = 0;<br>
+<br>
+protected:<br>
+  SymbolBody(Kind K) : SymbolKind(K) {}<br>
+<br>
+private:<br>
+  const Kind SymbolKind;<br>
+  Symbol *Backref = nullptr;<br>
+};<br>
+<br>
+// The base class for any defined symbols, including absolute symbols,<br>
+// etc.<br>
+class Defined : public SymbolBody {<br>
+public:<br>
+  Defined(Kind K) : SymbolBody(K) {}<br>
+<br>
+  static bool classof(const SymbolBody *S) {<br>
+    Kind K = S->kind();<br>
+    return DefinedFirst <= K && K <= DefinedLast;<br>
+  }<br>
+<br>
+  // Returns the VA (virtual address) of this symbol. The<br>
+  // writer sets and uses VAs.<br>
+  virtual uint64_t getVA() = 0;<br>
+<br>
+  // Returns the file offset of this symbol in the final executable.<br>
+  // The writer uses this information to apply relocations.<br>
+  virtual uint64_t getFileOff() = 0;<br>
+<br>
+  // Called by the garbage collector. All Defined subclasses should<br>
+  // know how to call depending symbols' markLive functions.<br>
+  virtual void markLive() {}<br>
+<br>
+  int compare(SymbolBody *Other) override;<br>
+};<br>
+<br>
+// Regular defined symbols read from object file symbol tables.<br>
+template <class ELFT> class DefinedRegular : public Defined {<br>
+  typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;<br>
+<br>
+public:<br>
+  DefinedRegular(ELFFile<ELFT> *F, const Elf_Sym *S, Chunk *C)<br>
+      : Defined(DefinedRegularKind), File(F), Sym(S), Data(C) {}<br>
+<br>
+  static bool classof(const SymbolBody *S) {<br>
+    return S->kind() == DefinedRegularKind;<br>
+  }<br>
+<br>
+  StringRef getName() override;<br>
+  uint64_t getVA() override { return Data->getVA() + Sym->getValue(); }<br>
+  bool isExternal() override { return Sym->isExternal(); }<br>
+  void markLive() override { Data->markLive(); }<br>
+  uint64_t getFileOff() override {<br>
+    return Data->getFileOff() + Sym->getValue();<br>
+  }<br>
+  int compare(SymbolBody *Other) override;<br>
+<br>
+  // Returns true if this is a common symbol.<br>
+  bool isCommon() const { return Sym->isCommon(); }<br>
+  uint32_t getCommonSize() const { return Sym->st_size; }<br>
+<br>
+private:<br>
+  StringRef Name;<br>
+  ELFFile<ELFT> *File;<br>
+  const Elf_Sym *Sym;<br>
+  Chunk *Data;<br>
+};<br>
+<br>
+// Absolute symbols.<br>
+class DefinedAbsolute : public Defined {<br>
+public:<br>
+  DefinedAbsolute(StringRef N, uint64_t VA)<br>
+      : Defined(DefinedAbsoluteKind), Name(N), VA(VA) {}<br>
+<br>
+  static bool classof(const SymbolBody *S) {<br>
+    return S->kind() == DefinedAbsoluteKind;<br>
+  }<br>
+<br>
+  StringRef getName() override { return Name; }<br>
+  uint64_t getVA() override { return VA; }<br>
+  uint64_t getFileOff() override { llvm_unreachable("internal error"); }<br>
+<br>
+private:<br>
+  StringRef Name;<br>
+  uint64_t VA;<br>
+};<br>
+<br>
+// This class represents a symbol defined in an archive file. It is<br>
+// created from an archive file header, and it knows how to load an<br>
+// object file from an archive to replace itself with a defined<br>
+// symbol. If the resolver finds both Undefined and Lazy for<br>
+// the same name, it will ask the Lazy to load a file.<br>
+class Lazy : public SymbolBody {<br>
+public:<br>
+  Lazy(ArchiveFile *F, const Archive::Symbol S)<br>
+      : SymbolBody(LazyKind), Name(S.getName()), File(F), Sym(S) {}<br>
+<br>
+  static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; }<br>
+  StringRef getName() override { return Name; }<br>
+<br>
+  // Returns an object file for this symbol, or a nullptr if the file<br>
+  // was already returned.<br>
+  ErrorOr<std::unique_ptr<InputFile>> getMember();<br>
+<br>
+  int compare(SymbolBody *Other) override;<br>
+<br>
+private:<br>
+  StringRef Name;<br>
+  ArchiveFile *File;<br>
+  const Archive::Symbol Sym;<br>
+};<br>
+<br>
+// Undefined symbols.<br>
+class Undefined : public SymbolBody {<br>
+public:<br>
+  explicit Undefined(StringRef N, SymbolBody **S = nullptr)<br>
+      : SymbolBody(UndefinedKind), Name(N), Alias(S) {}<br>
+<br>
+  static bool classof(const SymbolBody *S) {<br>
+    return S->kind() == UndefinedKind;<br>
+  }<br>
+  StringRef getName() override { return Name; }<br>
+<br>
+  // An undefined symbol can have a fallback symbol which gives an<br>
+  // undefined symbol a second chance if it would remain undefined.<br>
+  // If it remains undefined, it'll be replaced with whatever the<br>
+  // Alias pointer points to.<br>
+  SymbolBody *getWeakAlias() { return Alias ? *Alias : nullptr; }<br>
+<br>
+  int compare(SymbolBody *Other) override;<br>
+<br>
+private:<br>
+  StringRef Name;<br>
+  SymbolBody **Alias;<br>
+};<br>
+<br>
+class DefinedBitcode : public Defined {<br>
+public:<br>
+  DefinedBitcode(StringRef N, bool R)<br>
+      : Defined(DefinedBitcodeKind), Name(N), Replaceable(R) {}<br>
+<br>
+  static bool classof(const SymbolBody *S) {<br>
+    return S->kind() == DefinedBitcodeKind;<br>
+  }<br>
+<br>
+  StringRef getName() override { return Name; }<br>
+  uint64_t getVA() override { llvm_unreachable("bitcode reached writer"); }<br>
+  uint64_t getFileOff() override { llvm_unreachable("bitcode reached writer"); }<br>
+  int compare(SymbolBody *Other) override;<br>
+<br>
+private:<br>
+  StringRef Name;<br>
+  bool Replaceable;<br>
+};<br>
+<br>
+} // namespace elfv2<br>
+} // namespace lld<br>
+<br>
+#endif<br>
<br>
Added: lld/trunk/ELF/Writer.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_Writer.cpp-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=n-z6i0DG8u3BIiXOZwIDiY7PVjfvmqpzvqJgbTSL61I&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Writer.cpp (added)<br>
+++ lld/trunk/ELF/Writer.cpp Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,237 @@<br>
+//===- Writer.cpp ---------------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "Config.h"<br>
+#include "Writer.h"<br>
+#include "llvm/ADT/ArrayRef.h"<br>
+#include "llvm/ADT/Hashing.h"<br>
+#include "llvm/ADT/StringSwitch.h"<br>
+#include "llvm/ADT/STLExtras.h"<br>
+#include "llvm/Support/Debug.h"<br>
+#include "llvm/Support/Endian.h"<br>
+#include "llvm/Support/FileOutputBuffer.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+#include <algorithm><br>
+#include <cstdio><br>
+#include <functional><br>
+#include <unordered_map><br>
+#include <utility><br>
+<br>
+#include "llvm/Support/raw_ostream.h"<br>
+<br>
+using namespace llvm;<br>
+using namespace llvm::ELF;<br>
+using namespace llvm::object;<br>
+using namespace llvm::support;<br>
+using namespace llvm::support::endian;<br>
+<br>
+static const int PageSize = 4096;<br>
+<br>
+struct SectionTraits {<br>
+  uint64_t Type;<br>
+  uint64_t Flags;<br>
+  StringRef Name;<br>
+};<br>
+<br>
+bool operator==(const SectionTraits &A, const SectionTraits &B) {<br>
+  return A.Type == B.Type && A.Flags == B.Flags && A.Name == B.Name;<br>
+}<br>
+<br>
+namespace std {<br>
+template <> struct hash<SectionTraits> {<br>
+  size_t operator()(const SectionTraits &ST) const {<br>
+    return hash_combine(ST.Type, ST.Flags, ST.Name);<br>
+  }<br>
+};<br>
+}<br>
+<br>
+using namespace lld;<br>
+using namespace lld::elfv2;<br>
+<br>
+// The main function of the writer.<br>
+template <class ELFT><br>
+std::error_code Writer<ELFT>::write(StringRef OutputPath) {<br>
+  markLive();<br>
+  createSections();<br>
+  assignAddresses();<br>
+  removeEmptySections();<br>
+  if (auto EC = openFile(OutputPath))<br>
+    return EC;<br>
+  writeHeader();<br>
+  writeSections();<br>
+  return Buffer->commit();<br>
+}<br>
+<br>
+void OutputSection::setVA(uint64_t VA) {<br>
+  Header.sh_addr = VA;<br>
+  for (Chunk *C : Chunks)<br>
+    C->setVA(C->getVA() + VA);<br>
+}<br>
+<br>
+void OutputSection::setFileOffset(uint64_t Off) {<br>
+  if (Header.sh_size == 0)<br>
+    return;<br>
+  Header.sh_offset = Off;<br>
+  for (Chunk *C : Chunks)<br>
+    C->setFileOff(C->getFileOff() + Off);<br>
+}<br>
+<br>
+void OutputSection::addChunk(Chunk *C) {<br>
+  Chunks.push_back(C);<br>
+  C->setOutputSection(this);<br>
+  uint64_t Off = Header.sh_size;<br>
+  Off = RoundUpToAlignment(Off, C->getAlign());<br>
+  C->setVA(Off);<br>
+  C->setFileOff(Off);<br>
+  Off += C->getSize();<br>
+  Header.sh_size = Off;<br>
+}<br>
+<br>
+void OutputSection::addPermissions(uint32_t C) {<br>
+  // Header.Characteristics |= C & PermMask;<br>
+}<br>
+<br>
+// Write the section header to a given buffer.<br>
+void OutputSection::writeHeaderTo(uint8_t *Buf) {}<br>
+<br>
+// Set live bit on for each reachable chunk. Unmarked (unreachable)<br>
+// COMDAT chunks will be ignored in the next step, so that they don't<br>
+// come to the final output file.<br>
+template <class ELFT> void Writer<ELFT>::markLive() {<br>
+  if (!Config->DoGC)<br>
+    return;<br>
+  for (StringRef Name : Config->GCRoots)<br>
+    cast<Defined>(Symtab->find(Name))->markLive();<br>
+  for (Chunk *C : Symtab->getChunks())<br>
+    if (C->isRoot())<br>
+      C->markLive();<br>
+}<br>
+<br>
+static SectionTraits getChunkTraits(Chunk *C) {<br>
+  return {0, C->getFlags(), C->getSectionName()};<br>
+}<br>
+<br>
+// Create output section objects and add them to OutputSections.<br>
+template <class ELFT> void Writer<ELFT>::createSections() {<br>
+  std::unordered_map<SectionTraits, std::vector<Chunk *>> Map;<br>
+  for (Chunk *C : Symtab->getChunks()) {<br>
+    if (Config->DoGC && !C->isLive()) {<br>
+      if (Config->Verbose)<br>
+        C->printDiscardedMessage();<br>
+      continue;<br>
+    }<br>
+    Map[getChunkTraits(C)].push_back(C);<br>
+  }<br>
+<br>
+  for (auto &P : Map) {<br>
+    auto Sec = new (CAlloc.Allocate())<br>
+        OutputSection(<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__P.first.Name&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=utYUdhdcN-6eNNFhpmUEsOHDED79NmRjPblmSZWaiVA&e=" rel="noreferrer" target="_blank">P.first.Name</a>, OutputSections.size());<br>
+    OutputSections.push_back(Sec);<br>
+    for (Chunk *C : P.second) {<br>
+      Sec->addChunk(C);<br>
+      Sec->addPermissions(C->getFlags());<br>
+    }<br>
+  }<br>
+}<br>
+<br>
+template <class ELFT> void Writer<ELFT>::removeEmptySections() {<br>
+  auto IsEmpty = [](OutputSection *S) { return S->getSize() == 0; };<br>
+  OutputSections.erase(<br>
+      std::remove_if(OutputSections.begin(), OutputSections.end(), IsEmpty),<br>
+      OutputSections.end());<br>
+}<br>
+<br>
+// Visits all sections to assign incremental, non-overlapping RVAs and<br>
+// file offsets.<br>
+template <class ELFT> void Writer<ELFT>::assignAddresses() {<br>
+  SizeOfHeaders = RoundUpToAlignment(sizeof(Elf_Ehdr_Impl<ELFT>) +<br>
+                                         sizeof(Elf_Shdr_Impl<ELFT>) *<br>
+                                             OutputSections.size(),<br>
+                                     PageSize);<br>
+  uint64_t VA = 0x1000; // The first page is kept unmapped.<br>
+  uint64_t FileOff = SizeOfHeaders;<br>
+  for (OutputSection *Sec : OutputSections) {<br>
+    Sec->setVA(VA);<br>
+    Sec->setFileOffset(FileOff);<br>
+    VA += RoundUpToAlignment(Sec->getSize(), PageSize);<br>
+    FileOff += RoundUpToAlignment(Sec->getSize(), 8);<br>
+  }<br>
+  SizeOfImage = SizeOfHeaders + RoundUpToAlignment(VA - 0x1000, PageSize);<br>
+  FileSize = SizeOfHeaders + RoundUpToAlignment(FileOff - SizeOfHeaders, 8);<br>
+}<br>
+<br>
+template <class ELFT> void Writer<ELFT>::writeHeader() {<br>
+  uint8_t *Buf = Buffer->getBufferStart();<br>
+  auto *EHdr = reinterpret_cast<Elf_Ehdr_Impl<ELFT> *>(Buf);<br>
+  EHdr->e_ident[EI_MAG0] = 0x7F;<br>
+  EHdr->e_ident[EI_MAG1] = 0x45;<br>
+  EHdr->e_ident[EI_MAG2] = 0x4C;<br>
+  EHdr->e_ident[EI_MAG3] = 0x46;<br>
+  EHdr->e_ident[EI_CLASS] = ELFCLASS64;<br>
+  EHdr->e_ident[EI_DATA] = ELFDATA2LSB;<br>
+  EHdr->e_ident[EI_VERSION] = EV_CURRENT;<br>
+  EHdr->e_ident[EI_OSABI] = ELFOSABI_GNU;<br>
+<br>
+  EHdr->e_type = ET_EXEC;<br>
+  EHdr->e_machine = EM_X86_64;<br>
+  EHdr->e_version = EV_CURRENT;<br>
+  EHdr->e_entry = 0x401000;<br>
+  EHdr->e_phoff = sizeof(Elf_Ehdr_Impl<ELFT>);<br>
+  EHdr->e_shoff = 0;<br>
+  EHdr->e_ehsize = sizeof(Elf_Ehdr_Impl<ELFT>);<br>
+  EHdr->e_phentsize = sizeof(Elf_Phdr_Impl<ELFT>);<br>
+  EHdr->e_phnum = 1;<br>
+  EHdr->e_shentsize = sizeof(Elf_Shdr_Impl<ELFT>);<br>
+  EHdr->e_shnum = 0;<br>
+  EHdr->e_shstrndx = 0;<br>
+<br>
+  auto PHdrs = reinterpret_cast<Elf_Phdr_Impl<ELFT> *>(Buf + EHdr->e_phoff);<br>
+  PHdrs->p_type = PT_LOAD;<br>
+  PHdrs->p_flags = PF_R | PF_X;<br>
+  PHdrs->p_offset = 0x0000;<br>
+  PHdrs->p_vaddr = 0x400000;<br>
+  PHdrs->p_paddr = PHdrs->p_vaddr;<br>
+  PHdrs->p_filesz = FileSize;<br>
+  PHdrs->p_memsz = FileSize;<br>
+  PHdrs->p_align = 0x4000;<br>
+}<br>
+<br>
+template <class ELFT> std::error_code Writer<ELFT>::openFile(StringRef Path) {<br>
+  if (auto EC = FileOutputBuffer::create(Path, FileSize, Buffer,<br>
+                                         FileOutputBuffer::F_executable)) {<br>
+    llvm::errs() << "failed to open " << Path << ": " << EC.message() << "\n";<br>
+    return EC;<br>
+  }<br>
+  return std::error_code();<br>
+}<br>
+<br>
+// Write section contents to a mmap'ed file.<br>
+template <class ELFT> void Writer<ELFT>::writeSections() {<br>
+  uint8_t *Buf = Buffer->getBufferStart();<br>
+  for (OutputSection *Sec : OutputSections) {<br>
+    // Fill gaps between functions in .text with nop instructions instead of<br>
+    // leaving as null bytes (which can be interpreted as ADD instructions).<br>
+    if (Sec->getPermissions() & PF_X)<br>
+      memset(Buf + Sec->getFileOff(), 0x90, Sec->getSize());<br>
+    for (Chunk *C : Sec->getChunks())<br>
+      C->writeTo(Buf);<br>
+  }<br>
+}<br>
+<br>
+template <class ELFT> OutputSection *Writer<ELFT>::findSection(StringRef Name) {<br>
+  for (OutputSection *Sec : OutputSections)<br>
+    if (Sec->getName() == Name)<br>
+      return Sec;<br>
+  return nullptr;<br>
+}<br>
+<br>
+template class Writer<ELF32LE>;<br>
+template class Writer<ELF32BE>;<br>
+template class Writer<ELF64LE>;<br>
+template class Writer<ELF64BE>;<br>
<br>
Added: lld/trunk/ELF/Writer.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_ELF_Writer.h-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=mM1fDfLcrVH-90AG1tDAJLIkPoBp7tAgcDnxmuJm_hY&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.h?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Writer.h (added)<br>
+++ lld/trunk/ELF/Writer.h Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,91 @@<br>
+//===- Writer.h -----------------------------------------------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLD_ELF_WRITER_H<br>
+#define LLD_ELF_WRITER_H<br>
+<br>
+#include "InputFiles.h"<br>
+#include "SymbolTable.h"<br>
+#include "llvm/Support/ELF.h"<br>
+#include "llvm/Support/FileOutputBuffer.h"<br>
+#include <memory><br>
+#include <vector><br>
+<br>
+namespace lld {<br>
+namespace elfv2 {<br>
+<br>
+// OutputSection represents a section in an output file. It's a<br>
+// container of chunks. OutputSection and Chunk are 1:N relationship.<br>
+// Chunks cannot belong to more than one OutputSections. The writer<br>
+// creates multiple OutputSections and assign them unique,<br>
+// non-overlapping file offsets and VAs.<br>
+class OutputSection {<br>
+public:<br>
+  OutputSection(StringRef N, uint32_t SI)<br>
+      : Name(N), SectionIndex(SI), Header({}) {}<br>
+  void setVA(uint64_t);<br>
+  void setFileOffset(uint64_t);<br>
+  void addChunk(Chunk *C);<br>
+  StringRef getName() { return Name; }<br>
+  uint64_t getSectionIndex() { return SectionIndex; }<br>
+  std::vector<Chunk *> &getChunks() { return Chunks; }<br>
+  void addPermissions(uint32_t C);<br>
+  uint32_t getPermissions() { return 0; }<br>
+  uint64_t getVA() { return Header.sh_addr; }<br>
+  uint64_t getFileOff() { return Header.sh_offset; }<br>
+  void writeHeaderTo(uint8_t *Buf);<br>
+<br>
+  // Returns the size of the section in the output file.<br>
+  uint64_t getSize() { return Header.sh_size; }<br>
+<br>
+  // Set offset into the string table storing this section name.<br>
+  // Used only when the name is longer than 8 bytes.<br>
+  void setStringTableOff(uint32_t V) { StringTableOff = V; }<br>
+<br>
+private:<br>
+  StringRef Name;<br>
+  uint32_t SectionIndex;<br>
+  llvm::ELF::Elf64_Shdr Header;<br>
+  uint32_t StringTableOff = 0;<br>
+  std::vector<Chunk *> Chunks;<br>
+};<br>
+<br>
+// The writer writes a SymbolTable result to a file.<br>
+template <class ELFT> class Writer {<br>
+public:<br>
+  explicit Writer(SymbolTable<ELFT> *T) : Symtab(T) {}<br>
+  std::error_code write(StringRef Path);<br>
+<br>
+private:<br>
+  void markLive();<br>
+  void createSections();<br>
+  void assignAddresses();<br>
+  void removeEmptySections();<br>
+  std::error_code openFile(StringRef OutputPath);<br>
+  void writeHeader();<br>
+  void writeSections();<br>
+<br>
+  OutputSection *findSection(StringRef Name);<br>
+<br>
+  SymbolTable<ELFT> *Symtab;<br>
+  std::unique_ptr<llvm::FileOutputBuffer> Buffer;<br>
+  llvm::SpecificBumpPtrAllocator<OutputSection> CAlloc;<br>
+  std::vector<OutputSection *> OutputSections;<br>
+<br>
+  uint64_t FileSize;<br>
+  uint64_t SizeOfImage;<br>
+  uint64_t SizeOfHeaders;<br>
+<br>
+  std::vector<std::unique_ptr<Chunk>> Chunks;<br>
+};<br>
+<br>
+} // namespace elfv2<br>
+} // namespace lld<br>
+<br>
+#endif<br>
<br>
Modified: lld/trunk/include/lld/Driver/Driver.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_include_lld_Driver_Driver.h-3Frev-3D242088-26r1-3D242087-26r2-3D242088-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=7_8gZ-oVUeOcv6Qwqekmf9GHGgGQZ2qH6uu__Hxni2M&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/Driver.h?rev=242088&r1=242087&r2=242088&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/include/lld/Driver/Driver.h (original)<br>
+++ lld/trunk/include/lld/Driver/Driver.h Mon Jul 13 18:48:06 2015<br>
@@ -146,6 +146,10 @@ namespace coff {<br>
 bool link(llvm::ArrayRef<const char *> args);<br>
 }<br>
<br>
+namespace elfv2 {<br>
+bool link(llvm::ArrayRef<const char *> args);<br>
+}<br>
+<br>
 /// Driver for lld unit tests<br>
 class CoreDriver : public Driver {<br>
 public:<br>
<br>
Modified: lld/trunk/lib/Driver/UniversalDriver.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_lib_Driver_UniversalDriver.cpp-3Frev-3D242088-26r1-3D242087-26r2-3D242088-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=_LflTKom7q5GYbrx9pVO-v__7eh_iWQh8NcvlHKnZq8&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/UniversalDriver.cpp?rev=242088&r1=242087&r2=242088&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/Driver/UniversalDriver.cpp (original)<br>
+++ lld/trunk/lib/Driver/UniversalDriver.cpp Mon Jul 13 18:48:06 2015<br>
@@ -69,6 +69,7 @@ public:<br>
 enum class Flavor {<br>
   invalid,<br>
   gnu_ld,    // -flavor gnu<br>
+  gnu_ld2,   // -flavor gnu2<br>
   win_link,  // -flavor link<br>
   win_link2, // -flavor link2<br>
   darwin_ld, // -flavor darwin<br>
@@ -85,6 +86,7 @@ struct ProgramNameParts {<br>
 static Flavor strToFlavor(StringRef str) {<br>
   return llvm::StringSwitch<Flavor>(str)<br>
       .Case("gnu", Flavor::gnu_ld)<br>
+      .Case("gnu2", Flavor::gnu_ld2)<br>
       .Case("link", Flavor::win_link)<br>
       .Case("lld-link", Flavor::win_link)<br>
       .Case("link2", Flavor::win_link2)<br>
@@ -202,6 +204,8 @@ bool UniversalDriver::link(llvm::Mutable<br>
   switch (flavor) {<br>
   case Flavor::gnu_ld:<br>
     return GnuLdDriver::linkELF(args, diagnostics);<br>
+  case Flavor::gnu_ld2:<br>
+    return elfv2::link(args);<br>
   case Flavor::darwin_ld:<br>
     return DarwinLdDriver::linkMachO(args, diagnostics);<br>
   case Flavor::win_link:<br>
<br>
Added: lld/trunk/test/elfv2/basic.test<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_test_elfv2_basic.test-3Frev-3D242088-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=ftee1f04MhXK_uJbCoADkKGyzrxa6uE41rm0Kx9H3fM&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/elfv2/basic.test?rev=242088&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/elfv2/basic.test (added)<br>
+++ lld/trunk/test/elfv2/basic.test Mon Jul 13 18:48:06 2015<br>
@@ -0,0 +1,62 @@<br>
+# RUN: yaml2obj -format elf %s -o %t<br>
+# RUN: lld -flavor gnu2 %t -e _start -o %t2<br>
+# RUN: llvm-readobj -file-headers -program-headers %t2 | FileCheck %s<br>
+<br>
+FileHeader:<br>
+  Class:           ELFCLASS64<br>
+  Data:            ELFDATA2LSB<br>
+  OSABI:           ELFOSABI_GNU<br>
+  Type:            ET_REL<br>
+  Machine:         EM_X86_64<br>
+Sections:<br>
+  - Name:            .text<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         5548C7C03C00000048C7C7010000000F05<br>
+Symbols:<br>
+  Global:<br>
+    - Name:            _start<br>
+      Type:            STT_FUNC<br>
+      Section:         .text<br>
+<br>
+# CHECK: ElfHeader {<br>
+# CHECK:   Ident {<br>
+# CHECK:     Magic: (7F 45 4C 46)<br>
+# CHECK:     Class: 64-bit (0x2)<br>
+# CHECK:     DataEncoding: LittleEndian (0x1)<br>
+# CHECK:     FileVersion: 1<br>
+# CHECK:     OS/ABI: GNU/Linux (0x3)<br>
+# CHECK:     ABIVersion: 0<br>
+# CHECK:     Unused: (00 00 00 00 00 00 00)<br>
+# CHECK:   }<br>
+# CHECK:   Type: Executable (0x2)<br>
+# CHECK:   Machine: EM_X86_64 (0x3E)<br>
+# CHECK:   Version: 1<br>
+#  Entry: 0x401000<br>
+# CHECK:   ProgramHeaderOffset: 0x40<br>
+#  SectionHeaderOffset: 0x0<br>
+# CHECK:   Flags [ (0x0)<br>
+# CHECK:   ]<br>
+# CHECK:   HeaderSize: 64<br>
+# CHECK:   ProgramHeaderEntrySize: 56<br>
+#  ProgramHeaderCount: 1<br>
+# CHECK:   SectionHeaderEntrySize: 64<br>
+#  SectionHeaderCount: 0<br>
+#  StringTableSectionIndex: 0<br>
+# CHECK: }<br>
+# CHECK: ProgramHeaders [<br>
+# CHECK:   ProgramHeader {<br>
+# CHECK:     Type: PT_LOAD (0x1)<br>
+#    Offset: 0x0<br>
+#    VirtualAddress: 0x400000<br>
+#    PhysicalAddress: 0x400000<br>
+#    FileSize: 4128<br>
+#    MemSize: 4128<br>
+# CHECK:     Flags [ (0x5)<br>
+# CHECK:       PF_R (0x4)<br>
+# CHECK:       PF_X (0x1)<br>
+# CHECK:     ]<br>
+#    Alignment: 16384<br>
+# CHECK:   }<br>
+# CHECK: ]<br>
<br>
Modified: lld/trunk/tools/lld/CMakeLists.txt<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_tools_lld_CMakeLists.txt-3Frev-3D242088-26r1-3D242087-26r2-3D242088-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=UEMDIj_2o8JeZ5hyqUE6_tu9pwp4WnRo-K2uTGYNThE&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld/CMakeLists.txt?rev=242088&r1=242087&r2=242088&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/tools/lld/CMakeLists.txt (original)<br>
+++ lld/trunk/tools/lld/CMakeLists.txt Mon Jul 13 18:48:06 2015<br>
@@ -5,6 +5,7 @@ add_llvm_executable(lld<br>
 target_link_libraries(lld<br>
   lldDriver<br>
   lldCOFF<br>
+  lldELF2<br>
   LLVMSupport<br>
   )<br>
<br>
<br>
Modified: lld/trunk/unittests/DriverTests/CMakeLists.txt<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_unittests_DriverTests_CMakeLists.txt-3Frev-3D242088-26r1-3D242087-26r2-3D242088-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=abpYP-7R1Ck8glJI-kjNYJZRok2TZB36OPRVIgCxBW0&s=4rkerr71Jycz5U6nseRj52dzWALgVpz6BsuPDd8S3No&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/CMakeLists.txt?rev=242088&r1=242087&r2=242088&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/unittests/DriverTests/CMakeLists.txt (original)<br>
+++ lld/trunk/unittests/DriverTests/CMakeLists.txt Mon Jul 13 18:48:06 2015<br>
@@ -10,6 +10,7 @@ target_link_libraries(DriverTests<br>
   lldDriver<br>
   lldCOFF<br>
   lldCore<br>
+  lldELF2<br>
   lldPECOFF<br>
   lldMachO<br>
   )<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>