Skip to content

Commit 7e93351

Browse files
committed
feat: warn when libc debug info is not found
When a stripped libc is loaded without a matching debug file (no .debug_info section and no match via build-id or .gnu_debuglink), emit a warning pointing users at libc6-dbg / glibc-debuginfo so they know why libc frames show as unknown symbols. Refs COD-2536
1 parent 9b26b2b commit 7e93351

1 file changed

Lines changed: 34 additions & 4 deletions

File tree

src/executor/wall_time/perf/debug_info.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,13 @@ impl ModuleDebugInfoExt for ModuleDebugInfo {
6060
let ctx = if object.section_by_name(".debug_info").is_some() {
6161
Self::create_dwarf_context(&object).context("Failed to create DWARF context")?
6262
} else {
63-
let debug_path = find_debug_file(&object, path.as_ref()).with_context(|| {
64-
format!(
63+
let Some(debug_path) = find_debug_file(&object, path.as_ref()) else {
64+
warn_missing_libc_debug_info(path.as_ref());
65+
anyhow::bail!(
6566
"No DWARF in {:?} and no separate debug file found",
6667
path.as_ref()
67-
)
68-
})?;
68+
);
69+
};
6970
trace!(
7071
"Using separate debug file {debug_path:?} for {:?}",
7172
path.as_ref()
@@ -129,6 +130,25 @@ impl ModuleDebugInfoExt for ModuleDebugInfo {
129130
}
130131
}
131132

133+
fn is_libc_filename(file_name: &str) -> bool {
134+
file_name.starts_with("libc.so") || file_name.starts_with("libc-")
135+
}
136+
137+
fn warn_missing_libc_debug_info(path: &Path) {
138+
let Some(file_name) = path.file_name().and_then(|n| n.to_str()) else {
139+
return;
140+
};
141+
if !is_libc_filename(file_name) {
142+
return;
143+
}
144+
145+
warn!(
146+
"Debug info for {} not found. Install libc6-dbg (Debian/Ubuntu) or \
147+
glibc-debuginfo (Fedora/RHEL) to fix missing symbols in the flamegraph",
148+
path.display()
149+
);
150+
}
151+
132152
/// Compute debug info once per unique ELF path from deduplicated symbols.
133153
/// Returns a map of path -> ModuleDebugInfo with `load_bias: 0` (load bias is per-pid).
134154
pub fn debug_info_by_path(
@@ -260,6 +280,16 @@ mod tests {
260280
);
261281
}
262282

283+
#[rstest::rstest]
284+
#[case::libc_so_6("libc.so.6", true)]
285+
#[case::libc_so("libc.so", true)]
286+
#[case::libc_versioned("libc-2.31.so", true)]
287+
#[case::libm("libm.so.6", false)]
288+
#[case::random("my_binary", false)]
289+
fn test_is_libc_filename(#[case] name: &str, #[case] expected: bool) {
290+
assert_eq!(super::is_libc_filename(name), expected);
291+
}
292+
263293
#[test]
264294
fn test_ruff_debug_info() {
265295
const MODULE_PATH: &str = "testdata/perf_map/ty_walltime";

0 commit comments

Comments
 (0)