Merge pull request #740 from addisoncrump/main

Revisit the stack trace API to remove resolution support
pull/743/head
Alessandro Decina 1 year ago committed by GitHub
commit 0c0cf70deb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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,16 +46,20 @@ 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() {
/// for frame in stack_trace.frames() {
/// if let Some(sym) = ksyms.range(..=frame.ip).next_back().map(|(_, s)| s) {
/// println!(
/// "{:#x} {}",
/// frame.ip,
/// frame
/// .symbol_name
/// .as_deref()
/// .unwrap_or("[unknown symbol name]")
/// 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> {

@ -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?;

@ -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)

Loading…
Cancel
Save