1use alloc::{string::String, vec, vec::Vec};
2
3use bytes::BufMut;
4use object::Endianness;
5
6use crate::{
7 generated::{bpf_func_info, bpf_line_info},
8 relocation::INS_SIZE,
9 util::{bytes_of, HashMap},
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 ) -> FuncSecInfo {
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 FuncSecInfo {
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 pub fn len(&self) -> usize {
87 self.func_info.len()
88 }
89}
90
91#[derive(Debug, Clone)]
97pub struct FuncInfo {
98 pub data: HashMap<String, FuncSecInfo>,
100}
101
102impl FuncInfo {
103 pub(crate) fn new() -> FuncInfo {
104 FuncInfo {
105 data: HashMap::new(),
106 }
107 }
108
109 pub(crate) fn get(&self, name: &str) -> FuncSecInfo {
110 match self.data.get(name) {
111 Some(d) => d.clone(),
112 None => FuncSecInfo::default(),
113 }
114 }
115}
116
117#[derive(Debug, Clone, Default)]
123pub struct LineSecInfo {
124 pub(crate) _sec_name_offset: u32,
126 pub num_info: u32,
128 pub line_info: Vec<bpf_line_info>,
131}
132
133impl LineSecInfo {
134 pub(crate) fn parse(
135 sec_name_offset: u32,
136 num_info: u32,
137 rec_size: usize,
138 func_info_data: &[u8],
139 endianness: Endianness,
140 ) -> LineSecInfo {
141 let line_info = func_info_data
142 .chunks(rec_size)
143 .map(|data| {
144 let read_u32 = if endianness == Endianness::Little {
145 u32::from_le_bytes
146 } else {
147 u32::from_be_bytes
148 };
149
150 let mut offset = 0;
151
152 let insn_off =
156 read_u32(data[offset..offset + 4].try_into().unwrap()) / INS_SIZE as u32;
157 offset += 4;
158 let file_name_off = read_u32(data[offset..offset + 4].try_into().unwrap());
159 offset += 4;
160 let line_off = read_u32(data[offset..offset + 4].try_into().unwrap());
161 offset += 4;
162 let line_col = read_u32(data[offset..offset + 4].try_into().unwrap());
163
164 bpf_line_info {
165 insn_off,
166 file_name_off,
167 line_off,
168 line_col,
169 }
170 })
171 .collect();
172
173 LineSecInfo {
174 _sec_name_offset: sec_name_offset,
175 num_info,
176 line_info,
177 }
178 }
179
180 pub fn line_info_bytes(&self) -> Vec<u8> {
182 let mut buf = vec![];
183 for l in &self.line_info {
184 buf.put(unsafe { bytes_of::<bpf_line_info>(l) })
186 }
187 buf
188 }
189
190 pub fn len(&self) -> usize {
192 self.line_info.len()
193 }
194}
195
196#[derive(Debug, Clone)]
197pub(crate) struct LineInfo {
198 pub data: HashMap<String, LineSecInfo>,
199}
200
201impl LineInfo {
202 pub(crate) fn new() -> LineInfo {
203 LineInfo {
204 data: HashMap::new(),
205 }
206 }
207
208 pub(crate) fn get(&self, name: &str) -> LineSecInfo {
209 match self.data.get(name) {
210 Some(d) => d.clone(),
211 None => LineSecInfo::default(),
212 }
213 }
214}