aya-obj: add documentation on program names

This commit adds documentation on how program names are parsed from
section names, as is used by `aya_obj::Object.programs` as HashMap keys,
and updates the examples into using program names.
pull/475/head
Shenghui Ye 2 years ago
parent 9ec3447e89
commit 772af170ae

@ -27,8 +27,7 @@ object.relocate_calls().unwrap();
object.relocate_maps(std::iter::empty()).unwrap(); object.relocate_maps(std::iter::empty()).unwrap();
// Run with rbpf // Run with rbpf
let program = object.programs.iter().next().unwrap().1; let instructions = &object.programs["prog_name"].function.instructions;
let instructions = &program.function.instructions;
let data = unsafe { let data = unsafe {
core::slice::from_raw_parts( core::slice::from_raw_parts(
instructions.as_ptr() as *const u8, instructions.as_ptr() as *const u8,

@ -27,8 +27,7 @@
//! object.relocate_maps(std::iter::empty()).unwrap(); //! object.relocate_maps(std::iter::empty()).unwrap();
//! //!
//! // Run with rbpf //! // Run with rbpf
//! let program = object.programs.iter().next().unwrap().1; //! let instructions = &object.programs["prog_name"].function.instructions;
//! let instructions = &program.function.instructions;
//! let data = unsafe { //! let data = unsafe {
//! core::slice::from_raw_parts( //! core::slice::from_raw_parts(
//! instructions.as_ptr() as *const u8, //! instructions.as_ptr() as *const u8,

@ -48,7 +48,8 @@ pub struct Object {
pub btf_ext: Option<BtfExt>, pub btf_ext: Option<BtfExt>,
/// Referenced maps /// Referenced maps
pub maps: HashMap<String, Map>, pub maps: HashMap<String, Map>,
/// Programs /// A hash map of programs, using the program names parsed
/// in [ProgramSection]s as keys.
pub programs: HashMap<String, Program>, pub programs: HashMap<String, Program>,
/// Functions /// Functions
pub functions: HashMap<u64, Function>, pub functions: HashMap<u64, Function>,
@ -97,7 +98,69 @@ pub struct Function {
pub line_info_rec_size: usize, pub line_info_rec_size: usize,
} }
/// Sections containing eBPF programs /// Section types containing eBPF programs
///
/// # Section Name Parsing
///
/// Section types are parsed from the section name strings.
///
/// In order for Aya to treat a section as a [ProgramSection],
/// there are a few requirements:
/// - The section must be an executable code section.
/// - The section name must conform to [Program Types and ELF Sections].
///
/// [Program Types and ELF Sections]: https://docs.kernel.org/bpf/libbpf/program_types.html
///
/// ## Program Name
///
/// Each section name is parsed into a section type and a program name.
///
/// Generally speaking,
/// - if the section name does not contain any slashes,
/// then the program name is just that section name;
/// - if there are some slashes, the name is `section_name.rsplitn(2, '/')[0]`,
/// - except for tracepoint programs, for which the name is
/// `section_name.splitn(2, '/')[1]`.
///
/// ```rust
/// use aya_obj::ProgramSection;
/// use std::str::FromStr;
///
/// assert_eq!(
/// ProgramSection::from_str("kprobe/do_unlinkat")
/// .unwrap().name(),
/// "do_unlinkat",
/// );
/// assert_eq!(
/// ProgramSection::from_str("tracepoint/syscalls/sys_enter_openat")
/// .unwrap().name(),
/// "syscalls/sys_enter_openat",
/// );
/// ```
///
/// The program name will be used in [Object] as references to each program.
///
/// ## Unsupported Sections
///
/// Currently, the following section names are not supported yet:
/// - `flow_dissector`: `BPF_PROG_TYPE_FLOW_DISSECTOR`
/// - `ksyscall+` or `kretsyscall+`
/// - `uprobe.s+` or `uretprobe.s+`
/// - `usdt+`
/// - `kprobe.multi+` or `kretprobe.multi+`: `BPF_TRACE_KPROBE_MULTI`
/// - `lsm_cgroup+` or `lsm.s+`
/// - `lwt_in`, `lwt_out`, `lwt_seg6local`, `lwt_xmit`
/// - `raw_tp.w+`, `raw_tracepoint.w+`
/// - `action`
/// - `sk_reuseport/migrate`, `sk_reuseport`
/// - `syscall`
/// - `struct_ops+`
/// - `fmod_ret+`, `fmod_ret.s+`
/// - `fentry.s+`, `fexit.s+`
/// - `iter+`, `iter.s+`
/// - `xdp.frags/cpumap`, `xdp/cpumap`
/// - `xdp.frags/devmap`, `xdp/devmap`
/// - `xdp.frags`
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum ProgramSection { pub enum ProgramSection {

@ -2,7 +2,7 @@ use core::{mem::size_of, ptr::null_mut, slice::from_raw_parts};
use std::collections::HashMap; use std::collections::HashMap;
use aya::include_bytes_aligned; use aya::include_bytes_aligned;
use aya_obj::{generated::bpf_insn, Object}; use aya_obj::{generated::bpf_insn, Object, ProgramSection};
use super::{integration_test, IntegrationTest}; use super::{integration_test, IntegrationTest};
@ -10,7 +10,14 @@ use super::{integration_test, IntegrationTest};
fn run_with_rbpf() { fn run_with_rbpf() {
let bytes = include_bytes_aligned!("../../../../target/bpfel-unknown-none/debug/pass"); let bytes = include_bytes_aligned!("../../../../target/bpfel-unknown-none/debug/pass");
let object = Object::parse(bytes).unwrap(); let object = Object::parse(bytes).unwrap();
assert_eq!(object.programs.len(), 1); assert_eq!(object.programs.len(), 1);
assert!(matches!(
object.programs["pass"].section,
ProgramSection::Xdp { .. }
));
assert_eq!(object.programs["pass"].section.name(), "pass");
let instructions = &object.programs["pass"].function.instructions; let instructions = &object.programs["pass"].function.instructions;
let data = unsafe { let data = unsafe {
from_raw_parts( from_raw_parts(
@ -31,26 +38,34 @@ fn use_map_with_rbpf() {
let bytes = let bytes =
include_bytes_aligned!("../../../../target/bpfel-unknown-none/debug/multimap-btf.bpf.o"); include_bytes_aligned!("../../../../target/bpfel-unknown-none/debug/multimap-btf.bpf.o");
let mut object = Object::parse(bytes).unwrap(); let mut object = Object::parse(bytes).unwrap();
let mut maps = HashMap::new();
// Initializes maps: assert_eq!(object.programs.len(), 1);
// - fd: 0xCAFE00 or 0xCAFE01, assert!(matches!(
object.programs["tracepoint"].section,
ProgramSection::TracePoint { .. }
));
assert_eq!(object.programs["tracepoint"].section.name(), "tracepoint");
// Initialize maps:
// - fd: 0xCAFE00 or 0xCAFE01 (the 0xCAFE00 part is used to distinguish fds from indices),
// - Note that rbpf does not convert fds into real pointers, // - Note that rbpf does not convert fds into real pointers,
// so we keeps the pointers to our maps in MULTIMAP_MAPS, to be used in helpers. // so we keeps the pointers to our maps in MULTIMAP_MAPS, to be used in helpers.
let mut map_instances = Vec::new(); let mut maps = HashMap::new();
for (map_id, (name, map)) in object.maps.iter().enumerate() { let mut map_instances = vec![vec![0u64], vec![0u64]];
maps.insert(name.to_owned(), (map_id as i32 | 0xCAFE00, map.clone())); for (name, map) in object.maps.iter() {
assert_eq!(map.key_size(), size_of::<u32>() as u32); assert_eq!(map.key_size(), size_of::<u32>() as u32);
assert_eq!(map.value_size(), size_of::<u64>() as u32); assert_eq!(map.value_size(), size_of::<u64>() as u32);
assert_eq!( assert_eq!(
map.map_type(), map.map_type(),
aya_obj::generated::bpf_map_type::BPF_MAP_TYPE_ARRAY as u32 aya_obj::generated::bpf_map_type::BPF_MAP_TYPE_ARRAY as u32
); );
map_instances.push(vec![0u64]);
let map_id = if name == "map_1" { 0 } else { 1 };
let fd = map_id as i32 | 0xCAFE00;
maps.insert(name.to_owned(), (fd, map.clone()));
unsafe { unsafe {
MULTIMAP_MAPS[if name == "map_1" { 0 } else { 1 }] = MULTIMAP_MAPS[map_id] = &mut map_instances[map_id] as *mut _;
&mut map_instances[map_id] as *mut _;
} }
} }
@ -60,7 +75,7 @@ fn use_map_with_rbpf() {
.map(|(s, (fd, map))| (s.as_ref() as &str, Some(*fd), map)), .map(|(s, (fd, map))| (s.as_ref() as &str, Some(*fd), map)),
) )
.expect("Relocation failed"); .expect("Relocation failed");
// Actually there is no call involved. // Actually there is no local function call involved.
object.relocate_calls().unwrap(); object.relocate_calls().unwrap();
// Executes the program // Executes the program

Loading…
Cancel
Save