From 0314ff8522a6c991db26d5fb935e270d260e6dc0 Mon Sep 17 00:00:00 2001 From: Stephen Chen Date: Mon, 7 Aug 2017 09:32:27 -0700 Subject: [PATCH] aarch64: Use PTRACE_GETREGSET if available In remote ptrace mode, we currently use PTRACE_PEEKUSER to read the registers. PTRACE_PEEKUSER only works on x86 or arm 32 bit compatibility mode on linux. On aarch64 system, it always return -EIO. https://github.com/torvalds/linux/blob/master/kernel/ptrace.c#L885-L1102 PTRACE_GETREGSET is the newer and more supported way of reading registers. Use that if it's available. --- configure.ac | 2 +- src/ptrace/_UPT_access_reg.c | 45 +++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index e11ba8bf..d4007535 100644 --- a/configure.ac +++ b/configure.ac @@ -56,7 +56,7 @@ AC_CHECK_TYPES([struct elf_prstatus, struct prstatus], [], [], #endif ]) -AC_CHECK_DECLS([PTRACE_POKEUSER, PTRACE_POKEDATA, +AC_CHECK_DECLS([PTRACE_POKEUSER, PTRACE_POKEDATA, PTRACE_SETREGSET, PTRACE_TRACEME, PTRACE_CONT, PTRACE_SINGLESTEP, PTRACE_SYSCALL, PT_IO, PT_GETREGS, PT_GETFPREGS, PT_CONTINUE, PT_TRACE_ME, diff --git a/src/ptrace/_UPT_access_reg.c b/src/ptrace/_UPT_access_reg.c index ae71608b..ce25c783 100644 --- a/src/ptrace/_UPT_access_reg.c +++ b/src/ptrace/_UPT_access_reg.c @@ -34,7 +34,50 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ # include "tdep-ia64/rse.h" #endif -#if HAVE_DECL_PTRACE_POKEUSER || HAVE_TTRACE +#if HAVE_DECL_PTRACE_SETREGSET +#include +int +_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + gregset_t regs; + char *r; + struct iovec loc; + +#if UNW_DEBUG + Debug(16, "using getregset: reg: %s [%u], val: %lx, write: %u\n", + unw_regname(reg), (unsigned) reg, (long) val, write); + + if (write) + Debug (16, "%s [%u] <- %lx\n", unw_regname (reg), (unsigned) reg, (long) *val); +#endif + if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) + { + errno = EINVAL; + goto badreg; + } + + loc.iov_base = ®s; + loc.iov_len = sizeof(regs); + + r = (char *)®s + _UPT_reg_offset[reg]; + if (ptrace (PTRACE_GETREGSET, pid, NT_PRSTATUS, &loc) == -1) + goto badreg; + if (write) { + memcpy(r, val, sizeof(unw_word_t)); + if (ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &loc) == -1) + goto badreg; + } else + memcpy(val, r, sizeof(unw_word_t)); + return 0; + +badreg: + Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno)); + return -UNW_EBADREG; +} +#elif HAVE_DECL_PTRACE_POKEUSER || HAVE_TTRACE int _UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, void *arg)