1use std::{
5 convert::AsRef,
6 fs::File,
7 io::{BufReader, Cursor, Read},
8 path::Path,
9 sync::Arc,
10};
11
12use fallible_iterator::FallibleIterator;
13use memmap2::MmapOptions;
14
15use crate::{cbtf, section::BtfSection, Error, Result};
16
17#[non_exhaustive]
20pub enum Backend {
21 Cache,
25 Mmap,
29}
30
31pub struct Btf {
34 obj: Arc<BtfSection>,
35 base: Option<Arc<BtfSection>>,
36}
37
38impl Btf {
39 pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
45 Self::from_file_with_backend(&path, Backend::Cache)
46 }
47
48 pub fn from_file_with_backend<P: AsRef<Path>>(path: P, backend: Backend) -> Result<Self> {
52 Ok(Btf {
53 obj: Arc::new(match backend {
54 Backend::Cache => {
55 BtfSection::from_reader(&mut BufReader::new(File::open(path)?), None)?
56 }
57 Backend::Mmap => BtfSection::from_mmap(
58 unsafe { MmapOptions::new().map_copy_read_only(&File::open(path)?)? },
59 None,
60 )?,
61 }),
62 base: None,
63 })
64 }
65
66 pub fn from_split_file<P: AsRef<Path>>(path: P, base: &Btf) -> Result<Btf> {
70 if base.base.is_some() {
71 return Err(Error::OpNotSupp("Provided base is a split BTF".to_string()));
72 }
73
74 Ok(Btf {
75 obj: Arc::new(BtfSection::from_reader(
76 &mut BufReader::new(File::open(path)?),
77 Some(base.obj.clone()),
78 )?),
79 base: Some(base.obj.clone()),
80 })
81 }
82
83 pub fn from_bytes(bytes: &[u8]) -> Result<Btf> {
86 Ok(Btf {
87 obj: Arc::new(BtfSection::from_reader(&mut Cursor::new(bytes), None)?),
88 base: None,
89 })
90 }
91
92 pub fn from_split_bytes(bytes: &[u8], base: &Btf) -> Result<Btf> {
95 if base.base.is_some() {
96 return Err(Error::OpNotSupp("Provided base is a split BTF".to_string()));
97 }
98
99 let base = base.obj.clone();
100 Ok(Btf {
101 obj: Arc::new(BtfSection::from_reader(
102 &mut Cursor::new(bytes),
103 Some(base.clone()),
104 )?),
105 base: Some(base),
106 })
107 }
108
109 pub fn base(&self) -> &BtfSection {
113 match &self.base {
114 Some(base) => base,
115 None => &self.obj,
116 }
117 }
118
119 pub fn split(&self) -> Option<&BtfSection> {
123 self.base.as_ref()?;
124 Some(&self.obj)
125 }
126
127 pub fn resolve_ids_by_name(&self, name: &str) -> Result<Vec<u32>> {
131 let mut ids = self.obj.resolve_ids_by_name(name)?;
132
133 if let Some(base) = &self.base {
134 ids.append(&mut base.resolve_ids_by_name(name)?);
135 }
136
137 Ok(ids)
138 }
139
140 #[cfg(feature = "regex")]
145 pub fn resolve_ids_by_regex(&self, re: ®ex::Regex) -> Result<Vec<u32>> {
146 let mut ids = self.obj.resolve_ids_by_regex(re)?;
147
148 if let Some(base) = &self.base {
149 ids.append(&mut base.resolve_ids_by_regex(re)?);
150 }
151
152 Ok(ids)
153 }
154
155 pub fn resolve_type_by_id(&self, id: u32) -> Result<Type> {
157 if let Some(base) = &self.base {
158 if let Ok(r#type) = base.resolve_type_by_id(id) {
159 return Ok(r#type);
160 }
161 }
162
163 self.obj.resolve_type_by_id(id)
164 }
165
166 pub fn resolve_types_by_name(&self, name: &str) -> Result<Vec<Type>> {
170 let mut types = self.obj.resolve_types_by_name(name)?;
171
172 if let Some(base) = &self.base {
173 types.append(&mut base.resolve_types_by_name(name)?);
174 }
175
176 Ok(types)
177 }
178
179 #[cfg(feature = "regex")]
184 pub fn resolve_types_by_regex(&self, re: ®ex::Regex) -> Result<Vec<Type>> {
185 let mut types = self.obj.resolve_types_by_regex(re)?;
186
187 if let Some(base) = &self.base {
188 types.append(&mut base.resolve_types_by_regex(re)?);
189 }
190
191 Ok(types)
192 }
193
194 pub fn resolve_name(&self, r#type: &dyn BtfType) -> Result<String> {
197 match &self.base {
198 Some(base) => base
199 .resolve_name(r#type)
200 .or_else(|_| self.obj.resolve_name(r#type)),
201 None => self.obj.resolve_name(r#type),
202 }
203 }
204
205 pub fn type_iter(&self) -> TypeIter<'_> {
207 TypeIter::new(&self.obj, self.base.as_ref().map(|s| s.as_ref()))
208 }
209
210 pub fn resolve_chained_type<T: BtfType + ?Sized>(&self, r#type: &T) -> Result<Type> {
214 let id = r#type
215 .get_type_id()
216 .ok_or(Error::OpNotSupp("No chained type in type".to_string()))?;
217 self.resolve_type_by_id(id)
218 }
219
220 pub fn chained_type_iter<T: BtfType + ?Sized>(&self, r#type: &T) -> ChainedTypeIter<'_> {
224 ChainedTypeIter {
225 btf: self,
226 r#type: self.resolve_chained_type(r#type).ok(),
227 }
228 }
229}
230
231pub struct TypeIter<'a> {
233 pub(crate) section: &'a BtfSection,
234 pub(crate) next_section: Option<&'a BtfSection>,
235 cursor: u32,
236 end: u32,
237}
238
239impl<'a> TypeIter<'a> {
240 pub(crate) fn new(section: &'a BtfSection, next_section: Option<&'a BtfSection>) -> Self {
241 let (start, end) = section.type_id_range();
242
243 TypeIter {
244 section,
245 next_section,
246 cursor: start,
247 end,
248 }
249 }
250}
251
252impl FallibleIterator for TypeIter<'_> {
253 type Item = Type;
254 type Error = Error;
255
256 fn next(&mut self) -> Result<Option<Self::Item>> {
257 if self.cursor > self.end {
259 self.section = match self.next_section.take() {
260 Some(section) => section,
261 None => return Ok(None),
262 };
263
264 (self.cursor, self.end) = self.section.type_id_range();
265 }
266
267 let r#type = self.section.resolve_type_by_id(self.cursor)?;
268 self.cursor += 1;
269
270 Ok(Some(r#type))
271 }
272}
273
274pub struct ChainedTypeIter<'a> {
276 btf: &'a Btf,
277 r#type: Option<Type>,
278}
279
280impl Iterator for ChainedTypeIter<'_> {
281 type Item = Type;
282
283 fn next(&mut self) -> Option<Self::Item> {
284 match self.r#type.clone() {
285 None => None,
286 Some(ty) => {
287 self.r#type = match ty.as_btf_type() {
288 Some(x) => self.btf.resolve_chained_type(x).ok(),
289 None => None,
292 };
293 Some(ty)
294 }
295 }
296 }
297}
298
299#[non_exhaustive]
302#[derive(Clone, Debug, Eq, PartialEq)]
303pub enum Type {
304 Void,
305 Int(Int),
306 Ptr(Ptr),
307 Array(Array),
308 Struct(Struct),
309 Union(Union),
310 Enum(Enum),
311 Fwd(Fwd),
312 Typedef(Typedef),
313 Volatile(Volatile),
314 Const(Const),
315 Restrict(Restrict),
316 Func(Func),
317 FuncProto(FuncProto),
318 Var(Var),
319 Datasec(Datasec),
320 Float(Float),
321 DeclTag(DeclTag),
322 TypeTag(TypeTag),
323 Enum64(Enum64),
324}
325
326impl Type {
327 pub(super) fn from_reader<R: Read>(
329 reader: &mut R,
330 endianness: &cbtf::Endianness,
331 bt: cbtf::btf_type,
332 ) -> Result<Self> {
333 use cbtf::BtfKind;
335 Ok(match BtfKind::from_id(bt.kind())? {
336 BtfKind::Int => Type::Int(Int::from_reader(reader, endianness, bt)?),
337 BtfKind::Ptr => Type::Ptr(Ptr::new(bt)),
338 BtfKind::Array => Type::Array(Array::from_reader(reader, endianness, bt)?),
339 BtfKind::Struct => Type::Struct(Struct::from_reader(reader, endianness, bt)?),
340 BtfKind::Union => Type::Union(Struct::from_reader(reader, endianness, bt)?),
341 BtfKind::Enum => Type::Enum(Enum::from_reader(reader, endianness, bt)?),
342 BtfKind::Fwd => Type::Fwd(Fwd::new(bt)),
343 BtfKind::Typedef => Type::Typedef(Typedef::new(bt)),
344 BtfKind::Volatile => Type::Volatile(Volatile::new(bt)),
345 BtfKind::Const => Type::Const(Volatile::new(bt)),
346 BtfKind::Restrict => Type::Restrict(Volatile::new(bt)),
347 BtfKind::Func => Type::Func(Func::new(bt)),
348 BtfKind::FuncProto => Type::FuncProto(FuncProto::from_reader(reader, endianness, bt)?),
349 BtfKind::Var => Type::Var(Var::from_reader(reader, endianness, bt)?),
350 BtfKind::Datasec => Type::Datasec(Datasec::from_reader(reader, endianness, bt)?),
351 BtfKind::Float => Type::Float(Float::new(bt)),
352 BtfKind::DeclTag => Type::DeclTag(DeclTag::from_reader(reader, endianness, bt)?),
353 BtfKind::TypeTag => Type::TypeTag(TypeTag::new(bt)),
354 BtfKind::Enum64 => Type::Enum64(Enum64::from_reader(reader, endianness, bt)?),
355 })
356 }
357
358 pub(crate) fn from_bytes(
360 buf: &[u8],
361 endianness: &cbtf::Endianness,
362 bt: cbtf::btf_type,
363 ) -> Result<Self> {
364 Self::from_reader(&mut Cursor::new(buf), endianness, bt)
365 }
366
367 pub fn name(&self) -> &'static str {
369 match &self {
370 Type::Void => "void",
371 Type::Int(_) => "int",
372 Type::Ptr(_) => "ptr",
373 Type::Array(_) => "array",
374 Type::Struct(_) => "struct",
375 Type::Union(_) => "union",
376 Type::Enum(_) => "enum",
377 Type::Fwd(_) => "fwd",
378 Type::Typedef(_) => "typedef",
379 Type::Volatile(_) => "volatile",
380 Type::Const(_) => "const",
381 Type::Restrict(_) => "restrict",
382 Type::Func(_) => "func",
383 Type::FuncProto(_) => "func-proto",
384 Type::Var(_) => "var",
385 Type::Datasec(_) => "datasec",
386 Type::Float(_) => "float",
387 Type::DeclTag(_) => "decl-tag",
388 Type::TypeTag(_) => "type-tag",
389 Type::Enum64(_) => "enum64",
390 }
391 }
392
393 pub fn as_btf_type(&self) -> Option<&dyn BtfType> {
394 match self {
395 Type::Int(i) => Some(i),
396 Type::Ptr(p) => Some(p),
397 Type::Array(a) => Some(a),
398 Type::Struct(s) => Some(s),
399 Type::Union(u) => Some(u),
400 Type::Enum(e) => Some(e),
401 Type::Fwd(f) => Some(f),
402 Type::Typedef(td) => Some(td),
403 Type::Volatile(v) => Some(v),
404 Type::Const(c) => Some(c),
405 Type::Restrict(r) => Some(r),
406 Type::Func(fu) => Some(fu),
407 Type::Var(v) => Some(v),
408 Type::Datasec(ds) => Some(ds),
409 Type::Float(f) => Some(f),
410 Type::DeclTag(dt) => Some(dt),
411 Type::TypeTag(tt) => Some(tt),
412 Type::Enum64(e64) => Some(e64),
413 _ => None,
414 }
415 }
416}
417
418pub trait BtfType {
420 fn get_name_offset(&self) -> Option<u32> {
422 None
423 }
424
425 fn get_type_id(&self) -> Option<u32> {
427 None
428 }
429}
430
431#[derive(Clone, Debug, Eq, PartialEq)]
433pub struct Int {
434 btf_type: cbtf::btf_type,
435 btf_int: cbtf::btf_int,
436}
437
438impl Int {
439 fn from_reader<R: Read>(
440 reader: &mut R,
441 endianness: &cbtf::Endianness,
442 btf_type: cbtf::btf_type,
443 ) -> Result<Int> {
444 Ok(Int {
445 btf_type,
446 btf_int: cbtf::btf_int::from_reader(reader, endianness)?,
447 })
448 }
449
450 pub fn is_signed(&self) -> bool {
451 self.btf_int.encoding() & cbtf::BTF_INT_SIGNED == cbtf::BTF_INT_SIGNED
452 }
453
454 pub fn is_char(&self) -> bool {
455 self.btf_int.encoding() & cbtf::BTF_INT_CHAR == cbtf::BTF_INT_CHAR
456 }
457
458 pub fn is_bool(&self) -> bool {
459 self.btf_int.encoding() & cbtf::BTF_INT_BOOL == cbtf::BTF_INT_BOOL
460 }
461
462 pub fn size(&self) -> usize {
463 self.btf_type.size().expect("int should have a size")
464 }
465}
466
467impl BtfType for Int {
468 fn get_name_offset(&self) -> Option<u32> {
469 self.btf_type.name_offset()
470 }
471}
472
473#[derive(Clone, Debug, Eq, PartialEq)]
475pub struct Ptr {
476 btf_type: cbtf::btf_type,
477}
478
479impl Ptr {
480 fn new(btf_type: cbtf::btf_type) -> Ptr {
481 Ptr { btf_type }
482 }
483}
484
485impl BtfType for Ptr {
486 fn get_type_id(&self) -> Option<u32> {
487 self.btf_type.r#type()
488 }
489}
490
491#[derive(Clone, Debug, Eq, PartialEq)]
493pub struct Array {
494 btf_type: cbtf::btf_type,
495 btf_array: cbtf::btf_array,
496}
497
498#[allow(clippy::len_without_is_empty)]
499impl Array {
500 fn from_reader<R: Read>(
501 reader: &mut R,
502 endianness: &cbtf::Endianness,
503 btf_type: cbtf::btf_type,
504 ) -> Result<Array> {
505 Ok(Array {
506 btf_type,
507 btf_array: cbtf::btf_array::from_reader(reader, endianness)?,
508 })
509 }
510
511 pub fn len(&self) -> usize {
513 self.btf_array.nelems as usize
514 }
515}
516
517impl BtfType for Array {
518 fn get_type_id(&self) -> Option<u32> {
519 Some(self.btf_array.r#type)
520 }
521}
522
523#[derive(Clone, Debug, Eq, PartialEq)]
525pub struct Struct {
526 btf_type: cbtf::btf_type,
527 pub members: Vec<Member>,
529}
530
531impl Struct {
532 fn from_reader<R: Read>(
533 reader: &mut R,
534 endianness: &cbtf::Endianness,
535 btf_type: cbtf::btf_type,
536 ) -> Result<Struct> {
537 let mut members = Vec::new();
538
539 for _ in 0..btf_type.vlen() {
540 members.push(Member::from_reader(
541 reader,
542 endianness,
543 btf_type.kind_flag(),
544 )?);
545 }
546
547 Ok(Struct { btf_type, members })
548 }
549
550 pub fn size(&self) -> usize {
551 self.btf_type
552 .size()
553 .expect("struct and union should have a size")
554 }
555}
556
557impl BtfType for Struct {
558 fn get_name_offset(&self) -> Option<u32> {
559 self.btf_type.name_offset()
560 }
561}
562
563pub type Union = Struct;
565
566#[derive(Clone, Debug, Eq, PartialEq)]
568pub struct Member {
569 kind_flag: u32,
570 btf_member: cbtf::btf_member,
571}
572
573impl Member {
574 fn from_reader<R: Read>(
575 reader: &mut R,
576 endianness: &cbtf::Endianness,
577 kind_flag: u32,
578 ) -> Result<Member> {
579 Ok(Member {
580 kind_flag,
581 btf_member: cbtf::btf_member::from_reader(reader, endianness)?,
582 })
583 }
584
585 pub fn bit_offset(&self) -> u32 {
586 match self.kind_flag {
587 1 => self.btf_member.offset & 0xffffff,
588 _ => self.btf_member.offset,
589 }
590 }
591
592 pub fn bitfield_size(&self) -> Option<u32> {
593 match self.kind_flag {
594 1 => Some(self.btf_member.offset >> 24),
595 _ => None,
596 }
597 }
598}
599
600impl BtfType for Member {
601 fn get_name_offset(&self) -> Option<u32> {
602 Some(self.btf_member.name_off)
603 }
604
605 fn get_type_id(&self) -> Option<u32> {
606 Some(self.btf_member.r#type)
607 }
608}
609
610#[derive(Clone, Debug, Eq, PartialEq)]
612pub struct Enum {
613 btf_type: cbtf::btf_type,
614 pub members: Vec<EnumMember>,
616}
617
618#[allow(clippy::len_without_is_empty)]
619impl Enum {
620 fn from_reader<R: Read>(
621 reader: &mut R,
622 endianness: &cbtf::Endianness,
623 btf_type: cbtf::btf_type,
624 ) -> Result<Enum> {
625 let mut members = Vec::new();
626
627 for _ in 0..btf_type.vlen() {
628 members.push(EnumMember::from_reader(reader, endianness)?);
629 }
630
631 Ok(Enum { btf_type, members })
632 }
633
634 pub fn is_signed(&self) -> bool {
635 self.btf_type.kind_flag() == 1
636 }
637
638 pub fn size(&self) -> usize {
639 self.btf_type.size().expect("enum should have a size")
640 }
641}
642
643impl BtfType for Enum {
644 fn get_name_offset(&self) -> Option<u32> {
645 self.btf_type.name_offset()
646 }
647}
648
649#[derive(Clone, Debug, Eq, PartialEq)]
651pub struct EnumMember {
652 btf_enum: cbtf::btf_enum,
653}
654
655impl EnumMember {
656 fn from_reader<R: Read>(reader: &mut R, endianness: &cbtf::Endianness) -> Result<EnumMember> {
657 Ok(EnumMember {
658 btf_enum: cbtf::btf_enum::from_reader(reader, endianness)?,
659 })
660 }
661
662 pub fn val(&self) -> u32 {
663 self.btf_enum.val
664 }
665}
666
667impl BtfType for EnumMember {
668 fn get_name_offset(&self) -> Option<u32> {
669 Some(self.btf_enum.name_off)
670 }
671}
672
673#[derive(Clone, Debug, Eq, PartialEq)]
675pub struct Fwd {
676 btf_type: cbtf::btf_type,
677}
678
679impl Fwd {
680 fn new(btf_type: cbtf::btf_type) -> Fwd {
681 Fwd { btf_type }
682 }
683
684 pub fn is_struct(&self) -> bool {
686 self.btf_type.kind_flag() == 0
687 }
688
689 pub fn is_union(&self) -> bool {
691 self.btf_type.kind_flag() == 1
692 }
693}
694
695impl BtfType for Fwd {
696 fn get_name_offset(&self) -> Option<u32> {
697 self.btf_type.name_offset()
698 }
699}
700
701#[derive(Clone, Debug, Eq, PartialEq)]
703pub struct Typedef {
704 btf_type: cbtf::btf_type,
705}
706
707impl Typedef {
708 fn new(btf_type: cbtf::btf_type) -> Typedef {
709 Typedef { btf_type }
710 }
711}
712
713impl BtfType for Typedef {
714 fn get_name_offset(&self) -> Option<u32> {
715 self.btf_type.name_offset()
716 }
717
718 fn get_type_id(&self) -> Option<u32> {
719 self.btf_type.r#type()
720 }
721}
722
723#[derive(Clone, Debug, Eq, PartialEq)]
725pub struct Volatile {
726 btf_type: cbtf::btf_type,
727}
728
729impl Volatile {
730 fn new(btf_type: cbtf::btf_type) -> Volatile {
731 Volatile { btf_type }
732 }
733}
734
735impl BtfType for Volatile {
736 fn get_type_id(&self) -> Option<u32> {
737 self.btf_type.r#type()
738 }
739}
740
741pub type Const = Volatile;
743
744pub type Restrict = Volatile;
746
747#[derive(Clone, Debug, Eq, PartialEq)]
749pub struct Func {
750 btf_type: cbtf::btf_type,
751}
752
753impl Func {
754 fn new(btf_type: cbtf::btf_type) -> Func {
755 Func { btf_type }
756 }
757
758 pub fn is_static(&self) -> bool {
759 self.btf_type.vlen() == cbtf::BTF_FUNC_STATIC
760 }
761
762 pub fn is_global(&self) -> bool {
763 self.btf_type.vlen() == cbtf::BTF_FUNC_GLOBAL
764 }
765
766 pub fn is_extern(&self) -> bool {
767 self.btf_type.vlen() == cbtf::BTF_FUNC_EXTERN
768 }
769}
770
771impl BtfType for Func {
772 fn get_name_offset(&self) -> Option<u32> {
773 self.btf_type.name_offset()
774 }
775
776 fn get_type_id(&self) -> Option<u32> {
777 self.btf_type.r#type()
778 }
779}
780
781#[derive(Clone, Debug, Eq, PartialEq)]
783pub struct FuncProto {
784 btf_type: cbtf::btf_type,
785 pub parameters: Vec<Parameter>,
786}
787
788impl FuncProto {
789 fn from_reader<R: Read>(
790 reader: &mut R,
791 endianness: &cbtf::Endianness,
792 btf_type: cbtf::btf_type,
793 ) -> Result<FuncProto> {
794 let mut parameters = Vec::new();
795
796 for _ in 0..btf_type.vlen() {
797 parameters.push(Parameter::from_reader(reader, endianness)?);
798 }
799
800 Ok(FuncProto {
801 btf_type,
802 parameters,
803 })
804 }
805
806 pub fn return_type_id(&self) -> u32 {
807 self.btf_type
808 .r#type()
809 .expect("func proto should have a type")
810 }
811}
812
813#[derive(Clone, Debug, Eq, PartialEq)]
815pub struct Parameter {
816 btf_param: cbtf::btf_param,
817}
818
819impl Parameter {
820 fn from_reader<R: Read>(reader: &mut R, endianness: &cbtf::Endianness) -> Result<Parameter> {
821 Ok(Parameter {
822 btf_param: cbtf::btf_param::from_reader(reader, endianness)?,
823 })
824 }
825
826 pub fn is_variadic(&self) -> bool {
827 self.btf_param.name_off == 0 && self.btf_param.r#type == 0
828 }
829}
830
831impl BtfType for Parameter {
832 fn get_name_offset(&self) -> Option<u32> {
833 Some(self.btf_param.name_off)
834 }
835
836 fn get_type_id(&self) -> Option<u32> {
837 Some(self.btf_param.r#type)
838 }
839}
840
841#[derive(Clone, Debug, Eq, PartialEq)]
843pub struct Var {
844 btf_type: cbtf::btf_type,
845 btf_var: cbtf::btf_var,
846}
847
848impl Var {
849 fn from_reader<R: Read>(
850 reader: &mut R,
851 endianness: &cbtf::Endianness,
852 btf_type: cbtf::btf_type,
853 ) -> Result<Var> {
854 Ok(Var {
855 btf_type,
856 btf_var: cbtf::btf_var::from_reader(reader, endianness)?,
857 })
858 }
859
860 pub fn is_static(&self) -> bool {
861 self.btf_var.linkage == cbtf::BTF_VAR_STATIC
862 }
863
864 pub fn is_global(&self) -> bool {
865 self.btf_var.linkage == cbtf::BTF_VAR_GLOBAL_ALLOCATED
866 }
867
868 pub fn is_extern(&self) -> bool {
869 self.btf_var.linkage == cbtf::BTF_VAR_GLOBAL_EXTERN
870 }
871}
872
873impl BtfType for Var {
874 fn get_name_offset(&self) -> Option<u32> {
875 self.btf_type.name_offset()
876 }
877
878 fn get_type_id(&self) -> Option<u32> {
879 self.btf_type.r#type()
880 }
881}
882
883#[derive(Clone, Debug, Eq, PartialEq)]
885pub struct Datasec {
886 btf_type: cbtf::btf_type,
887 pub variables: Vec<VarSecinfo>,
888}
889
890impl Datasec {
891 fn from_reader<R: Read>(
892 reader: &mut R,
893 endianness: &cbtf::Endianness,
894 btf_type: cbtf::btf_type,
895 ) -> Result<Datasec> {
896 let mut variables = Vec::new();
897
898 for _ in 0..btf_type.vlen() {
899 variables.push(VarSecinfo::from_reader(reader, endianness)?);
900 }
901
902 Ok(Datasec {
903 btf_type,
904 variables,
905 })
906 }
907
908 pub fn size(&self) -> usize {
909 self.btf_type.size().expect("datasec should have a size")
910 }
911}
912
913impl BtfType for Datasec {
914 fn get_name_offset(&self) -> Option<u32> {
915 self.btf_type.name_offset()
916 }
917}
918
919#[derive(Clone, Debug, Eq, PartialEq)]
921pub struct VarSecinfo {
922 btf_var_secinfo: cbtf::btf_var_secinfo,
923}
924
925impl VarSecinfo {
926 fn from_reader<R: Read>(reader: &mut R, endianness: &cbtf::Endianness) -> Result<VarSecinfo> {
927 Ok(VarSecinfo {
928 btf_var_secinfo: cbtf::btf_var_secinfo::from_reader(reader, endianness)?,
929 })
930 }
931
932 pub fn offset(&self) -> u32 {
933 self.btf_var_secinfo.offset
934 }
935
936 pub fn size(&self) -> usize {
937 self.btf_var_secinfo.size as usize
938 }
939}
940
941impl BtfType for VarSecinfo {
942 fn get_type_id(&self) -> Option<u32> {
943 Some(self.btf_var_secinfo.r#type)
944 }
945}
946
947#[derive(Clone, Debug, Eq, PartialEq)]
949pub struct Float {
950 btf_type: cbtf::btf_type,
951}
952
953impl Float {
954 fn new(btf_type: cbtf::btf_type) -> Float {
955 Float { btf_type }
956 }
957
958 pub fn size(&self) -> usize {
959 self.btf_type.size().expect("float should have a size")
960 }
961}
962
963impl BtfType for Float {
964 fn get_name_offset(&self) -> Option<u32> {
965 self.btf_type.name_offset()
966 }
967}
968
969#[derive(Clone, Debug, Eq, PartialEq)]
971pub struct DeclTag {
972 btf_type: cbtf::btf_type,
973 btf_decl_tag: cbtf::btf_decl_tag,
974}
975
976impl DeclTag {
977 fn from_reader<R: Read>(
978 reader: &mut R,
979 endianness: &cbtf::Endianness,
980 btf_type: cbtf::btf_type,
981 ) -> Result<DeclTag> {
982 Ok(DeclTag {
983 btf_type,
984 btf_decl_tag: cbtf::btf_decl_tag::from_reader(reader, endianness)?,
985 })
986 }
987
988 pub fn component_index(&self) -> Option<u32> {
989 let component_idx = self.btf_decl_tag.component_idx;
990 match component_idx {
991 x if x < 0 => None,
992 x => Some(x as u32),
993 }
994 }
995
996 pub fn is_attribute(&self) -> bool {
997 self.btf_type.kind_flag() == 1
998 }
999}
1000
1001impl BtfType for DeclTag {
1002 fn get_name_offset(&self) -> Option<u32> {
1003 self.btf_type.name_offset()
1004 }
1005
1006 fn get_type_id(&self) -> Option<u32> {
1007 self.btf_type.r#type()
1008 }
1009}
1010
1011#[derive(Clone, Debug, Eq, PartialEq)]
1013pub struct TypeTag {
1014 btf_type: cbtf::btf_type,
1015}
1016
1017impl TypeTag {
1018 fn new(btf_type: cbtf::btf_type) -> TypeTag {
1019 TypeTag { btf_type }
1020 }
1021
1022 pub fn is_attribute(&self) -> bool {
1023 self.btf_type.kind_flag() == 1
1024 }
1025}
1026
1027impl BtfType for TypeTag {
1028 fn get_name_offset(&self) -> Option<u32> {
1029 self.btf_type.name_offset()
1030 }
1031
1032 fn get_type_id(&self) -> Option<u32> {
1033 self.btf_type.r#type()
1034 }
1035}
1036
1037#[derive(Clone, Debug, Eq, PartialEq)]
1039pub struct Enum64 {
1040 btf_type: cbtf::btf_type,
1041 pub members: Vec<Enum64Member>,
1043}
1044
1045#[allow(clippy::len_without_is_empty)]
1046impl Enum64 {
1047 fn from_reader<R: Read>(
1048 reader: &mut R,
1049 endianness: &cbtf::Endianness,
1050 btf_type: cbtf::btf_type,
1051 ) -> Result<Enum64> {
1052 let mut members = Vec::new();
1053
1054 for _ in 0..btf_type.vlen() {
1055 members.push(Enum64Member::from_reader(reader, endianness)?);
1056 }
1057
1058 Ok(Enum64 { btf_type, members })
1059 }
1060
1061 pub fn is_signed(&self) -> bool {
1062 self.btf_type.kind_flag() == 1
1063 }
1064
1065 pub fn size(&self) -> usize {
1066 self.btf_type.size().expect("enum64 should have a size")
1067 }
1068}
1069
1070impl BtfType for Enum64 {
1071 fn get_name_offset(&self) -> Option<u32> {
1072 self.btf_type.name_offset()
1073 }
1074}
1075
1076#[derive(Clone, Debug, Eq, PartialEq)]
1078pub struct Enum64Member {
1079 btf_enum64: cbtf::btf_enum64,
1080}
1081
1082impl Enum64Member {
1083 fn from_reader<R: Read>(reader: &mut R, endianness: &cbtf::Endianness) -> Result<Enum64Member> {
1084 Ok(Enum64Member {
1085 btf_enum64: cbtf::btf_enum64::from_reader(reader, endianness)?,
1086 })
1087 }
1088
1089 pub fn val(&self) -> u64 {
1090 ((self.btf_enum64.val_hi32 as u64) << 32) | self.btf_enum64.val_lo32 as u64
1091 }
1092}
1093
1094impl BtfType for Enum64Member {
1095 fn get_name_offset(&self) -> Option<u32> {
1096 Some(self.btf_enum64.name_off)
1097 }
1098}