12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850 |
- #![allow(missing_docs)]
- use alloc::{string::ToString, vec, vec::Vec};
- use core::{fmt::Display, mem, ptr};
- use object::Endianness;
- use crate::btf::{Btf, BtfError, MAX_RESOLVE_DEPTH};
- #[derive(Clone, Debug)]
- pub enum BtfType {
- Unknown,
- Fwd(Fwd),
- Const(Const),
- Volatile(Volatile),
- Restrict(Restrict),
- Ptr(Ptr),
- Typedef(Typedef),
- Func(Func),
- Int(Int),
- Float(Float),
- Enum(Enum),
- Array(Array),
- Struct(Struct),
- Union(Union),
- FuncProto(FuncProto),
- Var(Var),
- DataSec(DataSec),
- DeclTag(DeclTag),
- TypeTag(TypeTag),
- Enum64(Enum64),
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Fwd {
- pub(crate) name_offset: u32,
- info: u32,
- _unused: u32,
- }
- impl Fwd {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- bytes_of::<Fwd>(self).to_vec()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Fwd
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Self>()
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Const {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) btf_type: u32,
- }
- impl Const {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- bytes_of::<Const>(self).to_vec()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Const
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Self>()
- }
- pub(crate) fn new(btf_type: u32) -> Self {
- let info = (BtfKind::Const as u32) << 24;
- Self {
- name_offset: 0,
- info,
- btf_type,
- }
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Volatile {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) btf_type: u32,
- }
- impl Volatile {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- bytes_of::<Volatile>(self).to_vec()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Volatile
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Self>()
- }
- }
- #[derive(Clone, Debug)]
- pub struct Restrict {
- pub(crate) name_offset: u32,
- _info: u32,
- pub(crate) btf_type: u32,
- }
- impl Restrict {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- bytes_of::<Restrict>(self).to_vec()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Restrict
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Self>()
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Ptr {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) btf_type: u32,
- }
- impl Ptr {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- bytes_of::<Self>(self).to_vec()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Ptr
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Self>()
- }
- pub fn new(name_offset: u32, btf_type: u32) -> Self {
- let info = (BtfKind::Ptr as u32) << 24;
- Self {
- name_offset,
- info,
- btf_type,
- }
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Typedef {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) btf_type: u32,
- }
- impl Typedef {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- bytes_of::<Self>(self).to_vec()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Typedef
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Self>()
- }
- pub(crate) fn new(name_offset: u32, btf_type: u32) -> Self {
- let info = (BtfKind::Typedef as u32) << 24;
- Self {
- name_offset,
- info,
- btf_type,
- }
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Float {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) size: u32,
- }
- impl Float {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- bytes_of::<Self>(self).to_vec()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Float
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Self>()
- }
- pub fn new(name_offset: u32, size: u32) -> Self {
- let info = (BtfKind::Float as u32) << 24;
- Self {
- name_offset,
- info,
- size,
- }
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Func {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) btf_type: u32,
- }
- #[repr(u32)]
- #[derive(Clone, Debug, PartialEq, Eq)]
- pub enum FuncLinkage {
- Static = 0,
- Global = 1,
- Extern = 2,
- Unknown,
- }
- impl From<u32> for FuncLinkage {
- fn from(v: u32) -> Self {
- match v {
- 0 => FuncLinkage::Static,
- 1 => FuncLinkage::Global,
- 2 => FuncLinkage::Extern,
- _ => FuncLinkage::Unknown,
- }
- }
- }
- impl Func {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- bytes_of::<Self>(self).to_vec()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Func
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Self>()
- }
- pub fn new(name_offset: u32, proto: u32, linkage: FuncLinkage) -> Self {
- let mut info = (BtfKind::Func as u32) << 24;
- info |= (linkage as u32) & 0xFFFF;
- Self {
- name_offset,
- info,
- btf_type: proto,
- }
- }
- pub(crate) fn linkage(&self) -> FuncLinkage {
- (self.info & 0xFFF).into()
- }
- pub(crate) fn set_linkage(&mut self, linkage: FuncLinkage) {
- self.info = (self.info & 0xFFFF0000) | (linkage as u32) & 0xFFFF;
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct TypeTag {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) btf_type: u32,
- }
- impl TypeTag {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- bytes_of::<Self>(self).to_vec()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::TypeTag
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Self>()
- }
- pub fn new(name_offset: u32, btf_type: u32) -> Self {
- let info = (BtfKind::TypeTag as u32) << 24;
- Self {
- name_offset,
- info,
- btf_type,
- }
- }
- }
- #[repr(u32)]
- #[derive(Clone, Debug, Eq, PartialEq)]
- pub enum IntEncoding {
- None,
- Signed = 1,
- Char = 2,
- Bool = 4,
- Unknown,
- }
- impl From<u32> for IntEncoding {
- fn from(v: u32) -> Self {
- match v {
- 0 => IntEncoding::None,
- 1 => IntEncoding::Signed,
- 2 => IntEncoding::Char,
- 4 => IntEncoding::Bool,
- _ => IntEncoding::Unknown,
- }
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Int {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) size: u32,
- pub(crate) data: u32,
- }
- impl Int {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- let Self {
- name_offset,
- info,
- size,
- data,
- } = self;
- [
- bytes_of::<u32>(name_offset),
- bytes_of::<u32>(info),
- bytes_of::<u32>(size),
- bytes_of::<u32>(data),
- ]
- .concat()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Int
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Self>()
- }
- pub fn new(name_offset: u32, size: u32, encoding: IntEncoding, offset: u32) -> Self {
- let info = (BtfKind::Int as u32) << 24;
- let mut data = 0u32;
- data |= (encoding as u32 & 0x0f) << 24;
- data |= (offset & 0xff) << 16;
- data |= (size * 8) & 0xff;
- Self {
- name_offset,
- info,
- size,
- data,
- }
- }
- pub(crate) fn encoding(&self) -> IntEncoding {
- ((self.data & 0x0f000000) >> 24).into()
- }
- pub(crate) fn offset(&self) -> u32 {
- (self.data & 0x00ff0000) >> 16
- }
- // TODO: Remove directive this when this crate is pub
- #[cfg(test)]
- pub(crate) fn bits(&self) -> u32 {
- self.data & 0x000000ff
- }
- }
- #[repr(C)]
- #[derive(Debug, Clone)]
- pub struct BtfEnum {
- pub name_offset: u32,
- pub value: u32,
- }
- impl BtfEnum {
- pub fn new(name_offset: u32, value: u32) -> Self {
- Self { name_offset, value }
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Enum {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) size: u32,
- pub(crate) variants: Vec<BtfEnum>,
- }
- impl Enum {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- let Self {
- name_offset,
- info,
- size,
- variants,
- } = self;
- [
- bytes_of::<u32>(name_offset),
- bytes_of::<u32>(info),
- bytes_of::<u32>(size),
- ]
- .into_iter()
- .chain(variants.iter().flat_map(|BtfEnum { name_offset, value }| {
- [bytes_of::<u32>(name_offset), bytes_of::<u32>(value)]
- }))
- .flatten()
- .copied()
- .collect()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Enum
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Fwd>() + mem::size_of::<BtfEnum>() * self.variants.len()
- }
- pub fn new(name_offset: u32, signed: bool, variants: Vec<BtfEnum>) -> Self {
- let mut info = (BtfKind::Enum as u32) << 24;
- info |= (variants.len() as u32) & 0xFFFF;
- if signed {
- info |= 1 << 31;
- }
- Self {
- name_offset,
- info,
- size: 4,
- variants,
- }
- }
- pub(crate) fn is_signed(&self) -> bool {
- self.info >> 31 == 1
- }
- pub(crate) fn set_signed(&mut self, signed: bool) {
- if signed {
- self.info |= 1 << 31;
- } else {
- self.info &= !(1 << 31);
- }
- }
- }
- #[repr(C)]
- #[derive(Debug, Clone)]
- pub struct BtfEnum64 {
- pub(crate) name_offset: u32,
- pub(crate) value_low: u32,
- pub(crate) value_high: u32,
- }
- impl BtfEnum64 {
- pub fn new(name_offset: u32, value: u64) -> Self {
- Self {
- name_offset,
- value_low: value as u32,
- value_high: (value >> 32) as u32,
- }
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Enum64 {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) size: u32,
- pub(crate) variants: Vec<BtfEnum64>,
- }
- impl Enum64 {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- let Self {
- name_offset,
- info,
- size,
- variants,
- } = self;
- [
- bytes_of::<u32>(name_offset),
- bytes_of::<u32>(info),
- bytes_of::<u32>(size),
- ]
- .into_iter()
- .chain(variants.iter().flat_map(
- |BtfEnum64 {
- name_offset,
- value_low,
- value_high,
- }| {
- [
- bytes_of::<u32>(name_offset),
- bytes_of::<u32>(value_low),
- bytes_of::<u32>(value_high),
- ]
- },
- ))
- .flatten()
- .copied()
- .collect()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Enum64
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Fwd>() + mem::size_of::<BtfEnum64>() * self.variants.len()
- }
- pub(crate) fn is_signed(&self) -> bool {
- self.info >> 31 == 1
- }
- pub fn new(name_offset: u32, signed: bool, variants: Vec<BtfEnum64>) -> Self {
- let mut info = (BtfKind::Enum64 as u32) << 24;
- if signed {
- info |= 1 << 31
- };
- info |= (variants.len() as u32) & 0xFFFF;
- Enum64 {
- name_offset,
- info,
- // According to the documentation:
- //
- // https://www.kernel.org/doc/html/next/bpf/btf.html
- //
- // The size may be 1/2/4/8. Since BtfEnum64::new() takes a u64, we
- // can assume that the size is 8.
- size: 8,
- variants,
- }
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub(crate) struct BtfMember {
- pub(crate) name_offset: u32,
- pub(crate) btf_type: u32,
- pub(crate) offset: u32,
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Struct {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) size: u32,
- pub(crate) members: Vec<BtfMember>,
- }
- impl Struct {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- let Self {
- name_offset,
- info,
- size,
- members,
- } = self;
- [
- bytes_of::<u32>(name_offset),
- bytes_of::<u32>(info),
- bytes_of::<u32>(size),
- ]
- .into_iter()
- .chain(members.iter().flat_map(
- |BtfMember {
- name_offset,
- btf_type,
- offset,
- }| {
- [
- bytes_of::<u32>(name_offset),
- bytes_of::<u32>(btf_type),
- bytes_of::<u32>(offset),
- ]
- },
- ))
- .flatten()
- .copied()
- .collect()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Struct
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Fwd>() + mem::size_of::<BtfMember>() * self.members.len()
- }
- pub(crate) fn new(name_offset: u32, members: Vec<BtfMember>, size: u32) -> Self {
- let mut info = (BtfKind::Struct as u32) << 24;
- info |= (members.len() as u32) & 0xFFFF;
- Self {
- name_offset,
- info,
- size,
- members,
- }
- }
- pub(crate) fn member_bit_offset(&self, member: &BtfMember) -> usize {
- let k_flag = self.info >> 31 == 1;
- let bit_offset = if k_flag {
- member.offset & 0xFFFFFF
- } else {
- member.offset
- };
- bit_offset as usize
- }
- pub(crate) fn member_bit_field_size(&self, member: &BtfMember) -> usize {
- let k_flag = (self.info >> 31) == 1;
- let size = if k_flag { member.offset >> 24 } else { 0 };
- size as usize
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Union {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) size: u32,
- pub(crate) members: Vec<BtfMember>,
- }
- impl Union {
- pub(crate) fn new(name_offset: u32, size: u32, members: Vec<BtfMember>) -> Self {
- let mut info = (BtfKind::Union as u32) << 24;
- info |= (members.len() as u32) & 0xFFFF;
- Self {
- name_offset,
- info,
- size,
- members,
- }
- }
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- let Self {
- name_offset,
- info,
- size,
- members,
- } = self;
- [
- bytes_of::<u32>(name_offset),
- bytes_of::<u32>(info),
- bytes_of::<u32>(size),
- ]
- .into_iter()
- .chain(members.iter().flat_map(
- |BtfMember {
- name_offset,
- btf_type,
- offset,
- }| {
- [
- bytes_of::<u32>(name_offset),
- bytes_of::<u32>(btf_type),
- bytes_of::<u32>(offset),
- ]
- },
- ))
- .flatten()
- .copied()
- .collect()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Union
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Fwd>() + mem::size_of::<BtfMember>() * self.members.len()
- }
- pub(crate) fn member_bit_offset(&self, member: &BtfMember) -> usize {
- let k_flag = self.info >> 31 == 1;
- let bit_offset = if k_flag {
- member.offset & 0xFFFFFF
- } else {
- member.offset
- };
- bit_offset as usize
- }
- pub(crate) fn member_bit_field_size(&self, member: &BtfMember) -> usize {
- let k_flag = (self.info >> 31) == 1;
- let size = if k_flag { member.offset >> 24 } else { 0 };
- size as usize
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub(crate) struct BtfArray {
- pub(crate) element_type: u32,
- pub(crate) index_type: u32,
- pub(crate) len: u32,
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Array {
- pub(crate) name_offset: u32,
- info: u32,
- _unused: u32,
- pub(crate) array: BtfArray,
- }
- impl Array {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- let Self {
- name_offset,
- info,
- _unused,
- array,
- } = self;
- [
- bytes_of::<u32>(name_offset),
- bytes_of::<u32>(info),
- bytes_of::<u32>(_unused),
- bytes_of::<BtfArray>(array),
- ]
- .concat()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Array
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Self>()
- }
- #[cfg(test)]
- pub(crate) fn new(name_offset: u32, element_type: u32, index_type: u32, len: u32) -> Self {
- let info = (BtfKind::Array as u32) << 24;
- Self {
- name_offset,
- info,
- _unused: 0,
- array: BtfArray {
- element_type,
- index_type,
- len,
- },
- }
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct BtfParam {
- pub name_offset: u32,
- pub btf_type: u32,
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct FuncProto {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) return_type: u32,
- pub(crate) params: Vec<BtfParam>,
- }
- impl FuncProto {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- let Self {
- name_offset,
- info,
- return_type,
- params,
- } = self;
- [
- bytes_of::<u32>(name_offset),
- bytes_of::<u32>(info),
- bytes_of::<u32>(return_type),
- ]
- .into_iter()
- .chain(params.iter().flat_map(
- |BtfParam {
- name_offset,
- btf_type,
- }| { [bytes_of::<u32>(name_offset), bytes_of::<u32>(btf_type)] },
- ))
- .flatten()
- .copied()
- .collect()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::FuncProto
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Fwd>() + mem::size_of::<BtfParam>() * self.params.len()
- }
- pub fn new(params: Vec<BtfParam>, return_type: u32) -> Self {
- let mut info = (BtfKind::FuncProto as u32) << 24;
- info |= (params.len() as u32) & 0xFFFF;
- Self {
- name_offset: 0,
- info,
- return_type,
- params,
- }
- }
- }
- #[repr(u32)]
- #[derive(Clone, Debug, PartialEq, Eq)]
- pub enum VarLinkage {
- Static,
- Global,
- Extern,
- Unknown,
- }
- impl From<u32> for VarLinkage {
- fn from(v: u32) -> Self {
- match v {
- 0 => VarLinkage::Static,
- 1 => VarLinkage::Global,
- 2 => VarLinkage::Extern,
- _ => VarLinkage::Unknown,
- }
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct Var {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) btf_type: u32,
- pub(crate) linkage: VarLinkage,
- }
- impl Var {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- let Self {
- name_offset,
- info,
- btf_type,
- linkage,
- } = self;
- [
- bytes_of::<u32>(name_offset),
- bytes_of::<u32>(info),
- bytes_of::<u32>(btf_type),
- bytes_of::<VarLinkage>(linkage),
- ]
- .concat()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::Var
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Self>()
- }
- pub fn new(name_offset: u32, btf_type: u32, linkage: VarLinkage) -> Self {
- let info = (BtfKind::Var as u32) << 24;
- Self {
- name_offset,
- info,
- btf_type,
- linkage,
- }
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct DataSecEntry {
- pub btf_type: u32,
- pub offset: u32,
- pub size: u32,
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct DataSec {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) size: u32,
- pub(crate) entries: Vec<DataSecEntry>,
- }
- impl DataSec {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- let Self {
- name_offset,
- info,
- size,
- entries,
- } = self;
- [
- bytes_of::<u32>(name_offset),
- bytes_of::<u32>(info),
- bytes_of::<u32>(size),
- ]
- .into_iter()
- .chain(entries.iter().flat_map(
- |DataSecEntry {
- btf_type,
- offset,
- size,
- }| {
- [
- bytes_of::<u32>(btf_type),
- bytes_of::<u32>(offset),
- bytes_of::<u32>(size),
- ]
- },
- ))
- .flatten()
- .copied()
- .collect()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::DataSec
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Fwd>() + mem::size_of::<DataSecEntry>() * self.entries.len()
- }
- pub fn new(name_offset: u32, entries: Vec<DataSecEntry>, size: u32) -> Self {
- let mut info = (BtfKind::DataSec as u32) << 24;
- info |= (entries.len() as u32) & 0xFFFF;
- Self {
- name_offset,
- info,
- size,
- entries,
- }
- }
- }
- #[repr(C)]
- #[derive(Clone, Debug)]
- pub struct DeclTag {
- pub(crate) name_offset: u32,
- info: u32,
- pub(crate) btf_type: u32,
- pub(crate) component_index: i32,
- }
- impl DeclTag {
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- let Self {
- name_offset,
- info,
- btf_type,
- component_index,
- } = self;
- [
- bytes_of::<u32>(name_offset),
- bytes_of::<u32>(info),
- bytes_of::<u32>(btf_type),
- bytes_of::<i32>(component_index),
- ]
- .concat()
- }
- pub(crate) fn kind(&self) -> BtfKind {
- BtfKind::DeclTag
- }
- pub(crate) fn type_info_size(&self) -> usize {
- mem::size_of::<Self>()
- }
- pub fn new(name_offset: u32, btf_type: u32, component_index: i32) -> Self {
- let info = (BtfKind::DeclTag as u32) << 24;
- Self {
- name_offset,
- info,
- btf_type,
- component_index,
- }
- }
- }
- #[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
- #[repr(u32)]
- pub enum BtfKind {
- #[default]
- Unknown = 0,
- Int = 1,
- Ptr = 2,
- Array = 3,
- Struct = 4,
- Union = 5,
- Enum = 6,
- Fwd = 7,
- Typedef = 8,
- Volatile = 9,
- Const = 10,
- Restrict = 11,
- Func = 12,
- FuncProto = 13,
- Var = 14,
- DataSec = 15,
- Float = 16,
- DeclTag = 17,
- TypeTag = 18,
- Enum64 = 19,
- }
- impl TryFrom<u32> for BtfKind {
- type Error = BtfError;
- fn try_from(v: u32) -> Result<Self, Self::Error> {
- use BtfKind::*;
- Ok(match v {
- 0 => Unknown,
- 1 => Int,
- 2 => Ptr,
- 3 => Array,
- 4 => Struct,
- 5 => Union,
- 6 => Enum,
- 7 => Fwd,
- 8 => Typedef,
- 9 => Volatile,
- 10 => Const,
- 11 => Restrict,
- 12 => Func,
- 13 => FuncProto,
- 14 => Var,
- 15 => DataSec,
- 16 => Float,
- 17 => DeclTag,
- 18 => TypeTag,
- 19 => Enum64,
- kind => return Err(BtfError::InvalidTypeKind { kind }),
- })
- }
- }
- impl Display for BtfKind {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- match self {
- BtfKind::Unknown => write!(f, "[UNKNOWN]"),
- BtfKind::Int => write!(f, "[INT]"),
- BtfKind::Float => write!(f, "[FLOAT]"),
- BtfKind::Ptr => write!(f, "[PTR]"),
- BtfKind::Array => write!(f, "[ARRAY]"),
- BtfKind::Struct => write!(f, "[STRUCT]"),
- BtfKind::Union => write!(f, "[UNION]"),
- BtfKind::Enum => write!(f, "[ENUM]"),
- BtfKind::Fwd => write!(f, "[FWD]"),
- BtfKind::Typedef => write!(f, "[TYPEDEF]"),
- BtfKind::Volatile => write!(f, "[VOLATILE]"),
- BtfKind::Const => write!(f, "[CONST]"),
- BtfKind::Restrict => write!(f, "[RESTRICT]"),
- BtfKind::Func => write!(f, "[FUNC]"),
- BtfKind::FuncProto => write!(f, "[FUNC_PROTO]"),
- BtfKind::Var => write!(f, "[VAR]"),
- BtfKind::DataSec => write!(f, "[DATASEC]"),
- BtfKind::DeclTag => write!(f, "[DECL_TAG]"),
- BtfKind::TypeTag => write!(f, "[TYPE_TAG]"),
- BtfKind::Enum64 => write!(f, "[ENUM64]"),
- }
- }
- }
- unsafe fn read<T>(data: &[u8]) -> Result<T, BtfError> {
- if mem::size_of::<T>() > data.len() {
- return Err(BtfError::InvalidTypeInfo);
- }
- Ok(ptr::read_unaligned::<T>(data.as_ptr() as *const T))
- }
- unsafe fn read_array<T>(data: &[u8], len: usize) -> Result<Vec<T>, BtfError> {
- if mem::size_of::<T>() * len > data.len() {
- return Err(BtfError::InvalidTypeInfo);
- }
- let data = &data[0..mem::size_of::<T>() * len];
- let r = data
- .chunks(mem::size_of::<T>())
- .map(|chunk| ptr::read_unaligned(chunk.as_ptr() as *const T))
- .collect();
- Ok(r)
- }
- impl BtfType {
- #[allow(unused_unsafe)]
- pub(crate) unsafe fn read(data: &[u8], endianness: Endianness) -> Result<BtfType, BtfError> {
- let ty = unsafe { read_array::<u32>(data, 3)? };
- let data = &data[mem::size_of::<u32>() * 3..];
- let vlen = type_vlen(ty[1]);
- Ok(match type_kind(ty[1])? {
- BtfKind::Unknown => BtfType::Unknown,
- BtfKind::Fwd => BtfType::Fwd(Fwd {
- name_offset: ty[0],
- info: ty[1],
- _unused: 0,
- }),
- BtfKind::Const => BtfType::Const(Const {
- name_offset: ty[0],
- info: ty[1],
- btf_type: ty[2],
- }),
- BtfKind::Volatile => BtfType::Volatile(Volatile {
- name_offset: ty[0],
- info: ty[1],
- btf_type: ty[2],
- }),
- BtfKind::Restrict => BtfType::Restrict(Restrict {
- name_offset: ty[0],
- _info: ty[1],
- btf_type: ty[2],
- }),
- BtfKind::Ptr => BtfType::Ptr(Ptr {
- name_offset: ty[0],
- info: ty[1],
- btf_type: ty[2],
- }),
- BtfKind::Typedef => BtfType::Typedef(Typedef {
- name_offset: ty[0],
- info: ty[1],
- btf_type: ty[2],
- }),
- BtfKind::Func => BtfType::Func(Func {
- name_offset: ty[0],
- info: ty[1],
- btf_type: ty[2],
- }),
- BtfKind::Int => {
- if mem::size_of::<u32>() > data.len() {
- return Err(BtfError::InvalidTypeInfo);
- }
- let read_u32 = if endianness == Endianness::Little {
- u32::from_le_bytes
- } else {
- u32::from_be_bytes
- };
- BtfType::Int(Int {
- name_offset: ty[0],
- info: ty[1],
- size: ty[2],
- data: read_u32(data[..mem::size_of::<u32>()].try_into().unwrap()),
- })
- }
- BtfKind::Float => BtfType::Float(Float {
- name_offset: ty[0],
- info: ty[1],
- size: ty[2],
- }),
- BtfKind::Enum => BtfType::Enum(Enum {
- name_offset: ty[0],
- info: ty[1],
- size: ty[2],
- variants: unsafe { read_array::<BtfEnum>(data, vlen)? },
- }),
- BtfKind::Enum64 => BtfType::Enum64(Enum64 {
- name_offset: ty[0],
- info: ty[1],
- size: ty[2],
- variants: unsafe { read_array::<BtfEnum64>(data, vlen)? },
- }),
- BtfKind::Array => BtfType::Array(Array {
- name_offset: ty[0],
- info: ty[1],
- _unused: 0,
- array: unsafe { read(data)? },
- }),
- BtfKind::Struct => BtfType::Struct(Struct {
- name_offset: ty[0],
- info: ty[1],
- size: ty[2],
- members: unsafe { read_array::<BtfMember>(data, vlen)? },
- }),
- BtfKind::Union => BtfType::Union(Union {
- name_offset: ty[0],
- info: ty[1],
- size: ty[2],
- members: unsafe { read_array::<BtfMember>(data, vlen)? },
- }),
- BtfKind::FuncProto => BtfType::FuncProto(FuncProto {
- name_offset: ty[0],
- info: ty[1],
- return_type: ty[2],
- params: unsafe { read_array::<BtfParam>(data, vlen)? },
- }),
- BtfKind::Var => BtfType::Var(Var {
- name_offset: ty[0],
- info: ty[1],
- btf_type: ty[2],
- linkage: unsafe { read(data)? },
- }),
- BtfKind::DataSec => BtfType::DataSec(DataSec {
- name_offset: ty[0],
- info: ty[1],
- size: ty[2],
- entries: unsafe { read_array::<DataSecEntry>(data, vlen)? },
- }),
- BtfKind::DeclTag => BtfType::DeclTag(DeclTag {
- name_offset: ty[0],
- info: ty[1],
- btf_type: ty[2],
- component_index: unsafe { read(data)? },
- }),
- BtfKind::TypeTag => BtfType::TypeTag(TypeTag {
- name_offset: ty[0],
- info: ty[1],
- btf_type: ty[2],
- }),
- })
- }
- pub(crate) fn to_bytes(&self) -> Vec<u8> {
- match self {
- BtfType::Unknown => vec![],
- BtfType::Fwd(t) => t.to_bytes(),
- BtfType::Const(t) => t.to_bytes(),
- BtfType::Volatile(t) => t.to_bytes(),
- BtfType::Restrict(t) => t.to_bytes(),
- BtfType::Ptr(t) => t.to_bytes(),
- BtfType::Typedef(t) => t.to_bytes(),
- BtfType::Func(t) => t.to_bytes(),
- BtfType::Int(t) => t.to_bytes(),
- BtfType::Float(t) => t.to_bytes(),
- BtfType::Enum(t) => t.to_bytes(),
- BtfType::Enum64(t) => t.to_bytes(),
- BtfType::Array(t) => t.to_bytes(),
- BtfType::Struct(t) => t.to_bytes(),
- BtfType::Union(t) => t.to_bytes(),
- BtfType::FuncProto(t) => t.to_bytes(),
- BtfType::Var(t) => t.to_bytes(),
- BtfType::DataSec(t) => t.to_bytes(),
- BtfType::DeclTag(t) => t.to_bytes(),
- BtfType::TypeTag(t) => t.to_bytes(),
- }
- }
- pub(crate) fn size(&self) -> Option<u32> {
- match self {
- BtfType::Int(t) => Some(t.size),
- BtfType::Float(t) => Some(t.size),
- BtfType::Enum(t) => Some(t.size),
- BtfType::Enum64(t) => Some(t.size),
- BtfType::Struct(t) => Some(t.size),
- BtfType::Union(t) => Some(t.size),
- BtfType::DataSec(t) => Some(t.size),
- BtfType::Ptr(_) => Some(mem::size_of::<&()>() as u32),
- _ => None,
- }
- }
- pub(crate) fn btf_type(&self) -> Option<u32> {
- match self {
- BtfType::Const(t) => Some(t.btf_type),
- BtfType::Volatile(t) => Some(t.btf_type),
- BtfType::Restrict(t) => Some(t.btf_type),
- BtfType::Ptr(t) => Some(t.btf_type),
- BtfType::Typedef(t) => Some(t.btf_type),
- // FuncProto contains the return type here, and doesn't directly reference another type
- BtfType::FuncProto(t) => Some(t.return_type),
- BtfType::Var(t) => Some(t.btf_type),
- BtfType::DeclTag(t) => Some(t.btf_type),
- BtfType::TypeTag(t) => Some(t.btf_type),
- _ => None,
- }
- }
- pub(crate) fn type_info_size(&self) -> usize {
- match self {
- BtfType::Unknown => mem::size_of::<Fwd>(),
- BtfType::Fwd(t) => t.type_info_size(),
- BtfType::Const(t) => t.type_info_size(),
- BtfType::Volatile(t) => t.type_info_size(),
- BtfType::Restrict(t) => t.type_info_size(),
- BtfType::Ptr(t) => t.type_info_size(),
- BtfType::Typedef(t) => t.type_info_size(),
- BtfType::Func(t) => t.type_info_size(),
- BtfType::Int(t) => t.type_info_size(),
- BtfType::Float(t) => t.type_info_size(),
- BtfType::Enum(t) => t.type_info_size(),
- BtfType::Enum64(t) => t.type_info_size(),
- BtfType::Array(t) => t.type_info_size(),
- BtfType::Struct(t) => t.type_info_size(),
- BtfType::Union(t) => t.type_info_size(),
- BtfType::FuncProto(t) => t.type_info_size(),
- BtfType::Var(t) => t.type_info_size(),
- BtfType::DataSec(t) => t.type_info_size(),
- BtfType::DeclTag(t) => t.type_info_size(),
- BtfType::TypeTag(t) => t.type_info_size(),
- }
- }
- pub(crate) fn name_offset(&self) -> u32 {
- match self {
- BtfType::Unknown => 0,
- BtfType::Fwd(t) => t.name_offset,
- BtfType::Const(t) => t.name_offset,
- BtfType::Volatile(t) => t.name_offset,
- BtfType::Restrict(t) => t.name_offset,
- BtfType::Ptr(t) => t.name_offset,
- BtfType::Typedef(t) => t.name_offset,
- BtfType::Func(t) => t.name_offset,
- BtfType::Int(t) => t.name_offset,
- BtfType::Float(t) => t.name_offset,
- BtfType::Enum(t) => t.name_offset,
- BtfType::Enum64(t) => t.name_offset,
- BtfType::Array(t) => t.name_offset,
- BtfType::Struct(t) => t.name_offset,
- BtfType::Union(t) => t.name_offset,
- BtfType::FuncProto(t) => t.name_offset,
- BtfType::Var(t) => t.name_offset,
- BtfType::DataSec(t) => t.name_offset,
- BtfType::DeclTag(t) => t.name_offset,
- BtfType::TypeTag(t) => t.name_offset,
- }
- }
- pub(crate) fn kind(&self) -> BtfKind {
- match self {
- BtfType::Unknown => BtfKind::Unknown,
- BtfType::Fwd(t) => t.kind(),
- BtfType::Const(t) => t.kind(),
- BtfType::Volatile(t) => t.kind(),
- BtfType::Restrict(t) => t.kind(),
- BtfType::Ptr(t) => t.kind(),
- BtfType::Typedef(t) => t.kind(),
- BtfType::Func(t) => t.kind(),
- BtfType::Int(t) => t.kind(),
- BtfType::Float(t) => t.kind(),
- BtfType::Enum(t) => t.kind(),
- BtfType::Enum64(t) => t.kind(),
- BtfType::Array(t) => t.kind(),
- BtfType::Struct(t) => t.kind(),
- BtfType::Union(t) => t.kind(),
- BtfType::FuncProto(t) => t.kind(),
- BtfType::Var(t) => t.kind(),
- BtfType::DataSec(t) => t.kind(),
- BtfType::DeclTag(t) => t.kind(),
- BtfType::TypeTag(t) => t.kind(),
- }
- }
- pub(crate) fn is_composite(&self) -> bool {
- matches!(self, BtfType::Struct(_) | BtfType::Union(_))
- }
- pub(crate) fn members(&self) -> Option<impl Iterator<Item = &BtfMember>> {
- match self {
- BtfType::Struct(t) => Some(t.members.iter()),
- BtfType::Union(t) => Some(t.members.iter()),
- _ => None,
- }
- }
- pub(crate) fn member_bit_field_size(&self, member: &BtfMember) -> Option<usize> {
- match self {
- BtfType::Struct(t) => Some(t.member_bit_field_size(member)),
- BtfType::Union(t) => Some(t.member_bit_field_size(member)),
- _ => None,
- }
- }
- pub(crate) fn member_bit_offset(&self, member: &BtfMember) -> Option<usize> {
- match self {
- BtfType::Struct(t) => Some(t.member_bit_offset(member)),
- BtfType::Union(t) => Some(t.member_bit_offset(member)),
- _ => None,
- }
- }
- pub(crate) fn is_compatible(&self, other: &BtfType) -> bool {
- if self.kind() == other.kind() {
- return true;
- }
- matches!(
- (self.kind(), other.kind()),
- (BtfKind::Enum, BtfKind::Enum64) | (BtfKind::Enum64, BtfKind::Enum)
- )
- }
- }
- fn type_kind(info: u32) -> Result<BtfKind, BtfError> {
- ((info >> 24) & 0x1F).try_into()
- }
- fn type_vlen(info: u32) -> usize {
- (info & 0xFFFF) as usize
- }
- pub(crate) fn types_are_compatible(
- local_btf: &Btf,
- root_local_id: u32,
- target_btf: &Btf,
- root_target_id: u32,
- ) -> Result<bool, BtfError> {
- let mut local_id = root_local_id;
- let mut target_id = root_target_id;
- let local_ty = local_btf.type_by_id(local_id)?;
- let target_ty = target_btf.type_by_id(target_id)?;
- if !local_ty.is_compatible(target_ty) {
- return Ok(false);
- }
- for () in core::iter::repeat_n((), MAX_RESOLVE_DEPTH) {
- local_id = local_btf.resolve_type(local_id)?;
- target_id = target_btf.resolve_type(target_id)?;
- let local_ty = local_btf.type_by_id(local_id)?;
- let target_ty = target_btf.type_by_id(target_id)?;
- if !local_ty.is_compatible(target_ty) {
- return Ok(false);
- }
- match local_ty {
- BtfType::Unknown
- | BtfType::Struct(_)
- | BtfType::Union(_)
- | BtfType::Enum(_)
- | BtfType::Enum64(_)
- | BtfType::Fwd(_)
- | BtfType::Float(_) => return Ok(true),
- BtfType::Int(local) => {
- if let BtfType::Int(target) = target_ty {
- return Ok(local.offset() == 0 && target.offset() == 0);
- }
- }
- BtfType::Ptr(local) => {
- if let BtfType::Ptr(target) = target_ty {
- local_id = local.btf_type;
- target_id = target.btf_type;
- continue;
- }
- }
- BtfType::Array(Array { array: local, .. }) => {
- if let BtfType::Array(Array { array: target, .. }) = target_ty {
- local_id = local.element_type;
- target_id = target.element_type;
- continue;
- }
- }
- BtfType::FuncProto(local) => {
- if let BtfType::FuncProto(target) = target_ty {
- if local.params.len() != target.params.len() {
- return Ok(false);
- }
- for (l_param, t_param) in local.params.iter().zip(target.params.iter()) {
- let local_id = local_btf.resolve_type(l_param.btf_type)?;
- let target_id = target_btf.resolve_type(t_param.btf_type)?;
- if !types_are_compatible(local_btf, local_id, target_btf, target_id)? {
- return Ok(false);
- }
- }
- local_id = local.return_type;
- target_id = target.return_type;
- continue;
- }
- }
- local_ty => panic!("unexpected type {:?}", local_ty),
- }
- }
- Err(BtfError::MaximumTypeDepthReached { type_id: local_id })
- }
- pub(crate) fn fields_are_compatible(
- local_btf: &Btf,
- mut local_id: u32,
- target_btf: &Btf,
- mut target_id: u32,
- ) -> Result<bool, BtfError> {
- for () in core::iter::repeat_n((), MAX_RESOLVE_DEPTH) {
- local_id = local_btf.resolve_type(local_id)?;
- target_id = target_btf.resolve_type(target_id)?;
- let local_ty = local_btf.type_by_id(local_id)?;
- let target_ty = target_btf.type_by_id(target_id)?;
- if local_ty.is_composite() && target_ty.is_composite() {
- return Ok(true);
- }
- if !local_ty.is_compatible(target_ty) {
- return Ok(false);
- }
- match local_ty {
- BtfType::Fwd(_) | BtfType::Enum(_) | BtfType::Enum64(_) => {
- let flavorless_name =
- |name: &str| name.split_once("___").map_or(name, |x| x.0).to_string();
- let local_name = flavorless_name(&local_btf.type_name(local_ty)?);
- let target_name = flavorless_name(&target_btf.type_name(target_ty)?);
- return Ok(local_name == target_name);
- }
- BtfType::Int(local) => {
- if let BtfType::Int(target) = target_ty {
- return Ok(local.offset() == 0 && target.offset() == 0);
- }
- }
- BtfType::Float(_) => return Ok(true),
- BtfType::Ptr(_) => return Ok(true),
- BtfType::Array(Array { array: local, .. }) => {
- if let BtfType::Array(Array { array: target, .. }) = target_ty {
- local_id = local.element_type;
- target_id = target.element_type;
- continue;
- }
- }
- local_ty => panic!("unexpected type {:?}", local_ty),
- }
- }
- Err(BtfError::MaximumTypeDepthReached { type_id: local_id })
- }
- fn bytes_of<T>(val: &T) -> &[u8] {
- // Safety: all btf types are POD
- unsafe { crate::util::bytes_of(val) }
- }
- #[cfg(test)]
- mod tests {
- use assert_matches::assert_matches;
- use super::*;
- #[test]
- fn test_read_btf_type_int() {
- let endianness = Endianness::default();
- let bpf_type = BtfType::Int(Int::new(1, 8, IntEncoding::None, 0));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Int(new @ Int {
- name_offset,
- info: _,
- size,
- data: _,
- }) => {
- assert_eq!(name_offset, 1);
- assert_eq!(size, 8);
- assert_eq!(new.bits(), 64);
- assert_eq!(new.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_ptr() {
- let endianness = Endianness::default();
- let bpf_type = BtfType::Ptr(Ptr::new(0, 0x06));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Ptr(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_array() {
- let endianness = Endianness::default();
- let bpf_type = BtfType::Array(Array::new(0, 1, 0x12, 2));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Array(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_struct() {
- let endianness = Endianness::default();
- let members = vec![BtfMember {
- name_offset: 0x0247,
- btf_type: 0x12,
- offset: 0,
- }];
- let bpf_type = BtfType::Struct(Struct::new(0, members, 4));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Struct(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_union() {
- let endianness = Endianness::default();
- let members = vec![BtfMember {
- name_offset: 0x040d,
- btf_type: 0x68,
- offset: 0,
- }];
- let bpf_type = BtfType::Union(Union::new(0, 4, members));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Union(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_enum() {
- let endianness = Endianness::default();
- let enum1 = BtfEnum::new(0xc9, 0);
- let enum2 = BtfEnum::new(0xcf, 1);
- let variants = vec![enum1, enum2];
- let bpf_type = BtfType::Enum(Enum::new(0, false, variants));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Enum(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_fwd() {
- let endianness = Endianness::default();
- let info = (BtfKind::Fwd as u32) << 24;
- let bpf_type = BtfType::Fwd(Fwd {
- name_offset: 0x550b,
- info,
- _unused: 0,
- });
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Fwd(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_typedef() {
- let endianness = Endianness::default();
- let bpf_type = BtfType::Typedef(Typedef::new(0x31, 0x0b));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Typedef(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_volatile() {
- let endianness = Endianness::default();
- let info = (BtfKind::Volatile as u32) << 24;
- let bpf_type = BtfType::Volatile(Volatile {
- name_offset: 0,
- info,
- btf_type: 0x24,
- });
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Volatile(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_const() {
- let endianness = Endianness::default();
- let bpf_type = BtfType::Const(Const::new(1));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Const(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_restrict() {
- let endianness = Endianness::default();
- let info = (BtfKind::Restrict as u32) << 24;
- let bpf_type = BtfType::Restrict(Restrict {
- name_offset: 0,
- _info: info,
- btf_type: 4,
- });
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Restrict(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_func() {
- let endianness = Endianness::default();
- let bpf_type = BtfType::Func(Func::new(0x000f8b17, 0xe4f0, FuncLinkage::Global));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Func(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_func_proto() {
- let endianness = Endianness::default();
- let params = vec![BtfParam {
- name_offset: 0,
- btf_type: 0x12,
- }];
- let bpf_type = BtfType::FuncProto(FuncProto::new(params, 0));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::FuncProto(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_func_var() {
- let endianness = Endianness::default();
- // NOTE: There was no data in /sys/kernell/btf/vmlinux for this type
- let bpf_type = BtfType::Var(Var::new(0, 0xf0, VarLinkage::Static));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Var(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_read_btf_type_func_datasec() {
- let endianness = Endianness::default();
- let entries = vec![DataSecEntry {
- btf_type: 11,
- offset: 0,
- size: 4,
- }];
- let bpf_type = BtfType::DataSec(DataSec::new(0xd9, entries, 0));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::DataSec(DataSec {
- name_offset: _,
- info: _,
- size,
- entries,
- }) => {
- assert_eq!(size, 0);
- assert_matches!(*entries, [
- DataSecEntry {
- btf_type: 11,
- offset: 0,
- size: 4,
- }
- ]);
- }
- );
- }
- #[test]
- fn test_read_btf_type_float() {
- let endianness = Endianness::default();
- let bpf_type = BtfType::Float(Float::new(0x02fd, 8));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Float(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- #[test]
- fn test_write_btf_func_proto() {
- let params = vec![
- BtfParam {
- name_offset: 1,
- btf_type: 1,
- },
- BtfParam {
- name_offset: 3,
- btf_type: 1,
- },
- ];
- let func_proto = FuncProto::new(params, 2);
- let data = func_proto.to_bytes();
- assert_matches!(unsafe { BtfType::read(&data, Endianness::default()) }.unwrap(), BtfType::FuncProto(FuncProto {
- name_offset: _,
- info: _,
- return_type: _,
- params,
- }) => {
- assert_matches!(*params, [
- _,
- _,
- ])
- });
- }
- #[test]
- fn test_types_are_compatible() {
- let mut btf = Btf::new();
- let name_offset = btf.add_string("u32");
- let u32t = btf.add_type(BtfType::Int(Int::new(name_offset, 4, IntEncoding::None, 0)));
- let name_offset = btf.add_string("u64");
- let u64t = btf.add_type(BtfType::Int(Int::new(name_offset, 8, IntEncoding::None, 0)));
- let name_offset = btf.add_string("widgets");
- let array_type = btf.add_type(BtfType::Array(Array::new(name_offset, u64t, u32t, 16)));
- assert!(types_are_compatible(&btf, u32t, &btf, u32t).unwrap());
- // int types are compatible if offsets match. size and encoding aren't compared
- assert!(types_are_compatible(&btf, u32t, &btf, u64t).unwrap());
- assert!(types_are_compatible(&btf, array_type, &btf, array_type).unwrap());
- }
- #[test]
- pub fn test_read_btf_type_enum64() {
- let endianness = Endianness::default();
- let variants = vec![BtfEnum64::new(0, 0xbbbbbbbbaaaaaaaau64)];
- let bpf_type = BtfType::Enum64(Enum64::new(0, false, variants));
- let data: &[u8] = &bpf_type.to_bytes();
- assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Enum64(got) => {
- assert_eq!(got.to_bytes(), data);
- });
- }
- }
|