//===- 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" using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; using namespace lld; using namespace lld::elf; 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_VERSION] = EV_CURRENT; Header.e_ident[EI_OSABI] = 0; Header.e_type = Type; Header.e_machine = Machine; Header.e_version = EV_CURRENT; Header.e_entry = 0; Header.e_phoff = 0; Header.e_flags = 0; Header.e_ehsize = sizeof(Elf_Ehdr); Header.e_phnum = 0; Header.e_shentsize = sizeof(Elf_Shdr); Header.e_shstrndx = 1; ShStrTab = addSection(".shstrtab").Header; ShStrTab->sh_type = SHT_STRTAB; ShStrTab->sh_addralign = 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 = 2; SymTab->sh_info = 1; SymTab->sh_addralign = sizeof(uintX_t); SymTab->sh_entsize = sizeof(Elf_Sym); } template typename ELFCreator::Section ELFCreator::addSection(StringRef Name) { std::size_t NameOff = SecHdrStrTabBuilder.add(Name); auto Shdr = new (Alloc) Elf_Shdr{}; Shdr->sh_name = NameOff; Sections.push_back(Shdr); return {Shdr, Sections.size()}; } template typename ELFCreator::Symbol ELFCreator::addSymbol(StringRef Name) { std::size_t NameOff = StrTabBuilder.add(Name); auto Sym = new (Alloc) Elf_Sym{}; Sym->st_name = NameOff; StaticSymbols.push_back(Sym); return {Sym, StaticSymbols.size()}; } template std::size_t ELFCreator::layout() { SecHdrStrTabBuilder.finalizeInOrder(); ShStrTab->sh_size = SecHdrStrTabBuilder.getSize(); StrTabBuilder.finalizeInOrder(); StrTab->sh_size = StrTabBuilder.getSize(); SymTab->sh_size = (StaticSymbols.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::write(uint8_t *Out) { std::memcpy(Out, &Header, sizeof(Elf_Ehdr)); std::copy(SecHdrStrTabBuilder.data().begin(), SecHdrStrTabBuilder.data().end(), Out + ShStrTab->sh_offset); std::copy(StrTabBuilder.data().begin(), StrTabBuilder.data().end(), Out + StrTab->sh_offset); Elf_Sym *Sym = reinterpret_cast(Out + SymTab->sh_offset); // Skip null. ++Sym; for (Elf_Sym *S : StaticSymbols) *Sym++ = *S; Elf_Shdr *Shdr = reinterpret_cast(Out + Header.e_shoff); // Skip null. ++Shdr; for (Elf_Shdr *S : Sections) *Shdr++ = *S; } template class elf::ELFCreator; template class elf::ELFCreator; template class elf::ELFCreator; template class elf::ELFCreator;