Skip to content

feat: warn when libc debug info is not found#302

Draft
not-matthias wants to merge 1 commit intomainfrom
feat/warn-missing-libc-debug-info
Draft

feat: warn when libc debug info is not found#302
not-matthias wants to merge 1 commit intomainfrom
feat/warn-missing-libc-debug-info

Conversation

@not-matthias
Copy link
Copy Markdown
Member

Summary

  • Adds a warning during walltime profile processing when libc is loaded but has no DWARF debug info
  • Without libc-dbg installed, libc frames in flamegraphs appear as bare hex addresses, making diff comparisons unusable
  • The check specifically targets libc (by filename pattern) to avoid false positives from other libraries that may legitimately lack debug info (e.g. JIT-related shared objects deleted at benchmark exit)

Changes

  • Added is_libc_path() helper to match libc filenames (libc.so.6, libc-2.31.so, etc.) while excluding unrelated libraries (libc-client.so)
  • Added warn_missing_libc_debug_info() that compares loaded modules against successfully-extracted debug info and warns for libc modules with missing DWARF data
  • Called from save_debug_info() right after debug info extraction completes

Test plan

  • Run a walltime benchmark on a system without libc6-dbg installed — verify the warning appears in logs
  • Run a walltime benchmark on a system with libc6-dbg installed — verify no warning appears
  • Verify Go/Java benchmarks (where libinstrument-hooks.so is deleted at exit) do not trigger the warning

When libc-dbg is not installed, libc frames in perf flamegraphs appear
as bare hex addresses, making comparisons unusable. This adds a warning
during walltime profile processing when libc is loaded but has no DWARF
debug info, suggesting users install libc6-dbg.
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 20, 2026

Merging this PR will not alter performance

✅ 4 untouched benchmarks


Comparing feat/warn-missing-libc-debug-info (4fec70b) with main (218b80c)

Open in CodSpeed

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a targeted warning during wall-time perf artifact generation when libc is loaded but DWARF-based debug info extraction fails, to help users understand why libc frames may be poorly symbolicated in flamegraphs.

Changes:

  • Introduces is_libc_path() to detect glibc-like libc filenames while avoiding common false positives (e.g., libc-client.so).
  • Introduces warn_missing_libc_debug_info() to warn when libc symbols exist but DWARF debug info wasn’t extracted.
  • Invokes the warning from save_debug_info() immediately after debug info extraction.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +149 to +151
"libc debug info not found for {}. Flamegraphs may contain \
unsymbolicated libc frames. Install debug symbols \
(e.g., `apt install libc6-dbg`) to fix this.",
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The warning suggests installing libc6-dbg via apt will fix missing DWARF, but debug_info_by_path() only attempts to read DWARF sections from the mapped ELF at path (it doesn't resolve .gnu_debuglink/build-id or /usr/lib/debug files). On Debian/Ubuntu, installing libc6-dbg typically provides a separate debug file, so this message may be misleading/unactionable (and apt is distro-specific). Consider either (a) implementing lookup of external debug files for libc (debuglink/build-id) or (b) adjusting the warning text to be OS/distro-agnostic and accurately describe what data is missing and where the tool looks for it.

Suggested change
"libc debug info not found for {}. Flamegraphs may contain \
unsymbolicated libc frames. Install debug symbols \
(e.g., `apt install libc6-dbg`) to fix this.",
"No DWARF debug info was found in the mapped libc ELF at {}. \
Flamegraphs may contain unsymbolicated libc frames. \
This tool currently reads debug info from the mapped ELF path only.",

Copilot uses AI. Check for mistakes.
|| (filename.starts_with("libc-")
&& filename.as_bytes().get(5).is_some_and(u8::is_ascii_digit))
}

Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_libc_path() introduces non-trivial filename matching logic, but there are no unit tests for the accepted/rejected patterns (e.g., libc.so.6, libc-2.31.so should match; libc-client.so should not). Adding a small #[cfg(test)] module with table-driven cases would help prevent future regressions and clarify the intended matching behavior.

Suggested change
#[cfg(test)]
mod tests {
use super::is_libc_path;
use std::path::Path;
#[test]
fn is_libc_path_accepts_expected_libc_filenames() {
let cases = [
"/lib/x86_64-linux-gnu/libc.so",
"/lib/x86_64-linux-gnu/libc.so.6",
"/usr/lib/libc-2.31.so",
"libc-2.so",
];
for case in cases {
assert!(is_libc_path(Path::new(case)), "expected match for {case}");
}
}
#[test]
fn is_libc_path_rejects_non_libc_filenames() {
let cases = [
"/usr/lib/libc-client.so",
"/usr/lib/libcrypt.so",
"/usr/lib/libc-.so",
"/usr/lib/libc-a.so",
"/usr/lib/not-libc.so.6",
"/",
"",
];
for case in cases {
assert!(!is_libc_path(Path::new(case)), "unexpected match for {case}");
}
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +133 to +134
|| (filename.starts_with("libc-")
&& filename.as_bytes().get(5).is_some_and(u8::is_ascii_digit))
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The filename.as_bytes().get(5) check relies on the hard-coded index immediately after the "libc-" prefix, which is a bit opaque. Consider rewriting using strip_prefix("libc-") + bytes().next() (or similar) to make the intent clearer and avoid manual indexing.

Suggested change
|| (filename.starts_with("libc-")
&& filename.as_bytes().get(5).is_some_and(u8::is_ascii_digit))
|| filename
.strip_prefix("libc-")
.and_then(|rest| rest.bytes().next())
.is_some_and(|b| b.is_ascii_digit())

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants