diff --git a/CHANGELOG.md b/CHANGELOG.md index 43ddb585..79b260cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ Unreleased ---------- - Adjusted `symbolize::{Resolved,}Sym::code_info` to be heap allocated - Made `symbolize::ResolvedSym` non-exhaustive +- Report special module string when symbolizing vDSO and BPF symbols 0.2.0-rc.5 diff --git a/src/elf/parser.rs b/src/elf/parser.rs index 77cd0639..305cb876 100644 --- a/src/elf/parser.rs +++ b/src/elf/parser.rs @@ -1066,11 +1066,10 @@ impl ElfParser { impl ElfParser { /// Create an `ElfParser` from a region of static memory. - pub(crate) fn from_mem(mem: StaticMem) -> Self { + pub(crate) fn from_mem(mem: StaticMem, module: OsString) -> Self { Self { cache: Cache::new(mem), - // TODO: Should provide the module. - module: None, + module: Some(module), _backend: mem, } } diff --git a/src/kernel/bpf/prog.rs b/src/kernel/bpf/prog.rs index dae7e534..9964de92 100644 --- a/src/kernel/bpf/prog.rs +++ b/src/kernel/bpf/prog.rs @@ -3,6 +3,7 @@ use std::cell::OnceCell; use std::cell::RefCell; use std::collections::hash_map::Entry; use std::collections::HashMap; +use std::ffi::OsStr; use std::fmt::Debug; use std::fmt::Display; use std::fmt::Formatter; @@ -36,6 +37,9 @@ use super::sys; use super::Btf; +/// The special module string that we report for symbols inside a BPF +/// program. +pub(crate) const BPF_MODULE: &str = "[bpf]"; /// BPF kernel programs show up with this prefix followed by a tag and /// some other meta-data. const BPF_PROG_PREFIX: &str = "bpf_prog_"; @@ -371,7 +375,7 @@ impl BpfProg { } = self; let sym = ResolvedSym { name, - module: None, + module: Some(OsStr::new(BPF_MODULE)), addr: *prog_addr, // TODO: May be able to use `bpf_prog_info::func_info` here. // Unsure. @@ -411,7 +415,7 @@ impl<'prog> TryFrom<&'prog BpfProg> for SymInfo<'prog> { size: None, sym_type: SymType::Function, file_offset: None, - module: None, + module: Some(Cow::Borrowed(OsStr::new(BPF_MODULE))), _non_exhaustive: (), }; Ok(sym) diff --git a/src/symbolize/mod.rs b/src/symbolize/mod.rs index d0ece4c5..fd3fdf52 100644 --- a/src/symbolize/mod.rs +++ b/src/symbolize/mod.rs @@ -367,10 +367,11 @@ pub struct Sym<'src> { /// /// Typically this would be the path to a executable or shared /// object. Depending on the symbol source this member may not be - /// present or it could also just be a file name without path. In - /// case of an ELF file contained inside an APK, this will be an - /// Android style path of the form `!`. E.g., - /// `/root/test.apk!/lib/libc.so`. + /// present or it could also just be a file name without path or a + /// symbolic name such as `[vdso]` representing the vDSO or `[bpf]` + /// for symbols in BPF programs. In case of an ELF file contained + /// inside an APK, this will be an Android style path of the form + /// `!`. E.g., `/root/test.apk!/lib/libc.so`. pub module: Option>, /// The address at which the symbol is located (i.e., its "start"). /// diff --git a/src/test_helper.rs b/src/test_helper.rs index b56edc16..b525e5b8 100644 --- a/src/test_helper.rs +++ b/src/test_helper.rs @@ -17,6 +17,8 @@ use crate::inspect::SymInfo; use crate::vdso::find_vdso; #[cfg(linux)] use crate::vdso::find_vdso_maps; +#[cfg(linux)] +use crate::vdso::VDSO_MODULE; use crate::zip; use crate::Addr; use crate::Mmap; @@ -87,7 +89,7 @@ pub fn find_gettimeofday_in_process(pid: Pid) -> Addr { let data = vdso_range.start as *const u8; let len = vdso_range.end.saturating_sub(vdso_range.start); let mem = unsafe { slice::from_raw_parts(data, len as _) }; - let parser = ElfParser::from_mem(mem); + let parser = ElfParser::from_mem(mem, OsString::from(VDSO_MODULE)); let opts = FindAddrOpts { sym_type: SymType::Function, file_offset: false, diff --git a/src/vdso.rs b/src/vdso.rs index aab55251..414103fc 100644 --- a/src/vdso.rs +++ b/src/vdso.rs @@ -10,6 +10,9 @@ use crate::Pid; use crate::Result; +/// The special module string that we report for symbols inside the +/// vDSO. +pub(crate) const VDSO_MODULE: &str = "[vdso]"; /// The name of the "component" representing the vDSO inside /// `/proc//maps`. pub(crate) const VDSO_MAPS_COMPONENT: &str = "[vdso]"; @@ -42,6 +45,8 @@ pub(crate) fn find_vdso() -> Result>> { #[cfg(linux)] pub(crate) fn create_vdso_parser(pid: Pid, range: &Range) -> Result> { + use std::ffi::OsString; + let vdso_range = if pid == Pid::Slf { range.clone() } else { @@ -58,7 +63,7 @@ pub(crate) fn create_vdso_parser(pid: Pid, range: &Range) -> Result>(); assert_eq!(results.len(), 2); - // Given that we can't guarantee that these symbols are in a vDSO, - // it's hard for us to assert anything more than the name. + // We always assume that at least `gettimeofday` resides within + // the vDSO. let sym1 = results[0].as_sym().unwrap(); assert!(sym1.name.ends_with("gettimeofday"), "{sym1:?}"); + assert_eq!(sym1.module, Some(Cow::from(OsStr::new("[vdso]")))); + let sym2 = results[1].as_sym().unwrap(); assert!(sym2.name.contains("clock_gettime"), "{sym2:?}"); } @@ -1149,6 +1151,7 @@ fn symbolize_remote_process_vdso() { .into_sym() .unwrap(); assert!(sym.name.ends_with("gettimeofday"), "{sym:?}"); + assert_eq!(sym.module, Some(Cow::from(OsStr::new("[vdso]")))); }); } @@ -1646,6 +1649,10 @@ fn symbolize_kernel_bpf_program() { "{}", handle_getpid_sym.name ); + assert_eq!( + handle_getpid_sym.module, + Some(Cow::from(OsStr::new("[bpf]"))) + ); let code_info = handle_getpid_sym.code_info.as_ref().unwrap(); assert_eq!(code_info.dir, None); assert_eq!( @@ -1661,6 +1668,7 @@ fn symbolize_kernel_bpf_program() { "{}", subprogram_sym.name ); + assert_eq!(subprogram_sym.module, Some(Cow::from(OsStr::new("[bpf]")))); let code_info = subprogram_sym.code_info.as_ref().unwrap(); assert_eq!(code_info.dir, None); assert_eq!(