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
This commit is contained in:
Rui Ueyama 2016-10-20 21:57:06 +00:00
parent eb7ef2e1ca
commit 617d587432
4 changed files with 97 additions and 79 deletions

View File

@ -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 ELFT> 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<Elf_Shdr *> Sections;
std::vector<Elf_Sym *> Symbols;
StringTableBuilder ShStrTabBuilder{StringTableBuilder::ELF};
StringTableBuilder StrTabBuilder{StringTableBuilder::ELF};
BumpPtrAllocator Alloc;
StringSaver Saver{Alloc};
Elf_Shdr *ShStrTab;
Elf_Shdr *StrTab;
Elf_Shdr *SymTab;
};
}
template <class ELFT>
ELFCreator<ELFT>::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 <class ELFT> void ELFCreator<ELFT>::writeTo(uint8_t *Out) {
*Shdr++ = *S;
}
template class elf::ELFCreator<ELF32LE>;
template class elf::ELFCreator<ELF32BE>;
template class elf::ELFCreator<ELF64LE>;
template class elf::ELFCreator<ELF64BE>;
template <class ELFT>
std::vector<uint8_t> elf::wrapBinaryWithElfHeader(ArrayRef<uint8_t> Blob,
std::string Filename) {
typedef typename ELFT::uint uintX_t;
typedef typename ELFT::Sym Elf_Sym;
// Fill the ELF file header.
ELFCreator<ELFT> 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<uint8_t> 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<uint8_t>
elf::wrapBinaryWithElfHeader<ELF32LE>(ArrayRef<uint8_t>, std::string);
template std::vector<uint8_t>
elf::wrapBinaryWithElfHeader<ELF32BE>(ArrayRef<uint8_t>, std::string);
template std::vector<uint8_t>
elf::wrapBinaryWithElfHeader<ELF64LE>(ArrayRef<uint8_t>, std::string);
template std::vector<uint8_t>
elf::wrapBinaryWithElfHeader<ELF64BE>(ArrayRef<uint8_t>, std::string);

View File

@ -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 ELFT> 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<Elf_Shdr *> Sections;
std::vector<Elf_Sym *> 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 <class ELFT>
std::vector<uint8_t> wrapBinaryWithElfHeader(ArrayRef<uint8_t> Data,
std::string Filename);
}
}

View File

@ -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 <class ELFT> InputFile *BinaryFile::createELF() {
typedef typename ELFT::uint uintX_t;
typedef typename ELFT::Sym Elf_Sym;
ArrayRef<uint8_t> Blob((uint8_t *)MB.getBufferStart(), MB.getBufferSize());
StringRef Filename = MB.getBufferIdentifier();
Buffer = wrapBinaryWithElfHeader<ELFT>(Blob, Filename);
// Fill the ELF file header.
ELFCreator<ELFT> 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<ObjectFile>(MemoryBufferRef(
StringRef((char *)ELFData.data(), Size), MB.getBufferIdentifier()));
return createELFFile<ObjectFile>(
MemoryBufferRef(toStringRef(Buffer), Filename));
}
static bool isBitcode(MemoryBufferRef MB) {

View File

@ -326,7 +326,7 @@ public:
template <class ELFT> InputFile *createELF();
private:
std::vector<uint8_t> ELFData;
std::vector<uint8_t> Buffer;
};
InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "",