[lld] r242088 - Initial ELF port.

Adhemerval Zanella adhemerval.zanella at linaro.org
Tue Jul 14 04:24:39 PDT 2015



On 13-07-2015 22:34, Chandler Carruth wrote:
> On Mon, Jul 13, 2015 at 4:52 PM Michael J. Spencer <bigcheesegs at gmail.com <mailto:bigcheesegs at gmail.com>> wrote:
> 
>     Author: mspencer
>     Date: Mon Jul 13 18:48:06 2015
>     New Revision: 242088
> 
>     URL: http://llvm.org/viewvc/llvm-project?rev=242088&view=rev <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=XhDeonFi4DwUz8uoTJzQS5qq795Abl5oPo1Y4Yewmow&e=>
>     Log:
>     Initial ELF port.
> 
>     This is a direct port of the new PE/COFF linker to ELF.
> 
> 
> Did you discuss this with *anyone* else in the LLD community?
> 
> Dropping an *enourmous* patch like this without any review or discussion is completely unacceptable. Please revert this, and post a patch for review.
> 
> Even when Rui first did his COFF port, he posted it for review and discussed it prior to submitting it.
>  
> 

Indeed I really feel counterproductive to push this kinda of changes out of nowhere,
even now that some current ELF work is being done.  I am not against this patch and
based on previous lld rearchitecture thread section-based seems to be the desired 
direction, but we should at least set the general guidelines and aims current
developments to avoid either waste work and another possible 'rewrite'.

Also, I am currently aiming to make lld bootstrap itself at least for ELF/x86_64
and ELF/aarch64 (with latter in a more concise shape). So the idea is to abandon
current ELF port and rewrite using section-based architecture instead of the
atom one? Or will be to adjust current code?

