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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
#[repr(u16)]
pub enum EType {
    None = 0,
    Rel = 1,
    Exec = 2,
    Dyn = 3,
    Core = 4,
    Loos = 0xfe00,
    Hios = 0xfeff,
    Loproc = 0xff00,
    Hiproc = 0xffff,
}

#[derive(PartialEq, Eq, Debug, Copy, Clone)]
#[repr(u16)]
pub enum EMachine {
    None = 0x0,
    ATnTWe = 0x1,
    Sparc = 0x2,
    X86 = 0x3,
    M68k = 0x4,
    M88k = 0x5,
    IntelMcu = 0x6,
    Intel8086 = 0x7,
    Mips = 0x8,
    Ibm370 = 0x9,
    Intel80960 = 0x13,
    PowerPC32 = 0x14,
    PowerPC64 = 0x15,
    S390 = 0x16,
    ARM = 0x28,
    SuperH = 0x2A,
    IA64 = 0x32,
    Amd64 = 0x3E,
    Tms320c6000 = 0x8C,
    Aarch64 = 0xB7,
    RiscV = 0xF3,
}

#[derive(PartialEq, Eq, Debug, Copy, Clone)]
#[repr(u8)]
pub enum Bit {
    Bit32 = 1,
    Bit64 = 2,
}

#[derive(PartialEq, Eq, Debug, Copy, Clone)]
#[repr(u8)]
pub enum Endian {
    Little = 1,
    Big = 2,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct ELF64Union {
    /// Memory address of the entry point from where the process starts
    /// executing.
    pub e_entry: u64,
    /// Start of the program header table.
    pub e_phoff: u64,
    /// Start of the section header table.
    pub e_shoff: u64,
    /// Target specific flag.
    pub e_flags: u32,
    /// Size of this header.
    pub e_ehsize: u16,
    /// Size of program header table entry.
    pub e_phentsize: u16,
    /// Number of entries in program header table.
    pub e_phnum: u16,
    /// Size of section header table entry.
    pub e_shentsize: u16,
    /// Number of entries in section header table.
    pub e_shnum: u16,
    /// Index of the section header table entry that contains the section names.
    pub e_shstrndx: u16,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct ELF32Union {
    /// Memory address of the entry point from where the process starts
    /// executing.
    pub e_entry: u32,
    /// Start of the program header table.
    pub e_phoff: u32,
    /// Start of the section header table.
    pub e_shoff: u32,
    /// Target specific flag.
    pub e_flags: u32,
    /// Size of this header.
    pub e_ehsize: u16,
    /// Size of program header table entry.
    pub e_phentsize: u16,
    /// Number of entries in program header table.
    pub e_phnum: u16,
    /// Size of section header table entry.
    pub e_shentsize: u16,
    /// Number of entries in section header table.
    pub e_shnum: u16,
    /// Index of the section header table entry that contains the section names.
    pub e_shstrndx: u16,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub(crate) union ELFUnion {
    pub(crate) _u64: ELF64Union,
    pub(crate) _u32: ELF32Union,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub(crate) struct UHeader {
    /// 0x7F followed by ELF(45 4c 46) in ASCII; these four bytes constitute
    /// the magic number.
    pub magic: [u8; 4],
    /// Signify 32- or 64-bit format.
    pub class: Bit,
    /// Signify little or big endianness.
    pub data: Endian,
    /// Set to 1 for the original and current version of ELF.
    pub _version: u8,
    /// Identifies the target operating system ABI.
    pub _abi: u8,
    /// Further specifies the ABI version.
    pub _abi_version: u8,
    /// Unused.
    pub _pad: [u8; 7],
    /// Identifies object file type.
    pub e_type: EType,
    /// Specifies target instruction set architecture.
    pub e_machine: EMachine,
    /// Set to 1 for the original version of ELF.
    pub e_version: u32,
    pub _u: ELFUnion,
}