Skip to content

Commit 7a73def

Browse files
committed
Report special module strings for BPF and vDSO symbols
Both BPF and vDSO symbols don't really have an easily identifiable module and so currently we don't report one. However, in some scenarios it would be helpful to have some indication of where these symbols come from. With this change we associate the string "[bpf]" with BPF program symbols and "[vdso]" with vDSO symbols. We could alternatively introduce an enum capturing this information in a more structured way, but really it does not seem worth it. Signed-off-by: Daniel Müller <[email protected]>
1 parent 57cc3a5 commit 7a73def

File tree

7 files changed

+33
-13
lines changed

7 files changed

+33
-13
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ Unreleased
22
----------
33
- Adjusted `symbolize::{Resolved,}Sym::code_info` to be heap allocated
44
- Made `symbolize::ResolvedSym` non-exhaustive
5+
- Report special module string when symbolizing vDSO and BPF symbols
56

67

78
0.2.0-rc.5

src/elf/parser.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,11 +1066,10 @@ impl ElfParser<Mmap> {
10661066

10671067
impl ElfParser<StaticMem> {
10681068
/// Create an `ElfParser` from a region of static memory.
1069-
pub(crate) fn from_mem(mem: StaticMem) -> Self {
1069+
pub(crate) fn from_mem(mem: StaticMem, module: OsString) -> Self {
10701070
Self {
10711071
cache: Cache::new(mem),
1072-
// TODO: Should provide the module.
1073-
module: None,
1072+
module: Some(module),
10741073
_backend: mem,
10751074
}
10761075
}

src/kernel/bpf/prog.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::cell::OnceCell;
33
use std::cell::RefCell;
44
use std::collections::hash_map::Entry;
55
use std::collections::HashMap;
6+
use std::ffi::OsStr;
67
use std::fmt::Debug;
78
use std::fmt::Display;
89
use std::fmt::Formatter;
@@ -36,6 +37,9 @@ use super::sys;
3637
use super::Btf;
3738

3839

40+
/// The special module string that we report for symbols inside a BPF
41+
/// program.
42+
pub(crate) const BPF_MODULE: &str = "[bpf]";
3943
/// BPF kernel programs show up with this prefix followed by a tag and
4044
/// some other meta-data.
4145
const BPF_PROG_PREFIX: &str = "bpf_prog_";
@@ -371,7 +375,7 @@ impl BpfProg {
371375
} = self;
372376
let sym = ResolvedSym {
373377
name,
374-
module: None,
378+
module: Some(OsStr::new(BPF_MODULE)),
375379
addr: *prog_addr,
376380
// TODO: May be able to use `bpf_prog_info::func_info` here.
377381
// Unsure.
@@ -411,7 +415,7 @@ impl<'prog> TryFrom<&'prog BpfProg> for SymInfo<'prog> {
411415
size: None,
412416
sym_type: SymType::Function,
413417
file_offset: None,
414-
module: None,
418+
module: Some(Cow::Borrowed(OsStr::new(BPF_MODULE))),
415419
_non_exhaustive: (),
416420
};
417421
Ok(sym)

src/symbolize/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,10 +367,11 @@ pub struct Sym<'src> {
367367
///
368368
/// Typically this would be the path to a executable or shared
369369
/// object. Depending on the symbol source this member may not be
370-
/// present or it could also just be a file name without path. In
371-
/// case of an ELF file contained inside an APK, this will be an
372-
/// Android style path of the form `<apk>!<elf-in-apk>`. E.g.,
373-
/// `/root/test.apk!/lib/libc.so`.
370+
/// present or it could also just be a file name without path or a
371+
/// symbolic name such as `[vdso]` representing the vDSO or `[bpf]`
372+
/// for symbols in BPF programs. In case of an ELF file contained
373+
/// inside an APK, this will be an Android style path of the form
374+
/// `<apk>!<elf-in-apk>`. E.g., `/root/test.apk!/lib/libc.so`.
374375
pub module: Option<Cow<'src, OsStr>>,
375376
/// The address at which the symbol is located (i.e., its "start").
376377
///

src/test_helper.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ use crate::inspect::SymInfo;
1717
use crate::vdso::find_vdso;
1818
#[cfg(linux)]
1919
use crate::vdso::find_vdso_maps;
20+
#[cfg(linux)]
21+
use crate::vdso::VDSO_MODULE;
2022
use crate::zip;
2123
use crate::Addr;
2224
use crate::Mmap;
@@ -87,7 +89,7 @@ pub fn find_gettimeofday_in_process(pid: Pid) -> Addr {
8789
let data = vdso_range.start as *const u8;
8890
let len = vdso_range.end.saturating_sub(vdso_range.start);
8991
let mem = unsafe { slice::from_raw_parts(data, len as _) };
90-
let parser = ElfParser::from_mem(mem);
92+
let parser = ElfParser::from_mem(mem, OsString::from(VDSO_MODULE));
9193
let opts = FindAddrOpts {
9294
sym_type: SymType::Function,
9395
file_offset: false,

src/vdso.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ use crate::Pid;
1010
use crate::Result;
1111

1212

13+
/// The special module string that we report for symbols inside the
14+
/// vDSO.
15+
pub(crate) const VDSO_MODULE: &str = "[vdso]";
1316
/// The name of the "component" representing the vDSO inside
1417
/// `/proc/<pid>/maps`.
1518
pub(crate) const VDSO_MAPS_COMPONENT: &str = "[vdso]";
@@ -42,6 +45,8 @@ pub(crate) fn find_vdso() -> Result<Option<Range<Addr>>> {
4245

4346
#[cfg(linux)]
4447
pub(crate) fn create_vdso_parser(pid: Pid, range: &Range<Addr>) -> Result<ElfParser<StaticMem>> {
48+
use std::ffi::OsString;
49+
4550
let vdso_range = if pid == Pid::Slf {
4651
range.clone()
4752
} else {
@@ -58,7 +63,7 @@ pub(crate) fn create_vdso_parser(pid: Pid, range: &Range<Addr>) -> Result<ElfPar
5863
// memory range of the vDSO, which is statically
5964
// allocated by the kernel and will never vanish.
6065
let mem = unsafe { slice::from_raw_parts(data, len as _) };
61-
let parser = ElfParser::from_mem(mem);
66+
let parser = ElfParser::from_mem(mem, OsString::from(VDSO_MODULE));
6267
Ok(parser)
6368
}
6469

tests/suite/symbolize.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,10 +1121,12 @@ fn symbolize_own_process_vdso() {
11211121
.into_iter()
11221122
.collect::<Vec<_>>();
11231123
assert_eq!(results.len(), 2);
1124-
// Given that we can't guarantee that these symbols are in a vDSO,
1125-
// it's hard for us to assert anything more than the name.
1124+
// We always assume that at least `gettimeofday` resides within
1125+
// the vDSO.
11261126
let sym1 = results[0].as_sym().unwrap();
11271127
assert!(sym1.name.ends_with("gettimeofday"), "{sym1:?}");
1128+
assert_eq!(sym1.module, Some(Cow::from(OsStr::new("[vdso]"))));
1129+
11281130
let sym2 = results[1].as_sym().unwrap();
11291131
assert!(sym2.name.contains("clock_gettime"), "{sym2:?}");
11301132
}
@@ -1149,6 +1151,7 @@ fn symbolize_remote_process_vdso() {
11491151
.into_sym()
11501152
.unwrap();
11511153
assert!(sym.name.ends_with("gettimeofday"), "{sym:?}");
1154+
assert_eq!(sym.module, Some(Cow::from(OsStr::new("[vdso]"))));
11521155
});
11531156
}
11541157

@@ -1646,6 +1649,10 @@ fn symbolize_kernel_bpf_program() {
16461649
"{}",
16471650
handle_getpid_sym.name
16481651
);
1652+
assert_eq!(
1653+
handle_getpid_sym.module,
1654+
Some(Cow::from(OsStr::new("[bpf]")))
1655+
);
16491656
let code_info = handle_getpid_sym.code_info.as_ref().unwrap();
16501657
assert_eq!(code_info.dir, None);
16511658
assert_eq!(
@@ -1661,6 +1668,7 @@ fn symbolize_kernel_bpf_program() {
16611668
"{}",
16621669
subprogram_sym.name
16631670
);
1671+
assert_eq!(subprogram_sym.module, Some(Cow::from(OsStr::new("[bpf]"))));
16641672
let code_info = subprogram_sym.code_info.as_ref().unwrap();
16651673
assert_eq!(code_info.dir, None);
16661674
assert_eq!(

0 commit comments

Comments
 (0)