sbpf_disassembler/
program_header.rs1use std::{fmt::Debug, io::Cursor};
2
3use serde::{Deserialize, Serialize};
4
5use crate::{cursor::ELFCursor, errors::EZBpfError};
6
7pub const PF_X: u8 = 0x01;
9pub const PF_W: u8 = 0x02;
10pub const PF_R: u8 = 0x04;
11
12#[allow(non_camel_case_types)]
13#[derive(Debug, Clone, Serialize, Deserialize)]
14#[repr(u32)]
15pub enum ProgramType {
16 PT_NULL = 0x00, PT_LOAD = 0x01, PT_DYNAMIC = 0x02, PT_INTERP = 0x03, PT_NOTE = 0x04, PT_SHLIB = 0x05, PT_PHDR = 0x06, PT_TLS = 0x07, }
25
26impl TryFrom<u32> for ProgramType {
27 type Error = EZBpfError;
28
29 fn try_from(value: u32) -> Result<Self, Self::Error> {
30 Ok(match value {
31 0 => Self::PT_NULL,
32 1 => Self::PT_LOAD,
33 2 => Self::PT_DYNAMIC,
34 3 => Self::PT_INTERP,
35 4 => Self::PT_NOTE,
36 5 => Self::PT_SHLIB,
37 6 => Self::PT_PHDR,
38 7 => Self::PT_TLS,
39 _ => return Err(EZBpfError::InvalidProgramType),
40 })
41 }
42}
43
44impl From<ProgramType> for u32 {
45 fn from(val: ProgramType) -> Self {
46 match val {
47 ProgramType::PT_NULL => 0,
48 ProgramType::PT_LOAD => 1,
49 ProgramType::PT_DYNAMIC => 2,
50 ProgramType::PT_INTERP => 3,
51 ProgramType::PT_NOTE => 4,
52 ProgramType::PT_SHLIB => 5,
53 ProgramType::PT_PHDR => 6,
54 ProgramType::PT_TLS => 7,
55 }
56 }
57}
58
59impl From<ProgramType> for &str {
60 fn from(val: ProgramType) -> Self {
61 match val {
62 ProgramType::PT_NULL => "PT_NULL",
63 ProgramType::PT_LOAD => "PT_LOAD",
64 ProgramType::PT_DYNAMIC => "PT_DYNAMIC",
65 ProgramType::PT_INTERP => "PT_INTERP",
66 ProgramType::PT_NOTE => "PT_NOTE",
67 ProgramType::PT_SHLIB => "PT_SHLIB",
68 ProgramType::PT_PHDR => "PT_PHDR",
69 ProgramType::PT_TLS => "PT_TLS",
70 }
71 }
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct ProgramFlags(pub u32);
76
77impl From<u32> for ProgramFlags {
78 fn from(value: u32) -> Self {
79 Self(value & 7)
80 }
81}
82
83impl std::fmt::Display for ProgramFlags {
84 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 let x = match self.0 & PF_X as u32 == PF_X as u32 {
86 true => "X",
87 false => "*",
88 };
89
90 let r = match self.0 & PF_R as u32 == PF_R as u32 {
91 true => "R",
92 false => "*",
93 };
94
95 let w = match self.0 & PF_W as u32 == PF_W as u32 {
96 true => "W",
97 false => "*",
98 };
99 f.write_str(&format!("{}/{}/{}", r, w, x))
100 }
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct ProgramHeader {
105 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, }
114
115impl ProgramHeader {
116 pub fn from_bytes(b: &[u8]) -> Result<Self, EZBpfError> {
117 let mut c = Cursor::new(b);
118 c.read_program_header()
119 }
120
121 pub fn to_bytes(&self) -> Vec<u8> {
122 let mut b = (self.p_type.clone() as u32).to_le_bytes().to_vec();
123 b.extend_from_slice(&self.p_flags.0.to_le_bytes());
124 b.extend_from_slice(&self.p_offset.to_le_bytes());
125 b.extend_from_slice(&self.p_vaddr.to_le_bytes());
126 b.extend_from_slice(&self.p_paddr.to_le_bytes());
127 b.extend_from_slice(&self.p_filesz.to_le_bytes());
128 b.extend_from_slice(&self.p_memsz.to_le_bytes());
129 b.extend_from_slice(&self.p_align.to_le_bytes());
130 b
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use hex_literal::hex;
137
138 use crate::program_header::ProgramHeader;
139
140 #[test]
141 fn serialize_e2e() {
142 let b = hex!(
143 "0100000005000000780000000000000078000000000000007800000000000000080000000000000008000000000000000010000000000000"
144 );
145 let h = ProgramHeader::from_bytes(&b).unwrap();
146 assert_eq!(h.to_bytes(), &b)
147 }
148}