Merge pull request #285 from dave-tucker/btf-redux

aya: Improved BTF Type API
pull/379/head
Dave Tucker 2 years ago committed by GitHub
commit 66b4f79eca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,7 +1,8 @@
use std::{ use std::{
borrow::Cow, borrow::Cow,
collections::HashMap, collections::HashMap,
ffi::{c_void, CStr, CString}, convert::TryInto,
ffi::{CStr, CString},
fs, io, mem, fs, io, mem,
path::{Path, PathBuf}, path::{Path, PathBuf},
ptr, ptr,
@ -14,17 +15,17 @@ use object::Endianness;
use thiserror::Error; use thiserror::Error;
use crate::{ use crate::{
generated::{btf_enum, btf_ext_header, btf_func_linkage, btf_header, btf_member}, generated::{btf_ext_header, btf_header},
obj::btf::{relocation::Relocation, BtfKind, BtfType}, obj::btf::{
info::{FuncSecInfo, LineSecInfo},
relocation::Relocation,
Array, BtfEnum, BtfKind, BtfMember, BtfType, Const, Enum, FuncInfo, FuncLinkage, Int,
IntEncoding, LineInfo, Struct, Typedef, VarLinkage,
},
util::bytes_of, util::bytes_of,
Features, Features,
}; };
use super::{
info::{FuncSecInfo, LineSecInfo},
type_vlen, FuncInfo, LineInfo,
};
pub(crate) const MAX_RESOLVE_DEPTH: u8 = 32; pub(crate) const MAX_RESOLVE_DEPTH: u8 = 32;
pub(crate) const MAX_SPEC_LEN: usize = 64; pub(crate) const MAX_SPEC_LEN: usize = 64;
@ -198,16 +199,16 @@ impl Btf {
pub(crate) fn add_string(&mut self, name: String) -> u32 { pub(crate) fn add_string(&mut self, name: String) -> u32 {
let str = CString::new(name).unwrap(); let str = CString::new(name).unwrap();
let name_off = self.strings.len(); let name_offset = self.strings.len();
self.strings.extend(str.as_c_str().to_bytes_with_nul()); self.strings.extend(str.as_c_str().to_bytes_with_nul());
self.header.str_len = self.strings.len() as u32; self.header.str_len = self.strings.len() as u32;
name_off as u32 name_offset as u32
} }
pub(crate) fn add_type(&mut self, type_: BtfType) -> u32 { pub(crate) fn add_type(&mut self, btf_type: BtfType) -> u32 {
let size = type_.type_info_size() as u32; let size = btf_type.type_info_size() as u32;
let type_id = self.types.len(); let type_id = self.types.len();
self.types.push(type_); self.types.push(btf_type);
self.header.type_len += size; self.header.type_len += size;
self.header.str_off += size; self.header.str_off += size;
type_id as u32 type_id as u32
@ -315,35 +316,23 @@ impl Btf {
self.types.resolve_type(root_type_id) self.types.resolve_type(root_type_id)
} }
pub(crate) fn type_name(&self, ty: &BtfType) -> Result<Option<Cow<'_, str>>, BtfError> { pub(crate) fn type_name(&self, ty: &BtfType) -> Result<Cow<'_, str>, BtfError> {
ty.name_offset().map(|off| self.string_at(off)).transpose() self.string_at(ty.name_offset())
} }
pub(crate) fn err_type_name(&self, ty: &BtfType) -> Option<String> { pub(crate) fn err_type_name(&self, ty: &BtfType) -> Option<String> {
ty.name_offset() self.string_at(ty.name_offset()).ok().map(String::from)
.and_then(|off| self.string_at(off).ok().map(String::from))
} }
pub(crate) fn id_by_type_name_kind(&self, name: &str, kind: BtfKind) -> Result<u32, BtfError> { pub(crate) fn id_by_type_name_kind(&self, name: &str, kind: BtfKind) -> Result<u32, BtfError> {
for (type_id, ty) in self.types().enumerate() { for (type_id, ty) in self.types().enumerate() {
match ty.kind()? { if ty.kind() != kind {
Some(k) => { continue;
if k != kind {
continue;
}
}
None => continue,
} }
if self.type_name(ty)? == name {
match self.type_name(ty)? { return Ok(type_id as u32);
Some(ty_name) => {
if ty_name == name {
return Ok(type_id as u32);
}
continue;
}
None => continue,
} }
continue;
} }
Err(BtfError::UnknownBtfTypeName { Err(BtfError::UnknownBtfTypeName {
@ -356,41 +345,24 @@ impl Btf {
let mut n_elems = 1; let mut n_elems = 1;
for _ in 0..MAX_RESOLVE_DEPTH { for _ in 0..MAX_RESOLVE_DEPTH {
let ty = self.types.type_by_id(type_id)?; let ty = self.types.type_by_id(type_id)?;
use BtfType::*;
let size = match ty { let size = match ty {
Int(ty, _) BtfType::Array(Array { array, .. }) => {
| Struct(ty, _) n_elems = array.len;
| Union(ty, _) type_id = array.element_type;
| Enum(ty, _)
| DataSec(ty, _)
| Float(ty) => {
// Safety: union
unsafe { ty.__bindgen_anon_1.size as usize }
}
Ptr(_) => mem::size_of::<*const c_void>(), // FIXME
Typedef(ty)
| Volatile(ty)
| Const(ty)
| Restrict(ty)
| Var(ty, _)
| DeclTag(ty, _)
| TypeTag(ty) => {
// Safety: union
type_id = unsafe { ty.__bindgen_anon_1.type_ };
continue; continue;
} }
Array(_, array) => { other => {
n_elems *= array.nelems as usize; if let Some(size) = other.size() {
type_id = array.type_; size
continue; } else if let Some(next) = other.btf_type() {
} type_id = next;
Unknown | Fwd(_) | Func(_) | FuncProto(_, _) => { continue;
return Err(BtfError::UnexpectedBtfType { type_id }) } else {
return Err(BtfError::UnexpectedBtfType { type_id });
}
} }
}; };
return Ok((size * n_elems) as usize);
return Ok(size * n_elems);
} }
Err(BtfError::MaximumTypeDepthReached { Err(BtfError::MaximumTypeDepthReached {
@ -416,56 +388,55 @@ impl Btf {
let mut types = mem::take(&mut self.types); let mut types = mem::take(&mut self.types);
for i in 0..types.types.len() { for i in 0..types.types.len() {
let t = &types.types[i]; let t = &types.types[i];
let kind = t.kind()?.unwrap_or_default(); let kind = t.kind();
match t { match t {
// Fixup PTR for Rust // Fixup PTR for Rust
// LLVM emits names for Rust pointer types, which the kernel doesn't like // LLVM emits names for Rust pointer types, which the kernel doesn't like
// While I figure out if this needs fixing in the Kernel or LLVM, we'll // While I figure out if this needs fixing in the Kernel or LLVM, we'll
// do a fixup here // do a fixup here
BtfType::Ptr(ty) => { BtfType::Ptr(ptr) => {
let mut fixed_ty = *ty; let mut fixed_ty = ptr.clone();
fixed_ty.name_off = 0; fixed_ty.name_offset = 0;
types.types[i] = BtfType::Ptr(fixed_ty) types.types[i] = BtfType::Ptr(fixed_ty)
} }
// Sanitize VAR if they are not supported // Sanitize VAR if they are not supported
BtfType::Var(ty, _) if !features.btf_datasec => { BtfType::Var(v) if !features.btf_datasec => {
types.types[i] = BtfType::new_int(ty.name_off, 1, 0, 0); types.types[i] = BtfType::Int(Int::new(v.name_offset, 1, IntEncoding::None, 0));
} }
// Sanitize DATASEC if they are not supported // Sanitize DATASEC if they are not supported
BtfType::DataSec(ty, data) if !features.btf_datasec => { BtfType::DataSec(d) if !features.btf_datasec => {
debug!("{}: not supported. replacing with STRUCT", kind); debug!("{}: not supported. replacing with STRUCT", kind);
let mut members = vec![]; let mut members = vec![];
for member in data { for member in d.entries.iter() {
let mt = types.type_by_id(member.type_).unwrap(); let mt = types.type_by_id(member.btf_type).unwrap();
members.push(btf_member { members.push(BtfMember {
name_off: mt.btf_type().unwrap().name_off, name_offset: mt.name_offset(),
type_: member.type_, btf_type: member.btf_type,
offset: member.offset * 8, offset: member.offset * 8,
}) })
} }
types.types[i] = BtfType::new_struct(ty.name_off, members, 0); types.types[i] = BtfType::Struct(Struct::new(t.name_offset(), members, 0));
} }
// Fixup DATASEC // Fixup DATASEC
// DATASEC sizes aren't always set by LLVM // DATASEC sizes aren't always set by LLVM
// we need to fix them here before loading the btf to the kernel // we need to fix them here before loading the btf to the kernel
BtfType::DataSec(ty, data) if features.btf_datasec => { BtfType::DataSec(d) if features.btf_datasec => {
// Start DataSec Fixups // Start DataSec Fixups
let sec_name = self.string_at(ty.name_off)?; let sec_name = self.string_at(d.name_offset)?;
let name = sec_name.to_string(); let name = sec_name.to_string();
let mut fixed_ty = *ty; let mut fixed_ty = d.clone();
let mut fixed_data = data.clone();
// Handle any "/" characters in section names // Handle any "/" characters in section names
// Example: "maps/hashmap" // Example: "maps/hashmap"
let fixed_name = name.replace('/', "."); let fixed_name = name.replace('/', ".");
if fixed_name != name { if fixed_name != name {
fixed_ty.name_off = self.add_string(fixed_name); fixed_ty.name_offset = self.add_string(fixed_name);
} }
// There are some cases when the compiler does indeed populate the // There are some cases when the compiler does indeed populate the
// size // size
if unsafe { ty.__bindgen_anon_1.size > 0 } { if t.size().unwrap() > 0 {
debug!("{} {}: size fixup not required", kind, name); debug!("{} {}: size fixup not required", kind, name);
} else { } else {
// We need to get the size of the section from the ELF file // We need to get the size of the section from the ELF file
@ -477,19 +448,19 @@ impl Btf {
} }
})?; })?;
debug!("{} {}: fixup size to {}", kind, name, size); debug!("{} {}: fixup size to {}", kind, name, size);
fixed_ty.__bindgen_anon_1.size = *size as u32; fixed_ty.size = *size as u32;
// The Vec<btf_var_secinfo> contains BTF_KIND_VAR sections // The Vec<btf_var_secinfo> contains BTF_KIND_VAR sections
// that need to have their offsets adjusted. To do this, // that need to have their offsets adjusted. To do this,
// we need to get the offset from the ELF file. // we need to get the offset from the ELF file.
// This was also cached during initial parsing and // This was also cached during initial parsing and
// we can query by name in symbol_offsets // we can query by name in symbol_offsets
for d in &mut fixed_data { for d in &mut fixed_ty.entries.iter_mut() {
let var_type = types.type_by_id(d.type_)?; let var_type = types.type_by_id(d.btf_type)?;
let var_kind = var_type.kind()?.unwrap(); let var_kind = var_type.kind();
if let BtfType::Var(vty, var) = var_type { if let BtfType::Var(var) = var_type {
let var_name = self.string_at(vty.name_off)?.to_string(); let var_name = self.string_at(var.name_offset)?.to_string();
if var.linkage == btf_func_linkage::BTF_FUNC_STATIC as u32 { if var.linkage == VarLinkage::Static {
debug!( debug!(
"{} {}: {} {}: fixup not required", "{} {}: {} {}: fixup not required",
kind, name, var_kind, var_name kind, name, var_kind, var_name
@ -512,68 +483,66 @@ impl Btf {
} }
} }
} }
types.types[i] = BtfType::DataSec(fixed_ty, fixed_data); types.types[i] = BtfType::DataSec(fixed_ty);
} }
// Fixup FUNC_PROTO // Fixup FUNC_PROTO
BtfType::FuncProto(ty, params) if features.btf_func => { BtfType::FuncProto(ty) if features.btf_func => {
let mut params = params.clone(); let mut ty = ty.clone();
for (i, mut param) in params.iter_mut().enumerate() { for (i, mut param) in ty.params.iter_mut().enumerate() {
if param.name_off == 0 && param.type_ != 0 { if param.name_offset == 0 && param.btf_type != 0 {
param.name_off = self.add_string(format!("param{}", i)); param.name_offset = self.add_string(format!("param{}", i));
} }
} }
types.types[i] = BtfType::FuncProto(*ty, params); types.types[i] = BtfType::FuncProto(ty);
} }
// Sanitize FUNC_PROTO // Sanitize FUNC_PROTO
BtfType::FuncProto(ty, vars) if !features.btf_func => { BtfType::FuncProto(ty) if !features.btf_func => {
debug!("{}: not supported. replacing with ENUM", kind); debug!("{}: not supported. replacing with ENUM", kind);
let members: Vec<btf_enum> = vars let members: Vec<BtfEnum> = ty
.params
.iter() .iter()
.map(|p| btf_enum { .map(|p| BtfEnum {
name_off: p.name_off, name_offset: p.name_offset,
val: p.type_ as i32, value: p.btf_type as i32,
}) })
.collect(); .collect();
let enum_type = BtfType::new_enum(ty.name_off, members); let enum_type = BtfType::Enum(Enum::new(ty.name_offset, members));
types.types[i] = enum_type; types.types[i] = enum_type;
} }
// Sanitize FUNC // Sanitize FUNC
BtfType::Func(ty) if !features.btf_func => { BtfType::Func(ty) if !features.btf_func => {
debug!("{}: not supported. replacing with TYPEDEF", kind); debug!("{}: not supported. replacing with TYPEDEF", kind);
let typedef_type = let typedef_type = BtfType::Typedef(Typedef::new(ty.name_offset, ty.btf_type));
BtfType::new_typedef(ty.name_off, unsafe { ty.__bindgen_anon_1.type_ });
types.types[i] = typedef_type; types.types[i] = typedef_type;
} }
// Sanitize BTF_FUNC_GLOBAL // Sanitize BTF_FUNC_GLOBAL
BtfType::Func(ty) if !features.btf_func_global => { BtfType::Func(ty) if !features.btf_func_global => {
let mut fixed_ty = *ty; let mut fixed_ty = ty.clone();
if type_vlen(ty) == btf_func_linkage::BTF_FUNC_GLOBAL as usize { if ty.linkage() == FuncLinkage::Global {
debug!( debug!(
"{}: BTF_FUNC_GLOBAL not supported. replacing with BTF_FUNC_STATIC", "{}: BTF_FUNC_GLOBAL not supported. replacing with BTF_FUNC_STATIC",
kind kind
); );
fixed_ty.info = (ty.info & 0xFFFF0000) fixed_ty.set_linkage(FuncLinkage::Static);
| (btf_func_linkage::BTF_FUNC_STATIC as u32) & 0xFFFF;
} }
types.types[i] = BtfType::Func(fixed_ty); types.types[i] = BtfType::Func(fixed_ty);
} }
// Sanitize FLOAT // Sanitize FLOAT
BtfType::Float(ty) if !features.btf_float => { BtfType::Float(ty) if !features.btf_float => {
debug!("{}: not supported. replacing with STRUCT", kind); debug!("{}: not supported. replacing with STRUCT", kind);
let struct_ty = let struct_ty = BtfType::Struct(Struct::new(0, vec![], ty.size));
BtfType::new_struct(0, vec![], unsafe { ty.__bindgen_anon_1.size });
types.types[i] = struct_ty; types.types[i] = struct_ty;
} }
// Sanitize DECL_TAG // Sanitize DECL_TAG
BtfType::DeclTag(ty, _) if !features.btf_decl_tag => { BtfType::DeclTag(ty) if !features.btf_decl_tag => {
debug!("{}: not supported. replacing with INT", kind); debug!("{}: not supported. replacing with INT", kind);
let int_type = BtfType::new_int(ty.name_off, 1, 0, 0); let int_type = BtfType::Int(Int::new(ty.name_offset, 1, IntEncoding::None, 0));
types.types[i] = int_type; types.types[i] = int_type;
} }
// Sanitize TYPE_TAG // Sanitize TYPE_TAG
BtfType::TypeTag(ty) if !features.btf_type_tag => { BtfType::TypeTag(ty) if !features.btf_type_tag => {
debug!("{}: not supported. replacing with CONST", kind); debug!("{}: not supported. replacing with CONST", kind);
let const_type = BtfType::new_const(unsafe { ty.__bindgen_anon_1.type_ }); let const_type = BtfType::Const(Const::new(ty.btf_type));
types.types[i] = const_type; types.types[i] = const_type;
} }
// The type does not need fixing up or sanitization // The type does not need fixing up or sanitization
@ -670,12 +639,12 @@ impl BtfExt {
SecInfoIter::new(ext.func_info_data(), ext.func_info_rec_size, endianness) SecInfoIter::new(ext.func_info_data(), ext.func_info_rec_size, endianness)
.map(move |sec| { .map(move |sec| {
let name = btf let name = btf
.string_at(sec.sec_name_off) .string_at(sec.name_offset)
.ok() .ok()
.map(String::from) .map(String::from)
.unwrap(); .unwrap();
let info = FuncSecInfo::parse( let info = FuncSecInfo::parse(
sec.sec_name_off, sec.name_offset,
sec.num_info, sec.num_info,
func_info_rec_size, func_info_rec_size,
sec.data, sec.data,
@ -691,12 +660,12 @@ impl BtfExt {
SecInfoIter::new(ext.line_info_data(), ext.line_info_rec_size, endianness) SecInfoIter::new(ext.line_info_data(), ext.line_info_rec_size, endianness)
.map(move |sec| { .map(move |sec| {
let name = btf let name = btf
.string_at(sec.sec_name_off) .string_at(sec.name_offset)
.ok() .ok()
.map(String::from) .map(String::from)
.unwrap(); .unwrap();
let info = LineSecInfo::parse( let info = LineSecInfo::parse(
sec.sec_name_off, sec.name_offset,
sec.num_info, sec.num_info,
line_info_rec_size, line_info_rec_size,
sec.data, sec.data,
@ -717,7 +686,7 @@ impl BtfExt {
.enumerate() .enumerate()
.map(|(n, rec)| unsafe { Relocation::parse(rec, n) }) .map(|(n, rec)| unsafe { Relocation::parse(rec, n) })
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
Ok((sec.sec_name_off, relos)) Ok((sec.name_offset, relos))
}) })
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
); );
@ -793,7 +762,7 @@ impl<'a> Iterator for SecInfoIter<'a> {
} else { } else {
u32::from_be_bytes u32::from_be_bytes
}; };
let sec_name_off = read_u32(data[self.offset..self.offset + 4].try_into().unwrap()); let name_offset = read_u32(data[self.offset..self.offset + 4].try_into().unwrap());
self.offset += 4; self.offset += 4;
let num_info = u32::from_ne_bytes(data[self.offset..self.offset + 4].try_into().unwrap()); let num_info = u32::from_ne_bytes(data[self.offset..self.offset + 4].try_into().unwrap());
self.offset += 4; self.offset += 4;
@ -802,7 +771,7 @@ impl<'a> Iterator for SecInfoIter<'a> {
self.offset += self.rec_size * num_info as usize; self.offset += self.rec_size * num_info as usize;
Some(SecInfo { Some(SecInfo {
sec_name_off, name_offset,
num_info, num_info,
data, data,
}) })
@ -829,7 +798,7 @@ impl BtfTypes {
let mut buf = vec![]; let mut buf = vec![];
for t in self.types.iter().skip(1) { for t in self.types.iter().skip(1) {
let b = t.to_bytes(); let b = t.to_bytes();
buf.put(b.as_slice()) buf.extend(b)
} }
buf buf
} }
@ -855,9 +824,24 @@ impl BtfTypes {
use BtfType::*; use BtfType::*;
match ty { match ty {
Volatile(ty) | Const(ty) | Restrict(ty) | Typedef(ty) | TypeTag(ty) => { Volatile(ty) => {
// Safety: union type_id = ty.btf_type;
type_id = unsafe { ty.__bindgen_anon_1.type_ }; continue;
}
Const(ty) => {
type_id = ty.btf_type;
continue;
}
Restrict(ty) => {
type_id = ty.btf_type;
continue;
}
Typedef(ty) => {
type_id = ty.btf_type;
continue;
}
TypeTag(ty) => {
type_id = ty.btf_type;
continue; continue;
} }
_ => return Ok(type_id), _ => return Ok(type_id),
@ -872,15 +856,15 @@ impl BtfTypes {
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct SecInfo<'a> { pub(crate) struct SecInfo<'a> {
sec_name_off: u32, name_offset: u32,
num_info: u32, num_info: u32,
data: &'a [u8], data: &'a [u8],
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::generated::{ use crate::obj::btf::{
btf_param, btf_var_secinfo, BTF_INT_SIGNED, BTF_VAR_GLOBAL_EXTERN, BTF_VAR_STATIC, BtfParam, DataSec, DataSecEntry, DeclTag, Float, Func, FuncProto, Ptr, TypeTag, Var,
}; };
use super::*; use super::*;
@ -976,11 +960,11 @@ mod tests {
fn test_write_btf() { fn test_write_btf() {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0); let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
btf.add_type(int_type); btf.add_type(int_type);
let name_offset = btf.add_string("widget".to_string()); let name_offset = btf.add_string("widget".to_string());
let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0); let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
btf.add_type(int_type); btf.add_type(int_type);
let btf_bytes = btf.to_bytes(); let btf_bytes = btf.to_bytes();
@ -1002,10 +986,15 @@ mod tests {
fn test_fixup_ptr() { fn test_fixup_ptr() {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0)); let int_type_id = btf.add_type(BtfType::Int(Int::new(
name_offset,
4,
IntEncoding::Signed,
0,
)));
let name_offset = btf.add_string("&mut int".to_string()); let name_offset = btf.add_string("&mut int".to_string());
let ptr_type_id = btf.add_type(BtfType::new_ptr(name_offset, int_type_id)); let ptr_type_id = btf.add_type(BtfType::Ptr(Ptr::new(name_offset, int_type_id)));
let features = Features { let features = Features {
..Default::default() ..Default::default()
@ -1015,9 +1004,9 @@ mod tests {
.unwrap(); .unwrap();
if let BtfType::Ptr(fixed) = btf.type_by_id(ptr_type_id).unwrap() { if let BtfType::Ptr(fixed) = btf.type_by_id(ptr_type_id).unwrap() {
assert!( assert!(
fixed.name_off == 0, fixed.name_offset == 0,
"expected offset 0, got {}", "expected offset 0, got {}",
fixed.name_off fixed.name_offset
) )
} else { } else {
panic!("not a ptr") panic!("not a ptr")
@ -1031,10 +1020,19 @@ mod tests {
fn test_sanitize_var() { fn test_sanitize_var() {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0)); let int_type_id = btf.add_type(BtfType::Int(Int::new(
name_offset,
4,
IntEncoding::Signed,
0,
)));
let name_offset = btf.add_string("&mut int".to_string()); let name_offset = btf.add_string("&mut int".to_string());
let var_type_id = btf.add_type(BtfType::new_var(name_offset, int_type_id, BTF_VAR_STATIC)); let var_type_id = btf.add_type(BtfType::Var(Var::new(
name_offset,
int_type_id,
VarLinkage::Static,
)));
let features = Features { let features = Features {
btf_datasec: false, btf_datasec: false,
@ -1043,8 +1041,8 @@ mod tests {
btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features) btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
.unwrap(); .unwrap();
if let BtfType::Int(fixed, _) = btf.type_by_id(var_type_id).unwrap() { if let BtfType::Int(fixed) = btf.type_by_id(var_type_id).unwrap() {
assert!(fixed.name_off == name_offset) assert!(fixed.name_offset == name_offset)
} else { } else {
panic!("not an int") panic!("not an int")
} }
@ -1057,18 +1055,28 @@ mod tests {
fn test_sanitize_datasec() { fn test_sanitize_datasec() {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0)); let int_type_id = btf.add_type(BtfType::Int(Int::new(
name_offset,
4,
IntEncoding::Signed,
0,
)));
let name_offset = btf.add_string("foo".to_string()); let name_offset = btf.add_string("foo".to_string());
let var_type_id = btf.add_type(BtfType::new_var(name_offset, int_type_id, BTF_VAR_STATIC)); let var_type_id = btf.add_type(BtfType::Var(Var::new(
name_offset,
int_type_id,
VarLinkage::Static,
)));
let name_offset = btf.add_string(".data".to_string()); let name_offset = btf.add_string(".data".to_string());
let variables = vec![btf_var_secinfo { let variables = vec![DataSecEntry {
type_: var_type_id, btf_type: var_type_id,
offset: 0, offset: 0,
size: 4, size: 4,
}]; }];
let datasec_type_id = btf.add_type(BtfType::new_datasec(name_offset, variables, 0)); let datasec_type_id =
btf.add_type(BtfType::DataSec(DataSec::new(name_offset, variables, 0)));
let features = Features { let features = Features {
btf_datasec: false, btf_datasec: false,
@ -1077,11 +1085,11 @@ mod tests {
btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features) btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
.unwrap(); .unwrap();
if let BtfType::Struct(fixed, members) = btf.type_by_id(datasec_type_id).unwrap() { if let BtfType::Struct(fixed) = btf.type_by_id(datasec_type_id).unwrap() {
assert!(fixed.name_off == name_offset); assert!(fixed.name_offset == name_offset);
assert!(members.len() == 1); assert!(fixed.members.len() == 1);
assert!(members[0].type_ == var_type_id); assert!(fixed.members[0].btf_type == var_type_id);
assert!(members[0].offset == 0) assert!(fixed.members[0].offset == 0)
} else { } else {
panic!("not a struct") panic!("not a struct")
} }
@ -1094,22 +1102,28 @@ mod tests {
fn test_fixup_datasec() { fn test_fixup_datasec() {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0)); let int_type_id = btf.add_type(BtfType::Int(Int::new(
name_offset,
4,
IntEncoding::Signed,
0,
)));
let name_offset = btf.add_string("foo".to_string()); let name_offset = btf.add_string("foo".to_string());
let var_type_id = btf.add_type(BtfType::new_var( let var_type_id = btf.add_type(BtfType::Var(Var::new(
name_offset, name_offset,
int_type_id, int_type_id,
BTF_VAR_GLOBAL_EXTERN, VarLinkage::Global,
)); )));
let name_offset = btf.add_string(".data/foo".to_string()); let name_offset = btf.add_string(".data/foo".to_string());
let variables = vec![btf_var_secinfo { let variables = vec![DataSecEntry {
type_: var_type_id, btf_type: var_type_id,
offset: 0, offset: 0,
size: 4, size: 4,
}]; }];
let datasec_type_id = btf.add_type(BtfType::new_datasec(name_offset, variables, 0)); let datasec_type_id =
btf.add_type(BtfType::DataSec(DataSec::new(name_offset, variables, 0)));
let features = Features { let features = Features {
btf_datasec: true, btf_datasec: true,
@ -1123,17 +1137,17 @@ mod tests {
) )
.unwrap(); .unwrap();
if let BtfType::DataSec(fixed, sec_info) = btf.type_by_id(datasec_type_id).unwrap() { if let BtfType::DataSec(fixed) = btf.type_by_id(datasec_type_id).unwrap() {
assert!(fixed.name_off != name_offset); assert!(fixed.name_offset != name_offset);
assert!(unsafe { fixed.__bindgen_anon_1.size } == 32); assert!(fixed.size == 32);
assert!(sec_info.len() == 1); assert!(fixed.entries.len() == 1);
assert!(sec_info[0].type_ == var_type_id); assert!(fixed.entries[0].btf_type == var_type_id);
assert!( assert!(
sec_info[0].offset == 64, fixed.entries[0].offset == 64,
"expected 64, got {}", "expected 64, got {}",
sec_info[0].offset fixed.entries[0].offset
); );
assert!(btf.string_at(fixed.name_off).unwrap() == ".data.foo") assert!(btf.string_at(fixed.name_offset).unwrap() == ".data.foo")
} else { } else {
panic!("not a datasec") panic!("not a datasec")
} }
@ -1146,25 +1160,31 @@ mod tests {
fn test_sanitize_func_and_proto() { fn test_sanitize_func_and_proto() {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0)); let int_type_id = btf.add_type(BtfType::Int(Int::new(
name_offset,
4,
IntEncoding::Signed,
0,
)));
let params = vec![ let params = vec![
btf_param { BtfParam {
name_off: btf.add_string("a".to_string()), name_offset: btf.add_string("a".to_string()),
type_: int_type_id, btf_type: int_type_id,
}, },
btf_param { BtfParam {
name_off: btf.add_string("b".to_string()), name_offset: btf.add_string("b".to_string()),
type_: int_type_id, btf_type: int_type_id,
}, },
]; ];
let func_proto_type_id = btf.add_type(BtfType::new_func_proto(params, int_type_id)); let func_proto_type_id =
btf.add_type(BtfType::FuncProto(FuncProto::new(params, int_type_id)));
let inc = btf.add_string("inc".to_string()); let inc = btf.add_string("inc".to_string());
let func_type_id = btf.add_type(BtfType::new_func( let func_type_id = btf.add_type(BtfType::Func(Func::new(
inc, inc,
func_proto_type_id, func_proto_type_id,
btf_func_linkage::BTF_FUNC_STATIC, FuncLinkage::Static,
)); )));
let features = Features { let features = Features {
btf_func: false, btf_func: false,
@ -1173,21 +1193,20 @@ mod tests {
btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features) btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
.unwrap(); .unwrap();
if let BtfType::Enum(fixed) = btf.type_by_id(func_proto_type_id).unwrap() {
if let BtfType::Enum(fixed, vars) = btf.type_by_id(func_proto_type_id).unwrap() { assert!(fixed.name_offset == 0);
assert!(fixed.name_off == 0); assert!(fixed.variants.len() == 2);
assert!(vars.len() == 2); assert!(btf.string_at(fixed.variants[0].name_offset).unwrap() == "a");
assert!(btf.string_at(vars[0].name_off).unwrap() == "a"); assert!(fixed.variants[0].value == int_type_id as i32);
assert!(vars[0].val == int_type_id as i32); assert!(btf.string_at(fixed.variants[1].name_offset).unwrap() == "b");
assert!(btf.string_at(vars[1].name_off).unwrap() == "b"); assert!(fixed.variants[1].value == int_type_id as i32);
assert!(vars[1].val == int_type_id as i32);
} else { } else {
panic!("not an emum") panic!("not an emum")
} }
if let BtfType::Typedef(fixed) = btf.type_by_id(func_type_id).unwrap() { if let BtfType::Typedef(fixed) = btf.type_by_id(func_type_id).unwrap() {
assert!(fixed.name_off == inc); assert!(fixed.name_offset == inc);
assert!(unsafe { fixed.__bindgen_anon_1.type_ } == func_proto_type_id); assert!(fixed.btf_type == func_proto_type_id);
} else { } else {
panic!("not a typedef") panic!("not a typedef")
} }
@ -1200,20 +1219,20 @@ mod tests {
fn test_fixup_func_proto() { fn test_fixup_func_proto() {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0); let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
let int_type_id = btf.add_type(int_type); let int_type_id = btf.add_type(int_type);
let params = vec![ let params = vec![
btf_param { BtfParam {
name_off: 0, name_offset: 0,
type_: int_type_id, btf_type: int_type_id,
}, },
btf_param { BtfParam {
name_off: 0, name_offset: 0,
type_: int_type_id, btf_type: int_type_id,
}, },
]; ];
let func_proto = BtfType::new_func_proto(params, int_type_id); let func_proto = BtfType::FuncProto(FuncProto::new(params, int_type_id));
let func_proto_type_id = btf.add_type(func_proto); let func_proto_type_id = btf.add_type(func_proto);
let features = Features { let features = Features {
@ -1224,9 +1243,9 @@ mod tests {
btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features) btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
.unwrap(); .unwrap();
if let BtfType::FuncProto(_, vars) = btf.type_by_id(func_proto_type_id).unwrap() { if let BtfType::FuncProto(fixed) = btf.type_by_id(func_proto_type_id).unwrap() {
assert!(btf.string_at(vars[0].name_off).unwrap() == "param0"); assert!(btf.string_at(fixed.params[0].name_offset).unwrap() == "param0");
assert!(btf.string_at(vars[1].name_off).unwrap() == "param1"); assert!(btf.string_at(fixed.params[1].name_offset).unwrap() == "param1");
} else { } else {
panic!("not a func_proto") panic!("not a func_proto")
} }
@ -1239,25 +1258,31 @@ mod tests {
fn test_sanitize_func_global() { fn test_sanitize_func_global() {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0)); let int_type_id = btf.add_type(BtfType::Int(Int::new(
name_offset,
4,
IntEncoding::Signed,
0,
)));
let params = vec![ let params = vec![
btf_param { BtfParam {
name_off: btf.add_string("a".to_string()), name_offset: btf.add_string("a".to_string()),
type_: int_type_id, btf_type: int_type_id,
}, },
btf_param { BtfParam {
name_off: btf.add_string("b".to_string()), name_offset: btf.add_string("b".to_string()),
type_: int_type_id, btf_type: int_type_id,
}, },
]; ];
let func_proto_type_id = btf.add_type(BtfType::new_func_proto(params, int_type_id)); let func_proto_type_id =
btf.add_type(BtfType::FuncProto(FuncProto::new(params, int_type_id)));
let inc = btf.add_string("inc".to_string()); let inc = btf.add_string("inc".to_string());
let func_type_id = btf.add_type(BtfType::new_func( let func_type_id = btf.add_type(BtfType::Func(Func::new(
inc, inc,
func_proto_type_id, func_proto_type_id,
btf_func_linkage::BTF_FUNC_GLOBAL, FuncLinkage::Global,
)); )));
let features = Features { let features = Features {
btf_func: true, btf_func: true,
@ -1269,7 +1294,7 @@ mod tests {
.unwrap(); .unwrap();
if let BtfType::Func(fixed) = btf.type_by_id(func_type_id).unwrap() { if let BtfType::Func(fixed) = btf.type_by_id(func_type_id).unwrap() {
assert!(type_vlen(fixed) == btf_func_linkage::BTF_FUNC_STATIC as usize); assert!(fixed.linkage() == FuncLinkage::Static);
} else { } else {
panic!("not a func") panic!("not a func")
} }
@ -1282,7 +1307,7 @@ mod tests {
fn test_sanitize_float() { fn test_sanitize_float() {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("float".to_string()); let name_offset = btf.add_string("float".to_string());
let float_type_id = btf.add_type(BtfType::new_float(name_offset, 16)); let float_type_id = btf.add_type(BtfType::Float(Float::new(name_offset, 16)));
let features = Features { let features = Features {
btf_float: false, btf_float: false,
@ -1291,9 +1316,9 @@ mod tests {
btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features) btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
.unwrap(); .unwrap();
if let BtfType::Struct(fixed, _) = btf.type_by_id(float_type_id).unwrap() { if let BtfType::Struct(fixed) = btf.type_by_id(float_type_id).unwrap() {
assert!(fixed.name_off == 0); assert!(fixed.name_offset == 0);
assert!(unsafe { fixed.__bindgen_anon_1.size } == 16); assert!(fixed.size == 16);
} else { } else {
panic!("not a struct") panic!("not a struct")
} }
@ -1306,13 +1331,23 @@ mod tests {
fn test_sanitize_decl_tag() { fn test_sanitize_decl_tag() {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type_id = btf.add_type(BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0)); let int_type_id = btf.add_type(BtfType::Int(Int::new(
name_offset,
4,
IntEncoding::Signed,
0,
)));
let name_offset = btf.add_string("foo".to_string()); let name_offset = btf.add_string("foo".to_string());
let var_type_id = btf.add_type(BtfType::new_var(name_offset, int_type_id, BTF_VAR_STATIC)); let var_type_id = btf.add_type(BtfType::Var(Var::new(
name_offset,
int_type_id,
VarLinkage::Static,
)));
let name_offset = btf.add_string("decl_tag".to_string()); let name_offset = btf.add_string("decl_tag".to_string());
let decl_tag_type_id = btf.add_type(BtfType::new_decl_tag(name_offset, var_type_id, -1)); let decl_tag_type_id =
btf.add_type(BtfType::DeclTag(DeclTag::new(name_offset, var_type_id, -1)));
let features = Features { let features = Features {
btf_decl_tag: false, btf_decl_tag: false,
@ -1321,9 +1356,9 @@ mod tests {
btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features) btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
.unwrap(); .unwrap();
if let BtfType::Int(fixed, _) = btf.type_by_id(decl_tag_type_id).unwrap() { if let BtfType::Int(fixed) = btf.type_by_id(decl_tag_type_id).unwrap() {
assert!(fixed.name_off == name_offset); assert!(fixed.name_offset == name_offset);
assert!(unsafe { fixed.__bindgen_anon_1.size } == 1); assert!(fixed.size == 1);
} else { } else {
panic!("not an int") panic!("not an int")
} }
@ -1336,11 +1371,11 @@ mod tests {
fn test_sanitize_type_tag() { fn test_sanitize_type_tag() {
let mut btf = Btf::new(); let mut btf = Btf::new();
let int_type_id = btf.add_type(BtfType::new_int(0, 4, BTF_INT_SIGNED, 0)); let int_type_id = btf.add_type(BtfType::Int(Int::new(0, 4, IntEncoding::Signed, 0)));
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let type_tag_type = btf.add_type(BtfType::new_type_tag(name_offset, int_type_id)); let type_tag_type = btf.add_type(BtfType::TypeTag(TypeTag::new(name_offset, int_type_id)));
btf.add_type(BtfType::new_ptr(0, type_tag_type)); btf.add_type(BtfType::Ptr(Ptr::new(0, type_tag_type)));
let features = Features { let features = Features {
btf_type_tag: false, btf_type_tag: false,
@ -1350,7 +1385,7 @@ mod tests {
btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features) btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
.unwrap(); .unwrap();
if let BtfType::Const(fixed) = btf.type_by_id(type_tag_type).unwrap() { if let BtfType::Const(fixed) = btf.type_by_id(type_tag_type).unwrap() {
assert!(unsafe { fixed.__bindgen_anon_1.type_ } == int_type_id); assert!(fixed.btf_type == int_type_id);
} else { } else {
panic!("not a const") panic!("not a const")
} }
@ -1358,4 +1393,29 @@ mod tests {
let raw = btf.to_bytes(); let raw = btf.to_bytes();
Btf::parse(&raw, Endianness::default()).unwrap(); Btf::parse(&raw, Endianness::default()).unwrap();
} }
#[test]
#[cfg_attr(miri, ignore)]
fn test_read_btf_from_sys_fs() {
let btf = Btf::parse_file("/sys/kernel/btf/vmlinux", Endianness::default()).unwrap();
let task_struct_id = btf
.id_by_type_name_kind("task_struct", BtfKind::Struct)
.unwrap();
// we can't assert on exact ID since this may change across kernel versions
assert!(task_struct_id != 0);
let netif_id = btf
.id_by_type_name_kind("netif_receive_skb", BtfKind::Func)
.unwrap();
assert!(netif_id != 0);
let u32_def = btf.id_by_type_name_kind("__u32", BtfKind::Typedef).unwrap();
assert!(u32_def != 0);
let u32_base = btf.resolve_type(u32_def).unwrap();
assert!(u32_base != 0);
let u32_ty = btf.type_by_id(u32_base).unwrap();
assert_eq!(u32_ty.kind(), BtfKind::Int);
}
} }

@ -9,8 +9,8 @@ use crate::{
}, },
obj::{ obj::{
btf::{ btf::{
fields_are_compatible, member_bit_field_size, member_bit_offset, types_are_compatible, fields_are_compatible, types_are_compatible, Array, BtfMember, BtfType, IntEncoding,
BtfType, MAX_SPEC_LEN, Struct, Union, MAX_SPEC_LEN,
}, },
Btf, BtfError, Object, Program, ProgramSection, Btf, BtfError, Object, Program, ProgramSection,
}, },
@ -207,7 +207,7 @@ fn relocate_btf_program<'target>(
} }
let local_ty = local_btf.type_by_id(rel.type_id)?; let local_ty = local_btf.type_by_id(rel.type_id)?;
let local_name = &*local_btf.type_name(local_ty)?.unwrap(); let local_name = &*local_btf.type_name(local_ty)?;
let access_str = &*local_btf.string_at(rel.access_str_offset)?; let access_str = &*local_btf.string_at(rel.access_str_offset)?;
let local_spec = AccessSpec::new(local_btf, rel.type_id, access_str, *rel)?; let local_spec = AccessSpec::new(local_btf, rel.type_id, access_str, *rel)?;
@ -288,10 +288,10 @@ fn find_candidates<'target>(
let mut candidates = Vec::new(); let mut candidates = Vec::new();
let local_name = flavorless_name(local_name); let local_name = flavorless_name(local_name);
for (type_id, ty) in target_btf.types().enumerate() { for (type_id, ty) in target_btf.types().enumerate() {
if local_ty.kind()? != ty.kind()? { if local_ty.kind() != ty.kind() {
continue; continue;
} }
let name = &*target_btf.type_name(ty)?.unwrap(); let name = &*target_btf.type_name(ty)?;
if local_name != flavorless_name(name) { if local_name != flavorless_name(name) {
continue; continue;
} }
@ -342,9 +342,9 @@ fn match_candidate<'target>(
// the first accessor is guaranteed to have a name by construction // the first accessor is guaranteed to have a name by construction
let local_variant_name = local_spec.accessors[0].name.as_ref().unwrap(); let local_variant_name = local_spec.accessors[0].name.as_ref().unwrap();
match target_ty { match target_ty {
BtfType::Enum(_, members) => { BtfType::Enum(en) => {
for (index, member) in members.iter().enumerate() { for (index, member) in en.variants.iter().enumerate() {
let target_variant_name = candidate.btf.string_at(member.name_off)?; let target_variant_name = candidate.btf.string_at(member.name_offset)?;
if flavorless_name(local_variant_name) if flavorless_name(local_variant_name)
== flavorless_name(&target_variant_name) == flavorless_name(&target_variant_name)
{ {
@ -389,24 +389,24 @@ fn match_candidate<'target>(
if i > 0 { if i > 0 {
let target_ty = candidate.btf.type_by_id(target_id)?; let target_ty = candidate.btf.type_by_id(target_id)?;
let array = match target_ty { let array = match target_ty {
BtfType::Array(_, array) => array, BtfType::Array(Array { array, .. }) => array,
_ => return Ok(None), _ => return Ok(None),
}; };
let var_len = array.nelems == 0 && { let var_len = array.len == 0 && {
// an array is potentially variable length if it's the last field // an array is potentially variable length if it's the last field
// of the parent struct and has 0 elements // of the parent struct and has 0 elements
let parent = target_spec.accessors.last().unwrap(); let parent = target_spec.accessors.last().unwrap();
let parent_ty = candidate.btf.type_by_id(parent.type_id)?; let parent_ty = candidate.btf.type_by_id(parent.type_id)?;
match parent_ty { match parent_ty {
BtfType::Struct(_, members) => parent.index == members.len() - 1, BtfType::Struct(s) => parent.index == s.members.len() - 1,
_ => false, _ => false,
} }
}; };
if !var_len && accessor.index >= array.nelems as usize { if !var_len && accessor.index >= array.len as usize {
return Ok(None); return Ok(None);
} }
target_id = candidate.btf.resolve_type(array.type_)?; target_id = candidate.btf.resolve_type(array.element_type)?;
} }
if target_spec.parts.len() == MAX_SPEC_LEN { if target_spec.parts.len() == MAX_SPEC_LEN {
@ -442,21 +442,20 @@ fn match_member<'local, 'target>(
) -> Result<Option<u32>, ErrorWrapper> { ) -> Result<Option<u32>, ErrorWrapper> {
let local_ty = local_btf.type_by_id(local_accessor.type_id)?; let local_ty = local_btf.type_by_id(local_accessor.type_id)?;
let local_member = match local_ty { let local_member = match local_ty {
BtfType::Struct(_, members) | BtfType::Union(_, members) => { // this won't panic, bounds are checked when local_spec is built in AccessSpec::new
// this won't panic, bounds are checked when local_spec is built in AccessSpec::new BtfType::Struct(s) => s.members.get(local_accessor.index).unwrap(),
members[local_accessor.index] BtfType::Union(u) => u.members.get(local_accessor.index).unwrap(),
}
_ => panic!("bug! this should only be called for structs and unions"), _ => panic!("bug! this should only be called for structs and unions"),
}; };
let local_name = &*local_btf.string_at(local_member.name_off)?; let local_name = &*local_btf.string_at(local_member.name_offset)?;
let target_id = target_btf.resolve_type(target_id)?; let target_id = target_btf.resolve_type(target_id)?;
let target_ty = target_btf.type_by_id(target_id)?; let target_ty = target_btf.type_by_id(target_id)?;
let target_members = match target_ty { let target_members: Vec<&BtfMember> = match target_ty.members() {
BtfType::Struct(_, members) | BtfType::Union(_, members) => members, Some(members) => members.collect(),
// not a fields type, no match // not a fields type, no match
_ => return Ok(None), None => return Ok(None),
}; };
for (index, target_member) in target_members.iter().enumerate() { for (index, target_member) in target_members.iter().enumerate() {
@ -468,8 +467,9 @@ fn match_member<'local, 'target>(
.into()); .into());
} }
let bit_offset = member_bit_offset(target_ty.info().unwrap(), target_member); // this will not panic as we've already established these are fields types
let target_name = &*target_btf.string_at(target_member.name_off)?; let bit_offset = target_ty.member_bit_offset(target_member).unwrap();
let target_name = &*target_btf.string_at(target_member.name_offset)?;
if target_name.is_empty() { if target_name.is_empty() {
let ret = match_member( let ret = match_member(
@ -477,7 +477,7 @@ fn match_member<'local, 'target>(
local_spec, local_spec,
local_accessor, local_accessor,
target_btf, target_btf,
target_member.type_, target_member.btf_type,
target_spec, target_spec,
)?; )?;
if ret.is_some() { if ret.is_some() {
@ -488,9 +488,9 @@ fn match_member<'local, 'target>(
} else if local_name == target_name { } else if local_name == target_name {
if fields_are_compatible( if fields_are_compatible(
local_spec.btf, local_spec.btf,
local_member.type_, local_member.btf_type,
target_btf, target_btf,
target_member.type_, target_member.btf_type,
)? { )? {
target_spec.bit_offset += bit_offset; target_spec.bit_offset += bit_offset;
target_spec.parts.push(index); target_spec.parts.push(index);
@ -499,7 +499,7 @@ fn match_member<'local, 'target>(
index, index,
name: Some(target_name.to_owned()), name: Some(target_name.to_owned()),
}); });
return Ok(Some(target_member.type_)); return Ok(Some(target_member.btf_type));
} else { } else {
return Ok(None); return Ok(None);
} }
@ -558,7 +558,7 @@ impl<'a> AccessSpec<'a> {
} }
} }
RelocationKind::EnumVariantExists | RelocationKind::EnumVariantValue => match ty { RelocationKind::EnumVariantExists | RelocationKind::EnumVariantValue => match ty {
BtfType::Enum(_, members) => { BtfType::Enum(en) => {
if parts.len() != 1 { if parts.len() != 1 {
return Err(RelocationError::InvalidAccessString { return Err(RelocationError::InvalidAccessString {
access_str: spec.to_string(), access_str: spec.to_string(),
@ -566,12 +566,12 @@ impl<'a> AccessSpec<'a> {
.into()); .into());
} }
let index = parts[0]; let index = parts[0];
if index >= members.len() { if index >= en.variants.len() {
return Err(RelocationError::InvalidAccessIndex { return Err(RelocationError::InvalidAccessIndex {
type_name: btf.err_type_name(ty), type_name: btf.err_type_name(ty),
spec: spec.to_string(), spec: spec.to_string(),
index, index,
max_index: members.len(), max_index: en.variants.len(),
error: "tried to access nonexistant enum variant".to_string(), error: "tried to access nonexistant enum variant".to_string(),
} }
.into()); .into());
@ -579,7 +579,10 @@ impl<'a> AccessSpec<'a> {
let accessors = vec![Accessor { let accessors = vec![Accessor {
type_id, type_id,
index, index,
name: Some(btf.string_at(members[index].name_off)?.to_string()), name: Some(
btf.string_at(en.variants.get(index).unwrap().name_offset)?
.to_string(),
),
}]; }];
AccessSpec { AccessSpec {
@ -595,7 +598,7 @@ impl<'a> AccessSpec<'a> {
return Err(RelocationError::InvalidRelocationKindForType { return Err(RelocationError::InvalidRelocationKindForType {
relocation_number: relocation.number, relocation_number: relocation.number,
relocation_kind: format!("{:?}", relocation.kind), relocation_kind: format!("{:?}", relocation.kind),
type_kind: format!("{:?}", ty.kind()?.unwrap()), type_kind: format!("{:?}", ty.kind()),
error: "enum relocation on non-enum type".to_string(), error: "enum relocation on non-enum type".to_string(),
} }
.into()) .into())
@ -618,9 +621,9 @@ impl<'a> AccessSpec<'a> {
type_id = btf.resolve_type(type_id)?; type_id = btf.resolve_type(type_id)?;
let ty = btf.type_by_id(type_id)?; let ty = btf.type_by_id(type_id)?;
use BtfType::*;
match ty { match ty {
Struct(t, members) | Union(t, members) => { BtfType::Struct(Struct { members, .. })
| BtfType::Union(Union { members, .. }) => {
if index >= members.len() { if index >= members.len() {
return Err(RelocationError::InvalidAccessIndex { return Err(RelocationError::InvalidAccessIndex {
type_name: btf.err_type_name(ty), type_name: btf.err_type_name(ty),
@ -632,38 +635,38 @@ impl<'a> AccessSpec<'a> {
.into()); .into());
} }
let member = members[index]; let member = &members[index];
bit_offset += member_bit_offset(t.info, &member); bit_offset += ty.member_bit_offset(member).unwrap();
if member.name_off != 0 { if member.name_offset != 0 {
accessors.push(Accessor { accessors.push(Accessor {
type_id, type_id,
index, index,
name: Some(btf.string_at(member.name_off)?.to_string()), name: Some(btf.string_at(member.name_offset)?.to_string()),
}); });
} }
type_id = member.type_; type_id = member.btf_type;
} }
Array(_, array) => { BtfType::Array(Array { array, .. }) => {
type_id = btf.resolve_type(array.type_)?; type_id = btf.resolve_type(array.element_type)?;
let var_len = array.nelems == 0 && { let var_len = array.len == 0 && {
// an array is potentially variable length if it's the last field // an array is potentially variable length if it's the last field
// of the parent struct and has 0 elements // of the parent struct and has 0 elements
let parent = accessors.last().unwrap(); let parent = accessors.last().unwrap();
let parent_ty = btf.type_by_id(parent.type_id)?; let parent_ty = btf.type_by_id(parent.type_id)?;
match parent_ty { match parent_ty {
Struct(_, members) => index == members.len() - 1, BtfType::Struct(s) => index == s.members.len() - 1,
_ => false, _ => false,
} }
}; };
if !var_len && index >= array.nelems as usize { if !var_len && index >= array.len as usize {
return Err(RelocationError::InvalidAccessIndex { return Err(RelocationError::InvalidAccessIndex {
type_name: btf.err_type_name(ty), type_name: btf.err_type_name(ty),
spec: spec.to_string(), spec: spec.to_string(),
index, index,
max_index: array.nelems as usize, max_index: array.len as usize,
error: "array index out of bounds".to_string(), error: "array index out of bounds".to_string(),
} }
.into()); .into());
@ -814,8 +817,8 @@ impl ComputedRelocation {
use BtfType::*; use BtfType::*;
match (local_ty, target_ty) { match (local_ty, target_ty) {
(Ptr(_), Ptr(_)) => {} (Ptr(_), Ptr(_)) => {}
(Int(_, local_info), Int(_, target_info)) (Int(local), Int(target))
if unsigned(*local_info) && unsigned(*target_info) => {} if unsigned(local.data) && unsigned(target.data) => {}
_ => { _ => {
return Err(RelocationError::InvalidInstruction { return Err(RelocationError::InvalidInstruction {
relocation_number: rel.number, relocation_number: rel.number,
@ -885,7 +888,7 @@ impl ComputedRelocation {
let spec = spec.unwrap(); let spec = spec.unwrap();
let accessor = &spec.accessors[0]; let accessor = &spec.accessors[0];
match spec.btf.type_by_id(accessor.type_id)? { match spec.btf.type_by_id(accessor.type_id)? {
BtfType::Enum(_, variants) => variants[accessor.index].val as u32, BtfType::Enum(en) => en.variants[accessor.index].value as u32,
_ => panic!("should not be reached"), _ => panic!("should not be reached"),
} }
} }
@ -946,9 +949,8 @@ impl ComputedRelocation {
let ty = spec.btf.type_by_id(accessor.type_id)?; let ty = spec.btf.type_by_id(accessor.type_id)?;
let (ll_ty, member) = match ty { let (ll_ty, member) = match ty {
BtfType::Struct(ty, members) | BtfType::Union(ty, members) => { BtfType::Struct(t) => (ty, t.members.get(accessor.index).unwrap()),
(ty, members[accessor.index]) BtfType::Union(t) => (ty, t.members.get(accessor.index).unwrap()),
}
_ => { _ => {
return Err(RelocationError::InvalidRelocationKindForType { return Err(RelocationError::InvalidRelocationKindForType {
relocation_number: rel.number, relocation_number: rel.number,
@ -961,17 +963,16 @@ impl ComputedRelocation {
}; };
let bit_off = spec.bit_offset as u32; let bit_off = spec.bit_offset as u32;
let member_type_id = spec.btf.resolve_type(member.type_)?; let member_type_id = spec.btf.resolve_type(member.btf_type)?;
let member_ty = spec.btf.type_by_id(member_type_id)?; let member_ty = spec.btf.type_by_id(member_type_id)?;
let ll_member_ty = member_ty.btf_type().unwrap();
let mut byte_size; let mut byte_size;
let mut byte_off; let mut byte_off;
let mut bit_size = member_bit_field_size(ll_ty, &member) as u32; let mut bit_size = ll_ty.member_bit_field_size(member).unwrap() as u32;
let is_bitfield = bit_size > 0; let is_bitfield = bit_size > 0;
if is_bitfield { if is_bitfield {
// find out the smallest int size to load the bitfield // find out the smallest int size to load the bitfield
byte_size = unsafe { ll_member_ty.__bindgen_anon_1.size }; byte_size = member_ty.size().unwrap();
byte_off = bit_off / 8 / byte_size * byte_size; byte_off = bit_off / 8 / byte_size * byte_size;
while bit_off + bit_size - byte_off * 8 > byte_size * 8 { while bit_off + bit_size - byte_off * 8 > byte_size * 8 {
if byte_size >= 8 { if byte_size >= 8 {
@ -1006,8 +1007,8 @@ impl ComputedRelocation {
value.value = byte_size; value.value = byte_size;
} }
FieldSigned => match member_ty { FieldSigned => match member_ty {
BtfType::Enum(_, _) => value.value = 1, BtfType::Enum(_) => value.value = 1,
BtfType::Int(_, i) => value.value = ((i >> 24) & 0x0F) & BTF_INT_SIGNED, BtfType::Int(i) => value.value = i.encoding() as u32 & IntEncoding::Signed as u32,
_ => (), _ => (),
}, },
#[cfg(target_endian = "little")] #[cfg(target_endian = "little")]

File diff suppressed because it is too large Load Diff

@ -19,14 +19,14 @@ use relocation::*;
use crate::{ use crate::{
bpf_map_def, bpf_map_def,
generated::{bpf_insn, bpf_map_type::BPF_MAP_TYPE_ARRAY, btf_var_secinfo, BPF_F_RDONLY_PROG}, generated::{bpf_insn, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_F_RDONLY_PROG},
obj::btf::{Btf, BtfError, BtfExt, BtfType}, obj::btf::{Btf, BtfError, BtfExt, BtfType},
programs::{CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType}, programs::{CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType},
BpfError, BtfMapDef, PinningType, BpfError, BtfMapDef, PinningType,
}; };
use std::slice::from_raw_parts_mut; use std::slice::from_raw_parts_mut;
use self::btf::{BtfKind, FuncSecInfo, LineSecInfo}; use self::btf::{Array, DataSecEntry, FuncSecInfo, LineSecInfo};
const KERNEL_VERSION_ANY: u32 = 0xFFFF_FFFE; const KERNEL_VERSION_ANY: u32 = 0xFFFF_FFFE;
/// The first five __u32 of `bpf_map_def` must be defined. /// The first five __u32 of `bpf_map_def` must be defined.
@ -830,14 +830,14 @@ impl Object {
let btf = self.btf.as_ref().unwrap(); let btf = self.btf.as_ref().unwrap();
for t in btf.types() { for t in btf.types() {
if let BtfType::DataSec(_, sec_info) = &t { if let BtfType::DataSec(datasec) = &t {
let type_name = match btf.type_name(t) { let type_name = match btf.type_name(t) {
Ok(Some(name)) => name, Ok(name) => name,
_ => continue, _ => continue,
}; };
if type_name == section.name { if type_name == section.name {
// each btf_var_secinfo contains a map // each btf_var_secinfo contains a map
for info in sec_info { for info in &datasec.entries {
let (map_name, def) = parse_btf_map_def(btf, info)?; let (map_name, def) = parse_btf_map_def(btf, info)?;
let symbol_index = symbols let symbol_index = symbols
.get(&map_name) .get(&map_name)
@ -1144,20 +1144,20 @@ fn get_map_field(btf: &Btf, type_id: u32) -> Result<u32, BtfError> {
BtfType::Ptr(pty) => pty, BtfType::Ptr(pty) => pty,
other => { other => {
return Err(BtfError::UnexpectedBtfType { return Err(BtfError::UnexpectedBtfType {
type_id: other.kind()?.unwrap_or(BtfKind::Unknown) as u32, type_id: other.btf_type().unwrap_or(0) as u32,
}) })
} }
}; };
// Safety: union // Safety: union
let arr = match &btf.type_by_id(unsafe { pty.__bindgen_anon_1.type_ })? { let arr = match &btf.type_by_id(pty.btf_type)? {
BtfType::Array(_, arr) => arr, BtfType::Array(Array { array, .. }) => array,
other => { other => {
return Err(BtfError::UnexpectedBtfType { return Err(BtfError::UnexpectedBtfType {
type_id: other.kind()?.unwrap_or(BtfKind::Unknown) as u32, type_id: other.btf_type().unwrap_or(0) as u32,
}) })
} }
}; };
Ok(arr.nelems) Ok(arr.len)
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@ -1226,68 +1226,71 @@ fn parse_map_def(name: &str, data: &[u8]) -> Result<bpf_map_def, ParseError> {
} }
} }
fn parse_btf_map_def(btf: &Btf, info: &btf_var_secinfo) -> Result<(String, BtfMapDef), BtfError> { fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDef), BtfError> {
let ty = match btf.type_by_id(info.type_)? { let ty = match btf.type_by_id(info.btf_type)? {
BtfType::Var(ty, _) => ty, BtfType::Var(var) => var,
other => { other => {
return Err(BtfError::UnexpectedBtfType { return Err(BtfError::UnexpectedBtfType {
type_id: other.kind()?.unwrap_or(BtfKind::Unknown) as u32, type_id: other.btf_type().unwrap_or(0) as u32,
}) })
} }
}; };
let map_name = btf.string_at(ty.name_off)?; let map_name = btf.string_at(ty.name_offset)?;
let mut map_def = BtfMapDef::default(); let mut map_def = BtfMapDef::default();
// Safety: union // Safety: union
let root_type = btf.resolve_type(unsafe { ty.__bindgen_anon_1.type_ })?; let root_type = btf.resolve_type(ty.btf_type)?;
let members = match btf.type_by_id(root_type)? { let s = match btf.type_by_id(root_type)? {
BtfType::Struct(_, members) => members, BtfType::Struct(s) => s,
other => { other => {
return Err(BtfError::UnexpectedBtfType { return Err(BtfError::UnexpectedBtfType {
type_id: other.kind()?.unwrap_or(BtfKind::Unknown) as u32, type_id: other.btf_type().unwrap_or(0) as u32,
}) })
} }
}; };
for m in members { for m in &s.members {
match btf.string_at(m.name_off)?.as_ref() { match btf.string_at(m.name_offset)?.as_ref() {
"type" => { "type" => {
map_def.map_type = get_map_field(btf, m.type_)?; map_def.map_type = get_map_field(btf, m.btf_type)?;
} }
"key" => { "key" => {
if let BtfType::Ptr(pty) = btf.type_by_id(m.type_)? { if let BtfType::Ptr(pty) = btf.type_by_id(m.btf_type)? {
// Safety: union // Safety: union
let t = unsafe { pty.__bindgen_anon_1.type_ }; let t = pty.btf_type;
map_def.key_size = btf.type_size(t)? as u32; map_def.key_size = btf.type_size(t)? as u32;
map_def.btf_key_type_id = t; map_def.btf_key_type_id = t;
} else { } else {
return Err(BtfError::UnexpectedBtfType { type_id: m.type_ }); return Err(BtfError::UnexpectedBtfType {
type_id: m.btf_type,
});
} }
} }
"key_size" => { "key_size" => {
map_def.key_size = get_map_field(btf, m.type_)?; map_def.key_size = get_map_field(btf, m.btf_type)?;
} }
"value" => { "value" => {
if let BtfType::Ptr(pty) = btf.type_by_id(m.type_)? { if let BtfType::Ptr(pty) = btf.type_by_id(m.btf_type)? {
// Safety: union let t = pty.btf_type;
let t = unsafe { pty.__bindgen_anon_1.type_ };
map_def.value_size = btf.type_size(t)? as u32; map_def.value_size = btf.type_size(t)? as u32;
map_def.btf_value_type_id = t; map_def.btf_value_type_id = t;
} else { } else {
return Err(BtfError::UnexpectedBtfType { type_id: m.type_ }); return Err(BtfError::UnexpectedBtfType {
type_id: m.btf_type,
});
} }
} }
"value_size" => { "value_size" => {
map_def.value_size = get_map_field(btf, m.type_)?; map_def.value_size = get_map_field(btf, m.btf_type)?;
} }
"max_entries" => { "max_entries" => {
map_def.max_entries = get_map_field(btf, m.type_)?; map_def.max_entries = get_map_field(btf, m.btf_type)?;
} }
"map_flags" => { "map_flags" => {
map_def.map_flags = get_map_field(btf, m.type_)?; map_def.map_flags = get_map_field(btf, m.btf_type)?;
} }
"pinning" => { "pinning" => {
let pinning = get_map_field(btf, m.type_)?; let pinning = get_map_field(btf, m.btf_type)?;
map_def.pinning = PinningType::try_from(pinning).unwrap_or_else(|_| { map_def.pinning = PinningType::try_from(pinning).unwrap_or_else(|_| {
debug!("{} is not a valid pin type. using PIN_NONE", pinning); debug!("{} is not a valid pin type. using PIN_NONE", pinning);
PinningType::None PinningType::None

@ -1,8 +1,12 @@
use crate::{ use crate::{
generated::{ generated::BPF_F_REPLACE,
btf_func_linkage, btf_param, btf_var_secinfo, BPF_F_REPLACE, BTF_INT_SIGNED, BTF_VAR_STATIC, obj::{
btf::{
BtfParam, BtfType, DataSec, DataSecEntry, DeclTag, Float, Func, FuncLinkage, FuncProto,
Int, IntEncoding, Ptr, TypeTag, Var, VarLinkage,
},
copy_instructions,
}, },
obj::{btf::BtfType, copy_instructions},
Btf, Btf,
}; };
use libc::{c_char, c_long, close, ENOENT, ENOSPC}; use libc::{c_char, c_long, close, ENOENT, ENOSPC};
@ -546,7 +550,7 @@ pub(crate) fn is_prog_name_supported() -> bool {
pub(crate) fn is_btf_supported() -> bool { pub(crate) fn is_btf_supported() -> bool {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0); let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
btf.add_type(int_type); btf.add_type(int_type);
let btf_bytes = btf.to_bytes(); let btf_bytes = btf.to_bytes();
@ -568,26 +572,26 @@ pub(crate) fn is_btf_supported() -> bool {
pub(crate) fn is_btf_func_supported() -> bool { pub(crate) fn is_btf_func_supported() -> bool {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0); let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
let int_type_id = btf.add_type(int_type); let int_type_id = btf.add_type(int_type);
let a_name = btf.add_string("a".to_string()); let a_name = btf.add_string("a".to_string());
let b_name = btf.add_string("b".to_string()); let b_name = btf.add_string("b".to_string());
let params = vec![ let params = vec![
btf_param { BtfParam {
name_off: a_name, name_offset: a_name,
type_: int_type_id, btf_type: int_type_id,
}, },
btf_param { BtfParam {
name_off: b_name, name_offset: b_name,
type_: int_type_id, btf_type: int_type_id,
}, },
]; ];
let func_proto = BtfType::new_func_proto(params, int_type_id); let func_proto = BtfType::FuncProto(FuncProto::new(params, int_type_id));
let func_proto_type_id = btf.add_type(func_proto); let func_proto_type_id = btf.add_type(func_proto);
let add = btf.add_string("inc".to_string()); let add = btf.add_string("inc".to_string());
let func = BtfType::new_func(add, func_proto_type_id, btf_func_linkage::BTF_FUNC_STATIC); let func = BtfType::Func(Func::new(add, func_proto_type_id, FuncLinkage::Static));
btf.add_type(func); btf.add_type(func);
let btf_bytes = btf.to_bytes(); let btf_bytes = btf.to_bytes();
@ -610,26 +614,26 @@ pub(crate) fn is_btf_func_supported() -> bool {
pub(crate) fn is_btf_func_global_supported() -> bool { pub(crate) fn is_btf_func_global_supported() -> bool {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0); let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
let int_type_id = btf.add_type(int_type); let int_type_id = btf.add_type(int_type);
let a_name = btf.add_string("a".to_string()); let a_name = btf.add_string("a".to_string());
let b_name = btf.add_string("b".to_string()); let b_name = btf.add_string("b".to_string());
let params = vec![ let params = vec![
btf_param { BtfParam {
name_off: a_name, name_offset: a_name,
type_: int_type_id, btf_type: int_type_id,
}, },
btf_param { BtfParam {
name_off: b_name, name_offset: b_name,
type_: int_type_id, btf_type: int_type_id,
}, },
]; ];
let func_proto = BtfType::new_func_proto(params, int_type_id); let func_proto = BtfType::FuncProto(FuncProto::new(params, int_type_id));
let func_proto_type_id = btf.add_type(func_proto); let func_proto_type_id = btf.add_type(func_proto);
let add = btf.add_string("inc".to_string()); let add = btf.add_string("inc".to_string());
let func = BtfType::new_func(add, func_proto_type_id, btf_func_linkage::BTF_FUNC_GLOBAL); let func = BtfType::Func(Func::new(add, func_proto_type_id, FuncLinkage::Global));
btf.add_type(func); btf.add_type(func);
let btf_bytes = btf.to_bytes(); let btf_bytes = btf.to_bytes();
@ -652,20 +656,20 @@ pub(crate) fn is_btf_func_global_supported() -> bool {
pub(crate) fn is_btf_datasec_supported() -> bool { pub(crate) fn is_btf_datasec_supported() -> bool {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0); let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
let int_type_id = btf.add_type(int_type); let int_type_id = btf.add_type(int_type);
let name_offset = btf.add_string("foo".to_string()); let name_offset = btf.add_string("foo".to_string());
let var_type = BtfType::new_var(name_offset, int_type_id, BTF_VAR_STATIC); let var_type = BtfType::Var(Var::new(name_offset, int_type_id, VarLinkage::Static));
let var_type_id = btf.add_type(var_type); let var_type_id = btf.add_type(var_type);
let name_offset = btf.add_string(".data".to_string()); let name_offset = btf.add_string(".data".to_string());
let variables = vec![btf_var_secinfo { let variables = vec![DataSecEntry {
type_: var_type_id, btf_type: var_type_id,
offset: 0, offset: 0,
size: 4, size: 4,
}]; }];
let datasec_type = BtfType::new_datasec(name_offset, variables, 4); let datasec_type = BtfType::DataSec(DataSec::new(name_offset, variables, 4));
btf.add_type(datasec_type); btf.add_type(datasec_type);
let btf_bytes = btf.to_bytes(); let btf_bytes = btf.to_bytes();
@ -688,7 +692,7 @@ pub(crate) fn is_btf_datasec_supported() -> bool {
pub(crate) fn is_btf_float_supported() -> bool { pub(crate) fn is_btf_float_supported() -> bool {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("float".to_string()); let name_offset = btf.add_string("float".to_string());
let float_type = BtfType::new_float(name_offset, 16); let float_type = BtfType::Float(Float::new(name_offset, 16));
btf.add_type(float_type); btf.add_type(float_type);
let btf_bytes = btf.to_bytes(); let btf_bytes = btf.to_bytes();
@ -711,15 +715,15 @@ pub(crate) fn is_btf_float_supported() -> bool {
pub(crate) fn is_btf_decl_tag_supported() -> bool { pub(crate) fn is_btf_decl_tag_supported() -> bool {
let mut btf = Btf::new(); let mut btf = Btf::new();
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let int_type = BtfType::new_int(name_offset, 4, BTF_INT_SIGNED, 0); let int_type = BtfType::Int(Int::new(name_offset, 4, IntEncoding::Signed, 0));
let int_type_id = btf.add_type(int_type); let int_type_id = btf.add_type(int_type);
let name_offset = btf.add_string("foo".to_string()); let name_offset = btf.add_string("foo".to_string());
let var_type = BtfType::new_var(name_offset, int_type_id, BTF_VAR_STATIC); let var_type = BtfType::Var(Var::new(name_offset, int_type_id, VarLinkage::Static));
let var_type_id = btf.add_type(var_type); let var_type_id = btf.add_type(var_type);
let name_offset = btf.add_string("decl_tag".to_string()); let name_offset = btf.add_string("decl_tag".to_string());
let decl_tag = BtfType::new_decl_tag(name_offset, var_type_id, -1); let decl_tag = BtfType::DeclTag(DeclTag::new(name_offset, var_type_id, -1));
btf.add_type(decl_tag); btf.add_type(decl_tag);
let btf_bytes = btf.to_bytes(); let btf_bytes = btf.to_bytes();
@ -742,14 +746,14 @@ pub(crate) fn is_btf_decl_tag_supported() -> bool {
pub(crate) fn is_btf_type_tag_supported() -> bool { pub(crate) fn is_btf_type_tag_supported() -> bool {
let mut btf = Btf::new(); let mut btf = Btf::new();
let int_type = BtfType::new_int(0, 4, BTF_INT_SIGNED, 0); let int_type = BtfType::Int(Int::new(0, 4, IntEncoding::Signed, 0));
let int_type_id = btf.add_type(int_type); let int_type_id = btf.add_type(int_type);
let name_offset = btf.add_string("int".to_string()); let name_offset = btf.add_string("int".to_string());
let type_tag = BtfType::new_type_tag(name_offset, int_type_id); let type_tag = BtfType::TypeTag(TypeTag::new(name_offset, int_type_id));
let type_tag_type = btf.add_type(type_tag); let type_tag_type = btf.add_type(type_tag);
btf.add_type(BtfType::new_ptr(0, type_tag_type)); btf.add_type(BtfType::Ptr(Ptr::new(0, type_tag_type)));
let btf_bytes = btf.to_bytes(); let btf_bytes = btf.to_bytes();

Loading…
Cancel
Save