diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 4c28195fb0eab50b42e1b524c1047638ebcf3df6..f6f0ad975581db5bda41ec4b5a2613f416e2a95f 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,8 @@ +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 diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c index 2ffda8731d1e1d4b7ef6ec2a1f2b6b19ba02e783..e1261e54530e3a10b622fe0e53fc1083f46d8fd2 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