knurling-rs / probe-run

Run embedded programs just like native ones
Apache License 2.0
645 stars 75 forks source link

Change unwinder to mark registers as "unknown" when they don't appear in an unwind table row #284

Open jonas-schievink opened 2 years ago

jonas-schievink commented 2 years ago

Before unwinding is started, all registers have the value in the physical CPU registers. During unwinding, we use the rules in the matching unwind table row to restore all registers to their value in the previous frame:

https://github.com/knurling-rs/probe-run/blob/a826c796c3fdb000bd56905b996f21602799f84b/src/backtrace/unwind.rs#L76-L80

However, there's an implicit rule that we currently ignore: if a register does not appear in that list, its value is lost and can not be recovered. Currently, we just leave it at its old value, which can cause the unwinder to veer off into memory it shouldn't touch.

We should change the unwinder to track "unrecoverable" registers, and make it bail out when a register it needs (mostly LR or PC, SP is handled differently) is unrecoverable.

Note that this has the chance of affecting real-world programs that just happen to unwind correctly despite unrecoverable registers, but I think those should be rare (rustc tries to keep registers needed for unwinding intact).