sbpf_disassembler/
program_header.rs1use std::fmt::Debug;
2
3use object::Endianness;
4use object::read::elf::ElfFile64;
5use serde::{Deserialize, Serialize};
6
7use crate::errors::DisassemblerError;
8
9pub const PF_X: u8 = 0x01;
11pub const PF_W: u8 = 0x02;
12pub const PF_R: u8 = 0x04;
13
14#[allow(non_camel_case_types)]
15#[derive(Debug, Clone, Serialize, Deserialize)]
16#[repr(u32)]
17pub enum ProgramType {
18 PT_NULL = 0x00, PT_LOAD = 0x01, PT_DYNAMIC = 0x02, PT_INTERP = 0x03, PT_NOTE = 0x04, PT_SHLIB = 0x05, PT_PHDR = 0x06, PT_TLS = 0x07, }
27
28impl TryFrom<u32> for ProgramType {
29 type Error = DisassemblerError;
30
31 fn try_from(value: u32) -> Result<Self, Self::Error> {
32 Ok(match value {
33 0 => Self::PT_NULL,
34 1 => Self::PT_LOAD,
35 2 => Self::PT_DYNAMIC,
36 3 => Self::PT_INTERP,
37 4 => Self::PT_NOTE,
38 5 => Self::PT_SHLIB,
39 6 => Self::PT_PHDR,
40 7 => Self::PT_TLS,
41 _ => return Err(DisassemblerError::InvalidProgramType),
42 })
43 }
44}
45
46impl From<ProgramType> for u32 {
47 fn from(val: ProgramType) -> Self {
48 match val {
49 ProgramType::PT_NULL => 0,
50 ProgramType::PT_LOAD => 1,
51 ProgramType::PT_DYNAMIC => 2,
52 ProgramType::PT_INTERP => 3,
53 ProgramType::PT_NOTE => 4,
54 ProgramType::PT_SHLIB => 5,
55 ProgramType::PT_PHDR => 6,
56 ProgramType::PT_TLS => 7,
57 }
58 }
59}
60
61impl From<ProgramType> for &str {
62 fn from(val: ProgramType) -> Self {
63 match val {
64 ProgramType::PT_NULL => "PT_NULL",
65 ProgramType::PT_LOAD => "PT_LOAD",
66 ProgramType::PT_DYNAMIC => "PT_DYNAMIC",
67 ProgramType::PT_INTERP => "PT_INTERP",
68 ProgramType::PT_NOTE => "PT_NOTE",
69 ProgramType::PT_SHLIB => "PT_SHLIB",
70 ProgramType::PT_PHDR => "PT_PHDR",
71 ProgramType::PT_TLS => "PT_TLS",
72 }
73 }
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct ProgramFlags(pub u32);
78
79impl From<u32> for ProgramFlags {
80 fn from(value: u32) -> Self {
81 Self(value & 7)
82 }
83}
84
85impl std::fmt::Display for ProgramFlags {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 let x = match self.0 & PF_X as u32 == PF_X as u32 {
88 true => "X",
89 false => "*",
90 };
91
92 let r = match self.0 & PF_R as u32 == PF_R as u32 {
93 true => "R",
94 false => "*",
95 };
96
97 let w = match self.0 & PF_W as u32 == PF_W as u32 {
98 true => "W",
99 false => "*",
100 };
101 f.write_str(&format!("{}/{}/{}", r, w, x))
102 }
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct ProgramHeader {
107 pub p_type: ProgramType, pub p_flags: ProgramFlags, pub p_offset: u64, pub p_vaddr: u64, pub p_paddr: u64, pub p_filesz: u64, pub p_memsz: u64, pub p_align: u64, }
116
117impl ProgramHeader {
118 pub fn from_elf_file(elf_file: &ElfFile64<Endianness>) -> Result<Vec<Self>, DisassemblerError> {
119 let endian = elf_file.endian();
120 let program_headers_data = elf_file.elf_program_headers();
121
122 let mut program_headers = Vec::new();
123 for ph in program_headers_data {
124 let p_type = ProgramType::try_from(ph.p_type.get(endian))?;
125 let p_flags = ProgramFlags::from(ph.p_flags.get(endian));
126 let p_offset = ph.p_offset.get(endian);
127 let p_vaddr = ph.p_vaddr.get(endian);
128 let p_paddr = ph.p_paddr.get(endian);
129 let p_filesz = ph.p_filesz.get(endian);
130 let p_memsz = ph.p_memsz.get(endian);
131 let p_align = ph.p_align.get(endian);
132
133 program_headers.push(ProgramHeader {
134 p_type,
135 p_flags,
136 p_offset,
137 p_vaddr,
138 p_paddr,
139 p_filesz,
140 p_memsz,
141 p_align,
142 });
143 }
144
145 Ok(program_headers)
146 }
147
148 pub fn to_bytes(&self) -> Vec<u8> {
149 let mut b = (self.p_type.clone() as u32).to_le_bytes().to_vec();
150 b.extend_from_slice(&self.p_flags.0.to_le_bytes());
151 b.extend_from_slice(&self.p_offset.to_le_bytes());
152 b.extend_from_slice(&self.p_vaddr.to_le_bytes());
153 b.extend_from_slice(&self.p_paddr.to_le_bytes());
154 b.extend_from_slice(&self.p_filesz.to_le_bytes());
155 b.extend_from_slice(&self.p_memsz.to_le_bytes());
156 b.extend_from_slice(&self.p_align.to_le_bytes());
157 b
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 use hex_literal::hex;
164
165 use crate::program::Program;
166
167 #[test]
168 fn test_program_headers() {
169 let original_bytes = hex!(
170 "7F454C460201010000000000000000000300F700010000002001000000000000400000000000000028020000000000000000000040003800030040000600050001000000050000002001000000000000200100000000000020010000000000003000000000000000300000000000000000100000000000000100000004000000C001000000000000C001000000000000C0010000000000003C000000000000003C000000000000000010000000000000020000000600000050010000000000005001000000000000500100000000000070000000000000007000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007912A000000000007911182900000000B7000000010000002D21010000000000B70000000000000095000000000000001E0000000000000004000000000000000600000000000000C0010000000000000B0000000000000018000000000000000500000000000000F0010000000000000A000000000000000C00000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000120001002001000000000000300000000000000000656E747279706F696E7400002E74657874002E64796E737472002E64796E73796D002E64796E616D6963002E73687374727461620000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000600000000000000200100000000000020010000000000003000000000000000000000000000000008000000000000000000000000000000170000000600000003000000000000005001000000000000500100000000000070000000000000000400000000000000080000000000000010000000000000000F0000000B0000000200000000000000C001000000000000C001000000000000300000000000000004000000010000000800000000000000180000000000000007000000030000000200000000000000F001000000000000F0010000000000000C00000000000000000000000000000001000000000000000000000000000000200000000300000000000000000000000000000000000000FC010000000000002A00000000000000000000000000000001000000000000000000000000000000"
171 );
172 let program = Program::from_bytes(&original_bytes).unwrap();
173
174 assert_eq!(program.program_headers.len(), 3);
176
177 for (i, program_header) in program.program_headers.iter().enumerate() {
179 let serialized = program_header.to_bytes();
180 let header_offset = 0x40 + (i * 56);
181 let original_header_bytes = &original_bytes[header_offset..header_offset + 56];
182 assert_eq!(serialized, original_header_bytes,);
183 }
184 }
185}