summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--elf.cpp69
-rw-r--r--elf.h14
-rw-r--r--test-elf.cpp2
3 files changed, 72 insertions, 13 deletions
diff --git a/elf.cpp b/elf.cpp
index 9a835ff..2923392 100644
--- a/elf.cpp
+++ b/elf.cpp
@@ -2,17 +2,25 @@
#include "file.h"
+// TODO
//#include <boost/endian/conversion.hpp>
#include <cstring>
+// We need at least 4096 bytes aligment. Otherwise we get segfaults at startup
+#define PAD 0x1000
+
// Helper Functions
namespace {
void AddFileHeader(std::vector<uint8_t>& data, const std::vector<uint8_t>& code)
{
Elf::FileHeader fh;
- fh.e_shoff = sizeof(fh) + sizeof(Elf::ProgramHeader) + code.size() + 16;
+#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));
@@ -23,7 +31,12 @@ namespace {
{
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();
@@ -32,13 +45,35 @@ namespace {
std::memcpy(data.data() + old_size, reinterpret_cast<void*>(&ph), sizeof(ph));
}
- void AddSectionHeaderText(std::vector<uint8_t>& data, const std::vector<uint8_t>& code)
+ void AddSectionHeaderNull(std::vector<uint8_t>& data, const std::vector<uint8_t>& code)
{
Elf::SectionHeader sh;
sh.sh_name = 0; // offset in section
+ sh.sh_size = 0;
+ sh.sh_type = 0; // <null>
+ 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<void*>(&sh), sizeof(sh));
+ }
+
+ void AddSectionHeaderText(std::vector<uint8_t>& data, const std::vector<uint8_t>& 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));
@@ -49,15 +84,30 @@ namespace {
{
Elf::SectionHeader sh;
- sh.sh_name = 0; // offset in section
- sh.sh_size = 16;
+ 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<void*>(&sh), sizeof(sh));
}
+
+ void PadUpTo(std::vector<uint8_t>& 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<uint8_t>& code)
@@ -67,13 +117,21 @@ void Elf::Write(const std::filesystem::path& path, const std::vector<uint8_t>& c
AddFileHeader(data, code);
AddProgramHeader(data, code);
+#ifdef PAD
+ PadUpTo(data, PAD);
+#endif
+
data.insert(data.end(), code.begin(), code.end());
- std::string section_names(".text\0.shstrtab\0", 16);
+ 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);
@@ -88,3 +146,4 @@ std::vector<uint8_t> Elf::Read(const std::filesystem::path& path)
return result;
}
+
diff --git a/elf.h b/elf.h
index 9d1ba69..abcbca0 100644
--- a/elf.h
+++ b/elf.h
@@ -29,7 +29,7 @@ struct FileHeader
2, // 64 bit
1, // little endian
1, // Version: default == 1
- 3, // Linux
+ 0, // SysV, 3=Linux
0, // EI_ABIVERSION
0,0,0,0,0,0,0 // pad
};
@@ -39,13 +39,13 @@ struct FileHeader
uint64_t e_entry{0x0000000000401000};
uint64_t e_phoff{0x40};
uint64_t e_shoff{}; // section header table offset
- uint32_t e_flags{0x00000112}; // EXEC_P, HAS_SYMS, D_PAGED
+ uint32_t e_flags{};
uint16_t e_ehsize{0x40}; // size of this header
uint16_t e_phentsize{0x38}; // size of program header
uint16_t e_phnum{1}; // 1 program header
uint16_t e_shentsize{0x40}; // size of section header
- uint16_t e_shnum{2}; // number of section headers
- uint16_t e_shstrndx{1}; // 1st section header contains section names
+ uint16_t e_shnum{3}; // number of section headers
+ uint16_t e_shstrndx{2}; // 1st section header contains section names
};
// Segment
@@ -53,12 +53,12 @@ struct ProgramHeader
{
uint32_t p_type{1}; // Loadable segment
uint32_t p_flags{5}; // X=1 | W=2 | R=4
- uint64_t p_offset{0x0}; // offset in file
+ uint64_t p_offset{}; // offset in file
uint64_t p_vaddr{0x401000}; // virtual address
uint64_t p_paddr{0x401000}; // physical address, not really relevant
uint64_t p_filesz{}; // size of segment in file, e.g. size of code
uint64_t p_memsz{}; // size of segment in memory
- uint64_t p_align{0}; // alignment
+ uint64_t p_align{}; // alignment
};
struct SectionHeader
@@ -67,7 +67,7 @@ struct SectionHeader
uint32_t sh_type{1}; // program data
uint64_t sh_flags{6}; // ALLOC, EXE
uint64_t sh_addr{0x401000}; // virtual address
- uint64_t sh_offset{0x1000};
+ uint64_t sh_offset{};
uint64_t sh_size{}; // section size
uint32_t sh_link{};
uint32_t sh_info{};
diff --git a/test-elf.cpp b/test-elf.cpp
index dba220e..d3fa9a9 100644
--- a/test-elf.cpp
+++ b/test-elf.cpp
@@ -49,7 +49,7 @@ TEST_F(ElfTest, write) {
{
0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00, 0x00, // mov $0x3c,%rax # syscall 60
0x48, 0x31, 0xff, // xor %rdi,%rdi # exit code 0
- 0x0f, 0x05 // syscall
+ 0x0f, 0x05, // syscall
});
ASSERT_TRUE(fs::exists(TempFilename()));