1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
#pragma once
#include <bit>
#include <cstdint>
#include <filesystem>
#include <vector>
namespace Elf {
// ELF 64 bit only
#pragma pack(push, 1)
struct FileHeader
{
enum {
EI_MAG0 = 0,
EI_MAG1,
EI_MAG2,
EI_MAG3,
EI_CLASS,
EI_DATA,
EI_VERSION,
EI_OSABI,
EI_ABIVERSION,
EI_PAD
};
uint8_t e_ident[16]{
0x7F, 0x45, 0x4C, 0x46, // .ELF
2, // 64 bit
1, // little endian
1, // Version: default == 1
0, // SysV, 3=Linux
0, // EI_ABIVERSION
0,0,0,0,0,0,0 // pad
};
uint16_t e_type{0x02}; // ET_EXEC
uint16_t e_machine{0x3E}; // AMD64
uint32_t e_version{1};
uint64_t e_entry{0x0000000000401000};
uint64_t e_phoff{0x40};
uint64_t e_shoff{}; // section header table offset
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{3}; // number of section headers
uint16_t e_shstrndx{2}; // 1st section header contains section names
};
// Segment
struct ProgramHeader
{
uint32_t p_type{1}; // Loadable segment
uint32_t p_flags{5}; // X=1 | W=2 | R=4
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{}; // alignment
};
struct SectionHeader
{
uint32_t sh_name{}; // offset of name in .shstrtab
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{};
uint64_t sh_size{}; // section size
uint32_t sh_link{};
uint32_t sh_info{};
uint64_t sh_addralign{};
uint64_t sh_entsize{};
};
#pragma pack(pop)
void Write(const std::filesystem::path& path, const std::vector<uint8_t>&);
std::vector<uint8_t> Read(const std::filesystem::path& path);
}
|