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.
chromium/0001-Implement-support-for-...

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 = &regs;
@@ -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