aya: Add USDT documentation

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
pull/329/merge^2
Dave Tucker 3 years ago
parent 4c60210a2e
commit 68ca1e1f3f

@ -521,7 +521,9 @@ pub fn sk_lookup(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// use aya_bpf::{macros::usdt, programs::UsdtContext};
///
/// #[usdt]
/// pub fn tick(_ctx: UsdtContext) -> u32 {
/// pub fn tick(ctx: UsdtContext) -> u32 {
/// let arg = ctx.arg(0);
/// // Use aya-log to print the value to userspace
/// return 0
/// }
/// ```

@ -4,13 +4,16 @@ pub const USDT_MAX_SPEC_COUNT: u32 = 256;
pub const USDT_MAX_IP_COUNT: u32 = 4 * USDT_MAX_SPEC_COUNT;
pub const USDT_MAX_ARG_COUNT: usize = 12;
/// The type of argument in a USDT program
/// The type of argument in a USDT program.
#[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "user", derive(Debug))]
pub enum UsdtArgType {
/// Value is Constant.
Const,
/// Value is stored in a Register.
Reg,
/// Value is stored in a Register and requires dereferencing.
RegDeref,
}
@ -20,31 +23,37 @@ impl Default for UsdtArgType {
}
}
/// The specifcation of an argument in a USDT program
/// The specifcation of an argument in a USDT program.
#[repr(C)]
#[derive(Copy, Clone, Default, PartialEq, Eq)]
#[cfg_attr(feature = "user", derive(Debug))]
pub struct UsdtArgSpec {
/// scalar interpreted depending on arg_type
/// Meaning of val_off differs based on `arg_type`.
/// If Constant, this holds the scalar value of unknow type, up to u64 in size.
/// If RegDeref, this contains an offset which is an i64.
pub val_off: u64,
/// arg location case
/// Type of Argument.
pub arg_type: UsdtArgType,
/// offset of referenced register within struct pt_regs
/// Offset of the register within the BPF context
pub reg_off: i16,
/// whether arg should be interpreted as signed value
/// Whether the value should be interpreted as signed
pub arg_signed: bool,
/// number of bits that need to be cleared and, optionally,
/// Number of bits that need to be cleared and, optionally,
/// sign-extended to cast arguments that are 1, 2, or 4 bytes
/// long into final 8-byte u64/s64 value returned to user
/// long into final 8-byte u64/s64 value returned to user.
pub arg_bitshift: i8,
}
/// The specification of a USDT
#[repr(C)]
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "user", derive(Debug))]
pub struct UsdtSpec {
/// Specification used to access arguments.
pub args: [UsdtArgSpec; USDT_MAX_ARG_COUNT],
/// User supplied cookie since the BPF Attach Cookie is used internally.
pub cookie: u64,
/// Number of args in this tracepoint
pub arg_count: i16,
}

