#include "elf.h" #include "file.h" // TODO //#include #include // We need at least 4096 bytes aligment. Otherwise we get segfaults at startup #define PAD 0x1000 // Helper Functions namespace { void AddFileHeader(std::vector& data, const std::vector& code) { Elf::FileHeader fh; #ifdef PAD fh.e_shoff = PAD + code.size() + 17; #else fh.e_shoff = sizeof(fh) + sizeof(Elf::ProgramHeader) + code.size() + 17; #endif size_t old_size {data.size()}; data.resize(old_size + sizeof(fh)); std::memcpy(data.data() + old_size, reinterpret_cast(&fh), sizeof(fh)); } void AddProgramHeader(std::vector& data, const std::vector& code) { Elf::ProgramHeader ph; #ifdef PAD ph.p_offset = PAD; ph.p_align = PAD; #else ph.p_offset = sizeof(Elf::FileHeader) + sizeof(Elf::ProgramHeader); #endif ph.p_filesz = code.size(); ph.p_memsz = code.size(); size_t old_size {data.size()}; data.resize(old_size + sizeof(ph)); std::memcpy(data.data() + old_size, reinterpret_cast(&ph), sizeof(ph)); } void AddSectionHeaderNull(std::vector& data, const std::vector& code) { Elf::SectionHeader sh; sh.sh_name = 0; // offset in section sh.sh_size = 0; sh.sh_type = 0; // sh.sh_flags = 0; sh.sh_addr = 0; sh.sh_offset = 0; size_t old_size {data.size()}; data.resize(old_size + sizeof(sh)); std::memcpy(data.data() + old_size, reinterpret_cast(&sh), sizeof(sh)); } void AddSectionHeaderText(std::vector& data, const std::vector& code) { Elf::SectionHeader sh; sh.sh_name = 1; // offset in section sh.sh_size = code.size(); sh.sh_type = 1; // program #ifdef PAD sh.sh_offset = PAD; #else sh.sh_offset = sizeof(Elf::FileHeader) + sizeof(Elf::ProgramHeader); #endif sh.sh_addralign = 1; size_t old_size {data.size()}; data.resize(old_size + sizeof(sh)); std::memcpy(data.data() + old_size, reinterpret_cast(&sh), sizeof(sh)); } void AddSectionHeaderSectionNames(std::vector& data, const std::vector& code) { Elf::SectionHeader sh; sh.sh_name = 7; // offset in section sh.sh_size = 17; sh.sh_type = 3; // section names sh.sh_flags = 0; sh.sh_addr = 0; #ifdef PAD sh.sh_offset = PAD + code.size(); #else sh.sh_offset = sizeof(Elf::FileHeader) + sizeof(Elf::ProgramHeader) + code.size(); #endif sh.sh_addralign = 1; size_t old_size {data.size()}; data.resize(old_size + sizeof(sh)); std::memcpy(data.data() + old_size, reinterpret_cast(&sh), sizeof(sh)); } void PadUpTo(std::vector& data, size_t size) { if (data.size() < size) { data.resize(size); } else throw std::runtime_error("Padding not possible. Too many bytes already."); } } void Elf::Write(const std::filesystem::path& path, const std::vector& code) { std::vector data; AddFileHeader(data, code); AddProgramHeader(data, code); #ifdef PAD PadUpTo(data, PAD); #endif data.insert(data.end(), code.begin(), code.end()); std::string section_names("\0.text\0.shstrtab\0", 17); if (section_names.size() != 17) throw std::runtime_error("Bad size"); size_t old_size {data.size()}; data.resize(old_size + section_names.size()); std::memcpy(data.data() + old_size, section_names.data(), section_names.size()); AddSectionHeaderNull(data, code); AddSectionHeaderText(data, code); AddSectionHeaderSectionNames(data, code); File::setFile(path, data); } std::vector Elf::Read(const std::filesystem::path& path) { std::vector result; // TODO return result; }