Index: ELF/CMakeLists.txt =================================================================== --- ELF/CMakeLists.txt +++ ELF/CMakeLists.txt @@ -6,7 +6,6 @@ Driver.cpp DriverUtils.cpp EhFrame.cpp - ELFCreator.cpp Error.cpp GdbIndex.cpp ICF.cpp Index: ELF/ELFCreator.h =================================================================== --- ELF/ELFCreator.h +++ /dev/null @@ -1,28 +0,0 @@ -//===- ELFCreator.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_ELF_CREATOR_H -#define LLD_ELF_ELF_CREATOR_H - -#include "lld/Core/LLVM.h" -#include -#include - -namespace lld { -namespace elf { - -// Wraps a given binary blob with an ELF header so that the blob -// can be linked as an ELF file. Used for "--format binary". -template -std::vector wrapBinaryWithElfHeader(llvm::ArrayRef Data, - std::string Filename); -} -} - -#endif Index: ELF/ELFCreator.cpp =================================================================== --- ELF/ELFCreator.cpp +++ /dev/null @@ -1,178 +0,0 @@ -//===- ELFCreator.cpp -----------------------------------------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains a class to create an ELF file in memory. This is -// supposed to be used for "-format binary" option. -// -//===----------------------------------------------------------------------===// - -#include "ELFCreator.h" -#include "Config.h" -#include "llvm/MC/StringTableBuilder.h" -#include "llvm/Object/ELFTypes.h" -#include "llvm/Support/StringSaver.h" - -using namespace llvm; -using namespace llvm::ELF; -using namespace llvm::object; - -using namespace lld; -using namespace lld::elf; - -namespace { -template class ELFCreator { - 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: - struct Section { - Elf_Shdr *Header; - size_t Index; - }; - - ELFCreator(std::uint16_t Type, std::uint16_t Machine); - Section addSection(StringRef Name); - void addSymbol(StringRef Name, uintX_t SecIdx, uintX_t Value); - size_t layout(); - void writeTo(uint8_t *Out); - -private: - Elf_Ehdr Header = {}; - std::vector Sections; - std::vector Symbols; - StringTableBuilder StrTabBuilder{StringTableBuilder::ELF}; - BumpPtrAllocator Alloc; - StringSaver Saver{Alloc}; - Elf_Shdr *StrTab; - Elf_Shdr *SymTab; -}; -} - -template -ELFCreator::ELFCreator(std::uint16_t Type, std::uint16_t Machine) { - std::memcpy(Header.e_ident, "\177ELF", 4); - Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; - Header.e_ident[EI_DATA] = - ELFT::TargetEndianness == support::little ? ELFDATA2LSB : ELFDATA2MSB; - Header.e_ident[EI_VERSION] = EV_CURRENT; - Header.e_type = Type; - Header.e_machine = Machine; - Header.e_version = EV_CURRENT; - Header.e_ehsize = sizeof(Elf_Ehdr); - Header.e_shentsize = sizeof(Elf_Shdr); - Header.e_shstrndx = 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 = 1; - SymTab->sh_info = 1; - SymTab->sh_addralign = sizeof(uintX_t); - SymTab->sh_entsize = sizeof(Elf_Sym); -} - -template -typename ELFCreator::Section -ELFCreator::addSection(StringRef Name) { - auto *Shdr = new (Alloc) Elf_Shdr{}; - Shdr->sh_name = StrTabBuilder.add(Saver.save(Name)); - Sections.push_back(Shdr); - return {Shdr, Sections.size()}; -} - -template -void ELFCreator::addSymbol(StringRef Name, uintX_t SecIdx, - uintX_t Value) { - auto *Sym = new (Alloc) Elf_Sym{}; - Sym->st_name = StrTabBuilder.add(Saver.save(Name)); - Sym->setBindingAndType(STB_GLOBAL, STT_OBJECT); - Sym->st_shndx = SecIdx; - Sym->st_value = Value; - Symbols.push_back(Sym); -} - -template size_t ELFCreator::layout() { - StrTabBuilder.finalizeInOrder(); - StrTab->sh_size = StrTabBuilder.getSize(); - SymTab->sh_size = (Symbols.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; -} - -template void ELFCreator::writeTo(uint8_t *Out) { - std::memcpy(Out, &Header, sizeof(Elf_Ehdr)); - StrTabBuilder.write(Out + StrTab->sh_offset); - - Elf_Sym *Sym = reinterpret_cast(Out + SymTab->sh_offset); - // Skip null. - ++Sym; - for (Elf_Sym *S : Symbols) - *Sym++ = *S; - - Elf_Shdr *Shdr = reinterpret_cast(Out + Header.e_shoff); - // Skip null. - ++Shdr; - for (Elf_Shdr *S : Sections) - *Shdr++ = *S; -} - -template -std::vector elf::wrapBinaryWithElfHeader(ArrayRef Blob, - std::string Filename) { - // Fill the ELF file header. - ELFCreator File(ET_REL, Config->EMachine); - typename ELFCreator::Section Sec = File.addSection(".data"); - Sec.Header->sh_flags = SHF_ALLOC; - Sec.Header->sh_size = Blob.size(); - Sec.Header->sh_type = SHT_PROGBITS; - Sec.Header->sh_addralign = 8; - - // Replace non-alphanumeric characters with '_'. - std::transform(Filename.begin(), Filename.end(), Filename.begin(), - [](char C) { return isalnum(C) ? C : '_'; }); - - // Add _start, _end and _size symbols. - File.addSymbol("_binary_" + Filename + "_start", Sec.Index, 0); - File.addSymbol("_binary_" + Filename + "_end", Sec.Index, Blob.size()); - File.addSymbol("_binary_" + Filename + "_size", SHN_ABS, Blob.size()); - - // Fix the ELF file layout and write it down to a uint8_t vector. - size_t Size = File.layout(); - std::vector Ret(Size); - File.writeTo(Ret.data()); - - // Fill .data section with actual data. - memcpy(Ret.data() + Sec.Header->sh_offset, Blob.data(), Blob.size()); - return Ret; -} - -template std::vector - elf::wrapBinaryWithElfHeader(ArrayRef, std::string); -template std::vector - elf::wrapBinaryWithElfHeader(ArrayRef, std::string); -template std::vector - elf::wrapBinaryWithElfHeader(ArrayRef, std::string); -template std::vector - elf::wrapBinaryWithElfHeader(ArrayRef, std::string); Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -361,11 +361,13 @@ public: explicit BinaryFile(MemoryBufferRef M) : InputFile(BinaryKind, M) {} static bool classof(const InputFile *F) { return F->kind() == BinaryKind; } - template InputFile *createELF(); + template void parse(); + ArrayRef getSections() const { return Sections; } private: - std::vector Buffer; llvm::BumpPtrAllocator Alloc; + llvm::StringSaver Saver{Alloc}; + std::vector Sections; }; InputFile *createObjectFile(llvm::BumpPtrAllocator &Alloc, MemoryBufferRef MB, Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -9,7 +9,6 @@ #include "InputFiles.h" #include "Driver.h" -#include "ELFCreator.h" #include "Error.h" #include "InputSection.h" #include "LinkerScript.h" @@ -822,15 +821,29 @@ return Obj; } -// Wraps a binary blob with an ELF header and footer -// so that we can link it as a regular ELF file. -template InputFile *BinaryFile::createELF() { - ArrayRef Blob((uint8_t *)MB.getBufferStart(), MB.getBufferSize()); - StringRef Filename = MB.getBufferIdentifier(); - Buffer = wrapBinaryWithElfHeader(Blob, Filename); +template void BinaryFile::parse() { + StringRef Buf = MB.getBuffer(); + ArrayRef Data = + makeArrayRef((const uint8_t *)Buf.data(), Buf.size()); - return createELFFile( - Alloc, MemoryBufferRef(toStringRef(Buffer), Filename)); + std::string Filename = MB.getBufferIdentifier(); + std::transform(Filename.begin(), Filename.end(), Filename.begin(), + [](char C) { return isalnum(C) ? C : '_'; }); + Filename = "_binary_" + Filename; + StringRef StartName = Saver.save(Twine(Filename) + "_start"); + StringRef EndName = Saver.save(Twine(Filename) + "_end"); + StringRef SizeName = Saver.save(Twine(Filename) + "_size"); + + auto *Section = + new InputSection(SHF_ALLOC, SHT_PROGBITS, 8, Data, ".data"); + Sections.push_back(Section); + + elf::Symtab::X->addRegular(StartName, STV_DEFAULT, Section, STB_GLOBAL, + STT_OBJECT, 0); + elf::Symtab::X->addRegular(EndName, STV_DEFAULT, Section, STB_GLOBAL, + STT_OBJECT, Data.size()); + elf::Symtab::X->addRegular(SizeName, STV_DEFAULT, nullptr, STB_GLOBAL, + STT_OBJECT, Data.size()); } static bool isBitcode(MemoryBufferRef MB) { @@ -942,10 +955,10 @@ template class elf::SharedFile; template class elf::SharedFile; -template InputFile *BinaryFile::createELF(); -template InputFile *BinaryFile::createELF(); -template InputFile *BinaryFile::createELF(); -template InputFile *BinaryFile::createELF(); +template void BinaryFile::parse(); +template void BinaryFile::parse(); +template void BinaryFile::parse(); +template void BinaryFile::parse(); template class elf::DIHelper; template class elf::DIHelper; Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -237,7 +237,7 @@ public: InputSection(uintX_t Flags, uint32_t Type, uintX_t Addralign, - ArrayRef Data); + ArrayRef Data, StringRef Name); InputSection(ObjectFile *F, const Elf_Shdr *Header, StringRef Name); // Write this section to a mmap'ed file, assuming Buf is pointing to Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -189,10 +189,11 @@ template InputSection::InputSection(uintX_t Flags, uint32_t Type, - uintX_t Addralign, ArrayRef Data) + uintX_t Addralign, ArrayRef Data, + StringRef Name) : InputSectionBase(nullptr, Flags, Type, /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, Addralign, - Data, "", Base::Regular) {} + Data, Name, Base::Regular) {} template InputSection::InputSection(elf::ObjectFile *F, @@ -840,7 +841,7 @@ Size += Sym->Size; } ArrayRef Data = makeArrayRef(nullptr, Size); - InputSection Ret(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, Alignment, Data); + InputSection Ret(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, Alignment, Data, ""); Ret.Live = true; return Ret; } Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -46,7 +46,8 @@ ScriptConfiguration *elf::ScriptConfig; template static void addRegular(SymbolAssignment *Cmd) { - Symbol *Sym = Symtab::X->addRegular(Cmd->Name, STB_GLOBAL, STV_DEFAULT); + Symbol *Sym = Symtab::X->addRegular(Cmd->Name, STV_DEFAULT, nullptr, + STB_GLOBAL, STT_NOTYPE, 0); Sym->Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; Cmd->Sym = Sym->body(); Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -50,6 +50,10 @@ return ObjectFiles; } + const std::vector &getBinaryFiles() const { + return BinaryFiles; + } + const std::vector *> &getSharedFiles() const { return SharedFiles; } @@ -69,7 +73,9 @@ Symbol *addRegular(StringRef Name, const Elf_Sym &Sym, InputSectionBase *Section); - Symbol *addRegular(StringRef Name, uint8_t Binding, uint8_t StOther); + Symbol *addRegular(StringRef Name, uint8_t StOther, + InputSectionBase *Section, uint8_t Binding, + uint8_t Type, uintX_t Value); Symbol *addSynthetic(StringRef N, OutputSectionBase *Section, uintX_t Value, uint8_t StOther); void addShared(SharedFile *F, StringRef Name, const Elf_Sym &Sym, @@ -131,6 +137,7 @@ std::vector *> ObjectFiles; std::vector *> SharedFiles; std::vector BitcodeFiles; + std::vector BinaryFiles; // Set of .so files to not link the same shared object file more than once. llvm::DenseSet SoNames; Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -53,7 +53,8 @@ // Binary file if (auto *F = dyn_cast(File)) { - addFile(F->createELF()); + BinaryFiles.push_back(F); + F->parse(); return; } @@ -124,7 +125,7 @@ DefinedRegular *SymbolTable::addAbsolute(StringRef Name, uint8_t Visibility) { return cast>( - addRegular(Name, STB_GLOBAL, Visibility)->body()); + addRegular(Name, Visibility, nullptr, STB_GLOBAL, STT_NOTYPE, 0)->body()); } // Add Name as an "ignored" symbol. An ignored symbol is a regular @@ -398,9 +399,11 @@ } template -Symbol *SymbolTable::addRegular(StringRef Name, uint8_t Binding, - uint8_t StOther) { - return addRegular(Name, StOther, STT_NOTYPE, 0, 0, Binding, nullptr); +Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, + InputSectionBase *Section, + uint8_t Binding, uint8_t Type, + uintX_t Value) { + return addRegular(Name, StOther, Type, Value, 0, Binding, Section); } template Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -698,21 +698,27 @@ } template void Writer::createSections() { - for (elf::ObjectFile *F : Symtab::X->getObjectFiles()) { - for (InputSectionBase *IS : F->getSections()) { - if (isDiscarded(IS)) { - reportDiscarded(IS); - continue; - } - OutputSectionBase *Sec; - bool IsNew; - StringRef OutsecName = getOutputSectionName(IS->Name, Alloc); - std::tie(Sec, IsNew) = Factory.create(IS, OutsecName); - if (IsNew) - OutputSections.push_back(Sec); - Sec->addSection(IS); + auto Add = [&](InputSectionBase *IS) { + if (isDiscarded(IS)) { + reportDiscarded(IS); + return; } - } + OutputSectionBase *Sec; + bool IsNew; + StringRef OutsecName = getOutputSectionName(IS->Name, Alloc); + std::tie(Sec, IsNew) = Factory.create(IS, OutsecName); + if (IsNew) + OutputSections.push_back(Sec); + Sec->addSection(IS); + }; + + for (elf::ObjectFile *F : Symtab::X->getObjectFiles()) + for (InputSectionBase *IS : F->getSections()) + Add(IS); + + for (BinaryFile *F : Symtab::X->getBinaryFiles()) + for (InputSectionData *ID : F->getSections()) + Add(cast>(ID)); sortInitFini(findSection(".init_array")); sortInitFini(findSection(".fini_array"));