diff --git a/aya/src/maps/stack_trace.rs b/aya/src/maps/stack_trace.rs index f6900565..63a92fe9 100644 --- a/aya/src/maps/stack_trace.rs +++ b/aya/src/maps/stack_trace.rs @@ -1,7 +1,12 @@ //! A hash map of kernel or user space stack traces. //! //! See [`StackTraceMap`] for documentation and examples. -use std::{borrow::Borrow, collections::BTreeMap, fs, io, mem, path::Path, str::FromStr}; +use std::{ + borrow::{Borrow, Cow}, + fs, io, mem, + path::Path, + str::FromStr, +}; use crate::{ maps::{IterableMap, MapData, MapError, MapIter, MapKeys}, @@ -157,6 +162,12 @@ impl<'a, T: Borrow> IntoIterator for &'a StackTraceMap { } } +/// A resolver for symbols based on an address obtained from a stack trace. +pub trait SymbolResolver { + /// Resolve a symbol for a given address, if possible. + fn resolve_symbol(&self, addr: u64) -> Option>; +} + /// A kernel or user space stack trace. /// /// See the [`StackTraceMap`] documentation for examples. @@ -172,12 +183,9 @@ impl StackTrace { /// You can use [`util::kernel_symbols()`](crate::util::kernel_symbols) to load kernel symbols. For /// user-space traces you need to provide the symbols, for example loading /// them from debug info. - pub fn resolve(&mut self, symbols: &BTreeMap) -> &StackTrace { + pub fn resolve(&mut self, symbols: &R) -> &StackTrace { for frame in self.frames.iter_mut() { - frame.symbol_name = symbols - .range(..=frame.ip) - .next_back() - .map(|(_, s)| s.clone()) + frame.symbol_name = symbols.resolve_symbol(frame.ip).map(|s| s.into_owned()) } self diff --git a/aya/src/util.rs b/aya/src/util.rs index 2e6e01ec..1161885e 100644 --- a/aya/src/util.rs +++ b/aya/src/util.rs @@ -1,5 +1,6 @@ //! Utility functions. use std::{ + borrow::Cow, collections::BTreeMap, error::Error, ffi::{CStr, CString}, @@ -11,6 +12,7 @@ use std::{ use crate::{ generated::{TC_H_MAJ_MASK, TC_H_MIN_MASK}, + maps::stack_trace::SymbolResolver, Pod, }; @@ -201,16 +203,25 @@ fn parse_cpu_ranges(data: &str) -> Result, ()> { Ok(cpus) } +/// The simplest resolver: a direct map from addresses to strings. +pub type SimpleSymbolResolver = BTreeMap; + +impl SymbolResolver for SimpleSymbolResolver { + fn resolve_symbol(&self, addr: u64) -> Option> { + self.range(..=addr).next_back().map(|(_, s)| s.into()) + } +} + /// Loads kernel symbols from `/proc/kallsyms`. /// /// The symbols can be passed to [`StackTrace::resolve`](crate::maps::stack_trace::StackTrace::resolve). -pub fn kernel_symbols() -> Result, io::Error> { +pub fn kernel_symbols() -> Result { let mut reader = BufReader::new(File::open("/proc/kallsyms")?); parse_kernel_symbols(&mut reader) } -fn parse_kernel_symbols(reader: impl BufRead) -> Result, io::Error> { - let mut syms = BTreeMap::new(); +fn parse_kernel_symbols(reader: impl BufRead) -> Result { + let mut syms = SimpleSymbolResolver::new(); for line in reader.lines() { let line = line?; diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index a545bd61..629021f8 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -734,7 +734,7 @@ pub struct aya::maps::stack_trace::StackTrace pub aya::maps::stack_trace::StackTrace::id: u32 impl aya::maps::stack_trace::StackTrace pub fn aya::maps::stack_trace::StackTrace::frames(&self) -> &[aya::maps::stack_trace::StackFrame] -pub fn aya::maps::stack_trace::StackTrace::resolve(&mut self, symbols: &alloc::collections::btree::map::BTreeMap) -> &aya::maps::stack_trace::StackTrace +pub fn aya::maps::stack_trace::StackTrace::resolve(&mut self, symbols: &R) -> &aya::maps::stack_trace::StackTrace impl> aya::maps::IterableMap for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::get(&self, index: &u32) -> core::result::Result pub fn aya::maps::stack_trace::StackTraceMap::map(&self) -> &aya::maps::MapData @@ -803,6 +803,10 @@ impl core::borrow::BorrowMut for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::from(t: T) -> T +pub trait aya::maps::stack_trace::SymbolResolver +pub fn aya::maps::stack_trace::SymbolResolver::resolve_symbol(&self, addr: u64) -> core::option::Option> +impl aya::maps::stack_trace::SymbolResolver for aya::util::SimpleSymbolResolver +pub fn aya::util::SimpleSymbolResolver::resolve_symbol(&self, addr: u64) -> core::option::Option> pub enum aya::maps::Map pub aya::maps::Map::Array(aya::maps::MapData) pub aya::maps::Map::BloomFilter(aya::maps::MapData) @@ -6933,10 +6937,11 @@ impl core::borrow::BorrowMut for aya::util::KernelVersion where T: core::m pub fn aya::util::KernelVersion::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::util::KernelVersion pub fn aya::util::KernelVersion::from(t: T) -> T -pub fn aya::util::kernel_symbols() -> core::result::Result, std::io::error::Error> +pub fn aya::util::kernel_symbols() -> core::result::Result pub fn aya::util::nr_cpus() -> core::result::Result pub fn aya::util::online_cpus() -> core::result::Result, std::io::error::Error> pub fn aya::util::syscall_prefix() -> core::result::Result<&'static str, std::io::error::Error> +pub type aya::util::SimpleSymbolResolver = alloc::collections::btree::map::BTreeMap pub macro aya::include_bytes_aligned! pub enum aya::BpfError pub aya::BpfError::BtfError(aya_obj::btf::btf::BtfError)