[PATCH] D24060: [lld][ELF] Add support for -b binary

Rafael EspĂ­ndola via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 7 09:36:58 PDT 2016


I am taking a look at this.

A version of the patch is attached. So far I have only clang-formated
it and fixed the linux build.

Cheers,
Rafael


On 1 September 2016 at 08:19, Rafael EspĂ­ndola
<rafael.espindola at gmail.com> wrote:
>> I agree with Rui here. I looked at what it would take to do it without
>> creating an ELF file and it ends up touching a lot of code. Using the
>> existing ELF machinery makes this a very isolated change for a special case
>> feature. However if you see a simple way to implement it without ELF I'm
>> fine with doing so.
>
> Let me give it a try. I am opposed to having to invent an ELF file to
> load things in. It would be equivalent to doing that for LTO IMHO.
>
> Having said that, we do have two ELF writers in LLVM (MC and dwp), so
> you can already try replacing both with the writer you wrote.
>
> Cheers,
> Rafael
-------------- next part --------------
diff --git a/ELF/Config.h b/ELF/Config.h
index f06fe1b..0da4115 100644
--- a/ELF/Config.h
+++ b/ELF/Config.h
@@ -1,144 +1,145 @@
 //===- Config.h -------------------------------------------------*- C++ -*-===//
 //
 //                             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/MapVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ELF.h"
 
 #include <vector>
 
 namespace lld {
 namespace elf {
 
 class InputFile;
 struct Symbol;
 
 enum ELFKind {
   ELFNoneKind,
   ELF32LEKind,
   ELF32BEKind,
   ELF64LEKind,
   ELF64BEKind
 };
 
 // For --build-id.
 enum class BuildIdKind { None, Fnv1, Md5, Sha1, Hexstring, Uuid };
 
 // For --discard-{all,locals,none}.
 enum class DiscardPolicy { Default, All, Locals, None };
 
 // For --strip-{all,debug}.
 enum class StripPolicy { None, All, Debug };
 
 // For --unresolved-symbols.
 enum class UnresolvedPolicy { NoUndef, ReportError, Warn, Ignore };
 
 struct SymbolVersion {
   llvm::StringRef Name;
   bool IsExternCpp;
 };
 
 // This struct contains symbols version definition that
 // can be found in version script if it is used for link.
 struct VersionDefinition {
   VersionDefinition(llvm::StringRef Name, size_t Id) : Name(Name), Id(Id) {}
   llvm::StringRef Name;
   size_t Id;
   std::vector<SymbolVersion> Globals;
   size_t NameOff; // Offset in string table.
 };
 
 // This struct contains the global configuration for the linker.
 // Most fields are direct mapping from the command line options
 // and such fields have the same name as the corresponding options.
 // Most fields are initialized by the driver.
 struct Configuration {
   Symbol *EntrySym = nullptr;
   InputFile *FirstElf = nullptr;
   llvm::StringRef DynamicLinker;
   llvm::StringRef Entry;
   llvm::StringRef Emulation;
   llvm::StringRef Fini;
   llvm::StringRef Init;
   llvm::StringRef LtoAAPipeline;
   llvm::StringRef LtoNewPmPasses;
   llvm::StringRef OutputFile;
   llvm::StringRef SoName;
   llvm::StringRef Sysroot;
   std::string RPath;
   std::vector<VersionDefinition> VersionDefinitions;
   std::vector<llvm::StringRef> AuxiliaryList;
   std::vector<llvm::StringRef> DynamicList;
   std::vector<llvm::StringRef> SearchPaths;
   std::vector<llvm::StringRef> Undefined;
   std::vector<SymbolVersion> VersionScriptGlobals;
   std::vector<uint8_t> BuildIdVector;
   bool AllowMultipleDefinition;
   bool AsNeeded = false;
+  bool Binary = false;
   bool Bsymbolic;
   bool BsymbolicFunctions;
   bool Demangle = true;
   bool DisableVerify;
   bool EhFrameHdr;
   bool EnableNewDtags;
   bool ExportDynamic;
   bool FatalWarnings;
   bool GcSections;
   bool GnuHash = false;
   bool ICF;
   bool Mips64EL = false;
   bool NoGnuUnique;
   bool NoUndefinedVersion;
   bool Nostdlib;
   bool OFormatBinary;
   bool Pic;
   bool Pie;
   bool PrintGcSections;
   bool Rela;
   bool Relocatable;
   bool SaveTemps;
   bool Shared;
   bool Static = false;
   bool SysvHash = true;
   bool Target1Rel;
   bool Threads;
   bool Trace;
   bool Verbose;
   bool WarnCommon;
   bool ZCombreloc;
   bool ZExecStack;
   bool ZNodelete;
   bool ZNow;
   bool ZOrigin;
   bool ZRelro;
   DiscardPolicy Discard;
   StripPolicy Strip = StripPolicy::None;
   UnresolvedPolicy UnresolvedSymbols;
   BuildIdKind BuildId = BuildIdKind::None;
   ELFKind EKind = ELFNoneKind;
   uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL;
   uint16_t EMachine = llvm::ELF::EM_NONE;
   uint64_t EntryAddr = -1;
   uint64_t ImageBase;
   uint64_t ZStackSize = -1;
   unsigned LtoJobs;
   unsigned LtoO;
   unsigned Optimize;
 };
 
 // The only instance of Configuration struct.
 extern Configuration *Config;
 
 } // namespace elf
 } // namespace lld
 
 #endif
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index 45c6b1b..2fed11d 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -1,646 +1,667 @@
 //===- Driver.cpp ---------------------------------------------------------===//
 //
 //                             The LLVM Linker
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
 #include "Driver.h"
 #include "Config.h"
 #include "Error.h"
 #include "ICF.h"
 #include "InputFiles.h"
 #include "InputSection.h"
 #include "LinkerScript.h"
 #include "Strings.h"
 #include "SymbolListFile.h"
 #include "SymbolTable.h"
 #include "Target.h"
 #include "Writer.h"
 #include "lld/Driver/Driver.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cstdlib>
 #include <utility>
 
 using namespace llvm;
 using namespace llvm::ELF;
 using namespace llvm::object;
 using namespace llvm::sys;
 
 using namespace lld;
 using namespace lld::elf;
 
 Configuration *elf::Config;
 LinkerDriver *elf::Driver;
 
 bool elf::link(ArrayRef<const char *> Args, raw_ostream &Error) {
   HasError = false;
   ErrorOS = &Error;
 
   Configuration C;
   LinkerDriver D;
   ScriptConfiguration SC;
   Config = &C;
   Driver = &D;
   ScriptConfig = &SC;
 
   Driver->main(Args);
   return !HasError;
 }
 
 // Parses a linker -m option.
 static std::pair<ELFKind, uint16_t> parseEmulation(StringRef S) {
   if (S.endswith("_fbsd"))
     S = S.drop_back(5);
 
   std::pair<ELFKind, uint16_t> Ret =
       StringSwitch<std::pair<ELFKind, uint16_t>>(S)
           .Case("aarch64elf", {ELF64LEKind, EM_AARCH64})
           .Case("aarch64linux", {ELF64LEKind, EM_AARCH64})
           .Case("armelf_linux_eabi", {ELF32LEKind, EM_ARM})
           .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64})
           .Case("elf32btsmip", {ELF32BEKind, EM_MIPS})
           .Case("elf32ltsmip", {ELF32LEKind, EM_MIPS})
           .Case("elf32ppc", {ELF32BEKind, EM_PPC})
           .Case("elf64btsmip", {ELF64BEKind, EM_MIPS})
           .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS})
           .Case("elf64ppc", {ELF64BEKind, EM_PPC64})
           .Case("elf_i386", {ELF32LEKind, EM_386})
           .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU})
           .Case("elf_x86_64", {ELF64LEKind, EM_X86_64})
           .Default({ELFNoneKind, EM_NONE});
 
   if (Ret.first == ELFNoneKind) {
     if (S == "i386pe" || S == "i386pep" || S == "thumb2pe")
       error("Windows targets are not supported on the ELF frontend: " + S);
     else
       error("unknown emulation: " + S);
   }
   return Ret;
 }
 
 // Returns slices of MB by parsing MB as an archive file.
 // Each slice consists of a member file in the archive.
 std::vector<MemoryBufferRef>
 LinkerDriver::getArchiveMembers(MemoryBufferRef MB) {
   std::unique_ptr<Archive> File =
       check(Archive::create(MB), "failed to parse archive");
 
   std::vector<MemoryBufferRef> V;
   Error Err;
   for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) {
     Archive::Child C = check(COrErr, "could not get the child of the archive " +
                                          File->getFileName());
     MemoryBufferRef MBRef =
         check(C.getMemoryBufferRef(),
               "could not get the buffer for a child of the archive " +
                   File->getFileName());
     V.push_back(MBRef);
   }
   if (Err)
     Error(Err);
 
   // Take ownership of memory buffers created for members of thin archives.
   for (std::unique_ptr<MemoryBuffer> &MB : File->takeThinBuffers())
     OwningMBs.push_back(std::move(MB));
 
   return V;
 }
 
 // Opens and parses a file. Path has to be resolved already.
 // Newly created memory buffers are owned by this driver.
-void LinkerDriver::addFile(StringRef Path) {
+void LinkerDriver::addFile(StringRef Path, bool KnownScript) {
   using namespace sys::fs;
   if (Config->Verbose)
     outs() << Path << "\n";
 
   Optional<MemoryBufferRef> Buffer = readFile(Path);
   if (!Buffer.hasValue())
     return;
   MemoryBufferRef MBRef = *Buffer;
 
+  if (Config->Binary && !KnownScript) {
+    Files.push_back(make_unique<BinaryFile>(MBRef));
+    return;
+  }
+
   switch (identify_magic(MBRef.getBuffer())) {
   case file_magic::unknown:
     readLinkerScript(MBRef);
     return;
   case file_magic::archive:
     if (WholeArchive) {
       for (MemoryBufferRef MB : getArchiveMembers(MBRef))
         Files.push_back(createObjectFile(MB, Path));
       return;
     }
     Files.push_back(make_unique<ArchiveFile>(MBRef));
     return;
   case file_magic::elf_shared_object:
     if (Config->Relocatable) {
       error("attempted static link of dynamic object " + Path);
       return;
     }
     Files.push_back(createSharedFile(MBRef));
     return;
   default:
     if (InLib)
       Files.push_back(make_unique<LazyObjectFile>(MBRef));
     else
       Files.push_back(createObjectFile(MBRef));
   }
 }
 
 Optional<MemoryBufferRef> LinkerDriver::readFile(StringRef Path) {
   auto MBOrErr = MemoryBuffer::getFile(Path);
   if (auto EC = MBOrErr.getError()) {
     error(EC, "cannot open " + Path);
     return None;
   }
   std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
   MemoryBufferRef MBRef = MB->getMemBufferRef();
   OwningMBs.push_back(std::move(MB)); // take MB ownership
 
   if (Cpio)
     Cpio->append(relativeToRoot(Path), MBRef.getBuffer());
 
   return MBRef;
 }
 
 // Add a given library by searching it from input search paths.
 void LinkerDriver::addLibrary(StringRef Name) {
   std::string Path = searchLibrary(Name);
   if (Path.empty())
     error("unable to find library -l" + Name);
   else
     addFile(Path);
 }
 
 // This function is called on startup. We need this for LTO since
 // LTO calls LLVM functions to compile bitcode files to native code.
 // Technically this can be delayed until we read bitcode files, but
 // we don't bother to do lazily because the initialization is fast.
 static void initLLVM(opt::InputArgList &Args) {
   InitializeAllTargets();
   InitializeAllTargetMCs();
   InitializeAllAsmPrinters();
   InitializeAllAsmParsers();
 
   // This is a flag to discard all but GlobalValue names.
   // We want to enable it by default because it saves memory.
   // Disable it only when a developer option (-save-temps) is given.
   Driver->Context.setDiscardValueNames(!Config->SaveTemps);
   Driver->Context.enableDebugTypeODRUniquing();
 
   // Parse and evaluate -mllvm options.
   std::vector<const char *> V;
   V.push_back("lld (LLVM option parsing)");
   for (auto *Arg : Args.filtered(OPT_mllvm))
     V.push_back(Arg->getValue());
   cl::ParseCommandLineOptions(V.size(), V.data());
 }
 
 // Some command line options or some combinations of them are not allowed.
 // This function checks for such errors.
 static void checkOptions(opt::InputArgList &Args) {
   // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup
   // table which is a relatively new feature.
   if (Config->EMachine == EM_MIPS && Config->GnuHash)
     error("the .gnu.hash section is not compatible with the MIPS target.");
 
   if (Config->EMachine == EM_AMDGPU && !Config->Entry.empty())
     error("-e option is not valid for AMDGPU.");
 
   if (Config->Pie && Config->Shared)
     error("-shared and -pie may not be used together");
 
   if (Config->Relocatable) {
     if (Config->Shared)
       error("-r and -shared may not be used together");
     if (Config->GcSections)
       error("-r and --gc-sections may not be used together");
     if (Config->ICF)
       error("-r and --icf may not be used together");
     if (Config->Pie)
       error("-r and -pie may not be used together");
   }
 }
 
 static StringRef
 getString(opt::InputArgList &Args, unsigned Key, StringRef Default = "") {
   if (auto *Arg = Args.getLastArg(Key))
     return Arg->getValue();
   return Default;
 }
 
 static int getInteger(opt::InputArgList &Args, unsigned Key, int Default) {
   int V = Default;
   if (auto *Arg = Args.getLastArg(Key)) {
     StringRef S = Arg->getValue();
     if (S.getAsInteger(10, V))
       error(Arg->getSpelling() + ": number expected, but got " + S);
   }
   return V;
 }
 
 static const char *getReproduceOption(opt::InputArgList &Args) {
   if (auto *Arg = Args.getLastArg(OPT_reproduce))
     return Arg->getValue();
   return getenv("LLD_REPRODUCE");
 }
 
 static bool hasZOption(opt::InputArgList &Args, StringRef Key) {
   for (auto *Arg : Args.filtered(OPT_z))
     if (Key == Arg->getValue())
       return true;
   return false;
 }
 
 static Optional<StringRef>
 getZOptionValue(opt::InputArgList &Args, StringRef Key) {
   for (auto *Arg : Args.filtered(OPT_z)) {
     StringRef Value = Arg->getValue();
     size_t Pos = Value.find("=");
     if (Pos != StringRef::npos && Key == Value.substr(0, Pos))
       return Value.substr(Pos + 1);
   }
   return None;
 }
 
 void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
   ELFOptTable Parser;
   opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
   if (Args.hasArg(OPT_help)) {
     printHelp(ArgsArr[0]);
     return;
   }
   if (Args.hasArg(OPT_version))
     outs() << getVersionString();
 
   if (const char *Path = getReproduceOption(Args)) {
     // Note that --reproduce is a debug option so you can ignore it
     // if you are trying to understand the whole picture of the code.
     ErrorOr<CpioFile *> F = CpioFile::create(Path);
     if (F) {
       Cpio.reset(*F);
       Cpio->append("response.txt", createResponseFile(Args));
       Cpio->append("version.txt", getVersionString());
     } else
       error(F.getError(),
             Twine("--reproduce: failed to open ") + Path + ".cpio");
   }
 
   readConfigs(Args);
   initLLVM(Args);
   createFiles(Args);
   checkOptions(Args);
   if (HasError)
     return;
 
   switch (Config->EKind) {
   case ELF32LEKind:
     link<ELF32LE>(Args);
     return;
   case ELF32BEKind:
     link<ELF32BE>(Args);
     return;
   case ELF64LEKind:
     link<ELF64LE>(Args);
     return;
   case ELF64BEKind:
     link<ELF64BE>(Args);
     return;
   default:
     error("-m or at least a .o file required");
   }
 }
 
 static UnresolvedPolicy getUnresolvedSymbolOption(opt::InputArgList &Args) {
   if (Args.hasArg(OPT_noinhibit_exec))
     return UnresolvedPolicy::Warn;
   if (Args.hasArg(OPT_no_undefined) || hasZOption(Args, "defs"))
     return UnresolvedPolicy::NoUndef;
   if (Config->Relocatable)
     return UnresolvedPolicy::Ignore;
 
   if (auto *Arg = Args.getLastArg(OPT_unresolved_symbols)) {
     StringRef S = Arg->getValue();
     if (S == "ignore-all" || S == "ignore-in-object-files")
       return UnresolvedPolicy::Ignore;
     if (S == "ignore-in-shared-libs" || S == "report-all")
       return UnresolvedPolicy::ReportError;
     error("unknown --unresolved-symbols value: " + S);
   }
   return UnresolvedPolicy::ReportError;
 }
 
 static bool isOutputFormatBinary(opt::InputArgList &Args) {
   if (auto *Arg = Args.getLastArg(OPT_oformat)) {
     StringRef S = Arg->getValue();
     if (S == "binary")
       return true;
     error("unknown --oformat value: " + S);
   }
   return false;
 }
 
 static bool getArg(opt::InputArgList &Args, unsigned K1, unsigned K2,
                    bool Default) {
   if (auto *Arg = Args.getLastArg(K1, K2))
     return Arg->getOption().getID() == K1;
   return Default;
 }
 
 static DiscardPolicy getDiscardOption(opt::InputArgList &Args) {
   auto *Arg =
       Args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none);
   if (!Arg)
     return DiscardPolicy::Default;
   if (Arg->getOption().getID() == OPT_discard_all)
     return DiscardPolicy::All;
   if (Arg->getOption().getID() == OPT_discard_locals)
     return DiscardPolicy::Locals;
   return DiscardPolicy::None;
 }
 
 static StripPolicy getStripOption(opt::InputArgList &Args) {
   if (auto *Arg = Args.getLastArg(OPT_strip_all, OPT_strip_debug)) {
     if (Arg->getOption().getID() == OPT_strip_all)
       return StripPolicy::All;
     return StripPolicy::Debug;
   }
   return StripPolicy::None;
 }
 
 // Initializes Config members by the command line options.
 void LinkerDriver::readConfigs(opt::InputArgList &Args) {
   for (auto *Arg : Args.filtered(OPT_L))
     Config->SearchPaths.push_back(Arg->getValue());
 
   std::vector<StringRef> RPaths;
   for (auto *Arg : Args.filtered(OPT_rpath))
     RPaths.push_back(Arg->getValue());
   if (!RPaths.empty())
     Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":");
 
   if (auto *Arg = Args.getLastArg(OPT_m)) {
     // Parse ELF{32,64}{LE,BE} and CPU type.
     StringRef S = Arg->getValue();
     std::tie(Config->EKind, Config->EMachine) = parseEmulation(S);
     Config->Emulation = S;
   }
 
   Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition);
   Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);
   Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);
   Config->Demangle = getArg(Args, OPT_demangle, OPT_no_demangle, true);
   Config->DisableVerify = Args.hasArg(OPT_disable_verify);
   Config->Discard = getDiscardOption(Args);
   Config->EhFrameHdr = Args.hasArg(OPT_eh_frame_hdr);
   Config->EnableNewDtags = !Args.hasArg(OPT_disable_new_dtags);
   Config->ExportDynamic = Args.hasArg(OPT_export_dynamic);
   Config->FatalWarnings = Args.hasArg(OPT_fatal_warnings);
   Config->GcSections = getArg(Args, OPT_gc_sections, OPT_no_gc_sections, false);
   Config->ICF = Args.hasArg(OPT_icf);
   Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique);
   Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version);
   Config->Nostdlib = Args.hasArg(OPT_nostdlib);
   Config->Pie = Args.hasArg(OPT_pie);
   Config->PrintGcSections = Args.hasArg(OPT_print_gc_sections);
   Config->Relocatable = Args.hasArg(OPT_relocatable);
   Config->SaveTemps = Args.hasArg(OPT_save_temps);
   Config->Shared = Args.hasArg(OPT_shared);
   Config->Target1Rel = getArg(Args, OPT_target1_rel, OPT_target1_abs, false);
   Config->Threads = Args.hasArg(OPT_threads);
   Config->Trace = Args.hasArg(OPT_trace);
   Config->Verbose = Args.hasArg(OPT_verbose);
   Config->WarnCommon = Args.hasArg(OPT_warn_common);
 
   Config->DynamicLinker = getString(Args, OPT_dynamic_linker);
   Config->Entry = getString(Args, OPT_entry);
   Config->Fini = getString(Args, OPT_fini, "_fini");
   Config->Init = getString(Args, OPT_init, "_init");
   Config->LtoAAPipeline = getString(Args, OPT_lto_aa_pipeline);
   Config->LtoNewPmPasses = getString(Args, OPT_lto_newpm_passes);
   Config->OutputFile = getString(Args, OPT_o);
   Config->SoName = getString(Args, OPT_soname);
   Config->Sysroot = getString(Args, OPT_sysroot);
 
   Config->Optimize = getInteger(Args, OPT_O, 1);
   Config->LtoO = getInteger(Args, OPT_lto_O, 2);
   if (Config->LtoO > 3)
     error("invalid optimization level for LTO: " + getString(Args, OPT_lto_O));
   Config->LtoJobs = getInteger(Args, OPT_lto_jobs, 1);
   if (Config->LtoJobs == 0)
     error("number of threads must be > 0");
 
   Config->ZCombreloc = !hasZOption(Args, "nocombreloc");
   Config->ZExecStack = hasZOption(Args, "execstack");
   Config->ZNodelete = hasZOption(Args, "nodelete");
   Config->ZNow = hasZOption(Args, "now");
   Config->ZOrigin = hasZOption(Args, "origin");
   Config->ZRelro = !hasZOption(Args, "norelro");
 
   if (!Config->Relocatable)
     Config->Strip = getStripOption(Args);
 
   if (Optional<StringRef> Value = getZOptionValue(Args, "stack-size"))
     if (Value->getAsInteger(0, Config->ZStackSize))
       error("invalid stack size: " + *Value);
 
   // Config->Pic is true if we are generating position-independent code.
   Config->Pic = Config->Pie || Config->Shared;
 
   if (auto *Arg = Args.getLastArg(OPT_hash_style)) {
     StringRef S = Arg->getValue();
     if (S == "gnu") {
       Config->GnuHash = true;
       Config->SysvHash = false;
     } else if (S == "both") {
       Config->GnuHash = true;
     } else if (S != "sysv")
       error("unknown hash style: " + S);
   }
 
   // Parse --build-id or --build-id=<style>.
   if (Args.hasArg(OPT_build_id))
     Config->BuildId = BuildIdKind::Fnv1;
   if (auto *Arg = Args.getLastArg(OPT_build_id_eq)) {
     StringRef S = Arg->getValue();
     if (S == "md5") {
       Config->BuildId = BuildIdKind::Md5;
     } else if (S == "sha1") {
       Config->BuildId = BuildIdKind::Sha1;
     } else if (S == "uuid") {
       Config->BuildId = BuildIdKind::Uuid;
     } else if (S == "none") {
       Config->BuildId = BuildIdKind::None;
     } else if (S.startswith("0x")) {
       Config->BuildId = BuildIdKind::Hexstring;
       Config->BuildIdVector = parseHex(S.substr(2));
     } else {
       error("unknown --build-id style: " + S);
     }
   }
 
   Config->OFormatBinary = isOutputFormatBinary(Args);
 
   for (auto *Arg : Args.filtered(OPT_auxiliary))
     Config->AuxiliaryList.push_back(Arg->getValue());
   if (!Config->Shared && !Config->AuxiliaryList.empty())
     error("-f may not be used without -shared");
 
   for (auto *Arg : Args.filtered(OPT_undefined))
     Config->Undefined.push_back(Arg->getValue());
 
   Config->UnresolvedSymbols = getUnresolvedSymbolOption(Args);
 
   if (auto *Arg = Args.getLastArg(OPT_dynamic_list))
     if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
       parseDynamicList(*Buffer);
 
   for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol))
     Config->DynamicList.push_back(Arg->getValue());
 
   if (auto *Arg = Args.getLastArg(OPT_version_script))
     if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
       readVersionScript(*Buffer);
 }
 
 void LinkerDriver::createFiles(opt::InputArgList &Args) {
   for (auto *Arg : Args) {
     switch (Arg->getOption().getID()) {
     case OPT_l:
       addLibrary(Arg->getValue());
       break;
-    case OPT_alias_script_T:
     case OPT_INPUT:
-    case OPT_script:
       addFile(Arg->getValue());
       break;
+    case OPT_alias_script_T:
+    case OPT_script:
+      addFile(Arg->getValue(), true);
+      break;
     case OPT_as_needed:
       Config->AsNeeded = true;
       break;
+    case OPT_format: {
+      StringRef Val = Arg->getValue();
+      if (Val == "elf" || Val == "default") {
+        Config->Binary = false;
+        break;
+      }
+      if (Val == "binary") {
+        Config->Binary = true;
+        break;
+      }
+      error("unknown " + Arg->getSpelling() + " format: " + Arg->getValue() +
+            " (supported formats: elf, default, binary)");
+      break;
+    }
     case OPT_no_as_needed:
       Config->AsNeeded = false;
       break;
     case OPT_Bstatic:
       Config->Static = true;
       break;
     case OPT_Bdynamic:
       Config->Static = false;
       break;
     case OPT_whole_archive:
       WholeArchive = true;
       break;
     case OPT_no_whole_archive:
       WholeArchive = false;
       break;
     case OPT_start_lib:
       InLib = true;
       break;
     case OPT_end_lib:
       InLib = false;
       break;
     }
   }
 
   if (Files.empty() && !HasError)
     error("no input files.");
 
   // If -m <machine_type> was not given, infer it from object files.
   if (Config->EKind == ELFNoneKind) {
     for (std::unique_ptr<InputFile> &F : Files) {
       if (F->EKind == ELFNoneKind)
         continue;
       Config->EKind = F->EKind;
       Config->EMachine = F->EMachine;
       break;
     }
   }
 }
 
 // Do actual linking. Note that when this function is called,
 // all linker scripts have already been parsed.
 template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
   SymbolTable<ELFT> Symtab;
   elf::Symtab<ELFT>::X = &Symtab;
 
   std::unique_ptr<TargetInfo> TI(createTarget());
   Target = TI.get();
   LinkerScript<ELFT> LS;
   Script<ELFT>::X = &LS;
 
   Config->Rela = ELFT::Is64Bits || Config->EMachine == EM_X86_64;
   Config->Mips64EL =
       (Config->EMachine == EM_MIPS && Config->EKind == ELF64LEKind);
 
   // Add entry symbol. Note that AMDGPU binaries have no entry points.
   if (Config->Entry.empty() && !Config->Shared && !Config->Relocatable &&
       Config->EMachine != EM_AMDGPU)
     Config->Entry = (Config->EMachine == EM_MIPS) ? "__start" : "_start";
 
   // Default output filename is "a.out" by the Unix tradition.
   if (Config->OutputFile.empty())
     Config->OutputFile = "a.out";
 
   // Handle --trace-symbol.
   for (auto *Arg : Args.filtered(OPT_trace_symbol))
     Symtab.trace(Arg->getValue());
 
   // Set either EntryAddr (if S is a number) or EntrySym (otherwise).
   if (!Config->Entry.empty()) {
     StringRef S = Config->Entry;
     if (S.getAsInteger(0, Config->EntryAddr))
       Config->EntrySym = Symtab.addUndefined(S);
   }
 
   // Initialize Config->ImageBase.
   if (auto *Arg = Args.getLastArg(OPT_image_base)) {
     StringRef S = Arg->getValue();
     if (S.getAsInteger(0, Config->ImageBase))
       error(Arg->getSpelling() + ": number expected, but got " + S);
     else if ((Config->ImageBase % Target->PageSize) != 0)
       warning(Arg->getSpelling() + ": address isn't multiple of page size");
   } else {
     Config->ImageBase = Config->Pic ? 0 : Target->DefaultImageBase;
   }
 
   for (std::unique_ptr<InputFile> &F : Files)
     Symtab.addFile(std::move(F));
   if (HasError)
     return; // There were duplicate symbols or incompatible files
 
   Symtab.scanUndefinedFlags();
   Symtab.scanShlibUndefined();
   Symtab.scanDynamicList();
   Symtab.scanVersionScript();
 
   Symtab.addCombinedLtoObject();
   if (HasError)
     return;
 
   for (auto *Arg : Args.filtered(OPT_wrap))
     Symtab.wrap(Arg->getValue());
 
   // Write the result to the file.
   if (Config->GcSections)
     markLive<ELFT>();
   if (Config->ICF)
     doIcf<ELFT>();
 
   // MergeInputSection::splitIntoPieces needs to be called before
   // any call of MergeInputSection::getOffset. Do that.
   for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
        Symtab.getObjectFiles())
     for (InputSectionBase<ELFT> *S : F->getSections()) {
       if (!S || S == &InputSection<ELFT>::Discarded || !S->Live)
         continue;
       if (S->Compressed)
         S->uncompress();
       if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(S))
         MS->splitIntoPieces();
     }
 
   writeResult<ELFT>();
 }
diff --git a/ELF/Driver.h b/ELF/Driver.h
index 9726430..b16244f 100644
--- a/ELF/Driver.h
+++ b/ELF/Driver.h
@@ -1,84 +1,84 @@
 //===- Driver.h -------------------------------------------------*- C++ -*-===//
 //
 //                             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 "SymbolTable.h"
 #include "lld/Core/LLVM.h"
 #include "lld/Core/Reproduce.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/raw_ostream.h"
 
 namespace lld {
 namespace elf {
 
 extern class LinkerDriver *Driver;
 
 class LinkerDriver {
 public:
   void main(ArrayRef<const char *> Args);
-  void addFile(StringRef Path);
+  void addFile(StringRef Path, bool KnownScript = false);
   void addLibrary(StringRef Name);
   llvm::LLVMContext Context;      // to parse bitcode ifles
   std::unique_ptr<CpioFile> Cpio; // for reproduce
 
 private:
   std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB);
   llvm::Optional<MemoryBufferRef> readFile(StringRef Path);
   void readConfigs(llvm::opt::InputArgList &Args);
   void createFiles(llvm::opt::InputArgList &Args);
   template <class ELFT> void link(llvm::opt::InputArgList &Args);
 
   // True if we are in --whole-archive and --no-whole-archive.
   bool WholeArchive = false;
 
   // True if we are in --start-lib and --end-lib.
   bool InLib = false;
 
   llvm::BumpPtrAllocator Alloc;
   std::vector<std::unique_ptr<InputFile>> Files;
   std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
 };
 
 // Parses command line options.
 class ELFOptTable : public llvm::opt::OptTable {
 public:
   ELFOptTable();
   llvm::opt::InputArgList parse(ArrayRef<const char *> Argv);
 
 private:
   llvm::BumpPtrAllocator Alloc;
 };
 
 // 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
 };
 
 void printHelp(const char *Argv0);
 std::string getVersionString();
 std::vector<uint8_t> parseHexstring(StringRef S);
 
 std::string createResponseFile(const llvm::opt::InputArgList &Args);
 
 std::string findFromSearchPaths(StringRef Path);
 std::string searchLibrary(StringRef Path);
 std::string buildSysrootedPath(llvm::StringRef Dir, llvm::StringRef File);
 
 } // namespace elf
 } // namespace lld
 
 #endif
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index 4db9907..64212d2 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -1,851 +1,902 @@
 //===- InputFiles.cpp -----------------------------------------------------===//
 //
 //                             The LLVM Linker
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
 #include "InputFiles.h"
 #include "Driver.h"
 #include "Error.h"
 #include "InputSection.h"
 #include "LinkerScript.h"
