aboutsummaryrefslogtreecommitdiff
path: root/gdb/arm-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r--gdb/arm-tdep.c42
1 files changed, 25 insertions, 17 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 803596d..492a71f 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -3115,26 +3115,34 @@ arm_exidx_unwind_sniffer (const struct frame_unwind *self,
&& get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME)
exc_valid = 1;
- /* We also assume exception information is valid if we're currently
- blocked in a system call. The system library is supposed to
- ensure this, so that e.g. pthread cancellation works. */
- if (arm_frame_is_thumb (this_frame))
+ /* Some syscalls keep PC pointing to the SVC instruction itself. */
+ for (int shift = 0; shift <= 1 && !exc_valid; ++shift)
{
- ULONGEST insn;
+ /* We also assume exception information is valid if we're currently
+ blocked in a system call. The system library is supposed to
+ ensure this, so that e.g. pthread cancellation works. */
+ if (arm_frame_is_thumb (this_frame))
+ {
+ ULONGEST insn;
- if (safe_read_memory_unsigned_integer (get_frame_pc (this_frame) - 2,
- 2, byte_order_for_code, &insn)
- && (insn & 0xff00) == 0xdf00 /* svc */)
- exc_valid = 1;
- }
- else
- {
- ULONGEST insn;
+ if (safe_read_memory_unsigned_integer ((get_frame_pc (this_frame)
+ - (shift ? 2 : 0)),
+ 2, byte_order_for_code,
+ &insn)
+ && (insn & 0xff00) == 0xdf00 /* svc */)
+ exc_valid = 1;
+ }
+ else
+ {
+ ULONGEST insn;
- if (safe_read_memory_unsigned_integer (get_frame_pc (this_frame) - 4,
- 4, byte_order_for_code, &insn)
- && (insn & 0x0f000000) == 0x0f000000 /* svc */)
- exc_valid = 1;
+ if (safe_read_memory_unsigned_integer ((get_frame_pc (this_frame)
+ - (shift ? 4 : 0)),
+ 4, byte_order_for_code,
+ &insn)
+ && (insn & 0x0f000000) == 0x0f000000 /* svc */)
+ exc_valid = 1;
+ }
}
/* Bail out if we don't know that exception information is valid. */