Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -75,6 +75,7 @@ std::vector BuildIdVector; bool AllowMultipleDefinition; bool AsNeeded = false; + bool Binary = false; bool Bsymbolic; bool BsymbolicFunctions; bool Demangle = true; Index: ELF/Driver.h =================================================================== --- ELF/Driver.h +++ ELF/Driver.h @@ -27,7 +27,7 @@ class LinkerDriver { public: void main(ArrayRef 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 Cpio; // for reproduce Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -114,7 +114,7 @@ // 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"; @@ -124,6 +124,11 @@ return; MemoryBufferRef MBRef = *Buffer; + if (Config->Binary && !KnownScript) { + Files.push_back(make_unique(MBRef)); + return; + } + switch (identify_magic(MBRef.getBuffer())) { case file_magic::unknown: readLinkerScript(MBRef); @@ -487,14 +492,30 @@ 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; Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -45,6 +45,7 @@ LazyObjectKind, ArchiveKind, BitcodeKind, + BinaryKind, }; Kind kind() const { return FileKind; } @@ -297,6 +298,21 @@ 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 + std::unique_ptr createELF(); + +private: + std::unique_ptr ELFData; +}; + std::unique_ptr createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = ""); std::unique_ptr createSharedFile(MemoryBufferRef MB); Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -12,6 +12,7 @@ #include "Error.h" #include "InputSection.h" #include "LinkerScript.h" +#include "SimpleELFWriter.h" #include "SymbolTable.h" #include "Symbols.h" #include "llvm/ADT/STLExtras.h" @@ -19,6 +20,8 @@ #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; @@ -706,6 +709,50 @@ Symbols.push_back(createSymbol(KeptComdats, *Obj, Sym)); } +template +std::unique_ptr BinaryFile::createELF() { + SimpleELFWriter 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( + MemoryBufferRef(StringRef(Buff, Size), MB.getBufferIdentifier())); +} + template