1use alloc::{string::String, vec, vec::Vec};
2
3use bytes::BufMut as _;
4use object::Endianness;
5
6use crate::{
7 generated::{bpf_func_info, bpf_line_info},
8 relocation::INS_SIZE,
9 util::{HashMap, bytes_of},
10};
11
12#[derive(Debug, Clone, Default)]
29pub struct FuncSecInfo {
30 pub(crate) _sec_name_offset: u32,
31 pub num_info: u32,
33 pub func_info: Vec<bpf_func_info>,
35}
36
37impl FuncSecInfo {
38 pub(crate) fn parse(
39 sec_name_offset: u32,
40 num_info: u32,
41 rec_size: usize,
42 func_info_data: &[u8],
43 endianness: Endianness,
44 ) -> Self {
45 let func_info = func_info_data
46 .chunks(rec_size)
47 .map(|data| {
48 let read_u32 = if endianness == Endianness::Little {
49 u32::from_le_bytes
50 } else {
51 u32::from_be_bytes
52 };
53
54 let mut offset = 0;
55
56 let insn_off =
60 read_u32(data[offset..offset + 4].try_into().unwrap()) / INS_SIZE as u32;
61 offset += 4;
62 let type_id = read_u32(data[offset..offset + 4].try_into().unwrap());
63
64 bpf_func_info { insn_off, type_id }
65 })
66 .collect();
67
68 Self {
69 _sec_name_offset: sec_name_offset,
70 num_info,
71 func_info,
72 }
73 }
74
75 pub fn func_info_bytes(&self) -> Vec<u8> {
77 let mut buf = vec![];
78 for l in &self.func_info {
79 buf.put(unsafe { bytes_of::<bpf_func_info>(l) })
81 }
82 buf
83 }
84
85 #[expect(clippy::len_without_is_empty)]
87 pub fn len(&self) -> usize {
88 self.func_info.len()
89 }
90}
91
92#[derive(Debug, Clone)]
98pub struct FuncInfo {
99 pub data: HashMap<String, FuncSecInfo>,
101}
102
103impl FuncInfo {
104 pub(crate) fn new() -> Self {
105 Self {
106 data: HashMap::new(),
107 }
108 }
109
110 pub(crate) fn get(&self, name: &str) -> FuncSecInfo {
111 match self.data.get(name) {
112 Some(d) => d.clone(),
113 None => FuncSecInfo::default(),
114 }
115 }
116}
117
118#[derive(Debug, Clone, Default)]
124pub struct LineSecInfo {
125 pub(crate) _sec_name_offset: u32,
127 pub num_info: u32,
129 pub line_info: Vec<bpf_line_info>,
132}
133
134impl LineSecInfo {
135 pub(crate) fn parse(
136 sec_name_offset: u32,
137 num_info: u32,
138 rec_size: usize,
139 func_info_data: &[u8],
140 endianness: Endianness,
141 ) -> Self {
142 let line_info = func_info_data
143 .chunks(rec_size)
144 .map(|data| {
145 let read_u32 = if endianness == Endianness::Little {
146 u32::from_le_bytes
147 } else {
148 u32::from_be_bytes
149 };
150
151 let mut offset = 0;
152
153 let insn_off =
157 read_u32(data[offset..offset + 4].try_into().unwrap()) / INS_SIZE as u32;
158 offset += 4;
159 let file_name_off = read_u32(data[offset..offset + 4].try_into().unwrap());
160 offset += 4;
161 let line_off = read_u32(data[offset..offset + 4].try_into().unwrap());
162 offset += 4;
163 let line_col = read_u32(data[offset..offset + 4].try_into().unwrap());
164
165 bpf_line_info {
166 insn_off,
167 file_name_off,
168 line_off,
169 line_col,
170 }
171 })
172 .collect();
173
174 Self {
175 _sec_name_offset: sec_name_offset,
176 num_info,
177 line_info,
178 }
179 }
180
181 pub fn line_info_bytes(&self) -> Vec<u8> {
183 let mut buf = vec![];
184 for l in &self.line_info {
185 buf.put(unsafe { bytes_of::<bpf_line_info>(l) })
187 }
188 buf
189 }
190
191 #[expect(clippy::len_without_is_empty)]
193 pub fn len(&self) -> usize {
194 self.line_info.len()
195 }
196}
197
198#[derive(Debug, Clone)]
199pub(crate) struct LineInfo {
200 pub data: HashMap<String, LineSecInfo>,
201}
202
203impl LineInfo {
204 pub(crate) fn new() -> Self {
205 Self {
206 data: HashMap::new(),
207 }
208 }
209
210 pub(crate) fn get(&self, name: &str) -> LineSecInfo {
211 match self.data.get(name) {
212 Some(d) => d.clone(),
213 None => LineSecInfo::default(),
214 }
215 }
216}