You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
774 lines
34 KiB
774 lines
34 KiB
From cda9400739dfa064907d822f00578bb51b24a404 Mon Sep 17 00:00:00 2001
|
|
From: Shawn Anastasio <shawnanastasio@yahoo.com>
|
|
Date: Fri, 17 Aug 2018 14:18:33 -0500
|
|
Subject: [PATCH] Implement support for ppc64 on Linux
|
|
|
|
This patch implements support for the ppc64 architecture on Linux systems.
|
|
|
|
Notable changes include:
|
|
* Modification of tests to support non-4K page sizes
|
|
* minidump_writer: Determine size of stack to capture based on page size
|
|
* dump_writer_common: Introduce member function GetVectorRegisters to
|
|
ThreadInfo on ppc64 systems. This allows Altivec/VMX registers to be
|
|
dumped like they are on OS X. linux_ptrace_dumper has been updated
|
|
to utilize this function along with the ptrace mode NT_PPC_VMX.
|
|
* processor/exploitability_unittest.cc: Tests were disabled on
|
|
non-x86 systems. They assume the system objdump is capable of
|
|
disassembling x86 binaries which is not the case on other
|
|
architectures.
|
|
|
|
To-do:
|
|
* tools/linux/md2core has been updated as well, but functionality
|
|
has not been confirmed and restoration of Altivec/VMX registers
|
|
has not been implemented
|
|
|
|
Note that proper functionality depends on updates to third_party/LSS
|
|
that introduce PPC64 support. An in-progress patch that allows
|
|
breakpad to build and run successfully is available at:
|
|
https://wiki.raptorcs.com/wiki/Porting/Chromium
|
|
---
|
|
.../dump_writer_common/raw_context_cpu.h | 2 +
|
|
.../linux/dump_writer_common/thread_info.cc | 56 ++++++++++++++++++-
|
|
.../linux/dump_writer_common/thread_info.h | 9 +++
|
|
.../dump_writer_common/ucontext_reader.cc | 42 ++++++++++++++
|
|
.../dump_writer_common/ucontext_reader.h | 3 +
|
|
src/client/linux/handler/exception_handler.cc | 22 +++++++-
|
|
src/client/linux/handler/exception_handler.h | 6 +-
|
|
.../handler/exception_handler_unittest.cc | 8 ++-
|
|
.../microdump_writer/microdump_writer.cc | 14 ++++-
|
|
.../microdump_writer_unittest.cc | 15 ++++-
|
|
.../minidump_writer/linux_core_dumper.cc | 8 ++-
|
|
.../linux/minidump_writer/linux_dumper.cc | 4 +-
|
|
.../linux/minidump_writer/linux_dumper.h | 3 +-
|
|
.../linux_dumper_unittest_helper.cc | 2 +
|
|
.../minidump_writer/linux_ptrace_dumper.cc | 19 +++++--
|
|
.../linux_ptrace_dumper_unittest.cc | 5 ++
|
|
.../linux/minidump_writer/minidump_writer.cc | 18 ++++--
|
|
.../linux/minidump_writer/minidump_writer.h | 2 +
|
|
.../minidump_writer_unittest.cc | 3 +
|
|
src/common/linux/memory_mapped_file.cc | 3 +-
|
|
.../linux/memory_mapped_file_unittest.cc | 7 ++-
|
|
src/common/memory_allocator_unittest.cc | 3 +-
|
|
src/processor/exploitability_linux.cc | 2 +
|
|
src/processor/exploitability_unittest.cc | 15 +++--
|
|
src/tools/linux/md2core/minidump-2-core.cc | 45 +++++++++++++++
|
|
25 files changed, 281 insertions(+), 35 deletions(-)
|
|
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/raw_context_cpu.h
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/raw_context_cpu.h
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/raw_context_cpu.h
|
|
@@ -51,6 +51,8 @@ typedef MDRawContextRISCV64 RawContextCP
|
|
# else
|
|
# error "Unexpected __riscv_xlen"
|
|
# endif
|
|
+#elif defined(__powerpc64__)
|
|
+typedef MDRawContextPPC64 RawContextCPU;
|
|
#else
|
|
#error "This code has not been ported to your platform yet."
|
|
#endif
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
|
|
@@ -336,7 +336,42 @@ void ThreadInfo::FillCPUContext(RawConte
|
|
#error "Unexpected __riscv_xlen"
|
|
#endif
|
|
}
|
|
-#endif // __riscv
|
|
+
|
|
+#elif defined(__powerpc64__)
|
|
+
|
|
+uintptr_t ThreadInfo::GetInstructionPointer() const {
|
|
+ return mcontext.gp_regs[PT_NIP];
|
|
+}
|
|
+
|
|
+void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
|
|
+ out->context_flags = MD_CONTEXT_PPC64_FULL;
|
|
+ for (int i = 0; i < MD_CONTEXT_PPC64_GPR_COUNT; i++)
|
|
+ out->gpr[i] = mcontext.gp_regs[i];
|
|
+
|
|
+ out->lr = mcontext.gp_regs[PT_LNK];
|
|
+ out->srr0 = mcontext.gp_regs[PT_NIP];
|
|
+ out->srr1 = mcontext.gp_regs[PT_MSR];
|
|
+ out->cr = mcontext.gp_regs[PT_CCR];
|
|
+ out->xer = mcontext.gp_regs[PT_XER];
|
|
+ out->ctr = mcontext.gp_regs[PT_CTR];
|
|
+
|
|
+ for (int i = 0; i < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; i++)
|
|
+ out->float_save.fpregs[i] = mcontext.fp_regs[i];
|
|
+
|
|
+ out->float_save.fpscr = mcontext.fp_regs[NFPREG-1];
|
|
+
|
|
+ for (int i = 0; i < MD_VECTORSAVEAREA_PPC_VR_COUNT; i++)
|
|
+ out->vector_save.save_vr[i] = \
|
|
+ {(((uint64_t)vregs.vrregs[i][0]) << 32)
|
|
+ | vregs.vrregs[i][1],
|
|
+ (((uint64_t)vregs.vrregs[i][2]) << 32)
|
|
+ | vregs.vrregs[i][3]};
|
|
+
|
|
+ out->vrsave = vregs.vrsave;
|
|
+ out->vector_save.save_vscr = {0, vregs.vscr.vscr_word};
|
|
+ out->vector_save.save_vrvalid = 0xFFFFFFFF;
|
|
+}
|
|
+#endif // __powerpc64__
|
|
|
|
void ThreadInfo::GetGeneralPurposeRegisters(void** gp_regs, size_t* size) {
|
|
assert(gp_regs || size);
|
|
@@ -350,6 +385,11 @@ void ThreadInfo::GetGeneralPurposeRegist
|
|
*gp_regs = mcontext.__gregs;
|
|
if (size)
|
|
*size = sizeof(mcontext.__gregs);
|
|
+#elif defined(__powerpc64__)
|
|
+ if (gp_regs)
|
|
+ *gp_regs = mcontext.gp_regs;
|
|
+ if (size)
|
|
+ *size = sizeof(mcontext.gp_regs);
|
|
#else
|
|
if (gp_regs)
|
|
*gp_regs = ®s;
|
|
@@ -384,6 +424,11 @@ void ThreadInfo::GetFloatingPointRegiste
|
|
# else
|
|
# error "Unexpected __riscv_flen"
|
|
# endif
|
|
+#elif defined(__powerpc64__)
|
|
+ if (fp_regs)
|
|
+ *fp_regs = &mcontext.fp_regs;
|
|
+ if (size)
|
|
+ *size = sizeof(mcontext.fp_regs);
|
|
#else
|
|
if (fp_regs)
|
|
*fp_regs = &fpregs;
|
|
@@ -392,4 +437,13 @@ void ThreadInfo::GetFloatingPointRegiste
|
|
#endif
|
|
}
|
|
|
|
+#if defined(__powerpc64__)
|
|
+void ThreadInfo::GetVectorRegisters(void** v_regs, size_t* size) {
|
|
+ if (v_regs)
|
|
+ *v_regs = &vregs;
|
|
+ if (size)
|
|
+ *size = sizeof(vregs);
|
|
+}
|
|
+#endif
|
|
+
|
|
} // namespace google_breakpad
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.h
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.h
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.h
|
|
@@ -67,6 +67,10 @@ struct ThreadInfo {
|
|
// Use the structures defined in <sys/user.h>
|
|
struct user_regs_struct regs;
|
|
struct user_fpsimd_struct fpregs;
|
|
+#elif defined(__powerpc64__)
|
|
+ // Use the structures defined in <sys/ucontext.h>.
|
|
+ mcontext_t mcontext;
|
|
+ struct _libc_vrstate vregs;
|
|
#elif defined(__mips__) || defined(__riscv)
|
|
// Use the structure defined in <sys/ucontext.h>.
|
|
mcontext_t mcontext;
|
|
@@ -83,6 +87,11 @@ struct ThreadInfo {
|
|
|
|
// Returns the pointer and size of float point register area.
|
|
void GetFloatingPointRegisters(void** fp_regs, size_t* size);
|
|
+
|
|
+#if defined(__powerpc64__)
|
|
+ // Returns the pointer and size of the vector register area. (PPC64 only)
|
|
+ void GetVectorRegisters(void** v_regs, size_t* size);
|
|
+#endif
|
|
};
|
|
|
|
} // namespace google_breakpad
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
|
|
@@ -324,6 +324,48 @@ void UContextReader::FillCPUContext(RawC
|
|
#error "Unexpected __riscv_xlen"
|
|
#endif
|
|
}
|
|
+
|
|
+#elif defined(__powerpc64__)
|
|
+
|
|
+uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
|
|
+ return uc->uc_mcontext.gp_regs[MD_CONTEXT_PPC64_REG_SP];
|
|
+}
|
|
+
|
|
+uintptr_t UContextReader::GetInstructionPointer(const ucontext_t* uc) {
|
|
+ return uc->uc_mcontext.gp_regs[PT_NIP];
|
|
+}
|
|
+
|
|
+void UContextReader::FillCPUContext(RawContextCPU* out, const ucontext_t* uc,
|
|
+ const struct _libc_vrstate* vregs) {
|
|
+ out->context_flags = MD_CONTEXT_PPC64_FULL;
|
|
+
|
|
+ for (int i = 0; i < MD_CONTEXT_PPC64_GPR_COUNT; i++)
|
|
+ out->gpr[i] = uc->uc_mcontext.gp_regs[i];
|
|
+
|
|
+ out->lr = uc->uc_mcontext.gp_regs[PT_LNK];
|
|
+ out->srr0 = uc->uc_mcontext.gp_regs[PT_NIP];
|
|
+ out->srr1 = uc->uc_mcontext.gp_regs[PT_MSR];
|
|
+ out->cr = uc->uc_mcontext.gp_regs[PT_CCR];
|
|
+ out->xer = uc->uc_mcontext.gp_regs[PT_XER];
|
|
+ out->ctr = uc->uc_mcontext.gp_regs[PT_CTR];
|
|
+
|
|
+ for (int i = 0; i < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; i++)
|
|
+ out->float_save.fpregs[i] = uc->uc_mcontext.fp_regs[i];
|
|
+
|
|
+ out->float_save.fpscr = uc->uc_mcontext.fp_regs[NFPREG-1];
|
|
+
|
|
+ for (int i = 0; i < MD_VECTORSAVEAREA_PPC_VR_COUNT; i++)
|
|
+ out->vector_save.save_vr[i] =
|
|
+ {(((uint64_t)vregs->vrregs[i][0]) << 32)
|
|
+ | vregs->vrregs[i][1],
|
|
+ (((uint64_t)vregs->vrregs[i][2]) << 32)
|
|
+ | vregs->vrregs[i][3]};
|
|
+
|
|
+ out->vrsave = vregs->vrsave;
|
|
+ out->vector_save.save_vscr = {0, vregs->vscr.vscr_word};
|
|
+ out->vector_save.save_vrvalid = 0xFFFFFFFF;
|
|
+}
|
|
+
|
|
#endif
|
|
|
|
} // namespace google_breakpad
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h
|
|
@@ -54,6 +54,9 @@ struct UContextReader {
|
|
#elif defined(__aarch64__)
|
|
static void FillCPUContext(RawContextCPU* out, const ucontext_t* uc,
|
|
const struct fpsimd_context* fpregs);
|
|
+#elif defined(__powerpc64__)
|
|
+ static void FillCPUContext(RawContextCPU *out, const ucontext_t *uc,
|
|
+ const struct _libc_vrstate* vregs);
|
|
#else
|
|
static void FillCPUContext(RawContextCPU* out, const ucontext_t* uc);
|
|
#endif
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
|
|
@@ -464,6 +464,13 @@ bool ExceptionHandler::HandleSignal(int
|
|
memcpy(&g_crash_context_.float_state, fp_ptr,
|
|
sizeof(g_crash_context_.float_state));
|
|
}
|
|
+#elif defined(__powerpc64__)
|
|
+ // On PPC64, we must copy VR state
|
|
+ ucontext_t* uc_ptr = (ucontext_t*)uc;
|
|
+ if (uc_ptr->uc_mcontext.v_regs) {
|
|
+ memcpy(&g_crash_context_.vector_state, uc_ptr->uc_mcontext.v_regs,
|
|
+ sizeof(g_crash_context_.vector_state));
|
|
+ }
|
|
#elif GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
ucontext_t* uc_ptr = (ucontext_t*)uc;
|
|
if (uc_ptr->uc_mcontext.fpregs) {
|
|
@@ -701,10 +708,18 @@ bool ExceptionHandler::WriteMinidump() {
|
|
}
|
|
#endif
|
|
|
|
-#if GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE && !defined(__aarch64__)
|
|
+#if GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE && !defined(__aarch64__) \
|
|
+ && !defined(__powerpc64__)
|
|
memcpy(&context.float_state, context.context.uc_mcontext.fpregs,
|
|
sizeof(context.float_state));
|
|
#endif
|
|
+
|
|
+#if defined(__powerpc64__)
|
|
+ // Vector registers must be copied on PPC64
|
|
+ memcpy(&context.vector_state, context.context.uc_mcontext.v_regs,
|
|
+ sizeof(context.vector_state));
|
|
+#endif
|
|
+
|
|
context.tid = sys_gettid();
|
|
|
|
// Add an exception stream to the minidump for better reporting.
|
|
@@ -725,6 +740,9 @@ bool ExceptionHandler::WriteMinidump() {
|
|
#elif defined(__mips__)
|
|
context.siginfo.si_addr =
|
|
reinterpret_cast<void*>(context.context.uc_mcontext.pc);
|
|
+#elif defined(__powerpc64__)
|
|
+ context.siginfo.si_addr =
|
|
+ reinterpret_cast<void*>(context.context.uc_mcontext.gp_regs[PT_NIP]);
|
|
#elif defined(__riscv)
|
|
context.siginfo.si_addr =
|
|
reinterpret_cast<void*>(context.context.uc_mcontext.__gregs[REG_PC]);
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.h
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.h
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.h
|
|
@@ -200,7 +200,11 @@ class ExceptionHandler {
|
|
siginfo_t siginfo;
|
|
pid_t tid; // the crashing thread.
|
|
ucontext_t context;
|
|
-#if GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
+#if defined(__powerpc64__)
|
|
+ // PPC64's FP state is a part of ucontext_t like MIPS but the vector
|
|
+ // state is not, so a struct is needed.
|
|
+ vstate_t vector_state;
|
|
+#elif GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
fpstate_t float_state;
|
|
#endif
|
|
};
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler_unittest.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler_unittest.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler_unittest.cc
|
|
@@ -321,7 +321,7 @@ TEST(ExceptionHandlerTest, ParallelChild
|
|
ASSERT_EQ(SIGSEGV, WTERMSIG(status));
|
|
return;
|
|
} else {
|
|
- usleep(100000);
|
|
+ usleep(200000);
|
|
}
|
|
}
|
|
|
|
@@ -576,6 +576,8 @@ const unsigned char kIllegalInstruction[
|
|
#if defined(__mips__)
|
|
// mfc2 zero,Impl - usually illegal in userspace.
|
|
0x48, 0x00, 0x00, 0x48
|
|
+#elif defined(__powerpc64__)
|
|
+ 0x01, 0x01, 0x01, 0x01 // Crashes on a tested POWER9 cpu
|
|
#else
|
|
// This crashes with SIGILL on x86/x86-64/arm.
|
|
0xff, 0xff, 0xff, 0xff
|
|
@@ -771,10 +773,10 @@ TEST(ExceptionHandlerTest, InstructionPo
|
|
|
|
// These are defined here so the parent can use them to check the
|
|
// data from the minidump afterwards.
|
|
- // Use 4k here because the OS will hand out a single page even
|
|
+ // Use the page size here because the OS will hand out a single page even
|
|
// if a smaller size is requested, and this test wants to
|
|
// test the upper bound of the memory range.
|
|
- const uint32_t kMemorySize = 4096; // bytes
|
|
+ const uint32_t kMemorySize = getpagesize(); // bytes
|
|
const int kOffset = kMemorySize - sizeof(kIllegalInstruction);
|
|
|
|
const pid_t child = fork();
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer.cc
|
|
@@ -141,7 +141,9 @@ class MicrodumpWriter {
|
|
const MicrodumpExtraInfo& microdump_extra_info,
|
|
LinuxDumper* dumper)
|
|
: ucontext_(context ? &context->context : NULL),
|
|
-#if GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
+#if defined(__powerpc64__)
|
|
+ vector_state_(context ? &context->vector_state : NULL),
|
|
+#elif GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
float_state_(context ? &context->float_state : NULL),
|
|
#endif
|
|
dumper_(dumper),
|
|
@@ -348,6 +350,8 @@ class MicrodumpWriter {
|
|
# else
|
|
# error "Unexpected __riscv_xlen"
|
|
# endif
|
|
+#elif defined(__powerpc64__)
|
|
+ const char kArch[] = "ppc64";
|
|
#else
|
|
# error "This code has not been ported to your platform yet"
|
|
#endif
|
|
@@ -420,7 +424,9 @@ class MicrodumpWriter {
|
|
void DumpCPUState() {
|
|
RawContextCPU cpu;
|
|
my_memset(&cpu, 0, sizeof(RawContextCPU));
|
|
-#if GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
+#if defined(__powerpc64__)
|
|
+ UContextReader::FillCPUContext(&cpu, ucontext_, vector_state_);
|
|
+#elif GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
UContextReader::FillCPUContext(&cpu, ucontext_, float_state_);
|
|
#else
|
|
UContextReader::FillCPUContext(&cpu, ucontext_);
|
|
@@ -616,7 +622,9 @@ class MicrodumpWriter {
|
|
void* Alloc(unsigned bytes) { return dumper_->allocator()->Alloc(bytes); }
|
|
|
|
const ucontext_t* const ucontext_;
|
|
-#if GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
+#if defined(__powerpc64__)
|
|
+ const google_breakpad::vstate_t* const vector_state_;
|
|
+#elif GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
const google_breakpad::fpstate_t* const float_state_;
|
|
#endif
|
|
LinuxDumper* dumper_;
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer_unittest.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer_unittest.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer_unittest.cc
|
|
@@ -282,10 +282,19 @@ TEST(MicrodumpWriterTest, BasicWithMappi
|
|
CrashAndGetMicrodump(mappings, MicrodumpExtraInfo(), &buf);
|
|
ASSERT_TRUE(ContainsMicrodump(buf));
|
|
|
|
+ int page_size = getpagesize();
|
|
#ifdef __LP64__
|
|
- ASSERT_NE(std::string::npos,
|
|
- buf.find("M 0000000000001000 000000000000002A 0000000000001000 "
|
|
- "33221100554477668899AABBCCDDEEFF0 libfoo.so"));
|
|
+ // This test is only available for the following page sizes
|
|
+ ASSERT_TRUE((page_size == 4096) || (page_size == 65536));
|
|
+ if (page_size == 4096) {
|
|
+ ASSERT_NE(std::string::npos,
|
|
+ buf.find("M 0000000000001000 000000000000002A 0000000000001000 "
|
|
+ "33221100554477668899AABBCCDDEEFF0 libfoo.so"));
|
|
+ } else {
|
|
+ ASSERT_NE(std::string::npos,
|
|
+ buf.find("M 0000000000010000 000000000000002A 0000000000010000 "
|
|
+ "33221100554477668899AABBCCDDEEFF0 libfoo.so"));
|
|
+ }
|
|
#else
|
|
ASSERT_NE(std::string::npos,
|
|
buf.find("M 00001000 0000002A 00001000 "
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_core_dumper.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_core_dumper.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_core_dumper.cc
|
|
@@ -118,6 +118,9 @@ bool LinuxCoreDumper::GetThreadInfoByInd
|
|
#elif defined(__riscv)
|
|
stack_pointer = reinterpret_cast<uint8_t*>(
|
|
info->mcontext.__gregs[MD_CONTEXT_RISCV_REG_SP]);
|
|
+#elif defined(__powerpc64__)
|
|
+ stack_pointer =
|
|
+ reinterpret_cast<uint8_t*>(info->mcontext.gp_regs[MD_CONTEXT_PPC64_REG_SP]);
|
|
#else
|
|
# error "This code hasn't been ported to your platform yet."
|
|
#endif
|
|
@@ -213,7 +216,10 @@ bool LinuxCoreDumper::EnumerateThreads()
|
|
memset(&info, 0, sizeof(ThreadInfo));
|
|
info.tgid = status->pr_pgrp;
|
|
info.ppid = status->pr_ppid;
|
|
-#if defined(__mips__)
|
|
+#if defined(__powerpc64__)
|
|
+ for (int i = 0; i < 31; i++)
|
|
+ info.mcontext.gp_regs[i] = status->pr_reg[i];
|
|
+#elif defined(__mips__)
|
|
# if defined(__ANDROID__)
|
|
for (int i = EF_R0; i <= EF_R31; i++)
|
|
info.mcontext.gregs[i - EF_R0] = status->pr_reg[i];
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.cc
|
|
@@ -770,7 +770,9 @@ bool LinuxDumper::GetStackInfo(const voi
|
|
reinterpret_cast<uint8_t*>(int_stack_pointer & ~(page_size - 1));
|
|
|
|
// The number of bytes of stack which we try to capture.
|
|
- static const ptrdiff_t kStackToCapture = 32 * 1024;
|
|
+ // This now depends on page_size to avoid missing data
|
|
+ // on systems with larger page sizes.
|
|
+ static const ptrdiff_t kStackToCapture = 8 * page_size;
|
|
|
|
const MappingInfo* mapping = FindMapping(stack_pointer);
|
|
if (!mapping)
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.h
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.h
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.h
|
|
@@ -64,7 +64,8 @@ namespace google_breakpad {
|
|
typedef Elf32_auxv_t elf_aux_entry;
|
|
#elif defined(__x86_64) || defined(__aarch64__) || \
|
|
(defined(__mips__) && _MIPS_SIM != _ABIO32) || \
|
|
- (defined(__riscv) && __riscv_xlen == 64)
|
|
+ (defined(__riscv) && __riscv_xlen == 64) || \
|
|
+ defined(__powerpc64__)
|
|
typedef Elf64_auxv_t elf_aux_entry;
|
|
#endif
|
|
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
|
|
@@ -56,6 +56,8 @@
|
|
#define TID_PTR_REGISTER "$1"
|
|
#elif defined(__riscv)
|
|
#define TID_PTR_REGISTER "x4"
|
|
+#elif defined(__powerpc64__)
|
|
+#define TID_PTR_REGISTER "r8"
|
|
#else
|
|
#error This test has not been ported to this platform.
|
|
#endif
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
|
|
@@ -189,12 +189,12 @@ bool LinuxPtraceDumper::ReadRegisterSet(
|
|
#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) {
|
|
+ if (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) {
|
|
+ if (ptrace(PTRACE_GETREGSET, tid, (void*)NT_FPREGSET, (void*)&io) == -1) {
|
|
// We are going to check if we can read VFP registers on ARM32.
|
|
// Currently breakpad does not support VFP registers to be a part of minidump,
|
|
// so this is only to confirm that we can actually read FP registers.
|
|
@@ -214,6 +214,15 @@ bool LinuxPtraceDumper::ReadRegisterSet(
|
|
}
|
|
#endif // defined(__arm__)
|
|
}
|
|
+
|
|
+#if defined(__powerpc64__)
|
|
+ // Grab the vector registers on PPC64 too
|
|
+ info->GetVectorRegisters(&io.iov_base, &io.iov_len);
|
|
+ if (ptrace(PTRACE_GETREGSET, tid, (void*)NT_PPC_VMX, (void*)&io) == -1) {
|
|
+ return false;
|
|
+ }
|
|
+#endif // defined(__powerpc64__)
|
|
+
|
|
return true;
|
|
#else
|
|
return false;
|
|
@@ -378,6 +387,9 @@ bool LinuxPtraceDumper::GetThreadInfoByI
|
|
#elif defined(__riscv)
|
|
stack_pointer = reinterpret_cast<uint8_t*>(
|
|
info->mcontext.__gregs[MD_CONTEXT_RISCV_REG_SP]);
|
|
+#elif defined(__powerpc64__)
|
|
+ stack_pointer =
|
|
+ reinterpret_cast<uint8_t*>(info->mcontext.gp_regs[MD_CONTEXT_PPC64_REG_SP]);
|
|
#else
|
|
# error "This code hasn't been ported to your platform yet."
|
|
#endif
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
|
|
@@ -470,6 +470,9 @@ TEST(LinuxPtraceDumperTest, VerifyStackR
|
|
#elif defined(__riscv)
|
|
pid_t* process_tid_location =
|
|
reinterpret_cast<pid_t*>(one_thread.mcontext.__gregs[4]);
|
|
+#elif defined(__powerpc64__)
|
|
+ pid_t* process_tid_location =
|
|
+ reinterpret_cast<pid_t*>(one_thread.mcontext.gp_regs[8]);
|
|
#else
|
|
#error This test has not been ported to this platform.
|
|
#endif
|
|
@@ -569,6 +572,8 @@ TEST_F(LinuxPtraceDumperTest, SanitizeSt
|
|
uintptr_t heap_addr = thread_info.mcontext.gregs[1];
|
|
#elif defined(__riscv)
|
|
uintptr_t heap_addr = thread_info.mcontext.__gregs[4];
|
|
+#elif defined(__powerpc64__)
|
|
+ uintptr_t heap_addr = thread_info.mcontext.gp_regs[8];
|
|
#else
|
|
#error This test has not been ported to this platform.
|
|
#endif
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.cc
|
|
@@ -144,7 +144,9 @@ class MinidumpWriter {
|
|
: fd_(minidump_fd),
|
|
path_(minidump_path),
|
|
ucontext_(context ? &context->context : NULL),
|
|
-#if GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
+#if defined(__powerpc64__)
|
|
+ vector_state_(context ? &context->vector_state : NULL),
|
|
+#elif GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
float_state_(context ? &context->float_state : NULL),
|
|
#endif
|
|
dumper_(dumper),
|
|
@@ -476,7 +478,9 @@ class MinidumpWriter {
|
|
if (!cpu.Allocate())
|
|
return false;
|
|
my_memset(cpu.get(), 0, sizeof(RawContextCPU));
|
|
-#if GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
+#if defined(__powerpc64__)
|
|
+ UContextReader::FillCPUContext(cpu.get(), ucontext_, vector_state_);
|
|
+#elif GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
UContextReader::FillCPUContext(cpu.get(), ucontext_, float_state_);
|
|
#else
|
|
UContextReader::FillCPUContext(cpu.get(), ucontext_);
|
|
@@ -953,7 +957,7 @@ class MinidumpWriter {
|
|
dirent->location.rva = 0;
|
|
}
|
|
|
|
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
|
|
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || defined(__powerpc64__)
|
|
bool WriteCPUInformation(MDRawSystemInfo* sys_info) {
|
|
char vendor_id[sizeof(sys_info->cpu.x86_cpu_info.vendor_id) + 1] = {0};
|
|
static const char vendor_id_name[] = "vendor_id";
|
|
@@ -973,7 +977,9 @@ class MinidumpWriter {
|
|
|
|
// processor_architecture should always be set, do this first
|
|
sys_info->processor_architecture =
|
|
-#if defined(__mips__)
|
|
+#if defined(__powerpc64__)
|
|
+ MD_CPU_ARCHITECTURE_PPC64;
|
|
+#elif defined(__mips__)
|
|
# if _MIPS_SIM == _ABIO32
|
|
MD_CPU_ARCHITECTURE_MIPS;
|
|
# elif _MIPS_SIM == _ABI64
|
|
@@ -1440,7 +1446,9 @@ class MinidumpWriter {
|
|
const char* path_; // Path to the file where the minidum should be written.
|
|
|
|
const ucontext_t* const ucontext_; // also from the signal handler
|
|
-#if GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
+#if defined(__powerpc64__)
|
|
+ const google_breakpad::vstate_t* const vector_state_;
|
|
+#elif GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
|
const google_breakpad::fpstate_t* const float_state_; // ditto
|
|
#endif
|
|
LinuxDumper* dumper_;
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.h
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.h
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.h
|
|
@@ -47,6 +47,8 @@ class ExceptionHandler;
|
|
|
|
#if defined(__aarch64__)
|
|
typedef struct fpsimd_context fpstate_t;
|
|
+#elif defined(__powerpc64__)
|
|
+typedef struct _libc_vrstate vstate_t;
|
|
#elif !defined(__ARM_EABI__) && !defined(__mips__)
|
|
typedef std::remove_pointer<fpregset_t>::type fpstate_t;
|
|
#endif
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc
|
|
@@ -723,6 +723,9 @@ TEST(MinidumpWriterTest, InvalidStackPoi
|
|
#elif defined(__riscv)
|
|
context.context.uc_mcontext.__gregs[MD_CONTEXT_RISCV_REG_SP] =
|
|
invalid_stack_pointer;
|
|
+#elif defined(__powerpc64__)
|
|
+ context.context.uc_mcontext.gp_regs[MD_CONTEXT_PPC64_REG_SP] =
|
|
+ invalid_stack_pointer;
|
|
#else
|
|
# error "This code has not been ported to your platform yet."
|
|
#endif
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file.cc
|
|
@@ -72,8 +72,7 @@ bool MemoryMappedFile::Map(const char* p
|
|
|
|
#if defined(__x86_64__) || defined(__aarch64__) || \
|
|
(defined(__mips__) && _MIPS_SIM == _ABI64) || \
|
|
- (defined(__riscv) && __riscv_xlen == 64)
|
|
-
|
|
+ (defined(__riscv) && __riscv_xlen == 64) || defined(__powerpc64__)
|
|
struct kernel_stat st;
|
|
if (sys_fstat(fd, &st) == -1 || st.st_size < 0) {
|
|
#else
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file_unittest.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file_unittest.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file_unittest.cc
|
|
@@ -179,9 +179,10 @@ TEST_F(MemoryMappedFileTest, RemapAfterM
|
|
TEST_F(MemoryMappedFileTest, MapWithOffset) {
|
|
// Put more data in the test file this time. Offsets can only be
|
|
// done on page boundaries, so we need a two page file to test this.
|
|
- const int page_size = 4096;
|
|
- char data1[2 * page_size];
|
|
- size_t data1_size = sizeof(data1);
|
|
+ const int page_size = getpagesize();
|
|
+ char *data1 = static_cast<char*>(malloc(2 * page_size));
|
|
+ EXPECT_TRUE(data1 != NULL);
|
|
+ size_t data1_size = (2 * page_size);
|
|
for (size_t i = 0; i < data1_size; ++i) {
|
|
data1[i] = i & 0x7f;
|
|
}
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/common/memory_allocator_unittest.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/common/memory_allocator_unittest.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/common/memory_allocator_unittest.cc
|
|
@@ -60,8 +60,9 @@ TEST(PageAllocatorTest, LargeObject) {
|
|
|
|
EXPECT_EQ(0U, allocator.pages_allocated());
|
|
uint8_t* p = reinterpret_cast<uint8_t*>(allocator.Alloc(10000));
|
|
+ uint64_t expected_pages = 1 + ((10000 - 1) / getpagesize());
|
|
ASSERT_FALSE(p == NULL);
|
|
- EXPECT_EQ(3U, allocator.pages_allocated());
|
|
+ EXPECT_EQ(expected_pages, allocator.pages_allocated());
|
|
for (unsigned i = 1; i < 10; ++i) {
|
|
uint8_t* p = reinterpret_cast<uint8_t*>(allocator.Alloc(i));
|
|
ASSERT_FALSE(p == NULL);
|
|
Index: chromium-127.0.6533.72/third_party/breakpad/breakpad/src/tools/linux/md2core/minidump-2-core.cc
|
|
===================================================================
|
|
--- chromium-127.0.6533.72.orig/third_party/breakpad/breakpad/src/tools/linux/md2core/minidump-2-core.cc
|
|
+++ chromium-127.0.6533.72/third_party/breakpad/breakpad/src/tools/linux/md2core/minidump-2-core.cc
|
|
@@ -82,6 +82,8 @@
|
|
#define ELF_ARCH EM_AARCH64
|
|
#elif defined(__riscv)
|
|
#define ELF_ARCH EM_RISCV
|
|
+#elif defined(__powerpc64__)
|
|
+ #define ELF_ARCH EM_PPC64
|
|
#endif
|
|
|
|
#if defined(__arm__)
|
|
@@ -92,6 +94,8 @@ typedef user_regs user_regs_struct;
|
|
#elif defined (__mips__) || defined(__riscv)
|
|
// This file-local typedef simplifies the source code.
|
|
typedef gregset_t user_regs_struct;
|
|
+#elif defined(__powerpc64__)
|
|
+typedef struct pt_regs user_regs_struct;
|
|
#endif
|
|
|
|
using google_breakpad::MDTypeHelper;
|
|
@@ -324,6 +328,9 @@ struct CrashedProcess {
|
|
#if defined(__aarch64__)
|
|
user_fpsimd_struct fpregs;
|
|
#endif
|
|
+#if defined(__powerpc64__)
|
|
+ mcontext_t mcontext;
|
|
+#endif
|
|
uintptr_t stack_addr;
|
|
const uint8_t* stack;
|
|
size_t stack_length;
|
|
@@ -599,6 +606,38 @@ ParseThreadRegisters(CrashedProcess::Thr
|
|
#error "Unexpected __riscv_xlen"
|
|
#endif
|
|
}
|
|
+#elif defined(__powerpc64__)
|
|
+static void
|
|
+ParseThreadRegisters(CrashedProcess::Thread* thread,
|
|
+ const MinidumpMemoryRange& range) {
|
|
+ const MDRawContextPPC64* rawregs = range.GetData<MDRawContextPPC64>(0);
|
|
+
|
|
+ for (int i = 0; i < MD_CONTEXT_PPC64_GPR_COUNT; i++)
|
|
+ thread->mcontext.gp_regs[i] = rawregs->gpr[i];
|
|
+
|
|
+ thread->mcontext.gp_regs[PT_LNK] = rawregs->lr;
|
|
+ thread->mcontext.gp_regs[PT_NIP] = rawregs->srr0;
|
|
+ thread->mcontext.gp_regs[PT_MSR] = rawregs->srr1;
|
|
+ thread->mcontext.gp_regs[PT_CCR] = rawregs->cr;
|
|
+ thread->mcontext.gp_regs[PT_XER] = rawregs->xer;
|
|
+ thread->mcontext.gp_regs[PT_CTR] = rawregs->ctr;
|
|
+ thread->mcontext.v_regs->vrsave = rawregs->vrsave;
|
|
+
|
|
+ for (int i = 0; i < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; i++)
|
|
+ thread->mcontext.fp_regs[i] = rawregs->float_save.fpregs[i];
|
|
+
|
|
+ thread->mcontext.fp_regs[NFPREG-1] = rawregs->float_save.fpscr;
|
|
+
|
|
+ for (int i = 0; i < MD_VECTORSAVEAREA_PPC_VR_COUNT; i++) {
|
|
+ thread->mcontext.v_regs->vrregs[i][0] = rawregs->vector_save.save_vr[i].high >> 32;
|
|
+ thread->mcontext.v_regs->vrregs[i][1] = rawregs->vector_save.save_vr[i].high;
|
|
+ thread->mcontext.v_regs->vrregs[i][2] = rawregs->vector_save.save_vr[i].low >> 32;
|
|
+ thread->mcontext.v_regs->vrregs[i][3] = rawregs->vector_save.save_vr[i].low;
|
|
+ }
|
|
+
|
|
+ thread->mcontext.v_regs->vscr.vscr_word = rawregs->vector_save.save_vscr.low & 0xFFFFFFFF;
|
|
+}
|
|
+
|
|
#else
|
|
#error "This code has not been ported to your platform yet"
|
|
#endif
|
|
@@ -704,6 +743,12 @@ ParseSystemInfo(const Options& options,
|
|
# else
|
|
# error "Unexpected __riscv_xlen"
|
|
# endif
|
|
+#elif defined(__powerpc64__)
|
|
+ if (sysinfo->processor_architecture != MD_CPU_ARCHITECTURE_PPC64) {
|
|
+ fprintf(stderr,
|
|
+ "This version of minidump-2-core only supports PPC64.\n");
|
|
+ exit(1);
|
|
+ }
|
|
#else
|
|
#error "This code has not been ported to your platform yet"
|
|
#endif
|