mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-17 05:24:49 +00:00
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:
parent
eb7ef2e1ca
commit
617d587432
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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 = "",
|
||||
|
Loading…
x
Reference in New Issue
Block a user