aya-obj: migrate aya::obj into a separate crate

To split the crate into two, several changes were made:
1. Most `pub(crate)` are now `pub` to allow access from Aya;
2. Parts of BpfError are merged into, for example, RelocationError;
3. BTF part of Features is moved into the new crate;
4. `#![deny(missing_docs)]` is removed temporarily;
5. Some other code gets moved into the new crate, mainly:
   - aya::{bpf_map_def, BtfMapDef, PinningType},
   - aya::programs::{CgroupSock*AttachType},

The new crate is currenly allowing missing_docs. Member visibility
will be adjusted later to minimize exposure of implementation details.

Refs: #473
pull/475/head
Shenghui Ye 2 years ago
parent 81bc307dce
commit ac49827e20

@ -11,3 +11,10 @@ documentation = "https://docs.rs/aya-obj"
edition = "2021"
[dependencies]
bytes = "1"
log = "0.4"
object = { version = "0.30", default-features = false, features = ["std", "read_core", "elf"] }
thiserror = "1"
[dev-dependencies]
matches = "0.1.8"

@ -16,14 +16,13 @@ use thiserror::Error;
use crate::{
generated::{btf_ext_header, btf_header},
obj::btf::{
btf::{
info::{FuncSecInfo, LineSecInfo},
relocation::Relocation,
Array, BtfEnum, BtfKind, BtfMember, BtfType, Const, Enum, FuncInfo, FuncLinkage, Int,
IntEncoding, LineInfo, Struct, Typedef, VarLinkage,
},
util::bytes_of,
Features,
};
pub(crate) const MAX_RESOLVE_DEPTH: u8 = 32;
@ -158,6 +157,16 @@ pub enum BtfError {
InvalidSymbolName,
}
#[derive(Default, Debug)]
pub struct BtfFeatures {
pub btf_func: bool,
pub btf_func_global: bool,
pub btf_datasec: bool,
pub btf_float: bool,
pub btf_decl_tag: bool,
pub btf_type_tag: bool,
}
/// Bpf Type Format metadata.
///
/// BTF is a kind of debug metadata that allows eBPF programs compiled against one kernel version
@ -175,7 +184,7 @@ pub struct Btf {
}
impl Btf {
pub(crate) fn new() -> Btf {
pub fn new() -> Btf {
Btf {
header: btf_header {
magic: 0xeb9f,
@ -197,7 +206,7 @@ impl Btf {
self.types.types.iter()
}
pub(crate) fn add_string(&mut self, name: String) -> u32 {
pub fn add_string(&mut self, name: String) -> u32 {
let str = CString::new(name).unwrap();
let name_offset = self.strings.len();
self.strings.extend(str.as_c_str().to_bytes_with_nul());
@ -205,7 +214,7 @@ impl Btf {
name_offset as u32
}
pub(crate) fn add_type(&mut self, btf_type: BtfType) -> u32 {
pub fn add_type(&mut self, btf_type: BtfType) -> u32 {
let size = btf_type.type_info_size() as u32;
let type_id = self.types.len();
self.types.push(btf_type);
@ -231,7 +240,7 @@ impl Btf {
)
}
pub(crate) fn parse(data: &[u8], endianness: Endianness) -> Result<Btf, BtfError> {
pub fn parse(data: &[u8], endianness: Endianness) -> Result<Btf, BtfError> {
if data.len() < mem::size_of::<btf_header>() {
return Err(BtfError::InvalidHeader);
}
@ -324,7 +333,7 @@ impl Btf {
self.string_at(ty.name_offset()).ok().map(String::from)
}
pub(crate) fn id_by_type_name_kind(&self, name: &str, kind: BtfKind) -> Result<u32, BtfError> {
pub fn id_by_type_name_kind(&self, name: &str, kind: BtfKind) -> Result<u32, BtfError> {
for (type_id, ty) in self.types().enumerate() {
if ty.kind() != kind {
continue;
@ -370,7 +379,7 @@ impl Btf {
})
}
pub(crate) fn to_bytes(&self) -> Vec<u8> {
pub fn to_bytes(&self) -> Vec<u8> {
// Safety: btf_header is POD
let mut buf = unsafe { bytes_of::<btf_header>(&self.header).to_vec() };
// Skip the first type since it's always BtfType::Unknown for type_by_id to work
@ -379,11 +388,11 @@ impl Btf {
buf
}
pub(crate) fn fixup_and_sanitize(
pub fn fixup_and_sanitize(
&mut self,
section_sizes: &HashMap<String, u64>,
symbol_offsets: &HashMap<String, u64>,
features: &Features,
features: &BtfFeatures,
) -> Result<(), BtfError> {
let mut types = mem::take(&mut self.types);
for i in 0..types.types.len() {
@ -863,7 +872,7 @@ pub(crate) struct SecInfo<'a> {
#[cfg(test)]
mod tests {
use crate::obj::btf::{
use crate::btf::{
BtfParam, DataSec, DataSecEntry, DeclTag, Float, Func, FuncProto, Ptr, TypeTag, Var,
};
@ -996,7 +1005,7 @@ mod tests {
let name_offset = btf.add_string("&mut int".to_string());
let ptr_type_id = btf.add_type(BtfType::Ptr(Ptr::new(name_offset, int_type_id)));
let features = Features {
let features = BtfFeatures {
..Default::default()
};
@ -1034,7 +1043,7 @@ mod tests {
VarLinkage::Static,
)));
let features = Features {
let features = BtfFeatures {
btf_datasec: false,
..Default::default()
};
@ -1078,7 +1087,7 @@ mod tests {
let datasec_type_id =
btf.add_type(BtfType::DataSec(DataSec::new(name_offset, variables, 0)));
let features = Features {
let features = BtfFeatures {
btf_datasec: false,
..Default::default()
};
@ -1125,7 +1134,7 @@ mod tests {
let datasec_type_id =
btf.add_type(BtfType::DataSec(DataSec::new(name_offset, variables, 0)));
let features = Features {
let features = BtfFeatures {
btf_datasec: true,
..Default::default()
};
@ -1186,7 +1195,7 @@ mod tests {
FuncLinkage::Static,
)));
let features = Features {
let features = BtfFeatures {
btf_func: false,
..Default::default()
};
@ -1235,7 +1244,7 @@ mod tests {
let func_proto = BtfType::FuncProto(FuncProto::new(params, int_type_id));
let func_proto_type_id = btf.add_type(func_proto);
let features = Features {
let features = BtfFeatures {
btf_func: true,
..Default::default()
};
@ -1284,7 +1293,7 @@ mod tests {
FuncLinkage::Global,
)));
let features = Features {
let features = BtfFeatures {
btf_func: true,
btf_func_global: false,
..Default::default()
@ -1309,7 +1318,7 @@ mod tests {
let name_offset = btf.add_string("float".to_string());
let float_type_id = btf.add_type(BtfType::Float(Float::new(name_offset, 16)));
let features = Features {
let features = BtfFeatures {
btf_float: false,
..Default::default()
};
@ -1349,7 +1358,7 @@ mod tests {
let decl_tag_type_id =
btf.add_type(BtfType::DeclTag(DeclTag::new(name_offset, var_type_id, -1)));
let features = Features {
let features = BtfFeatures {
btf_decl_tag: false,
..Default::default()
};
@ -1377,7 +1386,7 @@ mod tests {
let type_tag_type = btf.add_type(BtfType::TypeTag(TypeTag::new(name_offset, int_type_id)));
btf.add_type(BtfType::Ptr(Ptr::new(0, type_tag_type)));
let features = Features {
let features = BtfFeatures {
btf_type_tag: false,
..Default::default()
};

@ -5,7 +5,7 @@ use object::Endianness;
use crate::{
generated::{bpf_func_info, bpf_line_info},
obj::relocation::INS_SIZE,
relocation::INS_SIZE,
util::bytes_of,
};
@ -20,7 +20,7 @@ use crate::{
* ......
*/
#[derive(Debug, Clone, Default)]
pub(crate) struct FuncSecInfo {
pub struct FuncSecInfo {
pub _sec_name_offset: u32,
pub num_info: u32,
pub func_info: Vec<bpf_func_info>,
@ -64,7 +64,7 @@ impl FuncSecInfo {
}
}
pub(crate) fn func_info_bytes(&self) -> Vec<u8> {
pub fn func_info_bytes(&self) -> Vec<u8> {
let mut buf = vec![];
for l in &self.func_info {
// Safety: bpf_func_info is POD
@ -73,13 +73,13 @@ impl FuncSecInfo {
buf
}
pub(crate) fn len(&self) -> usize {
pub fn len(&self) -> usize {
self.func_info.len()
}
}
#[derive(Debug, Clone)]
pub(crate) struct FuncInfo {
pub struct FuncInfo {
pub data: HashMap<String, FuncSecInfo>,
}
@ -99,7 +99,7 @@ impl FuncInfo {
}
#[derive(Debug, Clone, Default)]
pub(crate) struct LineSecInfo {
pub struct LineSecInfo {
// each line info section has a header
pub _sec_name_offset: u32,
pub num_info: u32,
@ -154,7 +154,7 @@ impl LineSecInfo {
}
}
pub(crate) fn line_info_bytes(&self) -> Vec<u8> {
pub fn line_info_bytes(&self) -> Vec<u8> {
let mut buf = vec![];
for l in &self.line_info {
// Safety: bpf_func_info is POD
@ -163,7 +163,7 @@ impl LineSecInfo {
buf
}
pub(crate) fn len(&self) -> usize {
pub fn len(&self) -> usize {
self.line_info.len()
}
}

@ -1,3 +1,5 @@
//! BTF loading, parsing and relocation.
#[allow(clippy::module_inception)]
mod btf;
mod info;

@ -3,20 +3,27 @@ use std::{collections::HashMap, io, mem, ptr, str::FromStr};
use thiserror::Error;
use crate::{
btf::{
fields_are_compatible, types_are_compatible, Array, Btf, BtfError, BtfMember, BtfType,
IntEncoding, Struct, Union, MAX_SPEC_LEN,
},
generated::{
bpf_core_relo, bpf_core_relo_kind::*, bpf_insn, BPF_ALU, BPF_ALU64, BPF_B, BPF_DW, BPF_H,
BPF_K, BPF_LD, BPF_LDX, BPF_ST, BPF_STX, BPF_W, BTF_INT_SIGNED,
},
obj::{
btf::{
fields_are_compatible, types_are_compatible, Array, BtfMember, BtfType, IntEncoding,
Struct, Union, MAX_SPEC_LEN,
},
Btf, BtfError, Object, Program, ProgramSection,
},
BpfError,
Object, Program, ProgramSection,
};
#[derive(Error, Debug)]
#[error("error relocating `{section}`")]
pub struct BtfRelocationError {
/// The function name
pub section: String,
#[source]
/// The original error
error: RelocationError,
}
#[derive(Error, Debug)]
enum RelocationError {
#[error(transparent)]
@ -78,6 +85,9 @@ enum RelocationError {
type_id: u32,
ins_index: usize,
},
#[error("invalid BTF")]
BtfError(#[from] BtfError),
}
fn err_type_name(name: &Option<String>) -> String {
@ -154,7 +164,7 @@ impl Relocation {
}
impl Object {
pub fn relocate_btf(&mut self, target_btf: &Btf) -> Result<(), BpfError> {
pub fn relocate_btf(&mut self, target_btf: &Btf) -> Result<(), BtfRelocationError> {
let (local_btf, btf_ext) = match (&self.btf, &self.btf_ext) {
(Some(btf), Some(btf_ext)) => (btf, btf_ext),
_ => return Ok(()),
@ -162,7 +172,10 @@ impl Object {
let mut candidates_cache = HashMap::<u32, Vec<Candidate>>::new();
for (sec_name_off, relos) in btf_ext.relocations() {
let section_name = local_btf.string_at(*sec_name_off)?;
let section_name = local_btf.string_at(*sec_name_off).map_err(|e| BtfRelocationError {
section: format!("section@{sec_name_off}"),
error: RelocationError::BtfError(e),
})?;
let program_section = match ProgramSection::from_str(&section_name) {
Ok(program) => program,
@ -173,20 +186,17 @@ impl Object {
let program = self
.programs
.get_mut(section_name)
.ok_or(BpfError::RelocationError {
function: section_name.to_owned(),
error: Box::new(RelocationError::ProgramNotFound),
.ok_or(BtfRelocationError {
section: section_name.to_owned(),
error: RelocationError::ProgramNotFound,
})?;
match relocate_btf_program(program, relos, local_btf, target_btf, &mut candidates_cache)
{
Ok(_) => {}
Err(ErrorWrapper::BtfError(e)) => return Err(e.into()),
Err(ErrorWrapper::RelocationError(error)) => {
return Err(BpfError::RelocationError {
function: section_name.to_owned(),
error: Box::new(error),
})
}
Err(error) => return Err(BtfRelocationError {
section: section_name.to_owned(),
error,
}),
}
}
@ -200,7 +210,7 @@ fn relocate_btf_program<'target>(
local_btf: &Btf,
target_btf: &'target Btf,
candidates_cache: &mut HashMap<u32, Vec<Candidate<'target>>>,
) -> Result<(), ErrorWrapper> {
) -> Result<(), RelocationError> {
for rel in relos {
let instructions = &mut program.function.instructions;
let ins_index = rel.ins_offset / std::mem::size_of::<bpf_insn>();
@ -209,8 +219,7 @@ fn relocate_btf_program<'target>(
index: ins_index,
num_instructions: instructions.len(),
relocation_number: rel.number,
}
.into());
});
}
let local_ty = local_btf.type_by_id(rel.type_id)?;
@ -266,8 +275,7 @@ fn relocate_btf_program<'target>(
return Err(RelocationError::ConflictingCandidates {
type_name: local_name.to_string(),
candidates: conflicts,
}
.into());
});
}
target_comp_rel
} else {
@ -317,7 +325,7 @@ fn find_candidates<'target>(
fn match_candidate<'target>(
local_spec: &AccessSpec,
candidate: &'target Candidate,
) -> Result<Option<AccessSpec<'target>>, ErrorWrapper> {
) -> Result<Option<AccessSpec<'target>>, RelocationError> {
let mut target_spec = AccessSpec {
btf: candidate.btf,
root_type_id: candidate.type_id,
@ -419,8 +427,7 @@ fn match_candidate<'target>(
if target_spec.parts.len() == MAX_SPEC_LEN {
return Err(RelocationError::MaximumNestingLevelReached {
type_name: Some(candidate.name.clone()),
}
.into());
});
}
target_spec.parts.push(accessor.index);
@ -446,7 +453,7 @@ fn match_member<'target>(
target_btf: &'target Btf,
target_id: u32,
target_spec: &mut AccessSpec<'target>,
) -> Result<Option<u32>, ErrorWrapper> {
) -> Result<Option<u32>, RelocationError> {
let local_ty = local_btf.type_by_id(local_accessor.type_id)?;
let local_member = match local_ty {
// this won't panic, bounds are checked when local_spec is built in AccessSpec::new
@ -470,8 +477,7 @@ fn match_member<'target>(
let root_ty = target_spec.btf.type_by_id(target_spec.root_type_id)?;
return Err(RelocationError::MaximumNestingLevelReached {
type_name: target_spec.btf.err_type_name(root_ty),
}
.into());
});
}
// this will not panic as we've already established these are fields types
@ -532,7 +538,7 @@ impl<'a> AccessSpec<'a> {
root_type_id: u32,
spec: &str,
relocation: Relocation,
) -> Result<AccessSpec<'a>, ErrorWrapper> {
) -> Result<AccessSpec<'a>, RelocationError> {
let parts = spec
.split(':')
.map(|s| s.parse::<usize>())
@ -552,8 +558,7 @@ impl<'a> AccessSpec<'a> {
if parts != [0] {
return Err(RelocationError::InvalidAccessString {
access_str: spec.to_string(),
}
.into());
});
}
AccessSpec {
btf,
@ -569,8 +574,7 @@ impl<'a> AccessSpec<'a> {
if parts.len() != 1 {
return Err(RelocationError::InvalidAccessString {
access_str: spec.to_string(),
}
.into());
});
}
let index = parts[0];
if index >= en.variants.len() {
@ -580,8 +584,7 @@ impl<'a> AccessSpec<'a> {
index,
max_index: en.variants.len(),
error: "tried to access nonexistant enum variant".to_string(),
}
.into());
});
}
let accessors = vec![Accessor {
type_id,
@ -607,8 +610,7 @@ impl<'a> AccessSpec<'a> {
relocation_kind: format!("{:?}", relocation.kind),
type_kind: format!("{:?}", ty.kind()),
error: "enum relocation on non-enum type".to_string(),
}
.into())
})
}
},
@ -638,8 +640,7 @@ impl<'a> AccessSpec<'a> {
index,
max_index: members.len(),
error: "out of bounds struct or union access".to_string(),
}
.into());
});
}
let member = &members[index];
@ -675,8 +676,7 @@ impl<'a> AccessSpec<'a> {
index,
max_index: array.len as usize,
error: "array index out of bounds".to_string(),
}
.into());
});
}
accessors.push(Accessor {
type_id,
@ -693,8 +693,7 @@ impl<'a> AccessSpec<'a> {
type_kind: format!("{:?}", ty.kind()),
error: "field relocation on a type that doesn't have fields"
.to_string(),
}
.into());
});
}
};
}
@ -747,7 +746,7 @@ impl ComputedRelocation {
rel: &Relocation,
local_spec: &AccessSpec,
target_spec: Option<&AccessSpec>,
) -> Result<ComputedRelocation, ErrorWrapper> {
) -> Result<ComputedRelocation, RelocationError> {
use RelocationKind::*;
let ret = match rel.kind {
FieldByteOffset | FieldByteSize | FieldExists | FieldSigned | FieldLShift64
@ -774,7 +773,7 @@ impl ComputedRelocation {
rel: &Relocation,
local_btf: &Btf,
target_btf: &Btf,
) -> Result<(), ErrorWrapper> {
) -> Result<(), RelocationError> {
let instructions = &mut program.function.instructions;
let num_instructions = instructions.len();
let ins_index = rel.ins_offset / std::mem::size_of::<bpf_insn>();
@ -799,8 +798,7 @@ impl ComputedRelocation {
relocation_number: rel.number,
index: ins_index,
error: format!("invalid src_reg={src_reg:x} expected {BPF_K:x}"),
}
.into());
});
}
ins.imm = target_value as i32;
@ -811,8 +809,7 @@ impl ComputedRelocation {
relocation_number: rel.number,
index: ins_index,
error: format!("value `{target_value}` overflows 16 bits offset field"),
}
.into());
});
}
ins.off = target_value as i16;
@ -837,8 +834,7 @@ impl ComputedRelocation {
err_type_name(&target_btf.err_type_name(target_ty)),
self.target.size,
),
}
.into())
})
}
}
@ -852,8 +848,7 @@ impl ComputedRelocation {
relocation_number: rel.number,
index: ins_index,
error: format!("invalid target size {size}"),
}
.into())
})
}
} as u8;
ins.code = ins.code & 0xE0 | size | ins.code & 0x07;
@ -876,8 +871,7 @@ impl ComputedRelocation {
relocation_number: rel.number,
index: ins_index,
error: format!("invalid instruction class {class:x}"),
}
.into())
})
}
};
@ -887,7 +881,7 @@ impl ComputedRelocation {
fn compute_enum_relocation(
rel: &Relocation,
spec: Option<&AccessSpec>,
) -> Result<ComputedRelocationValue, ErrorWrapper> {
) -> Result<ComputedRelocationValue, RelocationError> {
use RelocationKind::*;
let value = match (rel.kind, spec) {
(EnumVariantExists, spec) => spec.is_some() as u32,
@ -918,7 +912,7 @@ impl ComputedRelocation {
fn compute_field_relocation(
rel: &Relocation,
spec: Option<&AccessSpec>,
) -> Result<ComputedRelocationValue, ErrorWrapper> {
) -> Result<ComputedRelocationValue, RelocationError> {
use RelocationKind::*;
if let FieldExists = rel.kind {
@ -963,8 +957,7 @@ impl ComputedRelocation {
relocation_kind: format!("{rel_kind:?}"),
type_kind: format!("{:?}", ty.kind()),
error: "invalid relocation kind for array type".to_string(),
}
.into());
});
}
};
}
@ -979,8 +972,7 @@ impl ComputedRelocation {
relocation_kind: format!("{:?}", rel.kind),
type_kind: format!("{:?}", ty.kind()),
error: "field relocation on a type that doesn't have fields".to_string(),
}
.into());
});
}
};
@ -1055,7 +1047,7 @@ impl ComputedRelocation {
rel: &Relocation,
local_spec: &AccessSpec,
target_spec: Option<&AccessSpec>,
) -> Result<ComputedRelocationValue, ErrorWrapper> {
) -> Result<ComputedRelocationValue, RelocationError> {
use RelocationKind::*;
let value = match (rel.kind, target_spec) {
@ -1081,14 +1073,3 @@ impl ComputedRelocation {
})
}
}
// this exists only to simplify propagating errors from relocate_btf() and to associate
// RelocationError(s) with their respective program name
#[derive(Error, Debug)]
enum ErrorWrapper {
#[error(transparent)]
BtfError(#[from] BtfError),
#[error(transparent)]
RelocationError(#[from] RelocationError),
}

@ -2,10 +2,10 @@ use std::{fmt::Display, mem, ptr};
use object::Endianness;
use crate::obj::btf::{Btf, BtfError, MAX_RESOLVE_DEPTH};
use crate::btf::{Btf, BtfError, MAX_RESOLVE_DEPTH};
#[derive(Clone, Debug)]
pub(crate) enum BtfType {
pub enum BtfType {
Unknown,
Fwd(Fwd),
Const(Const),
@ -29,7 +29,7 @@ pub(crate) enum BtfType {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Fwd {
pub struct Fwd {
pub(crate) name_offset: u32,
info: u32,
_unused: u32,
@ -51,7 +51,7 @@ impl Fwd {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Const {
pub struct Const {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -82,7 +82,7 @@ impl Const {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Volatile {
pub struct Volatile {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -103,7 +103,7 @@ impl Volatile {
}
#[derive(Clone, Debug)]
pub(crate) struct Restrict {
pub struct Restrict {
pub(crate) name_offset: u32,
_info: u32,
pub(crate) btf_type: u32,
@ -125,7 +125,7 @@ impl Restrict {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Ptr {
pub struct Ptr {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -144,7 +144,7 @@ impl Ptr {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, btf_type: u32) -> Self {
pub fn new(name_offset: u32, btf_type: u32) -> Self {
let info = (BtfKind::Ptr as u32) << 24;
Ptr {
name_offset,
@ -156,7 +156,7 @@ impl Ptr {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Typedef {
pub struct Typedef {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -187,7 +187,7 @@ impl Typedef {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Float {
pub struct Float {
pub(crate) name_offset: u32,
info: u32,
pub(crate) size: u32,
@ -205,7 +205,7 @@ impl Float {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, size: u32) -> Self {
pub fn new(name_offset: u32, size: u32) -> Self {
let info = (BtfKind::Float as u32) << 24;
Float {
name_offset,
@ -217,7 +217,7 @@ impl Float {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Func {
pub struct Func {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -225,7 +225,7 @@ pub(crate) struct Func {
#[repr(u32)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum FuncLinkage {
pub enum FuncLinkage {
Static = 0,
Global = 1,
Extern = 2,
@ -255,7 +255,7 @@ impl Func {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, proto: u32, linkage: FuncLinkage) -> 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;
Func {
@ -276,7 +276,7 @@ impl Func {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct TypeTag {
pub struct TypeTag {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -295,7 +295,7 @@ impl TypeTag {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, btf_type: u32) -> Self {
pub fn new(name_offset: u32, btf_type: u32) -> Self {
let info = (BtfKind::TypeTag as u32) << 24;
TypeTag {
name_offset,
@ -307,7 +307,7 @@ impl TypeTag {
#[repr(u32)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum IntEncoding {
pub enum IntEncoding {
None,
Signed = 1,
Char = 2,
@ -329,7 +329,7 @@ impl From<u32> for IntEncoding {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Int {
pub struct Int {
pub(crate) name_offset: u32,
info: u32,
pub(crate) size: u32,
@ -353,7 +353,7 @@ impl Int {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, size: u32, encoding: IntEncoding, offset: u32) -> 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;
@ -391,7 +391,7 @@ pub(crate) struct BtfEnum {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Enum {
pub struct Enum {
pub(crate) name_offset: u32,
info: u32,
pub(crate) size: u32,
@ -441,7 +441,7 @@ pub(crate) struct BtfMember {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Struct {
pub struct Struct {
pub(crate) name_offset: u32,
info: u32,
pub(crate) size: u32,
@ -502,7 +502,7 @@ impl Struct {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Union {
pub struct Union {
pub(crate) name_offset: u32,
info: u32,
pub(crate) size: u32,
@ -559,7 +559,7 @@ pub(crate) struct BtfArray {
}
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Array {
pub struct Array {
pub(crate) name_offset: u32,
info: u32,
_unused: u32,
@ -602,14 +602,14 @@ impl Array {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct BtfParam {
pub(crate) name_offset: u32,
pub(crate) btf_type: u32,
pub struct BtfParam {
pub name_offset: u32,
pub btf_type: u32,
}
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct FuncProto {
pub struct FuncProto {
pub(crate) name_offset: u32,
info: u32,
pub(crate) return_type: u32,
@ -637,7 +637,7 @@ impl FuncProto {
mem::size_of::<Fwd>() + mem::size_of::<BtfParam>() * self.params.len()
}
pub(crate) fn new(params: Vec<BtfParam>, return_type: u32) -> Self {
pub fn new(params: Vec<BtfParam>, return_type: u32) -> Self {
let mut info = (BtfKind::FuncProto as u32) << 24;
info |= (params.len() as u32) & 0xFFFF;
FuncProto {
@ -651,7 +651,7 @@ impl FuncProto {
#[repr(u32)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum VarLinkage {
pub enum VarLinkage {
Static,
Global,
Extern,
@ -671,7 +671,7 @@ impl From<u32> for VarLinkage {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct Var {
pub struct Var {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -696,7 +696,7 @@ impl Var {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, btf_type: u32, linkage: VarLinkage) -> Self {
pub fn new(name_offset: u32, btf_type: u32, linkage: VarLinkage) -> Self {
let info = (BtfKind::Var as u32) << 24;
Var {
name_offset,
@ -709,15 +709,15 @@ impl Var {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct DataSecEntry {
pub(crate) btf_type: u32,
pub(crate) offset: u32,
pub(crate) size: u32,
pub struct DataSecEntry {
pub btf_type: u32,
pub offset: u32,
pub size: u32,
}
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct DataSec {
pub struct DataSec {
pub(crate) name_offset: u32,
info: u32,
pub(crate) size: u32,
@ -746,7 +746,7 @@ impl DataSec {
mem::size_of::<Fwd>() + mem::size_of::<DataSecEntry>() * self.entries.len()
}
pub(crate) fn new(name_offset: u32, entries: Vec<DataSecEntry>, size: u32) -> Self {
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;
DataSec {
@ -760,7 +760,7 @@ impl DataSec {
#[repr(C)]
#[derive(Clone, Debug)]
pub(crate) struct DeclTag {
pub struct DeclTag {
pub(crate) name_offset: u32,
info: u32,
pub(crate) btf_type: u32,
@ -785,7 +785,7 @@ impl DeclTag {
mem::size_of::<Self>()
}
pub(crate) fn new(name_offset: u32, btf_type: u32, component_index: i32) -> Self {
pub fn new(name_offset: u32, btf_type: u32, component_index: i32) -> Self {
let info = (BtfKind::DeclTag as u32) << 24;
DeclTag {
name_offset,
@ -798,7 +798,7 @@ impl DeclTag {
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(u32)]
pub(crate) enum BtfKind {
pub enum BtfKind {
Unknown = 0,
Int = 1,
Ptr = 2,

@ -31,56 +31,3 @@ pub use linux_bindings_aarch64::*;
#[cfg(target_arch = "riscv64")]
pub use linux_bindings_riscv64::*;
pub mod maps {
/// Invalid map type encontered
pub struct InvalidMapTypeError {
/// The map type
pub map_type: u32,
}
impl TryFrom<u32> for super::bpf_map_type {
type Error = InvalidMapTypeError;
fn try_from(map_type: u32) -> Result<Self, Self::Error> {
use super::bpf_map_type::*;
Ok(match map_type {
x if x == BPF_MAP_TYPE_UNSPEC as u32 => BPF_MAP_TYPE_UNSPEC,
x if x == BPF_MAP_TYPE_HASH as u32 => BPF_MAP_TYPE_HASH,
x if x == BPF_MAP_TYPE_ARRAY as u32 => BPF_MAP_TYPE_ARRAY,
x if x == BPF_MAP_TYPE_PROG_ARRAY as u32 => BPF_MAP_TYPE_PROG_ARRAY,
x if x == BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 => BPF_MAP_TYPE_PERF_EVENT_ARRAY,
x if x == BPF_MAP_TYPE_PERCPU_HASH as u32 => BPF_MAP_TYPE_PERCPU_HASH,
x if x == BPF_MAP_TYPE_PERCPU_ARRAY as u32 => BPF_MAP_TYPE_PERCPU_ARRAY,
x if x == BPF_MAP_TYPE_STACK_TRACE as u32 => BPF_MAP_TYPE_STACK_TRACE,
x if x == BPF_MAP_TYPE_CGROUP_ARRAY as u32 => BPF_MAP_TYPE_CGROUP_ARRAY,
x if x == BPF_MAP_TYPE_LRU_HASH as u32 => BPF_MAP_TYPE_LRU_HASH,
x if x == BPF_MAP_TYPE_LRU_PERCPU_HASH as u32 => BPF_MAP_TYPE_LRU_PERCPU_HASH,
x if x == BPF_MAP_TYPE_LPM_TRIE as u32 => BPF_MAP_TYPE_LPM_TRIE,
x if x == BPF_MAP_TYPE_BLOOM_FILTER as u32 => BPF_MAP_TYPE_BLOOM_FILTER,
x if x == BPF_MAP_TYPE_ARRAY_OF_MAPS as u32 => BPF_MAP_TYPE_ARRAY_OF_MAPS,
x if x == BPF_MAP_TYPE_HASH_OF_MAPS as u32 => BPF_MAP_TYPE_HASH_OF_MAPS,
x if x == BPF_MAP_TYPE_DEVMAP as u32 => BPF_MAP_TYPE_DEVMAP,
x if x == BPF_MAP_TYPE_SOCKMAP as u32 => BPF_MAP_TYPE_SOCKMAP,
x if x == BPF_MAP_TYPE_CPUMAP as u32 => BPF_MAP_TYPE_CPUMAP,
x if x == BPF_MAP_TYPE_XSKMAP as u32 => BPF_MAP_TYPE_XSKMAP,
x if x == BPF_MAP_TYPE_SOCKHASH as u32 => BPF_MAP_TYPE_SOCKHASH,
x if x == BPF_MAP_TYPE_CGROUP_STORAGE as u32 => BPF_MAP_TYPE_CGROUP_STORAGE,
x if x == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY as u32 => BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
x if x == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE as u32 => {
BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE
}
x if x == BPF_MAP_TYPE_QUEUE as u32 => BPF_MAP_TYPE_QUEUE,
x if x == BPF_MAP_TYPE_STACK as u32 => BPF_MAP_TYPE_STACK,
x if x == BPF_MAP_TYPE_SK_STORAGE as u32 => BPF_MAP_TYPE_SK_STORAGE,
x if x == BPF_MAP_TYPE_DEVMAP_HASH as u32 => BPF_MAP_TYPE_DEVMAP_HASH,
x if x == BPF_MAP_TYPE_STRUCT_OPS as u32 => BPF_MAP_TYPE_STRUCT_OPS,
x if x == BPF_MAP_TYPE_RINGBUF as u32 => BPF_MAP_TYPE_RINGBUF,
x if x == BPF_MAP_TYPE_INODE_STORAGE as u32 => BPF_MAP_TYPE_INODE_STORAGE,
x if x == BPF_MAP_TYPE_TASK_STORAGE as u32 => BPF_MAP_TYPE_TASK_STORAGE,
_ => return Err(InvalidMapTypeError { map_type }),
})
}
}
}

@ -1,12 +1,19 @@
//! A library for loading and relocating eBPF object files.
#![no_std]
#![doc(
html_logo_url = "https://aya-rs.dev/assets/images/crabby.svg",
html_favicon_url = "https://aya-rs.dev/assets/images/crabby.svg"
)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(clippy::all, missing_docs)]
#![deny(clippy::all)]
#![allow(clippy::missing_safety_doc, clippy::len_without_is_empty)]
pub mod btf;
pub mod generated;
pub mod maps;
pub mod obj;
pub mod programs;
pub mod relocation;
mod util;
pub use obj::*;

@ -0,0 +1,111 @@
//! Map struct and type bindings.
use thiserror::Error;
/// Invalid map type encontered
pub struct InvalidMapTypeError {
/// The map type
pub map_type: u32,
}
impl TryFrom<u32> for crate::generated::bpf_map_type {
type Error = InvalidMapTypeError;
fn try_from(map_type: u32) -> Result<Self, Self::Error> {
use crate::generated::bpf_map_type::*;
Ok(match map_type {
x if x == BPF_MAP_TYPE_UNSPEC as u32 => BPF_MAP_TYPE_UNSPEC,
x if x == BPF_MAP_TYPE_HASH as u32 => BPF_MAP_TYPE_HASH,
x if x == BPF_MAP_TYPE_ARRAY as u32 => BPF_MAP_TYPE_ARRAY,
x if x == BPF_MAP_TYPE_PROG_ARRAY as u32 => BPF_MAP_TYPE_PROG_ARRAY,
x if x == BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 => BPF_MAP_TYPE_PERF_EVENT_ARRAY,
x if x == BPF_MAP_TYPE_PERCPU_HASH as u32 => BPF_MAP_TYPE_PERCPU_HASH,
x if x == BPF_MAP_TYPE_PERCPU_ARRAY as u32 => BPF_MAP_TYPE_PERCPU_ARRAY,
x if x == BPF_MAP_TYPE_STACK_TRACE as u32 => BPF_MAP_TYPE_STACK_TRACE,
x if x == BPF_MAP_TYPE_CGROUP_ARRAY as u32 => BPF_MAP_TYPE_CGROUP_ARRAY,
x if x == BPF_MAP_TYPE_LRU_HASH as u32 => BPF_MAP_TYPE_LRU_HASH,
x if x == BPF_MAP_TYPE_LRU_PERCPU_HASH as u32 => BPF_MAP_TYPE_LRU_PERCPU_HASH,
x if x == BPF_MAP_TYPE_LPM_TRIE as u32 => BPF_MAP_TYPE_LPM_TRIE,
x if x == BPF_MAP_TYPE_BLOOM_FILTER as u32 => BPF_MAP_TYPE_BLOOM_FILTER,
x if x == BPF_MAP_TYPE_ARRAY_OF_MAPS as u32 => BPF_MAP_TYPE_ARRAY_OF_MAPS,
x if x == BPF_MAP_TYPE_HASH_OF_MAPS as u32 => BPF_MAP_TYPE_HASH_OF_MAPS,
x if x == BPF_MAP_TYPE_DEVMAP as u32 => BPF_MAP_TYPE_DEVMAP,
x if x == BPF_MAP_TYPE_SOCKMAP as u32 => BPF_MAP_TYPE_SOCKMAP,
x if x == BPF_MAP_TYPE_CPUMAP as u32 => BPF_MAP_TYPE_CPUMAP,
x if x == BPF_MAP_TYPE_XSKMAP as u32 => BPF_MAP_TYPE_XSKMAP,
x if x == BPF_MAP_TYPE_SOCKHASH as u32 => BPF_MAP_TYPE_SOCKHASH,
x if x == BPF_MAP_TYPE_CGROUP_STORAGE as u32 => BPF_MAP_TYPE_CGROUP_STORAGE,
x if x == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY as u32 => BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
x if x == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE as u32 => {
BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE
}
x if x == BPF_MAP_TYPE_QUEUE as u32 => BPF_MAP_TYPE_QUEUE,
x if x == BPF_MAP_TYPE_STACK as u32 => BPF_MAP_TYPE_STACK,
x if x == BPF_MAP_TYPE_SK_STORAGE as u32 => BPF_MAP_TYPE_SK_STORAGE,
x if x == BPF_MAP_TYPE_DEVMAP_HASH as u32 => BPF_MAP_TYPE_DEVMAP_HASH,
x if x == BPF_MAP_TYPE_STRUCT_OPS as u32 => BPF_MAP_TYPE_STRUCT_OPS,
x if x == BPF_MAP_TYPE_RINGBUF as u32 => BPF_MAP_TYPE_RINGBUF,
x if x == BPF_MAP_TYPE_INODE_STORAGE as u32 => BPF_MAP_TYPE_INODE_STORAGE,
x if x == BPF_MAP_TYPE_TASK_STORAGE as u32 => BPF_MAP_TYPE_TASK_STORAGE,
_ => return Err(InvalidMapTypeError { map_type }),
})
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct BtfMapDef {
pub(crate) map_type: u32,
pub(crate) key_size: u32,
pub(crate) value_size: u32,
pub(crate) max_entries: u32,
pub(crate) map_flags: u32,
pub(crate) pinning: PinningType,
pub btf_key_type_id: u32,
pub btf_value_type_id: u32,
}
#[repr(u32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PinningType {
None = 0,
ByName = 1,
}
#[derive(Debug, Error)]
pub enum PinningError {
#[error("unsupported pinning type")]
Unsupported,
}
impl TryFrom<u32> for PinningType {
type Error = PinningError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0 => Ok(PinningType::None),
1 => Ok(PinningType::ByName),
_ => Err(PinningError::Unsupported),
}
}
}
impl Default for PinningType {
fn default() -> Self {
PinningType::None
}
}
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct bpf_map_def {
// minimum features required by old BPF programs
pub map_type: u32,
pub key_size: u32,
pub value_size: u32,
pub max_entries: u32,
pub map_flags: u32,
// optional features
pub id: u32,
pub pinning: PinningType,
}

@ -1,5 +1,4 @@
pub(crate) mod btf;
mod relocation;
//! Object file loading, parsing, and relocation.
use log::debug;
use object::{
@ -15,18 +14,18 @@ use std::{
};
use thiserror::Error;
use relocation::*;
use crate::relocation::*;
use crate::{
bpf_map_def,
maps::bpf_map_def,
btf::{Btf, BtfError, BtfExt, BtfType},
generated::{bpf_insn, bpf_map_info, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_F_RDONLY_PROG},
obj::btf::{Btf, BtfError, BtfExt, BtfType},
programs::{CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType},
BpfError, BtfMapDef, PinningType,
maps::BtfMapDef, maps::PinningType,
};
use std::slice::from_raw_parts_mut;
use self::btf::{Array, DataSecEntry, FuncSecInfo, LineSecInfo};
use crate::btf::{Array, DataSecEntry, FuncSecInfo, LineSecInfo};
const KERNEL_VERSION_ANY: u32 = 0xFFFF_FFFE;
/// The first five __u32 of `bpf_map_def` must be defined.
@ -34,25 +33,25 @@ const MINIMUM_MAP_SIZE: usize = mem::size_of::<u32>() * 5;
#[derive(Clone)]
pub struct Object {
pub(crate) endianness: Endianness,
pub endianness: Endianness,
pub license: CString,
pub kernel_version: KernelVersion,
pub btf: Option<Btf>,
pub btf_ext: Option<BtfExt>,
pub(crate) maps: HashMap<String, Map>,
pub(crate) programs: HashMap<String, Program>,
pub(crate) functions: HashMap<u64, Function>,
pub(crate) relocations: HashMap<SectionIndex, HashMap<u64, Relocation>>,
pub(crate) symbols_by_index: HashMap<usize, Symbol>,
pub(crate) section_sizes: HashMap<String, u64>,
pub maps: HashMap<String, Map>,
pub programs: HashMap<String, Program>,
pub functions: HashMap<u64, Function>,
pub relocations: HashMap<SectionIndex, HashMap<u64, Relocation>>,
pub symbols_by_index: HashMap<usize, Symbol>,
pub section_sizes: HashMap<String, u64>,
// symbol_offset_by_name caches symbols that could be referenced from a
// BTF VAR type so the offsets can be fixed up
pub(crate) symbol_offset_by_name: HashMap<String, u64>,
pub(crate) text_section_index: Option<usize>,
pub symbol_offset_by_name: HashMap<String, u64>,
pub text_section_index: Option<usize>,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) enum MapKind {
pub enum MapKind {
Bss,
Data,
Rodata,
@ -80,84 +79,84 @@ pub enum Map {
}
impl Map {
pub(crate) fn map_type(&self) -> u32 {
pub fn map_type(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.map_type,
Map::Btf(m) => m.def.map_type,
}
}
pub(crate) fn key_size(&self) -> u32 {
pub fn key_size(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.key_size,
Map::Btf(m) => m.def.key_size,
}
}
pub(crate) fn value_size(&self) -> u32 {
pub fn value_size(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.value_size,
Map::Btf(m) => m.def.value_size,
}
}
pub(crate) fn max_entries(&self) -> u32 {
pub fn max_entries(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.max_entries,
Map::Btf(m) => m.def.max_entries,
}
}
pub(crate) fn set_max_entries(&mut self, v: u32) {
pub fn set_max_entries(&mut self, v: u32) {
match self {
Map::Legacy(m) => m.def.max_entries = v,
Map::Btf(m) => m.def.max_entries = v,
}
}
pub(crate) fn map_flags(&self) -> u32 {
pub fn map_flags(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.map_flags,
Map::Btf(m) => m.def.map_flags,
}
}
pub(crate) fn pinning(&self) -> PinningType {
pub fn pinning(&self) -> PinningType {
match self {
Map::Legacy(m) => m.def.pinning,
Map::Btf(m) => m.def.pinning,
}
}
pub(crate) fn data(&self) -> &[u8] {
pub fn data(&self) -> &[u8] {
match self {
Map::Legacy(m) => &m.data,
Map::Btf(m) => &m.data,
}
}
pub(crate) fn data_mut(&mut self) -> &mut Vec<u8> {
pub fn data_mut(&mut self) -> &mut Vec<u8> {
match self {
Map::Legacy(m) => m.data.as_mut(),
Map::Btf(m) => m.data.as_mut(),
}
}
pub(crate) fn kind(&self) -> MapKind {
pub fn kind(&self) -> MapKind {
match self {
Map::Legacy(m) => m.kind,
Map::Btf(m) => m.kind,
}
}
pub(crate) fn section_index(&self) -> usize {
pub fn section_index(&self) -> usize {
match self {
Map::Legacy(m) => m.section_index,
Map::Btf(m) => m.section_index,
}
}
pub(crate) fn symbol_index(&self) -> usize {
pub fn symbol_index(&self) -> usize {
match self {
Map::Legacy(m) => m.symbol_index,
Map::Btf(m) => m.symbol_index,
@ -167,41 +166,41 @@ impl Map {
#[derive(Debug, Clone)]
pub struct LegacyMap {
pub(crate) def: bpf_map_def,
pub(crate) section_index: usize,
pub(crate) symbol_index: usize,
pub(crate) data: Vec<u8>,
pub(crate) kind: MapKind,
pub def: bpf_map_def,
pub section_index: usize,
pub symbol_index: usize,
pub data: Vec<u8>,
pub kind: MapKind,
}
#[derive(Debug, Clone)]
pub struct BtfMap {
pub(crate) def: BtfMapDef,
pub(crate) section_index: usize,
pub(crate) symbol_index: usize,
pub(crate) kind: MapKind,
pub(crate) data: Vec<u8>,
pub def: BtfMapDef,
pub section_index: usize,
pub symbol_index: usize,
pub kind: MapKind,
pub data: Vec<u8>,
}
#[derive(Debug, Clone)]
pub(crate) struct Program {
pub(crate) license: CString,
pub(crate) kernel_version: KernelVersion,
pub(crate) section: ProgramSection,
pub(crate) function: Function,
pub struct Program {
pub license: CString,
pub kernel_version: KernelVersion,
pub section: ProgramSection,
pub function: Function,
}
#[derive(Debug, Clone)]
pub(crate) struct Function {
pub(crate) address: u64,
pub(crate) name: String,
pub(crate) section_index: SectionIndex,
pub(crate) section_offset: usize,
pub(crate) instructions: Vec<bpf_insn>,
pub(crate) func_info: FuncSecInfo,
pub(crate) line_info: LineSecInfo,
pub(crate) func_info_rec_size: usize,
pub(crate) line_info_rec_size: usize,
pub struct Function {
pub address: u64,
pub name: String,
pub section_index: SectionIndex,
pub section_offset: usize,
pub instructions: Vec<bpf_insn>,
pub func_info: FuncSecInfo,
pub line_info: LineSecInfo,
pub func_info_rec_size: usize,
pub line_info_rec_size: usize,
}
#[derive(Debug, Clone)]
@ -299,7 +298,7 @@ pub enum ProgramSection {
}
impl ProgramSection {
fn name(&self) -> &str {
pub fn name(&self) -> &str {
match self {
ProgramSection::KRetProbe { name } => name,
ProgramSection::KProbe { name } => name,
@ -521,7 +520,7 @@ impl FromStr for ProgramSection {
}
impl Object {
pub(crate) fn parse(data: &[u8]) -> Result<Object, BpfError> {
pub fn parse(data: &[u8]) -> Result<Object, ParseError> {
let obj = object::read::File::parse(data).map_err(ParseError::ElfError)?;
let endianness = obj.endianness();
@ -829,9 +828,9 @@ impl Object {
&mut self,
section: &Section,
symbols: HashMap<String, Symbol>,
) -> Result<(), BpfError> {
) -> Result<(), ParseError> {
if self.btf.is_none() {
return Err(BpfError::NoBTF);
return Err(ParseError::NoBTF);
}
let btf = self.btf.as_ref().unwrap();
@ -847,10 +846,8 @@ impl Object {
let (map_name, def) = parse_btf_map_def(btf, info)?;
let symbol_index = symbols
.get(&map_name)
.ok_or_else(|| {
BpfError::ParseError(ParseError::SymbolNotFound {
.ok_or_else(|| ParseError::SymbolNotFound {
name: map_name.to_string(),
})
})?
.index;
self.maps.insert(
@ -870,7 +867,7 @@ impl Object {
Ok(())
}
fn parse_section(&mut self, mut section: Section) -> Result<(), BpfError> {
fn parse_section(&mut self, mut section: Section) -> Result<(), ParseError> {
let mut parts = section.name.rsplitn(2, '/').collect::<Vec<_>>();
parts.reverse();
@ -945,11 +942,14 @@ impl Object {
}
}
#[derive(Debug, Clone, Error)]
#[derive(Debug, Error)]
pub enum ParseError {
#[error("error parsing ELF data")]
ElfError(#[from] object::read::Error),
#[error("BTF error")]
BtfError(#[from] BtfError),
#[error("invalid license `{data:?}`: missing NULL terminator")]
MissingLicenseNullTerminator { data: Vec<u8> },
@ -1005,6 +1005,9 @@ pub enum ParseError {
#[error("no symbols found for the maps included in the maps section")]
NoSymbolsInMapSection {},
#[error("no BTF parsed for object")]
NoBTF,
}
#[derive(Debug)]
@ -1311,7 +1314,7 @@ fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDe
Ok((map_name.to_string(), map_def))
}
pub(crate) fn parse_map_info(info: bpf_map_info, pinned: PinningType) -> Map {
pub fn parse_map_info(info: bpf_map_info, pinned: PinningType) -> Map {
if info.btf_key_type_id != 0 {
Map::Btf(BtfMap {
def: BtfMapDef {
@ -1350,7 +1353,7 @@ pub(crate) fn parse_map_info(info: bpf_map_info, pinned: PinningType) -> Map {
}
}
pub(crate) fn copy_instructions(data: &[u8]) -> Result<Vec<bpf_insn>, ParseError> {
pub fn copy_instructions(data: &[u8]) -> Result<Vec<bpf_insn>, ParseError> {
if data.len() % mem::size_of::<bpf_insn>() > 0 {
return Err(ParseError::InvalidProgramCode);
}
@ -1367,7 +1370,7 @@ mod tests {
use object::Endianness;
use super::*;
use crate::PinningType;
use crate::maps::PinningType;
fn fake_section<'a>(kind: BpfSectionKind, name: &'a str, data: &'a [u8]) -> Section<'a> {
Section {
@ -1416,7 +1419,7 @@ mod tests {
fn test_parse_generic_error() {
assert!(matches!(
Object::parse(&b"foo"[..]),
Err(BpfError::ParseError(ParseError::ElfError(_)))
Err(ParseError::ElfError(_))
))
}

@ -0,0 +1,52 @@
//! Cgroup socket programs.
use thiserror::Error;
use crate::generated::bpf_attach_type;
/// Defines where to attach a [`CgroupSock`] program.
#[derive(Copy, Clone, Debug)]
pub enum CgroupSockAttachType {
/// Called after the IPv4 bind events.
PostBind4,
/// Called after the IPv6 bind events.
PostBind6,
/// Attach to IPv4 connect events.
SockCreate,
/// Attach to IPv6 connect events.
SockRelease,
}
impl Default for CgroupSockAttachType {
// The kernel checks for a 0 attach_type and sets it to sock_create
// We may as well do that here also
fn default() -> Self {
CgroupSockAttachType::SockCreate
}
}
impl From<CgroupSockAttachType> for bpf_attach_type {
fn from(s: CgroupSockAttachType) -> bpf_attach_type {
match s {
CgroupSockAttachType::PostBind4 => bpf_attach_type::BPF_CGROUP_INET4_POST_BIND,
CgroupSockAttachType::PostBind6 => bpf_attach_type::BPF_CGROUP_INET6_POST_BIND,
CgroupSockAttachType::SockCreate => bpf_attach_type::BPF_CGROUP_INET_SOCK_CREATE,
CgroupSockAttachType::SockRelease => bpf_attach_type::BPF_CGROUP_INET_SOCK_RELEASE,
}
}
}
#[derive(Debug, Error)]
#[error("{0} is not a valid attach type for a CGROUP_SOCK program")]
pub(crate) struct InvalidAttachType(String);
impl CgroupSockAttachType {
pub(crate) fn try_from(value: &str) -> Result<CgroupSockAttachType, InvalidAttachType> {
match value {
"post_bind4" => Ok(CgroupSockAttachType::PostBind4),
"post_bind6" => Ok(CgroupSockAttachType::PostBind6),
"sock_create" => Ok(CgroupSockAttachType::SockCreate),
"sock_release" => Ok(CgroupSockAttachType::SockRelease),
_ => Err(InvalidAttachType(value.to_owned())),
}
}
}

@ -0,0 +1,76 @@
//! Cgroup socket address programs.
use thiserror::Error;
use crate::generated::bpf_attach_type;
/// Defines where to attach a [`CgroupSockAddr`] program.
#[derive(Copy, Clone, Debug)]
pub enum CgroupSockAddrAttachType {
/// Attach to IPv4 bind events.
Bind4,
/// Attach to IPv6 bind events.
Bind6,
/// Attach to IPv4 connect events.
Connect4,
/// Attach to IPv6 connect events.
Connect6,
/// Attach to IPv4 getpeername events.
GetPeerName4,
/// Attach to IPv6 getpeername events.
GetPeerName6,
/// Attach to IPv4 getsockname events.
GetSockName4,
/// Attach to IPv6 getsockname events.
GetSockName6,
/// Attach to IPv4 udp_sendmsg events.
UDPSendMsg4,
/// Attach to IPv6 udp_sendmsg events.
UDPSendMsg6,
/// Attach to IPv4 udp_recvmsg events.
UDPRecvMsg4,
/// Attach to IPv6 udp_recvmsg events.
UDPRecvMsg6,
}
impl From<CgroupSockAddrAttachType> for bpf_attach_type {
fn from(s: CgroupSockAddrAttachType) -> bpf_attach_type {
match s {
CgroupSockAddrAttachType::Bind4 => bpf_attach_type::BPF_CGROUP_INET4_BIND,
CgroupSockAddrAttachType::Bind6 => bpf_attach_type::BPF_CGROUP_INET6_BIND,
CgroupSockAddrAttachType::Connect4 => bpf_attach_type::BPF_CGROUP_INET4_CONNECT,
CgroupSockAddrAttachType::Connect6 => bpf_attach_type::BPF_CGROUP_INET6_CONNECT,
CgroupSockAddrAttachType::GetPeerName4 => bpf_attach_type::BPF_CGROUP_INET4_GETPEERNAME,
CgroupSockAddrAttachType::GetPeerName6 => bpf_attach_type::BPF_CGROUP_INET6_GETPEERNAME,
CgroupSockAddrAttachType::GetSockName4 => bpf_attach_type::BPF_CGROUP_INET4_GETSOCKNAME,
CgroupSockAddrAttachType::GetSockName6 => bpf_attach_type::BPF_CGROUP_INET6_GETSOCKNAME,
CgroupSockAddrAttachType::UDPSendMsg4 => bpf_attach_type::BPF_CGROUP_UDP4_SENDMSG,
CgroupSockAddrAttachType::UDPSendMsg6 => bpf_attach_type::BPF_CGROUP_UDP6_SENDMSG,
CgroupSockAddrAttachType::UDPRecvMsg4 => bpf_attach_type::BPF_CGROUP_UDP4_RECVMSG,
CgroupSockAddrAttachType::UDPRecvMsg6 => bpf_attach_type::BPF_CGROUP_UDP6_RECVMSG,
}
}
}
#[derive(Debug, Error)]
#[error("{0} is not a valid attach type for a CGROUP_SOCK_ADDR program")]
pub(crate) struct InvalidAttachType(String);
impl CgroupSockAddrAttachType {
pub(crate) fn try_from(value: &str) -> Result<CgroupSockAddrAttachType, InvalidAttachType> {
match value {
"bind4" => Ok(CgroupSockAddrAttachType::Bind4),
"bind6" => Ok(CgroupSockAddrAttachType::Bind6),
"connect4" => Ok(CgroupSockAddrAttachType::Connect4),
"connect6" => Ok(CgroupSockAddrAttachType::Connect6),
"getpeername4" => Ok(CgroupSockAddrAttachType::GetPeerName4),
"getpeername6" => Ok(CgroupSockAddrAttachType::GetPeerName6),
"getsockname4" => Ok(CgroupSockAddrAttachType::GetSockName4),
"getsockname6" => Ok(CgroupSockAddrAttachType::GetSockName6),
"sendmsg4" => Ok(CgroupSockAddrAttachType::UDPSendMsg4),
"sendmsg6" => Ok(CgroupSockAddrAttachType::UDPSendMsg6),
"recvmsg4" => Ok(CgroupSockAddrAttachType::UDPRecvMsg4),
"recvmsg6" => Ok(CgroupSockAddrAttachType::UDPRecvMsg6),
_ => Err(InvalidAttachType(value.to_owned())),
}
}
}

@ -0,0 +1,36 @@
//! Cgroup socket option programs.
use thiserror::Error;
use crate::generated::bpf_attach_type;
/// Defines where to attach a [`CgroupSockopt`] program.
#[derive(Copy, Clone, Debug)]
pub enum CgroupSockoptAttachType {
/// Attach to GetSockopt.
Get,
/// Attach to SetSockopt.
Set,
}
impl From<CgroupSockoptAttachType> for bpf_attach_type {
fn from(s: CgroupSockoptAttachType) -> bpf_attach_type {
match s {
CgroupSockoptAttachType::Get => bpf_attach_type::BPF_CGROUP_GETSOCKOPT,
CgroupSockoptAttachType::Set => bpf_attach_type::BPF_CGROUP_SETSOCKOPT,
}
}
}
#[derive(Debug, Error)]
#[error("{0} is not a valid attach type for a CGROUP_SOCKOPT program")]
pub(crate) struct InvalidAttachType(String);
impl CgroupSockoptAttachType {
pub(crate) fn try_from(value: &str) -> Result<CgroupSockoptAttachType, InvalidAttachType> {
match value {
"getsockopt" => Ok(CgroupSockoptAttachType::Get),
"setsockopt" => Ok(CgroupSockoptAttachType::Set),
_ => Err(InvalidAttachType(value.to_owned())),
}
}
}

@ -0,0 +1,9 @@
//! Program struct and type bindings.
pub mod cgroup_sock;
pub mod cgroup_sock_addr;
pub mod cgroup_sockopt;
pub use cgroup_sock::CgroupSockAttachType;
pub use cgroup_sock_addr::CgroupSockAddrAttachType;
pub use cgroup_sockopt::CgroupSockoptAttachType;

@ -9,15 +9,23 @@ use crate::{
bpf_insn, BPF_CALL, BPF_JMP, BPF_K, BPF_PSEUDO_CALL, BPF_PSEUDO_FUNC, BPF_PSEUDO_MAP_FD,
BPF_PSEUDO_MAP_VALUE,
},
maps::MapData,
obj::{Function, Object, Program},
BpfError,
obj::{Function, Object, Program}, Map,
};
pub(crate) const INS_SIZE: usize = mem::size_of::<bpf_insn>();
#[derive(Error, Debug)]
#[error("error relocating `{function}`")]
pub struct BpfRelocationError {
/// The function name
function: String,
#[source]
/// The original error
error: RelocationError,
}
#[derive(Debug, Error)]
enum RelocationError {
pub enum RelocationError {
#[error("unknown symbol, index `{index}`")]
UnknownSymbol { index: usize },
@ -43,7 +51,7 @@ enum RelocationError {
}
#[derive(Debug, Copy, Clone)]
pub(crate) struct Relocation {
pub struct Relocation {
// byte offset of the instruction to be relocated
pub(crate) offset: u64,
// index of the symbol to relocate to
@ -51,7 +59,7 @@ pub(crate) struct Relocation {
}
#[derive(Debug, Clone)]
pub(crate) struct Symbol {
pub struct Symbol {
pub(crate) index: usize,
pub(crate) section_index: Option<usize>,
pub(crate) name: Option<String>,
@ -62,16 +70,16 @@ pub(crate) struct Symbol {
}
impl Object {
pub fn relocate_maps(&mut self, maps: &HashMap<String, MapData>) -> Result<(), BpfError> {
let maps_by_section = maps
.iter()
.map(|(name, map)| (map.obj.section_index(), (name.as_str(), map)))
.collect::<HashMap<_, _>>();
let maps_by_symbol = maps
.iter()
.map(|(name, map)| (map.obj.symbol_index(), (name.as_str(), map)))
.collect::<HashMap<_, _>>();
pub fn relocate_maps<'a, I: Iterator<Item = (&'a str, Option<i32>, &'a Map)>>(
&mut self,
maps: I,
) -> Result<(), BpfRelocationError> {
let mut maps_by_section = HashMap::new();
let mut maps_by_symbol = HashMap::new();
for (name, fd, map) in maps {
maps_by_section.insert(map.section_index(), (name, fd, map));
maps_by_symbol.insert(map.symbol_index(), (name, fd, map));
}
let functions = self
.programs
@ -89,9 +97,9 @@ impl Object {
&self.symbols_by_index,
self.text_section_index,
)
.map_err(|error| BpfError::RelocationError {
.map_err(|error| BpfRelocationError {
function: function.name.clone(),
error: Box::new(error),
error,
})?;
}
}
@ -99,7 +107,7 @@ impl Object {
Ok(())
}
pub fn relocate_calls(&mut self) -> Result<(), BpfError> {
pub fn relocate_calls(&mut self) -> Result<(), BpfRelocationError> {
for (name, program) in self.programs.iter_mut() {
let linker = FunctionLinker::new(
self.text_section_index,
@ -109,9 +117,9 @@ impl Object {
);
linker
.link(program)
.map_err(|error| BpfError::RelocationError {
function: name.clone(),
error: Box::new(error),
.map_err(|error| BpfRelocationError{
function: name.to_owned(),
error,
})?;
}
@ -122,8 +130,8 @@ impl Object {
fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
fun: &mut Function,
relocations: I,
maps_by_section: &HashMap<usize, (&str, &MapData)>,
maps_by_symbol: &HashMap<usize, (&str, &MapData)>,
maps_by_section: &HashMap<usize, (&str, Option<i32>, &Map)>,
maps_by_symbol: &HashMap<usize, (&str, Option<i32>, &Map)>,
symbol_table: &HashMap<usize, Symbol>,
text_section_index: Option<usize>,
) -> Result<(), RelocationError> {
@ -166,7 +174,7 @@ fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
continue;
}
let (name, map) = if maps_by_symbol.contains_key(&rel.symbol_index) {
let (name, fd, map) = if maps_by_symbol.contains_key(&rel.symbol_index) {
maps_by_symbol
.get(&rel.symbol_index)
.ok_or(RelocationError::SectionNotFound {
@ -184,12 +192,12 @@ fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
})?
};
let map_fd = map.fd.ok_or_else(|| RelocationError::MapNotCreated {
let map_fd = fd.ok_or_else(|| RelocationError::MapNotCreated {
name: (*name).into(),
section_index,
})?;
if !map.obj.data().is_empty() {
if !map.data().is_empty() {
instructions[ins_index].set_src_reg(BPF_PSEUDO_MAP_VALUE as u8);
instructions[ins_index + 1].imm = instructions[ins_index].imm + sym.address as i32;
} else {
@ -437,10 +445,9 @@ fn insn_is_call(ins: &bpf_insn) -> bool {
#[cfg(test)]
mod test {
use crate::{
bpf_map_def,
maps::MapData,
maps::bpf_map_def,
obj::{self, BtfMap, LegacyMap, MapKind},
BtfMapDef,
maps::BtfMapDef,
};
use super::*;
@ -461,9 +468,8 @@ mod test {
unsafe { std::ptr::read_unaligned(bytes.as_ptr() as *const _) }
}
fn fake_legacy_map(fd: i32, symbol_index: usize) -> MapData {
MapData {
obj: obj::Map::Legacy(LegacyMap {
fn fake_legacy_map(symbol_index: usize) -> Map {
obj::Map::Legacy(LegacyMap {
def: bpf_map_def {
..Default::default()
},
@ -471,16 +477,11 @@ mod test {
symbol_index,
data: Vec::new(),
kind: MapKind::Other,
}),
fd: Some(fd),
btf_fd: None,
pinned: false,
}
})
}
fn fake_btf_map(fd: i32, symbol_index: usize) -> MapData {
MapData {
obj: obj::Map::Btf(BtfMap {
fn fake_btf_map(symbol_index: usize) -> Map {
obj::Map::Btf(BtfMap {
def: BtfMapDef {
..Default::default()
},
@ -488,11 +489,7 @@ mod test {
symbol_index,
data: Vec::new(),
kind: MapKind::Other,
}),
fd: Some(fd),
btf_fd: None,
pinned: false,
}
})
}
fn fake_func(name: &str, instructions: Vec<bpf_insn>) -> Function {
@ -527,8 +524,8 @@ mod test {
}];
let maps_by_section = HashMap::new();
let map = fake_legacy_map(1, 1);
let maps_by_symbol = HashMap::from([(1, ("test_map", &map))]);
let map = fake_legacy_map(1);
let maps_by_symbol = HashMap::from([(1, ("test_map", Some(1), &map))]);
relocate_maps(
&mut fun,
@ -579,10 +576,10 @@ mod test {
];
let maps_by_section = HashMap::new();
let map_1 = fake_legacy_map(1, 1);
let map_2 = fake_legacy_map(2, 2);
let map_1 = fake_legacy_map(1);
let map_2 = fake_legacy_map(2);
let maps_by_symbol =
HashMap::from([(1, ("test_map_1", &map_1)), (2, ("test_map_2", &map_2))]);
HashMap::from([(1, ("test_map_1", Some(1), &map_1)), (2, ("test_map_2", Some(2), &map_2))]);
relocate_maps(
&mut fun,
@ -622,8 +619,8 @@ mod test {
}];
let maps_by_section = HashMap::new();
let map = fake_btf_map(1, 1);
let maps_by_symbol = HashMap::from([(1, ("test_map", &map))]);
let map = fake_btf_map(1);
let maps_by_symbol = HashMap::from([(1, ("test_map", Some(1), &map))]);
relocate_maps(
&mut fun,
@ -674,10 +671,10 @@ mod test {
];
let maps_by_section = HashMap::new();
let map_1 = fake_btf_map(1, 1);
let map_2 = fake_btf_map(2, 2);
let map_1 = fake_btf_map(1);
let map_2 = fake_btf_map(2);
let maps_by_symbol =
HashMap::from([(1, ("test_map_1", &map_1)), (2, ("test_map_2", &map_2))]);
HashMap::from([(1, ("test_map_1", Some(1), &map_1)), (2, ("test_map_2", Some(2), &map_2))]);
relocate_maps(
&mut fun,

@ -0,0 +1,7 @@
use core::{mem, slice};
/// bytes_of converts a <T> to a byte slice
pub(crate) unsafe fn bytes_of<T>(val: &T) -> &[u8] {
let size = mem::size_of::<T>();
slice::from_raw_parts(slice::from_ref(val).as_ptr().cast(), size)
}

@ -1,13 +1,13 @@
use std::{
borrow::Cow,
collections::{HashMap, HashSet},
error::Error,
ffi::CString,
fs, io,
os::{raw::c_int, unix::io::RawFd},
path::{Path, PathBuf},
};
use aya_obj::{btf::{BtfFeatures, BtfRelocationError}, relocation::BpfRelocationError};
use log::debug;
use thiserror::Error;
@ -58,75 +58,15 @@ unsafe_impl_pod!(i8, u8, i16, u16, i32, u32, i64, u64, u128, i128);
// It only makes sense that an array of POD types is itself POD
unsafe impl<T: Pod, const N: usize> Pod for [T; N] {}
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub(crate) struct bpf_map_def {
// minimum features required by old BPF programs
pub(crate) map_type: u32,
pub(crate) key_size: u32,
pub(crate) value_size: u32,
pub(crate) max_entries: u32,
pub(crate) map_flags: u32,
// optional features
pub(crate) id: u32,
pub(crate) pinning: PinningType,
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub(crate) struct BtfMapDef {
pub(crate) map_type: u32,
pub(crate) key_size: u32,
pub(crate) value_size: u32,
pub(crate) max_entries: u32,
pub(crate) map_flags: u32,
pub(crate) pinning: PinningType,
pub(crate) btf_key_type_id: u32,
pub(crate) btf_value_type_id: u32,
}
#[repr(u32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum PinningType {
None = 0,
ByName = 1,
}
#[derive(Debug, Error)]
pub(crate) enum PinningError {
#[error("unsupported pinning type")]
Unsupported,
}
impl TryFrom<u32> for PinningType {
type Error = PinningError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0 => Ok(PinningType::None),
1 => Ok(PinningType::ByName),
_ => Err(PinningError::Unsupported),
}
}
}
impl Default for PinningType {
fn default() -> Self {
PinningType::None
}
}
pub use aya_obj::maps::bpf_map_def;
pub use aya_obj::maps::BtfMapDef;
pub use aya_obj::maps::PinningType;
// Features implements BPF and BTF feature detection
#[derive(Default, Debug)]
pub(crate) struct Features {
pub bpf_name: bool,
pub btf: bool,
pub btf_func: bool,
pub btf_func_global: bool,
pub btf_datasec: bool,
pub btf_float: bool,
pub btf_decl_tag: bool,
pub btf_type_tag: bool,
pub btf: Option<BtfFeatures>,
}
impl Features {
@ -134,33 +74,37 @@ impl Features {
self.bpf_name = is_prog_name_supported();
debug!("[FEAT PROBE] BPF program name support: {}", self.bpf_name);
self.btf = is_btf_supported();
debug!("[FEAT PROBE] BTF support: {}", self.btf);
self.btf = if is_btf_supported() {
Some(BtfFeatures::default())
} else {
None
};
debug!("[FEAT PROBE] BTF support: {}", self.btf.is_some());
if self.btf {
self.btf_func = is_btf_func_supported();
debug!("[FEAT PROBE] BTF func support: {}", self.btf_func);
if let Some(ref mut btf) = self.btf {
btf.btf_func = is_btf_func_supported();
debug!("[FEAT PROBE] BTF func support: {}", btf.btf_func);
self.btf_func_global = is_btf_func_global_supported();
btf.btf_func_global = is_btf_func_global_supported();
debug!(
"[FEAT PROBE] BTF global func support: {}",
self.btf_func_global
btf.btf_func_global
);
self.btf_datasec = is_btf_datasec_supported();
btf.btf_datasec = is_btf_datasec_supported();
debug!(
"[FEAT PROBE] BTF var and datasec support: {}",
self.btf_datasec
btf.btf_datasec
);
self.btf_float = is_btf_float_supported();
debug!("[FEAT PROBE] BTF float support: {}", self.btf_float);
btf.btf_float = is_btf_float_supported();
debug!("[FEAT PROBE] BTF float support: {}", btf.btf_float);
self.btf_decl_tag = is_btf_decl_tag_supported();
debug!("[FEAT PROBE] BTF decl_tag support: {}", self.btf_decl_tag);
btf.btf_decl_tag = is_btf_decl_tag_supported();
debug!("[FEAT PROBE] BTF decl_tag support: {}", btf.btf_decl_tag);
self.btf_type_tag = is_btf_type_tag_supported();
debug!("[FEAT PROBE] BTF type_tag support: {}", self.btf_type_tag);
btf.btf_type_tag = is_btf_type_tag_supported();
debug!("[FEAT PROBE] BTF type_tag support: {}", btf.btf_type_tag);
}
}
}
@ -413,12 +357,12 @@ impl<'a> BpfLoader<'a> {
let mut obj = Object::parse(data)?;
obj.patch_map_data(self.globals.clone())?;
let btf_fd = if self.features.btf {
let btf_fd = if let Some(ref btf) = self.features.btf {
if let Some(ref mut obj_btf) = obj.btf {
// fixup btf
let section_data = obj.section_sizes.clone();
let symbol_offsets = obj.symbol_offset_by_name.clone();
obj_btf.fixup_and_sanitize(&section_data, &symbol_offsets, &self.features)?;
obj_btf.fixup_and_sanitize(&section_data, &symbol_offsets, btf)?;
// load btf to the kernel
let raw_btf = obj_btf.to_bytes();
Some(load_btf(raw_btf)?)
@ -497,7 +441,7 @@ impl<'a> BpfLoader<'a> {
maps.insert(name, map);
}
obj.relocate_maps(&maps)?;
obj.relocate_maps(maps.iter().map(|(s, data)| (s.as_str(), data.fd, &data.obj)))?;
obj.relocate_calls()?;
let programs = obj
@ -921,14 +865,12 @@ pub enum BpfError {
BtfError(#[from] BtfError),
/// Error performing relocations
#[error("error relocating `{function}`")]
RelocationError {
/// The function name
function: String,
#[source]
/// The original error
error: Box<dyn Error + Send + Sync>,
},
#[error("error relocating function")]
RelocationError(#[from] BpfRelocationError),
/// Error performing relocations
#[error("error relocating section")]
BtfRelocationError(#[from] BtfRelocationError),
/// No BTF parsed for object
#[error("no BTF parsed for object")]

@ -46,9 +46,9 @@ extern crate lazy_static;
extern crate bitflags;
mod bpf;
use aya_obj::generated as generated;
use aya_obj::generated;
pub mod maps;
mod obj;
use aya_obj as obj;
pub mod pin;
pub mod programs;
mod sys;

@ -1,7 +1,6 @@
//! Cgroup socket programs.
use thiserror::Error;
pub use aya_obj::programs::CgroupSockAttachType;
use crate::generated::bpf_attach_type;
use std::{
hash::Hash,
os::unix::prelude::{AsRawFd, RawFd},
@ -154,51 +153,3 @@ define_link_wrapper!(
CgroupSockLinkInner,
CgroupSockLinkIdInner
);
/// Defines where to attach a [`CgroupSock`] program.
#[derive(Copy, Clone, Debug)]
pub enum CgroupSockAttachType {
/// Called after the IPv4 bind events.
PostBind4,
/// Called after the IPv6 bind events.
PostBind6,
/// Attach to IPv4 connect events.
SockCreate,
/// Attach to IPv6 connect events.
SockRelease,
}
impl Default for CgroupSockAttachType {
// The kernel checks for a 0 attach_type and sets it to sock_create
// We may as well do that here also
fn default() -> Self {
CgroupSockAttachType::SockCreate
}
}
impl From<CgroupSockAttachType> for bpf_attach_type {
fn from(s: CgroupSockAttachType) -> bpf_attach_type {
match s {
CgroupSockAttachType::PostBind4 => bpf_attach_type::BPF_CGROUP_INET4_POST_BIND,
CgroupSockAttachType::PostBind6 => bpf_attach_type::BPF_CGROUP_INET6_POST_BIND,
CgroupSockAttachType::SockCreate => bpf_attach_type::BPF_CGROUP_INET_SOCK_CREATE,
CgroupSockAttachType::SockRelease => bpf_attach_type::BPF_CGROUP_INET_SOCK_RELEASE,
}
}
}
#[derive(Debug, Error)]
#[error("{0} is not a valid attach type for a CGROUP_SOCK program")]
pub(crate) struct InvalidAttachType(String);
impl CgroupSockAttachType {
pub(crate) fn try_from(value: &str) -> Result<CgroupSockAttachType, InvalidAttachType> {
match value {
"post_bind4" => Ok(CgroupSockAttachType::PostBind4),
"post_bind6" => Ok(CgroupSockAttachType::PostBind6),
"sock_create" => Ok(CgroupSockAttachType::SockCreate),
"sock_release" => Ok(CgroupSockAttachType::SockRelease),
_ => Err(InvalidAttachType(value.to_owned())),
}
}
}

@ -1,7 +1,6 @@
//! Cgroup socket address programs.
use thiserror::Error;
pub use aya_obj::programs::CgroupSockAddrAttachType;
use crate::generated::bpf_attach_type;
use std::{
hash::Hash,
os::unix::prelude::{AsRawFd, RawFd},
@ -160,75 +159,3 @@ define_link_wrapper!(
CgroupSockAddrLinkInner,
CgroupSockAddrLinkIdInner
);
/// Defines where to attach a [`CgroupSockAddr`] program.
#[derive(Copy, Clone, Debug)]
pub enum CgroupSockAddrAttachType {
/// Attach to IPv4 bind events.
Bind4,
/// Attach to IPv6 bind events.
Bind6,
/// Attach to IPv4 connect events.
Connect4,
/// Attach to IPv6 connect events.
Connect6,
/// Attach to IPv4 getpeername events.
GetPeerName4,
/// Attach to IPv6 getpeername events.
GetPeerName6,
/// Attach to IPv4 getsockname events.
GetSockName4,
/// Attach to IPv6 getsockname events.
GetSockName6,
/// Attach to IPv4 udp_sendmsg events.
UDPSendMsg4,
/// Attach to IPv6 udp_sendmsg events.
UDPSendMsg6,
/// Attach to IPv4 udp_recvmsg events.
UDPRecvMsg4,
/// Attach to IPv6 udp_recvmsg events.
UDPRecvMsg6,
}
impl From<CgroupSockAddrAttachType> for bpf_attach_type {
fn from(s: CgroupSockAddrAttachType) -> bpf_attach_type {
match s {
CgroupSockAddrAttachType::Bind4 => bpf_attach_type::BPF_CGROUP_INET4_BIND,
CgroupSockAddrAttachType::Bind6 => bpf_attach_type::BPF_CGROUP_INET6_BIND,
CgroupSockAddrAttachType::Connect4 => bpf_attach_type::BPF_CGROUP_INET4_CONNECT,
CgroupSockAddrAttachType::Connect6 => bpf_attach_type::BPF_CGROUP_INET6_CONNECT,
CgroupSockAddrAttachType::GetPeerName4 => bpf_attach_type::BPF_CGROUP_INET4_GETPEERNAME,
CgroupSockAddrAttachType::GetPeerName6 => bpf_attach_type::BPF_CGROUP_INET6_GETPEERNAME,
CgroupSockAddrAttachType::GetSockName4 => bpf_attach_type::BPF_CGROUP_INET4_GETSOCKNAME,
CgroupSockAddrAttachType::GetSockName6 => bpf_attach_type::BPF_CGROUP_INET6_GETSOCKNAME,
CgroupSockAddrAttachType::UDPSendMsg4 => bpf_attach_type::BPF_CGROUP_UDP4_SENDMSG,
CgroupSockAddrAttachType::UDPSendMsg6 => bpf_attach_type::BPF_CGROUP_UDP6_SENDMSG,
CgroupSockAddrAttachType::UDPRecvMsg4 => bpf_attach_type::BPF_CGROUP_UDP4_RECVMSG,
CgroupSockAddrAttachType::UDPRecvMsg6 => bpf_attach_type::BPF_CGROUP_UDP6_RECVMSG,
}
}
}
#[derive(Debug, Error)]
#[error("{0} is not a valid attach type for a CGROUP_SOCK_ADDR program")]
pub(crate) struct InvalidAttachType(String);
impl CgroupSockAddrAttachType {
pub(crate) fn try_from(value: &str) -> Result<CgroupSockAddrAttachType, InvalidAttachType> {
match value {
"bind4" => Ok(CgroupSockAddrAttachType::Bind4),
"bind6" => Ok(CgroupSockAddrAttachType::Bind6),
"connect4" => Ok(CgroupSockAddrAttachType::Connect4),
"connect6" => Ok(CgroupSockAddrAttachType::Connect6),
"getpeername4" => Ok(CgroupSockAddrAttachType::GetPeerName4),
"getpeername6" => Ok(CgroupSockAddrAttachType::GetPeerName6),
"getsockname4" => Ok(CgroupSockAddrAttachType::GetSockName4),
"getsockname6" => Ok(CgroupSockAddrAttachType::GetSockName6),
"sendmsg4" => Ok(CgroupSockAddrAttachType::UDPSendMsg4),
"sendmsg6" => Ok(CgroupSockAddrAttachType::UDPSendMsg6),
"recvmsg4" => Ok(CgroupSockAddrAttachType::UDPRecvMsg4),
"recvmsg6" => Ok(CgroupSockAddrAttachType::UDPRecvMsg6),
_ => Err(InvalidAttachType(value.to_owned())),
}
}
}

@ -1,5 +1,5 @@
//! Cgroup socket option programs.
use thiserror::Error;
pub use aya_obj::programs::CgroupSockoptAttachType;
use std::{
hash::Hash,
@ -9,7 +9,7 @@ use std::{
use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCKOPT,
programs::{
bpf_attach_type, define_link_wrapper, load_program, FdLink, Link, ProgAttachLink,
define_link_wrapper, load_program, FdLink, Link, ProgAttachLink,
ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach, kernel_version},
@ -155,35 +155,3 @@ define_link_wrapper!(
CgroupSockoptLinkInner,
CgroupSockoptLinkIdInner
);
/// Defines where to attach a [`CgroupSockopt`] program.
#[derive(Copy, Clone, Debug)]
pub enum CgroupSockoptAttachType {
/// Attach to GetSockopt.
Get,
/// Attach to SetSockopt.
Set,
}
impl From<CgroupSockoptAttachType> for bpf_attach_type {
fn from(s: CgroupSockoptAttachType) -> bpf_attach_type {
match s {
CgroupSockoptAttachType::Get => bpf_attach_type::BPF_CGROUP_GETSOCKOPT,
CgroupSockoptAttachType::Set => bpf_attach_type::BPF_CGROUP_SETSOCKOPT,
}
}
}
#[derive(Debug, Error)]
#[error("{0} is not a valid attach type for a CGROUP_SOCKOPT program")]
pub(crate) struct InvalidAttachType(String);
impl CgroupSockoptAttachType {
pub(crate) fn try_from(value: &str) -> Result<CgroupSockoptAttachType, InvalidAttachType> {
match value {
"getsockopt" => Ok(CgroupSockoptAttachType::Get),
"setsockopt" => Ok(CgroupSockoptAttachType::Set),
_ => Err(InvalidAttachType(value.to_owned())),
}
}
}

Loading…
Cancel
Save