1#[derive(Debug)]
2pub struct ElfHeader {
3 pub e_ident: [u8; 16], pub e_type: u16, pub e_machine: u16, pub e_version: u32, pub e_entry: u64, pub e_phoff: u64, pub e_shoff: u64, pub e_flags: u32, pub e_ehsize: u16, pub e_phentsize: u16, pub e_phnum: u16, pub e_shentsize: u16, pub e_shnum: u16, pub e_shstrndx: u16, }
18
19#[derive(Debug)]
20pub struct ProgramHeader {
21 pub p_type: u32, pub p_flags: u32, pub p_offset: u64, pub p_vaddr: u64, pub p_paddr: u64, pub p_filesz: u64, pub p_memsz: u64, pub p_align: u64, }
30
31impl Default for ElfHeader {
32 fn default() -> Self {
33 Self {
34 e_ident: Self::SOLANA_IDENT,
35 e_type: Self::SOLANA_TYPE,
36 e_machine: Self::SOLANA_MACHINE,
37 e_version: Self::SOLANA_VERSION,
38 e_entry: 0,
39 e_phoff: Self::ELF64_HEADER_SIZE as u64,
40 e_shoff: 0,
41 e_flags: 0,
42 e_ehsize: Self::ELF64_HEADER_SIZE,
43 e_phentsize: Self::PROGRAM_HEADER_SIZE,
44 e_phnum: 0,
45 e_shentsize: Self::SECTION_HEADER_SIZE,
46 e_shnum: 0,
47 e_shstrndx: 0,
48 }
49 }
50}
51
52impl ElfHeader {
53 const SOLANA_IDENT: [u8; 16] = [
54 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
62 const SOLANA_TYPE: u16 = 3; const SOLANA_MACHINE: u16 = 247; const SOLANA_VERSION: u32 = 1; const ELF64_HEADER_SIZE: u16 = 64;
66 const PROGRAM_HEADER_SIZE: u16 = 56;
67 const SECTION_HEADER_SIZE: u16 = 64;
68
69 pub fn new() -> Self {
70 Self::default()
71 }
72
73 pub fn bytecode(&self) -> Vec<u8> {
74 let mut bytecode = Vec::with_capacity(Self::ELF64_HEADER_SIZE as usize);
75
76 bytecode.extend_from_slice(&self.e_ident);
78
79 bytecode.extend_from_slice(&self.e_type.to_le_bytes());
81 bytecode.extend_from_slice(&self.e_machine.to_le_bytes());
82 bytecode.extend_from_slice(&self.e_version.to_le_bytes());
83 bytecode.extend_from_slice(&self.e_entry.to_le_bytes());
84 bytecode.extend_from_slice(&self.e_phoff.to_le_bytes());
85 bytecode.extend_from_slice(&self.e_shoff.to_le_bytes());
86 bytecode.extend_from_slice(&self.e_flags.to_le_bytes());
87 bytecode.extend_from_slice(&self.e_ehsize.to_le_bytes());
88 bytecode.extend_from_slice(&self.e_phentsize.to_le_bytes());
89 bytecode.extend_from_slice(&self.e_phnum.to_le_bytes());
90 bytecode.extend_from_slice(&self.e_shentsize.to_le_bytes());
91 bytecode.extend_from_slice(&self.e_shnum.to_le_bytes());
92 bytecode.extend_from_slice(&self.e_shstrndx.to_le_bytes());
93
94 bytecode
95 }
96}
97
98#[rustfmt::skip]
99impl ProgramHeader {
100
101 const PT_LOAD: u32 = 1; const PT_DYNAMIC: u32 = 2; const PF_X: u32 = 1; const PF_W: u32 = 2; const PF_R: u32 = 4; const PAGE_SIZE: u64 = 4096; pub fn new_load(offset: u64, size: u64, executable: bool) -> Self {
111 let flags = if executable {
112 Self::PF_R | Self::PF_X } else {
114 Self::PF_R };
116
117 ProgramHeader {
118 p_type: Self::PT_LOAD,
119 p_flags: flags,
120 p_offset: offset,
121 p_vaddr: offset,
122 p_paddr: offset,
123 p_filesz: size,
124 p_memsz: size,
125 p_align: Self::PAGE_SIZE
126 }
127 }
128
129 pub fn new_dynamic(offset: u64, size: u64) -> Self {
130 ProgramHeader {
131 p_type: Self::PT_DYNAMIC,
132 p_flags: Self::PF_R | Self::PF_W,
133 p_offset: offset,
134 p_vaddr: offset,
135 p_paddr: offset,
136 p_filesz: size,
137 p_memsz: size,
138 p_align: 8
139 }
140 }
141
142 pub fn bytecode(&self) -> Vec<u8> {
143 let mut bytecode = Vec::with_capacity(56); bytecode.extend_from_slice(&self.p_type.to_le_bytes());
146 bytecode.extend_from_slice(&self.p_flags.to_le_bytes());
147 bytecode.extend_from_slice(&self.p_offset.to_le_bytes());
148 bytecode.extend_from_slice(&self.p_vaddr.to_le_bytes());
149 bytecode.extend_from_slice(&self.p_paddr.to_le_bytes());
150 bytecode.extend_from_slice(&self.p_filesz.to_le_bytes());
151 bytecode.extend_from_slice(&self.p_memsz.to_le_bytes());
152 bytecode.extend_from_slice(&self.p_align.to_le_bytes());
153
154 bytecode
155 }
156}
157#[derive(Debug)]
158pub struct SectionHeader {
159 sh_name: u32, sh_type: u32, sh_flags: u64, sh_addr: u64, sh_offset: u64, sh_size: u64, sh_link: u32, sh_info: u32, sh_addralign: u64, sh_entsize: u64, }
170
171#[rustfmt::skip]
172impl SectionHeader {
173 pub const SHT_NULL: u32 = 0; pub const SHT_PROGBITS: u32 = 1; pub const SHT_STRTAB: u32 = 3; pub const SHT_NOBITS: u32 = 8; pub const SHT_DYNAMIC: u32 = 6; pub const SHT_DYNSYM: u32 = 11; pub const SHT_REL: u32 = 9; pub const SHF_WRITE: u64 = 0x1; pub const SHF_ALLOC: u64 = 0x2; pub const SHF_EXECINSTR: u64 = 0x4; #[allow(clippy::too_many_arguments)]
188 pub fn new(name_offset: u32, sh_type: u32, flags: u64, addr: u64, offset: u64, size: u64, link: u32, info: u32, addralign: u64, entsize: u64) -> Self {
189 Self {
190 sh_name: name_offset,
191 sh_type,
192 sh_flags: flags,
193 sh_addr: addr,
194 sh_offset: offset,
195 sh_size: size,
196 sh_link: link,
197 sh_info: info,
198 sh_addralign: addralign,
199 sh_entsize: entsize,
200 }
201 }
202
203 pub fn bytecode(&self) -> Vec<u8> {
204 let mut bytecode = Vec::with_capacity(64); bytecode.extend_from_slice(&self.sh_name.to_le_bytes());
207 bytecode.extend_from_slice(&self.sh_type.to_le_bytes());
208 bytecode.extend_from_slice(&self.sh_flags.to_le_bytes());
209 bytecode.extend_from_slice(&self.sh_addr.to_le_bytes());
210 bytecode.extend_from_slice(&self.sh_offset.to_le_bytes());
211 bytecode.extend_from_slice(&self.sh_size.to_le_bytes());
212 bytecode.extend_from_slice(&self.sh_link.to_le_bytes());
213 bytecode.extend_from_slice(&self.sh_info.to_le_bytes());
214 bytecode.extend_from_slice(&self.sh_addralign.to_le_bytes());
215 bytecode.extend_from_slice(&self.sh_entsize.to_le_bytes());
216
217 bytecode
218 }
219}