+#include "SimpleELFWriter.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Bitcode/ReaderWriter.h"
 #include "llvm/CodeGen/Analysis.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
 
 using namespace llvm;
 using namespace llvm::ELF;
 using namespace llvm::object;
 using namespace llvm::sys::fs;
 
 using namespace lld;
 using namespace lld::elf;
 
 // Returns "(internal)", "foo.a(bar.o)" or "baz.o".
 std::string elf::getFilename(const InputFile *F) {
   if (!F)
     return "(internal)";
   if (!F->ArchiveName.empty())
     return (F->ArchiveName + "(" + F->getName() + ")").str();
   return F->getName();
 }
 
 template <class ELFT>
 static ELFFile<ELFT> createELFObj(MemoryBufferRef MB) {
   std::error_code EC;
   ELFFile<ELFT> F(MB.getBuffer(), EC);
   if (EC)
     error(EC, "failed to read " + MB.getBufferIdentifier());
   return F;
 }
 
 template <class ELFT> static ELFKind getELFKind() {
   if (ELFT::TargetEndianness == support::little)
     return ELFT::Is64Bits ? ELF64LEKind : ELF32LEKind;
   return ELFT::Is64Bits ? ELF64BEKind : ELF32BEKind;
 }
 
 template <class ELFT>
 ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef MB)
     : InputFile(K, MB), ELFObj(createELFObj<ELFT>(MB)) {
   EKind = getELFKind<ELFT>();
   EMachine = ELFObj.getHeader()->e_machine;
 }
 
 template <class ELFT>
 typename ELFT::SymRange ELFFileBase<ELFT>::getElfSymbols(bool OnlyGlobals) {
   if (!Symtab)
     return Elf_Sym_Range(nullptr, nullptr);
   Elf_Sym_Range Syms = ELFObj.symbols(Symtab);
   uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
   uint32_t FirstNonLocal = Symtab->sh_info;
   if (FirstNonLocal > NumSymbols)
     fatal(getFilename(this) + ": invalid sh_info in symbol table");
 
   if (OnlyGlobals)
     return makeArrayRef(Syms.begin() + FirstNonLocal, Syms.end());
   return makeArrayRef(Syms.begin(), Syms.end());
 }
 
 template <class ELFT>
 uint32_t ELFFileBase<ELFT>::getSectionIndex(const Elf_Sym &Sym) const {
   uint32_t I = Sym.st_shndx;
   if (I == ELF::SHN_XINDEX)
     return ELFObj.getExtendedSymbolTableIndex(&Sym, Symtab, SymtabSHNDX);
   if (I >= ELF::SHN_LORESERVE)
     return 0;
   return I;
 }
 
 template <class ELFT> void ELFFileBase<ELFT>::initStringTable() {
   if (!Symtab)
     return;
   StringTable = check(ELFObj.getStringTableForSymtab(*Symtab));
 }
 
 template <class ELFT>
 elf::ObjectFile<ELFT>::ObjectFile(MemoryBufferRef M)
     : ELFFileBase<ELFT>(Base::ObjectKind, M) {}
 
 template <class ELFT>
 ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getNonLocalSymbols() {
   if (!this->Symtab)
     return this->SymbolBodies;
   uint32_t FirstNonLocal = this->Symtab->sh_info;
   return makeArrayRef(this->SymbolBodies).slice(FirstNonLocal);
 }
 
 template <class ELFT>
 ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getLocalSymbols() {
   if (!this->Symtab)
     return this->SymbolBodies;
   uint32_t FirstNonLocal = this->Symtab->sh_info;
   return makeArrayRef(this->SymbolBodies).slice(1, FirstNonLocal - 1);
 }
 
 template <class ELFT>
 ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getSymbols() {
   if (!this->Symtab)
     return this->SymbolBodies;
   return makeArrayRef(this->SymbolBodies).slice(1);
 }
 
 template <class ELFT> uint32_t elf::ObjectFile<ELFT>::getMipsGp0() const {
   if (ELFT::Is64Bits && MipsOptions && MipsOptions->Reginfo)
     return MipsOptions->Reginfo->ri_gp_value;
   if (!ELFT::Is64Bits && MipsReginfo && MipsReginfo->Reginfo)
     return MipsReginfo->Reginfo->ri_gp_value;
   return 0;
 }
 
 template <class ELFT>
 void elf::ObjectFile<ELFT>::parse(DenseSet<StringRef> &ComdatGroups) {
   // Read section and symbol tables.
   initializeSections(ComdatGroups);
   initializeSymbols();
 }
 
 // Sections with SHT_GROUP and comdat bits define comdat section groups.
 // They are identified and deduplicated by group name. This function
 // returns a group name.
 template <class ELFT>
 StringRef elf::ObjectFile<ELFT>::getShtGroupSignature(const Elf_Shdr &Sec) {
   const ELFFile<ELFT> &Obj = this->ELFObj;
   const Elf_Shdr *Symtab = check(Obj.getSection(Sec.sh_link));
   const Elf_Sym *Sym = Obj.getSymbol(Symtab, Sec.sh_info);
   StringRef Strtab = check(Obj.getStringTableForSymtab(*Symtab));
   return check(Sym->getName(Strtab));
 }
 
 template <class ELFT>
 ArrayRef<typename elf::ObjectFile<ELFT>::Elf_Word>
 elf::ObjectFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) {
   const ELFFile<ELFT> &Obj = this->ELFObj;
   ArrayRef<Elf_Word> Entries =
       check(Obj.template getSectionContentsAsArray<Elf_Word>(&Sec));
   if (Entries.empty() || Entries[0] != GRP_COMDAT)
     fatal(getFilename(this) + ": unsupported SHT_GROUP format");
   return Entries.slice(1);
 }
 
 template <class ELFT>
 bool elf::ObjectFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {
   // We don't merge sections if -O0 (default is -O1). This makes sometimes
   // the linker significantly faster, although the output will be bigger.
   if (Config->Optimize == 0)
     return false;
 
   // We don't merge if linker script has SECTIONS command. When script
   // do layout it can merge several sections with different attributes
   // into single output sections. We currently do not support adding
   // mergeable input sections to regular output ones as well as adding
   // regular input sections to mergeable output.
   if (ScriptConfig->HasContents)
     return false;
 
   // A mergeable section with size 0 is useless because they don't have
   // any data to merge. A mergeable string section with size 0 can be
   // argued as invalid because it doesn't end with a null character.
   // We'll avoid a mess by handling them as if they were non-mergeable.
   if (Sec.sh_size == 0)
     return false;
 
   uintX_t Flags = Sec.sh_flags;
   if (!(Flags & SHF_MERGE))
     return false;
   if (Flags & SHF_WRITE)
     fatal(getFilename(this) + ": writable SHF_MERGE section is not supported");
   uintX_t EntSize = Sec.sh_entsize;
   if (!EntSize || Sec.sh_size % EntSize)
     fatal(getFilename(this) +
           ": SHF_MERGE section size must be a multiple of sh_entsize");
 
   // Don't try to merge if the alignment is larger than the sh_entsize and this
   // is not SHF_STRINGS.
   //
   // Since this is not a SHF_STRINGS, we would need to pad after every entity.
   // It would be equivalent for the producer of the .o to just set a larger
   // sh_entsize.
   if (Flags & SHF_STRINGS)
     return true;
 
   return Sec.sh_addralign <= EntSize;
 }
 
 template <class ELFT>
 void elf::ObjectFile<ELFT>::initializeSections(
     DenseSet<StringRef> &ComdatGroups) {
   uint64_t Size = this->ELFObj.getNumSections();
   Sections.resize(Size);
   unsigned I = -1;
   const ELFFile<ELFT> &Obj = this->ELFObj;
   for (const Elf_Shdr &Sec : Obj.sections()) {
     ++I;
     if (Sections[I] == &InputSection<ELFT>::Discarded)
       continue;
 
     switch (Sec.sh_type) {
     case SHT_GROUP:
       Sections[I] = &InputSection<ELFT>::Discarded;
       if (ComdatGroups.insert(getShtGroupSignature(Sec)).second)
         continue;
       for (uint32_t SecIndex : getShtGroupEntries(Sec)) {
         if (SecIndex >= Size)
           fatal(getFilename(this) + ": invalid section index in group: " +
                 Twine(SecIndex));
         Sections[SecIndex] = &InputSection<ELFT>::Discarded;
       }
       break;
     case SHT_SYMTAB:
       this->Symtab = &Sec;
       break;
     case SHT_SYMTAB_SHNDX:
       this->SymtabSHNDX = check(Obj.getSHNDXTable(Sec));
       break;
     case SHT_STRTAB:
     case SHT_NULL:
       break;
     case SHT_RELA:
     case SHT_REL: {
       // This section contains relocation information.
       // If -r is given, we do not interpret or apply relocation
       // but just copy relocation sections to output.
       if (Config->Relocatable) {
         Sections[I] = new (IAlloc.Allocate()) InputSection<ELFT>(this, &Sec);
         break;
       }
 
       // Find the relocation target section and associate this
       // section with it.
       InputSectionBase<ELFT> *Target = getRelocTarget(Sec);
       if (!Target)
         break;
       if (auto *S = dyn_cast<InputSection<ELFT>>(Target)) {
         S->RelocSections.push_back(&Sec);
         break;
       }
       if (auto *S = dyn_cast<EhInputSection<ELFT>>(Target)) {
         if (S->RelocSection)
           fatal(
               getFilename(this) +
               ": multiple relocation sections to .eh_frame are not supported");
         S->RelocSection = &Sec;
         break;
       }
       fatal(getFilename(this) +
             ": relocations pointing to SHF_MERGE are not supported");
     }
     case SHT_ARM_ATTRIBUTES:
       // FIXME: ARM meta-data section. At present attributes are ignored,
       // they can be used to reason about object compatibility.
       Sections[I] = &InputSection<ELFT>::Discarded;
       break;
     case SHT_MIPS_REGINFO:
       MipsReginfo.reset(new MipsReginfoInputSection<ELFT>(this, &Sec));
       Sections[I] = MipsReginfo.get();
       break;
     case SHT_MIPS_OPTIONS:
       MipsOptions.reset(new MipsOptionsInputSection<ELFT>(this, &Sec));
       Sections[I] = MipsOptions.get();
       break;
     case SHT_MIPS_ABIFLAGS:
       MipsAbiFlags.reset(new MipsAbiFlagsInputSection<ELFT>(this, &Sec));
       Sections[I] = MipsAbiFlags.get();
       break;
     default:
       Sections[I] = createInputSection(Sec);
     }
   }
 }
 
 template <class ELFT>
 InputSectionBase<ELFT> *
 elf::ObjectFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) {
   uint32_t Idx = Sec.sh_info;
   if (Idx >= Sections.size())
     fatal(getFilename(this) + ": invalid relocated section index: " +
           Twine(Idx));
   InputSectionBase<ELFT> *Target = Sections[Idx];
 
   // Strictly speaking, a relocation section must be included in the
   // group of the section it relocates. However, LLVM 3.3 and earlier
   // would fail to do so, so we gracefully handle that case.
   if (Target == &InputSection<ELFT>::Discarded)
     return nullptr;
 
   if (!Target)
     fatal(getFilename(this) + ": unsupported relocation reference");
   return Target;
 }
 
 template <class ELFT>
 InputSectionBase<ELFT> *
 elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
   StringRef Name = check(this->ELFObj.getSectionName(&Sec));
 
   // .note.GNU-stack is a marker section to control the presence of
   // PT_GNU_STACK segment in outputs. Since the presence of the segment
   // is controlled only by the command line option (-z execstack) in LLD,
   // .note.GNU-stack is ignored.
   if (Name == ".note.GNU-stack")
     return &InputSection<ELFT>::Discarded;
 
   if (Name == ".note.GNU-split-stack") {
     error("objects using splitstacks are not supported");
     return &InputSection<ELFT>::Discarded;
   }
 
   if (Config->Strip != StripPolicy::None && Name.startswith(".debug"))
     return &InputSection<ELFT>::Discarded;
 
   // The linker merges EH (exception handling) frames and creates a
   // .eh_frame_hdr section for runtime. So we handle them with a special
   // class. For relocatable outputs, they are just passed through.
   if (Name == ".eh_frame" && !Config->Relocatable)
     return new (EHAlloc.Allocate()) EhInputSection<ELFT>(this, &Sec);
 
   if (shouldMerge(Sec))
     return new (MAlloc.Allocate()) MergeInputSection<ELFT>(this, &Sec);
   return new (IAlloc.Allocate()) InputSection<ELFT>(this, &Sec);
 }
 
 template <class ELFT> void elf::ObjectFile<ELFT>::initializeSymbols() {
   this->initStringTable();
   Elf_Sym_Range Syms = this->getElfSymbols(false);
   uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
   SymbolBodies.reserve(NumSymbols);
   for (const Elf_Sym &Sym : Syms)
     SymbolBodies.push_back(createSymbolBody(&Sym));
 }
 
 template <class ELFT>
 InputSectionBase<ELFT> *
 elf::ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const {
   uint32_t Index = this->getSectionIndex(Sym);
   if (Index == 0)
     return nullptr;
   if (Index >= Sections.size())
     fatal(getFilename(this) + ": invalid section index: " + Twine(Index));
   InputSectionBase<ELFT> *S = Sections[Index];
   // We found that GNU assembler 2.17.50 [FreeBSD] 2007-07-03
   // could generate broken objects. STT_SECTION symbols can be
   // associated with SHT_REL[A]/SHT_SYMTAB/SHT_STRTAB sections.
   // In this case it is fine for section to be null here as we
   // do not allocate sections of these types.
   if (!S || S == &InputSectionBase<ELFT>::Discarded)
     return S;
   return S->Repl;
 }
 
 template <class ELFT>
 SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
   int Binding = Sym->getBinding();
   InputSectionBase<ELFT> *Sec = getSection(*Sym);
   if (Binding == STB_LOCAL) {
     if (Sym->st_shndx == SHN_UNDEF)
       return new (this->Alloc)
           Undefined(Sym->st_name, Sym->st_other, Sym->getType(), this);
     return new (this->Alloc) DefinedRegular<ELFT>(*Sym, Sec);
   }
 
   StringRef Name = check(Sym->getName(this->StringTable));
 
   switch (Sym->st_shndx) {
   case SHN_UNDEF:
     return elf::Symtab<ELFT>::X
         ->addUndefined(Name, Binding, Sym->st_other, Sym->getType(),
                        /*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false,
                        this)
         ->body();
   case SHN_COMMON:
     return elf::Symtab<ELFT>::X
         ->addCommon(Name, Sym->st_size, Sym->st_value, Binding, Sym->st_other,
                     Sym->getType(), /*HasUnnamedAddr*/ false, this)
         ->body();
   }
 
   switch (Binding) {
   default:
     fatal(getFilename(this) + ": unexpected binding: " + Twine(Binding));
   case STB_GLOBAL:
   case STB_WEAK:
   case STB_GNU_UNIQUE:
     if (Sec == &InputSection<ELFT>::Discarded)
       return elf::Symtab<ELFT>::X
           ->addUndefined(Name, Binding, Sym->st_other, Sym->getType(),
                          /*CanOmitFromDynSym*/ false,
                          /*HasUnnamedAddr*/ false, this)
           ->body();
     return elf::Symtab<ELFT>::X->addRegular(Name, *Sym, Sec)->body();
   }
 }
 
 template <class ELFT> void ArchiveFile::parse() {
   File = check(Archive::create(MB), "failed to parse archive");
 
   // Read the symbol table to construct Lazy objects.
   for (const Archive::Symbol &Sym : File->symbols())
     Symtab<ELFT>::X->addLazyArchive(this, Sym);
 }
 
 // Returns a buffer pointing to a member file containing a given symbol.
 MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
   Archive::Child C =
       check(Sym->getMember(),
             "could not get the member for symbol " + Sym->getName());
 
   if (!Seen.insert(C.getChildOffset()).second)
     return MemoryBufferRef();
 
   MemoryBufferRef Ret =
       check(C.getMemoryBufferRef(),
             "could not get the buffer for the member defining symbol " +
                 Sym->getName());
 
   if (C.getParent()->isThin() && Driver->Cpio)
     Driver->Cpio->append(relativeToRoot(check(C.getFullName())),
                          Ret.getBuffer());
 
   return Ret;
 }
 
 template <class ELFT>
 SharedFile<ELFT>::SharedFile(MemoryBufferRef M)
     : ELFFileBase<ELFT>(Base::SharedKind, M), AsNeeded(Config->AsNeeded) {}
 
 template <class ELFT>
 const typename ELFT::Shdr *
 SharedFile<ELFT>::getSection(const Elf_Sym &Sym) const {
   uint32_t Index = this->getSectionIndex(Sym);
   if (Index == 0)
     return nullptr;
   return check(this->ELFObj.getSection(Index));
 }
 
 // Partially parse the shared object file so that we can call
 // getSoName on this object.
 template <class ELFT> void SharedFile<ELFT>::parseSoName() {
   typedef typename ELFT::Dyn Elf_Dyn;
   typedef typename ELFT::uint uintX_t;
   const Elf_Shdr *DynamicSec = nullptr;
 
   const ELFFile<ELFT> Obj = this->ELFObj;
   for (const Elf_Shdr &Sec : Obj.sections()) {
     switch (Sec.sh_type) {
     default:
       continue;
     case SHT_DYNSYM:
       this->Symtab = &Sec;
       break;
     case SHT_DYNAMIC:
       DynamicSec = &Sec;
       break;
     case SHT_SYMTAB_SHNDX:
       this->SymtabSHNDX = check(Obj.getSHNDXTable(Sec));
       break;
     case SHT_GNU_versym:
       this->VersymSec = &Sec;
       break;
     case SHT_GNU_verdef:
       this->VerdefSec = &Sec;
       break;
     }
   }
 
   this->initStringTable();
   SoName = this->getName();
 
   if (!DynamicSec)
     return;
   auto *Begin =
       reinterpret_cast<const Elf_Dyn *>(Obj.base() + DynamicSec->sh_offset);
   const Elf_Dyn *End = Begin + DynamicSec->sh_size / sizeof(Elf_Dyn);
 
   for (const Elf_Dyn &Dyn : make_range(Begin, End)) {
     if (Dyn.d_tag == DT_SONAME) {
       uintX_t Val = Dyn.getVal();
       if (Val >= this->StringTable.size())
         fatal(getFilename(this) + ": invalid DT_SONAME entry");
       SoName = StringRef(this->StringTable.data() + Val);
       return;
     }
   }
 }
 
 // Parse the version definitions in the object file if present. Returns a vector
 // whose nth element contains a pointer to the Elf_Verdef for version identifier
 // n. Version identifiers that are not definitions map to nullptr. The array
 // always has at least length 1.
 template <class ELFT>
 std::vector<const typename ELFT::Verdef *>
 SharedFile<ELFT>::parseVerdefs(const Elf_Versym *&Versym) {
   std::vector<const Elf_Verdef *> Verdefs(1);
   // We only need to process symbol versions for this DSO if it has both a
   // versym and a verdef section, which indicates that the DSO contains symbol
   // version definitions.
   if (!VersymSec || !VerdefSec)
     return Verdefs;
 
   // The location of the first global versym entry.
   Versym = reinterpret_cast<const Elf_Versym *>(this->ELFObj.base() +
                                                 VersymSec->sh_offset) +
            this->Symtab->sh_info;
 
   // We cannot determine the largest verdef identifier without inspecting
   // every Elf_Verdef, but both bfd and gold assign verdef identifiers
   // sequentially starting from 1, so we predict that the largest identifier
   // will be VerdefCount.
   unsigned VerdefCount = VerdefSec->sh_info;
   Verdefs.resize(VerdefCount + 1);
 
   // Build the Verdefs array by following the chain of Elf_Verdef objects
   // from the start of the .gnu.version_d section.
   const uint8_t *Verdef = this->ELFObj.base() + VerdefSec->sh_offset;
   for (unsigned I = 0; I != VerdefCount; ++I) {
     auto *CurVerdef = reinterpret_cast<const Elf_Verdef *>(Verdef);
     Verdef += CurVerdef->vd_next;
     unsigned VerdefIndex = CurVerdef->vd_ndx;
     if (Verdefs.size() <= VerdefIndex)
       Verdefs.resize(VerdefIndex + 1);
     Verdefs[VerdefIndex] = CurVerdef;
   }
 
   return Verdefs;
 }
 
 // Fully parse the shared object file. This must be called after parseSoName().
 template <class ELFT> void SharedFile<ELFT>::parseRest() {
   // Create mapping from version identifiers to Elf_Verdef entries.
   const Elf_Versym *Versym = nullptr;
   std::vector<const Elf_Verdef *> Verdefs = parseVerdefs(Versym);
 
   Elf_Sym_Range Syms = this->getElfSymbols(true);
   for (const Elf_Sym &Sym : Syms) {
     unsigned VersymIndex = 0;
     if (Versym) {
       VersymIndex = Versym->vs_index;
       ++Versym;
     }
 
     StringRef Name = check(Sym.getName(this->StringTable));
     if (Sym.isUndefined()) {
       Undefs.push_back(Name);
       continue;
     }
 
     if (Versym) {
       // Ignore local symbols and non-default versions.
       if (VersymIndex == VER_NDX_LOCAL || (VersymIndex & VERSYM_HIDDEN))
         continue;
     }
 
     const Elf_Verdef *V =
         VersymIndex == VER_NDX_GLOBAL ? nullptr : Verdefs[VersymIndex];
     elf::Symtab<ELFT>::X->addShared(this, Name, Sym, V);
   }
 }
 
 static ELFKind getBitcodeELFKind(MemoryBufferRef MB) {
   Triple T(getBitcodeTargetTriple(MB, Driver->Context));
   if (T.isLittleEndian())
     return T.isArch64Bit() ? ELF64LEKind : ELF32LEKind;
   return T.isArch64Bit() ? ELF64BEKind : ELF32BEKind;
 }
 
 static uint8_t getBitcodeMachineKind(MemoryBufferRef MB) {
   Triple T(getBitcodeTargetTriple(MB, Driver->Context));
   switch (T.getArch()) {
   case Triple::aarch64:
     return EM_AARCH64;
   case Triple::arm:
     return EM_ARM;
   case Triple::mips:
   case Triple::mipsel:
   case Triple::mips64:
   case Triple::mips64el:
     return EM_MIPS;
   case Triple::ppc:
     return EM_PPC;
   case Triple::ppc64:
     return EM_PPC64;
   case Triple::x86:
     return T.isOSIAMCU() ? EM_IAMCU : EM_386;
   case Triple::x86_64:
     return EM_X86_64;
   default:
     fatal(MB.getBufferIdentifier() +
           ": could not infer e_machine from bitcode target triple " + T.str());
   }
 }
 
 BitcodeFile::BitcodeFile(MemoryBufferRef MB) : InputFile(BitcodeKind, MB) {
   EKind = getBitcodeELFKind(MB);
   EMachine = getBitcodeMachineKind(MB);
 }
 
 static uint8_t getGvVisibility(const GlobalValue *GV) {
   switch (GV->getVisibility()) {
   case GlobalValue::DefaultVisibility:
     return STV_DEFAULT;
   case GlobalValue::HiddenVisibility:
     return STV_HIDDEN;
   case GlobalValue::ProtectedVisibility:
     return STV_PROTECTED;
   }
   llvm_unreachable("unknown visibility");
 }
 
 template <class ELFT>
 Symbol *BitcodeFile::createSymbol(const DenseSet<const Comdat *> &KeptComdats,
                                   const IRObjectFile &Obj,
                                   const BasicSymbolRef &Sym) {
   const GlobalValue *GV = Obj.getSymbolGV(Sym.getRawDataRefImpl());
 
   SmallString<64> Name;
   raw_svector_ostream OS(Name);
   Sym.printName(OS);
   StringRef NameRef = Saver.save(StringRef(Name));
 
   uint32_t Flags = Sym.getFlags();
   uint32_t Binding = (Flags & BasicSymbolRef::SF_Weak) ? STB_WEAK : STB_GLOBAL;
 
   uint8_t Type = STT_NOTYPE;
   uint8_t Visibility;
   bool CanOmitFromDynSym = false;
   bool HasUnnamedAddr = false;
 
   // FIXME: Expose a thread-local flag for module asm symbols.
   if (GV) {
     if (GV->isThreadLocal())
       Type = STT_TLS;
     CanOmitFromDynSym = canBeOmittedFromSymbolTable(GV);
     Visibility = getGvVisibility(GV);
     HasUnnamedAddr =
         GV->getUnnamedAddr() == llvm::GlobalValue::UnnamedAddr::Global;
   } else {
     // FIXME: Set SF_Hidden flag correctly for module asm symbols, and expose
     // protected visibility.
     Visibility = STV_DEFAULT;
   }
 
   if (GV)
     if (const Comdat *C = GV->getComdat())
       if (!KeptComdats.count(C))
         return Symtab<ELFT>::X->addUndefined(NameRef, Binding, Visibility, Type,
                                              CanOmitFromDynSym, HasUnnamedAddr,
                                              this);
 
   const Module &M = Obj.getModule();
   if (Flags & BasicSymbolRef::SF_Undefined)
     return Symtab<ELFT>::X->addUndefined(NameRef, Binding, Visibility, Type,
                                          CanOmitFromDynSym, HasUnnamedAddr,
                                          this);
   if (Flags & BasicSymbolRef::SF_Common) {
     // FIXME: Set SF_Common flag correctly for module asm symbols, and expose
     // size and alignment.
     assert(GV);
     const DataLayout &DL = M.getDataLayout();
     uint64_t Size = DL.getTypeAllocSize(GV->getValueType());
     return Symtab<ELFT>::X->addCommon(NameRef, Size, GV->getAlignment(),
                                       Binding, Visibility, STT_OBJECT,
                                       HasUnnamedAddr, this);
   }
   return Symtab<ELFT>::X->addBitcode(NameRef, Binding, Visibility, Type,
                                      CanOmitFromDynSym, HasUnnamedAddr, this);
 }
 
 bool BitcodeFile::shouldSkip(uint32_t Flags) {
   return !(Flags & BasicSymbolRef::SF_Global) ||
          (Flags & BasicSymbolRef::SF_FormatSpecific);
 }
 
 template <class ELFT>
 void BitcodeFile::parse(DenseSet<StringRef> &ComdatGroups) {
   Obj = check(IRObjectFile::create(MB, Driver->Context));
   const Module &M = Obj->getModule();
 
   DenseSet<const Comdat *> KeptComdats;
   for (const auto &P : M.getComdatSymbolTable()) {
     StringRef N = Saver.save(P.first());
     if (ComdatGroups.insert(N).second)
       KeptComdats.insert(&P.second);
   }
 
   for (const BasicSymbolRef &Sym : Obj->symbols())
     if (!shouldSkip(Sym.getFlags()))
       Symbols.push_back(createSymbol<ELFT>(KeptComdats, *Obj, Sym));
 }
 
 template <template <class> class T>
 static std::unique_ptr<InputFile> createELFFile(MemoryBufferRef MB) {
   unsigned char Size;
   unsigned char Endian;
   std::tie(Size, Endian) = getElfArchType(MB.getBuffer());
   if (Endian != ELFDATA2LSB && Endian != ELFDATA2MSB)
     fatal("invalid data encoding: " + MB.getBufferIdentifier());
 
   std::unique_ptr<InputFile> Obj;
   if (Size == ELFCLASS32 && Endian == ELFDATA2LSB)
     Obj.reset(new T<ELF32LE>(MB));
   else if (Size == ELFCLASS32 && Endian == ELFDATA2MSB)
     Obj.reset(new T<ELF32BE>(MB));
   else if (Size == ELFCLASS64 && Endian == ELFDATA2LSB)
     Obj.reset(new T<ELF64LE>(MB));
   else if (Size == ELFCLASS64 && Endian == ELFDATA2MSB)
     Obj.reset(new T<ELF64BE>(MB));
   else
     fatal("invalid file class: " + MB.getBufferIdentifier());
 
   if (!Config->FirstElf)
     Config->FirstElf = Obj.get();
   return Obj;
 }
 
