aya-obj: add basic documentation to public members

Types relevant to maps are moved into aya_obj::maps.
Some members are marked `pub(crate)` again.

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

@ -15,14 +15,15 @@ use object::Endianness;
use thiserror::Error; use thiserror::Error;
use crate::{ use crate::{
generated::{btf_ext_header, btf_header},
btf::{ btf::{
info::{FuncSecInfo, LineSecInfo}, info::{FuncSecInfo, LineSecInfo},
relocation::Relocation, relocation::Relocation,
Array, BtfEnum, BtfKind, BtfMember, BtfType, Const, Enum, FuncInfo, FuncLinkage, Int, Array, BtfEnum, BtfKind, BtfMember, BtfType, Const, Enum, FuncInfo, FuncLinkage, Int,
IntEncoding, LineInfo, Struct, Typedef, VarLinkage, IntEncoding, LineInfo, Struct, Typedef, VarLinkage,
}, },
generated::{btf_ext_header, btf_header},
util::bytes_of, util::bytes_of,
Object,
}; };
pub(crate) const MAX_RESOLVE_DEPTH: u8 = 32; pub(crate) const MAX_RESOLVE_DEPTH: u8 = 32;
@ -157,7 +158,9 @@ pub enum BtfError {
InvalidSymbolName, InvalidSymbolName,
} }
/// Available BTF features
#[derive(Default, Debug)] #[derive(Default, Debug)]
#[allow(missing_docs)]
pub struct BtfFeatures { pub struct BtfFeatures {
pub btf_func: bool, pub btf_func: bool,
pub btf_func_global: bool, pub btf_func_global: bool,
@ -172,9 +175,9 @@ pub struct BtfFeatures {
/// BTF is a kind of debug metadata that allows eBPF programs compiled against one kernel version /// BTF is a kind of debug metadata that allows eBPF programs compiled against one kernel version
/// to be loaded into different kernel versions. /// to be loaded into different kernel versions.
/// ///
/// Aya automatically loads BTF metadata if you use [`Bpf::load_file`](crate::Bpf::load_file). You /// Aya automatically loads BTF metadata if you use `Bpf::load_file`. You
/// only need to explicitly use this type if you want to load BTF from a non-standard /// only need to explicitly use this type if you want to load BTF from a non-standard
/// location or if you are using [`Bpf::load`](crate::Bpf::load). /// location or if you are using `Bpf::load`.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Btf { pub struct Btf {
header: btf_header, header: btf_header,
@ -184,6 +187,7 @@ pub struct Btf {
} }
impl Btf { impl Btf {
/// Creates a new empty instance with its header initialized
pub fn new() -> Btf { pub fn new() -> Btf {
Btf { Btf {
header: btf_header { header: btf_header {
@ -206,6 +210,7 @@ impl Btf {
self.types.types.iter() self.types.types.iter()
} }
/// Adds a string to BTF metadata, returning an offset
pub fn add_string(&mut self, name: String) -> u32 { pub fn add_string(&mut self, name: String) -> u32 {
let str = CString::new(name).unwrap(); let str = CString::new(name).unwrap();
let name_offset = self.strings.len(); let name_offset = self.strings.len();
@ -214,6 +219,7 @@ impl Btf {
name_offset as u32 name_offset as u32
} }
/// Adds a type to BTF metadata, returning a type id
pub 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 size = btf_type.type_info_size() as u32;
let type_id = self.types.len(); let type_id = self.types.len();
@ -240,6 +246,7 @@ impl Btf {
) )
} }
/// Parses BTF from binary data of the given endianness
pub 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>() { if data.len() < mem::size_of::<btf_header>() {
return Err(BtfError::InvalidHeader); return Err(BtfError::InvalidHeader);
@ -333,6 +340,7 @@ impl Btf {
self.string_at(ty.name_offset()).ok().map(String::from) self.string_at(ty.name_offset()).ok().map(String::from)
} }
/// Returns a type id matching the type name and [BtfKind]
pub 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() { for (type_id, ty) in self.types().enumerate() {
if ty.kind() != kind { if ty.kind() != kind {
@ -379,6 +387,7 @@ impl Btf {
}) })
} }
/// Encodes the metadata as BTF format
pub fn to_bytes(&self) -> Vec<u8> { pub fn to_bytes(&self) -> Vec<u8> {
// Safety: btf_header is POD // Safety: btf_header is POD
let mut buf = unsafe { bytes_of::<btf_header>(&self.header).to_vec() }; let mut buf = unsafe { bytes_of::<btf_header>(&self.header).to_vec() };
@ -388,7 +397,7 @@ impl Btf {
buf buf
} }
pub fn fixup_and_sanitize( pub(crate) fn fixup_and_sanitize(
&mut self, &mut self,
section_sizes: &HashMap<String, u64>, section_sizes: &HashMap<String, u64>,
symbol_offsets: &HashMap<String, u64>, symbol_offsets: &HashMap<String, u64>,
@ -569,11 +578,34 @@ impl Default for Btf {
} }
} }
impl Object {
/// Fixes up and sanitizes BTF data.
///
/// Mostly, it removes unsupported types and works around LLVM behaviours.
pub fn fixup_and_sanitize_btf(
&mut self,
features: &BtfFeatures,
) -> Result<Option<&Btf>, BtfError> {
if let Some(ref mut obj_btf) = self.btf {
// fixup btf
obj_btf.fixup_and_sanitize(
&self.section_sizes,
&self.symbol_offset_by_name,
features,
)?;
Ok(Some(obj_btf))
} else {
Ok(None)
}
}
}
unsafe fn read_btf_header(data: &[u8]) -> btf_header { unsafe fn read_btf_header(data: &[u8]) -> btf_header {
// safety: btf_header is POD so read_unaligned is safe // safety: btf_header is POD so read_unaligned is safe
ptr::read_unaligned(data.as_ptr() as *const btf_header) ptr::read_unaligned(data.as_ptr() as *const btf_header)
} }
/// Data in .BTF.ext section
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct BtfExt { pub struct BtfExt {
data: Vec<u8>, data: Vec<u8>,

@ -19,10 +19,18 @@ use crate::{
* a list of bpf_func_info records for section #2 * a list of bpf_func_info records for section #2
* ...... * ......
*/ */
/// A collection of [bpf_func_info] collected from the `btf_ext_info_sec` struct
/// inside the [FuncInfo] subsection.
///
/// See [BPF Type Format (BTF) — The Linux Kernel documentation](https://docs.kernel.org/bpf/btf.html)
/// for more information.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct FuncSecInfo { pub struct FuncSecInfo {
pub _sec_name_offset: u32, pub(crate) _sec_name_offset: u32,
/// The number of info entries
pub num_info: u32, pub num_info: u32,
/// Info entries
pub func_info: Vec<bpf_func_info>, pub func_info: Vec<bpf_func_info>,
} }
@ -64,6 +72,7 @@ impl FuncSecInfo {
} }
} }
/// Encodes the [bpf_func_info] entries
pub fn func_info_bytes(&self) -> Vec<u8> { pub fn func_info_bytes(&self) -> Vec<u8> {
let mut buf = vec![]; let mut buf = vec![];
for l in &self.func_info { for l in &self.func_info {
@ -73,13 +82,20 @@ impl FuncSecInfo {
buf buf
} }
/// Returns the number of [bpf_func_info] entries
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.func_info.len() self.func_info.len()
} }
} }
/// A collection of [FuncSecInfo] collected from the `func_info` subsection
/// in the `.BTF.ext` section.
///
/// See [BPF Type Format (BTF) — The Linux Kernel documentation](https://docs.kernel.org/bpf/btf.html)
/// for more information.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct FuncInfo { pub struct FuncInfo {
/// The [FuncSecInfo] subsections for some sections, referenced by section names
pub data: HashMap<String, FuncSecInfo>, pub data: HashMap<String, FuncSecInfo>,
} }
@ -98,12 +114,19 @@ impl FuncInfo {
} }
} }
/// A collection of [bpf_line_info] collected from the `btf_ext_info_sec` struct
/// inside the `line_info` subsection.
///
/// See [BPF Type Format (BTF) — The Linux Kernel documentation](https://docs.kernel.org/bpf/btf.html)
/// for more information.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct LineSecInfo { pub struct LineSecInfo {
// each line info section has a header // each line info section has a header
pub _sec_name_offset: u32, pub(crate) _sec_name_offset: u32,
/// The number of entries
pub num_info: u32, pub num_info: u32,
// followed by one or more bpf_line_info structs // followed by one or more bpf_line_info structs
/// The [bpf_line_info] entries
pub line_info: Vec<bpf_line_info>, pub line_info: Vec<bpf_line_info>,
} }
@ -154,6 +177,7 @@ impl LineSecInfo {
} }
} }
/// Encode the entries
pub fn line_info_bytes(&self) -> Vec<u8> { pub fn line_info_bytes(&self) -> Vec<u8> {
let mut buf = vec![]; let mut buf = vec![];
for l in &self.line_info { for l in &self.line_info {
@ -163,6 +187,7 @@ impl LineSecInfo {
buf buf
} }
/// Returns the number of entries
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.line_info.len() self.line_info.len()
} }

@ -7,5 +7,6 @@ mod relocation;
mod types; mod types;
pub use btf::*; pub use btf::*;
pub(crate) use info::*; pub use info::*;
pub(crate) use types::*; pub use relocation::BtfRelocationError;
pub use types::*;

@ -14,6 +14,7 @@ use crate::{
Object, Program, ProgramSection, Object, Program, ProgramSection,
}; };
/// The error type returned by [`Object::relocate_btf`].
#[derive(Error, Debug)] #[derive(Error, Debug)]
#[error("error relocating `{section}`")] #[error("error relocating `{section}`")]
pub struct BtfRelocationError { pub struct BtfRelocationError {
@ -24,58 +25,91 @@ pub struct BtfRelocationError {
error: RelocationError, error: RelocationError,
} }
/// Relocation failures
#[derive(Error, Debug)] #[derive(Error, Debug)]
enum RelocationError { enum RelocationError {
/// I/O error
#[error(transparent)] #[error(transparent)]
IOError(#[from] io::Error), IOError(#[from] io::Error),
/// Program not found
#[error("program not found")] #[error("program not found")]
ProgramNotFound, ProgramNotFound,
/// Invalid relocation access string
#[error("invalid relocation access string {access_str}")] #[error("invalid relocation access string {access_str}")]
InvalidAccessString { access_str: String }, InvalidAccessString {
/// The access string
access_str: String,
},
/// Invalid instruction index referenced by relocation
#[error("invalid instruction index #{index} referenced by relocation #{relocation_number}, the program contains {num_instructions} instructions")] #[error("invalid instruction index #{index} referenced by relocation #{relocation_number}, the program contains {num_instructions} instructions")]
InvalidInstructionIndex { InvalidInstructionIndex {
/// The invalid instruction index
index: usize, index: usize,
/// Number of instructions in the program
num_instructions: usize, num_instructions: usize,
/// The relocation number
relocation_number: usize, relocation_number: usize,
}, },
/// Multiple candidate target types found with different memory layouts
#[error("error relocating {type_name}, multiple candidate target types found with different memory layouts: {candidates:?}")] #[error("error relocating {type_name}, multiple candidate target types found with different memory layouts: {candidates:?}")]
ConflictingCandidates { ConflictingCandidates {
/// The type name
type_name: String, type_name: String,
/// The candidates
candidates: Vec<String>, candidates: Vec<String>,
}, },
/// Maximum nesting level reached evaluating candidate type
#[error("maximum nesting level reached evaluating candidate type `{}`", err_type_name(.type_name))] #[error("maximum nesting level reached evaluating candidate type `{}`", err_type_name(.type_name))]
MaximumNestingLevelReached { type_name: Option<String> }, MaximumNestingLevelReached {
/// The type name
type_name: Option<String>,
},
/// Invalid access string
#[error("invalid access string `{spec}` for type `{}`: {error}", err_type_name(.type_name))] #[error("invalid access string `{spec}` for type `{}`: {error}", err_type_name(.type_name))]
InvalidAccessIndex { InvalidAccessIndex {
/// The type name
type_name: Option<String>, type_name: Option<String>,
/// The access string
spec: String, spec: String,
/// The index
index: usize, index: usize,
/// The max index
max_index: usize, max_index: usize,
/// The error message
error: String, error: String,
}, },
/// Relocation not valid for type
#[error( #[error(
"relocation #{relocation_number} of kind `{relocation_kind}` not valid for type `{type_kind}`: {error}" "relocation #{relocation_number} of kind `{relocation_kind}` not valid for type `{type_kind}`: {error}"
)] )]
InvalidRelocationKindForType { InvalidRelocationKindForType {
/// The relocation number
relocation_number: usize, relocation_number: usize,
/// The relocation kind
relocation_kind: String, relocation_kind: String,
/// The type kind
type_kind: String, type_kind: String,
/// The error message
error: String, error: String,
}, },
/// Invalid instruction referenced by relocation
#[error( #[error(
"instruction #{index} referenced by relocation #{relocation_number} is invalid: {error}" "instruction #{index} referenced by relocation #{relocation_number} is invalid: {error}"
)] )]
InvalidInstruction { InvalidInstruction {
/// The relocation number
relocation_number: usize, relocation_number: usize,
/// The instruction index
index: usize, index: usize,
/// The error message
error: String, error: String,
}, },
@ -86,6 +120,7 @@ enum RelocationError {
ins_index: usize, ins_index: usize,
}, },
/// BTF error
#[error("invalid BTF")] #[error("invalid BTF")]
BtfError(#[from] BtfError), BtfError(#[from] BtfError),
} }
@ -136,7 +171,7 @@ impl TryFrom<u32> for RelocationKind {
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Relocation { pub(crate) struct Relocation {
kind: RelocationKind, kind: RelocationKind,
ins_offset: usize, ins_offset: usize,
type_id: u32, type_id: u32,
@ -164,6 +199,7 @@ impl Relocation {
} }
impl Object { impl Object {
/// Relocate programs inside this object file with loaded BTF info.
pub fn relocate_btf(&mut self, target_btf: &Btf) -> Result<(), BtfRelocationError> { pub fn relocate_btf(&mut self, target_btf: &Btf) -> Result<(), BtfRelocationError> {
let (local_btf, btf_ext) = match (&self.btf, &self.btf_ext) { let (local_btf, btf_ext) = match (&self.btf, &self.btf_ext) {
(Some(btf), Some(btf_ext)) => (btf, btf_ext), (Some(btf), Some(btf_ext)) => (btf, btf_ext),
@ -172,10 +208,13 @@ impl Object {
let mut candidates_cache = HashMap::<u32, Vec<Candidate>>::new(); let mut candidates_cache = HashMap::<u32, Vec<Candidate>>::new();
for (sec_name_off, relos) in btf_ext.relocations() { for (sec_name_off, relos) in btf_ext.relocations() {
let section_name = local_btf.string_at(*sec_name_off).map_err(|e| BtfRelocationError { let section_name =
section: format!("section@{sec_name_off}"), local_btf
error: RelocationError::BtfError(e), .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) { let program_section = match ProgramSection::from_str(&section_name) {
Ok(program) => program, Ok(program) => program,
@ -193,10 +232,12 @@ impl Object {
match relocate_btf_program(program, relos, local_btf, target_btf, &mut candidates_cache) match relocate_btf_program(program, relos, local_btf, target_btf, &mut candidates_cache)
{ {
Ok(_) => {} Ok(_) => {}
Err(error) => return Err(BtfRelocationError { Err(error) => {
section: section_name.to_owned(), return Err(BtfRelocationError {
error, section: section_name.to_owned(),
}), error,
})
}
} }
} }

@ -1,3 +1,5 @@
#![allow(missing_docs)]
use std::{fmt::Display, mem, ptr}; use std::{fmt::Display, mem, ptr};
use object::Endianness; use object::Endianness;

@ -5,7 +5,7 @@
html_favicon_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))] #![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(clippy::all)] #![deny(clippy::all, missing_docs)]
#![allow(clippy::missing_safety_doc, clippy::len_without_is_empty)] #![allow(clippy::missing_safety_doc, clippy::len_without_is_empty)]
pub mod btf; pub mod btf;
@ -16,4 +16,5 @@ pub mod programs;
pub mod relocation; pub mod relocation;
mod util; mod util;
pub use maps::Map;
pub use obj::*; pub use obj::*;

@ -1,5 +1,7 @@
//! Map struct and type bindings. //! Map struct and type bindings.
use core::mem;
use thiserror::Error; use thiserror::Error;
/// Invalid map type encontered /// Invalid map type encontered
@ -52,6 +54,7 @@ impl TryFrom<u32> for crate::generated::bpf_map_type {
} }
} }
/// BTF definition of a map
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct BtfMapDef { pub struct BtfMapDef {
pub(crate) map_type: u32, pub(crate) map_type: u32,
@ -60,21 +63,34 @@ pub struct BtfMapDef {
pub(crate) max_entries: u32, pub(crate) max_entries: u32,
pub(crate) map_flags: u32, pub(crate) map_flags: u32,
pub(crate) pinning: PinningType, pub(crate) pinning: PinningType,
/// BTF type id of the map key
pub btf_key_type_id: u32, pub btf_key_type_id: u32,
/// BTF type id of the map value
pub btf_value_type_id: u32, pub btf_value_type_id: u32,
} }
/// The pinning type
///
/// Upon pinning a map, a file representation is created for the map,
/// so that the map can be alive and retrievable across sessions.
#[repr(u32)] #[repr(u32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PinningType { pub enum PinningType {
/// No pinning
None = 0, None = 0,
/// Pin by the name
ByName = 1, ByName = 1,
} }
/// The error type returned when failing to parse a [PinningType]
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum PinningError { pub enum PinningError {
#[error("unsupported pinning type")] /// Unsupported pinning type
Unsupported, #[error("unsupported pinning type `{pinning_type}`")]
Unsupported {
/// The unsupported pinning type
pinning_type: u32,
},
} }
impl TryFrom<u32> for PinningType { impl TryFrom<u32> for PinningType {
@ -84,7 +100,7 @@ impl TryFrom<u32> for PinningType {
match value { match value {
0 => Ok(PinningType::None), 0 => Ok(PinningType::None),
1 => Ok(PinningType::ByName), 1 => Ok(PinningType::ByName),
_ => Err(PinningError::Unsupported), pinning_type => Err(PinningError::Unsupported { pinning_type }),
} }
} }
} }
@ -95,17 +111,191 @@ impl Default for PinningType {
} }
} }
/// Map definition in legacy BPF map declaration style
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct bpf_map_def { pub struct bpf_map_def {
// minimum features required by old BPF programs // minimum features required by old BPF programs
/// The map type
pub map_type: u32, pub map_type: u32,
/// The key_size
pub key_size: u32, pub key_size: u32,
/// The value size
pub value_size: u32, pub value_size: u32,
/// Max entry number
pub max_entries: u32, pub max_entries: u32,
/// Map flags
pub map_flags: u32, pub map_flags: u32,
// optional features // optional features
/// Id
pub id: u32, pub id: u32,
/// Pinning type
pub pinning: PinningType, pub pinning: PinningType,
} }
/// The first five __u32 of `bpf_map_def` must be defined.
pub(crate) const MINIMUM_MAP_SIZE: usize = mem::size_of::<u32>() * 5;
/// Kinds of maps
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum MapKind {
/// A map holding `.bss` section data
Bss,
/// A map holding `.data` section data
Data,
/// A map holding `.rodata` section data
Rodata,
/// Other maps
Other,
}
impl From<&str> for MapKind {
fn from(s: &str) -> Self {
if s == ".bss" {
MapKind::Bss
} else if s.starts_with(".data") {
MapKind::Data
} else if s.starts_with(".rodata") {
MapKind::Rodata
} else {
MapKind::Other
}
}
}
/// Map data defined in `maps` or `.maps` sections
#[derive(Debug, Clone)]
pub enum Map {
/// A map defined in the `maps` section
Legacy(LegacyMap),
/// A map defined in the `.maps` section
Btf(BtfMap),
}
impl Map {
/// Returns the map type
pub fn map_type(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.map_type,
Map::Btf(m) => m.def.map_type,
}
}
/// Returns the key size in bytes
pub fn key_size(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.key_size,
Map::Btf(m) => m.def.key_size,
}
}
/// Returns the value size in bytes
pub fn value_size(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.value_size,
Map::Btf(m) => m.def.value_size,
}
}
/// Returns the max entry number
pub fn max_entries(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.max_entries,
Map::Btf(m) => m.def.max_entries,
}
}
/// Sets the max entry number
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,
}
}
/// Returns the map flags
pub fn map_flags(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.map_flags,
Map::Btf(m) => m.def.map_flags,
}
}
/// Returns the pinning type of the map
pub fn pinning(&self) -> PinningType {
match self {
Map::Legacy(m) => m.def.pinning,
Map::Btf(m) => m.def.pinning,
}
}
/// Returns the map data
pub fn data(&self) -> &[u8] {
match self {
Map::Legacy(m) => &m.data,
Map::Btf(m) => &m.data,
}
}
/// Returns the map data as mutable
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(),
}
}
/// Returns the map kind
pub fn kind(&self) -> MapKind {
match self {
Map::Legacy(m) => m.kind,
Map::Btf(m) => m.kind,
}
}
/// Returns the section index
pub fn section_index(&self) -> usize {
match self {
Map::Legacy(m) => m.section_index,
Map::Btf(m) => m.section_index,
}
}
/// Returns the symbol index
pub fn symbol_index(&self) -> usize {
match self {
Map::Legacy(m) => m.symbol_index,
Map::Btf(m) => m.symbol_index,
}
}
}
/// A map declared with legacy BPF map declaration style, most likely from a `maps` section.
///
/// See [Drop support for legacy BPF map declaration syntax - Libbpf: the road to v1.0](https://github.com/libbpf/libbpf/wiki/Libbpf:-the-road-to-v1.0#drop-support-for-legacy-bpf-map-declaration-syntax)
/// for more info.
#[derive(Debug, Clone)]
pub struct LegacyMap {
/// The definition of the map
pub def: bpf_map_def,
/// The section index
pub section_index: usize,
/// The symbol index
pub symbol_index: usize,
/// The map data
pub data: Vec<u8>,
/// The map kind
pub kind: MapKind,
}
/// A BTF-defined map, most likely from a `.maps` section.
#[derive(Debug, Clone)]
pub struct BtfMap {
/// The definition of the map
pub def: BtfMapDef,
pub(crate) section_index: usize,
pub(crate) symbol_index: usize,
pub(crate) kind: MapKind,
pub(crate) data: Vec<u8>,
}

