Browse Source

Merge pull request #740 from addisoncrump/main

Revisit the stack trace API to remove resolution support
Alessandro Decina 1 year ago
parent
commit
0c0cf70deb
3 changed files with 20 additions and 66 deletions
  1. 15 43
      aya/src/maps/stack_trace.rs
  2. 4 15
      aya/src/util.rs
  3. 1 8
      xtask/public-api/aya.txt

+ 15 - 43
aya/src/maps/stack_trace.rs

@@ -1,12 +1,7 @@
 //! A hash map of kernel or user space stack traces.
 //!
 //! See [`StackTraceMap`] for documentation and examples.
-use std::{
-    borrow::{Borrow, Cow},
-    fs, io, mem,
-    path::Path,
-    str::FromStr,
-};
+use std::{borrow::Borrow, fs, io, mem, path::Path, str::FromStr};
 
 use crate::{
     maps::{IterableMap, MapData, MapError, MapIter, MapKeys},
@@ -51,15 +46,19 @@ use crate::{
 /// // here we resolve symbol names using kernel symbols. If this was a user space stack (for
 /// // example captured from a uprobe), you'd have to load the symbols using some other mechanism
 /// // (eg loading the target binary debuginfo)
-/// for frame in stack_trace.resolve(&ksyms).frames() {
-///     println!(
-///         "{:#x} {}",
-///         frame.ip,
-///         frame
-///             .symbol_name
-///             .as_deref()
-///             .unwrap_or("[unknown symbol name]")
-///     );
+/// for frame in stack_trace.frames() {
+///     if let Some(sym) = ksyms.range(..=frame.ip).next_back().map(|(_, s)| s) {
+///         println!(
+///             "{:#x} {}",
+///             frame.ip,
+///             sym
+///         );
+///     } else {
+///         println!(
+///             "{:#x}",
+///             frame.ip
+///         );
+///     }
 /// }
 ///
 /// # Ok::<(), Error>(())
@@ -118,10 +117,7 @@ impl<T: Borrow<MapData>> StackTraceMap<T> {
         let frames = frames
             .into_iter()
             .take_while(|ip| *ip != 0)
-            .map(|ip| StackFrame {
-                ip,
-                symbol_name: None,
-            })
+            .map(|ip| StackFrame { ip })
             .collect::<Vec<_>>();
 
         Ok(StackTrace {
@@ -162,12 +158,6 @@ impl<'a, T: Borrow<MapData>> IntoIterator for &'a StackTraceMap<T> {
     }
 }
 
-/// 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<Cow<'_, str>>;
-}
-
 /// A kernel or user space stack trace.
 ///
 /// See the [`StackTraceMap`] documentation for examples.
@@ -178,19 +168,6 @@ pub struct StackTrace {
 }
 
 impl StackTrace {
-    /// Resolves symbol names using the given symbol map.
-    ///
-    /// 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<R: SymbolResolver>(&mut self, symbols: &R) -> &StackTrace {
-        for frame in self.frames.iter_mut() {
-            frame.symbol_name = symbols.resolve_symbol(frame.ip).map(|s| s.into_owned())
-        }
-
-        self
-    }
-
     /// Returns the frames in this stack trace.
     pub fn frames(&self) -> &[StackFrame] {
         &self.frames
@@ -201,11 +178,6 @@ impl StackTrace {
 pub struct StackFrame {
     /// The instruction pointer of this frame.
     pub ip: u64,
-    /// The symbol name corresponding to the start of this frame.
-    ///
-    /// Set to `Some()` if the frame address can be found in the symbols passed
-    /// to [`StackTrace::resolve`].
-    pub symbol_name: Option<String>,
 }
 
 fn sysctl<T: FromStr>(key: &str) -> Result<T, io::Error> {

+ 4 - 15
aya/src/util.rs

@@ -1,6 +1,5 @@
 //! Utility functions.
 use std::{
-    borrow::Cow,
     collections::BTreeMap,
     error::Error,
     ffi::{CStr, CString},
@@ -12,7 +11,6 @@ use std::{
 
 use crate::{
     generated::{TC_H_MAJ_MASK, TC_H_MIN_MASK},
-    maps::stack_trace::SymbolResolver,
     Pod,
 };
 
@@ -203,25 +201,16 @@ fn parse_cpu_ranges(data: &str) -> Result<Vec<u32>, ()> {
     Ok(cpus)
 }
 
-/// The simplest resolver: a direct map from addresses to strings.
-pub type SimpleSymbolResolver = BTreeMap<u64, String>;
-
-impl SymbolResolver for SimpleSymbolResolver {
-    fn resolve_symbol(&self, addr: u64) -> Option<Cow<'_, str>> {
-        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<SimpleSymbolResolver, io::Error> {
+/// See [`crate::maps::StackTraceMap`] for an example on how to use this to resolve kernel addresses to symbols.
+pub fn kernel_symbols() -> Result<BTreeMap<u64, String>, io::Error> {
     let mut reader = BufReader::new(File::open("/proc/kallsyms")?);
     parse_kernel_symbols(&mut reader)
 }
 
-fn parse_kernel_symbols(reader: impl BufRead) -> Result<SimpleSymbolResolver, io::Error> {
-    let mut syms = SimpleSymbolResolver::new();
+fn parse_kernel_symbols(reader: impl BufRead) -> Result<BTreeMap<u64, String>, io::Error> {
+    let mut syms = BTreeMap::new();
 
     for line in reader.lines() {
         let line = line?;

+ 1 - 8
xtask/public-api/aya.txt

@@ -708,7 +708,6 @@ pub fn aya::maps::stack::Stack<T, V>::from(t: T) -> T
 pub mod aya::maps::stack_trace
 pub struct aya::maps::stack_trace::StackFrame
 pub aya::maps::stack_trace::StackFrame::ip: u64
-pub aya::maps::stack_trace::StackFrame::symbol_name: core::option::Option<alloc::string::String>
 impl core::marker::Send for aya::maps::stack_trace::StackFrame
 impl core::marker::Sync for aya::maps::stack_trace::StackFrame
 impl core::marker::Unpin for aya::maps::stack_trace::StackFrame
@@ -734,7 +733,6 @@ 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<R: aya::maps::stack_trace::SymbolResolver>(&mut self, symbols: &R) -> &aya::maps::stack_trace::StackTrace
 impl<T: core::borrow::Borrow<aya::maps::MapData>> aya::maps::IterableMap<u32, aya::maps::stack_trace::StackTrace> for aya::maps::stack_trace::StackTraceMap<T>
 pub fn aya::maps::stack_trace::StackTraceMap<T>::get(&self, index: &u32) -> core::result::Result<aya::maps::stack_trace::StackTrace, aya::maps::MapError>
 pub fn aya::maps::stack_trace::StackTraceMap<T>::map(&self) -> &aya::maps::MapData
@@ -803,10 +801,6 @@ impl<T> core::borrow::BorrowMut<T> for aya::maps::stack_trace::StackTraceMap<T>
 pub fn aya::maps::stack_trace::StackTraceMap<T>::borrow_mut(&mut self) -> &mut T
 impl<T> core::convert::From<T> for aya::maps::stack_trace::StackTraceMap<T>
 pub fn aya::maps::stack_trace::StackTraceMap<T>::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<alloc::borrow::Cow<'_, str>>
-impl aya::maps::stack_trace::SymbolResolver for aya::util::SimpleSymbolResolver
-pub fn aya::util::SimpleSymbolResolver::resolve_symbol(&self, addr: u64) -> core::option::Option<alloc::borrow::Cow<'_, str>>
 pub enum aya::maps::Map
 pub aya::maps::Map::Array(aya::maps::MapData)
 pub aya::maps::Map::BloomFilter(aya::maps::MapData)
@@ -6935,11 +6929,10 @@ impl<T> core::borrow::BorrowMut<T> for aya::util::KernelVersion where T: core::m
 pub fn aya::util::KernelVersion::borrow_mut(&mut self) -> &mut T
 impl<T> core::convert::From<T> for aya::util::KernelVersion
 pub fn aya::util::KernelVersion::from(t: T) -> T
-pub fn aya::util::kernel_symbols() -> core::result::Result<aya::util::SimpleSymbolResolver, std::io::error::Error>
+pub fn aya::util::kernel_symbols() -> core::result::Result<alloc::collections::btree::map::BTreeMap<u64, alloc::string::String>, std::io::error::Error>
 pub fn aya::util::nr_cpus() -> core::result::Result<usize, std::io::error::Error>
 pub fn aya::util::online_cpus() -> core::result::Result<alloc::vec::Vec<u32>, 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<u64, alloc::string::String>
 pub macro aya::include_bytes_aligned!
 pub enum aya::BpfError
 pub aya::BpfError::BtfError(aya_obj::btf::btf::BtfError)