+template <class ELFT> std::unique_ptr<InputFile> BinaryFile::createELF() {
+  SimpleELFWriter<ELFT> ELF(ET_REL, Config->EMachine);
+  auto DataSec = ELF.addSection(".data");
+  DataSec.Header->sh_flags = SHF_ALLOC;
+  DataSec.Header->sh_size = MB.getBufferSize();
+  DataSec.Header->sh_type = SHT_PROGBITS;
+  DataSec.Header->sh_addralign = 8;
+
+  std::string Filename = sys::path::filename(MB.getBufferIdentifier()).str();
+  std::transform(Filename.begin(), Filename.end(), Filename.begin(),
+                 [](char C) { return isalnum(C) ? C : '_'; });
+  std::string StartSym = "_binary_" + Filename + "_start";
+  std::string EndSym = "_binary_" + Filename + "_end";
+  std::string SizeSym = "_binary_" + Filename + "_size";
+
+  auto SSym = ELF.addSymbol(StartSym);
+  SSym.Sym->setBindingAndType(STB_GLOBAL, STT_OBJECT);
+  SSym.Sym->st_shndx = DataSec.Index;
+
+  auto ESym = ELF.addSymbol(EndSym);
+  ESym.Sym->setBindingAndType(STB_GLOBAL, STT_OBJECT);
+  ESym.Sym->st_shndx = DataSec.Index;
+  ESym.Sym->st_value = MB.getBufferSize();
+
+  auto SZSym = ELF.addSymbol(SizeSym);
+  SZSym.Sym->setBindingAndType(STB_GLOBAL, STT_OBJECT);
+  SZSym.Sym->st_shndx = SHN_ABS;
+  SZSym.Sym->st_value = MB.getBufferSize();
+
+  std::size_t Size = ELF.layout();
+  char *Buff = new char[Size]{};
+  ELFData.reset(Buff);
+
+  ELF.write(Buff);
+
+  // .data
+  std::copy(MB.getBufferStart(), MB.getBufferEnd(),
+            Buff + DataSec.Header->sh_offset);
+
+  return createELFFile<ObjectFile>(
+      MemoryBufferRef(StringRef(Buff, Size), MB.getBufferIdentifier()));
+}
+
 static bool isBitcode(MemoryBufferRef MB) {
   using namespace sys::fs;
   return identify_magic(MB.getBuffer()) == file_magic::bitcode;
 }
 
 std::unique_ptr<InputFile> elf::createObjectFile(MemoryBufferRef MB,
                                                  StringRef ArchiveName) {
   std::unique_ptr<InputFile> F;
   if (isBitcode(MB))
     F.reset(new BitcodeFile(MB));
   else
     F = createELFFile<ObjectFile>(MB);
   F->ArchiveName = ArchiveName;
   return F;
 }
 
 std::unique_ptr<InputFile> elf::createSharedFile(MemoryBufferRef MB) {
   return createELFFile<SharedFile>(MB);
 }
 
 MemoryBufferRef LazyObjectFile::getBuffer() {
   if (Seen)
     return MemoryBufferRef();
   Seen = true;
   return MB;
 }
 
 template <class ELFT>
 void LazyObjectFile::parse() {
   for (StringRef Sym : getSymbols())
     Symtab<ELFT>::X->addLazyObject(Sym, *this);
 }
 
 template <class ELFT> std::vector<StringRef> LazyObjectFile::getElfSymbols() {
   typedef typename ELFT::Shdr Elf_Shdr;
   typedef typename ELFT::Sym Elf_Sym;
   typedef typename ELFT::SymRange Elf_Sym_Range;
 
   const ELFFile<ELFT> Obj = createELFObj<ELFT>(this->MB);
   for (const Elf_Shdr &Sec : Obj.sections()) {
     if (Sec.sh_type != SHT_SYMTAB)
       continue;
     Elf_Sym_Range Syms = Obj.symbols(&Sec);
     uint32_t FirstNonLocal = Sec.sh_info;
     StringRef StringTable = check(Obj.getStringTableForSymtab(Sec));
     std::vector<StringRef> V;
     for (const Elf_Sym &Sym : Syms.slice(FirstNonLocal))
       if (Sym.st_shndx != SHN_UNDEF)
         V.push_back(check(Sym.getName(StringTable)));
     return V;
   }
   return {};
 }
 
 std::vector<StringRef> LazyObjectFile::getBitcodeSymbols() {
   LLVMContext Context;
   std::unique_ptr<IRObjectFile> Obj =
       check(IRObjectFile::create(this->MB, Context));
   std::vector<StringRef> V;
   for (const BasicSymbolRef &Sym : Obj->symbols()) {
     uint32_t Flags = Sym.getFlags();
     if (BitcodeFile::shouldSkip(Flags))
       continue;
     if (Flags & BasicSymbolRef::SF_Undefined)
       continue;
     SmallString<64> Name;
     raw_svector_ostream OS(Name);
     Sym.printName(OS);
     V.push_back(Saver.save(StringRef(Name)));
   }
   return V;
 }
 
 // Returns a vector of globally-visible defined symbol names.
 std::vector<StringRef> LazyObjectFile::getSymbols() {
   if (isBitcode(this->MB))
     return getBitcodeSymbols();
 
   unsigned char Size;
   unsigned char Endian;
   std::tie(Size, Endian) = getElfArchType(this->MB.getBuffer());
   if (Size == ELFCLASS32) {
     if (Endian == ELFDATA2LSB)
       return getElfSymbols<ELF32LE>();
     return getElfSymbols<ELF32BE>();
   }
   if (Endian == ELFDATA2LSB)
     return getElfSymbols<ELF64LE>();
   return getElfSymbols<ELF64BE>();
 }
 
 template void ArchiveFile::parse<ELF32LE>();
 template void ArchiveFile::parse<ELF32BE>();
 template void ArchiveFile::parse<ELF64LE>();
 template void ArchiveFile::parse<ELF64BE>();
 
 template void BitcodeFile::parse<ELF32LE>(DenseSet<StringRef> &);
 template void BitcodeFile::parse<ELF32BE>(DenseSet<StringRef> &);
 template void BitcodeFile::parse<ELF64LE>(DenseSet<StringRef> &);
 template void BitcodeFile::parse<ELF64BE>(DenseSet<StringRef> &);
 
 template void LazyObjectFile::parse<ELF32LE>();
 template void LazyObjectFile::parse<ELF32BE>();
 template void LazyObjectFile::parse<ELF64LE>();
 template void LazyObjectFile::parse<ELF64BE>();
 
 template class elf::ELFFileBase<ELF32LE>;
 template class elf::ELFFileBase<ELF32BE>;
 template class elf::ELFFileBase<ELF64LE>;
 template class elf::ELFFileBase<ELF64BE>;
 
 template class elf::ObjectFile<ELF32LE>;
 template class elf::ObjectFile<ELF32BE>;
 template class elf::ObjectFile<ELF64LE>;
 template class elf::ObjectFile<ELF64BE>;
 
 template class elf::SharedFile<ELF32LE>;
 template class elf::SharedFile<ELF32BE>;
 template class elf::SharedFile<ELF64LE>;
 template class elf::SharedFile<ELF64BE>;
