| ... | @@ -493,6 +493,7 @@ pub const StackIterator = struct { | ... | @@ -493,6 +493,7 @@ pub const StackIterator = struct { |
| 493 | debug_info: *DebugInfo, | 493 | debug_info: *DebugInfo, |
| 494 | dwarf_context: DW.UnwindContext, | 494 | dwarf_context: DW.UnwindContext, |
| 495 | last_error: ?UnwindError = null, | 495 | last_error: ?UnwindError = null, |
| | 496 | failed: bool = false, |
| 496 | } else void = if (have_ucontext) null else {}, | 497 | } else void = if (have_ucontext) null else {}, |
| 497 | | 498 | |
| 498 | pub fn init(first_address: ?usize, fp: ?usize) StackIterator { | 499 | pub fn init(first_address: ?usize, fp: ?usize) StackIterator { |
| ... | @@ -530,6 +531,7 @@ pub const StackIterator = struct { | ... | @@ -530,6 +531,7 @@ pub const StackIterator = struct { |
| 530 | if (!have_ucontext) return null; | 531 | if (!have_ucontext) return null; |
| 531 | if (self.unwind_state) |*unwind_state| { | 532 | if (self.unwind_state) |*unwind_state| { |
| 532 | if (unwind_state.last_error) |err| { | 533 | if (unwind_state.last_error) |err| { |
| | 534 | unwind_state.last_error = null; |
| 533 | return .{ | 535 | return .{ |
| 534 | .err = err, | 536 | .err = err, |
| 535 | .address = unwind_state.dwarf_context.pc, | 537 | .address = unwind_state.dwarf_context.pc, |
| ... | @@ -648,15 +650,20 @@ pub const StackIterator = struct { | ... | @@ -648,15 +650,20 @@ pub const StackIterator = struct { |
| 648 | fn next_internal(self: *StackIterator) ?usize { | 650 | fn next_internal(self: *StackIterator) ?usize { |
| 649 | if (have_ucontext) { | 651 | if (have_ucontext) { |
| 650 | if (self.unwind_state) |*unwind_state| { | 652 | if (self.unwind_state) |*unwind_state| { |
| 651 | if (unwind_state.dwarf_context.pc == 0) return null; | 653 | if (!unwind_state.failed) { |
| 652 | if (unwind_state.last_error == null) { | 654 | if (unwind_state.dwarf_context.pc == 0) return null; |
| 653 | if (self.next_unwind()) |return_address| { | 655 | if (unwind_state.last_error == null) { |
| 654 | return return_address; | 656 | if (self.next_unwind()) |return_address| { |
| 655 | } else |err| { | 657 | return return_address; |
| 656 | unwind_state.last_error = err; | 658 | } else |err| { |
| 657 | | 659 | unwind_state.last_error = err; |
| 658 | // Fall back to fp-based unwinding on the first failure | 660 | unwind_state.failed = true; |
| 659 | self.fp = unwind_state.dwarf_context.getFp() catch 0; | 661 | |
| | 662 | // Fall back to fp-based unwinding on the first failure. |
| | 663 | // We can't attempt it for other modules later in the |
| | 664 | // stack because the full register state won't be unwound. |
| | 665 | self.fp = unwind_state.dwarf_context.getFp() catch 0; |
| | 666 | } |
| 660 | } | 667 | } |
| 661 | } | 668 | } |
| 662 | } | 669 | } |