Skip to content

Commit afa9934

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 0c5e65e commit afa9934

File tree

6 files changed

+31
-12
lines changed

6 files changed

+31
-12
lines changed

src/elf/parser.rs

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

10471047
impl ElfParser<StaticMem> {
10481048
/// Create an `ElfParser` from a region of static memory.
1049-
pub(crate) fn from_mem(mem: StaticMem) -> Self {
1049+
pub(crate) fn from_mem(mem: StaticMem, module: OsString) -> Self {
10501050
Self {
10511051
cache: Cache::new(mem),
1052-
// TODO: Should provide the module.
1053-
module: None,
1052+
module: Some(module),
10541053
_backend: mem,
10551054
}
10561055
}

src/kernel/bpf/prog.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::borrow::Cow;
22
use std::cell::RefCell;
33
use std::collections::hash_map::Entry;
44
use std::collections::HashMap;
5+
use std::ffi::OsStr;
56
use std::fmt::Debug;
67
use std::fmt::Display;
78
use std::fmt::Formatter;
@@ -35,6 +36,9 @@ use super::sys;
3536
use super::Btf;
3637

3738

39+
/// The special module string that we report for symbols inside a BPF
40+
/// program.
41+
pub(crate) const BPF_MODULE: &str = "[bpf]";
3842
/// BPF kernel programs show up with this prefix followed by a tag and
3943
/// some other meta-data.
4044
const BPF_PROG_PREFIX: &str = "bpf_prog_";
@@ -370,7 +374,7 @@ impl BpfProg {
370374
} = self;
371375
let sym = ResolvedSym {
372376
name,
373-
module: None,
377+
module: Some(OsStr::new(BPF_MODULE)),
374378
addr: *prog_addr,
375379
// TODO: May be able to use `bpf_prog_info::func_info` here.
376380
// Unsure.
@@ -409,7 +413,7 @@ impl<'prog> TryFrom<&'prog BpfProg> for SymInfo<'prog> {
409413
size: None,
410414
sym_type: SymType::Function,
411415
file_offset: None,
412-
module: None,
416+
module: Some(Cow::Borrowed(OsStr::new(BPF_MODULE))),
413417
_non_exhaustive: (),
414418
};
415419
Ok(sym)

src/symbolize/mod.rs

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

src/test_helper.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ use crate::inspect::SymInfo;
1616
use crate::vdso::find_vdso;
1717
#[cfg(linux)]
1818
use crate::vdso::find_vdso_maps;
19+
#[cfg(linux)]
20+
use crate::vdso::VDSO_MODULE;
1921
use crate::zip;
2022
use crate::Addr;
2123
use crate::Mmap;
@@ -80,7 +82,7 @@ pub fn find_gettimeofday_in_process(pid: Pid) -> Addr {
8082
let data = vdso_range.start as *const u8;
8183
let len = vdso_range.end.saturating_sub(vdso_range.start);
8284
let mem = unsafe { slice::from_raw_parts(data, len as _) };
83-
let parser = ElfParser::from_mem(mem);
85+
let parser = ElfParser::from_mem(mem, OsString::from(VDSO_MODULE));
8486
let opts = FindAddrOpts {
8587
sym_type: SymType::Function,
8688
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
@@ -1033,10 +1033,12 @@ fn symbolize_own_process_vdso() {
10331033
.into_iter()
10341034
.collect::<Vec<_>>();
10351035
assert_eq!(results.len(), 2);
1036-
// Given that we can't guarantee that these symbols are in a vDSO,
1037-
// it's hard for us to assert anything more than the name.
1036+
// We always assume that at least `gettimeofday` resides within
1037+
// the vDSO.
10381038
let sym1 = results[0].as_sym().unwrap();
10391039
assert!(sym1.name.ends_with("gettimeofday"), "{sym1:?}");
1040+
assert_eq!(sym1.module, Some(Cow::from(OsStr::new("[vdso]"))));
1041+
10401042
let sym2 = results[1].as_sym().unwrap();
10411043
assert!(sym2.name.contains("clock_gettime"), "{sym2:?}");
10421044
}
@@ -1061,6 +1063,7 @@ fn symbolize_remote_process_vdso() {
10611063
.into_sym()
10621064
.unwrap();
10631065
assert!(sym.name.ends_with("gettimeofday"), "{sym:?}");
1066+
assert_eq!(sym.module, Some(Cow::from(OsStr::new("[vdso]"))));
10641067
});
10651068
}
10661069

@@ -1540,6 +1543,10 @@ fn symbolize_kernel_bpf_program() {
15401543
"{}",
15411544
handle_getpid_sym.name
15421545
);
1546+
assert_eq!(
1547+
handle_getpid_sym.module,
1548+
Some(Cow::from(OsStr::new("[bpf]")))
1549+
);
15431550
let code_info = handle_getpid_sym.code_info.as_ref().unwrap();
15441551
assert_eq!(code_info.dir, None);
15451552
assert_eq!(
@@ -1555,6 +1562,7 @@ fn symbolize_kernel_bpf_program() {
15551562
"{}",
15561563
subprogram_sym.name
15571564
);
1565+
assert_eq!(subprogram_sym.module, Some(Cow::from(OsStr::new("[bpf]"))));
15581566
let code_info = subprogram_sym.code_info.as_ref().unwrap();
15591567
assert_eq!(code_info.dir, None);
15601568
assert_eq!(

0 commit comments

Comments
 (0)