+
+template std::unique_ptr<InputFile> BinaryFile::createELF<ELF32LE>();
+template std::unique_ptr<InputFile> BinaryFile::createELF<ELF32BE>();
+template std::unique_ptr<InputFile> BinaryFile::createELF<ELF64LE>();
+template std::unique_ptr<InputFile> BinaryFile::createELF<ELF64BE>();
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index 5978baf..b8e0911 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -1,307 +1,320 @@
 //===- InputFiles.h ---------------------------------------------*- C++ -*-===//
 //
 //                             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 "Config.h"
 #include "InputSection.h"
 #include "Error.h"
 #include "Symbols.h"
 
 #include "lld/Core/LLVM.h"
 #include "lld/Core/Reproduce.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/IR/Comdat.h"
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/ELF.h"
 #include "llvm/Object/IRObjectFile.h"
 #include "llvm/Support/StringSaver.h"
 
 #include <map>
 
 namespace lld {
 namespace elf {
 
 using llvm::object::Archive;
 
 class InputFile;
 class Lazy;
 class SymbolBody;
 
 // The root class of input files.
 class InputFile {
 public:
   enum Kind {
     ObjectKind,
     SharedKind,
     LazyObjectKind,
     ArchiveKind,
     BitcodeKind,
+    BinaryKind,
   };
 
   Kind kind() const { return FileKind; }
 
   StringRef getName() const { return MB.getBufferIdentifier(); }
   MemoryBufferRef MB;
 
   // Filename of .a which contained this file. If this file was
   // not in an archive file, it is the empty string. We use this
   // string for creating error messages.
   StringRef ArchiveName;
 
   // If this is an architecture-specific file, the following members
   // have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type.
   ELFKind EKind = ELFNoneKind;
   uint16_t EMachine = llvm::ELF::EM_NONE;
 
 protected:
   InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
 
 private:
   const Kind FileKind;
 };
 
 // Returns "(internal)", "foo.a(bar.o)" or "baz.o".
 std::string getFilename(const InputFile *F);
 
 template <typename ELFT> class ELFFileBase : public InputFile {
 public:
   typedef typename ELFT::Shdr Elf_Shdr;
   typedef typename ELFT::Sym Elf_Sym;
   typedef typename ELFT::Word Elf_Word;
   typedef typename ELFT::SymRange Elf_Sym_Range;
 
   ELFFileBase(Kind K, MemoryBufferRef M);
   static bool classof(const InputFile *F) {
     Kind K = F->kind();
     return K == ObjectKind || K == SharedKind;
   }
 
   const llvm::object::ELFFile<ELFT> &getObj() const { return ELFObj; }
   llvm::object::ELFFile<ELFT> &getObj() { return ELFObj; }
 
   uint8_t getOSABI() const {
     return getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI];
   }
 
   StringRef getStringTable() const { return StringTable; }
 
   uint32_t getSectionIndex(const Elf_Sym &Sym) const;
 
   Elf_Sym_Range getElfSymbols(bool OnlyGlobals);
 
 protected:
   llvm::object::ELFFile<ELFT> ELFObj;
   const Elf_Shdr *Symtab = nullptr;
   ArrayRef<Elf_Word> SymtabSHNDX;
   StringRef StringTable;
   void initStringTable();
 };
 
 // .o file.
 template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> {
   typedef ELFFileBase<ELFT> Base;
   typedef typename ELFT::Sym Elf_Sym;
   typedef typename ELFT::Shdr Elf_Shdr;
   typedef typename ELFT::SymRange Elf_Sym_Range;
   typedef typename ELFT::Word Elf_Word;
   typedef typename ELFT::uint uintX_t;
 
   StringRef getShtGroupSignature(const Elf_Shdr &Sec);
   ArrayRef<Elf_Word> getShtGroupEntries(const Elf_Shdr &Sec);
 
 public:
   static bool classof(const InputFile *F) {
     return F->kind() == Base::ObjectKind;
   }
 
   ArrayRef<SymbolBody *> getSymbols();
   ArrayRef<SymbolBody *> getLocalSymbols();
   ArrayRef<SymbolBody *> getNonLocalSymbols();
 
   explicit ObjectFile(MemoryBufferRef M);
   void parse(llvm::DenseSet<StringRef> &ComdatGroups);
 
   ArrayRef<InputSectionBase<ELFT> *> getSections() const { return Sections; }
   InputSectionBase<ELFT> *getSection(const Elf_Sym &Sym) const;
 
   SymbolBody &getSymbolBody(uint32_t SymbolIndex) const {
     return *SymbolBodies[SymbolIndex];
   }
 
   template <typename RelT> SymbolBody &getRelocTargetSym(const RelT &Rel) const {
     uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL);
     return getSymbolBody(SymIndex);
   }
 
   const Elf_Shdr *getSymbolTable() const { return this->Symtab; };
 
   // Get MIPS GP0 value defined by this file. This value represents the gp value
   // used to create the relocatable object and required to support
   // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
   uint32_t getMipsGp0() const;
 
   // The number is the offset in the string table. It will be used as the
   // st_name of the symbol.
   std::vector<std::pair<const DefinedRegular<ELFT> *, unsigned>> KeptLocalSyms;
 
   // SymbolBodies and Thunks for sections in this file are allocated
   // using this buffer.
   llvm::BumpPtrAllocator Alloc;
 
 private:
   void initializeSections(llvm::DenseSet<StringRef> &ComdatGroups);
   void initializeSymbols();
   InputSectionBase<ELFT> *getRelocTarget(const Elf_Shdr &Sec);
   InputSectionBase<ELFT> *createInputSection(const Elf_Shdr &Sec);
 
   bool shouldMerge(const Elf_Shdr &Sec);
   SymbolBody *createSymbolBody(const Elf_Sym *Sym);
 
   // List of all sections defined by this file.
   std::vector<InputSectionBase<ELFT> *> Sections;
 
   // List of all symbols referenced or defined by this file.
   std::vector<SymbolBody *> SymbolBodies;
 
   // MIPS .reginfo section defined by this file.
   std::unique_ptr<MipsReginfoInputSection<ELFT>> MipsReginfo;
   // MIPS .MIPS.options section defined by this file.
   std::unique_ptr<MipsOptionsInputSection<ELFT>> MipsOptions;
   // MIPS .MIPS.abiflags section defined by this file.
   std::unique_ptr<MipsAbiFlagsInputSection<ELFT>> MipsAbiFlags;
 
   llvm::SpecificBumpPtrAllocator<InputSection<ELFT>> IAlloc;
   llvm::SpecificBumpPtrAllocator<MergeInputSection<ELFT>> MAlloc;
   llvm::SpecificBumpPtrAllocator<EhInputSection<ELFT>> EHAlloc;
 };
 
 // LazyObjectFile is analogous to ArchiveFile in the sense that
 // the file contains lazy symbols. The difference is that
 // LazyObjectFile wraps a single file instead of multiple files.
 //
 // This class is used for --start-lib and --end-lib options which
 // instruct the linker to link object files between them with the
 // archive file semantics.
 class LazyObjectFile : public InputFile {
 public:
   explicit LazyObjectFile(MemoryBufferRef M) : InputFile(LazyObjectKind, M) {}
 
   static bool classof(const InputFile *F) {
     return F->kind() == LazyObjectKind;
   }
 
   template <class ELFT> void parse();
   MemoryBufferRef getBuffer();
 
 private:
   std::vector<StringRef> getSymbols();
   template <class ELFT> std::vector<StringRef> getElfSymbols();
   std::vector<StringRef> getBitcodeSymbols();
 
   llvm::BumpPtrAllocator Alloc;
   llvm::StringSaver Saver{Alloc};
   bool Seen = false;
 };
 
 // An ArchiveFile object represents a .a file.
 class ArchiveFile : public InputFile {
 public:
   explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
   static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
   template <class ELFT> void parse();
 
   // 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.)
   MemoryBufferRef getMember(const Archive::Symbol *Sym);
 
 private:
   std::unique_ptr<Archive> File;
   llvm::DenseSet<uint64_t> Seen;
 };
 
 class BitcodeFile : public InputFile {
 public:
   explicit BitcodeFile(MemoryBufferRef M);
   static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; }
   template <class ELFT>
   void parse(llvm::DenseSet<StringRef> &ComdatGroups);
   ArrayRef<Symbol *> getSymbols() { return Symbols; }
   static bool shouldSkip(uint32_t Flags);
   std::unique_ptr<llvm::object::IRObjectFile> Obj;
 
 private:
   std::vector<Symbol *> Symbols;
   llvm::BumpPtrAllocator Alloc;
   llvm::StringSaver Saver{Alloc};
   template <class ELFT>
   Symbol *createSymbol(const llvm::DenseSet<const llvm::Comdat *> &KeptComdats,
                        const llvm::object::IRObjectFile &Obj,
                        const llvm::object::BasicSymbolRef &Sym);
 };
 
 // .so file.
 template <class ELFT> class SharedFile : public ELFFileBase<ELFT> {
   typedef ELFFileBase<ELFT> Base;
   typedef typename ELFT::Shdr Elf_Shdr;
   typedef typename ELFT::Sym Elf_Sym;
   typedef typename ELFT::Word Elf_Word;
   typedef typename ELFT::SymRange Elf_Sym_Range;
   typedef typename ELFT::Versym Elf_Versym;
   typedef typename ELFT::Verdef Elf_Verdef;
 
   std::vector<StringRef> Undefs;
   StringRef SoName;
   const Elf_Shdr *VersymSec = nullptr;
   const Elf_Shdr *VerdefSec = nullptr;
 
 public:
   StringRef getSoName() const { return SoName; }
   const Elf_Shdr *getSection(const Elf_Sym &Sym) const;
   llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; }
 
   static bool classof(const InputFile *F) {
     return F->kind() == Base::SharedKind;
   }
 
   explicit SharedFile(MemoryBufferRef M);
 
   void parseSoName();
   void parseRest();
   std::vector<const Elf_Verdef *> parseVerdefs(const Elf_Versym *&Versym);
 
   struct NeededVer {
     // The string table offset of the version name in the output file.
     size_t StrTab;
 
     // The version identifier for this version name.
     uint16_t Index;
   };
 
   // Mapping from Elf_Verdef data structures to information about Elf_Vernaux
   // data structures in the output file.
   std::map<const Elf_Verdef *, NeededVer> VerdefMap;
 
   // Used for --as-needed
   bool AsNeeded = false;
   bool IsUsed = false;
   bool isNeeded() const { return !AsNeeded || IsUsed; }
 };
 