@ -14,196 +14,90 @@ use std::{
}; };
use thiserror::Error; use thiserror::Error;
use crate::relocation::*; use crate::{
maps::{BtfMap, LegacyMap, Map, MapKind, MINIMUM_MAP_SIZE},
relocation::*,
};
use crate::{ use crate::{
maps::bpf_map_def,
btf::{Btf, BtfError, BtfExt, BtfType}, btf::{Btf, BtfError, BtfExt, BtfType},
generated::{bpf_insn, bpf_map_info, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_F_RDONLY_PROG}, generated::{bpf_insn, bpf_map_info, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_F_RDONLY_PROG},
maps::{bpf_map_def, BtfMapDef, PinningType},
programs::{CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType}, programs::{CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType},
maps::BtfMapDef, maps::PinningType,
}; };
use std::slice::from_raw_parts_mut; use std::slice::from_raw_parts_mut;
use crate::btf::{Array, DataSecEntry, FuncSecInfo, LineSecInfo}; use crate::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.
const MINIMUM_MAP_SIZE: usize = mem::size_of::<u32>() * 5;
/// The loaded object file representation
#[derive(Clone)] #[derive(Clone)]
pub struct Object { pub struct Object {
/// The endianness
pub endianness: Endianness, pub endianness: Endianness,
/// Program license
pub license: CString, pub license: CString,
/// Kernel version
pub kernel_version: KernelVersion, pub kernel_version: KernelVersion,
/// Program BTF
pub btf: Option<Btf>, pub btf: Option<Btf>,
/// Program BTF.ext
pub btf_ext: Option<BtfExt>, pub btf_ext: Option<BtfExt>,
/// Referenced maps
pub maps: HashMap<String, Map>, pub maps: HashMap<String, Map>,
/// Programs
pub programs: HashMap<String, Program>, pub programs: HashMap<String, Program>,
/// Functions
pub functions: HashMap<u64, Function>, pub functions: HashMap<u64, Function>,
pub relocations: HashMap<SectionIndex, HashMap<u64, Relocation>>, pub(crate) relocations: HashMap<SectionIndex, HashMap<u64, Relocation>>,
pub symbols_by_index: HashMap<usize, Symbol>, pub(crate) symbols_by_index: HashMap<usize, Symbol>,
pub section_sizes: HashMap<String, u64>, pub(crate) section_sizes: HashMap<String, u64>,
// symbol_offset_by_name caches symbols that could be referenced from a // symbol_offset_by_name caches symbols that could be referenced from a
// BTF VAR type so the offsets can be fixed up // BTF VAR type so the offsets can be fixed up
pub symbol_offset_by_name: HashMap<String, u64>, pub(crate) symbol_offset_by_name: HashMap<String, u64>,
pub text_section_index: Option<usize>, pub(crate) text_section_index: Option<usize>,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum MapKind {
Bss,
Data,
Rodata,
Other,
}
impl From<&str> for MapKind {
fn from(s: &str) -> Self {
if s == ".bss" {
MapKind::Bss
} else if s.starts_with(".data") {
MapKind::Data
} else if s.starts_with(".rodata") {
MapKind::Rodata
} else {
MapKind::Other
}
}
}
#[derive(Debug, Clone)]
pub enum Map {
Legacy(LegacyMap),
Btf(BtfMap),
}
impl Map {
pub fn map_type(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.map_type,
Map::Btf(m) => m.def.map_type,
}
}
pub fn key_size(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.key_size,
Map::Btf(m) => m.def.key_size,
}
}
pub fn value_size(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.value_size,
Map::Btf(m) => m.def.value_size,
}
}
pub fn max_entries(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.max_entries,
Map::Btf(m) => m.def.max_entries,
}
}
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 fn map_flags(&self) -> u32 {
match self {
Map::Legacy(m) => m.def.map_flags,
Map::Btf(m) => m.def.map_flags,
}
}
pub fn pinning(&self) -> PinningType {
match self {
Map::Legacy(m) => m.def.pinning,
Map::Btf(m) => m.def.pinning,
}
}
pub fn data(&self) -> &[u8] {
match self {
Map::Legacy(m) => &m.data,
Map::Btf(m) => &m.data,
}
}
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 fn kind(&self) -> MapKind {
match self {
Map::Legacy(m) => m.kind,
Map::Btf(m) => m.kind,
}
}
pub fn section_index(&self) -> usize {
match self {
Map::Legacy(m) => m.section_index,
Map::Btf(m) => m.section_index,
}
}
pub fn symbol_index(&self) -> usize {
match self {
Map::Legacy(m) => m.symbol_index,
Map::Btf(m) => m.symbol_index,
}
}
}
#[derive(Debug, Clone)]
pub struct LegacyMap {
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 def: BtfMapDef,
pub section_index: usize,
pub symbol_index: usize,
pub kind: MapKind,
pub data: Vec<u8>,
} }
/// An eBPF program
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Program { pub struct Program {
/// The license
pub license: CString, pub license: CString,
/// The kernel version
pub kernel_version: KernelVersion, pub kernel_version: KernelVersion,
/// The section containing the program
pub section: ProgramSection, pub section: ProgramSection,
/// The function
pub function: Function, pub function: Function,
} }
/// An eBPF function
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Function { pub struct Function {
/// The address
pub address: u64, pub address: u64,
/// The function name
pub name: String, pub name: String,
/// The section index
pub section_index: SectionIndex, pub section_index: SectionIndex,
/// The section offset
pub section_offset: usize, pub section_offset: usize,
/// The eBPF byte code instructions
pub instructions: Vec<bpf_insn>, pub instructions: Vec<bpf_insn>,
/// The function info
pub func_info: FuncSecInfo, pub func_info: FuncSecInfo,
/// The line info
pub line_info: LineSecInfo, pub line_info: LineSecInfo,
/// Function info record size
pub func_info_rec_size: usize, pub func_info_rec_size: usize,
/// Line info record size
pub line_info_rec_size: usize, pub line_info_rec_size: usize,
} }
/// Sections containing eBPF programs
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[allow(missing_docs)]
pub enum ProgramSection { pub enum ProgramSection {
KRetProbe { KRetProbe {
name: String, name: String,
@ -298,6 +192,7 @@ pub enum ProgramSection {
} }
impl ProgramSection { impl ProgramSection {
/// Returns the program name
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
match self { match self {
ProgramSection::KRetProbe { name } => name, ProgramSection::KRetProbe { name } => name,
@ -520,6 +415,7 @@ impl FromStr for ProgramSection {
} }
impl Object { impl Object {
/// Parses the binary data as an object file into an [Object]
pub fn parse(data: &[u8]) -> Result<Object, ParseError> { pub fn parse(data: &[u8]) -> Result<Object, ParseError> {
let obj = object::read::File::parse(data).map_err(ParseError::ElfError)?; let obj = object::read::File::parse(data).map_err(ParseError::ElfError)?;
let endianness = obj.endianness(); let endianness = obj.endianness();
@ -603,6 +499,7 @@ impl Object {
} }
} }
/// Patches map data
pub fn patch_map_data(&mut self, globals: HashMap<&str, &[u8]>) -> Result<(), ParseError> { pub fn patch_map_data(&mut self, globals: HashMap<&str, &[u8]>) -> Result<(), ParseError> {
let symbols: HashMap<String, &Symbol> = self let symbols: HashMap<String, &Symbol> = self
.symbols_by_index .symbols_by_index
@ -942,11 +839,14 @@ impl Object {
} }
} }
/// Errors caught during parsing the object file
#[derive(Debug, Error)] #[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum ParseError { pub enum ParseError {
#[error("error parsing ELF data")] #[error("error parsing ELF data")]
ElfError(#[from] object::read::Error), ElfError(#[from] object::read::Error),
/// Error parsing BTF object
#[error("BTF error")] #[error("BTF error")]
BtfError(#[from] BtfError), BtfError(#[from] BtfError),
@ -1006,6 +906,7 @@ pub enum ParseError {
#[error("no symbols found for the maps included in the maps section")] #[error("no symbols found for the maps included in the maps section")]
NoSymbolsInMapSection {}, NoSymbolsInMapSection {},
/// No BTF parsed for object
#[error("no BTF parsed for object")] #[error("no BTF parsed for object")]
NoBTF, NoBTF,
} }
@ -1169,9 +1070,12 @@ fn get_map_field(btf: &Btf, type_id: u32) -> Result<u32, BtfError> {
Ok(arr.len) Ok(arr.len)
} }
/// The parsed kernel version
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum KernelVersion { pub enum KernelVersion {
/// Specified version
Version(u32), Version(u32),
/// Any version
Any, Any,
} }
@ -1314,6 +1218,7 @@ fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDe
Ok((map_name.to_string(), map_def)) Ok((map_name.to_string(), map_def))
} }
/// Parses a [bpf_map_info] into a [Map].
pub 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 { if info.btf_key_type_id != 0 {
Map::Btf(BtfMap { Map::Btf(BtfMap {
@ -1353,6 +1258,7 @@ pub fn parse_map_info(info: bpf_map_info, pinned: PinningType) -> Map {
} }
} }
/// Copies a block of eBPF instructions
pub 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 { if data.len() % mem::size_of::<bpf_insn>() > 0 {
return Err(ParseError::InvalidProgramCode); return Err(ParseError::InvalidProgramCode);

@ -3,7 +3,7 @@ use thiserror::Error;
use crate::generated::bpf_attach_type; use crate::generated::bpf_attach_type;
/// Defines where to attach a [`CgroupSock`] program. /// Defines where to attach a `CgroupSock` program.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum CgroupSockAttachType { pub enum CgroupSockAttachType {
/// Called after the IPv4 bind events. /// Called after the IPv4 bind events.

@ -3,7 +3,7 @@ use thiserror::Error;
use crate::generated::bpf_attach_type; use crate::generated::bpf_attach_type;
/// Defines where to attach a [`CgroupSockAddr`] program. /// Defines where to attach a `CgroupSockAddr` program.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum CgroupSockAddrAttachType { pub enum CgroupSockAddrAttachType {
/// Attach to IPv4 bind events. /// Attach to IPv4 bind events.

@ -3,7 +3,7 @@ use thiserror::Error;
use crate::generated::bpf_attach_type; use crate::generated::bpf_attach_type;
/// Defines where to attach a [`CgroupSockopt`] program. /// Defines where to attach a `CgroupSockopt` program.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum CgroupSockoptAttachType { pub enum CgroupSockoptAttachType {
/// Attach to GetSockopt. /// Attach to GetSockopt.

@ -1,3 +1,5 @@
//! Program relocation handling.
use std::{collections::HashMap, mem}; use std::{collections::HashMap, mem};
use log::debug; use log::debug;
@ -9,11 +11,13 @@ use crate::{
bpf_insn, BPF_CALL, BPF_JMP, BPF_K, BPF_PSEUDO_CALL, BPF_PSEUDO_FUNC, BPF_PSEUDO_MAP_FD, bpf_insn, BPF_CALL, BPF_JMP, BPF_K, BPF_PSEUDO_CALL, BPF_PSEUDO_FUNC, BPF_PSEUDO_MAP_FD,
BPF_PSEUDO_MAP_VALUE, BPF_PSEUDO_MAP_VALUE,
}, },
obj::{Function, Object, Program}, Map, maps::Map,
obj::{Function, Object, Program},
}; };
pub(crate) const INS_SIZE: usize = mem::size_of::<bpf_insn>(); pub(crate) const INS_SIZE: usize = mem::size_of::<bpf_insn>();
/// The error type returned by [`Object::relocate_maps`] and [`Object::relocate_calls`]
#[derive(Error, Debug)] #[derive(Error, Debug)]
#[error("error relocating `{function}`")] #[error("error relocating `{function}`")]
pub struct BpfRelocationError { pub struct BpfRelocationError {
@ -24,34 +28,58 @@ pub struct BpfRelocationError {
error: RelocationError, error: RelocationError,
} }
/// Relocation failures
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum RelocationError { pub enum RelocationError {
/// Unknown symbol
#[error("unknown symbol, index `{index}`")] #[error("unknown symbol, index `{index}`")]
UnknownSymbol { index: usize }, UnknownSymbol {
/// The symbol index
index: usize,
},
/// Section not found
#[error("section `{section_index}` not found, referenced by symbol `{}` #{symbol_index}", #[error("section `{section_index}` not found, referenced by symbol `{}` #{symbol_index}",
.symbol_name.clone().unwrap_or_default())] .symbol_name.clone().unwrap_or_default())]
SectionNotFound { SectionNotFound {
/// The section index
section_index: usize, section_index: usize,
/// The symbol index
symbol_index: usize, symbol_index: usize,
/// The symbol name
symbol_name: Option<String>, symbol_name: Option<String>,
}, },
/// Unknown function
#[error("function {address:#x} not found while relocating `{caller_name}`")] #[error("function {address:#x} not found while relocating `{caller_name}`")]
UnknownFunction { address: u64, caller_name: String }, UnknownFunction {
/// The function address
address: u64,
/// The caller name
caller_name: String,
},
/// Referenced map not created yet
#[error("the map `{name}` at section `{section_index}` has not been created")] #[error("the map `{name}` at section `{section_index}` has not been created")]
MapNotCreated { section_index: usize, name: String }, MapNotCreated {
/// The section index
section_index: usize,
/// The map name
name: String,
},
/// Invalid relocation offset
#[error("invalid offset `{offset}` applying relocation #{relocation_number}")] #[error("invalid offset `{offset}` applying relocation #{relocation_number}")]
InvalidRelocationOffset { InvalidRelocationOffset {
/// The relocation offset
offset: u64, offset: u64,
/// The relocation number
relocation_number: usize, relocation_number: usize,
}, },
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Relocation { pub(crate) struct Relocation {
// byte offset of the instruction to be relocated // byte offset of the instruction to be relocated
pub(crate) offset: u64, pub(crate) offset: u64,
// index of the symbol to relocate to // index of the symbol to relocate to
@ -59,7 +87,7 @@ pub struct Relocation {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Symbol { pub(crate) struct Symbol {
pub(crate) index: usize, pub(crate) index: usize,
pub(crate) section_index: Option<usize>, pub(crate) section_index: Option<usize>,
pub(crate) name: Option<String>, pub(crate) name: Option<String>,
@ -70,6 +98,7 @@ pub struct Symbol {
} }
impl Object { impl Object {
/// Relocates the map references
pub fn relocate_maps<'a, I: Iterator<Item = (&'a str, Option<i32>, &'a Map)>>( pub fn relocate_maps<'a, I: Iterator<Item = (&'a str, Option<i32>, &'a Map)>>(
&mut self, &mut self,
maps: I, maps: I,
@ -107,6 +136,7 @@ impl Object {
Ok(()) Ok(())
} }
/// Relocates function calls
pub fn relocate_calls(&mut self) -> Result<(), BpfRelocationError> { pub fn relocate_calls(&mut self) -> Result<(), BpfRelocationError> {
for (name, program) in self.programs.iter_mut() { for (name, program) in self.programs.iter_mut() {
let linker = FunctionLinker::new( let linker = FunctionLinker::new(
@ -115,12 +145,10 @@ impl Object {
&self.relocations, &self.relocations,
&self.symbols_by_index, &self.symbols_by_index,
); );
linker linker.link(program).map_err(|error| BpfRelocationError {
.link(program) function: name.to_owned(),
.map_err(|error| BpfRelocationError{ error,
function: name.to_owned(), })?;
error,
})?;
} }
Ok(()) Ok(())
@ -444,11 +472,7 @@ fn insn_is_call(ins: &bpf_insn) -> bool {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::{ use crate::maps::{bpf_map_def, BtfMap, BtfMapDef, LegacyMap, Map, MapKind};
maps::bpf_map_def,
obj::{self, BtfMap, LegacyMap, MapKind},
maps::BtfMapDef,
};
use super::*; use super::*;
@ -469,7 +493,7 @@ mod test {
} }
fn fake_legacy_map(symbol_index: usize) -> Map { fn fake_legacy_map(symbol_index: usize) -> Map {
obj::Map::Legacy(LegacyMap { Map::Legacy(LegacyMap {
def: bpf_map_def { def: bpf_map_def {
..Default::default() ..Default::default()
}, },
@ -481,7 +505,7 @@ mod test {
} }
fn fake_btf_map(symbol_index: usize) -> Map { fn fake_btf_map(symbol_index: usize) -> Map {
obj::Map::Btf(BtfMap { Map::Btf(BtfMap {
def: BtfMapDef { def: BtfMapDef {
..Default::default() ..Default::default()
}, },
@ -578,8 +602,10 @@ mod test {
let map_1 = fake_legacy_map(1); let map_1 = fake_legacy_map(1);
let map_2 = fake_legacy_map(2); let map_2 = fake_legacy_map(2);
let maps_by_symbol = let maps_by_symbol = HashMap::from([
HashMap::from([(1, ("test_map_1", Some(1), &map_1)), (2, ("test_map_2", Some(2), &map_2))]); (1, ("test_map_1", Some(1), &map_1)),
(2, ("test_map_2", Some(2), &map_2)),
]);
relocate_maps( relocate_maps(
&mut fun, &mut fun,
@ -673,8 +699,10 @@ mod test {
let map_1 = fake_btf_map(1); let map_1 = fake_btf_map(1);
let map_2 = fake_btf_map(2); let map_2 = fake_btf_map(2);
let maps_by_symbol = let maps_by_symbol = HashMap::from([
HashMap::from([(1, ("test_map_1", Some(1), &map_1)), (2, ("test_map_2", Some(2), &map_2))]); (1, ("test_map_1", Some(1), &map_1)),
(2, ("test_map_2", Some(2), &map_2)),
]);
relocate_maps( relocate_maps(
&mut fun, &mut fun,

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

@ -7,7 +7,10 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use aya_obj::{btf::{BtfFeatures, BtfRelocationError}, relocation::BpfRelocationError}; use aya_obj::{
btf::{BtfFeatures, BtfRelocationError},
relocation::BpfRelocationError,
};
use log::debug; use log::debug;
use thiserror::Error; use thiserror::Error;
@ -19,7 +22,8 @@ use crate::{
maps::{Map, MapData, MapError}, maps::{Map, MapData, MapError},
obj::{ obj::{
btf::{Btf, BtfError}, btf::{Btf, BtfError},
MapKind, Object, ParseError, ProgramSection, maps::MapKind,
Object, ParseError, ProgramSection,
}, },
programs::{ programs::{
BtfTracePoint, CgroupDevice, CgroupSkb, CgroupSkbAttachType, CgroupSock, CgroupSockAddr, BtfTracePoint, CgroupDevice, CgroupSkb, CgroupSkbAttachType, CgroupSock, CgroupSockAddr,
@ -58,9 +62,7 @@ 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 // It only makes sense that an array of POD types is itself POD
unsafe impl<T: Pod, const N: usize> Pod for [T; N] {} unsafe impl<T: Pod, const N: usize> Pod for [T; N] {}
pub use aya_obj::maps::bpf_map_def; pub use aya_obj::maps::{bpf_map_def, PinningType};
pub use aya_obj::maps::BtfMapDef;
pub use aya_obj::maps::PinningType;
// Features implements BPF and BTF feature detection // Features implements BPF and BTF feature detection
#[derive(Default, Debug)] #[derive(Default, Debug)]
@ -358,14 +360,9 @@ impl<'a> BpfLoader<'a> {
obj.patch_map_data(self.globals.clone())?; obj.patch_map_data(self.globals.clone())?;
let btf_fd = if let Some(ref btf) = self.features.btf { let btf_fd = if let Some(ref btf) = self.features.btf {
if let Some(ref mut obj_btf) = obj.btf { if let Some(btf) = obj.fixup_and_sanitize_btf(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, btf)?;
// load btf to the kernel // load btf to the kernel
let raw_btf = obj_btf.to_bytes(); Some(load_btf(btf.to_bytes())?)
Some(load_btf(raw_btf)?)
} else { } else {
None None
} }
@ -441,7 +438,10 @@ impl<'a> BpfLoader<'a> {
maps.insert(name, map); maps.insert(name, map);
} }
obj.relocate_maps(maps.iter().map(|(s, data)| (s.as_str(), data.fd, &data.obj)))?; obj.relocate_maps(
maps.iter()
.map(|(s, data)| (s.as_str(), data.fd, &data.obj)),
)?;
obj.relocate_calls()?; obj.relocate_calls()?;
let programs = obj let programs = obj

@ -84,14 +84,17 @@ mod tests {
bpf_map_type::{BPF_MAP_TYPE_BLOOM_FILTER, BPF_MAP_TYPE_PERF_EVENT_ARRAY}, bpf_map_type::{BPF_MAP_TYPE_BLOOM_FILTER, BPF_MAP_TYPE_PERF_EVENT_ARRAY},
}, },
maps::{Map, MapData}, maps::{Map, MapData},
obj, obj::{
self,
maps::{LegacyMap, MapKind},
},
sys::{override_syscall, SysResult, Syscall}, sys::{override_syscall, SysResult, Syscall},
}; };
use libc::{EFAULT, ENOENT}; use libc::{EFAULT, ENOENT};
use std::io; use std::io;
fn new_obj_map() -> obj::Map { fn new_obj_map() -> obj::Map {
obj::Map::Legacy(obj::LegacyMap { obj::Map::Legacy(LegacyMap {
def: bpf_map_def { def: bpf_map_def {
map_type: BPF_MAP_TYPE_BLOOM_FILTER as u32, map_type: BPF_MAP_TYPE_BLOOM_FILTER as u32,
key_size: 4, key_size: 4,
@ -102,7 +105,7 @@ mod tests {
section_index: 0, section_index: 0,
symbol_index: 0, symbol_index: 0,
data: Vec::new(), data: Vec::new(),
kind: obj::MapKind::Other, kind: MapKind::Other,
}) })
} }
@ -130,7 +133,7 @@ mod tests {
#[test] #[test]
fn test_try_from_wrong_map() { fn test_try_from_wrong_map() {
let map_data = MapData { let map_data = MapData {
obj: obj::Map::Legacy(obj::LegacyMap { obj: obj::Map::Legacy(LegacyMap {
def: bpf_map_def { def: bpf_map_def {
map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32, map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32,
key_size: 4, key_size: 4,
@ -141,7 +144,7 @@ mod tests {
section_index: 0, section_index: 0,
symbol_index: 0, symbol_index: 0,
data: Vec::new(), data: Vec::new(),
kind: obj::MapKind::Other, kind: MapKind::Other,
}), }),
fd: None, fd: None,
pinned: false, pinned: false,

@ -117,14 +117,17 @@ mod tests {
bpf_map_type::{BPF_MAP_TYPE_HASH, BPF_MAP_TYPE_LRU_HASH}, bpf_map_type::{BPF_MAP_TYPE_HASH, BPF_MAP_TYPE_LRU_HASH},
}, },
maps::{Map, MapData}, maps::{Map, MapData},
obj, obj::{
self,
maps::{LegacyMap, MapKind},
},
sys::{override_syscall, SysResult, Syscall}, sys::{override_syscall, SysResult, Syscall},
}; };
use super::*; use super::*;
fn new_obj_map() -> obj::Map { fn new_obj_map() -> obj::Map {
obj::Map::Legacy(obj::LegacyMap { obj::Map::Legacy(LegacyMap {
def: bpf_map_def { def: bpf_map_def {
map_type: BPF_MAP_TYPE_HASH as u32, map_type: BPF_MAP_TYPE_HASH as u32,
key_size: 4, key_size: 4,
@ -134,7 +137,7 @@ mod tests {
}, },
section_index: 0, section_index: 0,
data: Vec::new(), data: Vec::new(),
kind: obj::MapKind::Other, kind: MapKind::Other,
symbol_index: 0, symbol_index: 0,
}) })
} }
@ -255,7 +258,7 @@ mod tests {
#[test] #[test]
fn test_try_from_ok_lru() { fn test_try_from_ok_lru() {
let map_data = MapData { let map_data = MapData {
obj: obj::Map::Legacy(obj::LegacyMap { obj: obj::Map::Legacy(LegacyMap {
def: bpf_map_def { def: bpf_map_def {
map_type: BPF_MAP_TYPE_LRU_HASH as u32, map_type: BPF_MAP_TYPE_LRU_HASH as u32,
key_size: 4, key_size: 4,
@ -266,7 +269,7 @@ mod tests {
section_index: 0, section_index: 0,
symbol_index: 0, symbol_index: 0,
data: Vec::new(), data: Vec::new(),
kind: obj::MapKind::Other, kind: MapKind::Other,
}), }),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,

@ -247,14 +247,17 @@ mod tests {
bpf_map_type::{BPF_MAP_TYPE_LPM_TRIE, BPF_MAP_TYPE_PERF_EVENT_ARRAY}, bpf_map_type::{BPF_MAP_TYPE_LPM_TRIE, BPF_MAP_TYPE_PERF_EVENT_ARRAY},
}, },
maps::{Map, MapData}, maps::{Map, MapData},
obj, obj::{
self,
maps::{LegacyMap, MapKind},
},
sys::{override_syscall, SysResult, Syscall}, sys::{override_syscall, SysResult, Syscall},
}; };
use libc::{EFAULT, ENOENT}; use libc::{EFAULT, ENOENT};
use std::{io, mem, net::Ipv4Addr}; use std::{io, mem, net::Ipv4Addr};
fn new_obj_map() -> obj::Map { fn new_obj_map() -> obj::Map {
obj::Map::Legacy(obj::LegacyMap { obj::Map::Legacy(LegacyMap {
def: bpf_map_def { def: bpf_map_def {
map_type: BPF_MAP_TYPE_LPM_TRIE as u32, map_type: BPF_MAP_TYPE_LPM_TRIE as u32,
key_size: mem::size_of::<Key<u32>>() as u32, key_size: mem::size_of::<Key<u32>>() as u32,
@ -265,7 +268,7 @@ mod tests {
section_index: 0, section_index: 0,
symbol_index: 0, symbol_index: 0,
data: Vec::new(), data: Vec::new(),
kind: obj::MapKind::Other, kind: MapKind::Other,
}) })
} }
@ -310,7 +313,7 @@ mod tests {
#[test] #[test]
fn test_try_from_wrong_map() { fn test_try_from_wrong_map() {
let map_data = MapData { let map_data = MapData {
obj: obj::Map::Legacy(obj::LegacyMap { obj: obj::Map::Legacy(LegacyMap {
def: bpf_map_def { def: bpf_map_def {
map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32, map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32,
key_size: 4, key_size: 4,
@ -321,7 +324,7 @@ mod tests {
section_index: 0, section_index: 0,
symbol_index: 0, symbol_index: 0,
data: Vec::new(), data: Vec::new(),
kind: obj::MapKind::Other, kind: MapKind::Other,
}), }),
fd: None, fd: None,
btf_fd: None, btf_fd: None,

@ -844,14 +844,14 @@ mod tests {
bpf_map_def, bpf_map_def,
generated::{bpf_cmd, bpf_map_type::BPF_MAP_TYPE_HASH}, generated::{bpf_cmd, bpf_map_type::BPF_MAP_TYPE_HASH},
maps::MapData, maps::MapData,
obj::MapKind, obj::maps::{LegacyMap, MapKind},
sys::{override_syscall, Syscall}, sys::{override_syscall, Syscall},
}; };
use super::*; use super::*;
fn new_obj_map() -> obj::Map { fn new_obj_map() -> obj::Map {
obj::Map::Legacy(obj::LegacyMap { obj::Map::Legacy(LegacyMap {
def: bpf_map_def { def: bpf_map_def {
map_type: BPF_MAP_TYPE_HASH as u32, map_type: BPF_MAP_TYPE_HASH as u32,
key_size: 4, key_size: 4,

@ -9,8 +9,7 @@ use std::{
use crate::{ use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCKOPT, generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCKOPT,
programs::{ programs::{
define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError,
ProgramData, ProgramError,
}, },
sys::{bpf_link_create, bpf_prog_attach, kernel_version}, sys::{bpf_link_create, bpf_prog_attach, kernel_version},
}; };

Loading…
Cancel
Save