mstange / framehop

Stack unwinding library in Rust
Apache License 2.0
82 stars 11 forks source link

Add prologue / epilogue detection for the top-most stack frame #4

Closed mstange closed 2 years ago

mstange commented 2 years ago

A small but noticeable number of samples in the profiles I've taken with framehop incorrectly unwind the top-most stack frame. Sometimes the return address is entirely garbage, and sometimes it just skips the immediate caller and goes to the grandparent. Most of the time this seems to happen because the pc is inside the function prologue or epilogue. The unwind information doesn't account for them.

My goal is to have two entry points, unwind_one_frame_from_pc and unwind_one_frame_from_return_address. The latter can assume that it's somewhere in the "middle" of the function. And the former can have extra smarts to deal with prologues and epilogues.

The extra smarts will vary on the type of unwinder and on the architecture. We'll need to disassemble instructions around the pc and detect common prologue / epilogue matches. This seems to be a normal thing for an unwinder to do, for example it's also part of the PE exception unwinding process. It's also mentioned in Keno's unwinding notes: "Unwinders will generally avoid this problem by looking at the next instruction and compensating if it looks like the standard prologue instructions."

mstange commented 2 years ago

I've added a small amount of prologue detection to the arm64 CompactUnwindInfoUnwinder. No epilogue detection yet.

mstange commented 2 years ago

This is now implemented for both aarch64 and x86_64, for both prologues and epilogues. It has some good test coverage.