+class BinaryFile : public InputFile {
+public:
+  explicit BinaryFile(MemoryBufferRef M) : InputFile(BinaryKind, M) {}
+
+  static bool classof(const InputFile *F) { return F->kind() == BinaryKind; }
+
+  template <class ELFT> std::unique_ptr<InputFile> createELF();
+
+private:
+  std::unique_ptr<char[]> ELFData;
+};
+
 std::unique_ptr<InputFile> createObjectFile(MemoryBufferRef MB,
                                             StringRef ArchiveName = "");
 std::unique_ptr<InputFile> createSharedFile(MemoryBufferRef MB);
 
 } // namespace elf
 } // namespace lld
 
 #endif
diff --git a/ELF/Options.td b/ELF/Options.td
index fdc1874..85fd1f2 100644
--- a/ELF/Options.td
+++ b/ELF/Options.td
@@ -1,296 +1,300 @@
 include "llvm/Option/OptParser.td"
 
 // For options whose names are multiple letters, either one dash or
 // two can precede the option name except those that start with 'o'.
 class F<string name>: Flag<["--", "-"], name>;
 class J<string name>: Joined<["--", "-"], name>;
 class S<string name>: Separate<["--", "-"], name>;
 class JS<string name>: JoinedOrSeparate<["--", "-"], name>;
 
 def auxiliary: S<"auxiliary">, HelpText<"Set DT_AUXILIARY field to the specified name">;
 
 def Bsymbolic: F<"Bsymbolic">, HelpText<"Bind defined symbols locally">;
 
 def Bsymbolic_functions: F<"Bsymbolic-functions">,
   HelpText<"Bind defined function symbols locally">;
 
 def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries">;
 
 def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">;
 
 def build_id: F<"build-id">, HelpText<"Generate build ID note">;
 
 def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">;
 
 def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
   HelpText<"Add a directory to the library search path">;
 
 def O: Joined<["-"], "O">, HelpText<"Optimize output file size">;
 
 def allow_multiple_definition: F<"allow-multiple-definition">,
   HelpText<"Allow multiple definitions">;
 
 def as_needed: F<"as-needed">,
   HelpText<"Only set DT_NEEDED for shared libraries if used">;
 
 def disable_new_dtags: F<"disable-new-dtags">,
   HelpText<"Disable new dynamic tags">;
 
 def discard_all: F<"discard-all">, HelpText<"Delete all local symbols">;
 
 def discard_locals: F<"discard-locals">,
   HelpText<"Delete temporary local symbols">;
 
 def discard_none: F<"discard-none">,
   HelpText<"Keep all symbols in the symbol table">;
 
 def dynamic_linker: S<"dynamic-linker">,
   HelpText<"Which dynamic linker to use">;
 
 def dynamic_list: S<"dynamic-list">,
   HelpText<"Read a list of dynamic symbols">;
 
 def eh_frame_hdr: F<"eh-frame-hdr">,
   HelpText<"Request creation of .eh_frame_hdr section and PT_GNU_EH_FRAME segment header">;
 
 def enable_new_dtags: F<"enable-new-dtags">,
   HelpText<"Enable new dynamic tags">;
 
 def end_lib: F<"end-lib">,
   HelpText<"End a grouping of objects that should be treated as if they were together in an archive">;
 
 def entry: S<"entry">, MetaVarName<"<entry>">,
   HelpText<"Name of entry point symbol">;
 
 def export_dynamic: F<"export-dynamic">,
   HelpText<"Put symbols in the dynamic symbol table">;
 
 def export_dynamic_symbol: S<"export-dynamic-symbol">,
   HelpText<"Put a symbol in the dynamic symbol table">;
 
 def fatal_warnings: F<"fatal-warnings">,
   HelpText<"Treat warnings as errors">;
 
 def fini: S<"fini">, MetaVarName<"<symbol>">,
   HelpText<"Specify a finalizer function">;
 
 def gc_sections: F<"gc-sections">,
   HelpText<"Enable garbage collection of unused sections">;
 
+def format: J<"format=">, MetaVarName<"<input-format>">,
+  HelpText<"Change the input format of the inputs following this option">;
+
 def hash_style: S<"hash-style">,
   HelpText<"Specify hash style (sysv, gnu or both)">;
 
 def help: F<"help">, HelpText<"Print option help">;
 
 def icf: F<"icf=all">, HelpText<"Enable identical code folding">;
 
 def image_base : J<"image-base=">, HelpText<"Set the base address">;
 
 def init: S<"init">, MetaVarName<"<symbol>">,
   HelpText<"Specify an initializer function">;
 
 def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">,
   HelpText<"Root name of library to use">;
 
 def lto_O: J<"lto-O">, MetaVarName<"<opt-level>">,
   HelpText<"Optimization level for LTO">;
 
 def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">;
 
 def nostdlib: F<"nostdlib">,
   HelpText<"Only search directories specified on the command line">;
 
 def no_as_needed: F<"no-as-needed">,
   HelpText<"Always DT_NEEDED for shared libraries">;
 
 def no_demangle: F<"no-demangle">,
   HelpText<"Do not demangle symbol names">;
 
 def no_gc_sections: F<"no-gc-sections">,
   HelpText<"Disable garbage collection of unused sections">;
 
 def no_gnu_unique: F<"no-gnu-unique">,
   HelpText<"Disable STB_GNU_UNIQUE symbol binding">;
 
 def no_whole_archive: F<"no-whole-archive">,
   HelpText<"Restores the default behavior of loading archive members">;
 
 def noinhibit_exec: F<"noinhibit-exec">,
   HelpText<"Retain the executable output file whenever it is still usable">;
 
 def no_undefined: F<"no-undefined">,
   HelpText<"Report unresolved symbols even if the linker is creating a shared library">;
 
 def no_undefined_version: F<"no-undefined-version">,
   HelpText<"Report version scripts that refer undefined symbols">;
 
 def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">,
   HelpText<"Path to file to write output">;
 
 def oformat: Separate<["--"], "oformat">, MetaVarName<"<format>">,
   HelpText<"Specify the binary format for the output object file">;
 
 def pie: F<"pie">, HelpText<"Create a position independent executable">;
 
 def print_gc_sections: F<"print-gc-sections">,
   HelpText<"List removed unused sections">;
 
 def reproduce: S<"reproduce">,
   HelpText<"Dump linker invocation and input files for debugging">;
 
 def rpath: S<"rpath">, HelpText<"Add a DT_RUNPATH to the output">;
 
 def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">;
 
 def script: S<"script">, HelpText<"Read linker script">;
 
 def shared: F<"shared">, HelpText<"Build a shared object">;
 
 def soname: J<"soname=">, HelpText<"Set DT_SONAME">;
 
 def start_lib: F<"start-lib">,
   HelpText<"Start a grouping of objects that should be treated as if they were together in an archive">;
 
 def strip_all: F<"strip-all">, HelpText<"Strip all symbols">;
 
 def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">;
 
 def sysroot: J<"sysroot=">, HelpText<"Set the system root">;
 
 def target1_rel: F<"target1-rel">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_REL32">;
 
 def target1_abs: F<"target1-abs">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_ABS32">;
 
 def threads: F<"threads">, HelpText<"Enable use of threads">;
 
 def trace: F<"trace">, HelpText<"Print the names of the input files">;
 
 def trace_symbol : J<"trace-symbol=">, HelpText<"Trace references to symbols">;
 
 def undefined: J<"undefined=">,
   HelpText<"Force undefined symbol during linking">;
 
 def unresolved_symbols: J<"unresolved-symbols=">,
   HelpText<"Determine how to handle unresolved symbols">;
 
 def rsp_quoting: J<"rsp-quoting=">,
   HelpText<"Quoting style for response files. Values supported: windows|posix">;
 
 def verbose: F<"verbose">, HelpText<"Verbose mode">;
 
 def version: F<"version">, HelpText<"Display the version number">;
 
 def version_script: S<"version-script">,
   HelpText<"Read a version script">;
 
 def warn_common: F<"warn-common">,
   HelpText<"Warn about duplicate common symbols">;
 
 def whole_archive: F<"whole-archive">,
   HelpText<"Force load of all members in a static library">;
 
 def wrap: S<"wrap">, MetaVarName<"<symbol>">,
   HelpText<"Use wrapper functions for symbol">;
 
 def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,
   HelpText<"Linker option extensions">;
 
 // Aliases
 def alias_auxiliary: Separate<["-"], "f">, Alias<auxiliary>;
 def alias_Bdynamic_call_shared: F<"call_shared">, Alias<Bdynamic>;
 def alias_Bdynamic_dy: F<"dy">, Alias<Bdynamic>;
 def alias_Bstatic_dn: F<"dn">, Alias<Bstatic>;
 def alias_Bstatic_non_shared: F<"non_shared">, Alias<Bstatic>;
 def alias_Bstatic_static: F<"static">, Alias<Bstatic>;
 def alias_L__library_path: J<"library-path=">, Alias<L>;
 def alias_discard_all_x: Flag<["-"], "x">, Alias<discard_all>;
 def alias_discard_locals_X: Flag<["-"], "X">, Alias<discard_locals>;
 def alias_dynamic_list: J<"dynamic-list=">, Alias<dynamic_list>;
 def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>;
 def alias_entry_entry: J<"entry=">, Alias<entry>;
 def alias_export_dynamic_E: Flag<["-"], "E">, Alias<export_dynamic>;
 def alias_export_dynamic_symbol: J<"export-dynamic-symbol=">,
   Alias<export_dynamic_symbol>;
 def alias_fini_fini: J<"fini=">, Alias<fini>;
+def alias_format_b: S<"b">, Alias<format>;
 def alias_hash_style_hash_style: J<"hash-style=">, Alias<hash_style>;
 def alias_init_init: J<"init=">, Alias<init>;
 def alias_l__library: J<"library=">, Alias<l>;
 def alias_o_output: J<"output=">, Alias<o>;
 def alias_o_output2 : S<"output">, Alias<o>;
 def alias_pie_pic_executable: F<"pic-executable">, Alias<pie>;
 def alias_relocatable_r: Flag<["-"], "r">, Alias<relocatable>;
 def alias_rpath_R: Joined<["-"], "R">, Alias<rpath>;
 def alias_rpath_rpath: J<"rpath=">, Alias<rpath>;
 def alias_script_T: JoinedOrSeparate<["-"], "T">, Alias<script>;
 def alias_shared_Bshareable: F<"Bshareable">, Alias<shared>;
 def alias_soname_h: JoinedOrSeparate<["-"], "h">, Alias<soname>;
 def alias_soname_soname: S<"soname">, Alias<soname>;
 def alias_strip_all: Flag<["-"], "s">, Alias<strip_all>;
 def alias_strip_debug_S: Flag<["-"], "S">, Alias<strip_debug>;
 def alias_trace: Flag<["-"], "t">, Alias<trace>;
 def alias_trace_symbol_y : JoinedOrSeparate<["-"], "y">, Alias<trace_symbol>;
 def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>;
 def alias_version_V: Flag<["-"], "V">, Alias<version>;
 def alias_version_v: Flag<["-"], "v">, Alias<version>;
 def alias_wrap_wrap: J<"wrap=">, Alias<wrap>;
 
 // Our symbol resolution algorithm handles symbols in archive files differently
 // than traditional linkers, so we don't need --start-group and --end-group.
 // These options are recongized for compatibility but ignored.
 def end_group: F<"end-group">;
 def end_group_paren: Flag<["-"], ")">;
 def start_group: F<"start-group">;
 def start_group_paren: Flag<["-"], "(">;
 
 // Ignore LTO plugin-related options.
 // clang -flto passes -plugin and -plugin-opt to the linker. This is required
 // for ld.gold and ld.bfd to get LTO working. But it's not for lld which doesn't
 // rely on a plugin. Instead of detecting which linker is used on clang side we
 // just ignore the option on lld side as it's easier. In fact, the linker could
 // be called 'ld' and understanding which linker is used would require parsing of
 // --version output.
 def plugin: S<"plugin">;
 def plugin_eq: J<"plugin=">;
 def plugin_opt: S<"plugin-opt">;
 def plugin_opt_eq: J<"plugin-opt=">;
 
 // Options listed below are silently ignored for now for compatibility.
 def allow_shlib_undefined: F<"allow-shlib-undefined">;
 def define_common: F<"define-common">;
 def demangle: F<"demangle">;
 def detect_odr_violations: F<"detect-odr-violations">;
 def g: Flag<["-"], "g">;
 def no_add_needed: F<"no-add-needed">;
 def no_allow_shlib_undefined: F<"no-allow-shlib-undefined">;
 def no_copy_dt_needed_entries: F<"no-copy-dt-needed-entries">,
   Alias<no_add_needed>;
 def no_dynamic_linker: F<"no-dynamic-linker">;
 def no_fatal_warnings: F<"no-fatal-warnings">;
 def no_mmap_output_file: F<"no-mmap-output-file">;
 def no_warn_common: F<"no-warn-common">;
 def no_warn_mismatch: F<"no-warn-mismatch">;
 def rpath_link: S<"rpath-link">;
 def rpath_link_eq: J<"rpath-link=">;
 def sort_common: F<"sort-common">;
 def warn_execstack: F<"warn-execstack">;
 def warn_shared_textrel: F<"warn-shared-textrel">;
 def EB : F<"EB">;
 def EL : F<"EL">;
 def G: JoinedOrSeparate<["-"], "G">;
 
 // Aliases for ignored options
 def alias_define_common_d: Flag<["-"], "d">, Alias<define_common>;
 def alias_define_common_dc: F<"dc">, Alias<define_common>;
 def alias_define_common_dp: F<"dp">, Alias<define_common>;
 def alias_version_script_version_script: J<"version-script=">,
   Alias<version_script>;
 
 // LTO-related options.
 def lto_jobs: J<"lto-jobs=">, HelpText<"Number of threads to run codegen">;
 def lto_aa_pipeline: J<"lto-aa-pipeline=">,
   HelpText<"AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes">;
 def lto_newpm_passes: J<"lto-newpm-passes=">,
   HelpText<"Passes to run during LTO">;
 def disable_verify: F<"disable-verify">;
 def mllvm: S<"mllvm">;
 def save_temps: F<"save-temps">;