> 
>     It can take a single object file and generate a valid executable that executes at the first byte in the text section.
> 
>     Added:
>         lld/trunk/ELF/
>         lld/trunk/ELF/CMakeLists.txt
>         lld/trunk/ELF/Chunks.cpp
>         lld/trunk/ELF/Chunks.h
>         lld/trunk/ELF/Config.h
>         lld/trunk/ELF/Driver.cpp
>         lld/trunk/ELF/Driver.h
>         lld/trunk/ELF/DriverUtils.cpp
>         lld/trunk/ELF/Error.h
>         lld/trunk/ELF/InputFiles.cpp
>         lld/trunk/ELF/InputFiles.h
>         lld/trunk/ELF/Options.td
>         lld/trunk/ELF/README.md
>         lld/trunk/ELF/SymbolTable.cpp
>         lld/trunk/ELF/SymbolTable.h
>         lld/trunk/ELF/Symbols.cpp
>         lld/trunk/ELF/Symbols.h
>         lld/trunk/ELF/Writer.cpp
>         lld/trunk/ELF/Writer.h
>         lld/trunk/test/elfv2/
>         lld/trunk/test/elfv2/basic.test
>     Modified:
>         lld/trunk/CMakeLists.txt
>         lld/trunk/include/lld/Driver/Driver.h
>         lld/trunk/lib/Driver/UniversalDriver.cpp
>         lld/trunk/tools/lld/CMakeLists.txt
>         lld/trunk/unittests/DriverTests/CMakeLists.txt
> 
>     Modified: lld/trunk/CMakeLists.txt
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/CMakeLists.txt?rev=242088&r1=242087&r2=242088&view=diff <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=Ay7cRyEwjMkHSWf_4clS8RJsovlTX0Wbi2K7uATZNis&e=>
>     ==============================================================================
>     --- lld/trunk/CMakeLists.txt (original)
>     +++ lld/trunk/CMakeLists.txt Mon Jul 13 18:48:06 2015
>     @@ -97,3 +97,4 @@ endif()
> 
>      add_subdirectory(docs)
>      add_subdirectory(COFF)
>     +add_subdirectory(ELF)
> 
>     Added: lld/trunk/ELF/CMakeLists.txt
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=Vbn9-ofDNH6DJ-YYwcuE9nsC-Tl66l6n9xfzVlIwP-I&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/CMakeLists.txt (added)
>     +++ lld/trunk/ELF/CMakeLists.txt Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,23 @@
>     +set(LLVM_TARGET_DEFINITIONS Options.td)
>     +tablegen(LLVM Options.inc -gen-opt-parser-defs)
>     +add_public_tablegen_target(ELFOptionsTableGen)
>     +
>     +add_llvm_library(lldELF2
>     +  Chunks.cpp
>     +  Driver.cpp
>     +  DriverUtils.cpp
>     +  InputFiles.cpp
>     +  SymbolTable.cpp
>     +  Symbols.cpp
>     +  Writer.cpp
>     +
>     +  LINK_COMPONENTS
>     +  ${LLVM_TARGETS_TO_BUILD}
>     +  Core
>     +  LTO
>     +  MC
>     +  MCDisassembler
>     +  Support
>     +  )
>     +
>     +add_dependencies(lldELF2 ELFOptionsTableGen)
> 
>     Added: lld/trunk/ELF/Chunks.cpp
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Chunks.cpp?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=rWgS_aTgl0FVX6yjQb6wEcHRXGfwCY4Br4Rv6F67wro&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/Chunks.cpp (added)
>     +++ lld/trunk/ELF/Chunks.cpp Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,125 @@
>     +//===- Chunks.cpp ---------------------------------------------------------===//
>     +//
>     +//                             The LLVM Linker
>     +//
>     +// This file is distributed under the University of Illinois Open Source
>     +// License. See LICENSE.TXT for details.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +
>     +#include "Chunks.h"
>     +#include "InputFiles.h"
>     +#include "Writer.h"
>     +#include "llvm/ADT/STLExtras.h"
>     +#include "llvm/Support/Debug.h"
>     +#include "llvm/Support/Endian.h"
>     +#include "llvm/Support/raw_ostream.h"
>     +
>     +using namespace llvm;
>     +using namespace llvm::object;
>     +using namespace llvm::support::endian;
>     +using namespace llvm::ELF;
>     +
>     +using namespace lld;
>     +using namespace lld::elfv2;
>     +
>     +template <class ELFT>
>     +SectionChunk<ELFT>::SectionChunk(elfv2::ObjectFile<ELFT> *F, const Elf_Shdr *H,
>     +                                 uint32_t SI)
>     +    : File(F), Header(H), SectionIndex(SI) {
>     +  // Initialize SectionName.
>     +  SectionName = *File->getObj()->getSectionName(Header);
>     +
>     +  Align = Header->sh_addralign;
>     +
>     +  // When a new chunk is created, we don't if if it's going to make it
>     +  // to the final output. Initially all sections are unmarked in terms
>     +  // of garbage collection. The writer will call markLive() to mark
>     +  // all reachable section chunks.
>     +  Live = false;
>     +
>     +  Root = true;
>     +}
>     +
>     +template <class ELFT> void SectionChunk<ELFT>::writeTo(uint8_t *Buf) {
>     +  if (!hasData())
>     +    return;
>     +  // Copy section contents from source object file to output file.
>     +  ArrayRef<uint8_t> Data = *File->getObj()->getSectionContents(Header);
>     +  memcpy(Buf + FileOff, Data.data(), Data.size());
>     +
>     +  // FIXME: Relocations
>     +}
>     +
>     +template <class ELFT> void SectionChunk<ELFT>::mark() {
>     +  assert(!Live);
>     +  Live = true;
>     +
>     +  // Mark all symbols listed in the relocation table for this section.
>     +  // FIXME: Relocations
>     +}
>     +
>     +static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); }
>     +static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }
>     +static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); }
>     +
>     +template <class ELFT>
>     +void SectionChunk<ELFT>::applyReloc(uint8_t *Buf, const Elf_Rela *Rel) {
>     +  // FIXME: Relocations
>     +}
>     +
>     +template <class ELFT>
>     +void SectionChunk<ELFT>::applyReloc(uint8_t *Buf, const Elf_Rel *Rel) {}
>     +
>     +template <class ELFT> bool SectionChunk<ELFT>::hasData() const {
>     +  return Header->sh_type != SHT_NOBITS;
>     +}
>     +
>     +template <class ELFT> uint32_t SectionChunk<ELFT>::getFlags() const {
>     +  return Header->sh_flags;
>     +}
>     +
>     +// Prints "Discarded <symbol>" for all external function symbols.
>     +template <class ELFT> void SectionChunk<ELFT>::printDiscardedMessage() {
>     +  auto Obj = File->getObj();
>     +
>     +  for (auto &&Sym : Obj->symbols()) {
>     +    auto Sec = Obj->getSection(&Sym);
>     +    if (Sec && *Sec != Header)
>     +      continue;
>     +    if (Sym.getType() != STT_FUNC)
>     +      continue;
>     +    if (auto Name = Obj->getStaticSymbolName(&Sym)) {
>     +      llvm::outs() << "Discarded " << *Name << " from " << File->getShortName()
>     +                   << "\n";
>     +    }
>     +  }
>     +}
>     +
>     +template <class ELFT>
>     +const llvm::object::Elf_Shdr_Impl<ELFT> *SectionChunk<ELFT>::getSectionHdr() {
>     +  return Header;
>     +}
>     +
>     +template <class ELFT>
>     +CommonChunk<ELFT>::CommonChunk(const Elf_Sym *S)
>     +    : Sym(S) {
>     +  // Alignment is a section attribute, but common symbols don't
>     +  // belong to any section. How do we know common data alignments?
>     +  // Needs investigating. For now, we set a large number as an alignment.
>     +  Align = 16;
>     +}
>     +
>     +template <class ELFT> uint32_t CommonChunk<ELFT>::getFlags() const {
>     +  return PF_R | PF_W;
>     +}
>     +
>     +template class SectionChunk<llvm::object::ELF32LE>;
>     +template class SectionChunk<llvm::object::ELF32BE>;
>     +template class SectionChunk<llvm::object::ELF64LE>;
>     +template class SectionChunk<llvm::object::ELF64BE>;
>     +
>     +template class CommonChunk<llvm::object::ELF32LE>;
>     +template class CommonChunk<llvm::object::ELF32BE>;
>     +template class CommonChunk<llvm::object::ELF64LE>;
>     +template class CommonChunk<llvm::object::ELF64BE>;
> 
>     Added: lld/trunk/ELF/Chunks.h
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Chunks.h?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=oEmvZfOpJBnpQhDa5mLxPIlpnFbzNIdNcIUplqYhi_M&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/Chunks.h (added)
>     +++ lld/trunk/ELF/Chunks.h Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,152 @@
>     +//===- Chunks.h -----------------------------------------------------------===//
>     +//
>     +//                             The LLVM Linker
>     +//
>     +// This file is distributed under the University of Illinois Open Source
>     +// License. See LICENSE.TXT for details.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +
>     +#ifndef LLD_ELF_CHUNKS_H
>     +#define LLD_ELF_CHUNKS_H
>     +
>     +#include "lld/Core/LLVM.h"
>     +#include "llvm/ADT/ArrayRef.h"
>     +#include "llvm/Object/ELF.h"
>     +#include <map>
>     +#include <vector>
>     +
>     +namespace lld {
>     +namespace elfv2 {
>     +
>     +class Defined;
>     +template <class ELFT> class ObjectFile;
>     +class OutputSection;
>     +
>     +// A Chunk represents a chunk of data that will occupy space in the
>     +// output (if the resolver chose that). It may or may not be backed by
>     +// a section of an input file. It could be linker-created data, or
>     +// doesn't even have actual data (if common or bss).
>     +class Chunk {
>     +public:
>     +  virtual ~Chunk() = default;
>     +
>     +  // Returns the size of this chunk (even if this is a common or BSS.)
>     +  virtual size_t getSize() const = 0;
>     +
>     +  // Write this chunk to a mmap'ed file, assuming Buf is pointing to
>     +  // beginning of the file. Because this function may use VA values
>     +  // of other chunks for relocations, you need to set them properly
>     +  // before calling this function.
>     +  virtual void writeTo(uint8_t *Buf) {}
>     +
>     +  // The writer sets and uses the addresses.
>     +  uint64_t getVA() { return VA; }
>     +  uint64_t getFileOff() { return FileOff; }
>     +  uint32_t getAlign() { return Align; }
>     +  void setVA(uint64_t V) { VA = V; }
>     +  void setFileOff(uint64_t V) { FileOff = V; }
>     +
>     +  // Returns true if this has non-zero data. BSS chunks return
>     +  // false. If false is returned, the space occupied by this chunk
>     +  // will be filled with zeros.
>     +  virtual bool hasData() const { return true; }
>     +
>     +  // Returns readable/writable/executable bits.
>     +  virtual uint32_t getFlags() const { return 0; }
>     +
>     +  // Returns the section name if this is a section chunk.
>     +  // It is illegal to call this function on non-section chunks.
>     +  virtual StringRef getSectionName() const {
>     +    llvm_unreachable("unimplemented getSectionName");
>     +  }
>     +
>     +  // Called if the garbage collector decides to not include this chunk
>     +  // in a final output. It's supposed to print out a log message to stdout.
>     +  // It is illegal to call this function on non-section chunks because
>     +  // only section chunks are subject of garbage collection.
>     +  virtual void printDiscardedMessage() {
>     +    llvm_unreachable("unimplemented printDiscardedMessage");
>     +  }
>     +
>     +  // Used by the garbage collector.
>     +  bool isRoot() { return Root; }
>     +  bool isLive() { return Live; }
>     +  void markLive() {
>     +    if (!Live)
>     +      mark();
>     +  }
>     +
>     +  // An output section has pointers to chunks in the section, and each
>     +  // chunk has a back pointer to an output section.
>     +  void setOutputSection(OutputSection *O) { Out = O; }
>     +  OutputSection *getOutputSection() { return Out; }
>     +
>     +protected:
>     +  // The VA of this chunk in the output. The writer sets a value.
>     +  uint64_t VA = 0;
>     +
>     +  // The offset from beginning of the output file. The writer sets a value.
>     +  uint64_t FileOff = 0;
>     +
>     +  // The output section for this chunk.
>     +  OutputSection *Out = nullptr;
>     +
>     +  // The alignment of this chunk. The writer uses the value.
>     +  uint32_t Align = 1;
>     +
>     +  // Used by the garbage collector.
>     +  virtual void mark() {}
>     +  bool Live = true;
>     +  bool Root = false;
>     +};
>     +
>     +// A chunk corresponding a section of an input file.
>     +template <class ELFT> class SectionChunk : public Chunk {
>     +  typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
>     +  typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
>     +  typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
>     +
>     +public:
>     +  SectionChunk(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
>     +               uint32_t SectionIndex);
>     +  size_t getSize() const override { return Header->sh_size; }
>     +  void writeTo(uint8_t *Buf) override;
>     +  bool hasData() const override;
>     +  uint32_t getFlags() const override;
>     +  StringRef getSectionName() const override { return SectionName; }
>     +  void printDiscardedMessage() override;
>     +
>     +private:
>     +  void mark() override;
>     +  const Elf_Shdr *getSectionHdr();
>     +  void applyReloc(uint8_t *Buf, const Elf_Rela *Rel);
>     +  void applyReloc(uint8_t *Buf, const Elf_Rel *Rel);
>     +
>     +  // A file this chunk was created from.
>     +  ObjectFile<ELFT> *File;
>     +
>     +  const Elf_Shdr *Header;
>     +  uint32_t SectionIndex;
>     +  StringRef SectionName;
>     +};
>     +
>     +// A chunk for common symbols. Common chunks don't have actual data.
>     +template <class ELFT> class CommonChunk : public Chunk {
>     +  typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
>     +
>     +public:
>     +  CommonChunk(const Elf_Sym *Sym);
>     +  size_t getSize() const override { return Sym->getValue(); }
>     +  bool hasData() const override { return false; }
>     +  uint32_t getFlags() const override;
>     +  StringRef getSectionName() const override { return ".bss"; }
>     +
>     +private:
>     +  const Elf_Sym *Sym;
>     +};
>     +
>     +} // namespace elfv2
>     +} // namespace lld
>     +
>     +#endif
> 
>     Added: lld/trunk/ELF/Config.h
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=KdPWzc8AOCWmr9yfNcRat8FjZsduDnRfBaqOPQm4uVw&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/Config.h (added)
>     +++ lld/trunk/ELF/Config.h Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,40 @@
>     +//===- Config.h -----------------------------------------------------------===//
>     +//
>     +//                             The LLVM Linker
>     +//
>     +// This file is distributed under the University of Illinois Open Source
>     +// License. See LICENSE.TXT for details.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +
>     +#ifndef LLD_ELF_CONFIG_H
>     +#define LLD_ELF_CONFIG_H
>     +
>     +#include "llvm/ADT/StringRef.h"
>     +#include "llvm/Object/ELF.h"
>     +#include <set>
>     +#include <string>
>     +
>     +namespace lld {
>     +namespace elfv2 {
>     +
>     +using llvm::StringRef;
>     +
>     +class Configuration {
>     +public:
>     +  int MachineArchitecture = llvm::ELF::EM_X86_64;
>     +  bool Verbose = false;
>     +  StringRef EntryName;
>     +  std::string OutputFile;
>     +  bool DoGC = true;
>     +
>     +  // Symbols in this set are considered as live by the garbage collector.
>     +  std::set<StringRef> GCRoots;
>     +};
>     +
>     +extern Configuration *Config;
>     +
>     +} // namespace elfv2
>     +} // namespace lld
>     +
>     +#endif
> 
>     Added: lld/trunk/ELF/Driver.cpp
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=VBJI9KXAnrVRaT5OaV4GWOH-6IIhrLqgecai-ZRqXks&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/Driver.cpp (added)
>     +++ lld/trunk/ELF/Driver.cpp Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,240 @@
>     +//===- Driver.cpp ---------------------------------------------------------===//
>     +//
>     +//                             The LLVM Linker
>     +//
>     +// This file is distributed under the University of Illinois Open Source
>     +// License. See LICENSE.TXT for details.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +
>     +#include "Config.h"
>     +#include "Driver.h"
>     +#include "InputFiles.h"
>     +#include "SymbolTable.h"
>     +#include "Writer.h"
>     +#include "llvm/ADT/Optional.h"
>     +#include "llvm/ADT/STLExtras.h"
>     +#include "llvm/ADT/StringSwitch.h"
>     +#include "llvm/LibDriver/LibDriver.h"
>     +#include "llvm/Option/Arg.h"
>     +#include "llvm/Option/ArgList.h"
>     +#include "llvm/Option/Option.h"
>     +#include "llvm/Support/CommandLine.h"
>     +#include "llvm/Support/Debug.h"
>     +#include "llvm/Support/Path.h"
>     +#include "llvm/Support/Process.h"
>     +#include "llvm/Support/TargetSelect.h"
>     +#include "llvm/Support/raw_ostream.h"
>     +#include <algorithm>
>     +#include <memory>
>     +
>     +using namespace llvm;
>     +using llvm::sys::fs::file_magic;
>     +using llvm::sys::fs::identify_magic;
>     +
>     +using namespace lld;
>     +using namespace lld::elfv2;
>     +
>     +namespace lld {
>     +namespace elfv2 {
>     +Configuration *Config;
>     +LinkerDriver *Driver;
>     +
>     +bool link(llvm::ArrayRef<const char *> Args) {
>     +  auto C = make_unique<Configuration>();
>     +  Config = C.get();
>     +  auto D = make_unique<LinkerDriver>();
>     +  Driver = D.get();
>     +  return Driver->link(Args);
>     +}
>     +}
>     +}
>     +
>     +// Drop directory components and replace extension with ".exe".
>     +static std::string getOutputPath(StringRef Path) {
>     +  auto P = Path.find_last_of("\\/");
>     +  StringRef S = (P == StringRef::npos) ? Path : Path.substr(P + 1);
>     +  return (S.substr(0, S.rfind('.')) + ".exe").str();
>     +}
>     +
>     +// Opens a file. Path has to be resolved already.
>     +// Newly created memory buffers are owned by this driver.
>     +ErrorOr<MemoryBufferRef> LinkerDriver::openFile(StringRef Path) {
>     +  auto MBOrErr = MemoryBuffer::getFile(Path);
>     +  if (auto EC = MBOrErr.getError())
>     +    return EC;
>     +  std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get());
>     +  MemoryBufferRef MBRef = MB->getMemBufferRef();
>     +  OwningMBs.push_back(std::move(MB)); // take ownership
>     +  return MBRef;
>     +}
>     +
>     +static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB) {
>     +  // File type is detected by contents, not by file extension.
>     +  file_magic Magic = identify_magic(MB.getBuffer());
>     +  if (Magic == file_magic::archive)
>     +    return std::unique_ptr<InputFile>(new ArchiveFile(MB));
>     +  if (Magic == file_magic::bitcode)
>     +    return std::unique_ptr<InputFile>(new BitcodeFile(MB));
>     +  if (Config->OutputFile == "")
>     +    Config->OutputFile = getOutputPath(MB.getBufferIdentifier());
>     +  return std::unique_ptr<InputFile>(new ObjectFile<llvm::object::ELF64LE>(MB));
>     +}
>     +
>     +// Find file from search paths. You can omit ".obj", this function takes
>     +// care of that. Note that the returned path is not guaranteed to exist.
>     +StringRef LinkerDriver::doFindFile(StringRef Filename) {
>     +  bool hasPathSep = (Filename.find_first_of("/\\") != StringRef::npos);
>     +  if (hasPathSep)
>     +    return Filename;
>     +  bool hasExt = (Filename.find('.') != StringRef::npos);
>     +  for (StringRef Dir : SearchPaths) {
>     +    SmallString<128> Path = Dir;
>     +    llvm::sys::path::append(Path, Filename);
>     +    if (llvm::sys::fs::exists(Path.str()))
>     +      return Alloc.save(Path.str());
>     +    if (!hasExt) {
>     +      Path.append(".obj");
>     +      if (llvm::sys::fs::exists(Path.str()))
>     +        return Alloc.save(Path.str());
>     +    }
>     +  }
>     +  return Filename;
>     +}
>     +
>     +// Resolves a file path. This never returns the same path
>     +// (in that case, it returns None).
>     +Optional<StringRef> LinkerDriver::findFile(StringRef Filename) {
>     +  StringRef Path = doFindFile(Filename);
>     +  bool Seen = !VisitedFiles.insert(Path.lower()).second;
>     +  if (Seen)
>     +    return None;
>     +  return Path;
>     +}
>     +
>     +// Find library file from search path.
>     +StringRef LinkerDriver::doFindLib(StringRef Filename) {
>     +  // Add ".lib" to Filename if that has no file extension.
>     +  bool hasExt = (Filename.find('.') != StringRef::npos);
>     +  if (!hasExt)
>     +    Filename = Alloc.save(Filename + ".lib");
>     +  return doFindFile(Filename);
>     +}
>     +
>     +// Resolves a library path. /nodefaultlib options are taken into
>     +// consideration. This never returns the same path (in that case,
>     +// it returns None).
>     +Optional<StringRef> LinkerDriver::findLib(StringRef Filename) {
>     +  StringRef Path = doFindLib(Filename);
>     +  bool Seen = !VisitedFiles.insert(Path.lower()).second;
>     +  if (Seen)
>     +    return None;
>     +  return Path;
>     +}
>     +
>     +bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
>     +  // Needed for LTO.
>     +  llvm::InitializeAllTargetInfos();
>     +  llvm::InitializeAllTargets();
>     +  llvm::InitializeAllTargetMCs();
>     +  llvm::InitializeAllAsmParsers();
>     +  llvm::InitializeAllAsmPrinters();
>     +  llvm::InitializeAllDisassemblers();
>     +
>     +  // Parse command line options.
>     +  auto ArgsOrErr = Parser.parse(ArgsArr);
>     +  if (auto EC = ArgsOrErr.getError()) {
>     +    llvm::errs() << EC.message() << "\n";
>     +    return false;
>     +  }
>     +  llvm::opt::InputArgList Args = std::move(ArgsOrErr.get());
>     +
>     +  // Handle /help
>     +  if (Args.hasArg(OPT_help)) {
>     +    printHelp(ArgsArr[0]);
>     +    return true;
>     +  }
>     +
>     +  if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end()) {
>     +    llvm::errs() << "no input files.\n";
>     +    return false;
>     +  }
>     +
>     +  // Construct search path list.
>     +  SearchPaths.push_back("");
>     +  for (auto *Arg : Args.filtered(OPT_L))
>     +    SearchPaths.push_back(Arg->getValue());
>     +
>     +  // Handle /out
>     +  if (auto *Arg = Args.getLastArg(OPT_output))
>     +    Config->OutputFile = Arg->getValue();
>     +
>     +  // Handle /entry
>     +  if (auto *Arg = Args.getLastArg(OPT_e))
>     +    Config->EntryName = Arg->getValue();
>     +
>     +  // Create a list of input files. Files can be given as arguments
>     +  // for /defaultlib option.
>     +  std::vector<StringRef> InputPaths;
>     +  std::vector<MemoryBufferRef> Inputs;
>     +  for (auto *Arg : Args.filtered(OPT_INPUT))
>     +    if (Optional<StringRef> Path = findFile(Arg->getValue()))
>     +      InputPaths.push_back(*Path);
>     +
>     +  for (StringRef Path : InputPaths) {
>     +    ErrorOr<MemoryBufferRef> MBOrErr = openFile(Path);
>     +    if (auto EC = MBOrErr.getError()) {
>     +      llvm::errs() << "cannot open " << Path << ": " << EC.message() << "\n";
>     +      return false;
>     +    }
>     +    Inputs.push_back(MBOrErr.get());
>     +  }
>     +
>     +  // Create a symbol table.
>     +  SymbolTable<llvm::object::ELF64LE> Symtab;
>     +
>     +  // Parse all input files and put all symbols to the symbol table.
>     +  // The symbol table will take care of name resolution.
>     +  for (MemoryBufferRef MB : Inputs) {
>     +    std::unique_ptr<InputFile> File = createFile(MB);
>     +    if (Config->Verbose)
>     +      llvm::outs() << "Reading " << File->getName() << "\n";
>     +    if (auto EC = Symtab.addFile(std::move(File))) {
>     +      llvm::errs() << MB.getBufferIdentifier() << ": " << EC.message() << "\n";
>     +      return false;
>     +    }
>     +  }
>     +
>     +  // Resolve auxiliary symbols until converge.
>     +  // (Trying to resolve a symbol may trigger a Lazy symbol to load a new file.
>     +  // A new file may contain a directive section to add new command line options.
>     +  // That's why we have to repeat until converge.)
>     +  /*for (;;) {
>     +    size_t Ver = Symtab.getVersion();
>     +
>     +    if (Ver == Symtab.getVersion())
>     +      break;
>     +  }*/
>     +
>     +  // Make sure we have resolved all symbols.
>     +  if (Symtab.reportRemainingUndefines())
>     +    return false;
>     +
>     +  // Initialize a list of GC root.
>     +  Config->GCRoots.insert(Config->EntryName);
>     +
>     +  // Do LTO by compiling bitcode input files to a native ELF file
>     +  // then link that file.
>     +  if (auto EC = Symtab.addCombinedLTOObject()) {
>     +    llvm::errs() << EC.message() << "\n";
>     +    return false;
>     +  }
>     +
>     +  // Write the result.
>     +  Writer<llvm::object::ELF64LE> Out(&Symtab);
>     +  if (auto EC = Out.write(Config->OutputFile)) {
>     +    llvm::errs() << EC.message() << "\n";
>     +    return false;
>     +  }
>     +  return true;
>     +}
> 
>     Added: lld/trunk/ELF/Driver.h
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.h?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=KoSpixY-HBbz3KqKStxD6HfU6Z7J-BbU5aH_V5QH0z0&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/Driver.h (added)
>     +++ lld/trunk/ELF/Driver.h Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,102 @@
>     +//===- Driver.h -----------------------------------------------------------===//
>     +//
>     +//                             The LLVM Linker
>     +//
>     +// This file is distributed under the University of Illinois Open Source
>     +// License. See LICENSE.TXT for details.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +
>     +#ifndef LLD_ELF_DRIVER_H
>     +#define LLD_ELF_DRIVER_H
>     +
>     +#include "lld/Core/LLVM.h"
>     +#include "llvm/ADT/Optional.h"
>     +#include "llvm/ADT/StringRef.h"
>     +#include "llvm/Object/ELF.h"
>     +#include "llvm/Option/Arg.h"
>     +#include "llvm/Option/ArgList.h"
>     +#include "llvm/Support/StringSaver.h"
>     +#include <memory>
>     +#include <set>
>     +#include <system_error>
>     +#include <vector>
>     +
>     +namespace lld {
>     +namespace elfv2 {
>     +
>     +class LinkerDriver;
>     +extern LinkerDriver *Driver;
>     +
>     +using llvm::Optional;
>     +class InputFile;
>     +
>     +// Entry point of the ELF linker.
>     +bool link(llvm::ArrayRef<const char *> Args);
>     +
>     +class ArgParser {
>     +public:
>     +  ArgParser() : Alloc(AllocAux) {}
>     +  // Parses command line options.
>     +  ErrorOr<llvm::opt::InputArgList> parse(llvm::ArrayRef<const char *> Args);
>     +
>     +  // Tokenizes a given string and then parses as command line options.
>     +  ErrorOr<llvm::opt::InputArgList> parse(StringRef S) {
>     +    return parse(tokenize(S));
>     +  }
>     +
>     +private:
>     +  ErrorOr<llvm::opt::InputArgList> parse(std::vector<const char *> Argv);
>     +
>     +  std::vector<const char *> tokenize(StringRef S);
>     +
>     +  ErrorOr<std::vector<const char *>>
>     +  replaceResponseFiles(std::vector<const char *>);
>     +
>     +  llvm::BumpPtrAllocator AllocAux;
>     +  llvm::BumpPtrStringSaver Alloc;
>     +};
>     +
>     +class LinkerDriver {
>     +public:
>     +  LinkerDriver() : Alloc(AllocAux) {}
>     +  bool link(llvm::ArrayRef<const char *> Args);
>     +
>     +private:
>     +  llvm::BumpPtrAllocator AllocAux;
>     +  llvm::BumpPtrStringSaver Alloc;
>     +  ArgParser Parser;
>     +
>     +  // Opens a file. Path has to be resolved already.
>     +  ErrorOr<MemoryBufferRef> openFile(StringRef Path);
>     +
>     +  // Searches a file from search paths.
>     +  Optional<StringRef> findFile(StringRef Filename);
>     +  Optional<StringRef> findLib(StringRef Filename);
>     +  StringRef doFindFile(StringRef Filename);
>     +  StringRef doFindLib(StringRef Filename);
>     +
>     +  std::vector<StringRef> SearchPaths;
>     +  std::set<std::string> VisitedFiles;
>     +
>     +  // Driver is the owner of all opened files.
>     +  // InputFiles have MemoryBufferRefs to them.
>     +  std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
>     +};
>     +
>     +// Functions below this line are defined in DriverUtils.cpp.
>     +
>     +void printHelp(const char *Argv0);
>     +
>     +// Create enum with OPT_xxx values for each option in Options.td
>     +enum {
>     +  OPT_INVALID = 0,
>     +#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID,
>     +#include "Options.inc"
>     +#undef OPTION
>     +};
>     +
>     +} // namespace elfv2
>     +} // namespace lld
>     +
>     +#endif
> 
>     Added: lld/trunk/ELF/DriverUtils.cpp
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/DriverUtils.cpp?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=xLLIr7G843pmkkhNjUW3lpgx_LcminfAdu6dWBBy7Eo&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/DriverUtils.cpp (added)
>     +++ lld/trunk/ELF/DriverUtils.cpp Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,121 @@
>     +//===- DriverUtils.cpp ----------------------------------------------------===//
>     +//
>     +//                             The LLVM Linker
>     +//
>     +// This file is distributed under the University of Illinois Open Source
>     +// License. See LICENSE.TXT for details.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +//
>     +// This file contains utility functions for the driver. Because there
>     +// are so many small functions, we created this separate file to make
>     +// Driver.cpp less cluttered.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +
>     +#include "Config.h"
>     +#include "Driver.h"
>     +#include "Error.h"
>     +#include "llvm/ADT/Optional.h"
>     +#include "llvm/ADT/STLExtras.h"
>     +#include "llvm/ADT/StringSwitch.h"
>     +#include "llvm/Option/Arg.h"
>     +#include "llvm/Option/ArgList.h"
>     +#include "llvm/Option/Option.h"
>     +#include "llvm/Support/CommandLine.h"
>     +#include "llvm/Support/Process.h"
>     +#include "llvm/Support/Program.h"
>     +#include "llvm/Support/raw_ostream.h"
>     +#include <memory>
>     +
>     +using namespace llvm;
>     +using llvm::cl::ExpandResponseFiles;
>     +using llvm::cl::TokenizeWindowsCommandLine;
>     +using llvm::sys::Process;
>     +
>     +using namespace lld;
>     +using namespace lld::elfv2;
>     +
>     +// Create OptTable
>     +
>     +// Create prefix string literals used in Options.td
>     +#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
>     +#include "Options.inc"
>     +#undef PREFIX
>     +
>     +// Create table mapping all options defined in Options.td
>     +static const llvm::opt::OptTable::Info infoTable[] = {
>     +#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10)            \
>     +  {                                                                            \
>     +    X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7,         \
>     +        OPT_##GROUP, OPT_##ALIAS, X6                                           \
>     +  }                                                                            \
>     +  ,
>     +#include "Options.inc"
>     +#undef OPTION
>     +};
>     +
>     +class ELFOptTable : public llvm::opt::OptTable {
>     +public:
>     +  ELFOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)) {}
>     +};
>     +
>     +// Parses a given list of options.
>     +ErrorOr<llvm::opt::InputArgList>
>     +ArgParser::parse(std::vector<const char *> Argv) {
>     +  // First, replace respnose files (@<file>-style options).
>     +  auto ArgvOrErr = replaceResponseFiles(Argv);
>     +  if (auto EC = ArgvOrErr.getError()) {
>     +    llvm::errs() << "error while reading response file: " << EC.message()
>     +                 << "\n";
>     +    return EC;
>     +  }
>     +  Argv = std::move(ArgvOrErr.get());
>     +
>     +  // Make InputArgList from string vectors.
>     +  ELFOptTable Table;
>     +  unsigned MissingIndex;
>     +  unsigned MissingCount;
>     +
>     +  llvm::opt::InputArgList Args =
>     +      Table.ParseArgs(Argv, MissingIndex, MissingCount);
>     +  if (MissingCount) {
>     +    llvm::errs() << "missing arg value for \""
>     +                 << Args.getArgString(MissingIndex) << "\", expected "
>     +                 << MissingCount
>     +                 << (MissingCount == 1 ? " argument.\n" : " arguments.\n");
>     +    return make_error_code(LLDError::InvalidOption);
>     +  }
>     +  for (auto *Arg : Args.filtered(OPT_UNKNOWN))
>     +    llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n";
>     +  return std::move(Args);
>     +}
>     +
>     +ErrorOr<llvm::opt::InputArgList>
>     +ArgParser::parse(llvm::ArrayRef<const char *> Args) {
>     +  Args = Args.slice(1);
>     +  std::vector<const char *> V(Args.begin(), Args.end());
>     +  return parse(V);
>     +}
>     +
>     +std::vector<const char *> ArgParser::tokenize(StringRef S) {
>     +  SmallVector<const char *, 16> Tokens;
>     +  BumpPtrStringSaver Saver(AllocAux);
>     +  llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens);
>     +  return std::vector<const char *>(Tokens.begin(), Tokens.end());
>     +}
>     +
>     +// Creates a new command line by replacing options starting with '@'
>     +// character. '@<filename>' is replaced by the file's contents.
>     +ErrorOr<std::vector<const char *>>
>     +ArgParser::replaceResponseFiles(std::vector<const char *> Argv) {
>     +  SmallVector<const char *, 256> Tokens(Argv.data(), Argv.data() + Argv.size());
>     +  BumpPtrStringSaver Saver(AllocAux);
>     +  ExpandResponseFiles(Saver, TokenizeWindowsCommandLine, Tokens);
>     +  return std::vector<const char *>(Tokens.begin(), Tokens.end());
>     +}
>     +
>     +void lld::elfv2::printHelp(const char *Argv0) {
>     +  ELFOptTable Table;
>     +  Table.PrintHelp(llvm::outs(), Argv0, "LLVM Linker", false);
>     +}
> 
>     Added: lld/trunk/ELF/Error.h
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Error.h?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=IFaVVRfcAAc3gu4wxLBEbJvyOqAEFa3GOozMA47-6uM&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/Error.h (added)
>     +++ lld/trunk/ELF/Error.h Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,54 @@
>     +//===- Error.h ------------------------------------------------------------===//
>     +//
>     +//                             The LLVM Linker
>     +//
>     +// This file is distributed under the University of Illinois Open Source
>     +// License. See LICENSE.TXT for details.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +
>     +#ifndef LLD_ELF_ERROR_H
>     +#define LLD_ELF_ERROR_H
>     +
>     +#include <string>
>     +#include <system_error>
>     +#include "llvm/Support/ErrorHandling.h"
>     +
>     +namespace lld {
>     +namespace elfv2 {
>     +
>     +enum class LLDError {
>     +  InvalidOption = 1,
>     +  InvalidFile,
>     +  BrokenFile,
>     +  DuplicateSymbols,
>     +};
>     +
>     +class LLDErrorCategory : public std::error_category {
>     +public:
>     +  const char *name() const LLVM_NOEXCEPT override { return "lld"; }
>     +
>     +  std::string message(int EV) const override {
>     +    switch (static_cast<LLDError>(EV)) {
>     +    case LLDError::InvalidOption:
>     +      return "Invalid option";
>     +    case LLDError::InvalidFile:
>     +      return "Invalid file";
>     +    case LLDError::BrokenFile:
>     +      return "Broken file";
>     +    case LLDError::DuplicateSymbols:
>     +      return "Duplicate symbols";
>     +    }
>     +    llvm_unreachable("unknown error");
>     +  }
>     +};
>     +
>     +inline std::error_code make_error_code(LLDError Err) {
>     +  static LLDErrorCategory C;
>     +  return std::error_code(static_cast<int>(Err), C);
>     +}
>     +
>     +} // namespace elfv2
>     +} // namespace lld
>     +
>     +#endif
> 
>     Added: lld/trunk/ELF/InputFiles.cpp
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=7qcRJq2MDQF8ZSPtt_2YZwlEFqwimFBO4EBuJf51Hz8&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/InputFiles.cpp (added)
>     +++ lld/trunk/ELF/InputFiles.cpp Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,212 @@
>     +//===- InputFiles.cpp -----------------------------------------------------===//
>     +//
>     +//                             The LLVM Linker
>     +//
>     +// This file is distributed under the University of Illinois Open Source
>     +// License. See LICENSE.TXT for details.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +
>     +#include "Chunks.h"
>     +#include "Error.h"
>     +#include "InputFiles.h"
>     +#include "Writer.h"
>     +#include "llvm/ADT/STLExtras.h"
>     +#include "llvm/LTO/LTOModule.h"
>     +#include "llvm/Object/ELF.h"
>     +#include "llvm/Support/ELF.h"
>     +#include "llvm/Support/Debug.h"
>     +#include "llvm/Support/Endian.h"
>     +#include "llvm/Support/raw_ostream.h"
>     +
>     +using namespace llvm::ELF;
>     +using namespace llvm::object;
>     +using namespace llvm::support::endian;
>     +using llvm::RoundUpToAlignment;
>     +using llvm::sys::fs::identify_magic;
>     +using llvm::sys::fs::file_magic;
>     +
>     +using namespace lld;
>     +using namespace lld::elfv2;
>     +
>     +// Returns the last element of a path, which is supposed to be a filename.
>     +static StringRef getBasename(StringRef Path) {
>     +  size_t Pos = Path.rfind('\\');
>     +  if (Pos == StringRef::npos)
>     +    return Path;
>     +  return Path.substr(Pos + 1);
>     +}
>     +
>     +// Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)".
>     +std::string InputFile::getShortName() {
>     +  if (ParentName == "")
>     +    return getName().lower();
>     +  std::string Res =
>     +      (getBasename(ParentName) + "(" + getBasename(getName()) + ")").str();
>     +  return StringRef(Res).lower();
>     +}
>     +
>     +std::error_code ArchiveFile::parse() {
>     +  // Parse a MemoryBufferRef as an archive file.
>     +  auto ArchiveOrErr = Archive::create(MB);
>     +  if (auto EC = ArchiveOrErr.getError())
>     +    return EC;
>     +  File = std::move(ArchiveOrErr.get());
>     +
>     +  // Allocate a buffer for Lazy objects.
>     +  size_t BufSize = File->getNumberOfSymbols() * sizeof(Lazy);
>     +  Lazy *Buf = (Lazy *)Alloc.Allocate(BufSize, llvm::alignOf<Lazy>());
>     +
>     +  // Read the symbol table to construct Lazy objects.
>     +  uint32_t I = 0;
>     +  for (const Archive::Symbol &Sym : File->symbols()) {
>     +    SymbolBodies.push_back(new (&Buf[I++]) Lazy(this, Sym));
>     +  }
>     +  return std::error_code();
>     +}
>     +
>     +// Returns a buffer pointing to a member file containing a given symbol.
>     +ErrorOr<MemoryBufferRef> ArchiveFile::getMember(const Archive::Symbol *Sym) {
>     +  auto ItOrErr = Sym->getMember();
>     +  if (auto EC = ItOrErr.getError())
>     +    return EC;
>     +  Archive::child_iterator It = ItOrErr.get();
>     +
>     +  // Return an empty buffer if we have already returned the same buffer.
>     +  const char *StartAddr = It->getBuffer().data();
>     +  auto Pair = Seen.insert(StartAddr);
>     +  if (!Pair.second)
>     +    return MemoryBufferRef();
>     +  return It->getMemoryBufferRef();
>     +}
>     +
>     +template <class ELFT> std::error_code elfv2::ObjectFile<ELFT>::parse() {
>     +  // Parse a memory buffer as a ELF file.
>     +  std::error_code EC;
>     +  ELFObj = llvm::make_unique<ELFFile<ELFT>>(MB.getBuffer(), EC);
>     +
>     +  if (EC) {
>     +    llvm::errs() << getName() << " is not an ELF file.\n";
>     +    return EC;
>     +  }
>     +
>     +  // Read section and symbol tables.
>     +  if (EC = initializeChunks())
>     +    return EC;
>     +  return initializeSymbols();
>     +}
>     +
>     +template <class ELFT>
>     +SymbolBody *elfv2::ObjectFile<ELFT>::getSymbolBody(uint32_t SymbolIndex) {
>     +  return SparseSymbolBodies[SymbolIndex]->getReplacement();
>     +}
>     +
>     +static bool isIgnoredSectionType(unsigned Type) {
>     +  switch (Type) {
>     +  case SHT_NULL:
>     +  case SHT_SYMTAB:
>     +  case SHT_STRTAB:
>     +  case SHT_RELA:
>     +  case SHT_HASH:
>     +  case SHT_DYNAMIC:
>     +  case SHT_NOTE:
>     +  case SHT_REL:
>     +  case SHT_DYNSYM:
>     +  case SHT_SYMTAB_SHNDX:
>     +    return true;
>     +  }
>     +  return false;
>     +}
>     +
>     +template <class ELFT>
>     +std::error_code elfv2::ObjectFile<ELFT>::initializeChunks() {
>     +  auto Size = ELFObj->getNumSections();
>     +  Chunks.reserve(Size);
>     +  SparseChunks.resize(Size);
>     +  int I = 0;
>     +  for (auto &&Sec : ELFObj->sections()) {
>     +    if (isIgnoredSectionType(Sec.sh_type) || Sec.sh_addralign == 0) {
>     +      ++I;
>     +      continue;
>     +    }
>     +    auto *C = new (Alloc) SectionChunk<ELFT>(this, &Sec, I);
>     +    Chunks.push_back(C);
>     +    SparseChunks[I] = C;
>     +    ++I;
>     +  }
>     +  return std::error_code();
>     +}
>     +
>     +template <class ELFT>
>     +std::error_code elfv2::ObjectFile<ELFT>::initializeSymbols() {
>     +  auto Syms = ELFObj->symbols();
>     +  Syms = ELFFile<ELFT>::Elf_Sym_Range(Syms.begin() + 1, Syms.end());
>     +  auto NumSymbols = std::distance(Syms.begin(), Syms.end());
>     +  SymbolBodies.reserve(NumSymbols + 1);
>     +  SparseSymbolBodies.resize(NumSymbols + 1);
>     +  int I = 1;
>     +  for (auto &&Sym : Syms) {
>     +    SymbolBody *Body = createSymbolBody(&Sym);
>     +    if (Body) {
>     +      SymbolBodies.push_back(Body);
>     +      SparseSymbolBodies[I] = Body;
>     +    }
>     +    ++I;
>     +  }
>     +
>     +  return std::error_code();
>     +}
>     +
>     +template <class ELFT>
>     +SymbolBody *elfv2::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
>     +  StringRef Name;
>     +  if (Sym->isUndefined()) {
>     +    Name = *ELFObj->getStaticSymbolName(Sym);
>     +    return new (Alloc) Undefined(Name);
>     +  }
>     +  if (Sym->isCommon()) {
>     +    Chunk *C = new (Alloc) CommonChunk<ELFT>(Sym);
>     +    Chunks.push_back(C);
>     +    return new (Alloc) DefinedRegular<ELFT>(ELFObj.get(), Sym, C);
>     +  }
>     +  if (Sym->isAbsolute()) {
>     +    Name = *ELFObj->getStaticSymbolName(Sym);
>     +    return new (Alloc) DefinedAbsolute(Name, Sym->getValue());
>     +  }
>     +  if (Chunk *C = SparseChunks[Sym->st_shndx])
>     +    return new (Alloc) DefinedRegular<ELFT>(ELFObj.get(), Sym, C);
>     +  return nullptr;
>     +}
>     +
>     +std::error_code BitcodeFile::parse() {
>     +  std::string Err;
>     +  M.reset(LTOModule::createFromBuffer(MB.getBufferStart(), MB.getBufferSize(),
>     +                                      llvm::TargetOptions(), Err));
>     +  if (!Err.empty()) {
>     +    llvm::errs() << Err << '\n';
>     +    return make_error_code(LLDError::BrokenFile);
>     +  }
>     +
>     +  for (unsigned I = 0, E = M->getSymbolCount(); I != E; ++I) {
>     +    lto_symbol_attributes Attrs = M->getSymbolAttributes(I);
>     +    if ((Attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL)
>     +      continue;
>     +
>     +    StringRef SymName = M->getSymbolName(I);
>     +    int SymbolDef = Attrs & LTO_SYMBOL_DEFINITION_MASK;
>     +    if (SymbolDef == LTO_SYMBOL_DEFINITION_UNDEFINED) {
>     +      SymbolBodies.push_back(new (Alloc) Undefined(SymName));
>     +    } else {
>     +      bool Replaceable = (SymbolDef == LTO_SYMBOL_DEFINITION_TENTATIVE ||
>     +                          (Attrs & LTO_SYMBOL_COMDAT));
>     +      SymbolBodies.push_back(new (Alloc) DefinedBitcode(SymName, Replaceable));
>     +    }
>     +  }
>     +
>     +  return std::error_code();
>     +}
>     +
>     +template class elfv2::ObjectFile<llvm::object::ELF32LE>;
>     +template class elfv2::ObjectFile<llvm::object::ELF32BE>;
>     +template class elfv2::ObjectFile<llvm::object::ELF64LE>;
>     +template class elfv2::ObjectFile<llvm::object::ELF64BE>;
> 
>     Added: lld/trunk/ELF/InputFiles.h
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=3PYMj6oNLlJvmujTaAhIi0AwxyA6tUjj6y8zsAkDprE&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/InputFiles.h (added)
>     +++ lld/trunk/ELF/InputFiles.h Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,158 @@
>     +//===- InputFiles.h -------------------------------------------------------===//
>     +//
>     +//                             The LLVM Linker
>     +//
>     +// This file is distributed under the University of Illinois Open Source
>     +// License. See LICENSE.TXT for details.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +
>     +#ifndef LLD_ELF_INPUT_FILES_H
>     +#define LLD_ELF_INPUT_FILES_H
>     +
>     +#include "Chunks.h"
>     +#include "Symbols.h"
>     +#include "lld/Core/LLVM.h"
>     +#include "llvm/ADT/ArrayRef.h"
>     +#include "llvm/LTO/LTOModule.h"
>     +#include "llvm/Object/Archive.h"
>     +#include "llvm/Object/ELF.h"
>     +#include "llvm/Support/StringSaver.h"
>     +#include <memory>
>     +#include <set>
>     +#include <vector>
>     +
>     +namespace lld {
>     +namespace elfv2 {
>     +
>     +using llvm::LTOModule;
>     +using llvm::object::Archive;
>     +using llvm::object::ELFFile;
>     +
>     +// The root class of input files.
>     +class InputFile {
>     +public:
>     +  enum Kind { ArchiveKind, ObjectKind, ImportKind, BitcodeKind };
>     +  Kind kind() const { return FileKind; }
>     +  virtual ~InputFile() {}
>     +
>     +  // Returns the filename.
>     +  StringRef getName() { return MB.getBufferIdentifier(); }
>     +
>     +  // Returns symbols defined by this file.
>     +  virtual std::vector<SymbolBody *> &getSymbols() = 0;
>     +
>     +  // Reads a file (constructors don't do that). Returns an error if a
>     +  // file is broken.
>     +  virtual std::error_code parse() = 0;
>     +
>     +  // Returns a short, human-friendly filename. If this is a member of
>     +  // an archive file, a returned value includes parent's filename.
>     +  // Used for logging or debugging.
>     +  std::string getShortName();
>     +
>     +  // Sets a parent filename if this file is created from an archive.
>     +  void setParentName(StringRef N) { ParentName = N; }
>     +
>     +protected:
>     +  explicit InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
>     +  MemoryBufferRef MB;
>     +
>     +private:
>     +  const Kind FileKind;
>     +  StringRef ParentName;
>     +};
>     +
>     +// .lib or .a file.
>     +class ArchiveFile : public InputFile {
>     +public:
>     +  explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
>     +  static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
>     +  std::error_code parse() override;
>     +
>     +  // Returns a memory buffer for a given symbol. An empty memory buffer
>     +  // is returned if we have already returned the same memory buffer.
>     +  // (So that we don't instantiate same members more than once.)
>     +  ErrorOr<MemoryBufferRef> getMember(const Archive::Symbol *Sym);
>     +
>     +  // NB: All symbols returned by ArchiveFiles are of Lazy type.
>     +  std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
>     +
>     +private:
>     +  std::unique_ptr<Archive> File;
>     +  std::string Filename;
>     +  std::vector<SymbolBody *> SymbolBodies;
>     +  std::set<const char *> Seen;
>     +  llvm::MallocAllocator Alloc;
>     +};
>     +
>     +// .obj or .o file. This may be a member of an archive file.
>     +template <class ELFT> class ObjectFile : public InputFile {
>     +  typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
>     +
>     +public:
>     +  explicit ObjectFile(MemoryBufferRef M) : InputFile(ObjectKind, M) {}
>     +  static bool classof(const InputFile *F) { return F->kind() == ObjectKind; }
>     +  std::error_code parse() override;
>     +  std::vector<Chunk *> &getChunks() { return Chunks; }
>     +  std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
>     +
>     +  // Returns a SymbolBody object for the SymbolIndex'th symbol in the
>     +  // underlying object file.
>     +  SymbolBody *getSymbolBody(uint32_t SymbolIndex);
>     +
>     +  // Returns the underying ELF file.
>     +  ELFFile<ELFT> *getObj() { return ELFObj.get(); }
>     +
>     +private:
>     +  std::error_code initializeChunks();
>     +  std::error_code initializeSymbols();
>     +
>     +  SymbolBody *createSymbolBody(const Elf_Sym *Sym);
>     +
>     +  std::unique_ptr<ELFFile<ELFT>> ELFObj;
>     +  llvm::BumpPtrAllocator Alloc;
>     +
>     +  // List of all chunks defined by this file. This includes both section
>     +  // chunks and non-section chunks for common symbols.
>     +  std::vector<Chunk *> Chunks;
>     +
>     +  // This vector contains the same chunks as Chunks, but they are
>     +  // indexed such that you can get a SectionChunk by section index.
>     +  // Nonexistent section indices are filled with null pointers.
>     +  // (Because section number is 1-based, the first slot is always a
>     +  // null pointer.)
>     +  std::vector<Chunk *> SparseChunks;
>     +
>     +  // List of all symbols referenced or defined by this file.
>     +  std::vector<SymbolBody *> SymbolBodies;
>     +
>     +  // This vector contains the same symbols as SymbolBodies, but they
>     +  // are indexed such that you can get a SymbolBody by symbol
>     +  // index. Nonexistent indices (which are occupied by auxiliary
>     +  // symbols in the real symbol table) are filled with null pointers.
>     +  std::vector<SymbolBody *> SparseSymbolBodies;
>     +};
>     +
>     +// Used for LTO.
>     +class BitcodeFile : public InputFile {
>     +public:
>     +  explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {}
>     +  static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; }
>     +  std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
>     +
>     +  LTOModule *getModule() const { return M.get(); }
>     +  LTOModule *releaseModule() { return M.release(); }
>     +
>     +private:
>     +  std::error_code parse() override;
>     +
>     +  std::vector<SymbolBody *> SymbolBodies;
>     +  llvm::BumpPtrAllocator Alloc;
>     +  std::unique_ptr<LTOModule> M;
>     +};
>     +
>     +} // namespace elfv2
>     +} // namespace lld
>     +
>     +#endif
> 
>     Added: lld/trunk/ELF/Options.td
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=PzXU3klbcw8ppFvchWmLnoaeM_f89mAtoYu3xuUiyg0&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/Options.td (added)
>     +++ lld/trunk/ELF/Options.td Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,54 @@
>     +include "llvm/Option/OptParser.td"
>     +
>     +//===----------------------------------------------------------------------===//
>     +/// Utility Functions
>     +//===----------------------------------------------------------------------===//
>     +// Single and multiple dash options combined
>     +multiclass smDash<string opt1, string opt2, string help> {
>     +  // Option
>     +  def "" : Separate<["-"], opt1>, HelpText<help>;
>     +  def opt1_eq : Joined<["-"], opt1#"=">,
>     +      Alias<!cast<Option>(opt1)>;
>     +  // Compatibility aliases
>     +  def opt2_dashdash : Separate<["--"], opt2>,
>     +      Alias<!cast<Option>(opt1)>;
>     +  def opt2_dashdash_eq : Joined<["--"], opt2#"=">,
>     +      Alias<!cast<Option>(opt1)>;
>     +}
>     +
>     +// Support -<option>,-<option>=
>     +multiclass dashEq<string opt1, string opt2, string help> {
>     +  // Option
>     +  def "" : Separate<["-"], opt1>, HelpText<help>;
>     +  // Compatibility aliases
>     +  def opt2_eq : Joined<["-"], opt2#"=">,
>     +      Alias<!cast<Option>(opt1)>;
>     +}
>     +
>     +// Support --<option>,--<option>=
>     +multiclass mDashEq<string opt1, string help> {
>     +  // Option
>     +  def "" : Separate<["--"], opt1>, HelpText<help>;
>     +  // Compatibility aliases
>     +  def opt2_eq : Joined<["--"], opt1#"=">,
>     +      Alias<!cast<Option>(opt1)>;
>     +}
>     +
>     +def output : Separate<["-"], "o">, MetaVarName<"<path>">,
>     +     HelpText<"Path to file to write output">;
>     +
>     +def L : Joined<["-"], "L">, MetaVarName<"<dir>">,
>     +     HelpText<"Directory to search for libraries">;
>     +def l : Joined<["-"], "l">, MetaVarName<"<libName>">,
>     +     HelpText<"Root name of library to use">;
>     +def noinhibit_exec : Flag<["--"], "noinhibit-exec">,
>     +     HelpText<"Retain the executable output file whenever"
>     +              " it is still usable">;
>     +defm e : smDash<"e", "entry",
>     +      "Name of entry point symbol">;
>     +
>     +//===----------------------------------------------------------------------===//
>     +/// Help
>     +//===----------------------------------------------------------------------===//
>     +def help : Flag<["--"], "help">,
>     +     HelpText<"Display this help message">;
> 
>     Added: lld/trunk/ELF/README.md
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/README.md?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=-ezRMs2yE6MzsAeuOJNb0zI7TPO_1o6Xd0KDRIyL8gE&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/README.md (added)
>     +++ lld/trunk/ELF/README.md Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,12 @@
>     +The New ELF Linker
>     +==================
>     +This directory contains a port of the new PE/COFF linker for ELF.
>     +
>     +Overall Design
>     +--------------
>     +See COFF/README.md for details on the design.
>     +
>     +Capabilities
>     +------------
>     +This linker can currently generate a valid ELF file that can be run on linux
>     +from a single input file.
> 
>     Added: lld/trunk/ELF/SymbolTable.cpp
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=K5wnaDQ8UuhMzqXbO2aWCOQV1w83V4HpgMuVMHWDBbg&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/SymbolTable.cpp (added)
>     +++ lld/trunk/ELF/SymbolTable.cpp Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,302 @@
>     +//===- SymbolTable.cpp ----------------------------------------------------===//
>     +//
>     +//                             The LLVM Linker
>     +//
>     +// This file is distributed under the University of Illinois Open Source
>     +// License. See LICENSE.TXT for details.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +
>     +#include "Config.h"
>     +#include "Driver.h"
>     +#include "Error.h"
>     +#include "SymbolTable.h"
>     +#include "llvm/ADT/STLExtras.h"
>     +#include "llvm/LTO/LTOCodeGenerator.h"
>     +#include "llvm/Support/Debug.h"
>     +#include "llvm/Support/raw_ostream.h"
>     +
>     +using namespace llvm;
>     +
>     +using namespace lld;
>     +using namespace lld::elfv2;
>     +
>     +template <class ELFT> SymbolTable<ELFT>::SymbolTable() {
>     +  if (!Config->EntryName.empty())
>     +    resolve(new (Alloc) Undefined(Config->EntryName));
>     +}
>     +
>     +template <class ELFT>
>     +std::error_code SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
>     +  if (auto EC = File->parse())
>     +    return EC;
>     +  InputFile *FileP = File.release();
>     +  if (auto *P = dyn_cast<ObjectFile<ELFT>>(FileP))
>     +    return addObject(P);
>     +  if (auto *P = dyn_cast<ArchiveFile>(FileP))
>     +    return addArchive(P);
>     +  if (auto *P = dyn_cast<BitcodeFile>(FileP))
>     +    return addBitcode(P);
>     +  llvm_unreachable("Unknown file");
>     +}
>     +
>     +template <class ELFT>
>     +std::error_code SymbolTable<ELFT>::addObject(ObjectFile<ELFT> *File) {
>     +  ObjectFiles.emplace_back(File);
>     +  for (SymbolBody *Body : File->getSymbols())
>     +    if (Body->isExternal())
>     +      if (auto EC = resolve(Body))
>     +        return EC;
>     +  return std::error_code();
>     +}
>     +
>     +template <class ELFT>
>     +std::error_code SymbolTable<ELFT>::addArchive(ArchiveFile *File) {
>     +  ArchiveFiles.emplace_back(File);
>     +  for (SymbolBody *Body : File->getSymbols())
>     +    if (auto EC = resolve(Body))
>     +      return EC;
>     +  return std::error_code();
>     +}
>     +
>     +template <class ELFT>
>     +std::error_code SymbolTable<ELFT>::addBitcode(BitcodeFile *File) {
>     +  BitcodeFiles.emplace_back(File);
>     +  for (SymbolBody *Body : File->getSymbols())
>     +    if (Body->isExternal())
>     +      if (auto EC = resolve(Body))
>     +        return EC;
>     +  return std::error_code();
>     +}
>     +
>     +template <class ELFT> bool SymbolTable<ELFT>::reportRemainingUndefines() {
>     +  bool Ret = false;
>     +  for (auto &I : Symtab) {
>     +    Symbol *Sym = I.second;
>     +    auto *Undef = dyn_cast<Undefined>(Sym->Body);
>     +    if (!Undef)
>     +      continue;
>     +    if (SymbolBody *Alias = Undef->getWeakAlias()) {
>     +      Sym->Body = Alias->getReplacement();
>     +      if (!isa<Defined>(Sym->Body)) {
>     +        // Aliases are yet another symbols pointed by other symbols
>     +        // that could also remain undefined.
>     +        llvm::errs() << "undefined symbol: " << Undef->getName() << "\n";
>     +        Ret = true;
>     +      }
>     +      continue;
>     +    }
>     +    llvm::errs() << "undefined symbol: " << Undef->getName() << "\n";
>     +    Ret = true;
>     +  }
>     +  return Ret;
>     +}
>     +
>     +// This function resolves conflicts if there's an existing symbol with
>     +// the same name. Decisions are made based on symbol type.
>     +template <class ELFT>
>     +std::error_code SymbolTable<ELFT>::resolve(SymbolBody *New) {
>     +  // Find an existing Symbol or create and insert a new one.
>     +  StringRef Name = New->getName();
>     +  Symbol *&Sym = Symtab[Name];
>     +  if (!Sym) {
>     +    Sym = new (Alloc) Symbol(New);
>     +    New->setBackref(Sym);
>     +    return std::error_code();
>     +  }
>     +  New->setBackref(Sym);
>     +
>     +  // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
>     +  // equivalent (conflicting), or more preferable, respectively.
>     +  SymbolBody *Existing = Sym->Body;
>     +  int comp = Existing->compare(New);
>     +  if (comp < 0)
>     +    Sym->Body = New;
>     +  if (comp == 0) {
>     +    llvm::errs() << "duplicate symbol: " << Name << "\n";
>     +    return make_error_code(LLDError::DuplicateSymbols);
>     +  }
>     +
>     +  // If we have an Undefined symbol for a Lazy symbol, we need
>     +  // to read an archive member to replace the Lazy symbol with
>     +  // a Defined symbol.
>     +  if (isa<Undefined>(Existing) || isa<Undefined>(New))
>     +    if (auto *B = dyn_cast<Lazy>(Sym->Body))
>     +      return addMemberFile(B);
>     +  return std::error_code();
>     +}
>     +
>     +// Reads an archive member file pointed by a given symbol.
>     +template <class ELFT>
>     +std::error_code SymbolTable<ELFT>::addMemberFile(Lazy *Body) {
>     +  auto FileOrErr = Body->getMember();
>     +  if (auto EC = FileOrErr.getError())
>     +    return EC;
>     +  std::unique_ptr<InputFile> File = std::move(FileOrErr.get());
>     +
>     +  // getMember returns an empty buffer if the member was already
>     +  // read from the library.
>     +  if (!File)
>     +    return std::error_code();
>     +  if (Config->Verbose)
>     +    llvm::outs() << "Loaded " << File->getShortName() << " for "
>     +                 << Body->getName() << "\n";
>     +  return addFile(std::move(File));
>     +}
>     +
>     +template <class ELFT> std::vector<Chunk *> SymbolTable<ELFT>::getChunks() {
>     +  std::vector<Chunk *> Res;
>     +  for (std::unique_ptr<ObjectFile<ELFT>> &File : ObjectFiles) {
>     +    std::vector<Chunk *> &V = File->getChunks();
>     +    Res.insert(Res.end(), V.begin(), V.end());
>     +  }
>     +  return Res;
>     +}
>     +
>     +template <class ELFT> Defined *SymbolTable<ELFT>::find(StringRef Name) {
>     +  auto It = Symtab.find(Name);
>     +  if (It == Symtab.end())
>     +    return nullptr;
>     +  if (auto *Def = dyn_cast<Defined>(It->second->Body))
>     +    return Def;
>     +  return nullptr;
>     +}
>     +
>     +template <class ELFT>
>     +std::error_code SymbolTable<ELFT>::addUndefined(StringRef Name) {
>     +  return resolve(new (Alloc) Undefined(Name));
>     +}
>     +
>     +// Resolve To, and make From an alias to To.
>     +template <class ELFT>
>     +std::error_code SymbolTable<ELFT>::rename(StringRef From, StringRef To) {
>     +  SymbolBody *Body = new (Alloc) Undefined(To);
>     +  if (auto EC = resolve(Body))
>     +    return EC;
>     +  Symtab[From]->Body = Body->getReplacement();
>     +  return std::error_code();
>     +}
>     +
>     +template <class ELFT> void SymbolTable<ELFT>::dump() {
>     +  for (auto &P : Symtab) {
>     +    Symbol *Ref = P.second;
>     +    if (auto *Body = dyn_cast<Defined>(Ref->Body))
>     +      llvm::dbgs() << Twine::utohexstr(Body->getVA()) << " " << Body->getName()
>     +                   << "\n";
>     +  }
>     +}
>     +
>     +template <class ELFT>
>     +std::error_code SymbolTable<ELFT>::addCombinedLTOObject() {
>     +  if (BitcodeFiles.empty())
>     +    return std::error_code();
>     +
>     +  // Create an object file and add it to the symbol table by replacing any
>     +  // DefinedBitcode symbols with the definitions in the object file.
>     +  LTOCodeGenerator CG;
>     +  auto FileOrErr = createLTOObject(&CG);
>     +  if (auto EC = FileOrErr.getError())
>     +    return EC;
>     +  ObjectFile<ELFT> *Obj = FileOrErr.get();
>     +
>     +  for (SymbolBody *Body : Obj->getSymbols()) {
>     +    if (!Body->isExternal())
>     +      continue;
>     +    // Find an existing Symbol. We should not see any new undefined symbols at
>     +    // this point.
>     +    StringRef Name = Body->getName();
>     +    Symbol *&Sym = Symtab[Name];
>     +    if (!Sym) {
>     +      if (!isa<Defined>(Body)) {
>     +        llvm::errs() << "LTO: undefined symbol: " << Name << '\n';
>     +        return make_error_code(LLDError::BrokenFile);
>     +      }
>     +      Sym = new (Alloc) Symbol(Body);
>     +      Body->setBackref(Sym);
>     +      continue;
>     +    }
>     +    Body->setBackref(Sym);
>     +
>     +    if (isa<DefinedBitcode>(Sym->Body)) {
>     +      // The symbol should now be defined.
>     +      if (!isa<Defined>(Body)) {
>     +        llvm::errs() << "LTO: undefined symbol: " << Name << '\n';
>     +        return make_error_code(LLDError::BrokenFile);
>     +      }
>     +      Sym->Body = Body;
>     +    } else {
>     +      int comp = Sym->Body->compare(Body);
>     +      if (comp < 0)
>     +        Sym->Body = Body;
>     +      if (comp == 0) {
>     +        llvm::errs() << "LTO: unexpected duplicate symbol: " << Name << "\n";
>     +        return make_error_code(LLDError::BrokenFile);
>     +      }
>     +    }
>     +
>     +    // We may see new references to runtime library symbols such as __chkstk
>     +    // here. These symbols must be wholly defined in non-bitcode files.
>     +    if (auto *B = dyn_cast<Lazy>(Sym->Body)) {
>     +      size_t NumBitcodeFiles = BitcodeFiles.size();
>     +      if (auto EC = addMemberFile(B))
>     +        return EC;
>     +      if (BitcodeFiles.size() != NumBitcodeFiles) {
>     +        llvm::errs()
>     +            << "LTO: late loaded symbol created new bitcode reference: " << Name
>     +            << "\n";
>     +        return make_error_code(LLDError::BrokenFile);
>     +      }
>     +    }
>     +  }
>     +
>     +  // New runtime library symbol references may have created undefined
>     +  // references.
>     +  if (reportRemainingUndefines())
>     +    return make_error_code(LLDError::BrokenFile);
>     +  return std::error_code();
>     +}
>     +
>     +// Combine and compile bitcode files and then return the result
>     +// as a regular ELF object file.
>     +template <class ELFT>
>     +ErrorOr<ObjectFile<ELFT> *>
>     +SymbolTable<ELFT>::createLTOObject(LTOCodeGenerator *CG) {
>     +  // All symbols referenced by non-bitcode objects must be preserved.
>     +  for (std::unique_ptr<ObjectFile<ELFT>> &File : ObjectFiles)
>     +    for (SymbolBody *Body : File->getSymbols())
>     +      if (auto *S = dyn_cast<DefinedBitcode>(Body->getReplacement()))
>     +        CG->addMustPreserveSymbol(S->getName());
>     +
>     +  // Likewise for bitcode symbols which we initially resolved to non-bitcode.
>     +  for (std::unique_ptr<BitcodeFile> &File : BitcodeFiles)
>     +    for (SymbolBody *Body : File->getSymbols())
>     +      if (isa<DefinedBitcode>(Body) &&
>     +          !isa<DefinedBitcode>(Body->getReplacement()))
>     +        CG->addMustPreserveSymbol(Body->getName());
>     +
>     +  // Likewise for other symbols that must be preserved.
>     +  for (StringRef Name : Config->GCRoots)
>     +    if (isa<DefinedBitcode>(Symtab[Name]->Body))
>     +      CG->addMustPreserveSymbol(Name);
>     +
>     +  CG->setModule(BitcodeFiles[0]->releaseModule());
>     +  for (unsigned I = 1, E = BitcodeFiles.size(); I != E; ++I)
>     +    CG->addModule(BitcodeFiles[I]->getModule());
>     +
>     +  std::string ErrMsg;
>     +  LTOMB = CG->compile(false, false, false, ErrMsg); // take MB ownership
>     +  if (!LTOMB) {
>     +    llvm::errs() << ErrMsg << '\n';
>     +    return make_error_code(LLDError::BrokenFile);
>     +  }
>     +  auto Obj = new ObjectFile<ELFT>(LTOMB->getMemBufferRef());
>     +  ObjectFiles.emplace_back(Obj);
>     +  if (auto EC = Obj->parse())
>     +    return EC;
>     +  return Obj;
>     +}
>     +
>     +template class SymbolTable<llvm::object::ELF32LE>;
>     +template class SymbolTable<llvm::object::ELF32BE>;
>     +template class SymbolTable<llvm::object::ELF64LE>;
>     +template class SymbolTable<llvm::object::ELF64BE>;
> 
>     Added: lld/trunk/ELF/SymbolTable.h
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=KR9MS6ov0k2eaMhteJFDluYYhN7qromJQ7WdApFIrog&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/SymbolTable.h (added)
>     +++ lld/trunk/ELF/SymbolTable.h Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,88 @@
>     +//===- SymbolTable.h ------------------------------------------------------===//
>     +//
>     +//                             The LLVM Linker
>     +//
>     +// This file is distributed under the University of Illinois Open Source
>     +// License. See LICENSE.TXT for details.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +
>     +#ifndef LLD_ELF_SYMBOL_TABLE_H
>     +#define LLD_ELF_SYMBOL_TABLE_H
>     +
>     +#include "InputFiles.h"
>     +#include "llvm/Support/Allocator.h"
>     +#include <unordered_map>
>     +
>     +namespace llvm {
>     +struct LTOCodeGenerator;
>     +}
>     +
>     +namespace lld {
>     +namespace elfv2 {
>     +
>     +// SymbolTable is a bucket of all known symbols, including defined,
>     +// undefined, or lazy symbols (the last one is symbols in archive
>     +// files whose archive members are not yet loaded).
>     +//
>     +// We put all symbols of all files to a SymbolTable, and the
>     +// SymbolTable selects the "best" symbols if there are name
>     +// conflicts. For example, obviously, a defined symbol is better than
>     +// an undefined symbol. Or, if there's a conflict between a lazy and a
>     +// undefined, it'll read an archive member to read a real definition
>     +// to replace the lazy symbol. The logic is implemented in resolve().
>     +template <class ELFT> class SymbolTable {
>     +public:
>     +  SymbolTable();
>     +
>     +  std::error_code addFile(std::unique_ptr<InputFile> File);
>     +
>     +  // Print an error message on undefined symbols.
>     +  bool reportRemainingUndefines();
>     +
>     +  // Returns a list of chunks of selected symbols.
>     +  std::vector<Chunk *> getChunks();
>     +
>     +  // Returns a symbol for a given name. It's not guaranteed that the
>     +  // returned symbol actually has the same name (because of various
>     +  // mechanisms to allow aliases, a name can be resolved to a
>     +  // different symbol). Returns a nullptr if not found.
>     +  Defined *find(StringRef Name);
>     +
>     +  // Dump contents of the symbol table to stderr.
>     +  void dump();
>     +
>     +  // Build an ELF object representing the combined contents of BitcodeFiles
>     +  // and add it to the symbol table. Called after all files are added and
>     +  // before the writer writes results to a file.
>     +  std::error_code addCombinedLTOObject();
>     +
>     +  // The writer needs to infer the machine type from the object files.
>     +  std::vector<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles;
>     +
>     +  // Creates an Undefined symbol for a given name.
>     +  std::error_code addUndefined(StringRef Name);
>     +
>     +  // Rename From -> To in the symbol table.
>     +  std::error_code rename(StringRef From, StringRef To);
>     +
>     +private:
>     +  std::error_code addObject(ObjectFile<ELFT> *File);
>     +  std::error_code addArchive(ArchiveFile *File);
>     +  std::error_code addBitcode(BitcodeFile *File);
>     +
>     +  std::error_code resolve(SymbolBody *Body);
>     +  std::error_code addMemberFile(Lazy *Body);
>     +  ErrorOr<ObjectFile<ELFT> *> createLTOObject(llvm::LTOCodeGenerator *CG);
>     +
>     +  std::unordered_map<StringRef, Symbol *> Symtab;
>     +  std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;
>     +  std::vector<std::unique_ptr<BitcodeFile>> BitcodeFiles;
>     +  std::unique_ptr<MemoryBuffer> LTOMB;
>     +  llvm::BumpPtrAllocator Alloc;
>     +};
>     +
>     +} // namespace elfv2
>     +} // namespace lld
>     +
>     +#endif
> 
>     Added: lld/trunk/ELF/Symbols.cpp
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=fNwJK9e1CSOm277kRndO8gJODtijAs33MhAdhRvhbcQ&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/Symbols.cpp (added)
>     +++ lld/trunk/ELF/Symbols.cpp Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,141 @@
>     +//===- Symbols.cpp --------------------------------------------------------===//
>     +//
>     +//                             The LLVM Linker
>     +//
>     +// This file is distributed under the University of Illinois Open Source
>     +// License. See LICENSE.TXT for details.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +
>     +#include "Error.h"
>     +#include "InputFiles.h"
>     +#include "Symbols.h"
>     +#include "llvm/ADT/STLExtras.h"
>     +#include "llvm/Support/Debug.h"
>     +#include "llvm/Support/raw_ostream.h"
>     +
>     +using namespace llvm::object;
>     +using llvm::sys::fs::identify_magic;
>     +using llvm::sys::fs::file_magic;
>     +
>     +using namespace lld;
>     +using namespace lld::elfv2;
>     +
>     +// Returns 1, 0 or -1 if this symbol should take precedence
>     +// over the Other, tie or lose, respectively.
>     +template <class ELFT> int DefinedRegular<ELFT>::compare(SymbolBody *Other) {
>     +  if (Other->kind() < kind())
>     +    return -Other->compare(this);
>     +  auto *R = dyn_cast<DefinedRegular>(Other);
>     +  if (!R)
>     +    return 1;
>     +
>     +  // Common symbols are weaker than other types of defined symbols.
>     +  if (isCommon() && R->isCommon())
>     +    return (getCommonSize() < R->getCommonSize()) ? -1 : 1;
>     +  // TODO: we are not sure if regular defined symbol and common
>     +  // symbols are allowed to have the same name.
>     +  if (isCommon())
>     +    return -1;
>     +  if (R->isCommon())
>     +    return 1;
>     +  return 0;
>     +}
>     +
>     +int DefinedBitcode::compare(SymbolBody *Other) {
>     +  assert(Other->kind() >= kind());
>     +  if (!isa<Defined>(Other))
>     +    return 1;
>     +
>     +  if (auto *B = dyn_cast<DefinedBitcode>(Other)) {
>     +    if (!Replaceable && !B->Replaceable)
>     +      return 0;
>     +    // Non-replaceable symbols win.
>     +    return Replaceable ? -1 : 1;
>     +  }
>     +
>     +  // As an approximation, regular symbols win over bitcode symbols,
>     +  // but we definitely have a conflict if the regular symbol is not
>     +  // replaceable and neither is the bitcode symbol. We do not
>     +  // replicate the rest of the symbol resolution logic here; symbol
>     +  // resolution will be done accurately after lowering bitcode symbols
>     +  // to regular symbols in addCombinedLTOObject().
>     +  if (auto *R = dyn_cast<DefinedRegular<llvm::object::ELF64LE>>(Other)) {
>     +    if (!R->isCommon() && !Replaceable)
>     +      return 0;
>     +    return -1;
>     +  }
>     +  return 0;
>     +}
>     +
>     +int Defined::compare(SymbolBody *Other) {
>     +  if (Other->kind() < kind())
>     +    return -Other->compare(this);
>     +  if (isa<Defined>(Other))
>     +    return 0;
>     +  return 1;
>     +}
>     +
>     +int Lazy::compare(SymbolBody *Other) {
>     +  if (Other->kind() < kind())
>     +    return -Other->compare(this);
>     +
>     +  // Undefined symbols with weak aliases will turn into defined
>     +  // symbols if they remain undefined, so we don't need to resolve
>     +  // such symbols.
>     +  if (auto *U = dyn_cast<Undefined>(Other))
>     +    if (U->getWeakAlias())
>     +      return -1;
>     +  return 1;
>     +}
>     +
>     +int Undefined::compare(SymbolBody *Other) {
>     +  if (Other->kind() < kind())
>     +    return -Other->compare(this);
>     +  if (cast<Undefined>(Other)->getWeakAlias())
>     +    return -1;
>     +  return 1;
>     +}
>     +
>     +template <class ELFT> StringRef DefinedRegular<ELFT>::getName() {
>     +  // DefinedSymbol's name is read lazily for a performance reason.
>     +  // Non-external symbol names are never used by the linker
>     +  // except for logging or debugging.
>     +  // Their internal references are resolved not by name but by symbol index.
>     +  // And because they are not external, no one can refer them by name.
>     +  // Object files contain lots of non-external symbols, and creating
>     +  // StringRefs for them (which involves lots of strlen() on the string table)
>     +  // is a waste of time.
>     +  if (Name.empty())
>     +    Name = *File->getStaticSymbolName(Sym);
>     +  return Name;
>     +}
>     +
>     +ErrorOr<std::unique_ptr<InputFile>> Lazy::getMember() {
>     +  auto MBRefOrErr = File->getMember(&Sym);
>     +  if (auto EC = MBRefOrErr.getError())
>     +    return EC;
>     +  MemoryBufferRef MBRef = MBRefOrErr.get();
>     +
>     +  // getMember returns an empty buffer if the member was already
>     +  // read from the library.
>     +  if (MBRef.getBuffer().empty())
>     +    return std::unique_ptr<InputFile>(nullptr);
>     +
>     +  file_magic Magic = identify_magic(MBRef.getBuffer());
>     +  if (Magic == file_magic::bitcode)
>     +    return std::unique_ptr<InputFile>(new BitcodeFile(MBRef));
>     +  if (Magic != file_magic::elf_relocatable) {
>     +    llvm::errs() << File->getName() << ": unknown file type\n";
>     +    return make_error_code(LLDError::InvalidFile);
>     +  }
>     +
>     +  std::unique_ptr<InputFile> Obj(new ObjectFile<llvm::object::ELF64LE>(MBRef));
>     +  Obj->setParentName(File->getName());
>     +  return std::move(Obj);
>     +}
>     +
>     +template class DefinedRegular<llvm::object::ELF32LE>;
>     +template class DefinedRegular<llvm::object::ELF32BE>;
>     +template class DefinedRegular<llvm::object::ELF64LE>;
>     +template class DefinedRegular<llvm::object::ELF64BE>;
> 
>     Added: lld/trunk/ELF/Symbols.h
>     URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=242088&view=auto <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=zR5XFRJUzUfaUwjQ76fmr_USfI8_NMPyvWp_bFrZjqU&s=OEsan9I7l36GK7_h8tvaXlnvFLId2cSlZDeOKAdgwR8&e=>
>     ==============================================================================
>     --- lld/trunk/ELF/Symbols.h (added)
>     +++ lld/trunk/ELF/Symbols.h Mon Jul 13 18:48:06 2015
>     @@ -0,0 +1,232 @@
>     +//===- Symbols.h ----------------------------------------------------------===//
>     +//
>     +//                             The LLVM Linker
>     +//
>     +// This file is distributed under the University of Illinois Open Source
>     +// License. See LICENSE.TXT for details.
>     +//
>     +//===----------------------------------------------------------------------===//
>     +
>     +#ifndef LLD_ELF_SYMBOLS_H
>     +#define LLD_ELF_SYMBOLS_H
>     +
>     +#include "Chunks.h"
>     +#include "Config.h"
>     +#include "lld/Core/LLVM.h"
>     +#include "llvm/ADT/ArrayRef.h"
>     +#include "llvm/Object/Archive.h"
>     +#include "llvm/Object/ELF.h"
>     +#include <memory>
>     +#include <vector>
>     +
>     +namespace lld {
>     +namespace elfv2 {
>     +
>     +using llvm::object::Archive;
>     +using llvm::object::ELFFile;
>     +
>     +class ArchiveFile;
>     +class InputFile;
>     +class SymbolBody;
>     +
>     +// A real symbol object, SymbolBody, is usually accessed indirectly
>     +// through a Symbol. There's always one Symbol for each symbol name.
>     +// The resolver updates SymbolBody pointers as it resolves symbols.
>     +struct Symbol {
>     +  explicit Symbol(SymbolBody *P) : Body(P) {}
>     +  SymbolBody *Body;
>     +};
>     +
>     +// The base class for real symbol classes.
>     +class SymbolBody {
>     +public:
>     +  enum Kind {
>     +    DefinedFirst,
>     +    DefinedBitcodeKind,
>     +    DefinedAbsoluteKind,
>     +    DefinedRegularKind,
>     +    DefinedLast,
>     +    LazyKind,
>     +    UndefinedKind,
>     +  };
>     +
>     +  Kind kind() const { return SymbolKind; }
>     +  virtual ~SymbolBody() {}
>     +
>     +  // Returns true if this is an external symbol.
>     +  virtual bool isExternal() { return true; }
>     +
>     +  // Returns the symbol name.
>     +  virtual StringRef getName() = 0;
>     +
>     +  // A SymbolBody has a backreference to a Symbol. Originally they are
>     +  // doubly-linked. A backreference will never change. But the pointer
>     +  // in the Symbol may be mutated by the resolver. If you have a
>     +  // pointer P to a SymbolBody and are not sure whether the resolver
>     +  // has chosen the object among other objects having the same name,
>     +  // you can access P->Backref->Body to get the resolver's result.
>     +  void setBackref(Symbol *P) { Backref = P; }
>     +  SymbolBody *getReplacement() { return Backref ? Backref->Body : this; }
>     +
>     +  // Decides which symbol should "win" in the symbol table, this or
>     +  // the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if
>     +  // they are duplicate (conflicting) symbols.
>     +  virtual int compare(SymbolBody *Other) = 0;
>     +
>     +protected:
>     +  SymbolBody(Kind K) : SymbolKind(K) {}
>     +
>     +private:
>     +  const Kind SymbolKind;
>     +  Symbol *Backref = nullptr;
>     +};
>     +
>     +// The base class for any defined symbols, including absolute symbols,
>     +// etc.
>     +class Defined : public SymbolBody {
>     +public:
>     +  Defined(Kind K) : SymbolBody(K) {}
>     +
>     +  static bool classof(const SymbolBody *S) {
>     +    Kind K = S->kind();
>     +    return DefinedFirst <= K && K <= DefinedLast;
>     +  }
>     +
>     +  // Returns the VA (virtual address) of this symbol. The
>     +  // writer sets and uses VAs.
>     +  virtual uint64_t getVA() = 0;
>     +
>     +  // Returns the file offset of this symbol in the final executable.
>     +  // The writer uses this information to apply relocations.
>     +  virtual uint64_t getFileOff() = 0;
>     +
>     +  // Called by the garbage collector. All Defined subclasses should
>     +  // know how to call depending symbols' markLive functions.
>     +  virtual void markLive() {}
>     +
>     +  int compare(SymbolBody *Other) override;
>     +};
>     +
>     +// Regular defined symbols read from object file symbol tables.
>     +template <class ELFT> class DefinedRegular : public Defined {
>     +  typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
>     +
>     +public:
>     +  DefinedRegular(ELFFile<ELFT> *F, const Elf_Sym *S, Chunk *C)
>     +      : Defined(DefinedRegularKind), File(F), Sym(S), Data(C) {}
>     +
>     +  static bool classof(const SymbolBody *S) {
>     +    return S->kind() == DefinedRegularKind;
>     +  }
>     +
>     +  StringRef getName() override;
>     +  uint64_t getVA() override { return Data->getVA() + Sym->getValue(); }
>     +  bool isExternal() override { return Sym->isExternal(); }
>     +  void markLive() override { Data->markLive(); }
>     +  uint64_t getFileOff() override {
>     +    return Data->getFileOff() + Sym->getValue();
>     +  }
>     +  int compare(SymbolBody *Other) override;
>     +
>     +  // Returns true if this is a common symbol.
>     +  bool isCommon() const { return Sym->isCommon(); }
>     +  uint32_t getCommonSize() const { return Sym->st_size; }
>     +
>     +private:
>     +  StringRef Name;
>     +  ELFFile<ELFT> *File;
>     +  const Elf_Sym *Sym;
>     +  Chunk *Data;
>     +};
>     +
>     +// Absolute symbols.
>     +class DefinedAbsolute : public Defined {
>     +public:
>     +  DefinedAbsolute(StringRef N, uint64_t VA)
>     +      : Defined(DefinedAbsoluteKind), Name(N), VA(VA) {}
>     +
>     +  static bool classof(const SymbolBody *S) {
>     +    return S->kind() == DefinedAbsoluteKind;
>     +  }
>     +
>     +  StringRef getName() override { return Name; }
>     +  uint64_t getVA() override { return VA; }
>     +  uint64_t getFileOff() override { llvm_unreachable("internal error"); }
>     +
>     +private:
>     +  StringRef Name;
>     +  uint64_t VA;
>     +};
>     +
>     +// This class represents a s
> 
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> 



More information about the llvm-commits mailing list