diff options
-rw-r--r-- | gdb/gdbserver/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/gdbserver/linux-arm-low.c | 37 |
2 files changed, 41 insertions, 1 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 4c28195..f6f0ad9 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,5 +1,10 @@ 2016-06-28 Yao Qi <yao.qi@linaro.org> + * linux-arm-low.c (arm_get_syscall_trapinfo): New function. + (the_low_target): Install arm_get_syscall_trapinfo. + +2016-06-28 Yao Qi <yao.qi@linaro.org> + * linux-aarch64-low.c (aarch64_get_syscall_trapinfo): New function. (the_low_target): Install aarch64_get_syscall_trapinfo. diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c index 2ffda87..e1261e5 100644 --- a/gdb/gdbserver/linux-arm-low.c +++ b/gdb/gdbserver/linux-arm-low.c @@ -951,6 +951,40 @@ arm_supports_hardware_single_step (void) return 0; } +/* Implementation of linux_target_ops method "get_syscall_trapinfo". */ + +static void +arm_get_syscall_trapinfo (struct regcache *regcache, int *sysno) +{ + if (arm_is_thumb_mode ()) + collect_register_by_name (regcache, "r7", sysno); + else + { + unsigned long pc; + unsigned long insn; + + collect_register_by_name (regcache, "pc", &pc); + + if ((*the_target->read_memory) (pc - 4, (unsigned char *) &insn, 4)) + *sysno = UNKNOWN_SYSCALL; + else + { + unsigned long svc_operand = (0x00ffffff & insn); + + if (svc_operand) + { + /* OABI */ + *sysno = svc_operand - 0x900000; + } + else + { + /* EABI */ + collect_register_by_name (regcache, "r7", sysno); + } + } + } +} + /* Register sets without using PTRACE_GETREGSET. */ static struct regset_info arm_regsets[] = { @@ -1031,7 +1065,8 @@ struct linux_target_ops the_low_target = { NULL, /* get_min_fast_tracepoint_insn_len */ NULL, /* supports_range_stepping */ arm_breakpoint_kind_from_current_state, - arm_supports_hardware_single_step + arm_supports_hardware_single_step, + arm_get_syscall_trapinfo, }; void |