From: Rui Ueyama Date: Thu, 20 Oct 2016 21:57:06 +0000 (+0000) Subject: Move code from InputFile to ELFCreator to decouple the two files. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=617d587432739ed20ca4244debfdbfb3d6dad912;p=platform%2Fupstream%2Fllvm.git Move code from InputFile to ELFCreator to decouple the two files. Now that only one non-member function is exported from ELFCreator.h. All the details are handled internally in ELFCreator.cpp file. llvm-svn: 284786 --- diff --git a/lld/ELF/ELFCreator.cpp b/lld/ELF/ELFCreator.cpp index 3904449..d95f5ab 100644 --- a/lld/ELF/ELFCreator.cpp +++ b/lld/ELF/ELFCreator.cpp @@ -13,6 +13,10 @@ //===----------------------------------------------------------------------===// #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; @@ -21,13 +25,45 @@ 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); + Elf_Sym *addSymbol(StringRef Name); + size_t layout(); + void writeTo(uint8_t *Out); + +private: + Elf_Ehdr Header = {}; + std::vector Sections; + std::vector Symbols; + StringTableBuilder ShStrTabBuilder{StringTableBuilder::ELF}; + StringTableBuilder StrTabBuilder{StringTableBuilder::ELF}; + BumpPtrAllocator Alloc; + StringSaver Saver{Alloc}; + Elf_Shdr *ShStrTab; + 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 == llvm::support::little - ? ELFDATA2LSB - : ELFDATA2MSB; + 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; @@ -111,7 +147,50 @@ template void ELFCreator::writeTo(uint8_t *Out) { *Shdr++ = *S; } -template class elf::ELFCreator; -template class elf::ELFCreator; -template class elf::ELFCreator; -template class elf::ELFCreator; +template +std::vector elf::wrapBinaryWithElfHeader(ArrayRef Blob, + std::string Filename) { + typedef typename ELFT::uint uintX_t; + typedef typename ELFT::Sym Elf_Sym; + + // Fill the ELF file header. + ELFCreator File(ET_REL, Config->EMachine); + auto 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. + auto AddSym = [&](std::string Name, uintX_t SecIdx, uintX_t Value) { + Elf_Sym *Sym = File.addSymbol("_binary_" + Filename + Name); + Sym->setBindingAndType(STB_GLOBAL, STT_OBJECT); + Sym->st_shndx = SecIdx; + Sym->st_value = Value; + }; + AddSym("_start", Sec.Index, 0); + AddSym("_end", Sec.Index, Blob.size()); + AddSym("_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); diff --git a/lld/ELF/ELFCreator.h b/lld/ELF/ELFCreator.h index 5bf686f..ae4e19a 100644 --- a/lld/ELF/ELFCreator.h +++ b/lld/ELF/ELFCreator.h @@ -12,43 +12,14 @@ #include "lld/Core/LLVM.h" -#include "llvm/MC/StringTableBuilder.h" -#include "llvm/Object/ELFTypes.h" -#include "llvm/Support/StringSaver.h" - namespace lld { namespace elf { -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); - Elf_Sym *addSymbol(StringRef Name); - size_t layout(); - void writeTo(uint8_t *Out); - -private: - Elf_Ehdr Header = {}; - std::vector Sections; - std::vector Symbols; - llvm::StringTableBuilder ShStrTabBuilder{llvm::StringTableBuilder::ELF}; - llvm::StringTableBuilder StrTabBuilder{llvm::StringTableBuilder::ELF}; - llvm::BumpPtrAllocator Alloc; - llvm::StringSaver Saver{Alloc}; - Elf_Shdr *ShStrTab; - Elf_Shdr *StrTab; - Elf_Shdr *SymTab; -}; +// 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(ArrayRef Data, + std::string Filename); } } diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 154f792..27cfcee 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -781,44 +781,12 @@ static InputFile *createELFFile(MemoryBufferRef MB) { // 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() { - typedef typename ELFT::uint uintX_t; - typedef typename ELFT::Sym Elf_Sym; + ArrayRef Blob((uint8_t *)MB.getBufferStart(), MB.getBufferSize()); + StringRef Filename = MB.getBufferIdentifier(); + Buffer = wrapBinaryWithElfHeader(Blob, Filename); - // Fill the ELF file header. - ELFCreator File(ET_REL, Config->EMachine); - auto DataSec = File.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; - - // Replace non-alphanumeric characters with '_'. - std::string Filepath = MB.getBufferIdentifier(); - std::transform(Filepath.begin(), Filepath.end(), Filepath.begin(), - [](char C) { return isalnum(C) ? C : '_'; }); - - // Add _start, _end and _size symbols. - auto AddSym = [&](std::string Name, uintX_t SecIdx, uintX_t Value) { - Elf_Sym *Sym = File.addSymbol("_binary_" + Filepath + Name); - Sym->setBindingAndType(STB_GLOBAL, STT_OBJECT); - Sym->st_shndx = SecIdx; - Sym->st_value = Value; - }; - AddSym("_start", DataSec.Index, 0); - AddSym("_end", DataSec.Index, MB.getBufferSize()); - AddSym("_size", SHN_ABS, MB.getBufferSize()); - - // Fix the ELF file layout and write it down to ELFData uint8_t vector. - size_t Size = File.layout(); - ELFData.resize(Size); - File.writeTo(ELFData.data()); - - // Fill .data section with actual data. - memcpy(ELFData.data() + DataSec.Header->sh_offset, MB.getBufferStart(), - MB.getBufferSize()); - - return createELFFile(MemoryBufferRef( - StringRef((char *)ELFData.data(), Size), MB.getBufferIdentifier())); + return createELFFile( + MemoryBufferRef(toStringRef(Buffer), Filename)); } static bool isBitcode(MemoryBufferRef MB) { diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 13f47b5..61e9bbe 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -326,7 +326,7 @@ public: template InputFile *createELF(); private: - std::vector ELFData; + std::vector Buffer; }; InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "",