You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
aya/aya-tool/src/btf.rs

120 lines
4.9 KiB
Rust

use aya_obj::btf::{Btf, BtfType, IntEncoding, VarLinkage};
use object::Endianness;
use std::{fmt::Write, path::Path};
pub fn print_btf<P: AsRef<Path>>(path: P) -> anyhow::Result<()> {
let btf = Btf::parse_elf_file(path, Endianness::default())?;
for (i, t) in btf.types().enumerate().skip(1) {
let kind = t.kind();
let name = if t.name_offset() > 0 {
format!(
"'{}'",
btf.string_at(t.name_offset())
.unwrap_or(std::borrow::Cow::Borrowed(""))
)
} else {
"''".to_owned()
};
let info = match t {
BtfType::Unknown => "".to_string(),
BtfType::Fwd(_) => "type_id=0".to_string(),
BtfType::Const(ty) => format!("type_id={}", ty.btf_type()),
BtfType::Volatile(ty) => format!("type_id={}", ty.btf_type()),
BtfType::Restrict(ty) => format!("type_id={}", ty.btf_type()),
BtfType::Ptr(ty) => format!("type_id={}", ty.btf_type()),
BtfType::Typedef(ty) => format!("type_id={}", ty.btf_type()),
BtfType::Func(ty) => format!("type_id={}", ty.btf_type()),
BtfType::Int(i) => {
let encoding = match i.encoding() {
IntEncoding::Signed => "(signed)",
IntEncoding::Char => "(char)",
IntEncoding::Bool => "(bool)",
IntEncoding::None => "(none)",
IntEncoding::Unknown => "(unknown)",
};
format!(
"size={} bits_offset={} nr_bits={} encoding={}",
i.size(),
i.offset(),
i.bits(),
encoding,
)
}
BtfType::Float(_) => todo!(),
BtfType::Enum(_) => todo!(),
BtfType::Array(ty) => {
format!(
"type_id=0 index_type_id={} nr_elems={}",
ty.index_type(),
ty.len()
)
}
BtfType::Struct(ty) => {
let size = ty.size();
let vlen = ty.vlen();
let mut out = format!("size={} vlen={}", size, vlen,);
for m in ty.members() {
let name = btf
.string_at(m.name_offset())
.unwrap_or(std::borrow::Cow::Borrowed(""));
let type_id = m.btf_type();
let offset = ty.member_bit_offset(m);
write!(out, "\n\t'{name}' type_id={type_id} bits_offset={offset}")?;
}
out
}
BtfType::Union(_) => todo!(),
BtfType::FuncProto(ty) => {
let ret_type_id = ty.return_type();
let vlen = ty.vlen();
let mut out = format!("ret_type_id={ret_type_id} vlen={vlen}");
for p in ty.params() {
let name = btf
.string_at(p.name_offset())
.unwrap_or(std::borrow::Cow::Borrowed(""));
let type_id = p.btf_type();
write!(out, "\n\t'{name}' type_id={type_id}")?;
}
out
}
BtfType::Var(ty) => {
let type_id = ty.btf_type();
let linkage = match ty.linkage() {
VarLinkage::Static => "static".to_owned(),
VarLinkage::Global => "global".to_owned(),
VarLinkage::Extern => "extern".to_owned(),
VarLinkage::Unknown => "unknown".to_owned(),
};
format!("type_id={type_id} linkage={linkage}")
}
BtfType::DataSec(ty) => {
let size = ty.size();
let vlen = ty.vlen();
let mut out = format!("size={size} vlen={vlen}");
for entry in ty.entries() {
let points_to = btf.type_by_id(entry.btf_type()).unwrap();
let name = btf
.string_at(points_to.name_offset())
.unwrap_or(std::borrow::Cow::Borrowed(""));
write!(
out,
"\n\ttype_id={} offset={} size={} ({} '{}')",
entry.btf_type(),
entry.offset(),
entry.size(),
points_to.kind(),
name
)?;
}
out
}
BtfType::DeclTag(_) => unimplemented!("decl tag formatting not implemented"),
BtfType::TypeTag(_) => unimplemented!("type tag formatting not implemented"),
BtfType::Enum64(_) => unimplemented!("enum64 formatting not implemented"),
};
println!("[{i}] {kind} {name} {info}");
}
Ok(())
}