Browse Source

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
Shenghui Ye 2 years ago
parent
commit
e52497cb9c

+ 36 - 4
aya-obj/src/btf/btf.rs

@@ -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;
@@ -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,
@@ -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,
@@ -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 {
@@ -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();
@@ -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();
@@ -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);
@@ -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 {
@@ -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() };
@@ -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>,
@@ -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>,

+ 27 - 2
aya-obj/src/btf/info.rs

@@ -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>,
 }
 
@@ -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 {
@@ -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>,
 }
 
@@ -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>,
 }
 
@@ -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 {
@@ -163,6 +187,7 @@ impl LineSecInfo {
         buf
     }
 
+    /// Returns the number of entries
     pub fn len(&self) -> usize {
         self.line_info.len()
     }

+ 3 - 2
aya-obj/src/btf/mod.rs

@@ -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::*;

+ 52 - 11
aya-obj/src/btf/relocation.rs

@@ -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 {
@@ -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,
     },
 
@@ -86,6 +120,7 @@ enum RelocationError {
         ins_index: usize,
     },
 
+    /// BTF error
     #[error("invalid BTF")]
     BtfError(#[from] BtfError),
 }
@@ -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,
@@ -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),
@@ -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,
@@ -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,
+                    })
+                }
             }
         }
 

+ 2 - 0
aya-obj/src/btf/types.rs

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

+ 2 - 1
aya-obj/src/lib.rs

@@ -5,7 +5,7 @@
     html_favicon_url = "https://aya-rs.dev/assets/images/crabby.svg"
 )]
 #![cfg_attr(docsrs, feature(doc_cfg))]
-#![deny(clippy::all)]
+#![deny(clippy::all, missing_docs)]
 #![allow(clippy::missing_safety_doc, clippy::len_without_is_empty)]
 
 pub mod btf;
@@ -16,4 +16,5 @@ pub mod programs;
 pub mod relocation;
 mod util;
 
+pub use maps::Map;
 pub use obj::*;

+ 193 - 3
aya-obj/src/maps.rs

@@ -1,5 +1,7 @@
 //! Map struct and type bindings.
 
+use core::mem;
+
 use thiserror::Error;
 
 /// 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)]
 pub struct BtfMapDef {
     pub(crate) map_type: u32,
@@ -60,21 +63,34 @@ pub struct BtfMapDef {
     pub(crate) max_entries: u32,
     pub(crate) map_flags: u32,
     pub(crate) pinning: PinningType,
+    /// BTF type id of the map key
     pub btf_key_type_id: u32,
+    /// BTF type id of the map value
     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)]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum PinningType {
+    /// No pinning
     None = 0,
+    /// Pin by the name
     ByName = 1,
 }
 
+/// The error type returned when failing to parse a [PinningType]
 #[derive(Debug, Error)]
 pub enum PinningError {
-    #[error("unsupported pinning type")]
-    Unsupported,
+    /// Unsupported pinning type
+    #[error("unsupported pinning type `{pinning_type}`")]
+    Unsupported {
+        /// The unsupported pinning type
+        pinning_type: u32,
+    },
 }
 
 impl TryFrom<u32> for PinningType {
@@ -84,7 +100,7 @@ impl TryFrom<u32> for PinningType {
         match value {
             0 => Ok(PinningType::None),
             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)]
 #[repr(C)]
 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
 pub struct bpf_map_def {
     // minimum features required by old BPF programs
+    /// The map type
     pub map_type: u32,
+    /// The key_size
     pub key_size: u32,
+    /// The value size
     pub value_size: u32,
+    /// Max entry number
     pub max_entries: u32,
+    /// Map flags
     pub map_flags: u32,
     // optional features
+    /// Id
     pub id: u32,
+    /// Pinning type
     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>,
+}

+ 48 - 142
aya-obj/src/obj.rs

@@ -14,196 +14,90 @@ use std::{
 };
 use thiserror::Error;
 
-use crate::relocation::*;
+use crate::{
+    maps::{BtfMap, LegacyMap, Map, MapKind, MINIMUM_MAP_SIZE},
+    relocation::*,
+};
 
 use crate::{
-    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},
+    maps::{bpf_map_def, BtfMapDef, PinningType},
     programs::{CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType},
-    maps::BtfMapDef, maps::PinningType,
 };
 use std::slice::from_raw_parts_mut;
 
 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.
-const MINIMUM_MAP_SIZE: usize = mem::size_of::<u32>() * 5;
 
+/// The loaded object file representation
 #[derive(Clone)]
 pub struct Object {
+    /// The endianness
     pub endianness: Endianness,
+    /// Program license
     pub license: CString,
+    /// Kernel version
     pub kernel_version: KernelVersion,
+    /// Program BTF
     pub btf: Option<Btf>,
+    /// Program BTF.ext
     pub btf_ext: Option<BtfExt>,
+    /// Referenced maps
     pub maps: HashMap<String, Map>,
+    /// Programs
     pub programs: HashMap<String, Program>,
+    /// Functions
     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>,
+    pub(crate) relocations: HashMap<SectionIndex, HashMap<u64, Relocation>>,
+    pub(crate) symbols_by_index: HashMap<usize, Symbol>,
+    pub(crate) 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 symbol_offset_by_name: HashMap<String, u64>,
-    pub 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>,
+    pub(crate) symbol_offset_by_name: HashMap<String, u64>,
+    pub(crate) text_section_index: Option<usize>,
 }
 
