1#![allow(missing_docs)]
2
3use alloc::{string::ToString, vec, vec::Vec};
4use core::{fmt::Display, mem, ptr};
5
6use object::Endianness;
7
8use crate::btf::{Btf, BtfError, MAX_RESOLVE_DEPTH};
9
10#[derive(Clone, Debug)]
11pub enum BtfType {
12 Unknown,
13 Fwd(Fwd),
14 Const(Const),
15 Volatile(Volatile),
16 Restrict(Restrict),
17 Ptr(Ptr),
18 Typedef(Typedef),
19 Func(Func),
20 Int(Int),
21 Float(Float),
22 Enum(Enum),
23 Array(Array),
24 Struct(Struct),
25 Union(Union),
26 FuncProto(FuncProto),
27 Var(Var),
28 DataSec(DataSec),
29 DeclTag(DeclTag),
30 TypeTag(TypeTag),
31 Enum64(Enum64),
32}
33
34#[repr(C)]
35#[derive(Clone, Debug)]
36pub struct Fwd {
37 pub(crate) name_offset: u32,
38 info: u32,
39 _unused: u32,
40}
41
42impl Fwd {
43 pub(crate) fn to_bytes(&self) -> Vec<u8> {
44 bytes_of::<Fwd>(self).to_vec()
45 }
46
47 pub(crate) fn kind(&self) -> BtfKind {
48 BtfKind::Fwd
49 }
50
51 pub(crate) fn type_info_size(&self) -> usize {
52 mem::size_of::<Self>()
53 }
54}
55
56#[repr(C)]
57#[derive(Clone, Debug)]
58pub struct Const {
59 pub(crate) name_offset: u32,
60 info: u32,
61 pub(crate) btf_type: u32,
62}
63
64impl Const {
65 pub(crate) fn to_bytes(&self) -> Vec<u8> {
66 bytes_of::<Const>(self).to_vec()
67 }
68
69 pub(crate) fn kind(&self) -> BtfKind {
70 BtfKind::Const
71 }
72
73 pub(crate) fn type_info_size(&self) -> usize {
74 mem::size_of::<Self>()
75 }
76
77 pub(crate) fn new(btf_type: u32) -> Self {
78 let info = (BtfKind::Const as u32) << 24;
79 Self {
80 name_offset: 0,
81 info,
82 btf_type,
83 }
84 }
85}
86
87#[repr(C)]
88#[derive(Clone, Debug)]
89pub struct Volatile {
90 pub(crate) name_offset: u32,
91 info: u32,
92 pub(crate) btf_type: u32,
93}
94
95impl Volatile {
96 pub(crate) fn to_bytes(&self) -> Vec<u8> {
97 bytes_of::<Volatile>(self).to_vec()
98 }
99
100 pub(crate) fn kind(&self) -> BtfKind {
101 BtfKind::Volatile
102 }
103
104 pub(crate) fn type_info_size(&self) -> usize {
105 mem::size_of::<Self>()
106 }
107}
108
109#[derive(Clone, Debug)]
110pub struct Restrict {
111 pub(crate) name_offset: u32,
112 _info: u32,
113 pub(crate) btf_type: u32,
114}
115
116impl Restrict {
117 pub(crate) fn to_bytes(&self) -> Vec<u8> {
118 bytes_of::<Restrict>(self).to_vec()
119 }
120
121 pub(crate) fn kind(&self) -> BtfKind {
122 BtfKind::Restrict
123 }
124
125 pub(crate) fn type_info_size(&self) -> usize {
126 mem::size_of::<Self>()
127 }
128}
129
130#[repr(C)]
131#[derive(Clone, Debug)]
132pub struct Ptr {
133 pub(crate) name_offset: u32,
134 info: u32,
135 pub(crate) btf_type: u32,
136}
137
138impl Ptr {
139 pub(crate) fn to_bytes(&self) -> Vec<u8> {
140 bytes_of::<Self>(self).to_vec()
141 }
142
143 pub(crate) fn kind(&self) -> BtfKind {
144 BtfKind::Ptr
145 }
146
147 pub(crate) fn type_info_size(&self) -> usize {
148 mem::size_of::<Self>()
149 }
150
151 pub fn new(name_offset: u32, btf_type: u32) -> Self {
152 let info = (BtfKind::Ptr as u32) << 24;
153 Self {
154 name_offset,
155 info,
156 btf_type,
157 }
158 }
159}
160
161#[repr(C)]
162#[derive(Clone, Debug)]
163pub struct Typedef {
164 pub(crate) name_offset: u32,
165 info: u32,
166 pub(crate) btf_type: u32,
167}
168
169impl Typedef {
170 pub(crate) fn to_bytes(&self) -> Vec<u8> {
171 bytes_of::<Self>(self).to_vec()
172 }
173
174 pub(crate) fn kind(&self) -> BtfKind {
175 BtfKind::Typedef
176 }
177
178 pub(crate) fn type_info_size(&self) -> usize {
179 mem::size_of::<Self>()
180 }
181
182 pub(crate) fn new(name_offset: u32, btf_type: u32) -> Self {
183 let info = (BtfKind::Typedef as u32) << 24;
184 Self {
185 name_offset,
186 info,
187 btf_type,
188 }
189 }
190}
191
192#[repr(C)]
193#[derive(Clone, Debug)]
194pub struct Float {
195 pub(crate) name_offset: u32,
196 info: u32,
197 pub(crate) size: u32,
198}
199
200impl Float {
201 pub(crate) fn to_bytes(&self) -> Vec<u8> {
202 bytes_of::<Self>(self).to_vec()
203 }
204
205 pub(crate) fn kind(&self) -> BtfKind {
206 BtfKind::Float
207 }
208 pub(crate) fn type_info_size(&self) -> usize {
209 mem::size_of::<Self>()
210 }
211
212 pub fn new(name_offset: u32, size: u32) -> Self {
213 let info = (BtfKind::Float as u32) << 24;
214 Self {
215 name_offset,
216 info,
217 size,
218 }
219 }
220}
221
222#[repr(C)]
223#[derive(Clone, Debug)]
224pub struct Func {
225 pub(crate) name_offset: u32,
226 info: u32,
227 pub(crate) btf_type: u32,
228}
229
230#[repr(u32)]
231#[derive(Clone, Debug, PartialEq, Eq)]
232pub enum FuncLinkage {
233 Static = 0,
234 Global = 1,
235 Extern = 2,
236 Unknown,
237}
238
239impl From<u32> for FuncLinkage {
240 fn from(v: u32) -> Self {
241 match v {
242 0 => FuncLinkage::Static,
243 1 => FuncLinkage::Global,
244 2 => FuncLinkage::Extern,
245 _ => FuncLinkage::Unknown,
246 }
247 }
248}
249
250impl Func {
251 pub(crate) fn to_bytes(&self) -> Vec<u8> {
252 bytes_of::<Self>(self).to_vec()
253 }
254
255 pub(crate) fn kind(&self) -> BtfKind {
256 BtfKind::Func
257 }
258 pub(crate) fn type_info_size(&self) -> usize {
259 mem::size_of::<Self>()
260 }
261
262 pub fn new(name_offset: u32, proto: u32, linkage: FuncLinkage) -> Self {
263 let mut info = (BtfKind::Func as u32) << 24;
264 info |= (linkage as u32) & 0xFFFF;
265 Self {
266 name_offset,
267 info,
268 btf_type: proto,
269 }
270 }
271
272 pub(crate) fn linkage(&self) -> FuncLinkage {
273 (self.info & 0xFFF).into()
274 }
275
276 pub(crate) fn set_linkage(&mut self, linkage: FuncLinkage) {
277 self.info = (self.info & 0xFFFF0000) | (linkage as u32) & 0xFFFF;
278 }
279}
280
281#[repr(C)]
282#[derive(Clone, Debug)]
283pub struct TypeTag {
284 pub(crate) name_offset: u32,
285 info: u32,
286 pub(crate) btf_type: u32,
287}
288
289impl TypeTag {
290 pub(crate) fn to_bytes(&self) -> Vec<u8> {
291 bytes_of::<Self>(self).to_vec()
292 }
293
294 pub(crate) fn kind(&self) -> BtfKind {
295 BtfKind::TypeTag
296 }
297
298 pub(crate) fn type_info_size(&self) -> usize {
299 mem::size_of::<Self>()
300 }
301
302 pub fn new(name_offset: u32, btf_type: u32) -> Self {
303 let info = (BtfKind::TypeTag as u32) << 24;
304 Self {
305 name_offset,
306 info,
307 btf_type,
308 }
309 }
310}
311
312#[repr(u32)]
313#[derive(Clone, Debug, Eq, PartialEq)]
314pub enum IntEncoding {
315 None,
316 Signed = 1,
317 Char = 2,
318 Bool = 4,
319 Unknown,
320}
321
322impl From<u32> for IntEncoding {
323 fn from(v: u32) -> Self {
324 match v {
325 0 => IntEncoding::None,
326 1 => IntEncoding::Signed,
327 2 => IntEncoding::Char,
328 4 => IntEncoding::Bool,
329 _ => IntEncoding::Unknown,
330 }
331 }
332}
333
334#[repr(C)]
335#[derive(Clone, Debug)]
336pub struct Int {
337 pub(crate) name_offset: u32,
338 info: u32,
339 pub(crate) size: u32,
340 pub(crate) data: u32,
341}
342
343impl Int {
344 pub(crate) fn to_bytes(&self) -> Vec<u8> {
345 let Self {
346 name_offset,
347 info,
348 size,
349 data,
350 } = self;
351 [
352 bytes_of::<u32>(name_offset),
353 bytes_of::<u32>(info),
354 bytes_of::<u32>(size),
355 bytes_of::<u32>(data),
356 ]
357 .concat()
358 }
359
360 pub(crate) fn kind(&self) -> BtfKind {
361 BtfKind::Int
362 }
363 pub(crate) fn type_info_size(&self) -> usize {
364 mem::size_of::<Self>()
365 }
366
367 pub fn new(name_offset: u32, size: u32, encoding: IntEncoding, offset: u32) -> Self {
368 let info = (BtfKind::Int as u32) << 24;
369 let mut data = 0u32;
370 data |= (encoding as u32 & 0x0f) << 24;
371 data |= (offset & 0xff) << 16;
372 data |= (size * 8) & 0xff;
373 Self {
374 name_offset,
375 info,
376 size,
377 data,
378 }
379 }
380
381 pub(crate) fn encoding(&self) -> IntEncoding {
382 ((self.data & 0x0f000000) >> 24).into()
383 }
384
385 pub(crate) fn offset(&self) -> u32 {
386 (self.data & 0x00ff0000) >> 16
387 }
388
389 #[cfg(test)]
391 pub(crate) fn bits(&self) -> u32 {
392 self.data & 0x000000ff
393 }
394}
395
396#[repr(C)]
397#[derive(Debug, Clone)]
398pub struct BtfEnum {
399 pub name_offset: u32,
400 pub value: u32,
401}
402
403impl BtfEnum {
404 pub fn new(name_offset: u32, value: u32) -> Self {
405 Self { name_offset, value }
406 }
407}
408
409#[repr(C)]
410#[derive(Clone, Debug)]
411pub struct Enum {
412 pub(crate) name_offset: u32,
413 info: u32,
414 pub(crate) size: u32,
415 pub(crate) variants: Vec<BtfEnum>,
416}
417
418impl Enum {
419 pub(crate) fn to_bytes(&self) -> Vec<u8> {
420 let Self {
421 name_offset,
422 info,
423 size,
424 variants,
425 } = self;
426 [
427 bytes_of::<u32>(name_offset),
428 bytes_of::<u32>(info),
429 bytes_of::<u32>(size),
430 ]
431 .into_iter()
432 .chain(variants.iter().flat_map(|BtfEnum { name_offset, value }| {
433 [bytes_of::<u32>(name_offset), bytes_of::<u32>(value)]
434 }))
435 .flatten()
436 .copied()
437 .collect()
438 }
439
440 pub(crate) fn kind(&self) -> BtfKind {
441 BtfKind::Enum
442 }
443
444 pub(crate) fn type_info_size(&self) -> usize {
445 mem::size_of::<Fwd>() + mem::size_of::<BtfEnum>() * self.variants.len()
446 }
447
448 pub fn new(name_offset: u32, signed: bool, variants: Vec<BtfEnum>) -> Self {
449 let mut info = (BtfKind::Enum as u32) << 24;
450 info |= (variants.len() as u32) & 0xFFFF;
451 if signed {
452 info |= 1 << 31;
453 }
454 Self {
455 name_offset,
456 info,
457 size: 4,
458 variants,
459 }
460 }
461
462 pub(crate) fn is_signed(&self) -> bool {
463 self.info >> 31 == 1
464 }
465
466 pub(crate) fn set_signed(&mut self, signed: bool) {
467 if signed {
468 self.info |= 1 << 31;
469 } else {
470 self.info &= !(1 << 31);
471 }
472 }
473}
474
475#[repr(C)]
476#[derive(Debug, Clone)]
477pub struct BtfEnum64 {
478 pub(crate) name_offset: u32,
479 pub(crate) value_low: u32,
480 pub(crate) value_high: u32,
481}
482
483impl BtfEnum64 {
484 pub fn new(name_offset: u32, value: u64) -> Self {
485 Self {
486 name_offset,
487 value_low: value as u32,
488 value_high: (value >> 32) as u32,
489 }
490 }
491}
492
493#[repr(C)]
494#[derive(Clone, Debug)]
495pub struct Enum64 {
496 pub(crate) name_offset: u32,
497 info: u32,
498 pub(crate) size: u32,
499 pub(crate) variants: Vec<BtfEnum64>,
500}
501
502impl Enum64 {
503 pub(crate) fn to_bytes(&self) -> Vec<u8> {
504 let Self {
505 name_offset,
506 info,
507 size,
508 variants,
509 } = self;
510 [
511 bytes_of::<u32>(name_offset),
512 bytes_of::<u32>(info),
513 bytes_of::<u32>(size),
514 ]
515 .into_iter()
516 .chain(variants.iter().flat_map(
517 |BtfEnum64 {
518 name_offset,
519 value_low,
520 value_high,
521 }| {
522 [
523 bytes_of::<u32>(name_offset),
524 bytes_of::<u32>(value_low),
525 bytes_of::<u32>(value_high),
526 ]
527 },
528 ))
529 .flatten()
530 .copied()
531 .collect()
532 }
533
534 pub(crate) fn kind(&self) -> BtfKind {
535 BtfKind::Enum64
536 }
537
538 pub(crate) fn type_info_size(&self) -> usize {
539 mem::size_of::<Fwd>() + mem::size_of::<BtfEnum64>() * self.variants.len()
540 }
541
542 pub(crate) fn is_signed(&self) -> bool {
543 self.info >> 31 == 1
544 }
545
546 pub fn new(name_offset: u32, signed: bool, variants: Vec<BtfEnum64>) -> Self {
547 let mut info = (BtfKind::Enum64 as u32) << 24;
548 if signed {
549 info |= 1 << 31
550 };
551 info |= (variants.len() as u32) & 0xFFFF;
552 Enum64 {
553 name_offset,
554 info,
555 size: 8,
562 variants,
563 }
564 }
565}
566
567#[repr(C)]
568#[derive(Clone, Debug)]
569pub(crate) struct BtfMember {
570 pub(crate) name_offset: u32,
571 pub(crate) btf_type: u32,
572 pub(crate) offset: u32,
573}
574
575#[repr(C)]
576#[derive(Clone, Debug)]
577pub struct Struct {
578 pub(crate) name_offset: u32,
579 info: u32,
580 pub(crate) size: u32,
581 pub(crate) members: Vec<BtfMember>,
582}
583
584impl Struct {
585 pub(crate) fn to_bytes(&self) -> Vec<u8> {
586 let Self {
587 name_offset,
588 info,
589 size,
590 members,
591 } = self;
592 [
593 bytes_of::<u32>(name_offset),
594 bytes_of::<u32>(info),
595 bytes_of::<u32>(size),
596 ]
597 .into_iter()
598 .chain(members.iter().flat_map(
599 |BtfMember {
600 name_offset,
601 btf_type,
602 offset,
603 }| {
604 [
605 bytes_of::<u32>(name_offset),
606 bytes_of::<u32>(btf_type),
607 bytes_of::<u32>(offset),
608 ]
609 },
610 ))
611 .flatten()
612 .copied()
613 .collect()
614 }
615
616 pub(crate) fn kind(&self) -> BtfKind {
617 BtfKind::Struct
618 }
619
620 pub(crate) fn type_info_size(&self) -> usize {
621 mem::size_of::<Fwd>() + mem::size_of::<BtfMember>() * self.members.len()
622 }
623
624 pub(crate) fn new(name_offset: u32, members: Vec<BtfMember>, size: u32) -> Self {
625 let mut info = (BtfKind::Struct as u32) << 24;
626 info |= (members.len() as u32) & 0xFFFF;
627 Self {
628 name_offset,
629 info,
630 size,
631 members,
632 }
633 }
634
635 pub(crate) fn member_bit_offset(&self, member: &BtfMember) -> usize {
636 let k_flag = self.info >> 31 == 1;
637 let bit_offset = if k_flag {
638 member.offset & 0xFFFFFF
639 } else {
640 member.offset
641 };
642
643 bit_offset as usize
644 }
645
646 pub(crate) fn member_bit_field_size(&self, member: &BtfMember) -> usize {
647 let k_flag = (self.info >> 31) == 1;
648 let size = if k_flag { member.offset >> 24 } else { 0 };
649
650 size as usize
651 }
652}
653
654#[repr(C)]
655#[derive(Clone, Debug)]
656pub struct Union {
657 pub(crate) name_offset: u32,
658 info: u32,
659 pub(crate) size: u32,
660 pub(crate) members: Vec<BtfMember>,
661}
662
663impl Union {
664 pub(crate) fn new(name_offset: u32, size: u32, members: Vec<BtfMember>) -> Self {
665 let mut info = (BtfKind::Union as u32) << 24;
666 info |= (members.len() as u32) & 0xFFFF;
667 Self {
668 name_offset,
669 info,
670 size,
671 members,
672 }
673 }
674
675 pub(crate) fn to_bytes(&self) -> Vec<u8> {
676 let Self {
677 name_offset,
678 info,
679 size,
680 members,
681 } = self;
682 [
683 bytes_of::<u32>(name_offset),
684 bytes_of::<u32>(info),
685 bytes_of::<u32>(size),
686 ]
687 .into_iter()
688 .chain(members.iter().flat_map(
689 |BtfMember {
690 name_offset,
691 btf_type,
692 offset,
693 }| {
694 [
695 bytes_of::<u32>(name_offset),
696 bytes_of::<u32>(btf_type),
697 bytes_of::<u32>(offset),
698 ]
699 },
700 ))
701 .flatten()
702 .copied()
703 .collect()
704 }
705
706 pub(crate) fn kind(&self) -> BtfKind {
707 BtfKind::Union
708 }
709
710 pub(crate) fn type_info_size(&self) -> usize {
711 mem::size_of::<Fwd>() + mem::size_of::<BtfMember>() * self.members.len()
712 }
713
714 pub(crate) fn member_bit_offset(&self, member: &BtfMember) -> usize {
715 let k_flag = self.info >> 31 == 1;
716 let bit_offset = if k_flag {
717 member.offset & 0xFFFFFF
718 } else {
719 member.offset
720 };
721
722 bit_offset as usize
723 }
724
725 pub(crate) fn member_bit_field_size(&self, member: &BtfMember) -> usize {
726 let k_flag = (self.info >> 31) == 1;
727 let size = if k_flag { member.offset >> 24 } else { 0 };
728
729 size as usize
730 }
731}
732
733#[repr(C)]
734#[derive(Clone, Debug)]
735pub(crate) struct BtfArray {
736 pub(crate) element_type: u32,
737 pub(crate) index_type: u32,
738 pub(crate) len: u32,
739}
740
741#[repr(C)]
742#[derive(Clone, Debug)]
743pub struct Array {
744 pub(crate) name_offset: u32,
745 info: u32,
746 _unused: u32,
747 pub(crate) array: BtfArray,
748}
749
750impl Array {
751 pub(crate) fn to_bytes(&self) -> Vec<u8> {
752 let Self {
753 name_offset,
754 info,
755 _unused,
756 array,
757 } = self;
758 [
759 bytes_of::<u32>(name_offset),
760 bytes_of::<u32>(info),
761 bytes_of::<u32>(_unused),
762 bytes_of::<BtfArray>(array),
763 ]
764 .concat()
765 }
766
767 pub(crate) fn kind(&self) -> BtfKind {
768 BtfKind::Array
769 }
770
771 pub(crate) fn type_info_size(&self) -> usize {
772 mem::size_of::<Self>()
773 }
774
775 #[cfg(test)]
776 pub(crate) fn new(name_offset: u32, element_type: u32, index_type: u32, len: u32) -> Self {
777 let info = (BtfKind::Array as u32) << 24;
778 Self {
779 name_offset,
780 info,
781 _unused: 0,
782 array: BtfArray {
783 element_type,
784 index_type,
785 len,
786 },
787 }
788 }
789}
790
791#[repr(C)]
792#[derive(Clone, Debug)]
793pub struct BtfParam {
794 pub name_offset: u32,
795 pub btf_type: u32,
796}
797
798#[repr(C)]
799#[derive(Clone, Debug)]
800pub struct FuncProto {
801 pub(crate) name_offset: u32,
802 info: u32,
803 pub(crate) return_type: u32,
804 pub(crate) params: Vec<BtfParam>,
805}
806
807impl FuncProto {
808 pub(crate) fn to_bytes(&self) -> Vec<u8> {
809 let Self {
810 name_offset,
811 info,
812 return_type,
813 params,
814 } = self;
815 [
816 bytes_of::<u32>(name_offset),
817 bytes_of::<u32>(info),
818 bytes_of::<u32>(return_type),
819 ]
820 .into_iter()
821 .chain(params.iter().flat_map(
822 |BtfParam {
823 name_offset,
824 btf_type,
825 }| { [bytes_of::<u32>(name_offset), bytes_of::<u32>(btf_type)] },
826 ))
827 .flatten()
828 .copied()
829 .collect()
830 }
831
832 pub(crate) fn kind(&self) -> BtfKind {
833 BtfKind::FuncProto
834 }
835
836 pub(crate) fn type_info_size(&self) -> usize {
837 mem::size_of::<Fwd>() + mem::size_of::<BtfParam>() * self.params.len()
838 }
839
840 pub fn new(params: Vec<BtfParam>, return_type: u32) -> Self {
841 let mut info = (BtfKind::FuncProto as u32) << 24;
842 info |= (params.len() as u32) & 0xFFFF;
843 Self {
844 name_offset: 0,
845 info,
846 return_type,
847 params,
848 }
849 }
850}
851
852#[repr(u32)]
853#[derive(Clone, Debug, PartialEq, Eq)]
854pub enum VarLinkage {
855 Static,
856 Global,
857 Extern,
858 Unknown,
859}
860
861impl From<u32> for VarLinkage {
862 fn from(v: u32) -> Self {
863 match v {
864 0 => VarLinkage::Static,
865 1 => VarLinkage::Global,
866 2 => VarLinkage::Extern,
867 _ => VarLinkage::Unknown,
868 }
869 }
870}
871
872#[repr(C)]
873#[derive(Clone, Debug)]
874pub struct Var {
875 pub(crate) name_offset: u32,
876 info: u32,
877 pub(crate) btf_type: u32,
878 pub(crate) linkage: VarLinkage,
879}
880
881impl Var {
882 pub(crate) fn to_bytes(&self) -> Vec<u8> {
883 let Self {
884 name_offset,
885 info,
886 btf_type,
887 linkage,
888 } = self;
889 [
890 bytes_of::<u32>(name_offset),
891 bytes_of::<u32>(info),
892 bytes_of::<u32>(btf_type),
893 bytes_of::<VarLinkage>(linkage),
894 ]
895 .concat()
896 }
897
898 pub(crate) fn kind(&self) -> BtfKind {
899 BtfKind::Var
900 }
901
902 pub(crate) fn type_info_size(&self) -> usize {
903 mem::size_of::<Self>()
904 }
905
906 pub fn new(name_offset: u32, btf_type: u32, linkage: VarLinkage) -> Self {
907 let info = (BtfKind::Var as u32) << 24;
908 Self {
909 name_offset,
910 info,
911 btf_type,
912 linkage,
913 }
914 }
915}
916
917#[repr(C)]
918#[derive(Clone, Debug)]
919pub struct DataSecEntry {
920 pub btf_type: u32,
921 pub offset: u32,
922 pub size: u32,
923}
924
925#[repr(C)]
926#[derive(Clone, Debug)]
927pub struct DataSec {
928 pub(crate) name_offset: u32,
929 info: u32,
930 pub(crate) size: u32,
931 pub(crate) entries: Vec<DataSecEntry>,
932}
933
934impl DataSec {
935 pub(crate) fn to_bytes(&self) -> Vec<u8> {
936 let Self {
937 name_offset,
938 info,
939 size,
940 entries,
941 } = self;
942 [
943 bytes_of::<u32>(name_offset),
944 bytes_of::<u32>(info),
945 bytes_of::<u32>(size),
946 ]
947 .into_iter()
948 .chain(entries.iter().flat_map(
949 |DataSecEntry {
950 btf_type,
951 offset,
952 size,
953 }| {
954 [
955 bytes_of::<u32>(btf_type),
956 bytes_of::<u32>(offset),
957 bytes_of::<u32>(size),
958 ]
959 },
960 ))
961 .flatten()
962 .copied()
963 .collect()
964 }
965
966 pub(crate) fn kind(&self) -> BtfKind {
967 BtfKind::DataSec
968 }
969
970 pub(crate) fn type_info_size(&self) -> usize {
971 mem::size_of::<Fwd>() + mem::size_of::<DataSecEntry>() * self.entries.len()
972 }
973
974 pub fn new(name_offset: u32, entries: Vec<DataSecEntry>, size: u32) -> Self {
975 let mut info = (BtfKind::DataSec as u32) << 24;
976 info |= (entries.len() as u32) & 0xFFFF;
977 Self {
978 name_offset,
979 info,
980 size,
981 entries,
982 }
983 }
984}
985
986#[repr(C)]
987#[derive(Clone, Debug)]
988pub struct DeclTag {
989 pub(crate) name_offset: u32,
990 info: u32,
991 pub(crate) btf_type: u32,
992 pub(crate) component_index: i32,
993}
994
995impl DeclTag {
996 pub(crate) fn to_bytes(&self) -> Vec<u8> {
997 let Self {
998 name_offset,
999 info,
1000 btf_type,
1001 component_index,
1002 } = self;
1003 [
1004 bytes_of::<u32>(name_offset),
1005 bytes_of::<u32>(info),
1006 bytes_of::<u32>(btf_type),
1007 bytes_of::<i32>(component_index),
1008 ]
1009 .concat()
1010 }
1011
1012 pub(crate) fn kind(&self) -> BtfKind {
1013 BtfKind::DeclTag
1014 }
1015
1016 pub(crate) fn type_info_size(&self) -> usize {
1017 mem::size_of::<Self>()
1018 }
1019
1020 pub fn new(name_offset: u32, btf_type: u32, component_index: i32) -> Self {
1021 let info = (BtfKind::DeclTag as u32) << 24;
1022 Self {
1023 name_offset,
1024 info,
1025 btf_type,
1026 component_index,
1027 }
1028 }
1029}
1030
1031#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
1032#[repr(u32)]
1033pub enum BtfKind {
1034 #[default]
1035 Unknown = 0,
1036 Int = 1,
1037 Ptr = 2,
1038 Array = 3,
1039 Struct = 4,
1040 Union = 5,
1041 Enum = 6,
1042 Fwd = 7,
1043 Typedef = 8,
1044 Volatile = 9,
1045 Const = 10,
1046 Restrict = 11,
1047 Func = 12,
1048 FuncProto = 13,
1049 Var = 14,
1050 DataSec = 15,
1051 Float = 16,
1052 DeclTag = 17,
1053 TypeTag = 18,
1054 Enum64 = 19,
1055}
1056
1057impl TryFrom<u32> for BtfKind {
1058 type Error = BtfError;
1059
1060 fn try_from(v: u32) -> Result<Self, Self::Error> {
1061 use BtfKind::*;
1062 Ok(match v {
1063 0 => Unknown,
1064 1 => Int,
1065 2 => Ptr,
1066 3 => Array,
1067 4 => Struct,
1068 5 => Union,
1069 6 => Enum,
1070 7 => Fwd,
1071 8 => Typedef,
1072 9 => Volatile,
1073 10 => Const,
1074 11 => Restrict,
1075 12 => Func,
1076 13 => FuncProto,
1077 14 => Var,
1078 15 => DataSec,
1079 16 => Float,
1080 17 => DeclTag,
1081 18 => TypeTag,
1082 19 => Enum64,
1083 kind => return Err(BtfError::InvalidTypeKind { kind }),
1084 })
1085 }
1086}
1087
1088impl Display for BtfKind {
1089 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1090 match self {
1091 BtfKind::Unknown => write!(f, "[UNKNOWN]"),
1092 BtfKind::Int => write!(f, "[INT]"),
1093 BtfKind::Float => write!(f, "[FLOAT]"),
1094 BtfKind::Ptr => write!(f, "[PTR]"),
1095 BtfKind::Array => write!(f, "[ARRAY]"),
1096 BtfKind::Struct => write!(f, "[STRUCT]"),
1097 BtfKind::Union => write!(f, "[UNION]"),
1098 BtfKind::Enum => write!(f, "[ENUM]"),
1099 BtfKind::Fwd => write!(f, "[FWD]"),
1100 BtfKind::Typedef => write!(f, "[TYPEDEF]"),
1101 BtfKind::Volatile => write!(f, "[VOLATILE]"),
1102 BtfKind::Const => write!(f, "[CONST]"),
1103 BtfKind::Restrict => write!(f, "[RESTRICT]"),
1104 BtfKind::Func => write!(f, "[FUNC]"),
1105 BtfKind::FuncProto => write!(f, "[FUNC_PROTO]"),
1106 BtfKind::Var => write!(f, "[VAR]"),
1107 BtfKind::DataSec => write!(f, "[DATASEC]"),
1108 BtfKind::DeclTag => write!(f, "[DECL_TAG]"),
1109 BtfKind::TypeTag => write!(f, "[TYPE_TAG]"),
1110 BtfKind::Enum64 => write!(f, "[ENUM64]"),
1111 }
1112 }
1113}
1114
1115unsafe fn read<T>(data: &[u8]) -> Result<T, BtfError> {
1116 if mem::size_of::<T>() > data.len() {
1117 return Err(BtfError::InvalidTypeInfo);
1118 }
1119
1120 Ok(ptr::read_unaligned::<T>(data.as_ptr() as *const T))
1121}
1122
1123unsafe fn read_array<T>(data: &[u8], len: usize) -> Result<Vec<T>, BtfError> {
1124 if mem::size_of::<T>() * len > data.len() {
1125 return Err(BtfError::InvalidTypeInfo);
1126 }
1127 let data = &data[0..mem::size_of::<T>() * len];
1128 let r = data
1129 .chunks(mem::size_of::<T>())
1130 .map(|chunk| ptr::read_unaligned(chunk.as_ptr() as *const T))
1131 .collect();
1132 Ok(r)
1133}
1134
1135impl BtfType {
1136 #[allow(unused_unsafe)]
1137 pub(crate) unsafe fn read(data: &[u8], endianness: Endianness) -> Result<BtfType, BtfError> {
1138 let ty = unsafe { read_array::<u32>(data, 3)? };
1139 let data = &data[mem::size_of::<u32>() * 3..];
1140 let vlen = type_vlen(ty[1]);
1141 Ok(match type_kind(ty[1])? {
1142 BtfKind::Unknown => BtfType::Unknown,
1143 BtfKind::Fwd => BtfType::Fwd(Fwd {
1144 name_offset: ty[0],
1145 info: ty[1],
1146 _unused: 0,
1147 }),
1148 BtfKind::Const => BtfType::Const(Const {
1149 name_offset: ty[0],
1150 info: ty[1],
1151 btf_type: ty[2],
1152 }),
1153 BtfKind::Volatile => BtfType::Volatile(Volatile {
1154 name_offset: ty[0],
1155 info: ty[1],
1156 btf_type: ty[2],
1157 }),
1158 BtfKind::Restrict => BtfType::Restrict(Restrict {
1159 name_offset: ty[0],
1160 _info: ty[1],
1161 btf_type: ty[2],
1162 }),
1163 BtfKind::Ptr => BtfType::Ptr(Ptr {
1164 name_offset: ty[0],
1165 info: ty[1],
1166 btf_type: ty[2],
1167 }),
1168 BtfKind::Typedef => BtfType::Typedef(Typedef {
1169 name_offset: ty[0],
1170 info: ty[1],
1171 btf_type: ty[2],
1172 }),
1173 BtfKind::Func => BtfType::Func(Func {
1174 name_offset: ty[0],
1175 info: ty[1],
1176 btf_type: ty[2],
1177 }),
1178 BtfKind::Int => {
1179 if mem::size_of::<u32>() > data.len() {
1180 return Err(BtfError::InvalidTypeInfo);
1181 }
1182 let read_u32 = if endianness == Endianness::Little {
1183 u32::from_le_bytes
1184 } else {
1185 u32::from_be_bytes
1186 };
1187 BtfType::Int(Int {
1188 name_offset: ty[0],
1189 info: ty[1],
1190 size: ty[2],
1191 data: read_u32(data[..mem::size_of::<u32>()].try_into().unwrap()),
1192 })
1193 }
1194 BtfKind::Float => BtfType::Float(Float {
1195 name_offset: ty[0],
1196 info: ty[1],
1197 size: ty[2],
1198 }),
1199 BtfKind::Enum => BtfType::Enum(Enum {
1200 name_offset: ty[0],
1201 info: ty[1],
1202 size: ty[2],
1203 variants: unsafe { read_array::<BtfEnum>(data, vlen)? },
1204 }),
1205 BtfKind::Enum64 => BtfType::Enum64(Enum64 {
1206 name_offset: ty[0],
1207 info: ty[1],
1208 size: ty[2],
1209 variants: unsafe { read_array::<BtfEnum64>(data, vlen)? },
1210 }),
1211 BtfKind::Array => BtfType::Array(Array {
1212 name_offset: ty[0],
1213 info: ty[1],
1214 _unused: 0,
1215 array: unsafe { read(data)? },
1216 }),
1217 BtfKind::Struct => BtfType::Struct(Struct {
1218 name_offset: ty[0],
1219 info: ty[1],
1220 size: ty[2],
1221 members: unsafe { read_array::<BtfMember>(data, vlen)? },
1222 }),
1223 BtfKind::Union => BtfType::Union(Union {
1224 name_offset: ty[0],
1225 info: ty[1],
1226 size: ty[2],
1227 members: unsafe { read_array::<BtfMember>(data, vlen)? },
1228 }),
1229 BtfKind::FuncProto => BtfType::FuncProto(FuncProto {
1230 name_offset: ty[0],
1231 info: ty[1],
1232 return_type: ty[2],
1233 params: unsafe { read_array::<BtfParam>(data, vlen)? },
1234 }),
1235 BtfKind::Var => BtfType::Var(Var {
1236 name_offset: ty[0],
1237 info: ty[1],
1238 btf_type: ty[2],
1239 linkage: unsafe { read(data)? },
1240 }),
1241 BtfKind::DataSec => BtfType::DataSec(DataSec {
1242 name_offset: ty[0],
1243 info: ty[1],
1244 size: ty[2],
1245 entries: unsafe { read_array::<DataSecEntry>(data, vlen)? },
1246 }),
1247 BtfKind::DeclTag => BtfType::DeclTag(DeclTag {
1248 name_offset: ty[0],
1249 info: ty[1],
1250 btf_type: ty[2],
1251 component_index: unsafe { read(data)? },
1252 }),
1253 BtfKind::TypeTag => BtfType::TypeTag(TypeTag {
1254 name_offset: ty[0],
1255 info: ty[1],
1256 btf_type: ty[2],
1257 }),
1258 })
1259 }
1260
1261 pub(crate) fn to_bytes(&self) -> Vec<u8> {
1262 match self {
1263 BtfType::Unknown => vec![],
1264 BtfType::Fwd(t) => t.to_bytes(),
1265 BtfType::Const(t) => t.to_bytes(),
1266 BtfType::Volatile(t) => t.to_bytes(),
1267 BtfType::Restrict(t) => t.to_bytes(),
1268 BtfType::Ptr(t) => t.to_bytes(),
1269 BtfType::Typedef(t) => t.to_bytes(),
1270 BtfType::Func(t) => t.to_bytes(),
1271 BtfType::Int(t) => t.to_bytes(),
1272 BtfType::Float(t) => t.to_bytes(),
1273 BtfType::Enum(t) => t.to_bytes(),
1274 BtfType::Enum64(t) => t.to_bytes(),
1275 BtfType::Array(t) => t.to_bytes(),
1276 BtfType::Struct(t) => t.to_bytes(),
1277 BtfType::Union(t) => t.to_bytes(),
1278 BtfType::FuncProto(t) => t.to_bytes(),
1279 BtfType::Var(t) => t.to_bytes(),
1280 BtfType::DataSec(t) => t.to_bytes(),
1281 BtfType::DeclTag(t) => t.to_bytes(),
1282 BtfType::TypeTag(t) => t.to_bytes(),
1283 }
1284 }
1285
1286 pub(crate) fn size(&self) -> Option<u32> {
1287 match self {
1288 BtfType::Int(t) => Some(t.size),
1289 BtfType::Float(t) => Some(t.size),
1290 BtfType::Enum(t) => Some(t.size),
1291 BtfType::Enum64(t) => Some(t.size),
1292 BtfType::Struct(t) => Some(t.size),
1293 BtfType::Union(t) => Some(t.size),
1294 BtfType::DataSec(t) => Some(t.size),
1295 BtfType::Ptr(_) => Some(mem::size_of::<&()>() as u32),
1296 _ => None,
1297 }
1298 }
1299
1300 pub(crate) fn btf_type(&self) -> Option<u32> {
1301 match self {
1302 BtfType::Const(t) => Some(t.btf_type),
1303 BtfType::Volatile(t) => Some(t.btf_type),
1304 BtfType::Restrict(t) => Some(t.btf_type),
1305 BtfType::Ptr(t) => Some(t.btf_type),
1306 BtfType::Typedef(t) => Some(t.btf_type),
1307 BtfType::FuncProto(t) => Some(t.return_type),
1309 BtfType::Var(t) => Some(t.btf_type),
1310 BtfType::DeclTag(t) => Some(t.btf_type),
1311 BtfType::TypeTag(t) => Some(t.btf_type),
1312 _ => None,
1313 }
1314 }
1315
1316 pub(crate) fn type_info_size(&self) -> usize {
1317 match self {
1318 BtfType::Unknown => mem::size_of::<Fwd>(),
1319 BtfType::Fwd(t) => t.type_info_size(),
1320 BtfType::Const(t) => t.type_info_size(),
1321 BtfType::Volatile(t) => t.type_info_size(),
1322 BtfType::Restrict(t) => t.type_info_size(),
1323 BtfType::Ptr(t) => t.type_info_size(),
1324 BtfType::Typedef(t) => t.type_info_size(),
1325 BtfType::Func(t) => t.type_info_size(),
1326 BtfType::Int(t) => t.type_info_size(),
1327 BtfType::Float(t) => t.type_info_size(),
1328 BtfType::Enum(t) => t.type_info_size(),
1329 BtfType::Enum64(t) => t.type_info_size(),
1330 BtfType::Array(t) => t.type_info_size(),
1331 BtfType::Struct(t) => t.type_info_size(),
1332 BtfType::Union(t) => t.type_info_size(),
1333 BtfType::FuncProto(t) => t.type_info_size(),
1334 BtfType::Var(t) => t.type_info_size(),
1335 BtfType::DataSec(t) => t.type_info_size(),
1336 BtfType::DeclTag(t) => t.type_info_size(),
1337 BtfType::TypeTag(t) => t.type_info_size(),
1338 }
1339 }
1340
1341 pub(crate) fn name_offset(&self) -> u32 {
1342 match self {
1343 BtfType::Unknown => 0,
1344 BtfType::Fwd(t) => t.name_offset,
1345 BtfType::Const(t) => t.name_offset,
1346 BtfType::Volatile(t) => t.name_offset,
1347 BtfType::Restrict(t) => t.name_offset,
1348 BtfType::Ptr(t) => t.name_offset,
1349 BtfType::Typedef(t) => t.name_offset,
1350 BtfType::Func(t) => t.name_offset,
1351 BtfType::Int(t) => t.name_offset,
1352 BtfType::Float(t) => t.name_offset,
1353 BtfType::Enum(t) => t.name_offset,
1354 BtfType::Enum64(t) => t.name_offset,
1355 BtfType::Array(t) => t.name_offset,
1356 BtfType::Struct(t) => t.name_offset,
1357 BtfType::Union(t) => t.name_offset,
1358 BtfType::FuncProto(t) => t.name_offset,
1359 BtfType::Var(t) => t.name_offset,
1360 BtfType::DataSec(t) => t.name_offset,
1361 BtfType::DeclTag(t) => t.name_offset,
1362 BtfType::TypeTag(t) => t.name_offset,
1363 }
1364 }
1365
1366 pub(crate) fn kind(&self) -> BtfKind {
1367 match self {
1368 BtfType::Unknown => BtfKind::Unknown,
1369 BtfType::Fwd(t) => t.kind(),
1370 BtfType::Const(t) => t.kind(),
1371 BtfType::Volatile(t) => t.kind(),
1372 BtfType::Restrict(t) => t.kind(),
1373 BtfType::Ptr(t) => t.kind(),
1374 BtfType::Typedef(t) => t.kind(),
1375 BtfType::Func(t) => t.kind(),
1376 BtfType::Int(t) => t.kind(),
1377 BtfType::Float(t) => t.kind(),
1378 BtfType::Enum(t) => t.kind(),
1379 BtfType::Enum64(t) => t.kind(),
1380 BtfType::Array(t) => t.kind(),
1381 BtfType::Struct(t) => t.kind(),
1382 BtfType::Union(t) => t.kind(),
1383 BtfType::FuncProto(t) => t.kind(),
1384 BtfType::Var(t) => t.kind(),
1385 BtfType::DataSec(t) => t.kind(),
1386 BtfType::DeclTag(t) => t.kind(),
1387 BtfType::TypeTag(t) => t.kind(),
1388 }
1389 }
1390
1391 pub(crate) fn is_composite(&self) -> bool {
1392 matches!(self, BtfType::Struct(_) | BtfType::Union(_))
1393 }
1394
1395 pub(crate) fn members(&self) -> Option<impl Iterator<Item = &BtfMember>> {
1396 match self {
1397 BtfType::Struct(t) => Some(t.members.iter()),
1398 BtfType::Union(t) => Some(t.members.iter()),
1399 _ => None,
1400 }
1401 }
1402
1403 pub(crate) fn member_bit_field_size(&self, member: &BtfMember) -> Option<usize> {
1404 match self {
1405 BtfType::Struct(t) => Some(t.member_bit_field_size(member)),
1406 BtfType::Union(t) => Some(t.member_bit_field_size(member)),
1407 _ => None,
1408 }
1409 }
1410
1411 pub(crate) fn member_bit_offset(&self, member: &BtfMember) -> Option<usize> {
1412 match self {
1413 BtfType::Struct(t) => Some(t.member_bit_offset(member)),
1414 BtfType::Union(t) => Some(t.member_bit_offset(member)),
1415 _ => None,
1416 }
1417 }
1418
1419 pub(crate) fn is_compatible(&self, other: &BtfType) -> bool {
1420 if self.kind() == other.kind() {
1421 return true;
1422 }
1423
1424 matches!(
1425 (self.kind(), other.kind()),
1426 (BtfKind::Enum, BtfKind::Enum64) | (BtfKind::Enum64, BtfKind::Enum)
1427 )
1428 }
1429}
1430
1431fn type_kind(info: u32) -> Result<BtfKind, BtfError> {
1432 ((info >> 24) & 0x1F).try_into()
1433}
1434
1435fn type_vlen(info: u32) -> usize {
1436 (info & 0xFFFF) as usize
1437}
1438
1439pub(crate) fn types_are_compatible(
1440 local_btf: &Btf,
1441 root_local_id: u32,
1442 target_btf: &Btf,
1443 root_target_id: u32,
1444) -> Result<bool, BtfError> {
1445 let mut local_id = root_local_id;
1446 let mut target_id = root_target_id;
1447 let local_ty = local_btf.type_by_id(local_id)?;
1448 let target_ty = target_btf.type_by_id(target_id)?;
1449
1450 if !local_ty.is_compatible(target_ty) {
1451 return Ok(false);
1452 }
1453
1454 for _ in 0..MAX_RESOLVE_DEPTH {
1455 local_id = local_btf.resolve_type(local_id)?;
1456 target_id = target_btf.resolve_type(target_id)?;
1457 let local_ty = local_btf.type_by_id(local_id)?;
1458 let target_ty = target_btf.type_by_id(target_id)?;
1459
1460 if !local_ty.is_compatible(target_ty) {
1461 return Ok(false);
1462 }
1463
1464 match local_ty {
1465 BtfType::Unknown
1466 | BtfType::Struct(_)
1467 | BtfType::Union(_)
1468 | BtfType::Enum(_)
1469 | BtfType::Enum64(_)
1470 | BtfType::Fwd(_)
1471 | BtfType::Float(_) => return Ok(true),
1472 BtfType::Int(local) => {
1473 if let BtfType::Int(target) = target_ty {
1474 return Ok(local.offset() == 0 && target.offset() == 0);
1475 }
1476 }
1477 BtfType::Ptr(local) => {
1478 if let BtfType::Ptr(target) = target_ty {
1479 local_id = local.btf_type;
1480 target_id = target.btf_type;
1481 continue;
1482 }
1483 }
1484 BtfType::Array(Array { array: local, .. }) => {
1485 if let BtfType::Array(Array { array: target, .. }) = target_ty {
1486 local_id = local.element_type;
1487 target_id = target.element_type;
1488 continue;
1489 }
1490 }
1491 BtfType::FuncProto(local) => {
1492 if let BtfType::FuncProto(target) = target_ty {
1493 if local.params.len() != target.params.len() {
1494 return Ok(false);
1495 }
1496
1497 for (l_param, t_param) in local.params.iter().zip(target.params.iter()) {
1498 let local_id = local_btf.resolve_type(l_param.btf_type)?;
1499 let target_id = target_btf.resolve_type(t_param.btf_type)?;
1500 if !types_are_compatible(local_btf, local_id, target_btf, target_id)? {
1501 return Ok(false);
1502 }
1503 }
1504
1505 local_id = local.return_type;
1506 target_id = target.return_type;
1507 continue;
1508 }
1509 }
1510 local_ty => panic!("unexpected type {:?}", local_ty),
1511 }
1512 }
1513
1514 Err(BtfError::MaximumTypeDepthReached { type_id: local_id })
1515}
1516
1517pub(crate) fn fields_are_compatible(
1518 local_btf: &Btf,
1519 mut local_id: u32,
1520 target_btf: &Btf,
1521 mut target_id: u32,
1522) -> Result<bool, BtfError> {
1523 for _ in 0..MAX_RESOLVE_DEPTH {
1524 local_id = local_btf.resolve_type(local_id)?;
1525 target_id = target_btf.resolve_type(target_id)?;
1526 let local_ty = local_btf.type_by_id(local_id)?;
1527 let target_ty = target_btf.type_by_id(target_id)?;
1528
1529 if local_ty.is_composite() && target_ty.is_composite() {
1530 return Ok(true);
1531 }
1532
1533 if !local_ty.is_compatible(target_ty) {
1534 return Ok(false);
1535 }
1536
1537 match local_ty {
1538 BtfType::Fwd(_) | BtfType::Enum(_) | BtfType::Enum64(_) => {
1539 let flavorless_name =
1540 |name: &str| name.split_once("___").map_or(name, |x| x.0).to_string();
1541
1542 let local_name = flavorless_name(&local_btf.type_name(local_ty)?);
1543 let target_name = flavorless_name(&target_btf.type_name(target_ty)?);
1544
1545 return Ok(local_name == target_name);
1546 }
1547 BtfType::Int(local) => {
1548 if let BtfType::Int(target) = target_ty {
1549 return Ok(local.offset() == 0 && target.offset() == 0);
1550 }
1551 }
1552 BtfType::Float(_) => return Ok(true),
1553 BtfType::Ptr(_) => return Ok(true),
1554 BtfType::Array(Array { array: local, .. }) => {
1555 if let BtfType::Array(Array { array: target, .. }) = target_ty {
1556 local_id = local.element_type;
1557 target_id = target.element_type;
1558 continue;
1559 }
1560 }
1561 local_ty => panic!("unexpected type {:?}", local_ty),
1562 }
1563 }
1564
1565 Err(BtfError::MaximumTypeDepthReached { type_id: local_id })
1566}
1567
1568fn bytes_of<T>(val: &T) -> &[u8] {
1569 unsafe { crate::util::bytes_of(val) }
1571}
1572#[cfg(test)]
1573mod tests {
1574 use assert_matches::assert_matches;
1575
1576 use super::*;
1577
1578 #[test]
1579 fn test_read_btf_type_int() {
1580 let endianness = Endianness::default();
1581 let bpf_type = BtfType::Int(Int::new(1, 8, IntEncoding::None, 0));
1582 let data: &[u8] = &bpf_type.to_bytes();
1583 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Int(new @ Int {
1584 name_offset,
1585 info: _,
1586 size,
1587 data: _,
1588 }) => {
1589 assert_eq!(name_offset, 1);
1590 assert_eq!(size, 8);
1591 assert_eq!(new.bits(), 64);
1592 assert_eq!(new.to_bytes(), data);
1593 });
1594 }
1595
1596 #[test]
1597 fn test_read_btf_type_ptr() {
1598 let endianness = Endianness::default();
1599 let bpf_type = BtfType::Ptr(Ptr::new(0, 0x06));
1600 let data: &[u8] = &bpf_type.to_bytes();
1601 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Ptr(got) => {
1602 assert_eq!(got.to_bytes(), data);
1603 });
1604 }
1605
1606 #[test]
1607 fn test_read_btf_type_array() {
1608 let endianness = Endianness::default();
1609 let bpf_type = BtfType::Array(Array::new(0, 1, 0x12, 2));
1610 let data: &[u8] = &bpf_type.to_bytes();
1611 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Array(got) => {
1612 assert_eq!(got.to_bytes(), data);
1613 });
1614 }
1615
1616 #[test]
1617 fn test_read_btf_type_struct() {
1618 let endianness = Endianness::default();
1619 let members = vec![BtfMember {
1620 name_offset: 0x0247,
1621 btf_type: 0x12,
1622 offset: 0,
1623 }];
1624 let bpf_type = BtfType::Struct(Struct::new(0, members, 4));
1625 let data: &[u8] = &bpf_type.to_bytes();
1626 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Struct(got) => {
1627 assert_eq!(got.to_bytes(), data);
1628 });
1629 }
1630
1631 #[test]
1632 fn test_read_btf_type_union() {
1633 let endianness = Endianness::default();
1634 let members = vec![BtfMember {
1635 name_offset: 0x040d,
1636 btf_type: 0x68,
1637 offset: 0,
1638 }];
1639 let bpf_type = BtfType::Union(Union::new(0, 4, members));
1640 let data: &[u8] = &bpf_type.to_bytes();
1641 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Union(got) => {
1642 assert_eq!(got.to_bytes(), data);
1643 });
1644 }
1645
1646 #[test]
1647 fn test_read_btf_type_enum() {
1648 let endianness = Endianness::default();
1649 let enum1 = BtfEnum::new(0xc9, 0);
1650 let enum2 = BtfEnum::new(0xcf, 1);
1651 let variants = vec![enum1, enum2];
1652 let bpf_type = BtfType::Enum(Enum::new(0, false, variants));
1653 let data: &[u8] = &bpf_type.to_bytes();
1654 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Enum(got) => {
1655 assert_eq!(got.to_bytes(), data);
1656 });
1657 }
1658
1659 #[test]
1660 fn test_read_btf_type_fwd() {
1661 let endianness = Endianness::default();
1662 let info = (BtfKind::Fwd as u32) << 24;
1663 let bpf_type = BtfType::Fwd(Fwd {
1664 name_offset: 0x550b,
1665 info,
1666 _unused: 0,
1667 });
1668 let data: &[u8] = &bpf_type.to_bytes();
1669 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Fwd(got) => {
1670 assert_eq!(got.to_bytes(), data);
1671 });
1672 }
1673
1674 #[test]
1675 fn test_read_btf_type_typedef() {
1676 let endianness = Endianness::default();
1677 let bpf_type = BtfType::Typedef(Typedef::new(0x31, 0x0b));
1678 let data: &[u8] = &bpf_type.to_bytes();
1679 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Typedef(got) => {
1680 assert_eq!(got.to_bytes(), data);
1681 });
1682 }
1683
1684 #[test]
1685 fn test_read_btf_type_volatile() {
1686 let endianness = Endianness::default();
1687 let info = (BtfKind::Volatile as u32) << 24;
1688 let bpf_type = BtfType::Volatile(Volatile {
1689 name_offset: 0,
1690 info,
1691 btf_type: 0x24,
1692 });
1693 let data: &[u8] = &bpf_type.to_bytes();
1694 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Volatile(got) => {
1695 assert_eq!(got.to_bytes(), data);
1696 });
1697 }
1698
1699 #[test]
1700 fn test_read_btf_type_const() {
1701 let endianness = Endianness::default();
1702 let bpf_type = BtfType::Const(Const::new(1));
1703 let data: &[u8] = &bpf_type.to_bytes();
1704 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Const(got) => {
1705 assert_eq!(got.to_bytes(), data);
1706 });
1707 }
1708
1709 #[test]
1710 fn test_read_btf_type_restrict() {
1711 let endianness = Endianness::default();
1712 let info = (BtfKind::Restrict as u32) << 24;
1713 let bpf_type = BtfType::Restrict(Restrict {
1714 name_offset: 0,
1715 _info: info,
1716 btf_type: 4,
1717 });
1718 let data: &[u8] = &bpf_type.to_bytes();
1719 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Restrict(got) => {
1720 assert_eq!(got.to_bytes(), data);
1721 });
1722 }
1723
1724 #[test]
1725 fn test_read_btf_type_func() {
1726 let endianness = Endianness::default();
1727 let bpf_type = BtfType::Func(Func::new(0x000f8b17, 0xe4f0, FuncLinkage::Global));
1728 let data: &[u8] = &bpf_type.to_bytes();
1729 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Func(got) => {
1730 assert_eq!(got.to_bytes(), data);
1731 });
1732 }
1733
1734 #[test]
1735 fn test_read_btf_type_func_proto() {
1736 let endianness = Endianness::default();
1737 let params = vec![BtfParam {
1738 name_offset: 0,
1739 btf_type: 0x12,
1740 }];
1741 let bpf_type = BtfType::FuncProto(FuncProto::new(params, 0));
1742 let data: &[u8] = &bpf_type.to_bytes();
1743 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::FuncProto(got) => {
1744 assert_eq!(got.to_bytes(), data);
1745 });
1746 }
1747
1748 #[test]
1749 fn test_read_btf_type_func_var() {
1750 let endianness = Endianness::default();
1751 let bpf_type = BtfType::Var(Var::new(0, 0xf0, VarLinkage::Static));
1753 let data: &[u8] = &bpf_type.to_bytes();
1754 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Var(got) => {
1755 assert_eq!(got.to_bytes(), data);
1756 });
1757 }
1758
1759 #[test]
1760 fn test_read_btf_type_func_datasec() {
1761 let endianness = Endianness::default();
1762 let entries = vec![DataSecEntry {
1763 btf_type: 11,
1764 offset: 0,
1765 size: 4,
1766 }];
1767 let bpf_type = BtfType::DataSec(DataSec::new(0xd9, entries, 0));
1768 let data: &[u8] = &bpf_type.to_bytes();
1769 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::DataSec(DataSec {
1770 name_offset: _,
1771 info: _,
1772 size,
1773 entries,
1774 }) => {
1775 assert_eq!(size, 0);
1776 assert_matches!(*entries, [
1777 DataSecEntry {
1778 btf_type: 11,
1779 offset: 0,
1780 size: 4,
1781 }
1782 ]);
1783 }
1784 );
1785 }
1786
1787 #[test]
1788 fn test_read_btf_type_float() {
1789 let endianness = Endianness::default();
1790 let bpf_type = BtfType::Float(Float::new(0x02fd, 8));
1791 let data: &[u8] = &bpf_type.to_bytes();
1792 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Float(got) => {
1793 assert_eq!(got.to_bytes(), data);
1794 });
1795 }
1796
1797 #[test]
1798 fn test_write_btf_func_proto() {
1799 let params = vec![
1800 BtfParam {
1801 name_offset: 1,
1802 btf_type: 1,
1803 },
1804 BtfParam {
1805 name_offset: 3,
1806 btf_type: 1,
1807 },
1808 ];
1809 let func_proto = FuncProto::new(params, 2);
1810 let data = func_proto.to_bytes();
1811 assert_matches!(unsafe { BtfType::read(&data, Endianness::default()) }.unwrap(), BtfType::FuncProto(FuncProto {
1812 name_offset: _,
1813 info: _,
1814 return_type: _,
1815 params,
1816 }) => {
1817 assert_matches!(*params, [
1818 _,
1819 _,
1820 ])
1821 });
1822 }
1823
1824 #[test]
1825 fn test_types_are_compatible() {
1826 let mut btf = Btf::new();
1827 let name_offset = btf.add_string("u32");
1828 let u32t = btf.add_type(BtfType::Int(Int::new(name_offset, 4, IntEncoding::None, 0)));
1829 let name_offset = btf.add_string("u64");
1830 let u64t = btf.add_type(BtfType::Int(Int::new(name_offset, 8, IntEncoding::None, 0)));
1831 let name_offset = btf.add_string("widgets");
1832 let array_type = btf.add_type(BtfType::Array(Array::new(name_offset, u64t, u32t, 16)));
1833
1834 assert!(types_are_compatible(&btf, u32t, &btf, u32t).unwrap());
1835 assert!(types_are_compatible(&btf, u32t, &btf, u64t).unwrap());
1837 assert!(types_are_compatible(&btf, array_type, &btf, array_type).unwrap());
1838 }
1839
1840 #[test]
1841 pub fn test_read_btf_type_enum64() {
1842 let endianness = Endianness::default();
1843 let variants = vec![BtfEnum64::new(0, 0xbbbbbbbbaaaaaaaau64)];
1844 let bpf_type = BtfType::Enum64(Enum64::new(0, false, variants));
1845 let data: &[u8] = &bpf_type.to_bytes();
1846 assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Enum64(got) => {
1847 assert_eq!(got.to_bytes(), data);
1848 });
1849 }
1850}