void-packages/srcpkgs/electron9/files/patches/chromium-xxx-ppc64le.patch
2020-09-13 14:31:43 +02:00

3737 lines
148 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From e39b85b047c69bab8249346125a84bde98b31294 Mon Sep 17 00:00:00 2001
From: Daniel Kolesa <daniel@octaforge.org>
Date: Sun, 13 Sep 2020 00:08:43 +0200
Subject: [PATCH] ppc64le support
---
build/download_nacl_toolchains.py | 4 +
chrome/installer/linux/BUILD.gn | 3 -
sandbox/features.gni | 3 +-
sandbox/linux/BUILD.gn | 2 +
sandbox/linux/bpf_dsl/linux_syscall_ranges.h | 7 +
sandbox/linux/bpf_dsl/seccomp_macros.h | 48 ++++
.../seccomp-bpf-helpers/baseline_policy.cc | 10 +-
.../baseline_policy_unittest.cc | 2 +
.../syscall_parameters_restrictions.cc | 36 ++-
.../syscall_parameters_restrictions.h | 2 +-
.../linux/seccomp-bpf-helpers/syscall_sets.cc | 139 +++++++-----
.../linux/seccomp-bpf-helpers/syscall_sets.h | 10 +-
sandbox/linux/seccomp-bpf/syscall.cc | 62 ++++-
sandbox/linux/seccomp-bpf/trap.cc | 14 ++
sandbox/linux/services/credentials.cc | 2 +-
sandbox/linux/services/syscall_wrappers.cc | 2 +-
.../linux/syscall_broker/broker_process.cc | 2 +-
sandbox/linux/system_headers/linux_seccomp.h | 9 +
sandbox/linux/system_headers/linux_signal.h | 2 +-
sandbox/linux/system_headers/linux_syscalls.h | 4 +
sandbox/linux/system_headers/linux_ucontext.h | 2 +
.../system_headers/ppc64_linux_syscalls.h | 12 +
.../system_headers/ppc64_linux_ucontext.h | 12 +
.../linux/bpf_renderer_policy_linux.cc | 5 +
.../angle/src/compiler/translator/InfoSink.h | 11 +-
third_party/angle/src/libANGLE/Constants.h | 1 +
third_party/boringssl/BUILD.gn | 7 +
.../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 +
.../client/linux/handler/exception_handler.cc | 22 +-
.../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/processor/exploitability_linux.cc | 2 +
.../src/processor/exploitability_unittest.cc | 15 +-
.../tools/linux/md2core/minidump-2-core.cc | 45 ++++
third_party/crashpad/crashpad/CONTRIBUTORS | 1 +
.../crashpad/crashpad/compat/linux/sys/user.h | 1 +
.../crashpad/minidump/minidump_context.h | 64 ++++++
.../minidump/minidump_context_writer.cc | 50 +++++
.../minidump/minidump_context_writer.h | 39 ++++
.../minidump/minidump_context_writer_test.cc | 15 ++
.../minidump/minidump_misc_info_writer.cc | 2 +
.../crashpad/snapshot/capture_memory.cc | 5 +
.../crashpad/snapshot/cpu_architecture.h | 5 +-
.../crashpad/crashpad/snapshot/cpu_context.cc | 5 +
.../crashpad/crashpad/snapshot/cpu_context.h | 19 ++
.../snapshot/linux/cpu_context_linux.h | 73 ++++++
.../snapshot/linux/debug_rendezvous_test.cc | 4 +-
.../linux/exception_snapshot_linux.cc | 63 ++++++
.../snapshot/linux/exception_snapshot_linux.h | 2 +
.../linux/exception_snapshot_linux_test.cc | 21 ++
.../snapshot/linux/process_reader_linux.cc | 2 +
.../linux/process_reader_linux_test.cc | 2 +
.../crashpad/snapshot/linux/signal_context.h | 83 +++++++
.../snapshot/linux/system_snapshot_linux.cc | 11 +
.../snapshot/linux/thread_snapshot_linux.cc | 8 +
.../snapshot/linux/thread_snapshot_linux.h | 2 +
.../crashpad/util/linux/auxiliary_vector.cc | 5 +
.../crashpad/util/linux/ptrace_broker.cc | 4 +-
.../crashpad/crashpad/util/linux/ptracer.cc | 61 +++++
.../crashpad/util/linux/thread_info.h | 55 +++++
.../crashpad/util/misc/capture_context.h | 1 +
.../util/misc/capture_context_linux.S | 212 +++++++++++++++++-
.../util/misc/capture_context_test.cc | 2 +-
.../misc/capture_context_test_util_linux.cc | 6 +
.../crashpad/util/posix/signals_test.cc | 12 +-
third_party/dav1d/BUILD.gn | 21 ++
third_party/dav1d/config/linux/ppc64/config.h | 35 +++
third_party/dav1d/dav1d_generated.gni | 5 +
third_party/dav1d/generate_source.py | 3 +-
third_party/dav1d/libdav1d/src/ppc/types.h | 15 ++
third_party/libvpx/BUILD.gn | 4 +
third_party/lss/linux_syscall_support.h | 4 +-
third_party/pffft/src/pffft.c | 1 +
third_party/skia/src/sksl/SkSLString.cpp | 7 +-
third_party/sqlite/src/amalgamation/sqlite3.c | 3 +-
.../sqlite/src/amalgamation_dev/sqlite3.c | 3 +-
third_party/sqlite/src/ext/rtree/rtree.c | 2 +-
third_party/sqlite/src/src/sqliteInt.h | 3 +-
.../modules/desktop_capture/differ_block.cc | 10 +-
third_party/webrtc/rtc_base/system/arch.h | 12 +
ui/gl/BUILD.gn | 3 +-
v8/BUILD.gn | 6 +
v8/test/BUILD.gn | 6 +-
100 files changed, 1566 insertions(+), 138 deletions(-)
create mode 100644 sandbox/linux/system_headers/ppc64_linux_syscalls.h
create mode 100644 sandbox/linux/system_headers/ppc64_linux_ucontext.h
create mode 100644 third_party/dav1d/config/linux/ppc64/config.h
diff --git a/build/download_nacl_toolchains.py b/build/download_nacl_toolchains.py
index 286a92a27e..ec36a85d31 100755
--- a/build/download_nacl_toolchains.py
+++ b/build/download_nacl_toolchains.py
@@ -13,6 +13,10 @@ import sys
def Main(args):
+ # If `disable_nacl=1` is in GYP_DEFINES, exit
+ if 'disable_nacl=1' in os.environ.get('GYP_DEFINES', ''):
+ return 0
+
script_dir = os.path.dirname(os.path.abspath(__file__))
src_dir = os.path.dirname(script_dir)
nacl_dir = os.path.join(src_dir, 'native_client')
diff --git a/chrome/installer/linux/BUILD.gn b/chrome/installer/linux/BUILD.gn
index 9c92012ce3..a4a5cd86d6 100644
--- a/chrome/installer/linux/BUILD.gn
+++ b/chrome/installer/linux/BUILD.gn
@@ -65,8 +65,6 @@ packaging_files = packaging_files_binaries + [
"$root_out_dir/xdg-mime",
"$root_out_dir/xdg-settings",
"$root_out_dir/locales/en-US.pak",
- "$root_out_dir/MEIPreload/manifest.json",
- "$root_out_dir/MEIPreload/preloaded_data.pb",
]
action_foreach("calculate_deb_dependencies") {
@@ -331,7 +329,6 @@ group("installer_deps") {
":theme_files",
"//chrome",
"//chrome:packed_resources",
- "//chrome/browser/resources/media/mei_preload:component",
"//sandbox/linux:chrome_sandbox",
"//third_party/crashpad/crashpad/handler:crashpad_handler",
]
diff --git a/sandbox/features.gni b/sandbox/features.gni
index 09280d35f6..42514157fc 100644
--- a/sandbox/features.gni
+++ b/sandbox/features.gni
@@ -11,6 +11,7 @@ import("//build/config/nacl/config.gni")
use_seccomp_bpf = (is_linux || is_android) &&
(current_cpu == "x86" || current_cpu == "x64" ||
current_cpu == "arm" || current_cpu == "arm64" ||
- current_cpu == "mipsel" || current_cpu == "mips64el")
+ current_cpu == "mipsel" || current_cpu == "mips64el" ||
+ current_cpu == "ppc64")
use_seccomp_bpf = use_seccomp_bpf || is_nacl_nonsfi
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn
index c27351f9a6..9141e12394 100644
--- a/sandbox/linux/BUILD.gn
+++ b/sandbox/linux/BUILD.gn
@@ -407,6 +407,8 @@ component("sandbox_services") {
source_set("sandbox_services_headers") {
sources = [
+ "system_headers/ppc64_linux_syscalls.h",
+ "system_headers/ppc64_linux_ucontext.h",
"system_headers/arm64_linux_syscalls.h",
"system_headers/arm_linux_syscalls.h",
"system_headers/arm_linux_ucontext.h",
diff --git a/sandbox/linux/bpf_dsl/linux_syscall_ranges.h b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
index 313511f22e..0ca3a326f7 100644
--- a/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
+++ b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
@@ -56,6 +56,13 @@
#define MAX_PUBLIC_SYSCALL __NR_syscalls
#define MAX_SYSCALL MAX_PUBLIC_SYSCALL
+#elif defined(__powerpc64__)
+
+#include <asm/unistd.h>
+#define MIN_SYSCALL 0u
+#define MAX_PUBLIC_SYSCALL 386u
+#define MAX_SYSCALL MAX_PUBLIC_SYSCALL
+
#else
#error "Unsupported architecture"
#endif
diff --git a/sandbox/linux/bpf_dsl/seccomp_macros.h b/sandbox/linux/bpf_dsl/seccomp_macros.h
index 1a407b9523..a6aec544e0 100644
--- a/sandbox/linux/bpf_dsl/seccomp_macros.h
+++ b/sandbox/linux/bpf_dsl/seccomp_macros.h
@@ -16,6 +16,9 @@
#if defined(__mips__)
// sys/user.h in eglibc misses size_t definition
#include <stddef.h>
+#elif defined(__powerpc64__)
+// Manually define greg_t on ppc64
+typedef unsigned long long greg_t;
#endif
#endif
@@ -346,6 +349,51 @@ struct regs_struct {
#define SECCOMP_PT_PARM4(_regs) (_regs).regs[3]
#define SECCOMP_PT_PARM5(_regs) (_regs).regs[4]
#define SECCOMP_PT_PARM6(_regs) (_regs).regs[5]
+
+#elif defined(__powerpc64__)
+#include <asm/ptrace.h>
+
+typedef struct pt_regs regs_struct;
+
+#ifdef ARCH_CPU_LITTLE_ENDIAN
+#define SECCOMP_ARCH AUDIT_ARCH_PPC64LE
+#else
+#define SECCOMP_ARCH AUDIT_ARCH_PPC64
+#endif
+
+#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.regs->gpr[_reg])
+
+#define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, 3)
+#define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, 0)
+#define SECCOMP_IP(_ctx) (_ctx)->uc_mcontext.regs->nip
+#define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, 3)
+#define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, 4)
+#define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, 5)
+#define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, 6)
+#define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, 7)
+#define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, 8)
+
+#define SECCOMP_NR_IDX (offsetof(struct arch_seccomp_data, nr))
+#define SECCOMP_ARCH_IDX (offsetof(struct arch_seccomp_data, arch))
+#define SECCOMP_IP_MSB_IDX \
+ (offsetof(struct arch_seccomp_data, instruction_pointer) + 4)
+#define SECCOMP_IP_LSB_IDX \
+ (offsetof(struct arch_seccomp_data, instruction_pointer) + 0)
+#define SECCOMP_ARG_MSB_IDX(nr) \
+ (offsetof(struct arch_seccomp_data, args) + 8 * (nr) + 4)
+#define SECCOMP_ARG_LSB_IDX(nr) \
+ (offsetof(struct arch_seccomp_data, args) + 8 * (nr) + 0)
+
+#define SECCOMP_PT_RESULT(_regs) (_regs).gpr[3]
+#define SECCOMP_PT_SYSCALL(_regs) (_regs).gpr[0]
+#define SECCOMP_PT_IP(_regs) (_regs).nip
+#define SECCOMP_PT_PARM1(_regs) (_regs).gpr[3]
+#define SECCOMP_PT_PARM2(_regs) (_regs).gpr[4]
+#define SECCOMP_PT_PARM3(_regs) (_regs).gpr[5]
+#define SECCOMP_PT_PARM4(_regs) (_regs).gpr[6]
+#define SECCOMP_PT_PARM5(_regs) (_regs).gpr[7]
+#define SECCOMP_PT_PARM6(_regs) (_regs).gpr[8]
+
#else
#error Unsupported target platform
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
index 712f9699a9..55f062817e 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
@@ -88,7 +88,8 @@ bool IsBaselinePolicyWatched(int sysno) {
SyscallSets::IsPrctl(sysno) ||
SyscallSets::IsProcessGroupOrSession(sysno) ||
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
SyscallSets::IsSocketCall(sysno) ||
#endif
#if defined(__arm__)
@@ -210,7 +211,7 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno,
}
#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
- defined(__aarch64__)
+ defined(__aarch64__) || defined(__powerpc64__)
if (sysno == __NR_mmap)
return RestrictMmapFlags();
#endif
@@ -228,7 +229,7 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno,
return RestrictPrctl();
#if defined(__x86_64__) || defined(__arm__) || defined(__mips__) || \
- defined(__aarch64__)
+ defined(__aarch64__) || defined(__powerpc64__)
if (sysno == __NR_socketpair) {
// Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen.
static_assert(AF_UNIX == PF_UNIX,
@@ -268,7 +269,8 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno,
}
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
if (SyscallSets::IsSocketCall(sysno))
return RestrictSocketcallCommand();
#endif
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
index fc36187c94..1affc91897 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
@@ -291,8 +291,10 @@ TEST_BASELINE_SIGSYS(__NR_timer_create)
#if !defined(__aarch64__)
TEST_BASELINE_SIGSYS(__NR_eventfd)
TEST_BASELINE_SIGSYS(__NR_inotify_init)
+#if !defined(__powerpc64__)
TEST_BASELINE_SIGSYS(__NR_vserver)
#endif
+#endif
#if defined(LIBC_GLIBC) && !defined(OS_CHROMEOS)
BPF_TEST_C(BaselinePolicy, FutexEINVAL, BaselinePolicy) {
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index ff5a1c093c..7faa07c9a7 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -36,7 +36,8 @@
#include <sys/ioctl.h>
#include <sys/ptrace.h>
#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && !defined(__arm__) && \
- !defined(__aarch64__) && !defined(PTRACE_GET_THREAD_AREA)
+ !defined(__aarch64__) && !defined(PTRACE_GET_THREAD_AREA) && \
+ !defined(__powerpc64__)
// Also include asm/ptrace-abi.h since ptrace.h in older libc (for instance
// the one in Ubuntu 16.04 LTS) is missing PTRACE_GET_THREAD_AREA.
// asm/ptrace-abi.h doesn't exist on arm32 and PTRACE_GET_THREAD_AREA isn't
@@ -45,6 +46,11 @@
#endif
#endif // !OS_NACL_NONSFI
+// On PPC64, TCGETS is defined in terms of struct termios, so we must include termios.h
+#ifdef __powerpc64__
+#include <termios.h>
+#endif
+
#if defined(OS_ANDROID)
#if !defined(F_DUPFD_CLOEXEC)
@@ -107,6 +113,15 @@ inline bool IsArchitectureMips() {
#endif
}
+inline bool IsArchitecturePPC64() {
+#if defined(__powerpc64__)
+ return true;
+#else
+ return false;
+#endif
+}
+
+
// Ubuntu's version of glibc has a race condition in sem_post that can cause
// it to call futex(2) with bogus op arguments. To workaround this, we need
// to allow those futex(2) calls to fail with EINVAL, instead of crashing the
@@ -248,6 +263,8 @@ ResultExpr RestrictFcntlCommands() {
uint64_t kOLargeFileFlag = O_LARGEFILE;
if (IsArchitectureX86_64() || IsArchitectureI386() || IsArchitectureMips())
kOLargeFileFlag = 0100000;
+ else if (IsArchitecturePPC64())
+ kOLargeFileFlag = 0200000;
const Arg<int> cmd(1);
const Arg<long> long_arg(2);
@@ -262,14 +279,23 @@ ResultExpr RestrictFcntlCommands() {
F_SETLKW,
F_GETLK,
F_DUPFD,
- F_DUPFD_CLOEXEC),
- Allow())
+ F_DUPFD_CLOEXEC
+#if defined(__powerpc64__)
+// On PPC64, F_SETLK, F_GETLK, F_SETLKW are defined as the 64-bit variants
+// but glibc will sometimes still use the 32-bit versions. Allow both.
+ ,
+ 5, /* F_GETLK (32) */
+ 6, /* F_SETLK (32) */
+ 7 /* F_SETLKW (32) */
+#endif
+ ),
+ Allow())
.Case(F_SETFL,
If((long_arg & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS()))
.Default(CrashSIGSYS());
}
-#if defined(__i386__) || defined(__mips__)
+#if defined(__i386__) || defined(__mips__) || defined(__powerpc64__)
ResultExpr RestrictSocketcallCommand() {
// Unfortunately, we are unable to restrict the first parameter to
// socketpair(2). Whilst initially sounding bad, it's noteworthy that very
@@ -418,7 +444,7 @@ ResultExpr RestrictPrlimitToGetrlimit(pid_t target_pid) {
ResultExpr RestrictPtrace() {
const Arg<int> request(0);
return Switch(request).CASES((
-#if !defined(__aarch64__)
+#if !defined(__aarch64__) && !defined(__powerpc64__)
PTRACE_GETREGS,
PTRACE_GETFPREGS,
PTRACE_GET_THREAD_AREA,
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
index ba4289f05b..9a4d5ab2db 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
@@ -48,7 +48,7 @@ SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictMprotectFlags();
// O_NONBLOCK | O_SYNC | O_LARGEFILE | O_CLOEXEC | O_NOATIME.
SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictFcntlCommands();
-#if defined(__i386__) || defined(__mips__)
+#if defined(__i386__) || defined(__mips__) || defined(__powerpc64__)
// Restrict socketcall(2) to only allow socketpair(2), send(2), recv(2),
// sendto(2), recvfrom(2), shutdown(2), sendmsg(2) and recvmsg(2).
SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictSocketcallCommand();
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
index d9d18822f6..1acd39d30e 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
@@ -29,7 +29,8 @@ bool SyscallSets::IsAllowedGettime(int sysno) {
switch (sysno) {
case __NR_gettimeofday:
#if defined(__i386__) || defined(__x86_64__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_time:
#endif
return true;
@@ -41,12 +42,14 @@ bool SyscallSets::IsAllowedGettime(int sysno) {
case __NR_clock_nanosleep: // Parameters filtered by RestrictClockID().
case __NR_clock_settime: // Privileged.
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_ftime: // Obsolete.
#endif
case __NR_settimeofday: // Privileged.
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_stime:
#endif
default:
@@ -112,7 +115,7 @@ bool SyscallSets::IsFileSystem(int sysno) {
case __NR_faccessat: // EPERM not a valid errno.
case __NR_fchmodat:
case __NR_fchownat: // Should be called chownat ?
-#if defined(__x86_64__) || defined(__aarch64__)
+#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__)
case __NR_newfstatat: // fstatat(). EPERM not a valid errno.
#elif defined(__i386__) || defined(__arm__) || \
(defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
@@ -131,7 +134,7 @@ bool SyscallSets::IsFileSystem(int sysno) {
case __NR_memfd_create:
case __NR_mkdirat:
case __NR_mknodat:
-#if defined(__i386__)
+#if defined(__i386__) || defined(__powerpc64__)
case __NR_oldlstat:
case __NR_oldstat:
#endif
@@ -145,7 +148,8 @@ bool SyscallSets::IsFileSystem(int sysno) {
#endif
case __NR_statfs: // EPERM not a valid errno.
#if defined(__i386__) || defined(__arm__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_statfs64:
#endif
case __NR_symlinkat:
@@ -155,7 +159,8 @@ bool SyscallSets::IsFileSystem(int sysno) {
case __NR_truncate64:
#endif
case __NR_unlinkat:
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
+ defined(__powerpc64__)
case __NR_utime:
#endif
case __NR_utimensat: // New.
@@ -174,7 +179,8 @@ bool SyscallSets::IsAllowedFileSystemAccessViaFd(int sysno) {
#endif
return true;
// TODO(jln): these should be denied gracefully as well (moved below).
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
+ defined(__powerpc64__)
case __NR_fadvise64: // EPERM not a valid errno.
#endif
#if defined(__i386__)
@@ -187,11 +193,12 @@ bool SyscallSets::IsAllowedFileSystemAccessViaFd(int sysno) {
case __NR_flock: // EPERM not a valid errno.
case __NR_fstatfs: // Give information about the whole filesystem.
#if defined(__i386__) || defined(__arm__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_fstatfs64:
#endif
case __NR_fsync: // EPERM not a valid errno.
-#if defined(__i386__)
+#if defined(__i386__) || defined(__powerpc64__)
case __NR_oldfstat:
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
@@ -199,6 +206,8 @@ bool SyscallSets::IsAllowedFileSystemAccessViaFd(int sysno) {
case __NR_sync_file_range: // EPERM not a valid errno.
#elif defined(__arm__)
case __NR_arm_sync_file_range: // EPERM not a valid errno.
+#elif defined(__powerpc64__)
+ case __NR_sync_file_range2: // EPERM not a valid errno.
#endif
default:
return false;
@@ -224,7 +233,8 @@ bool SyscallSets::IsDeniedFileSystemAccessViaFd(int sysno) {
#endif
case __NR_getdents64: // EPERM not a valid errno.
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_readdir:
#endif
return true;
@@ -265,7 +275,7 @@ bool SyscallSets::IsGetSimpleId(int sysno) {
bool SyscallSets::IsProcessPrivilegeChange(int sysno) {
switch (sysno) {
case __NR_capset:
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc64__)
case __NR_ioperm: // Intel privilege.
case __NR_iopl: // Intel privilege.
#endif
@@ -316,7 +326,8 @@ bool SyscallSets::IsAllowedSignalHandling(int sysno) {
case __NR_rt_sigreturn:
case __NR_rt_sigtimedwait:
#if defined(__i386__) || defined(__arm__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_sigaction:
case __NR_sigprocmask:
case __NR_sigreturn:
@@ -332,7 +343,8 @@ bool SyscallSets::IsAllowedSignalHandling(int sysno) {
#endif
case __NR_signalfd4:
#if defined(__i386__) || defined(__arm__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_sigpending:
case __NR_sigsuspend:
#endif
@@ -356,7 +368,7 @@ bool SyscallSets::IsAllowedOperationOnFd(int sysno) {
#endif
case __NR_dup3:
#if defined(__x86_64__) || defined(__arm__) || defined(__mips__) || \
- defined(__aarch64__)
+ defined(__aarch64__) || defined(__powerpc64__)
case __NR_shutdown:
#endif
return true;
@@ -389,7 +401,7 @@ bool SyscallSets::IsAllowedProcessStartOrDeath(int sysno) {
case __NR_exit_group:
case __NR_wait4:
case __NR_waitid:
-#if defined(__i386__)
+#if defined(__i386__) || defined(__powerpc64__)
case __NR_waitpid:
#endif
return true;
@@ -406,7 +418,7 @@ bool SyscallSets::IsAllowedProcessStartOrDeath(int sysno) {
#endif
case __NR_set_tid_address:
case __NR_unshare:
-#if !defined(__mips__) && !defined(__aarch64__)
+#if !defined(__mips__) && !defined(__aarch64__) || defined(__powerpc64__)
case __NR_vfork:
#endif
default:
@@ -455,7 +467,7 @@ bool SyscallSets::IsAllowedGetOrModifySocket(int sysno) {
return true;
default:
#if defined(__x86_64__) || defined(__arm__) || defined(__mips__) || \
- defined(__aarch64__)
+ defined(__aarch64__) || defined(__powerpc64__)
case __NR_socketpair: // We will want to inspect its argument.
#endif
return false;
@@ -465,7 +477,7 @@ bool SyscallSets::IsAllowedGetOrModifySocket(int sysno) {
bool SyscallSets::IsDeniedGetOrModifySocket(int sysno) {
switch (sysno) {
#if defined(__x86_64__) || defined(__arm__) || defined(__mips__) || \
- defined(__aarch64__)
+ defined(__aarch64__) || defined(__powerpc64__)
case __NR_accept:
case __NR_accept4:
case __NR_bind:
@@ -480,7 +492,8 @@ bool SyscallSets::IsDeniedGetOrModifySocket(int sysno) {
}
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
// Big multiplexing system call for sockets.
bool SyscallSets::IsSocketCall(int sysno) {
switch (sysno) {
@@ -494,7 +507,8 @@ bool SyscallSets::IsSocketCall(int sysno) {
}
#endif
-#if defined(__x86_64__) || defined(__arm__) || defined(__mips__)
+#if defined(__x86_64__) || defined(__arm__) || defined(__mips__) || \
+ defined(__powerpc64__)
bool SyscallSets::IsNetworkSocketInformation(int sysno) {
switch (sysno) {
case __NR_getpeername:
@@ -519,7 +533,7 @@ bool SyscallSets::IsAllowedAddressSpaceAccess(int sysno) {
case __NR_mincore:
case __NR_mlockall:
#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
- defined(__aarch64__)
+ defined(__aarch64__) || defined(__powerpc64__)
case __NR_mmap:
#endif
#if defined(__i386__) || defined(__arm__) || \
@@ -549,7 +563,8 @@ bool SyscallSets::IsAllowedGeneralIo(int sysno) {
switch (sysno) {
case __NR_lseek:
#if defined(__i386__) || defined(__arm__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR__llseek:
#endif
#if !defined(__aarch64__)
@@ -561,26 +576,28 @@ bool SyscallSets::IsAllowedGeneralIo(int sysno) {
case __NR_readv:
case __NR_pread64:
#if defined(__arm__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_recv:
#endif
#if defined(__x86_64__) || defined(__arm__) || defined(__mips__) || \
- defined(__aarch64__)
+ defined(__aarch64__) || defined(__powerpc64__)
case __NR_recvfrom: // Could specify source.
case __NR_recvmsg: // Could specify source.
#endif
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc64__)
case __NR_select:
#endif
-#if defined(__i386__) || defined(__arm__) || defined(__mips__)
+#if defined(__i386__) || defined(__arm__) || defined(__mips__) || defined(__powerpc64__)
case __NR__newselect:
#endif
#if defined(__arm__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_send:
#endif
#if defined(__x86_64__) || defined(__arm__) || defined(__mips__) || \
- defined(__aarch64__)
+ defined(__aarch64__) || defined(__powerpc64__)
case __NR_sendmsg: // Could specify destination.
case __NR_sendto: // Could specify destination.
#endif
@@ -637,7 +654,8 @@ bool SyscallSets::IsAllowedBasicScheduler(int sysno) {
return true;
case __NR_getpriority:
#if defined(__i386__) || defined(__arm__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_nice:
#endif
case __NR_setpriority:
@@ -649,7 +667,8 @@ bool SyscallSets::IsAllowedBasicScheduler(int sysno) {
bool SyscallSets::IsAdminOperation(int sysno) {
switch (sysno) {
#if defined(__i386__) || defined(__arm__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_bdflush:
#endif
case __NR_kexec_load:
@@ -665,7 +684,8 @@ bool SyscallSets::IsAdminOperation(int sysno) {
bool SyscallSets::IsKernelModule(int sysno) {
switch (sysno) {
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
+ defined(__powerpc64__)
case __NR_create_module:
case __NR_get_kernel_syms: // Should ENOSYS.
case __NR_query_module:
@@ -698,7 +718,8 @@ bool SyscallSets::IsFsControl(int sysno) {
case __NR_swapoff:
case __NR_swapon:
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_umount:
#endif
case __NR_umount2:
@@ -714,7 +735,7 @@ bool SyscallSets::IsNuma(int sysno) {
case __NR_getcpu:
case __NR_mbind:
#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
- defined(__aarch64__)
+ defined(__aarch64__) || defined(__powerpc64__)
case __NR_migrate_pages:
#endif
case __NR_move_pages:
@@ -743,14 +764,15 @@ bool SyscallSets::IsGlobalProcessEnvironment(int sysno) {
switch (sysno) {
case __NR_acct: // Privileged.
#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
- defined(__aarch64__)
+ defined(__aarch64__) || defined(__powerpc64__)
case __NR_getrlimit:
#endif
-#if defined(__i386__) || defined(__arm__)
+#if defined(__i386__) || defined(__arm__) || defined(__powerpc64__)
case __NR_ugetrlimit:
#endif
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_ulimit:
#endif
case __NR_getrusage:
@@ -784,7 +806,7 @@ bool SyscallSets::IsGlobalSystemStatus(int sysno) {
#endif
case __NR_sysinfo:
case __NR_uname:
-#if defined(__i386__)
+#if defined(__i386__) || defined(__powerpc64__)
case __NR_olduname:
case __NR_oldolduname:
#endif
@@ -846,8 +868,16 @@ bool SyscallSets::IsSystemVSemaphores(int sysno) {
}
#endif
+/* shitty hack around Void's 4.19 kernel headers missing those numbers */
+#if defined(__powerpc64__) && !defined(__NR_shmget)
+#define __NR_shmget 395
+#define __NR_shmctl 396
+#define __NR_shmat 397
+#define __NR_shmdt 398
+#endif
+
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \
- defined(__aarch64__) || \
+ defined(__aarch64__) || defined(__powerpc64__) || \
(defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_64_BITS))
// These give a lot of ambient authority and bypass the setuid sandbox.
bool SyscallSets::IsSystemVSharedMemory(int sysno) {
@@ -879,7 +909,8 @@ bool SyscallSets::IsSystemVMessageQueue(int sysno) {
#endif
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
// Big system V multiplexing system call.
bool SyscallSets::IsSystemVIpc(int sysno) {
switch (sysno) {
@@ -899,7 +930,8 @@ bool SyscallSets::IsAnySystemV(int sysno) {
return IsSystemVMessageQueue(sysno) || IsSystemVSemaphores(sysno) ||
IsSystemVSharedMemory(sysno);
#elif defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
return IsSystemVIpc(sysno);
#endif
}
@@ -952,7 +984,8 @@ bool SyscallSets::IsFaNotify(int sysno) {
bool SyscallSets::IsTimer(int sysno) {
switch (sysno) {
case __NR_getitimer:
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
+ defined(__powerpc64__)
case __NR_alarm:
#endif
case __NR_setitimer:
@@ -1011,18 +1044,22 @@ bool SyscallSets::IsMisc(int sysno) {
case __NR_syncfs:
case __NR_vhangup:
// The system calls below are not implemented.
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
+ defined(__powerpc64__)
case __NR_afs_syscall:
#endif
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_break:
#endif
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
+ defined(__powerpc64__)
case __NR_getpmsg:
#endif
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_gtty:
case __NR_idle:
case __NR_lock:
@@ -1030,20 +1067,22 @@ bool SyscallSets::IsMisc(int sysno) {
case __NR_prof:
case __NR_profil:
#endif
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
+ defined(__powerpc64__)
case __NR_putpmsg:
#endif
#if defined(__x86_64__)
case __NR_security:
#endif
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
case __NR_stty:
#endif
-#if defined(__x86_64__)
+#if defined(__x86_64__) || defined(__powerpc64__)
case __NR_tuxcall:
#endif
-#if !defined(__aarch64__)
+#if !defined(__aarch64__) && !defined(__powerpc64__)
case __NR_vserver:
#endif
return true;
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
index 923533ec9f..411f72acdb 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
@@ -43,13 +43,14 @@ class SANDBOX_EXPORT SyscallSets {
static bool IsDeniedGetOrModifySocket(int sysno);
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
// Big multiplexing system call for sockets.
static bool IsSocketCall(int sysno);
#endif
#if defined(__x86_64__) || defined(__arm__) || defined(__mips__) || \
- defined(__aarch64__)
+ defined(__aarch64__) || defined(__powerpc64__)
static bool IsNetworkSocketInformation(int sysno);
#endif
@@ -76,7 +77,7 @@ class SANDBOX_EXPORT SyscallSets {
static bool IsSystemVSemaphores(int sysno);
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \
- defined(__aarch64__) || \
+ defined(__aarch64__) || defined(__powerpc64__) || \
(defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_64_BITS))
// These give a lot of ambient authority and bypass the setuid sandbox.
static bool IsSystemVSharedMemory(int sysno);
@@ -88,7 +89,8 @@ class SANDBOX_EXPORT SyscallSets {
#endif
#if defined(__i386__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
+ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) || \
+ defined(__powerpc64__)
// Big system V multiplexing system call.
static bool IsSystemVIpc(int sysno);
#endif
diff --git a/sandbox/linux/seccomp-bpf/syscall.cc b/sandbox/linux/seccomp-bpf/syscall.cc
index 34edabd2b8..10fa5fd070 100644
--- a/sandbox/linux/seccomp-bpf/syscall.cc
+++ b/sandbox/linux/seccomp-bpf/syscall.cc
@@ -16,7 +16,7 @@ namespace sandbox {
namespace {
#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) || \
- defined(ARCH_CPU_MIPS_FAMILY)
+ defined(ARCH_CPU_MIPS_FAMILY) || defined (ARCH_CPU_PPC64_FAMILY)
// Number that's not currently used by any Linux kernel ABIs.
const int kInvalidSyscallNumber = 0x351d3;
#else
@@ -308,12 +308,56 @@ asm(// We need to be able to tell the kernel exactly where we made a
// Enter the kernel
"svc 0\n"
"2:ret\n"
+ ".cfi_endproc\n"
+ ".size SyscallAsm, .-SyscallAsm\n"
+#elif defined(__powerpc64__)
+ ".text\n"
+ ".align 4\n"
+ ".type SyscallAsm @function\n"
+ "SyscallAsm:\n"
+ ".cfi_startproc\n"
+
+ // Check if r3 is negative
+ "cmpdi 3, 0\n"
+ "bgt 2f\n"
+
+ // Load address of 3f into r3 and return
+ "mflr 10\n"
+ "bl 1f\n"
+ "1: mflr 3\n"
+ "mtlr 10\n"
+ "addi 3, 3, 4*13\n"
+ "blr\n"
+
+ // Load arguments from array into r3-8
+ // save param 3 in r10
+ "2:\n"
+ "mr 0, 3\n"
+ "ld 3, 0(4)\n"
+ "ld 5, 16(4)\n"
+ "ld 6, 24(4)\n"
+ "ld 7, 32(4)\n"
+ "ld 8, 40(4)\n"
+ "ld 4, 8(4)\n"
+ "li 9, 0\n"
+
+ // Enter kernel
+ "sc\n"
+
+ // Magic return address
+ "3:\n"
+ // Like MIPS, ppc64 return values are always positive.
+ // Check for error in cr0.SO and negate upon error
+ "bc 4, 3, 4f\n"
+ "neg 3, 3\n"
+ "4: blr\n"
+
".cfi_endproc\n"
".size SyscallAsm, .-SyscallAsm\n"
#endif
); // asm
-#if defined(__x86_64__)
+#if defined(__x86_64__) || defined(__powerpc64__)
extern "C" {
intptr_t SyscallAsm(intptr_t nr, const intptr_t args[6]);
}
@@ -427,6 +471,8 @@ intptr_t Syscall::Call(int nr,
ret = inout;
}
+#elif defined(__powerpc64__)
+ intptr_t ret = SyscallAsm(nr, args);
#else
#error "Unimplemented architecture"
#endif
@@ -443,8 +489,18 @@ void Syscall::PutValueInUcontext(intptr_t ret_val, ucontext_t* ctx) {
// needs to be changed back.
ret_val = -ret_val;
SECCOMP_PARM4(ctx) = 1;
- } else
+ } else {
SECCOMP_PARM4(ctx) = 0;
+ }
+#endif
+#if defined(__powerpc64__)
+ // Same as MIPS, need to invert ret and set error register (cr0.SO)
+ if (ret_val <= -1 && ret_val >= -4095) {
+ ret_val = -ret_val;
+ ctx->uc_mcontext.regs->ccr |= (1 << 28);
+ } else {
+ ctx->uc_mcontext.regs->ccr &= ~(1 << 28);
+ }
#endif
SECCOMP_RESULT(ctx) = static_cast<greg_t>(ret_val);
}
diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc
index 9884be8bb2..98e4371aac 100644
--- a/sandbox/linux/seccomp-bpf/trap.cc
+++ b/sandbox/linux/seccomp-bpf/trap.cc
@@ -232,6 +232,20 @@ void Trap::SigSys(int nr, LinuxSigInfo* info, ucontext_t* ctx) {
SetIsInSigHandler();
}
+#if defined(__powerpc64__)
+ // On ppc64+glibc, some syscalls seem to accidentally negate the first
+ // parameter which causes checks against it to fail. For now, manually
+ // negate them back.
+ // TODO(shawn@anastas.io): investigate this issue further
+ auto nr = SECCOMP_SYSCALL(ctx);
+ if (nr == __NR_openat || nr == __NR_mkdirat || nr == __NR_faccessat || nr == __NR_readlinkat ||
+ nr == __NR_renameat || nr == __NR_renameat2 || nr == __NR_newfstatat || nr == __NR_unlinkat) {
+ if (static_cast<int>(SECCOMP_PARM1(ctx)) > 0) {
+ SECCOMP_PARM1(ctx) = -SECCOMP_PARM1(ctx);
+ }
+ }
+#endif
+
// Copy the seccomp-specific data into a arch_seccomp_data structure. This
// is what we are showing to TrapFnc callbacks that the system call
// evaluator registered with the sandbox.
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc
index d7b5d8c441..4adc6d0d43 100644
--- a/sandbox/linux/services/credentials.cc
+++ b/sandbox/linux/services/credentials.cc
@@ -81,7 +81,7 @@ bool ChrootToSafeEmptyDir() {
pid_t pid = -1;
alignas(16) char stack_buf[PTHREAD_STACK_MIN];
#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) || \
- defined(ARCH_CPU_MIPS_FAMILY)
+ defined(ARCH_CPU_MIPS_FAMILY) || defined(ARCH_CPU_PPC64_FAMILY)
// The stack grows downward.
void* stack = stack_buf + sizeof(stack_buf);
#else
diff --git a/sandbox/linux/services/syscall_wrappers.cc b/sandbox/linux/services/syscall_wrappers.cc
index fcfd2aa129..f6eb32fb76 100644
--- a/sandbox/linux/services/syscall_wrappers.cc
+++ b/sandbox/linux/services/syscall_wrappers.cc
@@ -58,7 +58,7 @@ long sys_clone(unsigned long flags,
#if defined(ARCH_CPU_X86_64)
return syscall(__NR_clone, flags, child_stack, ptid, ctid, tls);
#elif defined(ARCH_CPU_X86) || defined(ARCH_CPU_ARM_FAMILY) || \
- defined(ARCH_CPU_MIPS_FAMILY)
+ defined(ARCH_CPU_MIPS_FAMILY) || defined(ARCH_CPU_PPC64_FAMILY)
// CONFIG_CLONE_BACKWARDS defined.
return syscall(__NR_clone, flags, child_stack, ptid, tls, ctid);
#endif
diff --git a/sandbox/linux/syscall_broker/broker_process.cc b/sandbox/linux/syscall_broker/broker_process.cc
index 8321d23798..7e5ad1de37 100644
--- a/sandbox/linux/syscall_broker/broker_process.cc
+++ b/sandbox/linux/syscall_broker/broker_process.cc
@@ -157,7 +157,7 @@ bool BrokerProcess::IsSyscallAllowed(int sysno) const {
#if defined(__NR_fstatat)
case __NR_fstatat:
#endif
-#if defined(__x86_64__) || defined(__aarch64__)
+#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__)
case __NR_newfstatat:
#endif
return !fast_check_in_client_ || allowed_command_set_.test(COMMAND_STAT);
diff --git a/sandbox/linux/system_headers/linux_seccomp.h b/sandbox/linux/system_headers/linux_seccomp.h
index a60fe2ad3d..9dccdb51d0 100644
--- a/sandbox/linux/system_headers/linux_seccomp.h
+++ b/sandbox/linux/system_headers/linux_seccomp.h
@@ -29,6 +29,9 @@
#ifndef EM_AARCH64
#define EM_AARCH64 183
#endif
+#ifndef EM_PPC64
+#define EM_PPC64 21
+#endif
#ifndef __AUDIT_ARCH_64BIT
#define __AUDIT_ARCH_64BIT 0x80000000
@@ -54,6 +57,12 @@
#ifndef AUDIT_ARCH_AARCH64
#define AUDIT_ARCH_AARCH64 (EM_AARCH64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
#endif
+#ifndef AUDIT_ARCH_PPC64
+#define AUDIT_ARCH_PPC64 (EM_PPC64 | __AUDIT_ARCH_64BIT)
+#endif
+#ifndef AUDIT_ARCH_PPC64LE
+#define AUDIT_ARCH_PPC64LE (EM_PPC64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
+#endif
// For prctl.h
#ifndef PR_SET_SECCOMP
diff --git a/sandbox/linux/system_headers/linux_signal.h b/sandbox/linux/system_headers/linux_signal.h
index f5a7367617..515b21a5fd 100644
--- a/sandbox/linux/system_headers/linux_signal.h
+++ b/sandbox/linux/system_headers/linux_signal.h
@@ -13,7 +13,7 @@
// (not undefined, but defined different values and in different memory
// layouts). So, fill the gap here.
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \
- defined(__aarch64__)
+ defined(__aarch64__) || defined(__powerpc64__)
#define LINUX_SIGHUP 1
#define LINUX_SIGINT 2
diff --git a/sandbox/linux/system_headers/linux_syscalls.h b/sandbox/linux/system_headers/linux_syscalls.h
index 2b78a0cc3b..0a70f5ea58 100644
--- a/sandbox/linux/system_headers/linux_syscalls.h
+++ b/sandbox/linux/system_headers/linux_syscalls.h
@@ -35,5 +35,9 @@
#include "sandbox/linux/system_headers/arm64_linux_syscalls.h"
#endif
+#if defined(__powerpc64__)
+#include "sandbox/linux/system_headers/ppc64_linux_syscalls.h"
+#endif
+
#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SYSCALLS_H_
diff --git a/sandbox/linux/system_headers/linux_ucontext.h b/sandbox/linux/system_headers/linux_ucontext.h
index 22ce780274..a69b024c2f 100644
--- a/sandbox/linux/system_headers/linux_ucontext.h
+++ b/sandbox/linux/system_headers/linux_ucontext.h
@@ -11,6 +11,8 @@
#include "sandbox/linux/system_headers/arm_linux_ucontext.h"
#elif defined(__i386__)
#include "sandbox/linux/system_headers/i386_linux_ucontext.h"
+#elif defined(__powerpc64__)
+#include "sandbox/linux/system_headers/ppc64_linux_ucontext.h"
#else
#error "No support for your architecture in PNaCl header"
#endif
diff --git a/sandbox/linux/system_headers/ppc64_linux_syscalls.h b/sandbox/linux/system_headers/ppc64_linux_syscalls.h
new file mode 100644
index 0000000000..ccacffe22e
--- /dev/null
+++ b/sandbox/linux/system_headers/ppc64_linux_syscalls.h
@@ -0,0 +1,12 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_PPC64_LINUX_SYSCALLS_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_PPC64_LINUX_SYSCALLS_H_
+
+#include <asm/unistd.h>
+
+//TODO: is it necessary to redefine syscall numbers for PPC64?
+
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_PPC64_LINUX_SYSCALLS_H_
diff --git a/sandbox/linux/system_headers/ppc64_linux_ucontext.h b/sandbox/linux/system_headers/ppc64_linux_ucontext.h
new file mode 100644
index 0000000000..07728e0879
--- /dev/null
+++ b/sandbox/linux/system_headers/ppc64_linux_ucontext.h
@@ -0,0 +1,12 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_PPC64_LINUX_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_PPC64_LINUX_UCONTEXT_H_
+
+#include <sys/ucontext.h>
+
+//TODO: is it necessary to redefine ucontext on PPC64?
+
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_PPC64_LINUX_UCONTEXT_H_
diff --git a/services/service_manager/sandbox/linux/bpf_renderer_policy_linux.cc b/services/service_manager/sandbox/linux/bpf_renderer_policy_linux.cc
index a85c0ea867..00bcd12698 100644
--- a/services/service_manager/sandbox/linux/bpf_renderer_policy_linux.cc
+++ b/services/service_manager/sandbox/linux/bpf_renderer_policy_linux.cc
@@ -15,6 +15,11 @@
#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
+// On PPC64, TCGETS is defined in terms of struct termios, so we must include termios.h
+#ifdef __powerpc64__
+#include <termios.h>
+#endif
+
// TODO(vignatti): replace the local definitions below with #include
// <linux/dma-buf.h> once kernel version 4.6 becomes widely used.
#include <linux/types.h>
diff --git a/third_party/angle/src/compiler/translator/InfoSink.h b/third_party/angle/src/compiler/translator/InfoSink.h
index 3a807e1e3d..5258617a7e 100644
--- a/third_party/angle/src/compiler/translator/InfoSink.h
+++ b/third_party/angle/src/compiler/translator/InfoSink.h
@@ -92,7 +92,16 @@ class TInfoSinkBase
stream.precision(8);
stream << f;
}
- sink.append(stream.str());
+
+ // Hack to work around a bug where negative floating point values
+ // are rendered like '.0.5' instead of '-0.5'
+ std::string res(stream.str());
+
+ if (signbit(f)) { // test if f is negative
+ res[0] = '-';
+ }
+
+ sink.append(res);
return *this;
}
// Write boolean values as their names instead of integral value.
diff --git a/third_party/angle/src/libANGLE/Constants.h b/third_party/angle/src/libANGLE/Constants.h
index 7467899135..9132b3fc0f 100644
--- a/third_party/angle/src/libANGLE/Constants.h
+++ b/third_party/angle/src/libANGLE/Constants.h
@@ -9,6 +9,7 @@
#ifndef LIBANGLE_CONSTANTS_H_
#define LIBANGLE_CONSTANTS_H_
+#include <cstddef>
#include "common/platform.h"
#include <stdint.h>
diff --git a/third_party/boringssl/BUILD.gn b/third_party/boringssl/BUILD.gn
index b435499f45..ac8a84b6db 100644
--- a/third_party/boringssl/BUILD.gn
+++ b/third_party/boringssl/BUILD.gn
@@ -101,6 +101,13 @@ if (is_win && !is_msan && current_cpu != "arm64") {
} else {
public_configs = [ ":no_asm_config" ]
}
+ } else if (current_cpu == "ppc64") {
+ if (is_linux) {
+ # TODO: ppc64 (be) check
+ sources += crypto_sources_linux_ppc64le
+ } else {
+ public_configs = [ ":no_asm_config" ]
+ }
} else {
public_configs = [ ":no_asm_config" ]
}
diff --git a/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/raw_context_cpu.h b/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/raw_context_cpu.h
index 07d9171a0a..9aed4cb369 100644
--- a/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/raw_context_cpu.h
+++ b/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/raw_context_cpu.h
@@ -44,6 +44,8 @@ typedef MDRawContextARM RawContextCPU;
typedef MDRawContextARM64_Old RawContextCPU;
#elif defined(__mips__)
typedef MDRawContextMIPS RawContextCPU;
+#elif defined(__powerpc64__)
+typedef MDRawContextPPC64 RawContextCPU;
#else
#error "This code has not been ported to your platform yet."
#endif
diff --git a/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc b/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
index aae1dc13b2..03afec7a58 100644
--- a/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
+++ b/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
@@ -270,7 +270,42 @@ void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
out->float_save.fir = mcontext.fpc_eir;
#endif
}
-#endif // __mips__
+
+#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);
@@ -279,6 +314,11 @@ void ThreadInfo::GetGeneralPurposeRegisters(void** gp_regs, size_t* size) {
*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;
@@ -294,6 +334,11 @@ void ThreadInfo::GetFloatingPointRegisters(void** fp_regs, size_t* size) {
*fp_regs = &mcontext.fpregs;
if (size)
*size = sizeof(mcontext.fpregs);
+#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;
@@ -302,4 +347,13 @@ void ThreadInfo::GetFloatingPointRegisters(void** fp_regs, size_t* size) {
#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
diff --git a/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.h b/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.h
index fb216fa6d7..593aac8225 100644
--- a/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.h
+++ b/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.h
@@ -68,6 +68,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;
+ vrregset_t vregs;
#elif defined(__mips__)
// Use the structure defined in <sys/ucontext.h>.
mcontext_t mcontext;
@@ -84,6 +88,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
diff --git a/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc b/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
index 6ee6cc1e4c..44fee5ba06 100644
--- a/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
+++ b/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
@@ -254,6 +254,48 @@ void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc) {
out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused.
#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 vrregset_t* 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
diff --git a/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h b/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h
index f830618f24..24d996380f 100644
--- a/third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h
+++ b/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 vrregset_t* vregs);
#else
static void FillCPUContext(RawContextCPU *out, const ucontext_t *uc);
#endif
diff --git a/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc b/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
index b895f6d7ad..901cd68fbd 100644
--- a/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
+++ b/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
@@ -461,9 +461,16 @@ bool ExceptionHandler::HandleSignal(int /*sig*/, siginfo_t* info, void* uc) {
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 !defined(__ARM_EABI__) && !defined(__mips__)
// FP state is not part of user ABI on ARM Linux.
- // In case of MIPS Linux FP state is already part of ucontext_t
+ // In case of MIPS, Linux FP state is already part of ucontext_t
// and 'float_state' is not a member of CrashContext.
ucontext_t* uc_ptr = (ucontext_t*)uc;
if (uc_ptr->uc_mcontext.fpregs) {
@@ -701,11 +708,19 @@ bool ExceptionHandler::WriteMinidump() {
}
#endif
-#if !defined(__ARM_EABI__) && !defined(__aarch64__) && !defined(__mips__)
+#if !defined(__ARM_EABI__) && !defined(__aarch64__) && !defined(__mips__) \
+ && !defined(__powerpc64__)
// FPU state is not part of ARM EABI ucontext_t.
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.
@@ -726,6 +741,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]);
#else
#error "This code has not been ported to your platform yet."
#endif
diff --git a/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.h b/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.h
index f44483ff0f..36ce6d6ce4 100644
--- a/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.h
+++ b/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.h
@@ -192,7 +192,11 @@ class ExceptionHandler {
siginfo_t siginfo;
pid_t tid; // the crashing thread.
ucontext_t context;
-#if !defined(__ARM_EABI__) && !defined(__mips__)
+#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 !defined(__ARM_EABI__) && !defined(__mips__)
// #ifdef this out because FP state is not part of user ABI for Linux ARM.
// In case of MIPS Linux FP state is already part of ucontext_t so
// 'float_state' is not required.
diff --git a/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler_unittest.cc b/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler_unittest.cc
index bcbf9c26f1..2c36ed41f2 100644
--- a/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler_unittest.cc
+++ b/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler_unittest.cc
@@ -307,7 +307,7 @@ TEST(ExceptionHandlerTest, ParallelChildCrashesDontHang) {
}
// Wait a while until the child should have crashed.
- usleep(1000000);
+ usleep(2000000);
// Kill the child if it is still running.
kill(child, SIGKILL);
@@ -559,6 +559,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
@@ -754,10 +756,10 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
// 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();
diff --git a/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer.cc b/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer.cc
index fa3c1713a5..6ce709e2f0 100644
--- a/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer.cc
+++ b/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer.cc
@@ -138,7 +138,9 @@ class MicrodumpWriter {
const MicrodumpExtraInfo& microdump_extra_info,
LinuxDumper* dumper)
: ucontext_(context ? &context->context : NULL),
-#if !defined(__ARM_EABI__) && !defined(__mips__)
+#if defined(__powerpc64__)
+ vector_state_(context ? &context->vector_state : NULL),
+#elif !defined(__ARM_EABI__) && !defined(__mips__)
float_state_(context ? &context->float_state : NULL),
#endif
dumper_(dumper),
@@ -337,6 +339,8 @@ class MicrodumpWriter {
# else
# error "This mips ABI is currently not supported (n32)"
#endif
+#elif defined(__powerpc64__)
+ const char kArch[] = "ppc64";
#else
#error "This code has not been ported to your platform yet"
#endif
@@ -409,7 +413,9 @@ class MicrodumpWriter {
void DumpCPUState() {
RawContextCPU cpu;
my_memset(&cpu, 0, sizeof(RawContextCPU));
-#if !defined(__ARM_EABI__) && !defined(__mips__)
+#if defined(__powerpc64__)
+ UContextReader::FillCPUContext(&cpu, ucontext_, vector_state_);
+#elif !defined(__ARM_EABI__) && !defined(__mips__)
UContextReader::FillCPUContext(&cpu, ucontext_, float_state_);
#else
UContextReader::FillCPUContext(&cpu, ucontext_);
@@ -605,7 +611,9 @@ class MicrodumpWriter {
void* Alloc(unsigned bytes) { return dumper_->allocator()->Alloc(bytes); }
const ucontext_t* const ucontext_;
-#if !defined(__ARM_EABI__) && !defined(__mips__)
+#if defined(__powerpc64__)
+ const google_breakpad::vstate_t* const vector_state_;
+#elif !defined(__ARM_EABI__) && !defined(__mips__)
const google_breakpad::fpstate_t* const float_state_;
#endif
LinuxDumper* dumper_;
diff --git a/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer_unittest.cc b/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer_unittest.cc
index c2fea0225e..8c62c524a2 100644
--- a/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer_unittest.cc
+++ b/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer_unittest.cc
@@ -278,10 +278,19 @@ TEST(MicrodumpWriterTest, BasicWithMappings) {
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 "
diff --git a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_core_dumper.cc b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_core_dumper.cc
index 4150689839..b93e4afcff 100644
--- a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_core_dumper.cc
+++ b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_core_dumper.cc
@@ -112,6 +112,9 @@ bool LinuxCoreDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
#elif defined(__mips__)
stack_pointer =
reinterpret_cast<uint8_t*>(info->mcontext.gregs[MD_CONTEXT_MIPS_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
@@ -197,7 +200,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];
diff --git a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.cc b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.cc
index 1112035bc5..8523dad634 100644
--- a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.cc
+++ b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.cc
@@ -765,7 +765,9 @@ bool LinuxDumper::GetStackInfo(const void** stack, size_t* stack_len,
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)
diff --git a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.h b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.h
index f4a75d9060..020981f57e 100644
--- a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.h
+++ b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.h
@@ -63,7 +63,8 @@ namespace google_breakpad {
(defined(__mips__) && _MIPS_SIM == _ABIO32)
typedef Elf32_auxv_t elf_aux_entry;
#elif defined(__x86_64) || defined(__aarch64__) || \
- (defined(__mips__) && _MIPS_SIM != _ABIO32)
+ (defined(__mips__) && _MIPS_SIM != _ABIO32) || \
+ defined(__powerpc64__)
typedef Elf64_auxv_t elf_aux_entry;
#endif
diff --git a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
index 3ad48e5015..1688c365ef 100644
--- a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
+++ b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
@@ -51,6 +51,8 @@
#define TID_PTR_REGISTER "rcx"
#elif defined(__mips__)
#define TID_PTR_REGISTER "$1"
+#elif defined(__powerpc64__)
+#define TID_PTR_REGISTER "r8"
#else
#error This test has not been ported to this platform.
#endif
diff --git a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.cc b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
index e3ddb81a65..fa28575ef5 100644
--- a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
+++ b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
@@ -149,19 +149,27 @@ bool LinuxPtraceDumper::CopyFromProcess(void* dest, pid_t child,
return true;
}
-bool LinuxPtraceDumper::ReadRegisterSet(ThreadInfo* info, pid_t tid)
-{
+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) {
+ 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) {
return false;
}
+
+#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;
@@ -298,6 +306,9 @@ bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
#elif defined(__mips__)
stack_pointer =
reinterpret_cast<uint8_t*>(info->mcontext.gregs[MD_CONTEXT_MIPS_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
diff --git a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
index a41dafce04..31743940de 100644
--- a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
+++ b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
@@ -462,6 +462,9 @@ TEST(LinuxPtraceDumperTest, VerifyStackReadWithMultipleThreads) {
#elif defined(__mips__)
pid_t* process_tid_location =
reinterpret_cast<pid_t*>(one_thread.mcontext.gregs[1]);
+#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
@@ -559,6 +562,8 @@ TEST_F(LinuxPtraceDumperTest, SanitizeStackCopy) {
uintptr_t heap_addr = thread_info.regs.rcx;
#elif defined(__mips__)
uintptr_t heap_addr = thread_info.mcontext.gregs[1];
+#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
diff --git a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.cc b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.cc
index f8cdf2a1c6..cb808c151f 100644
--- a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.cc
+++ b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.cc
@@ -136,7 +136,9 @@ class MinidumpWriter {
: fd_(minidump_fd),
path_(minidump_path),
ucontext_(context ? &context->context : NULL),
-#if !defined(__ARM_EABI__) && !defined(__mips__)
+#if defined(__powerpc64__)
+ vector_state_(context ? &context->vector_state : NULL),
+#elif !defined(__ARM_EABI__) && !defined(__mips__)
float_state_(context ? &context->float_state : NULL),
#endif
dumper_(dumper),
@@ -468,7 +470,9 @@ class MinidumpWriter {
if (!cpu.Allocate())
return false;
my_memset(cpu.get(), 0, sizeof(RawContextCPU));
-#if !defined(__ARM_EABI__) && !defined(__mips__)
+#if defined(__powerpc64__)
+ UContextReader::FillCPUContext(cpu.get(), ucontext_, vector_state_);
+#elif !defined(__ARM_EABI__) && !defined(__mips__)
UContextReader::FillCPUContext(cpu.get(), ucontext_, float_state_);
#else
UContextReader::FillCPUContext(cpu.get(), ucontext_);
@@ -897,7 +901,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";
@@ -917,7 +921,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
@@ -1333,7 +1339,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 !defined(__ARM_EABI__) && !defined(__mips__)
+#if defined(__powerpc64__)
+ const google_breakpad::vstate_t* const vector_state_;
+#elif !defined(__ARM_EABI__) && !defined(__mips__)
const google_breakpad::fpstate_t* const float_state_; // ditto
#endif
LinuxDumper* dumper_;
diff --git a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.h b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.h
index d1dc331215..c344621df1 100644
--- a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.h
+++ b/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 vrregset_t vstate_t;
#elif !defined(__ARM_EABI__) && !defined(__mips__)
typedef struct _libc_fpstate fpstate_t;
#endif
diff --git a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc
index c951e69d8f..e1d6e40d67 100644
--- a/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc
+++ b/third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc
@@ -714,6 +714,9 @@ TEST(MinidumpWriterTest, InvalidStackPointer) {
#elif defined(__mips__)
context.context.uc_mcontext.gregs[MD_CONTEXT_MIPS_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
diff --git a/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file.cc b/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file.cc
index 4e938269f2..f0ff15d967 100644
--- a/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file.cc
+++ b/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file.cc
@@ -65,8 +65,7 @@ bool MemoryMappedFile::Map(const char* path, size_t offset) {
}
#if defined(__x86_64__) || defined(__aarch64__) || \
- (defined(__mips__) && _MIPS_SIM == _ABI64)
-
+ (defined(__mips__) && _MIPS_SIM == _ABI64) || defined(__powerpc64__)
struct kernel_stat st;
if (sys_fstat(fd, &st) == -1 || st.st_size < 0) {
#else
diff --git a/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file_unittest.cc b/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file_unittest.cc
index fad59f40cd..616496d672 100644
--- a/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file_unittest.cc
+++ b/third_party/breakpad/breakpad/src/common/linux/memory_mapped_file_unittest.cc
@@ -176,9 +176,10 @@ TEST_F(MemoryMappedFileTest, RemapAfterMap) {
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;
}
diff --git a/third_party/breakpad/breakpad/src/processor/exploitability_linux.cc b/third_party/breakpad/breakpad/src/processor/exploitability_linux.cc
index ccc9f1459c..debaed4d6e 100644
--- a/third_party/breakpad/breakpad/src/processor/exploitability_linux.cc
+++ b/third_party/breakpad/breakpad/src/processor/exploitability_linux.cc
@@ -202,12 +202,14 @@ bool ExploitabilityLinux::EndedOnIllegalWrite(uint64_t instruction_ptr) {
// Check architecture and set architecture variable to corresponding flag
// in objdump.
switch (context->GetContextCPU()) {
+#if defined(__i386) || defined(__x86_64)
case MD_CONTEXT_X86:
architecture = "i386";
break;
case MD_CONTEXT_AMD64:
architecture = "i386:x86-64";
break;
+#endif
default:
// Unsupported architecture. Note that ARM architectures are not
// supported because objdump does not support ARM.
diff --git a/third_party/breakpad/breakpad/src/processor/exploitability_unittest.cc b/third_party/breakpad/breakpad/src/processor/exploitability_unittest.cc
index 528ee5f213..72764d6c1e 100644
--- a/third_party/breakpad/breakpad/src/processor/exploitability_unittest.cc
+++ b/third_party/breakpad/breakpad/src/processor/exploitability_unittest.cc
@@ -104,6 +104,8 @@ ExploitabilityFor(const string& filename) {
}
TEST(ExploitabilityTest, TestWindowsEngine) {
+// The following tests are only executable on an x86-class linux machine.
+#if !defined(_WIN32) && (defined(__i386) || defined(__x86_64))
ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
ExploitabilityFor("ascii_read_av.dmp"));
ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
@@ -136,9 +138,12 @@ TEST(ExploitabilityTest, TestWindowsEngine) {
ExploitabilityFor("read_av_clobber_write.dmp"));
ASSERT_EQ(google_breakpad::EXPLOITABILITY_LOW,
ExploitabilityFor("read_av_conditional.dmp"));
+#endif
}
TEST(ExploitabilityTest, TestLinuxEngine) {
+// The following tests are only executable on an x86-class linux machine.
+#if defined(__i386) || defined(__x86_64)
ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING,
ExploitabilityFor("linux_null_read_av.dmp"));
ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
@@ -171,7 +176,8 @@ TEST(ExploitabilityTest, TestLinuxEngine) {
ExploitabilityFor("linux_executable_heap.dmp"));
ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
ExploitabilityFor("linux_jmp_to_module_not_exe_region.dmp"));
-#ifndef _WIN32
+#endif
+#if !defined(_WIN32) && (defined(__i386) || defined(__x86_64))
ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
ExploitabilityFor("linux_write_to_nonwritable_module.dmp"));
ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
@@ -182,10 +188,10 @@ TEST(ExploitabilityTest, TestLinuxEngine) {
ExploitabilityFor("linux_write_to_outside_module_via_math.dmp"));
ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING,
ExploitabilityFor("linux_write_to_under_4k.dmp"));
-#endif // _WIN32
+#endif // !defined(_WIN32) && (!defined(__i386) && !defined(__x86_64))
}
-#ifndef _WIN32
+#if !defined(_WIN32) && (defined(__i386) || defined(__x86_64))
TEST(ExploitabilityLinuxUtilsTest, DisassembleBytesTest) {
ASSERT_FALSE(ExploitabilityLinuxTest::DisassembleBytes("", NULL, 5, NULL));
uint8_t bytes[6] = {0xc7, 0x0, 0x5, 0x0, 0x0, 0x0};
@@ -301,6 +307,7 @@ TEST(ExploitabilityLinuxUtilsTest, CalculateAddressTest) {
context,
&write_address));
}
-#endif // _WIN32
+#endif // !defined(_WIN32) && (defined(__i386) || defined(__x86_64))
+
} // namespace
diff --git a/third_party/breakpad/breakpad/src/tools/linux/md2core/minidump-2-core.cc b/third_party/breakpad/breakpad/src/tools/linux/md2core/minidump-2-core.cc
index 941586e9f6..49cdc3fc28 100644
--- a/third_party/breakpad/breakpad/src/tools/linux/md2core/minidump-2-core.cc
+++ b/third_party/breakpad/breakpad/src/tools/linux/md2core/minidump-2-core.cc
@@ -76,6 +76,8 @@
#define ELF_ARCH EM_MIPS
#elif defined(__aarch64__)
#define ELF_ARCH EM_AARCH64
+#elif defined(__powerpc64__)
+ #define ELF_ARCH EM_PPC64
#endif
#if defined(__arm__)
@@ -86,6 +88,8 @@ typedef user_regs user_regs_struct;
#elif defined (__mips__)
// 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;
@@ -320,6 +324,9 @@ struct CrashedProcess {
#endif
#if defined(__aarch64__)
user_fpsimd_struct fpregs;
+#endif
+#if defined(__powerpc64__)
+ mcontext_t mcontext;
#endif
uintptr_t stack_addr;
const uint8_t* stack;
@@ -534,6 +541,38 @@ ParseThreadRegisters(CrashedProcess::Thread* thread,
thread->mcontext.fpc_eir = rawregs->float_save.fir;
#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
@@ -622,6 +661,12 @@ ParseSystemInfo(const Options& options, CrashedProcess* crashinfo,
# else
# error "This mips ABI is currently not supported (n32)"
# 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
diff --git a/third_party/crashpad/crashpad/CONTRIBUTORS b/third_party/crashpad/crashpad/CONTRIBUTORS
index 8724b7f32f..8e29424ef6 100644
--- a/third_party/crashpad/crashpad/CONTRIBUTORS
+++ b/third_party/crashpad/crashpad/CONTRIBUTORS
@@ -13,3 +13,4 @@ Mark Mentovai <mark@chromium.org>
Robert Sesek <rsesek@chromium.org>
Scott Graham <scottmg@chromium.org>
Joshua Peraza <jperaza@chromium.org>
+Shawn Anastasio <shawn@anastas.io>
diff --git a/third_party/crashpad/crashpad/compat/linux/sys/user.h b/third_party/crashpad/crashpad/compat/linux/sys/user.h
index 6ed77a98e1..1fd83469a0 100644
--- a/third_party/crashpad/crashpad/compat/linux/sys/user.h
+++ b/third_party/crashpad/crashpad/compat/linux/sys/user.h
@@ -15,6 +15,7 @@
#ifndef CRASHPAD_COMPAT_LINUX_SYS_USER_H_
#define CRASHPAD_COMPAT_LINUX_SYS_USER_H_
+#include <cstddef>
#include_next <sys/user.h>
#include <features.h>
diff --git a/third_party/crashpad/crashpad/minidump/minidump_context.h b/third_party/crashpad/crashpad/minidump/minidump_context.h
index 3a3e603cb0..3118d9e9f9 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_context.h
+++ b/third_party/crashpad/crashpad/minidump/minidump_context.h
@@ -592,6 +592,70 @@ struct MinidumpContextMIPS64 {
uint64_t fir;
};
+//! \brief ppc64-specific flags for MinidumpPPC64::context_flags
+//! Based on minidump_cpu_ppc64.h from breakpad
+enum MinidumpContextPPC64Flags : uint32_t {
+ //! \brief Identifies the context as PPC64.
+ kMinidumpContextPPC64 = 0x01000000,
+
+ //! \brief Indicates the validity of general purpose registers.
+ //!
+ //! Registers `r0`-`r31`, `nip`, `msr`, `lr`, etc. are valid.
+ kMinidumpContextPPC64Base = kMinidumpContextPPC64 | 0x00000001,
+
+ //! \brief Indicates the validity of floating point registers.
+ //!
+ //! Registers `fp0`-`fp31`, `fpscr` are valid.
+ kMinidumpContextPPC64Floating = kMinidumpContextPPC64 | 0x00000008,
+
+ //! \brief Indicates the validity of Altivec/VMX registers.
+ //!
+ //! Registers `v0`-`v31`, `vscr`, `vrsave`.
+ kMinidumpContextPPC64Vector = kMinidumpContextPPC64 | 0x00000020,
+
+ //! \brief Indicates the validity of all registers
+ kMinidumpContextPPC64All = kMinidumpContextPPC64Base |
+ kMinidumpContextPPC64Floating |
+ kMinidumpContextPPC64Vector
+};
+
+//! \brief A PPC64 CPU context carried in a minidump file.
+//! Based on minidump_cpu_ppc64.h from breakpad.
+struct MinidumpContextPPC64 {
+ uint64_t context_flags;
+
+ //! \brief General purpose registers.
+ uint64_t nip;
+ uint64_t msr;
+ uint64_t regs[32];
+ uint64_t ccr;
+ uint64_t xer;
+ uint64_t lnk;
+ uint64_t ctr;
+
+ //! \brief Floating point registers.
+ double fpregs[32];
+
+ //! \brief FPU status register.
+ double fpscr;
+
+ //! \brief Altivec/VMX vector registers.
+ struct {
+ //! \brief Vector registers are 128bits.
+ uint128_struct save_vr[32];
+ uint128_struct save_vscr;
+
+ //! \brief Padding included for breakpad compatibiltiy.
+ uint32_t save_pad5[4];
+
+ //! \brief VRSAVE register.
+ uint32_t save_vrsave;
+
+ //! \brief Padding included for breakpad compatibiltiy.
+ uint32_t save_pad6[7];
+ } vregs;
+};
+
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_H_
diff --git a/third_party/crashpad/crashpad/minidump/minidump_context_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_context_writer.cc
index d7e53a4932..d89eb9e013 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_context_writer.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_context_writer.cc
@@ -101,6 +101,13 @@ MinidumpContextWriter::CreateFromSnapshot(const CPUContext* context_snapshot) {
break;
}
+ case kCPUArchitecturePPC64: {
+ context = std::make_unique<MinidumpContextPPC64Writer>();
+ reinterpret_cast<MinidumpContextPPC64Writer*>(context.get())
+ ->InitalizeFromSnapshot(context_snapshot->ppc64);
+ break;
+ }
+
default: {
LOG(ERROR) << "unknown context architecture "
<< context_snapshot->architecture;
@@ -453,4 +460,47 @@ size_t MinidumpContextMIPS64Writer::ContextSize() const {
return sizeof(context_);
}
+MinidumpContextPPC64Writer::MinidumpContextPPC64Writer()
+ : MinidumpContextWriter(), context_() {
+ context_.context_flags = kMinidumpContextPPC64;
+}
+
+MinidumpContextPPC64Writer::~MinidumpContextPPC64Writer() = default;
+
+void MinidumpContextPPC64Writer::InitalizeFromSnapshot(
+ const CPUContextPPC64* context_snapshot) {
+ DCHECK_EQ(state(), kStateMutable);
+ DCHECK_EQ(context_.context_flags, kMinidumpContextPPC64);
+
+ context_.context_flags = kMinidumpContextPPC64All;
+
+ memcpy(context_.regs, context_snapshot->regs, sizeof(context_.regs));
+ context_.nip = context_snapshot->nip;
+ context_.msr = context_snapshot->msr;
+ context_.ccr = context_snapshot->ccr;
+ context_.xer = context_snapshot->xer;
+ context_.lnk = context_snapshot->lnk;
+ context_.ctr = context_snapshot->ctr;
+
+ memcpy(context_.fpregs, context_snapshot->fpregs, sizeof(context_.fpregs));
+ context_.fpscr = context_snapshot->fpscr;
+
+ memcpy(context_.vregs.save_vr, context_snapshot->vregs.save_vr,
+ sizeof(context_.vregs.save_vr));
+ memcpy(&context_.vregs.save_vscr, &context_snapshot->vregs.save_vscr,
+ sizeof(context_.vregs.save_vscr));
+ context_.vregs.save_vrsave = context_snapshot->vregs.save_vrsave;
+}
+
+bool MinidumpContextPPC64Writer::WriteObject(
+ FileWriterInterface* file_writer) {
+ DCHECK_EQ(state(), kStateWritable);
+ return file_writer->Write(&context_, sizeof(context_));
+}
+
+size_t MinidumpContextPPC64Writer::ContextSize() const {
+ DCHECK_GE(state(), kStateFrozen);
+ return sizeof(context_);
+}
+
} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/minidump/minidump_context_writer.h b/third_party/crashpad/crashpad/minidump/minidump_context_writer.h
index d4ab936ee7..1d22fc59c9 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_context_writer.h
+++ b/third_party/crashpad/crashpad/minidump/minidump_context_writer.h
@@ -315,6 +315,45 @@ class MinidumpContextMIPS64Writer final : public MinidumpContextWriter {
DISALLOW_COPY_AND_ASSIGN(MinidumpContextMIPS64Writer);
};
+class MinidumpContextPPC64Writer final : public MinidumpContextWriter {
+ public:
+ MinidumpContextPPC64Writer();
+ ~MinidumpContextPPC64Writer() override;
+
+ //! \brief Initalizes the MinidumpContextPPC64 based on \a context_snapshot.
+ //!
+ //! \param[in] context_snapshot The context snapshot to use as source data.
+ //!
+ //! \note Valid in #kStateMutable. No mutation of context() may be done before
+ //! calling this method, and it is not normally necessary to alter
+ //! context() after calling this method.
+ void InitalizeFromSnapshot(const CPUContextPPC64* context_snapshot);
+
+ //! \brief Returns a pointer to the context structure that this object will
+ //! write.
+ //!
+ //! \attention This returns a non-`const` pointer to this objects private
+ //! data so that a caller can populate the context structure directly.
+ //! This is done because providing setter interfaces to each field in the
+ //! context structure would be unwieldy and cumbersome. Care must be taken
+ //! to populate the context structure correctly. The context structure
+ //! must only be modified while this object is in the #kStateMutable
+ //! state.
+ MinidumpContextPPC64* context() { return &context_; }
+
+ protected:
+ // MinidumpWritable:
+ bool WriteObject(FileWriterInterface* file_writer) override;
+
+ // MinidumpContextWriter:
+ size_t ContextSize() const override;
+
+ private:
+ MinidumpContextPPC64 context_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpContextPPC64Writer);
+};
+
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_WRITER_H_
diff --git a/third_party/crashpad/crashpad/minidump/minidump_context_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_context_writer_test.cc
index 3216a906ba..a9fcbe9d8e 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_context_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_context_writer_test.cc
@@ -213,6 +213,21 @@ TEST(MinidumpContextWriter, MIPS64_FromSnapshot) {
context, ExpectMinidumpContextMIPS64, kSeed);
}
+TEST(MinidumpContextWriter, PPC64_Zeros) {
+ EmptyContextTest<MinidumpContextPPC64Writer, MinidumpContextPPC64>(
+ ExpectMinidumpContextPPC64);
+}
+
+TEST(MinidumpContextWriter, PPC64_FromSnapshot) {
+ constexpr uint32_t kSeed = 64;
+ CPUContextPPC64 context_ppc64;
+ CPUContext context;
+ context.ppc64 = &context_ppc64;
+ InitializeCPUContextPPC64(&context, kSeed);
+ FromSnapshotTest<MinidumpContextPPC64Writer, MinidumpContextPPC64>(
+ context, ExpectMinidumpContextPPC64, kSeed);
+}
+
} // namespace
} // namespace test
} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc
index a13407605f..95dc925240 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc
@@ -126,6 +126,8 @@ std::string MinidumpMiscInfoDebugBuildString() {
static constexpr char kCPU[] = "mips";
#elif defined(ARCH_CPU_MIPS64EL)
static constexpr char kCPU[] = "mips64";
+#elif defined(ARCH_CPU_PPC64)
+ static constexpr char kCPU[] = "ppc64";
#else
#error define kCPU for this CPU
#endif
diff --git a/third_party/crashpad/crashpad/snapshot/capture_memory.cc b/third_party/crashpad/crashpad/snapshot/capture_memory.cc
index a51626ccdc..61e0b20a17 100644
--- a/third_party/crashpad/crashpad/snapshot/capture_memory.cc
+++ b/third_party/crashpad/crashpad/snapshot/capture_memory.cc
@@ -111,6 +111,11 @@ void CaptureMemory::PointedToByContext(const CPUContext& context,
for (size_t i = 0; i < base::size(context.mipsel->regs); ++i) {
MaybeCaptureMemoryAround(delegate, context.mipsel->regs[i]);
}
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ MaybeCaptureMemoryAround(delegate, context.ppc64->nip);
+ for (size_t i = 0; i < base::size(context.ppc64->regs); ++i) {
+ MaybeCaptureMemoryAround(delegate, context.ppc64->regs[i]);
+ }
#else
#error Port.
#endif
diff --git a/third_party/crashpad/crashpad/snapshot/cpu_architecture.h b/third_party/crashpad/crashpad/snapshot/cpu_architecture.h
index 811a720958..f4f83981df 100644
--- a/third_party/crashpad/crashpad/snapshot/cpu_architecture.h
+++ b/third_party/crashpad/crashpad/snapshot/cpu_architecture.h
@@ -43,7 +43,10 @@ enum CPUArchitecture {
kCPUArchitectureMIPSEL,
//! \brief 64-bit MIPSEL.
- kCPUArchitectureMIPS64EL
+ kCPUArchitectureMIPS64EL,
+
+ //! \brief 64-bit PPC64.
+ kCPUArchitecturePPC64
};
} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/cpu_context.cc b/third_party/crashpad/crashpad/snapshot/cpu_context.cc
index 6fb8d7e719..b01f7cad11 100644
--- a/third_party/crashpad/crashpad/snapshot/cpu_context.cc
+++ b/third_party/crashpad/crashpad/snapshot/cpu_context.cc
@@ -169,6 +169,8 @@ uint64_t CPUContext::InstructionPointer() const {
return arm->pc;
case kCPUArchitectureARM64:
return arm64->pc;
+ case kCPUArchitecturePPC64:
+ return ppc64->nip;
default:
NOTREACHED();
return ~0ull;
@@ -185,6 +187,8 @@ uint64_t CPUContext::StackPointer() const {
return arm->sp;
case kCPUArchitectureARM64:
return arm64->sp;
+ case kCPUArchitecturePPC64:
+ return ppc64->regs[1];
default:
NOTREACHED();
return ~0ull;
@@ -196,6 +200,7 @@ bool CPUContext::Is64Bit() const {
case kCPUArchitectureX86_64:
case kCPUArchitectureARM64:
case kCPUArchitectureMIPS64EL:
+ case kCPUArchitecturePPC64:
return true;
case kCPUArchitectureX86:
case kCPUArchitectureARM:
diff --git a/third_party/crashpad/crashpad/snapshot/cpu_context.h b/third_party/crashpad/crashpad/snapshot/cpu_context.h
index fb23c4679f..eebede63c6 100644
--- a/third_party/crashpad/crashpad/snapshot/cpu_context.h
+++ b/third_party/crashpad/crashpad/snapshot/cpu_context.h
@@ -352,6 +352,24 @@ struct CPUContextMIPS64 {
uint64_t fir;
};
+//! \brief A context structure carrying PPC64 CPU state.
+struct CPUContextPPC64 {
+ uint64_t nip;
+ uint64_t msr;
+ uint64_t regs[32];
+ uint64_t ccr;
+ uint64_t xer;
+ uint64_t lnk;
+ uint64_t ctr;
+ double fpregs[32];
+ double fpscr;
+ struct {
+ uint128_struct save_vr[32];
+ uint128_struct save_vscr;
+ uint32_t save_vrsave;
+ } vregs;
+};
+
//! \brief A context structure capable of carrying the context of any supported
//! CPU architecture.
struct CPUContext {
@@ -382,6 +400,7 @@ struct CPUContext {
CPUContextARM64* arm64;
CPUContextMIPS* mipsel;
CPUContextMIPS64* mips64;
+ CPUContextPPC64* ppc64;
};
};
diff --git a/third_party/crashpad/crashpad/snapshot/linux/cpu_context_linux.h b/third_party/crashpad/crashpad/snapshot/linux/cpu_context_linux.h
index 9f46a48977..aa677c4eb9 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/cpu_context_linux.h
+++ b/third_party/crashpad/crashpad/snapshot/linux/cpu_context_linux.h
@@ -15,6 +15,7 @@
#ifndef CRASHPAD_SNAPSHOT_LINUX_CPU_CONTEXT_LINUX_H_
#define CRASHPAD_SNAPSHOT_LINUX_CPU_CONTEXT_LINUX_H_
+#include <cstring>
#include "build/build_config.h"
#include "snapshot/cpu_context.h"
#include "snapshot/linux/signal_context.h"
@@ -174,6 +175,78 @@ void InitializeCPUContextMIPS(
#endif // ARCH_CPU_MIPS_FAMILY || DOXYGEN
+#if defined(ARCH_CPU_PPC64_FAMILY) || DOXYGEN
+
+//! \brief Initalizes a CPUContextPPC64 structure from native context
+//! structures on Linux.
+//!
+//! \param[in] thread_context The native thread context.
+//! \param[in] float_context The native float context.
+//! \param[in] vector_context The native vector context.
+//! \param[out] context The CPUContextPPC64 structure to initalize.
+template <typename Traits>
+void InitializeCPUContextPPC64(
+ const ThreadContext::t64_t& thread_context,
+ const FloatContext::f64_t& float_context,
+ const VectorContext::v64_t& vector_context,
+ typename Traits::CPUContext* context) {
+
+ memcpy(context->regs, thread_context.gpr, sizeof(context->regs));
+ context->nip = thread_context.nip;
+ context->msr = thread_context.msr;
+ context->ccr = thread_context.ccr;
+ context->xer = thread_context.xer;
+ context->lnk = thread_context.lnk;
+ context->ctr = thread_context.ctr;
+
+ memcpy(context->fpregs, float_context.fpregs, sizeof(context->fpregs));
+ context->fpscr = float_context.fpscr;
+
+ for (uint8_t i = 0; i < 32; i++) {
+ context->vregs.save_vr[i] = {
+ (((uint64_t)vector_context.vrregs[i][0]) << 32) |
+ vector_context.vrregs[i][1],
+ (((uint64_t)vector_context.vrregs[i][2]) << 32) |
+ vector_context.vrregs[i][3]
+ };
+ }
+ context->vregs.save_vrsave = vector_context.vrsave;
+ context->vregs.save_vscr = {0, (uint64_t)vector_context.vscr.vscr_word};
+}
+
+template <typename Traits>
+void InitializeCPUContextPPC64(
+ const SignalThreadContext64 &thread_context,
+ const SignalFloatContext64 &float_context,
+ const SignalVectorContext64 &vector_context,
+ typename Traits::CPUContext* context) {
+
+ memcpy(context->regs, thread_context.regs, sizeof(context->regs));
+ context->nip = thread_context.nip;
+ context->msr = thread_context.msr;
+ context->ccr = thread_context.ccr;
+ context->xer = thread_context.xer;
+ context->lnk = thread_context.lnk;
+ context->ctr = thread_context.ctr;
+
+ memcpy(context->fpregs, float_context.regs, sizeof(context->fpregs));
+ context->fpscr = float_context.fpscr;
+
+ for (uint8_t i = 0; i < 32; i++) {
+ context->vregs.save_vr[i] = {
+ (((uint64_t)vector_context.vrregs[i][0]) << 32) |
+ vector_context.vrregs[i][1],
+ (((uint64_t)vector_context.vrregs[i][2]) << 32) |
+ vector_context.vrregs[i][3]
+ };
+ }
+ context->vregs.save_vrsave = vector_context.vrsave;
+ context->vregs.save_vscr = {0, (uint64_t)vector_context.vscr.vscr_word};
+}
+
+
+#endif
+
} // namespace internal
} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/linux/debug_rendezvous_test.cc b/third_party/crashpad/crashpad/snapshot/linux/debug_rendezvous_test.cc
index be22c90313..c5df23d1b4 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/debug_rendezvous_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/debug_rendezvous_test.cc
@@ -159,9 +159,11 @@ void TestAgainstTarget(PtraceConnection* connection) {
const bool is_vdso_mapping =
device == 0 && inode == 0 && mapping_name == "[vdso]";
static constexpr char kPrefix[] = "linux-vdso.so.";
+ static constexpr char kPrefix64[] = "linux-vdso64.so.";
return is_vdso_mapping ==
(module_name.empty() ||
- module_name.compare(0, strlen(kPrefix), kPrefix) == 0);
+ module_name.compare(0, strlen(kPrefix), kPrefix) == 0 ||
+ module_name.compare(0, strlen(kPrefix64), kPrefix64) == 0);
},
module_mapping->name,
module_mapping->device,
diff --git a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc
index cd40b3b12d..6bcf23b6ff 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc
@@ -323,6 +323,69 @@ bool ExceptionSnapshotLinux::ReadContext<ContextTraits64>(
reader, context_address, context_.mips64);
}
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+
+template <typename Traits>
+static bool ReadContext(ProcessReaderLinux* reader,
+ LinuxVMAddress context_address,
+ typename Traits::CPUContext* dest_context) {
+ const ProcessMemory* memory = reader->Memory();
+
+ LinuxVMAddress gp_regs_address = context_address +
+ offsetof(UContext, mcontext) +
+ offsetof(typename Traits::MContext, gp_regs);
+
+ typename Traits::SignalThreadContext thread_context;
+ if (!memory->Read(gp_regs_address, sizeof(thread_context), &thread_context)) {
+ LOG(ERROR) << "Couldn't read gp_regs!";
+ return false;
+ }
+
+ LinuxVMAddress fp_regs_address = context_address +
+ offsetof(UContext, mcontext) +
+ offsetof(typename Traits::MContext, fp_regs);
+
+ typename Traits::SignalFloatContext fp_context;
+ if (!memory->Read(fp_regs_address, sizeof(fp_context), &fp_context)) {
+ LOG(ERROR) << "Couldn't read fp_regs!";
+ return false;
+ }
+
+ LinuxVMAddress v_regs_ptr_address = context_address +
+ offsetof(UContext, mcontext) +
+ offsetof(typename Traits::MContext, vmx_reserve) + 8;
+
+ typename Traits::SignalVectorContext v_context;
+ if (!memory->Read(v_regs_ptr_address, sizeof(v_context), &v_context)) {
+ LOG(ERROR) << "Couldn't read v_regs!";
+ return false;
+ }
+
+ InitializeCPUContextPPC64<ContextTraits64>(thread_context, fp_context,
+ v_context, dest_context);
+
+ return true;
+}
+
+template<>
+bool ExceptionSnapshotLinux::ReadContext<ContextTraits64>(
+ ProcessReaderLinux* reader,
+ LinuxVMAddress context_address) {
+ context_.architecture = kCPUArchitecturePPC64;
+ context_.ppc64 = &context_union_.ppc64;
+
+ return internal::ReadContext<ContextTraits64>(
+ reader, context_address, context_.ppc64);
+}
+
+template<>
+bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>(
+ ProcessReaderLinux* reader,
+ LinuxVMAddress context_address) {
+ // PPC64 is 64-bit
+ return false;
+}
+
#endif // ARCH_CPU_X86_FAMILY
bool ExceptionSnapshotLinux::Initialize(ProcessReaderLinux* process_reader,
diff --git a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h
index ea0cd21066..e42df520ff 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h
+++ b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h
@@ -84,6 +84,8 @@ class ExceptionSnapshotLinux final : public ExceptionSnapshot {
#elif defined(ARCH_CPU_MIPS_FAMILY)
CPUContextMIPS mipsel;
CPUContextMIPS64 mips64;
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ CPUContextPPC64 ppc64;
#endif
} context_union_;
CPUContext context_;
diff --git a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc
index e4ff1ab79f..25534dd087 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc
@@ -296,7 +296,28 @@ void ExpectContext(const CPUContext& actual, const NativeCPUContext& expected) {
0);
#undef CPU_ARCH_NAME
}
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+using NativeCPUContext = ucontext_t;
+
+void InitializeContext(NativeCPUContext* context) {
+ for (size_t reg = 0; reg < 32; ++reg) {
+ context->uc_mcontext.gp_regs[reg] = reg;
+ }
+
+ memset(&context->uc_mcontext.fp_regs, 44,
+ sizeof(context->uc_mcontext.fp_regs));
+}
+void ExpectContext(const CPUContext& actual, const NativeCPUContext& expected) {
+ EXPECT_EQ(actual.architecture, kCPUArchitecturePPC64);
+
+ for (size_t reg = 0; reg < 32; ++reg) {
+ EXPECT_EQ(actual.ppc64->regs[reg], expected.uc_mcontext.gp_regs[reg]);
+ }
+
+ EXPECT_EQ(memcmp(actual.ppc64->fpregs, expected.uc_mcontext.fp_regs,
+ sizeof(actual.ppc64->fpregs)), 0);
+}
#else
#error Port.
#endif
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc
index b96abfe74f..df12ca5669 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc
@@ -108,6 +108,8 @@ void ProcessReaderLinux::Thread::InitializeStack(ProcessReaderLinux* reader) {
#elif defined(ARCH_CPU_MIPS_FAMILY)
stack_pointer = reader->Is64Bit() ? thread_info.thread_context.t64.regs[29]
: thread_info.thread_context.t32.regs[29];
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ stack_pointer = thread_info.thread_context.t64.gpr[1];
#else
#error Port.
#endif
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc
index 5b5723616f..049c32858c 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc
@@ -612,6 +612,8 @@ bool WriteTestModule(const base::FilePath& module_path) {
module.ehdr.e_machine = EM_AARCH64;
#elif defined(ARCH_CPU_MIPSEL) || defined(ARCH_CPU_MIPS64EL)
module.ehdr.e_machine = EM_MIPS;
+#elif defined(ARCH_CPU_PPC64)
+ module.ehdr.e_machine = EM_PPC64;
#endif
module.ehdr.e_version = EV_CURRENT;
diff --git a/third_party/crashpad/crashpad/snapshot/linux/signal_context.h b/third_party/crashpad/crashpad/snapshot/linux/signal_context.h
index 110024680b..a1f2da2591 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/signal_context.h
+++ b/third_party/crashpad/crashpad/snapshot/linux/signal_context.h
@@ -422,6 +422,89 @@ static_assert(offsetof(UContext<ContextTraits64>, mcontext.fpregs) ==
"context offset mismatch");
#endif
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+
+struct SignalThreadContext64 {
+ uint64_t regs[32];
+ uint64_t nip;
+ uint64_t msr;
+ uint64_t orig_r3;
+ uint64_t ctr;
+ uint64_t lnk;
+ uint64_t xer;
+ uint64_t ccr;
+ uint64_t softe;
+ uint64_t trap;
+ uint64_t dar;
+ uint64_t dsisr;
+ uint64_t result;
+ uint64_t dscr;
+ uint64_t fpr0[3];
+};
+
+struct SignalFloatContext64 {
+ double regs[32];
+ double fpscr;
+};
+
+struct SignalVectorContext64 {
+ int32_t vrregs[32][4];
+ struct {
+ int32_t __pad[3];
+ int32_t vscr_word;
+ } vscr;
+ int32_t vrsave;
+ int32_t __pad[3];
+} __attribute__((__aligned__(16)));
+
+
+#pragma pack(pop)
+struct MContext64 {
+ uint64_t reserved[4];
+ int32_t signal;
+ int32_t __pad0;
+ uint64_t handler;
+ uint64_t oldmask;
+ uint64_t pt_regs_ptr;
+ SignalThreadContext64 gp_regs;
+ SignalFloatContext64 fp_regs;
+ SignalVectorContext64 *v_regs;
+ int64_t vmx_reserve[69];
+};
+
+struct ContextTraits64 : public Traits64 {
+ using MContext = MContext64;
+ using SignalThreadContext = SignalThreadContext64;
+ using SignalFloatContext = SignalFloatContext64;
+ using SignalVectorContext = SignalVectorContext64;
+ using CPUContext = CPUContextPPC64;
+};
+
+struct ContextTraits32 : public Traits32 {};
+
+struct UContext {
+ uint64_t flags;
+ uint64_t link;
+ SignalStack<ContextTraits64> stack;
+ Sigset<ContextTraits64> sigmask;
+ MContext64 mcontext;
+};
+#pragma pack(push, 1)
+
+static_assert(sizeof(UContext) == sizeof(ucontext_t),
+ "ucontext_t size mismatch");
+static_assert(sizeof(MContext64) == sizeof(mcontext_t),
+ "mcontext_t size mismatch");
+static_assert(sizeof(SignalThreadContext64) == sizeof(gregset_t),
+ "gregset_t size mismatch");
+static_assert(sizeof(SignalFloatContext64) == sizeof(fpregset_t),
+ "fpregset_t size mismatch");
+static_assert(sizeof(SignalVectorContext64) == sizeof(vrregset_t),
+ "vrregset_t size mismatch");
+static_assert(offsetof(UContext, mcontext) ==
+ offsetof(ucontext_t, uc_mcontext), "mcontext offset mismatch");
+static_assert(offsetof(MContext64, gp_regs) ==
+ offsetof(mcontext_t, gp_regs), "gp_regs offset mismatch");
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY
diff --git a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
index 8564d3d455..b690ecd48f 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
@@ -203,6 +203,8 @@ CPUArchitecture SystemSnapshotLinux::GetCPUArchitecture() const {
#elif defined(ARCH_CPU_MIPS_FAMILY)
return process_reader_->Is64Bit() ? kCPUArchitectureMIPS64EL
: kCPUArchitectureMIPSEL;
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ return kCPUArchitecturePPC64;
#else
#error port to your architecture
#endif
@@ -218,6 +220,9 @@ uint32_t SystemSnapshotLinux::CPURevision() const {
#elif defined(ARCH_CPU_MIPS_FAMILY)
// Not implementable on MIPS
return 0;
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ // Not yet implemented on PPC64
+ return 0;
#else
#error port to your architecture
#endif
@@ -238,6 +243,9 @@ std::string SystemSnapshotLinux::CPUVendor() const {
#elif defined(ARCH_CPU_MIPS_FAMILY)
// Not implementable on MIPS
return std::string();
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ // Not yet implemented on PPC64
+ return std::string();
#else
#error port to your architecture
#endif
@@ -371,6 +379,9 @@ bool SystemSnapshotLinux::NXEnabled() const {
#elif defined(ARCH_CPU_MIPS_FAMILY)
// Not implementable on MIPS
return false;
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ // Not yet implemented on PPC64
+ return false;
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY
diff --git a/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc
index e3e2bebddb..8ef43752eb 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc
@@ -186,6 +186,14 @@ bool ThreadSnapshotLinux::Initialize(ProcessReaderLinux* process_reader,
thread.thread_info.float_context.f32,
context_.mipsel);
}
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ context_.architecture = kCPUArchitecturePPC64;
+ context_.ppc64 = &context_union_.ppc64;
+ InitializeCPUContextPPC64<ContextTraits64>(
+ thread.thread_info.thread_context.t64,
+ thread.thread_info.float_context.f64,
+ thread.thread_info.vector_context.v64,
+ context_.ppc64);
#else
#error Port.
#endif
diff --git a/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h
index 44cc6f6d97..d4136461e2 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h
+++ b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h
@@ -68,6 +68,8 @@ class ThreadSnapshotLinux final : public ThreadSnapshot {
#elif defined(ARCH_CPU_MIPS_FAMILY)
CPUContextMIPS mipsel;
CPUContextMIPS64 mips64;
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ CPUContextPPC64 ppc64;
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY
diff --git a/third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc b/third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc
index d3d5ebdfb9..3fd730cb52 100644
--- a/third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc
+++ b/third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc
@@ -56,6 +56,11 @@ bool AuxiliaryVector::Read(PtraceConnection* connection) {
if (type == AT_IGNORE) {
continue;
}
+#if defined(ARCH_CPU_PPC64_FAMILY)
+ if (type == AT_IGNOREPPC) {
+ continue;
+ }
+#endif
if (!MapInsertOrReplace(&values_, type, value, nullptr)) {
LOG(ERROR) << "duplicate auxv entry";
return false;
diff --git a/third_party/crashpad/crashpad/util/linux/ptrace_broker.cc b/third_party/crashpad/crashpad/util/linux/ptrace_broker.cc
index 155a1e0c6f..5e50ceb5f8 100644
--- a/third_party/crashpad/crashpad/util/linux/ptrace_broker.cc
+++ b/third_party/crashpad/crashpad/util/linux/ptrace_broker.cc
@@ -94,8 +94,8 @@ int PtraceBroker::Run() {
}
bool PtraceBroker::AllocateAttachments() {
- constexpr size_t page_size = 4096;
- constexpr size_t alloc_size =
+ static size_t page_size = getpagesize();
+ size_t alloc_size =
(sizeof(ScopedPtraceAttach) + page_size - 1) & ~(page_size - 1);
void* alloc = sbrk(alloc_size);
if (reinterpret_cast<intptr_t>(alloc) == -1) {
diff --git a/third_party/crashpad/crashpad/util/linux/ptracer.cc b/third_party/crashpad/crashpad/util/linux/ptracer.cc
index 557e0d3635..08ae434b80 100644
--- a/third_party/crashpad/crashpad/util/linux/ptracer.cc
+++ b/third_party/crashpad/crashpad/util/linux/ptracer.cc
@@ -398,6 +398,64 @@ bool GetThreadArea64(pid_t tid,
return true;
}
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+// PPC64 has had HAVE_ARCH_TRACEHOOK set since 2.6.27 (even before x86 had it).
+// That means we can simply use PTRACE_GETREGESET.
+
+template <typename Destination>
+bool GetRegisterSet(pid_t tid, int set, Destination* dest, bool can_log) {
+ iovec iov;
+ iov.iov_base = reinterpret_cast<void*>(dest);
+ iov.iov_len = sizeof(*dest);
+ if (ptrace(PTRACE_GETREGSET, tid, reinterpret_cast<void*>(set), &iov) != 0) {
+ PLOG_IF(ERROR, can_log) << "ptrace";
+ return false;
+ }
+ if (iov.iov_len != sizeof(*dest)) {
+ LOG_IF(ERROR, can_log) << "Unexpected registers size";
+ return false;
+ }
+ return true;
+}
+
+bool GetVectorRegisters64(pid_t tid,
+ VectorContext* context,
+ bool can_log) {
+ return GetRegisterSet(tid, NT_PPC_VMX, &context->v64, can_log);
+}
+
+bool GetFloatingPointRegisters64(pid_t tid,
+ FloatContext* context,
+ bool can_log) {
+ return GetRegisterSet(tid, NT_PRFPREG, &context->f64, can_log);
+}
+
+bool GetThreadArea64(pid_t tid,
+ const ThreadContext& context,
+ LinuxVMAddress* address,
+ bool can_log) {
+ // PPC64 doesn't have PTRACE_GET_THREAD_AREA since the thread pointer
+ // is stored in GPR 13.
+ ThreadContext::t64_t tc;
+ if (!GetRegisterSet(tid, NT_PRSTATUS, &tc, can_log)) {
+ LOG_IF(ERROR, can_log) << "Unable to get thread pointer!";
+ return false;
+ }
+
+ *address = tc.gpr[13];
+
+ return true;
+}
+
+// Stubs for 32-bit functions not applicable on PPC64
+bool GetFloatingPointRegisters32(pid_t tid,
+ FloatContext* context,
+ bool can_log) { return false; }
+bool GetThreadArea32(pid_t tid,
+ const ThreadContext &context,
+ LinuxVMAddress *address,
+ bool can_log) { return false; }
+
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY
@@ -494,6 +552,9 @@ bool Ptracer::GetThreadInfo(pid_t tid, ThreadInfo* info) {
if (is_64_bit_) {
return GetGeneralPurposeRegisters64(tid, &info->thread_context, can_log_) &&
GetFloatingPointRegisters64(tid, &info->float_context, can_log_) &&
+#if defined(ARCH_CPU_PPC64_FAMILY)
+ GetVectorRegisters64(tid, &info->vector_context, can_log_) &&
+#endif
GetThreadArea64(tid,
info->thread_context,
&info->thread_specific_data_address,
diff --git a/third_party/crashpad/crashpad/util/linux/thread_info.h b/third_party/crashpad/crashpad/util/linux/thread_info.h
index 5b55c24a76..dea0d1f39e 100644
--- a/third_party/crashpad/crashpad/util/linux/thread_info.h
+++ b/third_party/crashpad/crashpad/util/linux/thread_info.h
@@ -28,6 +28,10 @@
#include <android/api-level.h>
#endif
+#if defined(ARCH_CPU_PPC64_FAMILY)
+#include <sys/ucontext.h>
+#endif
+
namespace crashpad {
//! \brief The set of general purpose registers for an architecture family.
@@ -79,6 +83,8 @@ union ThreadContext {
uint32_t cp0_status;
uint32_t cp0_cause;
uint32_t padding1_;
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ // PPC64 is 64-bit
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY
@@ -132,6 +138,21 @@ union ThreadContext {
uint64_t cp0_badvaddr;
uint64_t cp0_status;
uint64_t cp0_cause;
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ // Reflects struct pt_regs in asm/ptrace.h.
+ uint64_t gpr[32];
+ uint64_t nip;
+ uint64_t msr;
+ uint64_t orig_gpr3;
+ uint64_t ctr;
+ uint64_t lnk;
+ uint64_t xer;
+ uint64_t ccr;
+ uint64_t softe;
+ uint64_t trap;
+ uint64_t dar;
+ uint64_t dsisr;
+ uint64_t result;
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY
@@ -143,6 +164,8 @@ union ThreadContext {
using NativeThreadContext = user_regs;
#elif defined(ARCH_CPU_MIPS_FAMILY)
// No appropriate NativeThreadsContext type available for MIPS
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ using NativeThreadContext = struct pt_regs;
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY || ARCH_CPU_ARM64
@@ -218,6 +241,9 @@ union FloatContext {
} fpregs[32];
uint32_t fpcsr;
uint32_t fpu_id;
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ // Crashpad's PPC support is 64-bit only, so this
+ // 32bit-only struct is declared as empty.
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY
@@ -252,6 +278,10 @@ union FloatContext {
double fpregs[32];
uint32_t fpcsr;
uint32_t fpu_id;
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ // Reflects fpregset_t in sys/ucontext.h
+ double fpregs[32];
+ double fpscr;
#else
#error Port.
#endif // ARCH_CPU_X86_FAMILY
@@ -280,6 +310,8 @@ union FloatContext {
static_assert(sizeof(f64) == sizeof(user_fpsimd_struct), "Size mismatch");
#elif defined(ARCH_CPU_MIPS_FAMILY)
// No appropriate floating point context native type for available MIPS.
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ static_assert(sizeof(f64) == sizeof(fpregset_t), "Size mismatch");
#else
#error Port.
#endif // ARCH_CPU_X86
@@ -287,6 +319,26 @@ union FloatContext {
static_assert(std::is_standard_layout<FloatContext>::value,
"Not standard layout");
+//! \brief The vector registers used for an architecture family
+union VectorContext {
+ struct v32_t {} v32;
+#if defined(ARCH_CPU_PPC64_FAMILY)
+ __attribute__((__aligned__(16))) // Vector context must be doubleword aligned.
+#endif
+ struct v64_t {
+#if defined(ARCH_CPU_PPC64_FAMILY)
+ // Reflects vrregset_t in sys/ucontext.h
+ uint32_t vrregs[32][4];
+ struct {
+ uint32_t __pad[3];
+ uint32_t vscr_word;
+ } vscr;
+ uint32_t vrsave;
+ uint32_t __pad[3];
+#endif
+ } v64;
+};
+
//! \brief A collection of `ptrace`-able information about a thread.
struct ThreadInfo {
ThreadInfo();
@@ -298,6 +350,9 @@ struct ThreadInfo {
//! \brief The floating point registers for the thread.
FloatContext float_context;
+ //! \brief (Optional) The vector registers used for the thread.
+ VectorContext vector_context;
+
//! \brief The thread-local storage address for the thread.
LinuxVMAddress thread_specific_data_address;
};
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context.h b/third_party/crashpad/crashpad/util/misc/capture_context.h
index a88a10336f..b0d6578bdd 100644
--- a/third_party/crashpad/crashpad/util/misc/capture_context.h
+++ b/third_party/crashpad/crashpad/util/misc/capture_context.h
@@ -70,6 +70,7 @@ using NativeCPUContext = ucontext_t;
//! macOS/Linux/Fuchsia | x86_64 | `%%rdi`
//! Linux | ARM/ARM64 | `r0`/`x0`
//! Linux | MIPS/MIPS64 | `$a0`
+//! Linux | PPC64 | `r3`
//!
//! Additionally, the value `LR` on ARM/ARM64 will be the return address of
//! this function.
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_linux.S b/third_party/crashpad/crashpad/util/misc/capture_context_linux.S
index 52215ee5d0..b3e4a3ec7e 100644
--- a/third_party/crashpad/crashpad/util/misc/capture_context_linux.S
+++ b/third_party/crashpad/crashpad/util/misc/capture_context_linux.S
@@ -32,7 +32,7 @@
.balign 4, 0x0
.type CAPTURECONTEXT_SYMBOL, %function
.type CAPTURECONTEXT_SYMBOL2, %function
-#elif defined(__mips__)
+#elif defined(__mips__) || defined(__powerpc64__)
.balign 4, 0x0
#endif
@@ -423,4 +423,214 @@ CAPTURECONTEXT_SYMBOL2:
jr $ra
.set at
+#elif defined(__powerpc64__)
+ // Store r0-r31
+ std 0, 0xe8(3) // context->uc_mcontext.gp_regs[0]
+ std 1, 0xf0(3) // context->uc_mcontext.gp_regs[1]
+ std 2, 0xf8(3) // context->uc_mcontext.gp_regs[2]
+ // note that r3's original value was lost
+ std 3, 0x100(3) // context->uc_mcontext.gp_regs[3]
+ std 4, 0x108(3) // context->uc_mcontext.gp_regs[4]
+ std 5, 0x110(3) // context->uc_mcontext.gp_regs[5]
+ std 6, 0x118(3) // context->uc_mcontext.gp_regs[6]
+ std 7, 0x120(3) // context->uc_mcontext.gp_regs[7]
+ std 8, 0x128(3) // context->uc_mcontext.gp_regs[8]
+ std 9, 0x130(3) // context->uc_mcontext.gp_regs[9]
+ std 10, 0x138(3) // context->uc_mcontext.gp_regs[10]
+ std 11, 0x140(3) // context->uc_mcontext.gp_regs[11]
+ std 12, 0x148(3) // context->uc_mcontext.gp_regs[12]
+ std 13, 0x150(3) // context->uc_mcontext.gp_regs[13]
+ std 14, 0x158(3) // context->uc_mcontext.gp_regs[14]
+ std 15, 0x160(3) // context->uc_mcontext.gp_regs[15]
+ std 16, 0x168(3) // context->uc_mcontext.gp_regs[16]
+ std 17, 0x170(3) // context->uc_mcontext.gp_regs[17]
+ std 18, 0x178(3) // context->uc_mcontext.gp_regs[18]
+ std 19, 0x180(3) // context->uc_mcontext.gp_regs[19]
+ std 20, 0x188(3) // context->uc_mcontext.gp_regs[20]
+ std 21, 0x190(3) // context->uc_mcontext.gp_regs[21]
+ std 22, 0x198(3) // context->uc_mcontext.gp_regs[22]
+ std 23, 0x1a0(3) // context->uc_mcontext.gp_regs[23]
+ std 24, 0x1a8(3) // context->uc_mcontext.gp_regs[24]
+ std 25, 0x1b0(3) // context->uc_mcontext.gp_regs[25]
+ std 26, 0x1b8(3) // context->uc_mcontext.gp_regs[26]
+ std 27, 0x1c0(3) // context->uc_mcontext.gp_regs[27]
+ std 28, 0x1c8(3) // context->uc_mcontext.gp_regs[28]
+ std 29, 0x1d0(3) // context->uc_mcontext.gp_regs[29]
+ std 30, 0x1d8(3) // context->uc_mcontext.gp_regs[30]
+ std 31, 0x1e0(3) // context->uc_mcontext.gp_regs[31]
+
+ // For NIP, we can use the value in the link register
+ mflr 0
+ std 0, 0x1e8(3) // context->uc_mcontext.gp_regs[PT_NIP]
+
+ // CTR
+ mfctr 0
+ std 0, 0x200(3) // context->uc_mcontext.gp_regs[PT_CTR]
+
+ // For LNK, we'll use the caller's LR save area (2 stack frames up).
+ // r4 can be used as a scratch register since it has already been saved.
+ ld 4, 0(1)
+ ld 4, 16(4)
+ std 4, 0x208(3) // context->uc_mcontext.gp_regs[PT_LNK]
+
+ // XER
+ mfxer 0
+ std 0, 0x210(3) // context->uc_mcontext.gp_regs[PT_XER]
+
+ // CCR
+ mfcr 0
+ std 0, 0x218(3) // context->uc_mcontext.gp_regs[PT_CCR]
+
+ // MSR, orig_r3, MQ, TRAP, DAR, DSISR, RESULT, DSCR,
+ // not used or not relevant, zero them out.
+ li 4, 0
+ std 4, 0x1f0(3) // context->uc_mcontext.gp_regs[PT_MSR]
+ std 4, 0x1f8(3) // context->uc_mcontext.gp_regs[PT_ORIG_R3]
+ std 4, 0x220(3) // context->uc_mcontext.gp_regs[PT_MQ]
+ std 4, 0x228(3) // context->uc_mcontext.gp_regs[PT_TRAP]
+ std 4, 0x230(3) // context->uc_mcontext.gp_regs[PT_DAR]
+ std 4, 0x238(3) // context->uc_mcontext.gp_regs[PT_DSISR]
+ std 4, 0x240(3) // context->uc_mcontext.gp_regs[PT_RESULT]
+ std 4, 0x248(3) // context->uc_mcontext.gp_regs[PT_DSCR]
+
+ // Update context->uc_mcontext.regs to point to gp_regs
+ addi 0, 3, 0xe8
+ std 0, 0xe0(3)
+
+ // Save floating point registers 0-31
+ stfd 0, 0x268(3) // context->uc_mcontext.fp_regs[0]
+ stfd 1, 0x270(3) // context->uc_mcontext.fp_regs[1]
+ stfd 2, 0x278(3) // context->uc_mcontext.fp_regs[2]
+ stfd 3, 0x280(3) // context->uc_mcontext.fp_regs[3]
+ stfd 4, 0x288(3) // context->uc_mcontext.fp_regs[4]
+ stfd 5, 0x290(3) // context->uc_mcontext.fp_regs[5]
+ stfd 6, 0x298(3) // context->uc_mcontext.fp_regs[6]
+ stfd 7, 0x2a0(3) // context->uc_mcontext.fp_regs[7]
+ stfd 8, 0x2a8(3) // context->uc_mcontext.fp_regs[8]
+ stfd 9, 0x2b0(3) // context->uc_mcontext.fp_regs[9]
+ stfd 10, 0x2b8(3) // context->uc_mcontext.fp_regs[10]
+ stfd 11, 0x2c0(3) // context->uc_mcontext.fp_regs[11]
+ stfd 12, 0x2c8(3) // context->uc_mcontext.fp_regs[12]
+ stfd 13, 0x2d0(3) // context->uc_mcontext.fp_regs[13]
+ stfd 14, 0x2d8(3) // context->uc_mcontext.fp_regs[14]
+ stfd 15, 0x2e0(3) // context->uc_mcontext.fp_regs[15]
+ stfd 16, 0x2e8(3) // context->uc_mcontext.fp_regs[16]
+ stfd 17, 0x2f0(3) // context->uc_mcontext.fp_regs[17]
+ stfd 18, 0x2f8(3) // context->uc_mcontext.fp_regs[18]
+ stfd 19, 0x300(3) // context->uc_mcontext.fp_regs[19]
+ stfd 20, 0x308(3) // context->uc_mcontext.fp_regs[20]
+ stfd 21, 0x310(3) // context->uc_mcontext.fp_regs[21]
+ stfd 22, 0x318(3) // context->uc_mcontext.fp_regs[22]
+ stfd 23, 0x320(3) // context->uc_mcontext.fp_regs[23]
+ stfd 24, 0x328(3) // context->uc_mcontext.fp_regs[24]
+ stfd 25, 0x330(3) // context->uc_mcontext.fp_regs[25]
+ stfd 26, 0x338(3) // context->uc_mcontext.fp_regs[26]
+ stfd 27, 0x340(3) // context->uc_mcontext.fp_regs[27]
+ stfd 28, 0x348(3) // context->uc_mcontext.fp_regs[28]
+ stfd 29, 0x350(3) // context->uc_mcontext.fp_regs[29]
+ stfd 30, 0x358(3) // context->uc_mcontext.fp_regs[30]
+ stfd 31, 0x360(3) // context->uc_mcontext.fp_regs[31]
+
+ // FPSCR
+ mffs 0
+ stfd 0, 0x368(3) // context->uc_mcontext.fp_regs[32]
+
+ // Save VMX Vector registers
+ // Update r4 to contain the base address of vmx_reserve
+ addi 4, 3, 0x378
+ // Ensure that it is quadword aligned
+ andi. 5, 4, 0xF
+ beq 1f // No alignment is necessary
+ // Address is doubleword aligned and not quadword aligned, add 8
+ addi 4, 4, 8
+
+1:
+ // Store VMX registers 0-31
+ // r4 will contain the base address
+ // r5 will contain the index
+ li 5, 0
+ stvx 0, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 0]
+ addi 5, 5, 16
+ stvx 1, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 1]
+ addi 5, 5, 16
+ stvx 2, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 2]
+ addi 5, 5, 16
+ stvx 3, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 3]
+ addi 5, 5, 16
+ stvx 4, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 4]
+ addi 5, 5, 16
+ stvx 5, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 5]
+ addi 5, 5, 16
+ stvx 6, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 6]
+ addi 5, 5, 16
+ stvx 7, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 7]
+ addi 5, 5, 16
+ stvx 8, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 8]
+ addi 5, 5, 16
+ stvx 9, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 9]
+ addi 5, 5, 16
+ stvx 10, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 10]
+ addi 5, 5, 16
+ stvx 11, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 11]
+ addi 5, 5, 16
+ stvx 12, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 12]
+ addi 5, 5, 16
+ stvx 13, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 13]
+ addi 5, 5, 16
+ stvx 14, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 14]
+ addi 5, 5, 16
+ stvx 15, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 15]
+ addi 5, 5, 16
+ stvx 16, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 16]
+ addi 5, 5, 16
+ stvx 17, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 17]
+ addi 5, 5, 16
+ stvx 18, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 18]
+ addi 5, 5, 16
+ stvx 19, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 19]
+ addi 5, 5, 16
+ stvx 20, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 20]
+ addi 5, 5, 16
+ stvx 21, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 21]
+ addi 5, 5, 16
+ stvx 22, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 22]
+ addi 5, 5, 16
+ stvx 23, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 23]
+ addi 5, 5, 16
+ stvx 24, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 24]
+ addi 5, 5, 16
+ stvx 25, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 25]
+ addi 5, 5, 16
+ stvx 26, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 26]
+ addi 5, 5, 16
+ stvx 27, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 27]
+ addi 5, 5, 16
+ stvx 28, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 28]
+ addi 5, 5, 16
+ stvx 29, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 29]
+ addi 5, 5, 16
+ stvx 30, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 30]
+ addi 5, 5, 16
+ stvx 31, 4, 5 // context->uc_mcontext.vmx_reserve[(align) + 31]
+ addi 5, 5, 16
+
+ // VSCR
+ mfvscr 0
+ stvx 0, 4, 5
+ addi 5, 5, 16
+
+ // VRSAVE
+ mfvrsave 0
+ stwx 0, 4, 5
+
+ // Update context->uc_mcontext.v_regs to point to vmx_reserve + alignment.
+ std 4, 0x370(3)
+
+ // Zero out all unused fields
+ li 4, 0
+ std 4, 0xc8(3) // context->uc_mcontext.signal
+ std 4, 0xd0(3) // context->uc_mcontext.handler
+ std 4, 0xd8(3) // context->uc_mcontext.oldmask
+
+ blr
#endif // __i386__
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_test.cc b/third_party/crashpad/crashpad/util/misc/capture_context_test.cc
index cf23c2deff..5f264bc923 100644
--- a/third_party/crashpad/crashpad/util/misc/capture_context_test.cc
+++ b/third_party/crashpad/crashpad/util/misc/capture_context_test.cc
@@ -57,7 +57,7 @@ void TestCaptureContext() {
uintptr_t pc = ProgramCounterFromContext(context_1);
#if !defined(ADDRESS_SANITIZER) && !defined(ARCH_CPU_MIPS_FAMILY) && \
- !defined(MEMORY_SANITIZER)
+ !defined(MEMORY_SANITIZER) && !defined(ARCH_CPU_PPC64_FAMILY)
// Sanitizers can cause enough code bloat that the “nearby” check would
// likely fail.
const uintptr_t kReferencePC =
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc
index 9fc5db28c4..5f69f8dced 100644
--- a/third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc
+++ b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc
@@ -36,6 +36,8 @@ void SanityCheckContext(const NativeCPUContext& context) {
EXPECT_EQ(context.uc_mcontext.regs[0], FromPointerCast<uintptr_t>(&context));
#elif defined(ARCH_CPU_MIPS_FAMILY)
EXPECT_EQ(context.uc_mcontext.gregs[4], FromPointerCast<uintptr_t>(&context));
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ EXPECT_EQ(context.uc_mcontext.gp_regs[3], FromPointerCast<uintptr_t>(&context));
#endif
}
@@ -50,6 +52,8 @@ uintptr_t ProgramCounterFromContext(const NativeCPUContext& context) {
return context.uc_mcontext.pc;
#elif defined(ARCH_CPU_MIPS_FAMILY)
return context.uc_mcontext.pc;
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ return context.uc_mcontext.gp_regs[PT_NIP];
#endif
}
@@ -64,6 +68,8 @@ uintptr_t StackPointerFromContext(const NativeCPUContext& context) {
return context.uc_mcontext.sp;
#elif defined(ARCH_CPU_MIPS_FAMILY)
return context.uc_mcontext.gregs[29];
+#elif defined(ARCH_CPU_PPC64_FAMILY)
+ return context.uc_mcontext.gp_regs[1];
#endif
}
diff --git a/third_party/crashpad/crashpad/util/posix/signals_test.cc b/third_party/crashpad/crashpad/util/posix/signals_test.cc
index 58bfa8f835..8fc37c464c 100644
--- a/third_party/crashpad/crashpad/util/posix/signals_test.cc
+++ b/third_party/crashpad/crashpad/util/posix/signals_test.cc
@@ -46,12 +46,12 @@ bool CanCauseSignal(int sig) {
return sig == SIGABRT ||
sig == SIGALRM ||
sig == SIGBUS ||
-#if !defined(ARCH_CPU_ARM64)
+#if !defined(ARCH_CPU_ARM64) && !defined(ARCH_CPU_PPC64)
sig == SIGFPE ||
-#endif // !defined(ARCH_CPU_ARM64)
+#endif // !defined(ARCH_CPU_ARM64) && !defined(ARCH_CPU_PPC64)
#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARMEL)
sig == SIGILL ||
-#endif // defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARMEL
+#endif // defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARMEL)
sig == SIGPIPE ||
sig == SIGSEGV ||
#if defined(OS_MACOSX)
@@ -117,9 +117,11 @@ void CauseSignal(int sig) {
break;
}
-#if !defined(ARCH_CPU_ARM64)
+#if !defined(ARCH_CPU_ARM64) && !defined(ARCH_CPU_PPC64)
// ARM64 has hardware integer division instructions that dont generate a
// trap for divide-by-zero, so this doesnt produce SIGFPE.
+ //
+ // PPC64 fixed-point division by zero also doesn't produce a SIGFPE.
case SIGFPE: {
// Optimization makes this tricky, so get zero from a system call likely
// to succeed, and try to do something with the result.
@@ -137,7 +139,7 @@ void CauseSignal(int sig) {
fstat(quotient, &stat_buf);
break;
}
-#endif // ARCH_CPU_ARM64
+#endif // !defined(ARCH_CPU_ARM64) && !defined(ARCH_CPU_PPC64)
#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARMEL)
case SIGILL: {
diff --git a/third_party/dav1d/BUILD.gn b/third_party/dav1d/BUILD.gn
index 788dc6cff9..5fd7e8fda0 100644
--- a/third_party/dav1d/BUILD.gn
+++ b/third_party/dav1d/BUILD.gn
@@ -182,6 +182,8 @@ static_library("dav1d_8bit") {
sources += arm_template_sources
} else if (current_cpu == "arm64") {
sources += arm_template_sources
+ } else if (current_cpu == "ppc64") {
+ sources += ppc64_template_sources
}
cflags = dav1d_copts
@@ -210,6 +212,8 @@ static_library("dav1d_10bit") {
sources += arm_template_sources
} else if (current_cpu == "arm64") {
sources += arm_template_sources
+ } else if (current_cpu == "ppc64") {
+ sources += ppc64_template_sources
}
cflags = dav1d_copts
@@ -256,6 +260,21 @@ if (current_cpu == "x86" || current_cpu == "x64") {
":dav1d_config",
]
+ cflags = dav1d_copts
+ }
+} else if (current_cpu == "ppc64") {
+ static_library("dav1d_ppc") {
+ sources = [
+ "libdav1d/src/ppc/cpu.c",
+ "libdav1d/src/ppc/cpu.h",
+ ]
+
+ configs -= [ "//build/config/compiler:chromium_code" ]
+ configs += [
+ "//build/config/compiler:no_chromium_code",
+ ":dav1d_config",
+ ]
+
cflags = dav1d_copts
}
}
@@ -285,5 +304,7 @@ static_library("dav1d") {
}
} else if (current_cpu == "arm" || current_cpu == "arm64") {
deps += [ ":dav1d_arm" ]
+ } else if (current_cpu == "ppc64") {
+ deps += [ ":dav1d_ppc" ]
}
}
diff --git a/third_party/dav1d/config/linux/ppc64/config.h b/third_party/dav1d/config/linux/ppc64/config.h
new file mode 100644
index 0000000000..f6ca57f7f0
--- /dev/null
+++ b/third_party/dav1d/config/linux/ppc64/config.h
@@ -0,0 +1,35 @@
+/*
+ * Autogenerated by the Meson build system.
+ * Do not edit, your changes will be lost.
+ */
+
+#pragma once
+
+#define ARCH_AARCH64 0
+
+#define ARCH_ARM 0
+
+#define ARCH_PPC64LE 1
+
+#define ARCH_X86 0
+
+#define ARCH_X86_32 0
+
+#define ARCH_X86_64 0
+
+#define CONFIG_16BPC 1
+
+#define CONFIG_8BPC 1
+
+#define CONFIG_LOG 1
+
+#define ENDIANNESS_BIG 0
+
+#define HAVE_ASM 1
+
+#define HAVE_GETAUXVAL 1
+
+#define HAVE_POSIX_MEMALIGN 1
+
+#define HAVE_UNISTD_H 1
+
diff --git a/third_party/dav1d/dav1d_generated.gni b/third_party/dav1d/dav1d_generated.gni
index 458935cd8a..f0cbc4aede 100644
--- a/third_party/dav1d/dav1d_generated.gni
+++ b/third_party/dav1d/dav1d_generated.gni
@@ -70,6 +70,11 @@ arm_template_sources = [
"libdav1d/src/arm/mc_init_tmpl.c",
]
+ppc64_template_sources = [
+ "libdav1d/src/ppc/cdef_init_tmpl.c",
+ "libdav1d/src/ppc/looprestoration_init_tmpl.c",
+]
+
template_sources = [
"libdav1d/src/cdef_apply_tmpl.c",
"libdav1d/src/cdef_tmpl.c",
diff --git a/third_party/dav1d/generate_source.py b/third_party/dav1d/generate_source.py
index 9ab5e00b83..ad3feffee4 100755
--- a/third_party/dav1d/generate_source.py
+++ b/third_party/dav1d/generate_source.py
@@ -50,7 +50,8 @@ def WriteGn(fd):
WriteArray(fd, "arm32_asm_sources", glob.glob("libdav1d/src/arm/32/*.S"))
WriteArray(fd, "arm64_asm_sources", glob.glob("libdav1d/src/arm/64/*.S"))
WriteArray(fd, "arm_template_sources", glob.glob("libdav1d/src/arm/*_tmpl.c"))
-
+ WriteArray(fd, "ppc64_template_sources", glob.glob("libdav1d/src/ppc/*_tmpl.c"))
+
template_sources = glob.glob("libdav1d/src/*_tmpl.c")
WriteArray(fd, "template_sources", template_sources)
diff --git a/third_party/dav1d/libdav1d/src/ppc/types.h b/third_party/dav1d/libdav1d/src/ppc/types.h
index 0b4bd72f0e..a0caa5e710 100644
--- a/third_party/dav1d/libdav1d/src/ppc/types.h
+++ b/third_party/dav1d/libdav1d/src/ppc/types.h
@@ -51,4 +51,19 @@
#define u16l_to_i32(v) ((i32x4) vec_mergel((u16x8) v, vec_splat_u16(0)))
#define i16l_to_i32(v) ((i32x4) vec_unpackl((i16x8)v))
+#if defined(__clang__)
+#undef vec_splats
+#define vec_splats(N) \
+ _Generic((N), \
+ unsigned char: ((u8x16)(N)), \
+ signed char: ((i8x16)(N)), \
+ unsigned short: ((u16x8)(N)), \
+ signed short: ((i16x8)(N)), \
+ unsigned int: ((u32x4)(N)), \
+ signed int: ((i32x4)(N)), \
+ unsigned long long: ((u64x2)(N)), \
+ signed long long: ((i64x2)(N)) \
+ )
+#endif
+
#endif /* DAV1D_SRC_PPC_TYPES_H */
diff --git a/third_party/libvpx/BUILD.gn b/third_party/libvpx/BUILD.gn
index 31a26e5b44..84c15b61b8 100644
--- a/third_party/libvpx/BUILD.gn
+++ b/third_party/libvpx/BUILD.gn
@@ -38,6 +38,8 @@ if (current_cpu == "x86") {
if (is_nacl) {
platform_include_dir = "source/config/nacl"
+} else if (current_cpu == "ppc64") {
+ platform_include_dir = "source/config/linux/generic"
} else {
# The mac configurations are currently a relic. They were useful when
# x86inc.asm did not work for MACH_O but now the build is identical to the
@@ -336,6 +338,8 @@ static_library("libvpx") {
} else {
sources = libvpx_srcs_arm64
}
+ } else if (current_cpu == "ppc64") {
+ sources = libvpx_srcs_generic
}
configs -= [ "//build/config/compiler:chromium_code" ]
diff --git a/third_party/lss/linux_syscall_support.h b/third_party/lss/linux_syscall_support.h
index d2baee9d24..9955ce446b 100644
--- a/third_party/lss/linux_syscall_support.h
+++ b/third_party/lss/linux_syscall_support.h
@@ -3922,7 +3922,7 @@ struct kernel_statfs {
LSS_REG(2, buf);
LSS_BODY(void*, mmap2, "0"(__r2));
}
-#else
+#elif !defined(__powerpc64__) /* ppc64 doesn't have mmap2 */
#define __NR__mmap2 __NR_mmap2
LSS_INLINE _syscall6(void*, _mmap2, void*, s,
size_t, l, int, p,
@@ -4033,7 +4033,7 @@ struct kernel_statfs {
#if defined(__i386__) || \
defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \
(defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \
- defined(__PPC__) || \
+ (defined(__PPC__) && !defined(__powerpc64__)) || \
(defined(__s390__) && !defined(__s390x__))
/* On these architectures, implement mmap() with mmap2(). */
LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
diff --git a/third_party/pffft/src/pffft.c b/third_party/pffft/src/pffft.c
index bdac4d7849..51e0f2cacc 100644
--- a/third_party/pffft/src/pffft.c
+++ b/third_party/pffft/src/pffft.c
@@ -100,6 +100,7 @@
Altivec support macros
*/
#if !defined(PFFFT_SIMD_DISABLE) && (defined(__ppc__) || defined(__ppc64__))
+#include <altivec.h>
typedef vector float v4sf;
# define SIMD_SZ 4
# define VZERO() ((vector float) vec_splat_u8(0))
diff --git a/third_party/skia/src/sksl/SkSLString.cpp b/third_party/skia/src/sksl/SkSLString.cpp
index 88eb1c7d3b..4be33fa5bd 100644
--- a/third_party/skia/src/sksl/SkSLString.cpp
+++ b/third_party/skia/src/sksl/SkSLString.cpp
@@ -240,7 +240,12 @@ String to_string(double value) {
if (needsDotZero) {
buffer << ".0";
}
- return String(buffer.str().c_str());
+
+ std::string ret(buffer.str());
+ if (signbit(value) && ret[0] == '.') {
+ ret[0] = '-';
+ }
+ return String(ret.c_str());
}
SKSL_INT stoi(const String& s) {
diff --git a/third_party/sqlite/src/amalgamation/sqlite3.c b/third_party/sqlite/src/amalgamation/sqlite3.c
index b8e84c1b6a..9ba9cb6c14 100644
--- a/third_party/sqlite/src/amalgamation/sqlite3.c
+++ b/third_party/sqlite/src/amalgamation/sqlite3.c
@@ -14301,7 +14301,8 @@ typedef INT16_TYPE LogEst;
# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64)
+ defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64) || \
+ defined(__powerpc64__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
# define SQLITE_BYTEORDER 1234
# elif defined(sparc) || defined(__ppc__) || \
defined(__ARMEB__) || defined(__AARCH64EB__)
diff --git a/third_party/sqlite/src/amalgamation_dev/sqlite3.c b/third_party/sqlite/src/amalgamation_dev/sqlite3.c
index 734ac355d2..e259911dfd 100644
--- a/third_party/sqlite/src/amalgamation_dev/sqlite3.c
+++ b/third_party/sqlite/src/amalgamation_dev/sqlite3.c
@@ -14314,7 +14314,8 @@ typedef INT16_TYPE LogEst;
# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64)
+ defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64) || \
+ defined(__powerpc64__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
# define SQLITE_BYTEORDER 1234
# elif defined(sparc) || defined(__ppc__) || \
defined(__ARMEB__) || defined(__AARCH64EB__)
diff --git a/third_party/sqlite/src/ext/rtree/rtree.c b/third_party/sqlite/src/ext/rtree/rtree.c
index 1eef1a1b53..b53097b7f4 100644
--- a/third_party/sqlite/src/ext/rtree/rtree.c
+++ b/third_party/sqlite/src/ext/rtree/rtree.c
@@ -432,7 +432,7 @@ struct RtreeMatchArg {
#if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__arm__)
+ defined(__arm__) || defined(__powerpc64__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
# define SQLITE_BYTEORDER 1234
#elif defined(sparc) || defined(__ppc__)
# define SQLITE_BYTEORDER 4321
diff --git a/third_party/sqlite/src/src/sqliteInt.h b/third_party/sqlite/src/src/sqliteInt.h
index 9ef2437b06..db5d3321ed 100644
--- a/third_party/sqlite/src/src/sqliteInt.h
+++ b/third_party/sqlite/src/src/sqliteInt.h
@@ -853,7 +853,8 @@ typedef INT16_TYPE LogEst;
# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64)
+ defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64) || \
+ defined(__powerpc64__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
# define SQLITE_BYTEORDER 1234
# elif defined(sparc) || defined(__ppc__) || \
defined(__ARMEB__) || defined(__AARCH64EB__)
diff --git a/third_party/webrtc/modules/desktop_capture/differ_block.cc b/third_party/webrtc/modules/desktop_capture/differ_block.cc
index dd9ab457e0..c005d95990 100644
--- a/third_party/webrtc/modules/desktop_capture/differ_block.cc
+++ b/third_party/webrtc/modules/desktop_capture/differ_block.cc
@@ -30,11 +30,7 @@ bool VectorDifference(const uint8_t* image1, const uint8_t* image2) {
static bool (*diff_proc)(const uint8_t*, const uint8_t*) = nullptr;
if (!diff_proc) {
-#if defined(WEBRTC_ARCH_ARM_FAMILY) || defined(WEBRTC_ARCH_MIPS_FAMILY)
- // For ARM and MIPS processors, always use C version.
- // TODO(hclam): Implement a NEON version.
- diff_proc = &VectorDifference_C;
-#else
+#if defined(WEBRTC_ARCH_X86_FAMILY)
bool have_sse2 = WebRtc_GetCPUInfo(kSSE2) != 0;
// For x86 processors, check if SSE2 is supported.
if (have_sse2 && kBlockSize == 32) {
@@ -44,6 +40,10 @@ bool VectorDifference(const uint8_t* image1, const uint8_t* image2) {
} else {
diff_proc = &VectorDifference_C;
}
+#else
+ // For other processors, always use C version.
+ // TODO(hclam): Implement a NEON version.
+ diff_proc = &VectorDifference_C;
#endif
}
diff --git a/third_party/webrtc/rtc_base/system/arch.h b/third_party/webrtc/rtc_base/system/arch.h
index ed216e660f..25d36c071a 100644
--- a/third_party/webrtc/rtc_base/system/arch.h
+++ b/third_party/webrtc/rtc_base/system/arch.h
@@ -50,6 +50,18 @@
#elif defined(__EMSCRIPTEN__)
#define WEBRTC_ARCH_32_BITS
#define WEBRTC_ARCH_LITTLE_ENDIAN
+#elif defined(__PPC__)
+#define WEBRTC_ARCH_PPC_FAMILY
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#else
+#define WEBRTC_ARCH_BIG_ENDIAN
+#endif
+#if defined(__LP64__)
+#define WEBRTC_ARCH_64_BITS
+#else
+#define WEBRTC_ARCH_32_BITS
+#endif
#else
#error Please add support for your architecture in rtc_base/system/arch.h
#endif
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index 8fac30ee40..9e0c536d1b 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -15,7 +15,8 @@ declare_args() {
is_chromeos || is_fuchsia) &&
(target_cpu == "x86" || target_cpu == "x64" ||
target_cpu == "arm" || target_cpu == "arm64" ||
- target_cpu == "mipsel" || target_cpu == "mips64el")
+ target_cpu == "mipsel" || target_cpu == "mips64el" ||
+ target_cpu == "ppc64")
# Whether service side logging (actual calls into the GL driver) is enabled
# or not.
diff --git a/v8/BUILD.gn b/v8/BUILD.gn
index b2dde3f9d7..7c28f900e1 100644
--- a/v8/BUILD.gn
+++ b/v8/BUILD.gn
@@ -673,6 +673,12 @@ config("toolchain") {
}
if (host_byteorder == "little") {
defines += [ "V8_TARGET_ARCH_PPC_LE" ]
+ cflags += [
+ # Enable usage of AltiVec, VSX, and other POWER8 and higher features
+ "-mcpu=power8",
+ "-maltivec",
+ "-mvsx",
+ ]
} else if (host_byteorder == "big") {
defines += [ "V8_TARGET_ARCH_PPC_BE" ]
if (current_os == "aix") {
diff --git a/v8/test/BUILD.gn b/v8/test/BUILD.gn
index f6d30537a8..287b270809 100644
--- a/v8/test/BUILD.gn
+++ b/v8/test/BUILD.gn
@@ -31,7 +31,7 @@ group("gn_all") {
deps += [
"cctest:cctest",
"cctest:generate-bytecode-expectations",
- "unittests:unittests",
+ #"unittests:unittests",
]
}
}
@@ -73,7 +73,7 @@ group("v8_bot_default") {
"message:v8_message",
"mjsunit:v8_mjsunit",
"mkgrokdump:mkgrokdump",
- "unittests:unittests",
+ #"unittests:unittests",
"wasm-api-tests:wasm_api_tests",
"wasm-js:v8_wasm_js",
"wasm-spec-tests:v8_wasm_spec_tests",
@@ -93,7 +93,7 @@ group("v8_default") {
"message:v8_message",
"mjsunit:v8_mjsunit",
"mkgrokdump:mkgrokdump",
- "unittests:unittests",
+ #"unittests:unittests",
"wasm-api-tests:wasm_api_tests",
"wasm-js:v8_wasm_js",
"wasm-spec-tests:v8_wasm_spec_tests",
--
2.28.0