diff --git a/ELF/SimpleELFWriter.h b/ELF/SimpleELFWriter.h
new file mode 100644
index 0000000..b2ebb8f
--- /dev/null
+++ b/ELF/SimpleELFWriter.h
@@ -0,0 +1,150 @@
+//===- SimpleELFWriter.h ----------------------------------------*- C++ -*-===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_SIMPLE_ELF_WRITER_H
+#define LLD_ELF_SIMPLE_ELF_WRITER_H
+
+#include "lld/Core/LLVM.h"
+
+#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Object/ELFTypes.h"
+
+using namespace llvm;
+using namespace llvm::ELF;
+
+namespace lld {
+namespace elf {
+
+template <class ELFT> class SimpleELFWriter {
+  typedef typename ELFT::uint uintX_t;
+  typedef typename ELFT::Ehdr Elf_Ehdr;
+  typedef typename ELFT::Shdr Elf_Shdr;
+  typedef typename ELFT::Sym Elf_Sym;
+
+public:
+  SimpleELFWriter(std::uint16_t Type, std::uint16_t Machine) {
+    memcpy(Header.e_ident, "\177ELF", 4);
+    Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
+    Header.e_ident[EI_DATA] = ELFT::TargetEndianness == llvm::support::little
+                                  ? ELFDATA2LSB
+                                  : ELFDATA2MSB;
+    Header.e_ident[EI_VERSION] = EV_CURRENT;
+    Header.e_ident[EI_OSABI] = 0;
+    Header.e_type = Type;
+    Header.e_machine = Machine;
+    Header.e_version = EV_CURRENT;
+    Header.e_entry = 0;
+    Header.e_phoff = 0;
+    Header.e_flags = 0;
+    Header.e_ehsize = sizeof(Elf_Ehdr);
+    Header.e_phnum = 0;
+    Header.e_shentsize = sizeof(Elf_Shdr);
+    Header.e_shstrndx = 1;
+
+    ShStrTab = addSection(".shstrtab").Header;
+    ShStrTab->sh_type = SHT_STRTAB;
+    ShStrTab->sh_addralign = 1;
+
+    StrTab = addSection(".strtab").Header;
+    StrTab->sh_type = SHT_STRTAB;
+    StrTab->sh_addralign = 1;
+
+    SymTab = addSection(".symtab").Header;
+    SymTab->sh_type = SHT_SYMTAB;
+    SymTab->sh_link = 2;
+    SymTab->sh_info = 1;
+    SymTab->sh_addralign = sizeof(uintX_t);
+    SymTab->sh_entsize = sizeof(Elf_Sym);
+  }
+
+  struct Section {
+    Elf_Shdr *Header;
+    std::size_t Index;
+  };
+
+  struct Symbol {
+    Elf_Sym *Sym;
+    std::size_t Index;
+  };
+
+  Section addSection(StringRef Name) {
+    std::size_t NameOff = SecHdrStrTabBuilder.add(Name);
+    auto Shdr = new (Alloc) Elf_Shdr{};
+    Shdr->sh_name = NameOff;
+    Sections.push_back(Shdr);
+    return {Shdr, Sections.size()};
+  }
+
+  Symbol addSymbol(StringRef Name) {
+    std::size_t NameOff = StrTabBuilder.add(Name);
+    auto Sym = new (Alloc) Elf_Sym{};
+    Sym->st_name = NameOff;
+    StaticSymbols.push_back(Sym);
+    return {Sym, StaticSymbols.size()};
+  }
+
+  std::size_t layout() {
+    SecHdrStrTabBuilder.finalizeInOrder();
+    ShStrTab->sh_size = SecHdrStrTabBuilder.getSize();
+
+    StrTabBuilder.finalizeInOrder();
+    StrTab->sh_size = StrTabBuilder.getSize();
+
+    SymTab->sh_size = (StaticSymbols.size() + 1) * sizeof(Elf_Sym);
+
+    uintX_t Offset = sizeof(Elf_Ehdr);
+    for (Elf_Shdr *Sec : Sections) {
+      Offset = alignTo(Offset, Sec->sh_addralign);
+      Sec->sh_offset = Offset;
+      Offset += Sec->sh_size;
+    }
+
+    Offset = alignTo(Offset, sizeof(uintX_t));
+    Header.e_shoff = Offset;
+    Offset += (Sections.size() + 1) * sizeof(Elf_Shdr);
+    Header.e_shnum = Sections.size() + 1;
+
+    return Offset;
+  }
+
+  void write(char *Out) {
+    std::memcpy(Out, &Header, sizeof(Elf_Ehdr));
+    std::copy(SecHdrStrTabBuilder.data().begin(),
+              SecHdrStrTabBuilder.data().end(), Out + ShStrTab->sh_offset);
+    std::copy(StrTabBuilder.data().begin(), StrTabBuilder.data().end(),
+              Out + StrTab->sh_offset);
+
+    Elf_Sym *Sym = reinterpret_cast<Elf_Sym *>(Out + SymTab->sh_offset);
+    // Skip null.
+    ++Sym;
+    for (Elf_Sym *S : StaticSymbols)
+      *Sym++ = *S;
+
+    Elf_Shdr *Shdr = reinterpret_cast<Elf_Shdr *>(Out + Header.e_shoff);
+    // Skip null.
+    ++Shdr;
+    for (Elf_Shdr *S : Sections)
+      *Shdr++ = *S;
+  }
+
+private:
+  Elf_Ehdr Header;
+  std::vector<Elf_Shdr *> Sections;
+  std::vector<Elf_Sym *> StaticSymbols;
+  llvm::StringTableBuilder SecHdrStrTabBuilder{llvm::StringTableBuilder::ELF};
+  llvm::StringTableBuilder StrTabBuilder{llvm::StringTableBuilder::ELF};
+  llvm::BumpPtrAllocator Alloc;
+  Elf_Shdr *ShStrTab;
+  Elf_Shdr *StrTab;
+  Elf_Shdr *SymTab;
+};
+}
+}
+
+#endif
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index 152881d..eff5851 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -1,703 +1,709 @@
 //===- SymbolTable.cpp ----------------------------------------------------===//
 //
 //                             The LLVM Linker
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
 // Symbol table is a bag of all known symbols. We put all symbols of
 // all input files to the symbol table. The symbol table is basically
 // a hash table with the logic to resolve symbol name conflicts using
 // the symbol types.
 //
 //===----------------------------------------------------------------------===//
 
 #include "SymbolTable.h"
 #include "Config.h"
 #include "Error.h"
 #include "LinkerScript.h"
 #include "Strings.h"
 #include "SymbolListFile.h"
 #include "Symbols.h"
 #include "llvm/Bitcode/ReaderWriter.h"
 #include "llvm/Support/StringSaver.h"
 
 using namespace llvm;
 using namespace llvm::object;
 using namespace llvm::ELF;
 
 using namespace lld;
 using namespace lld::elf;
 
 // All input object files must be for the same architecture
 // (e.g. it does not make sense to link x86 object files with
 // MIPS object files.) This function checks for that error.
 template <class ELFT> static bool isCompatible(InputFile *F) {
   if (!isa<ELFFileBase<ELFT>>(F) && !isa<BitcodeFile>(F))
     return true;
   if (F->EKind == Config->EKind && F->EMachine == Config->EMachine)
     return true;
   StringRef A = F->getName();
   StringRef B = Config->Emulation;
   if (B.empty())
     B = Config->FirstElf->getName();
   error(A + " is incompatible with " + B);
   return false;
 }
 
 // Add symbols in File to the symbol table.
 template <class ELFT>
 void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
   InputFile *FileP = File.get();
   if (!isCompatible<ELFT>(FileP))
     return;
 