+/// An eBPF program
 #[derive(Debug, Clone)]
 pub struct Program {
+    /// The license
     pub license: CString,
+    /// The kernel version
     pub kernel_version: KernelVersion,
+    /// The section containing the program
     pub section: ProgramSection,
+    /// The function
     pub function: Function,
 }
 
+/// An eBPF function
 #[derive(Debug, Clone)]
 pub struct Function {
+    /// The address
     pub address: u64,
+    /// The function name
     pub name: String,
+    /// The section index
     pub section_index: SectionIndex,
+    /// The section offset
     pub section_offset: usize,
+    /// The eBPF byte code instructions
     pub instructions: Vec<bpf_insn>,
+    /// The function info
     pub func_info: FuncSecInfo,
+    /// The line info
     pub line_info: LineSecInfo,
+    /// Function info record size
     pub func_info_rec_size: usize,
+    /// Line info record size
     pub line_info_rec_size: usize,
 }
 
+/// Sections containing eBPF programs
 #[derive(Debug, Clone)]
+#[allow(missing_docs)]
 pub enum ProgramSection {
     KRetProbe {
         name: String,
@@ -298,6 +192,7 @@ pub enum ProgramSection {
 }
 
 impl ProgramSection {
+    /// Returns the program name
     pub fn name(&self) -> &str {
         match self {
             ProgramSection::KRetProbe { name } => name,
@@ -520,6 +415,7 @@ impl FromStr for ProgramSection {
 }
 
 impl Object {
+    /// Parses the binary data as an object file into an [Object]
     pub fn parse(data: &[u8]) -> Result<Object, ParseError> {
         let obj = object::read::File::parse(data).map_err(ParseError::ElfError)?;
         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> {
         let symbols: HashMap<String, &Symbol> = self
             .symbols_by_index
@@ -942,11 +839,14 @@ impl Object {
     }
 }
 
+/// Errors caught during parsing the object file
 #[derive(Debug, Error)]
+#[allow(missing_docs)]
 pub enum ParseError {
     #[error("error parsing ELF data")]
     ElfError(#[from] object::read::Error),
 
+    /// Error parsing BTF object
     #[error("BTF error")]
     BtfError(#[from] BtfError),
 
@@ -1006,6 +906,7 @@ pub enum ParseError {
     #[error("no symbols found for the maps included in the maps section")]
     NoSymbolsInMapSection {},
 
+    /// No BTF parsed for object
     #[error("no BTF parsed for object")]
     NoBTF,
 }
@@ -1169,9 +1070,12 @@ fn get_map_field(btf: &Btf, type_id: u32) -> Result<u32, BtfError> {
     Ok(arr.len)
 }
 
+/// The parsed kernel version
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum KernelVersion {
+    /// Specified version
     Version(u32),
+    /// Any version
     Any,
 }
 
@@ -1314,6 +1218,7 @@ fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDe
     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 {
     if info.btf_key_type_id != 0 {
         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> {
     if data.len() % mem::size_of::<bpf_insn>() > 0 {
         return Err(ParseError::InvalidProgramCode);

+ 1 - 1
aya-obj/src/programs/cgroup_sock.rs

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

+ 1 - 1
aya-obj/src/programs/cgroup_sock_addr.rs

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

+ 1 - 1
aya-obj/src/programs/cgroup_sockopt.rs

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

+ 51 - 23
aya-obj/src/relocation.rs

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

+ 1 - 1
aya-obj/src/util.rs

@@ -4,4 +4,4 @@ use core::{mem, 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)
-}
+}

+ 13 - 13
aya/src/bpf.rs

@@ -7,7 +7,10 @@ use std::{
     path::{Path, PathBuf},
 };
 
-use aya_obj::{btf::{BtfFeatures, BtfRelocationError}, relocation::BpfRelocationError};
+use aya_obj::{
+    btf::{BtfFeatures, BtfRelocationError},
+    relocation::BpfRelocationError,
+};
 use log::debug;
 use thiserror::Error;
 
@@ -19,7 +22,8 @@ use crate::{
     maps::{Map, MapData, MapError},
     obj::{
         btf::{Btf, BtfError},
-        MapKind, Object, ParseError, ProgramSection,
+        maps::MapKind,
+        Object, ParseError, ProgramSection,
     },
     programs::{
         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
 unsafe impl<T: Pod, const N: usize> Pod for [T; N] {}
 
-pub use aya_obj::maps::bpf_map_def;
-pub use aya_obj::maps::BtfMapDef;
-pub use aya_obj::maps::PinningType;
+pub use aya_obj::maps::{bpf_map_def, PinningType};
 
 // Features implements BPF and BTF feature detection
 #[derive(Default, Debug)]
@@ -358,14 +360,9 @@ impl<'a> BpfLoader<'a> {
         obj.patch_map_data(self.globals.clone())?;
 
         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, btf)?;
+            if let Some(btf) = obj.fixup_and_sanitize_btf(btf)? {
                 // load btf to the kernel
-                let raw_btf = obj_btf.to_bytes();
-                Some(load_btf(raw_btf)?)
+                Some(load_btf(btf.to_bytes())?)
             } else {
                 None
             }
@@ -441,7 +438,10 @@ impl<'a> BpfLoader<'a> {
             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()?;
 
         let programs = obj

+ 8 - 5
aya/src/maps/bloom_filter.rs

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

+ 8 - 5
aya/src/maps/hash_map/hash_map.rs

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

+ 8 - 5
aya/src/maps/lpm_trie.rs

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

+ 2 - 2
aya/src/maps/mod.rs

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

+ 1 - 2
aya/src/programs/cgroup_sockopt.rs

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