1use crate::SbpfArch;
2
3#[derive(Debug)]
4pub struct ElfHeader {
5 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, }
20
21#[derive(Debug)]
22pub struct ProgramHeader {
23 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, }
32
33impl Default for ElfHeader {
34 fn default() -> Self {
35 Self {
36 e_ident: Self::SOLANA_IDENT,
37 e_type: Self::SOLANA_TYPE,
38 e_machine: Self::SOLANA_MACHINE,
39 e_version: Self::SOLANA_VERSION,
40 e_entry: 0,
41 e_phoff: Self::ELF64_HEADER_SIZE as u64,
42 e_shoff: 0,
43 e_flags: 0,
44 e_ehsize: Self::ELF64_HEADER_SIZE,
45 e_phentsize: Self::PROGRAM_HEADER_SIZE,
46 e_phnum: 0,
47 e_shentsize: Self::SECTION_HEADER_SIZE,
48 e_shnum: 0,
49 e_shstrndx: 0,
50 }
51 }
52}
53
54impl ElfHeader {
55 const SOLANA_IDENT: [u8; 16] = [
56 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
64 const SOLANA_TYPE: u16 = 3; const SOLANA_MACHINE: u16 = 247; const SOLANA_VERSION: u32 = 1; const ELF64_HEADER_SIZE: u16 = 64;
68 const PROGRAM_HEADER_SIZE: u16 = 56;
69 const SECTION_HEADER_SIZE: u16 = 64;
70
71 pub fn new() -> Self {
72 Self::default()
73 }
74
75 pub fn bytecode(&self) -> Vec<u8> {
76 let mut bytecode = Vec::with_capacity(Self::ELF64_HEADER_SIZE as usize);
77
78 bytecode.extend_from_slice(&self.e_ident);
80
81 bytecode.extend_from_slice(&self.e_type.to_le_bytes());
83 bytecode.extend_from_slice(&self.e_machine.to_le_bytes());
84 bytecode.extend_from_slice(&self.e_version.to_le_bytes());
85 bytecode.extend_from_slice(&self.e_entry.to_le_bytes());
86 bytecode.extend_from_slice(&self.e_phoff.to_le_bytes());
87 bytecode.extend_from_slice(&self.e_shoff.to_le_bytes());
88 bytecode.extend_from_slice(&self.e_flags.to_le_bytes());
89 bytecode.extend_from_slice(&self.e_ehsize.to_le_bytes());
90 bytecode.extend_from_slice(&self.e_phentsize.to_le_bytes());
91 bytecode.extend_from_slice(&self.e_phnum.to_le_bytes());
92 bytecode.extend_from_slice(&self.e_shentsize.to_le_bytes());
93 bytecode.extend_from_slice(&self.e_shnum.to_le_bytes());
94 bytecode.extend_from_slice(&self.e_shstrndx.to_le_bytes());
95
96 bytecode
97 }
98}
99
100#[rustfmt::skip]
101impl ProgramHeader {
102
103 const PT_LOAD: u32 = 1; const PT_DYNAMIC: u32 = 2; pub const PF_X: u32 = 1; pub const PF_W: u32 = 2; pub const PF_R: u32 = 4; const PAGE_SIZE: u64 = 4096; pub const V3_RODATA_VADDR: u64 = 0 << 32;
113 pub const V3_BYTECODE_VADDR: u64 = 1 << 32;
114
115 pub fn new_load(offset: u64, size: u64, executable: bool, arch: SbpfArch) -> Self {
116 let (flags, vaddr, align) = match (arch, executable) {
117 (SbpfArch::V0, true) => (Self::PF_R | Self::PF_X, offset, Self::PAGE_SIZE),
118 (SbpfArch::V0, false) => (Self::PF_R, offset, Self::PAGE_SIZE),
119 (SbpfArch::V3, true) => (Self::PF_X, Self::V3_BYTECODE_VADDR, 0),
120 (SbpfArch::V3, false) => (Self::PF_R, Self::V3_RODATA_VADDR, 0),
121 };
122
123 ProgramHeader {
124 p_type: Self::PT_LOAD,
125 p_flags: flags,
126 p_offset: offset,
127 p_vaddr: vaddr,
128 p_paddr: vaddr,
129 p_filesz: size,
130 p_memsz: size,
131 p_align: align }
133 }
134
135 pub fn new_dynamic(offset: u64, size: u64) -> Self {
136 ProgramHeader {
137 p_type: Self::PT_DYNAMIC,
138 p_flags: Self::PF_R | Self::PF_W,
139 p_offset: offset,
140 p_vaddr: offset,
141 p_paddr: offset,
142 p_filesz: size,
143 p_memsz: size,
144 p_align: 8
145 }
146 }
147
148 pub fn bytecode(&self) -> Vec<u8> {
149 let mut bytecode = Vec::with_capacity(56); bytecode.extend_from_slice(&self.p_type.to_le_bytes());
152 bytecode.extend_from_slice(&self.p_flags.to_le_bytes());
153 bytecode.extend_from_slice(&self.p_offset.to_le_bytes());
154 bytecode.extend_from_slice(&self.p_vaddr.to_le_bytes());
155 bytecode.extend_from_slice(&self.p_paddr.to_le_bytes());
156 bytecode.extend_from_slice(&self.p_filesz.to_le_bytes());
157 bytecode.extend_from_slice(&self.p_memsz.to_le_bytes());
158 bytecode.extend_from_slice(&self.p_align.to_le_bytes());
159
160 bytecode
161 }
162}
163#[derive(Debug)]
164pub struct SectionHeader {
165 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, }
176
177#[rustfmt::skip]
178impl SectionHeader {
179 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)]
194 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 {
195 Self {
196 sh_name: name_offset,
197 sh_type,
198 sh_flags: flags,
199 sh_addr: addr,
200 sh_offset: offset,
201 sh_size: size,
202 sh_link: link,
203 sh_info: info,
204 sh_addralign: addralign,
205 sh_entsize: entsize,
206 }
207 }
208
209 pub fn bytecode(&self) -> Vec<u8> {
210 let mut bytecode = Vec::with_capacity(64); bytecode.extend_from_slice(&self.sh_name.to_le_bytes());
213 bytecode.extend_from_slice(&self.sh_type.to_le_bytes());
214 bytecode.extend_from_slice(&self.sh_flags.to_le_bytes());
215 bytecode.extend_from_slice(&self.sh_addr.to_le_bytes());
216 bytecode.extend_from_slice(&self.sh_offset.to_le_bytes());
217 bytecode.extend_from_slice(&self.sh_size.to_le_bytes());
218 bytecode.extend_from_slice(&self.sh_link.to_le_bytes());
219 bytecode.extend_from_slice(&self.sh_info.to_le_bytes());
220 bytecode.extend_from_slice(&self.sh_addralign.to_le_bytes());
221 bytecode.extend_from_slice(&self.sh_entsize.to_le_bytes());
222
223 bytecode
224 }
225}