+  // Binary file
+  if (auto *F = dyn_cast<BinaryFile>(FileP)) {
+    addFile(F->createELF<ELFT>());
+    return;
+  }
+
   // .a file
   if (auto *F = dyn_cast<ArchiveFile>(FileP)) {
     ArchiveFiles.emplace_back(cast<ArchiveFile>(File.release()));
     F->parse<ELFT>();
     return;
   }
 
   // Lazy object file
   if (auto *F = dyn_cast<LazyObjectFile>(FileP)) {
     LazyObjectFiles.emplace_back(cast<LazyObjectFile>(File.release()));
     F->parse<ELFT>();
     return;
   }
 
   if (Config->Trace)
     outs() << getFilename(FileP) << "\n";
 
   // .so file
   if (auto *F = dyn_cast<SharedFile<ELFT>>(FileP)) {
     // DSOs are uniquified not by filename but by soname.
     F->parseSoName();
     if (!SoNames.insert(F->getSoName()).second)
       return;
 
     SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release()));
     F->parseRest();
     return;
   }
 
   // LLVM bitcode file
   if (auto *F = dyn_cast<BitcodeFile>(FileP)) {
     BitcodeFiles.emplace_back(cast<BitcodeFile>(File.release()));
     F->parse<ELFT>(ComdatGroups);
     return;
   }
 
   // Regular object file
   auto *F = cast<ObjectFile<ELFT>>(FileP);
   ObjectFiles.emplace_back(cast<ObjectFile<ELFT>>(File.release()));
   F->parse(ComdatGroups);
 }
 
 // This function is where all the optimizations of link-time
 // optimization happens. When LTO is in use, some input files are
 // not in native object file format but in the LLVM bitcode format.
 // This function compiles bitcode files into a few big native files
 // using LLVM functions and replaces bitcode symbols with the results.
 // Because all bitcode files that consist of a program are passed
 // to the compiler at once, it can do whole-program optimization.
 template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() {
   if (BitcodeFiles.empty())
     return;
 
   // Compile bitcode files.
   Lto.reset(new BitcodeCompiler);
   for (const std::unique_ptr<BitcodeFile> &F : BitcodeFiles)
     Lto->add(*F);
   std::vector<std::unique_ptr<InputFile>> IFs = Lto->compile();
 
   // Replace bitcode symbols.
   for (auto &IF : IFs) {
     ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(IF.release());
 
     DenseSet<StringRef> DummyGroups;
     Obj->parse(DummyGroups);
     ObjectFiles.emplace_back(Obj);
   }
 }
 
 template <class ELFT>
 DefinedRegular<ELFT> *SymbolTable<ELFT>::addAbsolute(StringRef Name,
                                                      uint8_t Visibility) {
   return cast<DefinedRegular<ELFT>>(
       addRegular(Name, STB_GLOBAL, Visibility)->body());
 }
 
 // Add Name as an "ignored" symbol. An ignored symbol is a regular
 // linker-synthesized defined symbol, but is only defined if needed.
 template <class ELFT>
 DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name,
                                                     uint8_t Visibility) {
   if (!find(Name))
     return nullptr;
   return addAbsolute(Name, Visibility);
 }
 
 // Set a flag for --trace-symbol so that we can print out a log message
 // if a new symbol with the same name is inserted into the symbol table.
 template <class ELFT> void SymbolTable<ELFT>::trace(StringRef Name) {
   Symtab.insert({Name, {-1, true}});
 }
 
 // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM.
 // Used to implement --wrap.
 template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) {
   SymbolBody *B = find(Name);
   if (!B)
     return;
   StringSaver Saver(Alloc);
   Symbol *Sym = B->symbol();
   Symbol *Real = addUndefined(Saver.save("__real_" + Name));
   Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name));
   // We rename symbols by replacing the old symbol's SymbolBody with the new
   // symbol's SymbolBody. This causes all SymbolBody pointers referring to the
   // old symbol to instead refer to the new symbol.
   memcpy(Real->Body.buffer, Sym->Body.buffer, sizeof(Sym->Body));
   memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body));
 }
 
 static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
   if (VA == STV_DEFAULT)
     return VB;
   if (VB == STV_DEFAULT)
     return VA;
   return std::min(VA, VB);
 }
 
 // Parses a symbol in the form of <name>@<version> or <name>@@<version>.
 static std::pair<StringRef, uint16_t> getSymbolVersion(StringRef S) {
   if (Config->VersionDefinitions.empty())
     return {S, Config->DefaultSymbolVersion};
 
   size_t Pos = S.find('@');
   if (Pos == 0 || Pos == StringRef::npos)
     return {S, Config->DefaultSymbolVersion};
 
   StringRef Name = S.substr(0, Pos);
   StringRef Verstr = S.substr(Pos + 1);
   if (Verstr.empty())
     return {S, Config->DefaultSymbolVersion};
 
   // '@@' in a symbol name means the default version.
   // It is usually the most recent one.
   bool IsDefault = (Verstr[0] == '@');
   if (IsDefault)
     Verstr = Verstr.substr(1);
 
   for (VersionDefinition &V : Config->VersionDefinitions) {
     if (V.Name == Verstr)
       return {Name, IsDefault ? V.Id : (V.Id | VERSYM_HIDDEN)};
   }
 
   // It is an error if the specified version was not defined.
   error("symbol " + S + " has undefined version " + Verstr);
   return {S, Config->DefaultSymbolVersion};
 }
 
 // Find an existing symbol or create and insert a new one.
 template <class ELFT>
 std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef &Name) {
   auto P = Symtab.insert({Name, SymIndex((int)SymVector.size(), false)});
   SymIndex &V = P.first->second;
   bool IsNew = P.second;
 
   if (V.Idx == -1) {
     IsNew = true;
     V = SymIndex((int)SymVector.size(), true);
   }
 
   Symbol *Sym;
   if (IsNew) {
     Sym = new (Alloc) Symbol;
     Sym->Binding = STB_WEAK;
     Sym->Visibility = STV_DEFAULT;
     Sym->IsUsedInRegularObj = false;
     Sym->HasUnnamedAddr = true;
     Sym->ExportDynamic = false;
     Sym->Traced = V.Traced;
     std::tie(Name, Sym->VersionId) = getSymbolVersion(Name);
     SymVector.push_back(Sym);
   } else {
     Sym = SymVector[V.Idx];
   }
   return {Sym, IsNew};
 }
 
 // Find an existing symbol or create and insert a new one, then apply the given
 // attributes.
 template <class ELFT>
 std::pair<Symbol *, bool>
 SymbolTable<ELFT>::insert(StringRef &Name, uint8_t Type, uint8_t Visibility,
                           bool CanOmitFromDynSym, bool HasUnnamedAddr,
                           InputFile *File) {
   bool IsUsedInRegularObj = !File || File->kind() == InputFile::ObjectKind;
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) = insert(Name);
 
   // Merge in the new unnamed_addr attribute.
   S->HasUnnamedAddr &= HasUnnamedAddr;
   // Merge in the new symbol's visibility.
   S->Visibility = getMinVisibility(S->Visibility, Visibility);
   if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic))
     S->ExportDynamic = true;
   if (IsUsedInRegularObj)
     S->IsUsedInRegularObj = true;
   if (!WasInserted && S->body()->Type != SymbolBody::UnknownType &&
       ((Type == STT_TLS) != S->body()->isTls()))
     error("TLS attribute mismatch for symbol: " +
           conflictMsg(S->body(), File));
 
   return {S, WasInserted};
 }
 
 // Construct a string in the form of "Sym in File1 and File2".
 // Used to construct an error message.
 template <typename ELFT>
 std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Existing,
                                            InputFile *NewFile) {
   std::string Sym = Existing->getName();
   if (Config->Demangle)
     Sym = demangle(Sym);
   return Sym + " in " + getFilename(Existing->File) + " and " +
          getFilename(NewFile);
 }
 
 template <class ELFT> Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name) {
   return addUndefined(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0,
                       /*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false,
                       /*File*/ nullptr);
 }
 
 template <class ELFT>
 Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, uint8_t Binding,
                                         uint8_t StOther, uint8_t Type,
                                         bool CanOmitFromDynSym,
                                         bool HasUnnamedAddr, InputFile *File) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) =
       insert(Name, Type, StOther & 3, CanOmitFromDynSym, HasUnnamedAddr, File);
   if (WasInserted) {
     S->Binding = Binding;
     replaceBody<Undefined>(S, Name, StOther, Type, File);
     return S;
   }
   if (Binding != STB_WEAK) {
     if (S->body()->isShared() || S->body()->isLazy())
       S->Binding = Binding;
     if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(S->body()))
       SS->file()->IsUsed = true;
   }
   if (auto *L = dyn_cast<Lazy>(S->body())) {
     // An undefined weak will not fetch archive members, but we have to remember
     // its type. See also comment in addLazyArchive.
     if (S->isWeak())
       L->Type = Type;
     else if (auto F = L->fetch())
       addFile(std::move(F));
   }
   return S;
 }
 
 // We have a new defined symbol with the specified binding. Return 1 if the new
 // symbol should win, -1 if the new symbol should lose, or 0 if both symbols are
 // strong defined symbols.
 static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) {
   if (WasInserted)
     return 1;
   SymbolBody *Body = S->body();
   if (Body->isLazy() || Body->isUndefined() || Body->isShared())
     return 1;
   if (Binding == STB_WEAK)
     return -1;
   if (S->isWeak())
     return 1;
   return 0;
 }
 
 // We have a new non-common defined symbol with the specified binding. Return 1
 // if the new symbol should win, -1 if the new symbol should lose, or 0 if there
 // is a conflict. If the new symbol wins, also update the binding.
 static int compareDefinedNonCommon(Symbol *S, bool WasInserted,
                                    uint8_t Binding) {
   if (int Cmp = compareDefined(S, WasInserted, Binding)) {
     if (Cmp > 0)
       S->Binding = Binding;
     return Cmp;
   }
   if (isa<DefinedCommon>(S->body())) {
     // Non-common symbols take precedence over common symbols.
     if (Config->WarnCommon)
       warning("common " + S->body()->getName() + " is overridden");
     return 1;
   }
   return 0;
 }
 
 template <class ELFT>
 Symbol *SymbolTable<ELFT>::addCommon(StringRef N, uint64_t Size,
                                      uint64_t Alignment, uint8_t Binding,
                                      uint8_t StOther, uint8_t Type,
                                      bool HasUnnamedAddr, InputFile *File) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) = insert(
       N, Type, StOther & 3, /*CanOmitFromDynSym*/ false, HasUnnamedAddr, File);
   int Cmp = compareDefined(S, WasInserted, Binding);
   if (Cmp > 0) {
     S->Binding = Binding;
     replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File);
   } else if (Cmp == 0) {
     auto *C = dyn_cast<DefinedCommon>(S->body());
     if (!C) {
       // Non-common symbols take precedence over common symbols.
       if (Config->WarnCommon)
         warning("common " + S->body()->getName() + " is overridden");
       return S;
     }
 
     if (Config->WarnCommon)
       warning("multiple common of " + S->body()->getName());
 
     Alignment = C->Alignment = std::max(C->Alignment, Alignment);
     if (Size > C->Size)
       replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File);
   }
   return S;
 }
 
 template <class ELFT>
 void SymbolTable<ELFT>::reportDuplicate(SymbolBody *Existing,
                                         InputFile *NewFile) {
   std::string Msg = "duplicate symbol: " + conflictMsg(Existing, NewFile);
   if (Config->AllowMultipleDefinition)
     warning(Msg);
   else
     error(Msg);
 }
 
 template <typename ELFT>
 Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, const Elf_Sym &Sym,
                                       InputSectionBase<ELFT> *Section) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) =
       insert(Name, Sym.getType(), Sym.getVisibility(),
              /*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false,
              Section ? Section->getFile() : nullptr);
   int Cmp = compareDefinedNonCommon(S, WasInserted, Sym.getBinding());
   if (Cmp > 0)
     replaceBody<DefinedRegular<ELFT>>(S, Name, Sym, Section);
   else if (Cmp == 0)
     reportDuplicate(S->body(), Section->getFile());
   return S;
 }
 
 template <typename ELFT>
 Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t Binding,
                                       uint8_t StOther) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) =
       insert(Name, STT_NOTYPE, StOther & 3, /*CanOmitFromDynSym*/ false,
              /*HasUnnamedAddr*/ false, nullptr);
   int Cmp = compareDefinedNonCommon(S, WasInserted, Binding);
   if (Cmp > 0)
     replaceBody<DefinedRegular<ELFT>>(S, Name, StOther);
   else if (Cmp == 0)
     reportDuplicate(S->body(), nullptr);
   return S;
 }
 
 template <typename ELFT>
 Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N,
                                         OutputSectionBase<ELFT> *Section,
                                         uintX_t Value, uint8_t StOther) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) = insert(N, STT_NOTYPE, /*Visibility*/ StOther & 0x3,
                                     /*CanOmitFromDynSym*/ false,
                                     /*HasUnnamedAddr*/ false, nullptr);
   int Cmp = compareDefinedNonCommon(S, WasInserted, STB_GLOBAL);
   if (Cmp > 0)
     replaceBody<DefinedSynthetic<ELFT>>(S, N, Value, Section);
   else if (Cmp == 0)
     reportDuplicate(S->body(), nullptr);
   return S;
 }
 
 template <typename ELFT>
 void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name,
                                   const Elf_Sym &Sym,
                                   const typename ELFT::Verdef *Verdef) {
   // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT
   // as the visibility, which will leave the visibility in the symbol table
   // unchanged.
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) =
       insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true,
              /*HasUnnamedAddr*/ false, F);
   // Make sure we preempt DSO symbols with default visibility.
   if (Sym.getVisibility() == STV_DEFAULT)
     S->ExportDynamic = true;
   if (WasInserted || isa<Undefined>(S->body())) {
     replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef);
     if (!S->isWeak())
       F->IsUsed = true;
   }
 }
 
 template <class ELFT>
 Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, uint8_t Binding,
                                       uint8_t StOther, uint8_t Type,
                                       bool CanOmitFromDynSym,
                                       bool HasUnnamedAddr, BitcodeFile *F) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) =
       insert(Name, Type, StOther & 3, CanOmitFromDynSym, HasUnnamedAddr, F);
   int Cmp = compareDefinedNonCommon(S, WasInserted, Binding);
   if (Cmp > 0)
     replaceBody<DefinedRegular<ELFT>>(S, Name, StOther, Type, F);
   else if (Cmp == 0)
     reportDuplicate(S->body(), F);
   return S;
 }
 
 template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) {
   auto It = Symtab.find(Name);
   if (It == Symtab.end())
     return nullptr;
   SymIndex V = It->second;
   if (V.Idx == -1)
     return nullptr;
   return SymVector[V.Idx]->body();
 }
 
 // Returns a list of defined symbols that match with a given regex.
 template <class ELFT>
 std::vector<SymbolBody *> SymbolTable<ELFT>::findAll(const Regex &Re) {
   std::vector<SymbolBody *> Res;
   for (Symbol *Sym : SymVector) {
     SymbolBody *B = Sym->body();
     StringRef Name = B->getName();
     if (!B->isUndefined() && const_cast<Regex &>(Re).match(Name))
       Res.push_back(B);
   }
   return Res;
 }
 
 template <class ELFT>
 void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F,
                                        const object::Archive::Symbol Sym) {
   Symbol *S;
   bool WasInserted;
   StringRef Name = Sym.getName();
   std::tie(S, WasInserted) = insert(Name);
   if (WasInserted) {
     replaceBody<LazyArchive>(S, *F, Sym, SymbolBody::UnknownType);
     return;
   }
   if (!S->body()->isUndefined())
     return;
 
   // Weak undefined symbols should not fetch members from archives. If we were
   // to keep old symbol we would not know that an archive member was available
   // if a strong undefined symbol shows up afterwards in the link. If a strong
   // undefined symbol never shows up, this lazy symbol will get to the end of
   // the link and must be treated as the weak undefined one. We already marked
   // this symbol as used when we added it to the symbol table, but we also need
   // to preserve its type. FIXME: Move the Type field to Symbol.
   if (S->isWeak()) {
     replaceBody<LazyArchive>(S, *F, Sym, S->body()->Type);
     return;
   }
   MemoryBufferRef MBRef = F->getMember(&Sym);
   if (!MBRef.getBuffer().empty())
     addFile(createObjectFile(MBRef, F->getName()));
 }
 
 template <class ELFT>
 void SymbolTable<ELFT>::addLazyObject(StringRef Name, LazyObjectFile &Obj) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) = insert(Name);
   if (WasInserted) {
     replaceBody<LazyObject>(S, Name, Obj, SymbolBody::UnknownType);
     return;
   }
   if (!S->body()->isUndefined())
     return;
 
   // See comment for addLazyArchive above.
   if (S->isWeak()) {
     replaceBody<LazyObject>(S, Name, Obj, S->body()->Type);
   } else {
     MemoryBufferRef MBRef = Obj.getBuffer();
     if (!MBRef.getBuffer().empty())
       addFile(createObjectFile(MBRef));
   }
 }
 
 // Process undefined (-u) flags by loading lazy symbols named by those flags.
 template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() {
   for (StringRef S : Config->Undefined)
     if (auto *L = dyn_cast_or_null<Lazy>(find(S)))
       if (std::unique_ptr<InputFile> File = L->fetch())
         addFile(std::move(File));
 }
 
 // This function takes care of the case in which shared libraries depend on
 // the user program (not the other way, which is usual). Shared libraries
 // may have undefined symbols, expecting that the user program provides
 // the definitions for them. An example is BSD's __progname symbol.
 // We need to put such symbols to the main program's .dynsym so that
 // shared libraries can find them.
 // Except this, we ignore undefined symbols in DSOs.
 template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() {
   for (std::unique_ptr<SharedFile<ELFT>> &File : SharedFiles)
     for (StringRef U : File->getUndefinedSymbols())
       if (SymbolBody *Sym = find(U))
         if (Sym->isDefined())
           Sym->symbol()->ExportDynamic = true;
 }
 
 // This function processes --export-dynamic-symbol and --dynamic-list.
 template <class ELFT> void SymbolTable<ELFT>::scanDynamicList() {
   for (StringRef S : Config->DynamicList)
     if (SymbolBody *B = find(S))
       B->symbol()->ExportDynamic = true;
 }
 
 static void setVersionId(SymbolBody *Body, StringRef VersionName,
                          StringRef Name, uint16_t Version) {
   if (!Body || Body->isUndefined()) {
     if (Config->NoUndefinedVersion)
       error("version script assignment of " + VersionName + " to symbol " +
             Name + " failed: symbol not defined");
     return;
   }
 
   Symbol *Sym = Body->symbol();
   if (Sym->VersionId != Config->DefaultSymbolVersion)
     warning("duplicate symbol " + Name + " in version script");
   Sym->VersionId = Version;
 }
 
 template <class ELFT>
 std::map<std::string, SymbolBody *> SymbolTable<ELFT>::getDemangledSyms() {
   std::map<std::string, SymbolBody *> Result;
   for (Symbol *Sym : SymVector) {
     SymbolBody *B = Sym->body();
     Result[demangle(B->getName())] = B;
   }
   return Result;
 }
 
 static bool hasExternCpp() {
   for (VersionDefinition &V : Config->VersionDefinitions)
     for (SymbolVersion Sym : V.Globals)
       if (Sym.IsExternCpp)
         return true;
   return false;
 }
 
 static SymbolBody *findDemangled(const std::map<std::string, SymbolBody *> &D,
                                  StringRef Name) {
   auto I = D.find(Name);
   if (I != D.end())
     return I->second;
   return nullptr;
 }
 
 static std::vector<SymbolBody *>
 findAllDemangled(const std::map<std::string, SymbolBody *> &D,
                  const Regex &Re) {
   std::vector<SymbolBody *> Res;
   for (auto &P : D) {
     SymbolBody *Body = P.second;
     if (!Body->isUndefined() && const_cast<Regex &>(Re).match(P.first))
       Res.push_back(Body);
   }
   return Res;
 }
 
 // This function processes version scripts by updating VersionId
 // member of symbols.
 template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
   // If there's only one anonymous version definition in a version
   // script file, the script does not actullay define any symbol version,
   // but just specifies symbols visibilities. We assume that the script was
   // in the form of { global: foo; bar; local *; }. So, local is default.
   // Here, we make specified symbols global.
   if (!Config->VersionScriptGlobals.empty()) {
     for (SymbolVersion &Sym : Config->VersionScriptGlobals)
       if (SymbolBody *B = find(Sym.Name))
         B->symbol()->VersionId = VER_NDX_GLOBAL;
     return;
   }
 
   if (Config->VersionDefinitions.empty())
     return;
 
   // Now we have version definitions, so we need to set version ids to symbols.
   // Each version definition has a glob pattern, and all symbols that match
   // with the pattern get that version.
 
   // Users can use "extern C++ {}" directive to match against demangled
   // C++ symbols. For example, you can write a pattern such as
   // "llvm::*::foo(int, ?)". Obviously, there's no way to handle this
   // other than trying to match a regexp against all demangled symbols.
   // So, if "extern C++" feature is used, we demangle all known symbols.
   std::map<std::string, SymbolBody *> Demangled;
   if (hasExternCpp())
     Demangled = getDemangledSyms();
 
   // First, we assign versions to exact matching symbols,
   // i.e. version definitions not containing any glob meta-characters.
   for (VersionDefinition &V : Config->VersionDefinitions) {
     for (SymbolVersion Sym : V.Globals) {
       if (hasWildcard(Sym.Name))
         continue;
       StringRef N = Sym.Name;
       SymbolBody *B = Sym.IsExternCpp ? findDemangled(Demangled, N) : find(N);
       setVersionId(B, V.Name, N, V.Id);
     }
   }
 
   // Next, we assign versions to fuzzy matching symbols,
   // i.e. version definitions containing glob meta-characters.
   // Note that because the last match takes precedence over previous matches,
   // we iterate over the definitions in the reverse order.
   for (size_t I = Config->VersionDefinitions.size() - 1; I != (size_t)-1; --I) {
     VersionDefinition &V = Config->VersionDefinitions[I];
     for (SymbolVersion &Sym : V.Globals) {
       if (!hasWildcard(Sym.Name))
         continue;
       Regex Re = compileGlobPatterns({Sym.Name});
       std::vector<SymbolBody *> Syms =
           Sym.IsExternCpp ? findAllDemangled(Demangled, Re) : findAll(Re);
 
       // Exact matching takes precendence over fuzzy matching,
       // so we set a version to a symbol only if no version has been assigned
       // to the symbol. This behavior is compatible with GNU.
       for (SymbolBody *B : Syms)
         if (B->symbol()->VersionId == Config->DefaultSymbolVersion)
           B->symbol()->VersionId = V.Id;
     }
   }
 }
 
 template class elf::SymbolTable<ELF32LE>;
 template class elf::SymbolTable<ELF32BE>;
 template class elf::SymbolTable<ELF64LE>;
 template class elf::SymbolTable<ELF64BE>;
diff --git a/test/ELF/format-binary.test b/test/ELF/format-binary.test
new file mode 100644
index 0000000..493893d
--- /dev/null
+++ b/test/ELF/format-binary.test
@@ -0,0 +1,52 @@
+# REQUIRES: x86
+
+# RUN: echo -n "Fluffle Puff" > %t.binary
+# RUN: ld.lld -m elf_x86_64 -r -b binary %t.binary -o %t.out
+# RUN: llvm-readobj %t.out -sections -section-data -symbols | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -b binary %t.binary -b default %t.o -shared -o %t.out
+
+# CHECK:          Name: .data
+# CHECK-NEXT:     Type: SHT_PROGBITS
+# CHECK-NEXT:     Flags [
+# CHECK-NEXT:       SHF_ALLOC
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Address: 0x0
+# CHECK-NEXT:     Offset:
+# CHECK-NEXT:     Size: 12
+# CHECK-NEXT:     Link: 0
+# CHECK-NEXT:     Info: 0
+# CHECK-NEXT:     AddressAlignment:
+# CHECK-NEXT:     EntrySize: 0
+# CHECK-NEXT:     SectionData (
+# CHECK-NEXT:       0000: 466C7566 666C6520 50756666           |Fluffle Puff|
+# CHECK-NEXT:     )
+# CHECK-NEXT:   }
+
+# CHECK:          Name: _binary_format_binary_test_tmp_binary_start
+# CHECK-NEXT:     Value: 0x0
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Global
+# CHECK-NEXT:     Type: Object
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: .data
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name: _binary_format_binary_test_tmp_binary_end
+# CHECK-NEXT:     Value: 0xC
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Global
+# CHECK-NEXT:     Type: Object
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: .data
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name: _binary_format_binary_test_tmp_binary_size
+# CHECK-NEXT:     Value: 0xC
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Global
+# CHECK-NEXT:     Type: Object
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: Absolute
+# CHECK-NEXT:   }


More information about the llvm-commits mailing list