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