Skip to content

Commit

Permalink
Give preference to ELF symbolization for kernel addresses
Browse files Browse the repository at this point in the history
As a side effect of commit 7ee10af ("Merge
SymResolver::find_code_info() into SymResolver::find_sym()") we changed
the behavior of the kernel resolver in that where previously it would
consult the ELF resolver for source code information, it no longer did
so. That was mostly a result of the kernel resolver giving preference to
the internally used KSymResolver, as opposed to the ElfResolver.
This change adjusts the logic to make sure that if an ElfResolver is
present, we end up using it for symbolization.

Signed-off-by: Daniel Müller <[email protected]>
  • Loading branch information
d-e-s-o committed Jan 29, 2025
1 parent 0eabad1 commit 9af1396
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Unreleased
----------
- Added support for 32 bit ELF binaries
- Adjusted kernel symbolization logic to give preference to ELF kernel
image, if present


0.2.0-rc.2
Expand Down
9 changes: 3 additions & 6 deletions src/kernel/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,10 @@ impl KernelResolver {

impl Symbolize for KernelResolver {
fn find_sym(&self, addr: Addr, opts: &FindSymOpts) -> Result<Result<ResolvedSym<'_>, Reason>> {
// TODO: If an `ElfResolver` is available we probably should give
// preference to it, if for no other reason than the fact that it
// may report source code location information.
if let Some(ksym_resolver) = self.ksym_resolver.as_ref() {
ksym_resolver.find_sym(addr, opts)
if let Some(elf_resolver) = self.elf_resolver.as_ref() {
elf_resolver.find_sym(addr, opts)
} else {
self.elf_resolver.as_ref().unwrap().find_sym(addr, opts)
self.ksym_resolver.as_ref().unwrap().find_sym(addr, opts)
}
}
}
Expand Down
61 changes: 61 additions & 0 deletions tests/suite/symbolize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,67 @@ fn symbolize_kernel() {
assert_eq!(init_task_sym.code_info, None);
}

/// Test symbolization of a "kernel" address in an ELF file.
#[test]
fn symbolize_kernel_elf() {
#[track_caller]
fn test(kernel: Kernel, has_code_info: bool) {
let src = Source::Kernel(kernel);
let symbolizer = Symbolizer::new();
let symbolized = symbolizer
.symbolize_single(&src, Input::AbsAddr(0x2000100))
.unwrap();
let sym = symbolized.into_sym().unwrap();
assert_eq!(sym.name, "factorial");
assert_eq!(sym.addr, 0x2000100);

if has_code_info {
let code_info = sym.code_info.as_ref().unwrap();
assert_ne!(code_info.dir, None);
assert_eq!(code_info.file, OsStr::new("test-stable-addrs.c"));
assert!(code_info.line.is_some());
} else {
assert_eq!(sym.code_info, None);
}
}

let mut src = Kernel {
kallsyms: Some(
Path::new(&env!("CARGO_MANIFEST_DIR"))
.join("data")
.join("kallsyms"),
),
// We use a fake kernel image here for testing purposes, which
// really is just a regular ELF file, but that's what the kernel
// image would be anyway.
kernel_image: Some(
Path::new(&env!("CARGO_MANIFEST_DIR"))
.join("data")
.join("test-stable-addrs.bin"),
),
debug_syms: true,
..Default::default()
};
// Source has debug syms and we want to use them.
test(src.clone(), true);

// Source has debug syms, but we do not want to use them.
src.debug_syms = false;
test(src.clone(), false);

// Source has no debug syms and we do not want to use them.
src.kernel_image = Some(
Path::new(&env!("CARGO_MANIFEST_DIR"))
.join("data")
.join("test-stable-addrs-no-dwarf.bin"),
);
test(src.clone(), false);

// Source has no debug syms and we do want to use them.
src.debug_syms = true;
test(src.clone(), false);
}

/// Test symbolization of a kernel address inside a BPF program.
#[cfg(linux)]
#[test]
Expand Down

0 comments on commit 9af1396

Please sign in to comment.