@ -36,7 +36,50 @@ pub const USDT_SPEC_MAP: &str = "__bpf_usdt_specs";
/// Name of the map used for USDT to IP mappings.
pub const USDT_IP_TO_SPEC_MAP: &str = "__bpf_usdt_ip_to_spec_id";
/// A user statically-defined tracepoint
/// A user statically-defined tracepoint program.
///
/// USDT programs are the fastest of the userspace tracing programs and can be
/// used to trace events instrumented libraries or binaries. Unlike uprobes and
/// uretprobes that have access to all CPU registers, USDTs provide a structured
/// specification for accessing the arguments for each tracepoint. When compliled
/// a single tracepoint may have mutliple different entrypoints in the same program.
/// In order to simply access to arguments from eBPF, Aya keeps state in 2 maps:
///
/// - [`USDT_SPEC_MAP`] which keeps track of USDT specifications
/// - [`USDT_IP_TO_SPEC_MAP`] which keeps track of Instructio Pointers to USDT specs.
///
/// The last map is not used on kernels which support the BPF Attach Cookie feature.
///
/// # Minimum kernel version
///
/// While support was added to the kenel in 4.19, Aya depends on a feature that
/// allows the kernel to manage semaphore reference counting which was added in
/// 4.20.
///
/// The minimum supported kernel version is 4.20.
///
/// # Examples
///
/// ```no_run
/// # let mut bpf = Bpf::load_file("ebpf_programs.o")?;
/// use aya::{Bpf, programs::{Usdt, usdt::{USDT_SPEC_MAP, USDT_IP_TO_SPEC_MAP}}};
/// use aya::maps::{Array, HashMap};
/// use std::convert::TryInto;
///
/// let spec_map = Array::try_from(bpf.map_mut(USDT_SPEC_MAP).unwrap())?;
/// let ip_to_spec_map = HashMap::try_from(bpf.map_mut(USDT_IP_TO_SPEC_MAP).unwrap())?;
/// let program: &mut Usdt = bpf.program_mut("usdt").unwrap().try_into()?;
/// program.load()?;
/// program.attach(
/// spec_map,
/// ip_to_spec_map,
/// "clock",
/// "loop",
/// "/path/to/target/debug/clock",
/// Some(12345),
/// )?;
/// # Ok::<(), aya::BpfError>(())
/// ```
#[derive(Debug)]
#[doc(alias = "BPF_PROG_TYPE_KPROBE")]
pub struct Usdt {
@ -51,13 +94,19 @@ impl Usdt {
/// Attaches the program.
///
/// Attaches the uprobe to the tracepoint `tp_provider`/`tp_name` defined in the `target`.
/// Attaches the USDT to the tracepoint with a matching `tp_provider` and `tp_name`
/// in the `target`.
///
/// If `pid` is not `None`, the program executes only when the target
/// function is executed by the given `pid`.
/// function is executed by the given `pid`. This is only supported in kernels which
/// provide the BPF Attach Cookie feature.
///
/// The `target` argument can be an absolute path to a binary or library, or
/// a library name (eg: `"libc"`).
///
/// Since there a single tracepoint can have multiple entrypoints, a single `UsdtLinkId`
/// may be comprised of multiple links.
///
/// The returned value can be used to detach, see [Usdt::detach].
pub fn attach<T: AsRef<Path>>(
&mut self,
@ -158,11 +207,11 @@ impl Usdt {
/// The identifer of a MultiPerfLink.
#[derive(Debug, Hash, Eq, PartialEq)]
pub struct MultiPerfLinkId(Vec<PerfLinkIdInner>);
pub(crate) struct MultiPerfLinkId(Vec<PerfLinkIdInner>);
/// The attachment type of USDT programs.
// A wrapper around multiple PerfLinkInner
#[derive(Debug)]
pub struct MultiPerfLink {
pub(crate) struct MultiPerfLink {
perf_links: Vec<PerfLinkInner>,
}
@ -191,7 +240,7 @@ define_link_wrapper!(
MultiPerfLinkId
);
/// The type returned when attaching an [`UProbe`] fails.
/// The type returned when attaching a [`Usdt`] fails.
#[derive(Debug, Error)]
pub enum UsdtError {
/// There was an error parsing `/etc/ld.so.cache`.
@ -384,6 +433,7 @@ fn find_segment_by_address<Elf: FileHeader<Endian = Endianness>>(
})
}
// A resolved Usdt target.
#[derive(Debug)]
pub(crate) struct UsdtTarget {
abs_ip: u64,
@ -393,6 +443,7 @@ pub(crate) struct UsdtTarget {
spec: UsdtSpec,
}
// A parsed note from an ELF stapsdt note.
#[derive(Debug)]
pub(crate) struct UsdtNote {
loc_addr: u64,

@ -29,23 +29,27 @@ pub struct UsdtContext {
}
impl UsdtContext {
/// Creates a new Usdtcontext.
pub fn new(ctx: *mut c_void) -> UsdtContext {
UsdtContext {
regs: ctx as *mut pt_regs,
}
}
/// Access the register that holds the next instruction pointer.
#[inline(always)]
fn ip<T: FromPtRegs>(&self) -> Option<T> {
T::from_ip(unsafe { &*self.regs })
}
/// Access the spec_id from the BPF Attach Cookie.
#[cfg(feature = "cookie")]
#[inline(always)]
fn spec_id(&self) -> Result<u32, ()> {
unsafe { Ok(aya_bpf_bindings::helpers::bpf_get_attach_cookie(self.as_ptr()) as u32) }
}
/// Access the spec_id using the `USDT_IP_TO_SPEC_ID` map
#[cfg(not(feature = "cookie"))]
#[inline(always)]
fn spec_id(&self) -> Result<u32, ()> {
@ -54,6 +58,10 @@ impl UsdtContext {
Ok(*spec)
}
/// Returns the value of the USDT argument `n` as a u64.
///
/// This uses the USDT_SPEC_MAP to determine the correct specification to use in order
/// to read the value of argument `n` from the eBPF Context.
#[inline(always)]
pub fn arg(&self, n: usize) -> Result<u64, ()> {
if n > USDT_MAX_ARG_COUNT {

Loading…
Cancel
Save