From 67649c61853108eb0c29703f6ff0db42e9d69f10 Mon Sep 17 00:00:00 2001 From: Andrew Ermakovich Date: Fri, 21 Apr 2017 18:41:24 +0300 Subject: Fixing breakpad on old linux kernel Try to read the trace's registers by PTRACE_GETREGS if kernel doesn't support PTRACE_GETREGSET. Bug: Change-Id: I881f3a868789747ca217f22a93370c6914881f9a Reviewed-on: https://chromium-review.googlesource.com/484479 Reviewed-by: Mike Frysinger --- .../linux/minidump_writer/linux_ptrace_dumper.cc | 73 +++++++++++++--------- 1 file changed, 44 insertions(+), 29 deletions(-) (limited to 'src/client/linux/minidump_writer/linux_ptrace_dumper.cc') diff --git a/src/client/linux/minidump_writer/linux_ptrace_dumper.cc b/src/client/linux/minidump_writer/linux_ptrace_dumper.cc index 30b8f3dd..f181bf92 100644 --- a/src/client/linux/minidump_writer/linux_ptrace_dumper.cc +++ b/src/client/linux/minidump_writer/linux_ptrace_dumper.cc @@ -149,6 +149,46 @@ bool LinuxPtraceDumper::CopyFromProcess(void* dest, pid_t child, return true; } +bool LinuxPtraceDumper::ReadRegisterSet(ThreadInfo* info, pid_t tid) +{ +#ifdef PTRACE_GETREGSET + struct iovec io; + info->GetGeneralPurposeRegisters(&io.iov_base, &io.iov_len); + if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_PRSTATUS, (void*)&io) == -1) { + return false; + } + + info->GetFloatingPointRegisters(&io.iov_base, &io.iov_len); + if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_FPREGSET, (void*)&io) == -1) { + return false; + } + return true; +#else + return false; +#endif +} + +bool LinuxPtraceDumper::ReadRegisters(ThreadInfo* info, pid_t tid) { + void* gp_addr; + info->GetGeneralPurposeRegisters(&gp_addr, NULL); + if (sys_ptrace(PTRACE_GETREGS, tid, NULL, gp_addr) == -1) { + return false; + } + +#if !(defined(__ANDROID__) && defined(__ARM_EABI__)) + // When running an arm build on an arm64 device, attempting to get the + // floating point registers fails. On Android, the floating point registers + // aren't written to the cpu context anyway, so just don't get them here. + // See http://crbug.com/508324 + void* fp_addr; + info->GetFloatingPointRegisters(&fp_addr, NULL); + if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, fp_addr) == -1) { + return false; + } +#endif + return true; +} + // Read thread info from /proc/$pid/status. // Fill out the |tgid|, |ppid| and |pid| members of |info|. If unavailable, // these members are set to -1. Returns true iff all three members are @@ -188,36 +228,11 @@ bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) { if (info->ppid == -1 || info->tgid == -1) return false; -#ifdef PTRACE_GETREGSET - struct iovec io; - info->GetGeneralPurposeRegisters(&io.iov_base, &io.iov_len); - if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_PRSTATUS, (void*)&io) == -1) { - return false; - } - - info->GetFloatingPointRegisters(&io.iov_base, &io.iov_len); - if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_FPREGSET, (void*)&io) == -1) { - return false; - } -#else // PTRACE_GETREGSET - void* gp_addr; - info->GetGeneralPurposeRegisters(&gp_addr, NULL); - if (sys_ptrace(PTRACE_GETREGS, tid, NULL, gp_addr) == -1) { - return false; - } - -#if !(defined(__ANDROID__) && defined(__ARM_EABI__)) - // When running an arm build on an arm64 device, attempting to get the - // floating point registers fails. On Android, the floating point registers - // aren't written to the cpu context anyway, so just don't get them here. - // See http://crbug.com/508324 - void* fp_addr; - info->GetFloatingPointRegisters(&fp_addr, NULL); - if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, fp_addr) == -1) { - return false; + if (!ReadRegisterSet(info, tid)) { + if (!ReadRegisters(info, tid)) { + return false; + } } -#endif -#endif // PTRACE_GETREGSET #if defined(__i386) #if !defined(bit_FXSAVE) // e.g. Clang -- cgit v1.2.1