summaryrefslogtreecommitdiffhomepage
path: root/elf.h
blob: abcbca04989b3273cbbdba9b69a1a76cb545de43 (plain)
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);
}