Skip to content

Commit

Permalink
aya-obj: add basic documentation to public members
Browse files Browse the repository at this point in the history
Types relevant to maps are moved into aya_obj::maps.
Some members are marked `pub(crate)` again.

Refs: #473
  • Loading branch information
yesh0 committed Jan 2, 2023
1 parent ac49827 commit e52497c
Show file tree
Hide file tree
Showing 19 changed files with 458 additions and 224 deletions.
40 changes: 36 additions & 4 deletions aya-obj/src/btf/btf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ use object::Endianness;
use thiserror::Error;

use crate::{
generated::{btf_ext_header, btf_header},
btf::{
info::{FuncSecInfo, LineSecInfo},
relocation::Relocation,
Array, BtfEnum, BtfKind, BtfMember, BtfType, Const, Enum, FuncInfo, FuncLinkage, Int,
IntEncoding, LineInfo, Struct, Typedef, VarLinkage,
},
generated::{btf_ext_header, btf_header},
util::bytes_of,
Object,
};

pub(crate) const MAX_RESOLVE_DEPTH: u8 = 32;
Expand Down Expand Up @@ -157,7 +158,9 @@ pub enum BtfError {
InvalidSymbolName,
}

/// Available BTF features
#[derive(Default, Debug)]
#[allow(missing_docs)]
pub struct BtfFeatures {
pub btf_func: bool,
pub btf_func_global: bool,
Expand All @@ -172,9 +175,9 @@ pub struct BtfFeatures {
/// BTF is a kind of debug metadata that allows eBPF programs compiled against one kernel version
/// 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
/// location or if you are using [`Bpf::load`](crate::Bpf::load).
/// location or if you are using `Bpf::load`.
#[derive(Clone, Debug)]
pub struct Btf {
header: btf_header,
Expand All @@ -184,6 +187,7 @@ pub struct Btf {
}

impl Btf {
/// Creates a new empty instance with its header initialized
pub fn new() -> Btf {
Btf {
header: btf_header {
Expand All @@ -206,6 +210,7 @@ impl Btf {
self.types.types.iter()
}

/// Adds a string to BTF metadata, returning an offset
pub fn add_string(&mut self, name: String) -> u32 {
let str = CString::new(name).unwrap();
let name_offset = self.strings.len();
Expand All @@ -214,6 +219,7 @@ impl Btf {
name_offset as u32
}

/// Adds a type to BTF metadata, returning a type id
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();
Expand All @@ -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> {
if data.len() < mem::size_of::<btf_header>() {
return Err(BtfError::InvalidHeader);
Expand Down Expand Up @@ -333,6 +340,7 @@ impl Btf {
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> {
for (type_id, ty) in self.types().enumerate() {
if ty.kind() != kind {
Expand Down Expand Up @@ -379,6 +387,7 @@ impl Btf {
})
}

/// Encodes the metadata as BTF format
pub fn to_bytes(&self) -> Vec<u8> {
// Safety: btf_header is POD
let mut buf = unsafe { bytes_of::<btf_header>(&self.header).to_vec() };
Expand All @@ -388,7 +397,7 @@ impl Btf {
buf
}

pub fn fixup_and_sanitize(
pub(crate) fn fixup_and_sanitize(
&mut self,
section_sizes: &HashMap<String, u64>,
symbol_offsets: &HashMap<String, u64>,
Expand Down Expand Up @@ -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 {
// safety: btf_header is POD so read_unaligned is safe
ptr::read_unaligned(data.as_ptr() as *const btf_header)
}

/// Data in .BTF.ext section
#[derive(Debug, Clone)]
pub struct BtfExt {
data: Vec<u8>,
Expand Down
29 changes: 27 additions & 2 deletions aya-obj/src/btf/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,18 @@ use crate::{
* 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)]
pub struct FuncSecInfo {
pub _sec_name_offset: u32,
pub(crate) _sec_name_offset: u32,
/// The number of info entries
pub num_info: u32,
/// Info entries
pub func_info: Vec<bpf_func_info>,
}

Expand Down Expand Up @@ -64,6 +72,7 @@ impl FuncSecInfo {
}
}

/// Encodes the [bpf_func_info] entries
pub fn func_info_bytes(&self) -> Vec<u8> {
let mut buf = vec![];
for l in &self.func_info {
Expand All @@ -73,13 +82,20 @@ impl FuncSecInfo {
buf
}

/// Returns the number of [bpf_func_info] entries
pub fn len(&self) -> usize {
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)]
pub struct FuncInfo {
/// The [FuncSecInfo] subsections for some sections, referenced by section names
pub data: HashMap<String, FuncSecInfo>,
}

Expand All @@ -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)]
pub struct LineSecInfo {
// 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,
// followed by one or more bpf_line_info structs
/// The [bpf_line_info] entries
pub line_info: Vec<bpf_line_info>,
}

Expand Down Expand Up @@ -154,6 +177,7 @@ impl LineSecInfo {
}
}

/// Encode the entries
pub fn line_info_bytes(&self) -> Vec<u8> {
let mut buf = vec![];
for l in &self.line_info {
Expand All @@ -163,6 +187,7 @@ impl LineSecInfo {
buf
}

/// Returns the number of entries
pub fn len(&self) -> usize {
self.line_info.len()
}
Expand Down
5 changes: 3 additions & 2 deletions aya-obj/src/btf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ mod relocation;
mod types;

pub use btf::*;
pub(crate) use info::*;
pub(crate) use types::*;
pub use info::*;
pub use relocation::BtfRelocationError;
pub use types::*;
63 changes: 52 additions & 11 deletions aya-obj/src/btf/relocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{
Object, Program, ProgramSection,
};

/// The error type returned by [`Object::relocate_btf`].
#[derive(Error, Debug)]
#[error("error relocating `{section}`")]
pub struct BtfRelocationError {
Expand All @@ -24,58 +25,91 @@ pub struct BtfRelocationError {
error: RelocationError,
}

/// Relocation failures
#[derive(Error, Debug)]
enum RelocationError {
/// I/O error
#[error(transparent)]
IOError(#[from] io::Error),

/// Program not found
#[error("program not found")]
ProgramNotFound,

/// Invalid relocation access string
#[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")]
InvalidInstructionIndex {
/// The invalid instruction index
index: usize,
/// Number of instructions in the program
num_instructions: usize,
/// The relocation number
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:?}")]
ConflictingCandidates {
/// The type name
type_name: String,
/// The candidates
candidates: Vec<String>,
},

/// Maximum nesting level reached evaluating candidate type
#[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))]
InvalidAccessIndex {
/// The type name
type_name: Option<String>,
/// The access string
spec: String,
/// The index
index: usize,
/// The max index
max_index: usize,
/// The error message
error: String,
},

/// Relocation not valid for type
#[error(
"relocation #{relocation_number} of kind `{relocation_kind}` not valid for type `{type_kind}`: {error}"
)]
InvalidRelocationKindForType {
/// The relocation number
relocation_number: usize,
/// The relocation kind
relocation_kind: String,
/// The type kind
type_kind: String,
/// The error message
error: String,
},

/// Invalid instruction referenced by relocation
#[error(
"instruction #{index} referenced by relocation #{relocation_number} is invalid: {error}"
)]
InvalidInstruction {
/// The relocation number
relocation_number: usize,
/// The instruction index
index: usize,
/// The error message
error: String,
},

Expand All @@ -86,6 +120,7 @@ enum RelocationError {
ins_index: usize,
},

/// BTF error
#[error("invalid BTF")]
BtfError(#[from] BtfError),
}
Expand Down Expand Up @@ -136,7 +171,7 @@ impl TryFrom<u32> for RelocationKind {
}

#[derive(Debug, Copy, Clone)]
pub struct Relocation {
pub(crate) struct Relocation {
kind: RelocationKind,
ins_offset: usize,
type_id: u32,
Expand Down Expand Up @@ -164,6 +199,7 @@ impl Relocation {
}

impl Object {
/// Relocate programs inside this object file with loaded BTF info.
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),
Expand All @@ -172,10 +208,13 @@ 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).map_err(|e| BtfRelocationError {
section: format!("section@{sec_name_off}"),
error: RelocationError::BtfError(e),
})?;
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,
Expand All @@ -193,10 +232,12 @@ impl Object {
match relocate_btf_program(program, relos, local_btf, target_btf, &mut candidates_cache)
{
Ok(_) => {}
Err(error) => return Err(BtfRelocationError {
section: section_name.to_owned(),
error,
}),
Err(error) => {
return Err(BtfRelocationError {
section: section_name.to_owned(),
error,
})
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions aya-obj/src/btf/types.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![allow(missing_docs)]

use std::{fmt::Display, mem, ptr};

use object::Endianness;
Expand Down
Loading

0 comments on commit e52497c

Please sign in to comment.