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>
This commit is contained in:
parent
a9fca58305
commit
67649c6185
2 changed files with 53 additions and 29 deletions
|
@ -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,37 +228,12 @@ 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;
|
||||
if (!ReadRegisterSet(info, tid)) {
|
||||
if (!ReadRegisters(info, tid)) {
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
#endif // PTRACE_GETREGSET
|
||||
|
||||
#if defined(__i386)
|
||||
#if !defined(bit_FXSAVE) // e.g. Clang
|
||||
#define bit_FXSAVE bit_FXSR
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue