1use std::cmp::{max, min};
2use std::ffi::{c_char, CStr};
3use std::fmt;
4use std::mem::size_of;
5
6use object::{Object, ObjectSection};
7use scroll::Pread;
8use scroll_derive::{IOread, IOwrite, Pread as DerivePread, Pwrite, SizeWith};
9
10use crate::{btf_error, BtfError, BtfResult};
11
12pub const BTF_ELF_SEC: &str = ".BTF";
13pub const BTF_EXT_ELF_SEC: &str = ".BTF.ext";
14
15pub const BTF_MAGIC: u16 = 0xeB9F;
16pub const BTF_VERSION: u8 = 1;
17
18pub const BTF_KIND_UNKN: u32 = 0;
19pub const BTF_KIND_INT: u32 = 1;
20pub const BTF_KIND_PTR: u32 = 2;
21pub const BTF_KIND_ARRAY: u32 = 3;
22pub const BTF_KIND_STRUCT: u32 = 4;
23pub const BTF_KIND_UNION: u32 = 5;
24pub const BTF_KIND_ENUM: u32 = 6;
25pub const BTF_KIND_FWD: u32 = 7;
26pub const BTF_KIND_TYPEDEF: u32 = 8;
27pub const BTF_KIND_VOLATILE: u32 = 9;
28pub const BTF_KIND_CONST: u32 = 10;
29pub const BTF_KIND_RESTRICT: u32 = 11;
30pub const BTF_KIND_FUNC: u32 = 12;
31pub const BTF_KIND_FUNC_PROTO: u32 = 13;
32pub const BTF_KIND_VAR: u32 = 14;
33pub const BTF_KIND_DATASEC: u32 = 15;
34pub const BTF_KIND_FLOAT: u32 = 16;
35pub const BTF_KIND_DECL_TAG: u32 = 17;
36pub const BTF_KIND_TYPE_TAG: u32 = 18;
37pub const BTF_KIND_ENUM64: u32 = 19;
38pub const BTF_KIND_MAX: u32 = 19;
39pub const NR_BTF_KINDS: u32 = BTF_KIND_MAX + 1;
40
41pub const BTF_INT_SIGNED: u32 = 0b001;
42pub const BTF_INT_CHAR: u32 = 0b010;
43pub const BTF_INT_BOOL: u32 = 0b100;
44
45pub const BTF_VAR_STATIC: u32 = 0;
46pub const BTF_VAR_GLOBAL_ALLOCATED: u32 = 1;
47pub const BTF_VAR_GLOBAL_EXTERNAL: u32 = 2;
48
49pub const BTF_FUNC_STATIC: u32 = 0;
50pub const BTF_FUNC_GLOBAL: u32 = 1;
51pub const BTF_FUNC_EXTERN: u32 = 2;
52
53#[repr(C)]
54#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
55pub struct btf_header {
56 pub magic: u16,
57 pub version: u8,
58 pub flags: u8,
59 pub hdr_len: u32,
60 pub type_off: u32,
61 pub type_len: u32,
62 pub str_off: u32,
63 pub str_len: u32,
64}
65
66#[repr(C)]
67#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
68pub struct btf_type {
69 pub name_off: u32,
70 pub info: u32,
71 pub type_id: u32,
72}
73
74#[repr(C)]
75#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
76pub struct btf_enum {
77 pub name_off: u32,
78 pub val: i32,
79}
80
81#[repr(C)]
82#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
83pub struct btf_array {
84 pub val_type_id: u32,
85 pub idx_type_id: u32,
86 pub nelems: u32,
87}
88
89#[repr(C)]
90#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
91pub struct btf_member {
92 pub name_off: u32,
93 pub type_id: u32,
94 pub offset: u32,
95}
96
97#[repr(C)]
98#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
99pub struct btf_param {
100 pub name_off: u32,
101 pub type_id: u32,
102}
103
104#[repr(C)]
105#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
106pub struct btf_datasec_var {
107 pub type_id: u32,
108 pub offset: u32,
109 pub size: u32,
110}
111
112#[repr(C)]
113#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
114pub struct btf_enum64 {
115 pub name_off: u32,
116 pub val_lo32: u32,
117 pub val_hi32: u32,
118}
119
120#[repr(C)]
121#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
122pub struct btf_ext_min_header {
123 pub magic: u16,
124 pub version: u8,
125 pub flags: u8,
126 pub hdr_len: u32,
127}
128
129#[repr(C)]
130#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
131pub struct btf_ext_header_v1 {
132 pub magic: u16,
133 pub version: u8,
134 pub flags: u8,
135 pub hdr_len: u32,
136 pub func_info_off: u32,
137 pub func_info_len: u32,
138 pub line_info_off: u32,
139 pub line_info_len: u32,
140}
141
142#[repr(C)]
143#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
144pub struct btf_ext_header_v2 {
145 pub magic: u16,
146 pub version: u8,
147 pub flags: u8,
148 pub hdr_len: u32,
149 pub func_info_off: u32,
150 pub func_info_len: u32,
151 pub line_info_off: u32,
152 pub line_info_len: u32,
153 pub core_reloc_off: u32,
154 pub core_reloc_len: u32,
155}
156
157#[repr(C)]
158#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
159pub struct btf_ext_info_sec {
160 pub sec_name_off: u32,
161 pub num_info: u32,
162}
163
164#[repr(C)]
165#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
166pub struct btf_ext_func_info {
167 pub insn_off: u32,
168 pub type_id: u32,
169}
170
171#[repr(C)]
172#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
173pub struct btf_ext_line_info {
174 pub insn_off: u32,
175 pub file_name_off: u32,
176 pub line_off: u32,
177 pub line_col: u32,
178}
179
180pub const BTF_FIELD_BYTE_OFFSET: u32 = 0;
181pub const BTF_FIELD_BYTE_SIZE: u32 = 1;
182pub const BTF_FIELD_EXISTS: u32 = 2;
183pub const BTF_FIELD_SIGNED: u32 = 3;
184pub const BTF_FIELD_LSHIFT_U64: u32 = 4;
185pub const BTF_FIELD_RSHIFT_U64: u32 = 5;
186pub const BTF_TYPE_LOCAL_ID: u32 = 6;
187pub const BTF_TYPE_TARGET_ID: u32 = 7;
188pub const BTF_TYPE_EXISTS: u32 = 8;
189pub const BTF_TYPE_SIZE: u32 = 9;
190pub const BTF_ENUMVAL_EXISTS: u32 = 10;
191pub const BTF_ENUMVAL_VALUE: u32 = 11;
192pub const BTF_TYPE_MATCHES: u32 = 12;
193
194#[repr(C)]
195#[derive(Debug, Copy, Clone, DerivePread, Pwrite, IOread, IOwrite, SizeWith)]
196pub struct btf_ext_core_reloc {
197 pub insn_off: u32,
198 pub type_id: u32,
199 pub access_spec_off: u32,
200 pub kind: u32,
201}
202
203const EMPTY: &'static str = "";
204const ANON_NAME: &'static str = "<anon>";
205
206fn disp_name(s: &str) -> &str {
207 if s == "" {
208 ANON_NAME
209 } else {
210 s
211 }
212}
213
214#[derive(Debug, Copy, Clone, PartialEq)]
215pub enum BtfIntEncoding {
216 None,
217 Signed,
218 Char,
219 Bool,
220}
221
222impl fmt::Display for BtfIntEncoding {
223 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
224 match self {
225 BtfIntEncoding::None => write!(f, "none"),
226 BtfIntEncoding::Signed => write!(f, "signed"),
227 BtfIntEncoding::Char => write!(f, "char"),
228 BtfIntEncoding::Bool => write!(f, "bool"),
229 }
230 }
231}
232
233#[derive(Debug)]
234pub struct BtfInt<'a> {
235 pub name: &'a str,
236 pub bits: u32,
237 pub offset: u32,
238 pub encoding: BtfIntEncoding,
239}
240
241impl<'a> fmt::Display for BtfInt<'a> {
242 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243 write!(
244 f,
245 "<{}> '{}' bits:{} off:{}",
246 "INT",
247 disp_name(self.name),
248 self.bits,
249 self.offset
250 )?;
251 match self.encoding {
252 BtfIntEncoding::None => (),
253 _ => write!(f, " enc:{}", self.encoding)?,
254 }
255 Ok(())
256 }
257}
258
259#[derive(Debug)]
260pub struct BtfPtr {
261 pub type_id: u32,
262}
263
264impl fmt::Display for BtfPtr {
265 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
266 write!(f, "<{}> --> [{}]", "PTR", self.type_id)
267 }
268}
269
270#[derive(Debug)]
271pub struct BtfArray {
272 pub nelems: u32,
273 pub idx_type_id: u32,
274 pub val_type_id: u32,
275}
276
277impl fmt::Display for BtfArray {
278 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
279 write!(
280 f,
281 "<{}> n:{} idx-->[{}] val-->[{}]",
282 "ARRAY", self.nelems, self.idx_type_id, self.val_type_id
283 )
284 }
285}
286
287#[derive(Debug)]
288pub struct BtfMember<'a> {
289 pub name: &'a str,
290 pub type_id: u32,
291 pub bit_offset: u32,
292 pub bit_size: u8,
293}
294
295impl<'a> fmt::Display for BtfMember<'a> {
296 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
297 write!(f, "'{}' off:{}", disp_name(self.name), self.bit_offset)?;
298 if self.bit_size != 0 {
299 write!(f, " sz:{}", self.bit_size)?;
300 }
301 write!(f, " --> [{}]", self.type_id)
302 }
303}
304
305#[derive(Debug)]
306pub struct BtfComposite<'a> {
307 pub is_struct: bool,
308 pub name: &'a str,
309 pub sz: u32,
310 pub members: Vec<BtfMember<'a>>,
311}
312
313impl<'a> fmt::Display for BtfComposite<'a> {
314 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
315 write!(
316 f,
317 "<{}> '{}' sz:{} n:{}",
318 if self.is_struct { "STRUCT" } else { "UNION" },
319 disp_name(self.name),
320 self.sz,
321 self.members.len()
322 )?;
323 for i in 0..self.members.len() {
324 write!(f, "\n\t#{:02} {}", i, self.members[i])?;
325 }
326 Ok(())
327 }
328}
329
330#[derive(Debug)]
331pub struct BtfEnumValue<'a> {
332 pub name: &'a str,
333 pub value: i32,
334}
335
336impl<'a> fmt::Display for BtfEnumValue<'a> {
337 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
338 write!(f, "{} = {}", disp_name(self.name), self.value)
339 }
340}
341
342#[derive(Debug)]
343pub struct BtfEnum<'a> {
344 pub name: &'a str,
345 pub sz: u32,
346 pub values: Vec<BtfEnumValue<'a>>,
347}
348
349impl<'a> fmt::Display for BtfEnum<'a> {
350 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
351 write!(
352 f,
353 "<{}> '{}' sz:{} n:{}",
354 "ENUM",
355 disp_name(self.name),
356 self.sz,
357 self.values.len()
358 )?;
359 for i in 0..self.values.len() {
360 write!(f, "\n\t#{:02} {}", i, self.values[i])?;
361 }
362 Ok(())
363 }
364}
365
366#[derive(Debug)]
367pub struct BtfEnum64Value<'a> {
368 pub name: &'a str,
369 pub value: i64,
370}
371
372impl<'a> fmt::Display for BtfEnum64Value<'a> {
373 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
374 write!(f, "{} = {}", disp_name(self.name), self.value)
375 }
376}
377
378#[derive(Debug)]
379pub struct BtfEnum64<'a> {
380 pub name: &'a str,
381 pub sz: u32,
382 pub values: Vec<BtfEnum64Value<'a>>,
383}
384
385impl<'a> fmt::Display for BtfEnum64<'a> {
386 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
387 write!(
388 f,
389 "<{}> '{}' sz:{} n:{}",
390 "ENUM64",
391 disp_name(self.name),
392 self.sz,
393 self.values.len()
394 )?;
395 for i in 0..self.values.len() {
396 write!(f, "\n\t#{:02} {}", i, self.values[i])?;
397 }
398 Ok(())
399 }
400}
401
402#[derive(Debug, Copy, Clone, PartialEq)]
403pub enum BtfFwdKind {
404 Struct,
405 Union,
406}
407
408impl fmt::Display for BtfFwdKind {
409 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
410 match self {
411 BtfFwdKind::Struct => write!(f, "struct"),
412 BtfFwdKind::Union => write!(f, "union"),
413 }
414 }
415}
416
417#[derive(Debug)]
418pub struct BtfFwd<'a> {
419 pub name: &'a str,
420 pub kind: BtfFwdKind,
421}
422
423impl<'a> fmt::Display for BtfFwd<'a> {
424 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
425 write!(
426 f,
427 "<{}> '{}' kind:{}",
428 "FWD",
429 disp_name(self.name),
430 self.kind
431 )
432 }
433}
434
435#[derive(Debug)]
436pub struct BtfTypedef<'a> {
437 pub name: &'a str,
438 pub type_id: u32,
439}
440
441impl<'a> fmt::Display for BtfTypedef<'a> {
442 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
443 write!(
444 f,
445 "<{}> '{}' --> [{}]",
446 "TYPEDEF",
447 disp_name(self.name),
448 self.type_id
449 )
450 }
451}
452
453#[derive(Debug)]
454pub struct BtfVolatile {
455 pub type_id: u32,
456}
457
458impl fmt::Display for BtfVolatile {
459 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
460 write!(f, "<{}> --> [{}]", "VOLATILE", self.type_id)
461 }
462}
463
464#[derive(Debug)]
465pub struct BtfConst {
466 pub type_id: u32,
467}
468
469impl fmt::Display for BtfConst {
470 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
471 write!(f, "<{}> --> [{}]", "CONST", self.type_id)
472 }
473}
474
475#[derive(Debug)]
476pub struct BtfRestrict {
477 pub type_id: u32,
478}
479
480impl fmt::Display for BtfRestrict {
481 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
482 write!(f, "<{}> --> [{}]", "RESTRICT", self.type_id)
483 }
484}
485
486#[derive(Debug, Copy, Clone, PartialEq)]
487pub enum BtfFuncKind {
488 Unknown,
489 Static,
490 Global,
491 Extern,
492}
493
494impl fmt::Display for BtfFuncKind {
495 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
496 match self {
497 BtfFuncKind::Unknown => write!(f, "<unknown>"),
498 BtfFuncKind::Static => write!(f, "static"),
499 BtfFuncKind::Global => write!(f, "global"),
500 BtfFuncKind::Extern => write!(f, "extern"),
501 }
502 }
503}
504
505#[derive(Debug)]
506pub struct BtfFunc<'a> {
507 pub name: &'a str,
508 pub proto_type_id: u32,
509 pub kind: BtfFuncKind,
510}
511
512impl<'a> fmt::Display for BtfFunc<'a> {
513 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
514 write!(
515 f,
516 "<{}> '{}' --> {} [{}]",
517 "FUNC",
518 disp_name(self.name),
519 self.kind,
520 self.proto_type_id
521 )
522 }
523}
524
525#[derive(Debug)]
526pub struct BtfFuncParam<'a> {
527 pub name: &'a str,
528 pub type_id: u32,
529}
530
531impl<'a> fmt::Display for BtfFuncParam<'a> {
532 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
533 write!(f, "'{}' --> [{}]", disp_name(self.name), self.type_id)
534 }
535}
536
537#[derive(Debug)]
538pub struct BtfFuncProto<'a> {
539 pub res_type_id: u32,
540 pub params: Vec<BtfFuncParam<'a>>,
541}
542
543impl<'a> fmt::Display for BtfFuncProto<'a> {
544 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
545 write!(
546 f,
547 "<{}> r-->[{}] n:{}",
548 "FUNC_PROTO",
549 self.res_type_id,
550 self.params.len()
551 )?;
552 for i in 0..self.params.len() {
553 write!(f, "\n\t#{:02} {}", i, self.params[i])?;
554 }
555 Ok(())
556 }
557}
558
559#[derive(Debug, Copy, Clone, PartialEq)]
560pub enum BtfVarKind {
561 Static,
562 GlobalAlloc,
563 GlobalExtern,
564}
565
566impl fmt::Display for BtfVarKind {
567 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
568 match self {
569 BtfVarKind::Static => write!(f, "static"),
570 BtfVarKind::GlobalAlloc => write!(f, "global-alloc"),
571 BtfVarKind::GlobalExtern => write!(f, "global-extern"),
572 }
573 }
574}
575
576#[derive(Debug)]
577pub struct BtfVar<'a> {
578 pub name: &'a str,
579 pub type_id: u32,
580 pub kind: BtfVarKind,
581}
582
583impl<'a> fmt::Display for BtfVar<'a> {
584 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
585 write!(
586 f,
587 "<{}> '{}' kind:{} --> [{}]",
588 "VAR",
589 disp_name(self.name),
590 self.kind,
591 self.type_id
592 )
593 }
594}
595
596#[derive(Debug)]
597pub struct BtfDatasecVar {
598 pub type_id: u32,
599 pub offset: u32,
600 pub sz: u32,
601}
602
603impl fmt::Display for BtfDatasecVar {
604 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
605 write!(
606 f,
607 "off:{} sz:{} --> [{}]",
608 self.offset, self.sz, self.type_id
609 )
610 }
611}
612
613#[derive(Debug)]
614pub struct BtfDatasec<'a> {
615 pub name: &'a str,
616 pub sz: u32,
617 pub vars: Vec<BtfDatasecVar>,
618}
619
620impl<'a> fmt::Display for BtfDatasec<'a> {
621 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
622 write!(
623 f,
624 "<{}> '{}' sz:{} n:{}",
625 "DATASEC",
626 disp_name(self.name),
627 self.sz,
628 self.vars.len()
629 )?;
630 for i in 0..self.vars.len() {
631 write!(f, "\n\t#{:02} {}", i, self.vars[i])?;
632 }
633 Ok(())
634 }
635}
636
637#[derive(Debug)]
638pub struct BtfFloat<'a> {
639 pub name: &'a str,
640 pub sz: u32,
641}
642
643impl<'a> fmt::Display for BtfFloat<'a> {
644 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
645 write!(f, "<{}> '{}' sz:{}", "FLOAT", disp_name(self.name), self.sz)?;
646 Ok(())
647 }
648}
649
650#[derive(Debug)]
651pub struct BtfDeclTag<'a> {
652 pub name: &'a str,
653 pub type_id: u32,
654 pub comp_idx: u32,
655}
656
657impl<'a> fmt::Display for BtfDeclTag<'a> {
658 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
659 write!(
660 f,
661 "<{}> '{}' --> [{}] comp_idx:{}",
662 "DECL_TAG",
663 disp_name(self.name),
664 self.type_id,
665 self.comp_idx,
666 )
667 }
668}
669
670#[derive(Debug)]
671pub struct BtfTypeTag<'a> {
672 pub name: &'a str,
673 pub type_id: u32,
674}
675
676impl<'a> fmt::Display for BtfTypeTag<'a> {
677 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
678 write!(
679 f,
680 "<{}> '{}' --> [{}]",
681 "TYPE_TAG",
682 disp_name(self.name),
683 self.type_id
684 )
685 }
686}
687
688#[derive(Debug)]
689pub enum BtfType<'a> {
690 Void,
691 Int(BtfInt<'a>),
692 Ptr(BtfPtr),
693 Array(BtfArray),
694 Struct(BtfComposite<'a>),
695 Union(BtfComposite<'a>),
696 Enum(BtfEnum<'a>),
697 Fwd(BtfFwd<'a>),
698 Typedef(BtfTypedef<'a>),
699 Volatile(BtfVolatile),
700 Const(BtfConst),
701 Restrict(BtfRestrict),
702 Func(BtfFunc<'a>),
703 FuncProto(BtfFuncProto<'a>),
704 Var(BtfVar<'a>),
705 Datasec(BtfDatasec<'a>),
706 Float(BtfFloat<'a>),
707 DeclTag(BtfDeclTag<'a>),
708 TypeTag(BtfTypeTag<'a>),
709 Enum64(BtfEnum64<'a>),
710}
711
712impl<'a> fmt::Display for BtfType<'a> {
713 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
714 match self {
715 BtfType::Void => write!(f, "<{}>", "VOID"),
716 BtfType::Int(t) => t.fmt(f),
717 BtfType::Ptr(t) => t.fmt(f),
718 BtfType::Array(t) => t.fmt(f),
719 BtfType::Struct(t) => t.fmt(f),
720 BtfType::Union(t) => t.fmt(f),
721 BtfType::Enum(t) => t.fmt(f),
722 BtfType::Fwd(t) => t.fmt(f),
723 BtfType::Typedef(t) => t.fmt(f),
724 BtfType::Volatile(t) => t.fmt(f),
725 BtfType::Const(t) => t.fmt(f),
726 BtfType::Restrict(t) => t.fmt(f),
727 BtfType::Func(t) => t.fmt(f),
728 BtfType::FuncProto(t) => t.fmt(f),
729 BtfType::Var(t) => t.fmt(f),
730 BtfType::Datasec(t) => t.fmt(f),
731 BtfType::Float(t) => t.fmt(f),
732 BtfType::DeclTag(t) => t.fmt(f),
733 BtfType::TypeTag(t) => t.fmt(f),
734 BtfType::Enum64(t) => t.fmt(f),
735 }
736 }
737}
738
739impl<'a> BtfType<'a> {
740 pub fn kind(&self) -> BtfKind {
741 match self {
742 BtfType::Void => BtfKind::Void,
743 BtfType::Int(_) => BtfKind::Int,
744 BtfType::Ptr(_) => BtfKind::Ptr,
745 BtfType::Array(_) => BtfKind::Array,
746 BtfType::Struct(_) => BtfKind::Struct,
747 BtfType::Union(_) => BtfKind::Union,
748 BtfType::Enum(_) => BtfKind::Enum,
749 BtfType::Fwd(_) => BtfKind::Fwd,
750 BtfType::Typedef(_) => BtfKind::Typedef,
751 BtfType::Volatile(_) => BtfKind::Volatile,
752 BtfType::Const(_) => BtfKind::Const,
753 BtfType::Restrict(_) => BtfKind::Restrict,
754 BtfType::Func(_) => BtfKind::Func,
755 BtfType::FuncProto(_) => BtfKind::FuncProto,
756 BtfType::Var(_) => BtfKind::Var,
757 BtfType::Datasec(_) => BtfKind::Datasec,
758 BtfType::Float(_) => BtfKind::Float,
759 BtfType::DeclTag(_) => BtfKind::DeclTag,
760 BtfType::TypeTag(_) => BtfKind::TypeTag,
761 BtfType::Enum64(_) => BtfKind::Enum64,
762 }
763 }
764
765 pub fn name(&self) -> &str {
766 match self {
767 BtfType::Void => EMPTY,
768 BtfType::Int(t) => &t.name,
769 BtfType::Ptr(_) => EMPTY,
770 BtfType::Array(_) => EMPTY,
771 BtfType::Struct(t) => &t.name,
772 BtfType::Union(t) => &t.name,
773 BtfType::Enum(t) => &t.name,
774 BtfType::Fwd(t) => &t.name,
775 BtfType::Typedef(t) => &t.name,
776 BtfType::Volatile(_) => EMPTY,
777 BtfType::Const(_) => EMPTY,
778 BtfType::Restrict(_) => EMPTY,
779 BtfType::Func(t) => &t.name,
780 BtfType::FuncProto(_) => EMPTY,
781 BtfType::Var(t) => &t.name,
782 BtfType::Datasec(t) => &t.name,
783 BtfType::Float(t) => &t.name,
784 BtfType::DeclTag(t) => &t.name,
785 BtfType::TypeTag(t) => &t.name,
786 BtfType::Enum64(t) => &t.name,
787 }
788 }
789}
790
791#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
792pub enum BtfKind {
793 Void,
794 Int,
795 Ptr,
796 Array,
797 Struct,
798 Union,
799 Enum,
800 Fwd,
801 Typedef,
802 Volatile,
803 Const,
804 Restrict,
805 Func,
806 FuncProto,
807 Var,
808 Datasec,
809 Float,
810 DeclTag,
811 TypeTag,
812 Enum64,
813}
814
815impl std::str::FromStr for BtfKind {
816 type Err = BtfError;
817
818 fn from_str(s: &str) -> Result<Self, Self::Err> {
819 match s {
820 "void" => Ok(BtfKind::Void),
821 "int" | "i" => Ok(BtfKind::Int),
822 "ptr" | "p" => Ok(BtfKind::Ptr),
823 "array" | "arr" | "a" => Ok(BtfKind::Array),
824 "struct" | "s" => Ok(BtfKind::Struct),
825 "union" | "u" => Ok(BtfKind::Union),
826 "enum" | "e" => Ok(BtfKind::Enum),
827 "fwd" => Ok(BtfKind::Fwd),
828 "typedef" | "t" => Ok(BtfKind::Typedef),
829 "volatile" => Ok(BtfKind::Volatile),
830 "const" => Ok(BtfKind::Const),
831 "restrict" => Ok(BtfKind::Restrict),
832 "func_proto" | "funcproto" | "fnproto" | "fp" => Ok(BtfKind::FuncProto),
833 "func" | "fn" => Ok(BtfKind::Func),
834 "var" | "v" => Ok(BtfKind::Var),
835 "datasec" => Ok(BtfKind::Datasec),
836 "float" => Ok(BtfKind::Float),
837 "decl_tag" => Ok(BtfKind::DeclTag),
838 "type_tag" => Ok(BtfKind::TypeTag),
839 "enum64" | "e64" => Ok(BtfKind::Enum64),
840 _ => Err(BtfError::new_owned(format!(
841 "unrecognized btf kind: '{}'",
842 s
843 ))),
844 }
845 }
846}
847
848#[derive(Debug)]
849pub struct BtfExtSection<'a, T> {
850 pub name: &'a str,
851 pub rec_sz: usize,
852 pub recs: Vec<T>,
853}
854
855#[derive(Debug)]
856pub struct BtfExtFunc {
857 pub insn_off: u32,
858 pub type_id: u32,
859}
860
861impl fmt::Display for BtfExtFunc {
862 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
863 write!(
864 f,
865 "func: insn #{} --> [{}]",
866 self.insn_off / 8,
867 self.type_id
868 )
869 }
870}
871
872#[derive(Debug)]
873pub struct BtfExtLine<'a> {
874 pub insn_off: u32,
875 pub file_name: &'a str,
876 pub src_line: &'a str,
877 pub line_num: u32,
878 pub col_num: u32,
879}
880
881impl<'a> fmt::Display for BtfExtLine<'a> {
882 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
883 write!(
884 f,
885 "line: insn #{} --> {}:{} @ {}\n\t{}",
886 self.insn_off / 8,
887 self.line_num,
888 self.col_num,
889 self.file_name,
890 self.src_line
891 )
892 }
893}
894
895#[derive(Debug, Copy, Clone, PartialEq)]
896pub enum BtfCoreRelocKind {
897 ByteOff = 0,
898 ByteSz = 1,
899 FieldExists = 2,
900 Signed = 3,
901 LShiftU64 = 4,
902 RShiftU64 = 5,
903 LocalTypeId = 6,
904 TargetTypeId = 7,
905 TypeExists = 8,
906 TypeSize = 9,
907 EnumvalExists = 10,
908 EnumvalValue = 11,
909 TypeMatches = 12,
910}
911
912impl fmt::Display for BtfCoreRelocKind {
913 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
914 match self {
915 BtfCoreRelocKind::ByteOff => write!(f, "byte_off"),
916 BtfCoreRelocKind::ByteSz => write!(f, "byte_sz"),
917 BtfCoreRelocKind::FieldExists => write!(f, "field_exists"),
918 BtfCoreRelocKind::Signed => write!(f, "signed"),
919 BtfCoreRelocKind::LShiftU64 => write!(f, "lshift_u64"),
920 BtfCoreRelocKind::RShiftU64 => write!(f, "rshift_u64"),
921 BtfCoreRelocKind::LocalTypeId => write!(f, "local_type_id"),
922 BtfCoreRelocKind::TargetTypeId => write!(f, "target_type_id"),
923 BtfCoreRelocKind::TypeExists => write!(f, "type_exists"),
924 BtfCoreRelocKind::TypeMatches => write!(f, "type_matches"),
925 BtfCoreRelocKind::TypeSize => write!(f, "type_size"),
926 BtfCoreRelocKind::EnumvalExists => write!(f, "enumval_exists"),
927 BtfCoreRelocKind::EnumvalValue => write!(f, "enumval_value"),
928 }
929 }
930}
931
932#[derive(Debug)]
933pub struct BtfExtCoreReloc<'a> {
934 pub insn_off: u32,
935 pub type_id: u32,
936 pub access_spec_str: &'a str,
937 pub access_spec: Vec<usize>,
938 pub kind: BtfCoreRelocKind,
939}
940
941impl<'a> fmt::Display for BtfExtCoreReloc<'a> {
942 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
943 write!(
944 f,
945 "core_reloc: insn #{} --> [{}] + {}: {}",
946 self.insn_off / 8,
947 self.type_id,
948 self.access_spec_str,
949 self.kind,
950 )
951 }
952}
953
954#[derive(Debug)]
955pub struct Btf<'a> {
956 endian: scroll::Endian,
957 types: Vec<BtfType<'a>>,
958 ptr_sz: u32,
959
960 has_ext: bool,
962 func_secs: Vec<BtfExtSection<'a, BtfExtFunc>>,
963 line_secs: Vec<BtfExtSection<'a, BtfExtLine<'a>>>,
964 core_reloc_secs: Vec<BtfExtSection<'a, BtfExtCoreReloc<'a>>>,
965}
966
967impl<'a> Btf<'a> {
968 pub fn ptr_sz(&self) -> u32 {
969 self.ptr_sz
970 }
971
972 pub fn types(&self) -> &[BtfType] {
973 &self.types
974 }
975
976 pub fn type_by_id(&self, type_id: u32) -> &BtfType {
977 &self.types[type_id as usize]
978 }
979
980 pub fn type_cnt(&self) -> u32 {
981 self.types.len() as u32
982 }
983
984 pub fn has_ext(&self) -> bool {
985 self.has_ext
986 }
987
988 pub fn func_secs(&self) -> &[BtfExtSection<BtfExtFunc>] {
989 &self.func_secs
990 }
991
992 pub fn line_secs(&self) -> &[BtfExtSection<BtfExtLine>] {
993 &self.line_secs
994 }
995
996 pub fn core_reloc_secs(&self) -> &[BtfExtSection<BtfExtCoreReloc>] {
997 &self.core_reloc_secs
998 }
999
1000 pub fn get_size_of(&self, type_id: u32) -> u32 {
1001 match self.type_by_id(type_id) {
1002 BtfType::Void => 0,
1003 BtfType::Int(t) => (t.bits + 7) / 8,
1004 BtfType::Volatile(t) => self.get_size_of(t.type_id),
1005 BtfType::Const(t) => self.get_size_of(t.type_id),
1006 BtfType::Restrict(t) => self.get_size_of(t.type_id),
1007 BtfType::Ptr(_) => self.ptr_sz,
1008 BtfType::Array(t) => t.nelems * self.get_size_of(t.val_type_id),
1009 BtfType::FuncProto(_) => 0,
1010 BtfType::Struct(t) => t.sz,
1011 BtfType::Union(t) => t.sz,
1012 BtfType::Enum(t) => t.sz,
1013 BtfType::Fwd(_) => 0,
1014 BtfType::Typedef(t) => self.get_size_of(t.type_id),
1015 BtfType::Func(_) => 0,
1016 BtfType::Var(_) => 0,
1017 BtfType::Datasec(t) => t.sz,
1018 BtfType::Float(t) => t.sz,
1019 BtfType::DeclTag(t) => self.get_size_of(t.type_id),
1020 BtfType::TypeTag(t) => self.get_size_of(t.type_id),
1021 BtfType::Enum64(t) => t.sz,
1022 }
1023 }
1024
1025 pub fn get_align_of(&self, type_id: u32) -> u32 {
1026 match self.type_by_id(type_id) {
1027 BtfType::Void => 0,
1028 BtfType::Int(t) => min(self.ptr_sz, (t.bits + 7) / 8),
1029 BtfType::Volatile(t) => self.get_align_of(t.type_id),
1030 BtfType::Const(t) => self.get_align_of(t.type_id),
1031 BtfType::Restrict(t) => self.get_align_of(t.type_id),
1032 BtfType::Ptr(_) => self.ptr_sz,
1033 BtfType::Array(t) => self.get_align_of(t.val_type_id),
1034 BtfType::FuncProto(_) => 0,
1035 BtfType::Struct(t) => {
1036 let mut align = 1;
1037 for m in &t.members {
1038 align = max(align, self.get_align_of(m.type_id));
1039 }
1040 align
1041 }
1042 BtfType::Union(t) => {
1043 let mut align = 1;
1044 for m in &t.members {
1045 align = max(align, self.get_align_of(m.type_id));
1046 }
1047 align
1048 }
1049 BtfType::Enum(t) => min(self.ptr_sz, t.sz),
1050 BtfType::Fwd(_) => 0,
1051 BtfType::Typedef(t) => self.get_align_of(t.type_id),
1052 BtfType::Func(_) => 0,
1053 BtfType::Var(_) => 0,
1054 BtfType::Datasec(_) => 0,
1055 BtfType::Float(t) => min(self.ptr_sz, t.sz),
1056 BtfType::DeclTag(_) => 0,
1057 BtfType::TypeTag(t) => self.get_align_of(t.type_id),
1058 BtfType::Enum64(t) => min(self.ptr_sz, t.sz),
1059 }
1060 }
1061
1062 pub fn skip_mods(&self, mut type_id: u32) -> u32 {
1063 loop {
1064 match self.type_by_id(type_id) {
1065 BtfType::Volatile(t) => type_id = t.type_id,
1066 BtfType::Const(t) => type_id = t.type_id,
1067 BtfType::Restrict(t) => type_id = t.type_id,
1068 BtfType::TypeTag(t) => type_id = t.type_id,
1069 _ => return type_id,
1070 }
1071 }
1072 }
1073
1074 pub fn skip_mods_and_typedefs(&self, mut type_id: u32) -> u32 {
1075 loop {
1076 match self.type_by_id(type_id) {
1077 BtfType::Volatile(t) => type_id = t.type_id,
1078 BtfType::Const(t) => type_id = t.type_id,
1079 BtfType::Restrict(t) => type_id = t.type_id,
1080 BtfType::Typedef(t) => type_id = t.type_id,
1081 BtfType::TypeTag(t) => type_id = t.type_id,
1082 _ => return type_id,
1083 }
1084 }
1085 }
1086
1087 pub fn load(elf: &object::File<'a>) -> BtfResult<Btf<'a>> {
1088 let endian = if elf.is_little_endian() {
1089 scroll::LE
1090 } else {
1091 scroll::BE
1092 };
1093 let mut btf = Btf::<'a> {
1094 endian: endian,
1095 ptr_sz: if elf.is_64() { 8 } else { 4 },
1096 types: vec![BtfType::Void],
1097 has_ext: false,
1098 func_secs: Vec::new(),
1099 line_secs: Vec::new(),
1100 core_reloc_secs: Vec::new(),
1101 };
1102
1103 let btf_section = elf
1104 .section_by_name(BTF_ELF_SEC)
1105 .ok_or_else(|| Box::new(BtfError::new("No .BTF section found!")))?;
1106 let data = match btf_section.data() {
1107 Ok(d) => d,
1108 _ => panic!("expected borrowed data"),
1109 };
1110 let hdr = data.pread_with::<btf_header>(0, endian)?;
1111 if hdr.magic != BTF_MAGIC {
1112 return btf_error(format!("Invalid BTF magic: {}", hdr.magic));
1113 }
1114 if hdr.version != BTF_VERSION {
1115 return btf_error(format!(
1116 "Unsupported BTF version: {}, expect: {}",
1117 hdr.version, BTF_VERSION
1118 ));
1119 }
1120
1121 let str_off = (hdr.hdr_len + hdr.str_off) as usize;
1122 let str_data = &data[str_off..str_off + hdr.str_len as usize];
1123
1124 let type_off = (hdr.hdr_len + hdr.type_off) as usize;
1125 let type_data = &data[type_off..type_off + hdr.type_len as usize];
1126 let mut off: usize = 0;
1127 while off < hdr.type_len as usize {
1128 let t = btf.load_type(&type_data[off..], str_data)?;
1129 off += Btf::type_size(&t);
1130 btf.types.push(t);
1131 }
1132
1133 if let Some(ext_section) = elf.section_by_name(BTF_EXT_ELF_SEC) {
1134 btf.has_ext = true;
1135 let ext_data = match ext_section.data() {
1136 Ok(d) => d,
1137 _ => panic!("expected borrowed data"),
1138 };
1139 let ext_hdr = ext_data.pread_with::<btf_ext_header_v1>(0, endian)?;
1140 if ext_hdr.magic != BTF_MAGIC {
1141 return btf_error(format!("Invalid .BTF.ext magic: {}", ext_hdr.magic));
1142 }
1143 if ext_hdr.version != BTF_VERSION {
1144 return btf_error(format!(
1145 "Unsupported .BTF.ext version: {}, expect: {}",
1146 ext_hdr.version, BTF_VERSION
1147 ));
1148 }
1149 let ext_hdr2 = if ext_hdr.hdr_len >= size_of::<btf_ext_header_v2>() as u32 {
1150 Some(ext_data.pread_with::<btf_ext_header_v2>(0, endian)?)
1151 } else {
1152 None
1153 };
1154 if ext_hdr.func_info_len > 0 {
1155 let func_off = (ext_hdr.hdr_len + ext_hdr.func_info_off) as usize;
1156 let func_data = &ext_data[func_off..func_off + ext_hdr.func_info_len as usize];
1157 btf.func_secs = btf.load_func_secs(func_data, str_data)?;
1158 }
1159 if ext_hdr.line_info_len > 0 {
1160 let line_off = (ext_hdr.hdr_len + ext_hdr.line_info_off) as usize;
1161 let line_data = &ext_data[line_off..line_off + ext_hdr.line_info_len as usize];
1162 btf.line_secs = btf.load_line_secs(line_data, str_data)?;
1163 }
1164 if let Some(h) = ext_hdr2 {
1165 if h.core_reloc_len > 0 {
1166 let reloc_off = (h.hdr_len + h.core_reloc_off) as usize;
1167 let reloc_data = &ext_data[reloc_off..reloc_off + h.core_reloc_len as usize];
1168 btf.core_reloc_secs = btf.load_core_reloc_secs(reloc_data, str_data)?;
1169 }
1170 }
1171 }
1172
1173 Ok(btf)
1174 }
1175
1176 pub fn type_size(t: &BtfType) -> usize {
1177 let common = size_of::<btf_type>();
1178 match t {
1179 BtfType::Void => 0,
1180 BtfType::Ptr(_)
1181 | BtfType::Fwd(_)
1182 | BtfType::Typedef(_)
1183 | BtfType::Volatile(_)
1184 | BtfType::Const(_)
1185 | BtfType::Restrict(_)
1186 | BtfType::Func(_)
1187 | BtfType::Float(_)
1188 | BtfType::TypeTag(_) => common,
1189 BtfType::Int(_) | BtfType::Var(_) | BtfType::DeclTag(_) => common + size_of::<u32>(),
1190 BtfType::Array(_) => common + size_of::<btf_array>(),
1191 BtfType::Struct(t) => common + t.members.len() * size_of::<btf_member>(),
1192 BtfType::Union(t) => common + t.members.len() * size_of::<btf_member>(),
1193 BtfType::Enum(t) => common + t.values.len() * size_of::<btf_enum>(),
1194 BtfType::Enum64(t) => common + t.values.len() * size_of::<btf_enum64>(),
1195 BtfType::FuncProto(t) => common + t.params.len() * size_of::<btf_param>(),
1196 BtfType::Datasec(t) => common + t.vars.len() * size_of::<btf_datasec_var>(),
1197 }
1198 }
1199
1200 fn load_type(&self, data: &'a [u8], strs: &'a [u8]) -> BtfResult<BtfType<'a>> {
1201 let t = data.pread_with::<btf_type>(0, self.endian)?;
1202 let extra = &data[size_of::<btf_type>()..];
1203 let kind = Btf::get_kind(t.info);
1204 match kind {
1205 BTF_KIND_INT => self.load_int(&t, extra, strs),
1206 BTF_KIND_PTR => Ok(BtfType::Ptr(BtfPtr { type_id: t.type_id })),
1207 BTF_KIND_ARRAY => self.load_array(extra),
1208 BTF_KIND_STRUCT => self.load_struct(&t, extra, strs),
1209 BTF_KIND_UNION => self.load_union(&t, extra, strs),
1210 BTF_KIND_ENUM => self.load_enum(&t, extra, strs),
1211 BTF_KIND_FWD => self.load_fwd(&t, strs),
1212 BTF_KIND_TYPEDEF => Ok(BtfType::Typedef(BtfTypedef {
1213 name: Btf::get_btf_str(strs, t.name_off)?,
1214 type_id: t.type_id,
1215 })),
1216 BTF_KIND_VOLATILE => Ok(BtfType::Volatile(BtfVolatile { type_id: t.type_id })),
1217 BTF_KIND_CONST => Ok(BtfType::Const(BtfConst { type_id: t.type_id })),
1218 BTF_KIND_RESTRICT => Ok(BtfType::Restrict(BtfRestrict { type_id: t.type_id })),
1219 BTF_KIND_FUNC => Ok(BtfType::Func(BtfFunc {
1220 name: Btf::get_btf_str(strs, t.name_off)?,
1221 proto_type_id: t.type_id,
1222 kind: match Btf::get_vlen(t.info) {
1223 BTF_FUNC_STATIC => BtfFuncKind::Static,
1224 BTF_FUNC_GLOBAL => BtfFuncKind::Global,
1225 BTF_FUNC_EXTERN => BtfFuncKind::Extern,
1226 _ => BtfFuncKind::Unknown,
1227 },
1228 })),
1229 BTF_KIND_FUNC_PROTO => self.load_func_proto(&t, extra, strs),
1230 BTF_KIND_VAR => self.load_var(&t, extra, strs),
1231 BTF_KIND_DATASEC => self.load_datasec(&t, extra, strs),
1232 BTF_KIND_FLOAT => Ok(BtfType::Float(BtfFloat {
1233 name: Btf::get_btf_str(strs, t.name_off)?,
1234 sz: t.type_id,
1235 })),
1236 BTF_KIND_DECL_TAG => self.load_decl_tag(&t, extra, strs),
1237 BTF_KIND_TYPE_TAG => Ok(BtfType::TypeTag(BtfTypeTag {
1238 name: Btf::get_btf_str(strs, t.name_off)?,
1239 type_id: t.type_id,
1240 })),
1241 BTF_KIND_ENUM64 => self.load_enum64(&t, extra, strs),
1242 _ => btf_error(format!("Unknown BTF kind: {}", kind)),
1243 }
1244 }
1245
1246 fn load_int(&self, t: &btf_type, extra: &'a [u8], strs: &'a [u8]) -> BtfResult<BtfType<'a>> {
1247 let info = extra.pread_with::<u32>(0, self.endian)?;
1248 let enc = (info >> 24) & 0xf;
1249 let off = (info >> 16) & 0xff;
1250 let bits = info & 0xff;
1251 Ok(BtfType::Int(BtfInt {
1252 name: Btf::get_btf_str(strs, t.name_off)?,
1253 bits: bits,
1254 offset: off,
1255 encoding: match enc {
1256 0 => BtfIntEncoding::None,
1257 BTF_INT_SIGNED => BtfIntEncoding::Signed,
1258 BTF_INT_CHAR => BtfIntEncoding::Char,
1259 BTF_INT_BOOL => BtfIntEncoding::Bool,
1260 _ => {
1261 return btf_error(format!("Unknown BTF int encoding: {}", enc));
1262 }
1263 },
1264 }))
1265 }
1266
1267 fn load_array(&self, extra: &'a [u8]) -> BtfResult<BtfType<'a>> {
1268 let info = extra.pread_with::<btf_array>(0, self.endian)?;
1269 Ok(BtfType::Array(BtfArray {
1270 nelems: info.nelems,
1271 idx_type_id: info.idx_type_id,
1272 val_type_id: info.val_type_id,
1273 }))
1274 }
1275
1276 fn load_struct(&self, t: &btf_type, extra: &'a [u8], strs: &'a [u8]) -> BtfResult<BtfType<'a>> {
1277 Ok(BtfType::Struct(BtfComposite {
1278 is_struct: true,
1279 name: Btf::get_btf_str(strs, t.name_off)?,
1280 sz: t.type_id, members: self.load_members(t, extra, strs)?,
1282 }))
1283 }
1284
1285 fn load_union(&self, t: &btf_type, extra: &'a [u8], strs: &'a [u8]) -> BtfResult<BtfType<'a>> {
1286 Ok(BtfType::Union(BtfComposite {
1287 is_struct: false,
1288 name: Btf::get_btf_str(strs, t.name_off)?,
1289 sz: t.type_id, members: self.load_members(t, extra, strs)?,
1291 }))
1292 }
1293
1294 fn load_members(
1295 &self,
1296 t: &btf_type,
1297 extra: &'a [u8],
1298 strs: &'a [u8],
1299 ) -> BtfResult<Vec<BtfMember<'a>>> {
1300 let mut res = Vec::new();
1301 let mut off: usize = 0;
1302 let bits = Btf::get_kind_flag(t.info);
1303
1304 for _ in 0..Btf::get_vlen(t.info) {
1305 let m = extra.pread_with::<btf_member>(off, self.endian)?;
1306 res.push(BtfMember {
1307 name: Btf::get_btf_str(strs, m.name_off)?,
1308 type_id: m.type_id,
1309 bit_size: if bits { (m.offset >> 24) as u8 } else { 0 },
1310 bit_offset: if bits { m.offset & 0xffffff } else { m.offset },
1311 });
1312 off += size_of::<btf_member>();
1313 }
1314 Ok(res)
1315 }
1316
1317 fn load_enum(&self, t: &btf_type, extra: &'a [u8], strs: &'a [u8]) -> BtfResult<BtfType<'a>> {
1318 let mut vals = Vec::new();
1319 let mut off: usize = 0;
1320
1321 for _ in 0..Btf::get_vlen(t.info) {
1322 let v = extra.pread_with::<btf_enum>(off, self.endian)?;
1323 vals.push(BtfEnumValue {
1324 name: Btf::get_btf_str(strs, v.name_off)?,
1325 value: v.val,
1326 });
1327 off += size_of::<btf_enum>();
1328 }
1329 Ok(BtfType::Enum(BtfEnum {
1330 name: Btf::get_btf_str(strs, t.name_off)?,
1331 sz: t.type_id, values: vals,
1333 }))
1334 }
1335
1336 fn load_enum64(&self, t: &btf_type, extra: &'a [u8], strs: &'a [u8]) -> BtfResult<BtfType<'a>> {
1337 let mut vals = Vec::new();
1338 let mut off: usize = 0;
1339
1340 for _ in 0..Btf::get_vlen(t.info) {
1341 let v = extra.pread_with::<btf_enum64>(off, self.endian)?;
1342 vals.push(BtfEnum64Value {
1343 name: Btf::get_btf_str(strs, v.name_off)?,
1344 value: i64::from(v.val_lo32) + i64::from(v.val_hi32) << 32,
1345 });
1346 off += size_of::<btf_enum64>();
1347 }
1348 Ok(BtfType::Enum64(BtfEnum64 {
1349 name: Btf::get_btf_str(strs, t.name_off)?,
1350 sz: t.type_id, values: vals,
1352 }))
1353 }
1354
1355 fn load_fwd(&self, t: &btf_type, strs: &'a [u8]) -> BtfResult<BtfType<'a>> {
1356 Ok(BtfType::Fwd(BtfFwd {
1357 name: Btf::get_btf_str(strs, t.name_off)?,
1358 kind: if Btf::get_kind_flag(t.info) {
1359 BtfFwdKind::Union
1360 } else {
1361 BtfFwdKind::Struct
1362 },
1363 }))
1364 }
1365
1366 fn load_func_proto(
1367 &self,
1368 t: &btf_type,
1369 extra: &'a [u8],
1370 strs: &'a [u8],
1371 ) -> BtfResult<BtfType<'a>> {
1372 let mut params = Vec::new();
1373 let mut off: usize = 0;
1374
1375 for _ in 0..Btf::get_vlen(t.info) {
1376 let p = extra.pread_with::<btf_param>(off, self.endian)?;
1377 params.push(BtfFuncParam {
1378 name: Btf::get_btf_str(strs, p.name_off)?,
1379 type_id: p.type_id,
1380 });
1381 off += size_of::<btf_param>();
1382 }
1383 Ok(BtfType::FuncProto(BtfFuncProto {
1384 res_type_id: t.type_id,
1385 params: params,
1386 }))
1387 }
1388
1389 fn load_var(&self, t: &btf_type, extra: &'a [u8], strs: &'a [u8]) -> BtfResult<BtfType<'a>> {
1390 let kind = extra.pread_with::<u32>(0, self.endian)?;
1391 Ok(BtfType::Var(BtfVar {
1392 name: Btf::get_btf_str(strs, t.name_off)?,
1393 type_id: t.type_id,
1394 kind: match kind {
1395 BTF_VAR_STATIC => BtfVarKind::Static,
1396 BTF_VAR_GLOBAL_ALLOCATED => BtfVarKind::GlobalAlloc,
1397 BTF_VAR_GLOBAL_EXTERNAL => BtfVarKind::GlobalExtern,
1398 _ => {
1399 return btf_error(format!("Unknown BTF var kind: {}", kind));
1400 }
1401 },
1402 }))
1403 }
1404
1405 fn load_datasec(
1406 &self,
1407 t: &btf_type,
1408 extra: &'a [u8],
1409 strs: &'a [u8],
1410 ) -> BtfResult<BtfType<'a>> {
1411 let mut vars = Vec::new();
1412 let mut off: usize = 0;
1413
1414 for _ in 0..Btf::get_vlen(t.info) {
1415 let v = extra.pread_with::<btf_datasec_var>(off, self.endian)?;
1416 vars.push(BtfDatasecVar {
1417 type_id: v.type_id,
1418 offset: v.offset,
1419 sz: v.size,
1420 });
1421 off += size_of::<btf_datasec_var>();
1422 }
1423 Ok(BtfType::Datasec(BtfDatasec {
1424 name: Btf::get_btf_str(strs, t.name_off)?,
1425 sz: t.type_id, vars: vars,
1427 }))
1428 }
1429
1430 fn load_decl_tag(
1431 &self,
1432 t: &btf_type,
1433 extra: &'a [u8],
1434 strs: &'a [u8],
1435 ) -> BtfResult<BtfType<'a>> {
1436 let comp_idx = extra.pread_with::<u32>(0, self.endian)?;
1437 Ok(BtfType::DeclTag(BtfDeclTag {
1438 name: Btf::get_btf_str(strs, t.name_off)?,
1439 type_id: t.type_id,
1440 comp_idx: comp_idx,
1441 }))
1442 }
1443
1444 fn get_vlen(info: u32) -> u32 {
1445 info & 0xffff
1446 }
1447
1448 fn get_kind(info: u32) -> u32 {
1449 (info >> 24) & 0x1f
1450 }
1451
1452 fn get_kind_flag(info: u32) -> bool {
1453 (info >> 31) == 1
1454 }
1455
1456 fn load_func_secs(
1457 &self,
1458 mut data: &'a [u8],
1459 strs: &'a [u8],
1460 ) -> BtfResult<Vec<BtfExtSection<'a, BtfExtFunc>>> {
1461 let rec_sz = data.pread_with::<u32>(0, self.endian)?;
1462 if rec_sz < size_of::<btf_ext_func_info>() as u32 {
1463 return btf_error(format!(
1464 "Too small func info record size: {}, expect at least: {}",
1465 rec_sz,
1466 size_of::<btf_ext_func_info>()
1467 ));
1468 }
1469
1470 data = &data[size_of::<u32>()..];
1471 let mut secs = Vec::new();
1472 while !data.is_empty() {
1473 let sec_hdr = data.pread_with::<btf_ext_info_sec>(0, self.endian)?;
1474 data = &data[size_of::<btf_ext_info_sec>()..];
1475
1476 let mut recs = Vec::new();
1477 for i in 0..sec_hdr.num_info {
1478 let off = (i * rec_sz) as usize;
1479 let rec = data.pread_with::<btf_ext_func_info>(off, self.endian)?;
1480 recs.push(BtfExtFunc {
1481 insn_off: rec.insn_off,
1482 type_id: rec.type_id,
1483 });
1484 }
1485 secs.push(BtfExtSection::<BtfExtFunc> {
1486 name: Btf::get_btf_str(strs, sec_hdr.sec_name_off)?,
1487 rec_sz: rec_sz as usize,
1488 recs: recs,
1489 });
1490
1491 data = &data[(sec_hdr.num_info * rec_sz) as usize..];
1492 }
1493 Ok(secs)
1494 }
1495
1496 fn load_line_secs(
1497 &self,
1498 mut data: &'a [u8],
1499 strs: &'a [u8],
1500 ) -> BtfResult<Vec<BtfExtSection<'a, BtfExtLine<'a>>>> {
1501 let rec_sz = data.pread_with::<u32>(0, self.endian)?;
1502 if rec_sz < size_of::<btf_ext_line_info>() as u32 {
1503 return btf_error(format!(
1504 "Too small line info record size: {}, expect at least: {}",
1505 rec_sz,
1506 size_of::<btf_ext_line_info>()
1507 ));
1508 }
1509 data = &data[size_of::<u32>()..];
1510 let mut secs = Vec::new();
1511 while !data.is_empty() {
1512 let sec_hdr = data.pread_with::<btf_ext_info_sec>(0, self.endian)?;
1513 data = &data[size_of::<btf_ext_info_sec>()..];
1514
1515 let mut recs = Vec::new();
1516 for i in 0..sec_hdr.num_info {
1517 let off = (i * rec_sz) as usize;
1518 let rec = data.pread_with::<btf_ext_line_info>(off, self.endian)?;
1519 recs.push(BtfExtLine {
1520 insn_off: rec.insn_off,
1521 file_name: Btf::get_btf_str(strs, rec.file_name_off)?,
1522 src_line: Btf::get_btf_str(strs, rec.line_off)?,
1523 line_num: rec.line_col >> 10,
1524 col_num: rec.line_col & 0x3ff,
1525 });
1526 }
1527 secs.push(BtfExtSection::<BtfExtLine> {
1528 name: Btf::get_btf_str(strs, sec_hdr.sec_name_off)?,
1529 rec_sz: rec_sz as usize,
1530 recs: recs,
1531 });
1532
1533 data = &data[(sec_hdr.num_info * rec_sz) as usize..];
1534 }
1535 Ok(secs)
1536 }
1537
1538 fn load_core_reloc_secs(
1539 &self,
1540 mut data: &'a [u8],
1541 strs: &'a [u8],
1542 ) -> BtfResult<Vec<BtfExtSection<'a, BtfExtCoreReloc<'a>>>> {
1543 let rec_sz = data.pread_with::<u32>(0, self.endian)?;
1544 if rec_sz < size_of::<btf_ext_core_reloc>() as u32 {
1545 return btf_error(format!(
1546 "Too small CO-RE reloc record size: {}, expect at least: {}",
1547 rec_sz,
1548 size_of::<btf_ext_core_reloc>()
1549 ));
1550 }
1551 data = &data[size_of::<u32>()..];
1552 let mut secs = Vec::new();
1553 while !data.is_empty() {
1554 let sec_hdr = data.pread_with::<btf_ext_info_sec>(0, self.endian)?;
1555 data = &data[size_of::<btf_ext_info_sec>()..];
1556
1557 let mut recs = Vec::new();
1558 for i in 0..sec_hdr.num_info {
1559 let off = (i * rec_sz) as usize;
1560 let rec = data.pread_with::<btf_ext_core_reloc>(off, self.endian)?;
1561 let kind = match rec.kind {
1562 BTF_FIELD_BYTE_OFFSET => BtfCoreRelocKind::ByteOff,
1563 BTF_FIELD_BYTE_SIZE => BtfCoreRelocKind::ByteSz,
1564 BTF_FIELD_EXISTS => BtfCoreRelocKind::FieldExists,
1565 BTF_FIELD_SIGNED => BtfCoreRelocKind::Signed,
1566 BTF_FIELD_LSHIFT_U64 => BtfCoreRelocKind::LShiftU64,
1567 BTF_FIELD_RSHIFT_U64 => BtfCoreRelocKind::RShiftU64,
1568 BTF_TYPE_LOCAL_ID => BtfCoreRelocKind::LocalTypeId,
1569 BTF_TYPE_TARGET_ID => BtfCoreRelocKind::TargetTypeId,
1570 BTF_TYPE_EXISTS => BtfCoreRelocKind::TypeExists,
1571 BTF_TYPE_MATCHES => BtfCoreRelocKind::TypeMatches,
1572 BTF_TYPE_SIZE => BtfCoreRelocKind::TypeSize,
1573 BTF_ENUMVAL_EXISTS => BtfCoreRelocKind::EnumvalExists,
1574 BTF_ENUMVAL_VALUE => BtfCoreRelocKind::EnumvalValue,
1575 _ => {
1576 return btf_error(format!("Unknown BTF CO-RE reloc kind: {}", rec.kind));
1577 }
1578 };
1579 let relo = {
1580 let access_spec_str = Btf::get_btf_str(strs, rec.access_spec_off)?;
1581 let access_spec = Btf::parse_reloc_access_spec(&access_spec_str)?;
1582 BtfExtCoreReloc {
1583 insn_off: rec.insn_off,
1584 type_id: rec.type_id,
1585 access_spec_str: access_spec_str,
1586 access_spec: access_spec,
1587 kind: kind,
1588 }
1589 };
1590 recs.push(relo);
1591 }
1592 secs.push(BtfExtSection::<BtfExtCoreReloc> {
1593 name: Btf::get_btf_str(strs, sec_hdr.sec_name_off)?,
1594 rec_sz: rec_sz as usize,
1595 recs: recs,
1596 });
1597
1598 data = &data[(sec_hdr.num_info * rec_sz) as usize..];
1599 }
1600 Ok(secs)
1601 }
1602 fn parse_reloc_access_spec(access_spec_str: &str) -> BtfResult<Vec<usize>> {
1603 let mut spec = Vec::new();
1604 for p in access_spec_str.split(':') {
1605 spec.push(p.parse::<usize>()?);
1606 }
1607 Ok(spec)
1608 }
1609
1610 fn get_btf_str(strs: &[u8], off: u32) -> BtfResult<&str> {
1611 let c_str = unsafe { CStr::from_ptr(&strs[off as usize] as *const u8 as *const c_char) };
1612 Ok(c_str.to_str()?)
1613 }
1614}