1#![allow(non_camel_case_types, dead_code)]
7
8use std::io::Read;
9
10use anyhow::{bail, Result};
11use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
12
13pub(super) enum Endianness {
14 Little,
15 Big,
16}
17
18impl Endianness {
19 fn u16_from_reader<R: Read>(&self, reader: &mut R) -> Result<u16, std::io::Error> {
20 match &self {
21 Endianness::Little => reader.read_u16::<LittleEndian>(),
22 Endianness::Big => reader.read_u16::<BigEndian>(),
23 }
24 }
25
26 fn u32_from_reader<R: Read>(&self, reader: &mut R) -> Result<u32, std::io::Error> {
27 match &self {
28 Endianness::Little => reader.read_u32::<LittleEndian>(),
29 Endianness::Big => reader.read_u32::<BigEndian>(),
30 }
31 }
32
33 fn i32_from_reader<R: Read>(&self, reader: &mut R) -> Result<i32, std::io::Error> {
34 match &self {
35 Endianness::Little => reader.read_i32::<LittleEndian>(),
36 Endianness::Big => reader.read_i32::<BigEndian>(),
37 }
38 }
39}
40
41#[derive(Clone, Copy, Debug)]
42#[repr(C, packed)]
43pub(super) struct btf_header {
44 pub(super) magic: u16,
45 pub(super) version: u8,
46 pub(super) flags: u8,
47 pub(super) hdr_len: u32,
48 pub(super) type_off: u32,
49 pub(super) type_len: u32,
50 pub(super) str_off: u32,
51 pub(super) str_len: u32,
52}
53
54impl btf_header {
55 pub(super) fn from_reader<R: Read>(reader: &mut R) -> Result<(btf_header, Endianness)> {
56 let magic = reader.read_u16::<LittleEndian>()?;
57 #[allow(clippy::mixed_case_hex_literals)]
58 let endianness = match magic {
59 0xeB9F => Endianness::Little,
60 0x9FeB => Endianness::Big,
61 magic => bail!("Invalid BTF magic: {:#x}", magic),
62 };
63
64 Ok((
65 btf_header {
66 magic,
67 version: reader.read_u8()?,
68 flags: reader.read_u8()?,
69 hdr_len: endianness.u32_from_reader(reader)?,
70 type_off: endianness.u32_from_reader(reader)?,
71 type_len: endianness.u32_from_reader(reader)?,
72 str_off: endianness.u32_from_reader(reader)?,
73 str_len: endianness.u32_from_reader(reader)?,
74 },
75 endianness,
76 ))
77 }
78}
79
80#[derive(Clone, Copy, Debug)]
81#[repr(C, packed)]
82pub(super) struct btf_type {
83 pub(super) name_off: u32,
84 info: u32,
90 size_type: u32,
95}
96
97impl btf_type {
98 pub(super) fn from_reader<R: Read>(
99 reader: &mut R,
100 endianness: &Endianness,
101 ) -> Result<btf_type> {
102 Ok(btf_type {
103 name_off: endianness.u32_from_reader(reader)?,
104 info: endianness.u32_from_reader(reader)?,
105 size_type: endianness.u32_from_reader(reader)?,
106 })
107 }
108
109 pub(super) fn vlen(&self) -> u32 {
110 self.info & 0xffff
111 }
112
113 pub(super) fn kind(&self) -> u32 {
114 (self.info >> 24) & 0x1f
115 }
116
117 pub(super) fn kind_flag(&self) -> u32 {
118 (self.info >> 31) & 0x1
119 }
120
121 pub(super) fn size(&self) -> usize {
122 self.size_type as usize
123 }
124
125 pub(super) fn r#type(&self) -> u32 {
126 self.size_type
127 }
128}
129
130#[derive(Clone, Copy, Debug)]
131#[repr(C, packed)]
132pub(super) struct btf_int {
133 data: u32,
134}
135
136impl btf_int {
137 pub(super) fn from_reader<R: Read>(reader: &mut R, endianness: &Endianness) -> Result<btf_int> {
138 Ok(btf_int {
139 data: endianness.u32_from_reader(reader)?,
140 })
141 }
142
143 pub(super) fn encoding(&self) -> u32 {
144 (self.data & 0x0f000000) >> 24
145 }
146
147 pub(super) fn offset(&self) -> u32 {
148 (self.data & 0x00ff0000) >> 16
149 }
150
151 pub(super) fn bits(&self) -> u32 {
152 self.data & 0x000000ff
153 }
154}
155
156pub(super) const BTF_INT_SIGNED: u32 = 1 << 0;
157pub(super) const BTF_INT_CHAR: u32 = 1 << 1;
158pub(super) const BTF_INT_BOOL: u32 = 1 << 2;
159
160#[derive(Clone, Copy, Debug)]
161#[repr(C, packed)]
162pub(super) struct btf_array {
163 pub(super) r#type: u32,
164 pub(super) index_type: u32,
165 pub(super) nelems: u32,
166}
167
168impl btf_array {
169 pub(super) fn from_reader<R: Read>(
170 reader: &mut R,
171 endianness: &Endianness,
172 ) -> Result<btf_array> {
173 Ok(btf_array {
174 r#type: endianness.u32_from_reader(reader)?,
175 index_type: endianness.u32_from_reader(reader)?,
176 nelems: endianness.u32_from_reader(reader)?,
177 })
178 }
179}
180
181#[derive(Clone, Copy, Debug)]
182#[repr(C, packed)]
183pub(super) struct btf_member {
184 pub(super) name_off: u32,
185 pub(super) r#type: u32,
186 pub(super) offset: u32,
187}
188
189impl btf_member {
190 pub(super) fn from_reader<R: Read>(
191 reader: &mut R,
192 endianness: &Endianness,
193 ) -> Result<btf_member> {
194 Ok(btf_member {
195 name_off: endianness.u32_from_reader(reader)?,
196 r#type: endianness.u32_from_reader(reader)?,
197 offset: endianness.u32_from_reader(reader)?,
198 })
199 }
200}
201
202#[derive(Clone, Copy, Debug)]
203#[repr(C, packed)]
204pub(super) struct btf_enum {
205 pub(super) name_off: u32,
206 pub(super) val: u32,
207}
208
209impl btf_enum {
210 pub(super) fn from_reader<R: Read>(
211 reader: &mut R,
212 endianness: &Endianness,
213 ) -> Result<btf_enum> {
214 Ok(btf_enum {
215 name_off: endianness.u32_from_reader(reader)?,
216 val: endianness.u32_from_reader(reader)?,
217 })
218 }
219}
220
221pub(super) const BTF_FUNC_STATIC: u32 = 0;
222pub(super) const BTF_FUNC_GLOBAL: u32 = 1;
223pub(super) const BTF_FUNC_EXTERN: u32 = 2;
224
225#[derive(Clone, Copy, Debug)]
226#[repr(C, packed)]
227pub(super) struct btf_param {
228 pub(super) name_off: u32,
229 pub(super) r#type: u32,
230}
231
232impl btf_param {
233 pub(super) fn from_reader<R: Read>(
234 reader: &mut R,
235 endianness: &Endianness,
236 ) -> Result<btf_param> {
237 Ok(btf_param {
238 name_off: endianness.u32_from_reader(reader)?,
239 r#type: endianness.u32_from_reader(reader)?,
240 })
241 }
242}
243
244#[derive(Clone, Copy, Debug)]
245#[repr(C, packed)]
246pub(super) struct btf_var {
247 pub(super) linkage: u32,
248}
249
250impl btf_var {
251 pub(super) fn from_reader<R: Read>(reader: &mut R, endianness: &Endianness) -> Result<btf_var> {
252 Ok(btf_var {
253 linkage: endianness.u32_from_reader(reader)?,
254 })
255 }
256}
257
258#[derive(Clone, Copy, Debug)]
259#[repr(C, packed)]
260pub(super) struct btf_var_secinfo {
261 pub(super) r#type: u32,
262 pub(super) offset: u32,
263 pub(super) size: u32,
264}
265
266impl btf_var_secinfo {
267 pub(super) fn from_reader<R: Read>(
268 reader: &mut R,
269 endianness: &Endianness,
270 ) -> Result<btf_var_secinfo> {
271 Ok(btf_var_secinfo {
272 r#type: endianness.u32_from_reader(reader)?,
273 offset: endianness.u32_from_reader(reader)?,
274 size: endianness.u32_from_reader(reader)?,
275 })
276 }
277}
278
279#[derive(Clone, Copy, Debug)]
280#[repr(C, packed)]
281pub(super) struct btf_decl_tag {
282 pub(super) component_idx: i32,
283}
284
285impl btf_decl_tag {
286 pub(super) fn from_reader<R: Read>(
287 reader: &mut R,
288 endianness: &Endianness,
289 ) -> Result<btf_decl_tag> {
290 Ok(btf_decl_tag {
291 component_idx: endianness.i32_from_reader(reader)?,
292 })
293 }
294}
295
296#[derive(Clone, Copy, Debug)]
297#[repr(C, packed)]
298pub(super) struct btf_enum64 {
299 pub(super) name_off: u32,
300 pub(super) val_lo32: u32,
301 pub(super) val_hi32: u32,
302}
303
304impl btf_enum64 {
305 pub(super) fn from_reader<R: Read>(
306 reader: &mut R,
307 endianness: &Endianness,
308 ) -> Result<btf_enum64> {
309 Ok(btf_enum64 {
310 name_off: endianness.u32_from_reader(reader)?,
311 val_lo32: endianness.u32_from_reader(reader)?,
312 val_hi32: endianness.u32_from_reader(reader)?,
313 })
314 }
315}