Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Bug Fixes 🐛

- Temp files are now always created in the configured cache directory. ([#2028](https://github.com/getsentry/symbolicator/pull/2028))
- Filter bogus entry point frames after `__clone` and `__clone3` frames. ([#2040](https://github.com/getsentry/symbolicator/pull/2040))

## 26.8.0

Expand Down
28 changes: 21 additions & 7 deletions crates/symbolicator-native/src/symbolication/symbolicate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,21 +239,21 @@ fn symbolicate_stacktrace(
continue;
}

// Glibc inserts an explicit `DW_CFA_undefined: RIP` DWARF rule to say that `_start`
// has no return address.
// Glibc inserts an explicit `DW_CFA_undefined: RIP` DWARF rule to say that frames like
// `_start` have no return address.
// See https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86_64/start.S;h=1b3e36826b8a477474cee24d1c931429fbdf6d8f;hb=HEAD#l59
// We do not support this due to lack of breakpad support, and will thus use the
// previous rule for RIP, which says to look it up the value on the stack,
// resulting in an unmapped garbage frame. We work around this by trimming the
// trailing garbage frame on the following conditions:
// * it is unmapped (UnknownImage)
// * this is the last frame to symbolicate (via peek)
// * the previous symbolicated frame is `_start`
let is_start =
|frame: &SymbolicatedFrame| frame.raw.function.as_deref() == Some("_start");
// * the previous symbolicated frame is a well known frame like `_start`
if status == FrameStatus::UnknownImage
&& unsymbolicated_frames_iter.peek().is_none()
&& symbolicated_frames.last().is_some_and(is_start)
&& symbolicated_frames
.last()
.is_some_and(is_likely_glibc_undefined_rip_frame)
{
continue;
}
Expand Down Expand Up @@ -375,7 +375,10 @@ fn is_likely_base_frame(frame: &SymbolicatedFrame) -> bool {
};

// C start/main
if matches!(function, "main" | "start" | "_start") {
if matches!(
function,
"main" | "start" | "_start" | "__clone" | "__clone3"
) {
return true;
}

Expand All @@ -391,3 +394,14 @@ fn is_likely_base_frame(frame: &SymbolicatedFrame) -> bool {

false
}

/// Returns `true` if the passed frame is likely a well known glibc frame using a DWARF
/// `DW_CFA_undefined: RIP` rule.
///
/// Note: This has some overlap with [`is_likely_base_frame`] but is more specific.
fn is_likely_glibc_undefined_rip_frame(frame: &SymbolicatedFrame) -> bool {
matches!(
frame.raw.function.as_deref(),
Some("_start" | "__clone" | "__clone3")
)
}
Loading