diff options
author | Andrew Ermakovich <andrew@resilio.com> | 2017-04-21 18:41:24 +0300 |
---|---|---|
committer | Mike Frysinger <vapier@chromium.org> | 2017-04-21 17:28:03 +0000 |
commit | 67649c61853108eb0c29703f6ff0db42e9d69f10 (patch) | |
tree | e447f2c18db26d32314b02e7c94a1644f054c030 /src/client/linux | |
parent | Make minidump name generation on Linux as random as possible (diff) | |
download | breakpad-67649c61853108eb0c29703f6ff0db42e9d69f10.tar.xz |
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 <vapier@chromium.org>
Diffstat (limited to 'src/client/linux')
-rw-r--r-- | src/client/linux/minidump_writer/linux_ptrace_dumper.cc | 73 | ||||
-rw-r--r-- | src/client/linux/minidump_writer/linux_ptrace_dumper.h | 9 |
2 files changed, 53 insertions, 29 deletions
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 diff --git a/src/client/linux/minidump_writer/linux_ptrace_dumper.h b/src/client/linux/minidump_writer/linux_ptrace_dumper.h index 2ce834b0..cee58178 100644 --- a/src/client/linux/minidump_writer/linux_ptrace_dumper.h +++ b/src/client/linux/minidump_writer/linux_ptrace_dumper.h @@ -85,6 +85,15 @@ class LinuxPtraceDumper : public LinuxDumper { private: // Set to true if all threads of the crashed process are suspended. bool threads_suspended_; + + // Read the tracee's registers on kernel with PTRACE_GETREGSET support. + // Returns false if PTRACE_GETREGSET is not defined. + // Returns true on success. + bool ReadRegisterSet(ThreadInfo* info, pid_t tid); + + // Read the tracee's registers on kernel with PTRACE_GETREGS support. + // Returns true on success. + bool ReadRegisters(ThreadInfo* info, pid_t tid); }; } // namespace google_breakpad |