Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Skip trailing garbage frames after _start #514

Merged
merged 3 commits into from
Aug 4, 2021

Conversation

Swatinem
Copy link
Member

@Swatinem Swatinem commented Aug 3, 2021

Our lack of support for DW_CFA_undefined can lead to conditions where we read a garbage return address via CFI. We observed this specifically for the _start function as generated for some linux compiler/libc combinations.

This works around this by explicitly skipping a trailing unmapped frame following _start.

Fixes https://getsentry.atlassian.net/browse/ISSUE-1247

Our lack of support for `DW_CFA_undefined` can lead to conditions where we read a garbage return address via CFI. We observed this specifically for the `_start` function as generated for some linux compiler/libc combinations.

This works around this by explicitly skipping a trailing unmapped frame following `_start`.
@Swatinem Swatinem requested a review from a team August 3, 2021 10:48

for (index, mut frame) in thread.frames.into_iter().enumerate() {
while let Some((index, mut frame)) = frames_iter.next() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I was sure that clippy would complain about this being equivalent to for (I realize that for doesn't work here due to borrowing).

Copy link
Member Author

Choose a reason for hiding this comment

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

It did complain (as expected), but putting in the .peek() made it realize that we do need a mutable frames_iter to be around.

Copy link
Contributor

Choose a reason for hiding this comment

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

Clippy really is quite amazing.

Copy link
Contributor

@relaxolotl relaxolotl left a comment

Choose a reason for hiding this comment

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

just general nitpicky comments as i read through the diff, but i don't think any of them should block the change if it's urgently needed.

crates/symbolicator/src/services/symbolication.rs Outdated Show resolved Hide resolved
Comment on lines 1315 to 1316
// Certain linux compilers/libc combinations create a `DW_CFA_undefined: RIP` DWARF
// rule to say that `_start` has no return address. We do not support this and will
Copy link
Contributor

Choose a reason for hiding this comment

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

out of curiosity, is this undocumented behaviour? i'm wondering if it'd be useful to directly link to or reference a spec or source that mentions this.

Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -1316,6 +1312,23 @@ fn symbolicate_stacktrace(
continue;
}

// Certain linux compilers/libc combinations create a `DW_CFA_undefined: RIP` DWARF
// rule to say that `_start` has no return address. We do not support this and will
// thus use the previous rule for RIP, which might look up the register value on the
Copy link
Contributor

Choose a reason for hiding this comment

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

just to be clear, what does the "previous rule" refer to in this case?

Copy link
Member Author

Choose a reason for hiding this comment

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

CFI generated a table of rules, the previous one basically is the previous row. you can see an example here: https://github.com/getsentry/breakpad/blob/master/docs/symbol_files.md#stack-cfi-records

crates/symbolicator/src/services/symbolication.rs Outdated Show resolved Hide resolved
crates/symbolicator/src/services/symbolication.rs Outdated Show resolved Hide resolved
&& frames_iter.peek().is_none()
&& frames.last().map_or(false, is_start)
{
continue;
Copy link
Contributor

Choose a reason for hiding this comment

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

do you suppose it'd be useful to eventually track these garbage frames (and other skipped frames) with metrics or logging eventually in the future?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don’t think this makes particular sense. We had a discussion recently about measuring with intent, and not just throw a metric on every little thing. I’m not sure how such a metric can drive us in a direction to improve this or not.

@Swatinem Swatinem merged commit a4fe086 into master Aug 4, 2021
@Swatinem Swatinem deleted the fix/skip-trailing-garbage branch August 4, 2021 08:23
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.

3 participants