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:
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).
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).