Github messages for voidlinux
 help / color / mirror / Atom feed
* [PR PATCH] [WiP] New package: electron13-13.0.0
@ 2021-05-26 19:41 Johnnynator
  2021-08-29  0:24 ` [PR PATCH] [Updated] " Johnnynator
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Johnnynator @ 2021-05-26 19:41 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 1753 bytes --]

There is a new pull request by Johnnynator against master on the void-packages repository

https://github.com/Johnnynator/void-packages electron13
https://github.com/void-linux/void-packages/pull/31136

[WiP] New package: electron13-13.0.0
<!-- Mark items with [x] where applicable -->

#### General
- [ ] This is a new package and it conforms to the [quality requirements](https://github.com/void-linux/void-packages/blob/master/Manual.md#quality-requirements)

#### Have the results of the proposed changes been tested?
- [ ] I use the packages affected by the proposed changes on a regular basis and confirm this PR works for me
- [ ] I generally don't use the affected packages but briefly tested this PR

- This doesn't compile yet on musl, they move a lot of dns stuff from generic posix to a linux specific file, that ofc only works for glibc.

<!--
If GitHub CI cannot be used to validate the build result (for example, if the
build is likely to take several hours), make sure to
[skip CI](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#continuous-integration).
When skipping CI, uncomment and fill out the following section.
Note: for builds that are likely to complete in less than 2 hours, it is not
acceptable to skip CI.
-->
<!-- 
#### Does it build and run successfully? 
(Please choose at least one native build and, if supported, at least one cross build. More are better.)
- [ ] I built this PR locally for my native architecture, (ARCH-LIBC)
- [ ] I built this PR locally for these architectures (if supported. mark crossbuilds):
  - [ ] aarch64-musl
  - [ ] armv7l
  - [ ] armv6l-musl
-->


A patch file from https://github.com/void-linux/void-packages/pull/31136.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-electron13-31136.patch --]
[-- Type: text/x-diff, Size: 290729 bytes --]

From fb48e06a37b6d87ea34202d750fae4af50433888 Mon Sep 17 00:00:00 2001
From: John <me@johnnynator.dev>
Date: Wed, 26 May 2021 21:38:32 +0200
Subject: [PATCH] New package: electron13-13.0.0

---
 .../chromium-default-pthread-stacksize.patch  |   29 +
 .../musl-patches/chromium-musl-crashpad.patch |   23 +
 .../musl-patches/chromium-musl-dns.patch      |   32 +
 .../musl-patches/chromium-musl-fixes.patch    |  201 +
 .../musl-patches/chromium-musl-hacks.patch    |   22 +
 .../musl-patches/chromium-musl-libc++.patch   |   55 +
 .../musl-patches/chromium-musl-sandbox.patch  |   92 +
 .../musl-patches/chromium-musl-sync.patch     |   30 +
 .../chromium-musl-xxx-ppc64le.patch           |  190 +
 .../musl-patches/chromium-no-mallinfo.patch   |   54 +
 .../musl-patches/chromium-resolver.patch      |   38 +
 .../patches/chromium-88-glibc-2.33.patch      |  144 +
 .../patches/chromium-browser-size_t.patch     |   10 +
 .../files/patches/chromium-libc_malloc.patch  |   26 +
 ...-v8-monotonic-pthread-cont_timedwait.patch |   24 +
 .../files/patches/chromium-no-execinfo.patch  |   72 +
 .../patches/chromium-no-getcontext.patch      |   27 +
 .../chromium-revert-drop-of-system-java.patch |   15 +
 .../patches/chromium-sandbox-membarrier.patch |   10 +
 .../chromium-sandbox-sched_getparam.patch     |   20 +
 .../files/patches/chromium-sndio.patch        |  886 ++++
 .../patches/chromium-system-nodejs.patch      |   20 +
 .../patches/chromium-webrtc-include.patch     |   10 +
 .../files/patches/chromium-webrtc-r0.patch    |   33 +
 .../patches/chromium-webrtc-size_t.patch      |   10 +
 .../patches/chromium-xxx-ppc64le-libvpx.patch |   72 +
 .../chromium-xxx-ppc64le-support.patch        | 3636 +++++++++++++++++
 .../chromium-xxx-ppc64le-swiftshader.patch    |   18 +
 ...a-script-to-list-patch-targets.patch.patch |   42 +
 .../patches/electron-Build-fixes.patch.patch  |   47 +
 ...ectron-dont-assume-python-is-python2.patch |   17 +
 ...lectron-exclude-content-test-patches.patch |   10 +
 .../sndio-files/audio_manager_openbsd.cc      |  148 +
 .../files/sndio-files/audio_manager_openbsd.h |   65 +
 .../files/sndio-files/sndio_input.cc          |  200 +
 .../files/sndio-files/sndio_input.h           |   91 +
 .../files/sndio-files/sndio_output.cc         |  183 +
 .../files/sndio-files/sndio_output.h          |   86 +
 ...a_audio_linux_audio_manager_linux.cc.patch |   43 +
 ...src_3rdparty_chromium_media_BUILD.gn.patch |   12 +
 ...dparty_chromium_media_audio_BUILD.gn.patch |   23 +
 ...ty_chromium_media_media__options.gni.patch |   12 +
 srcpkgs/electron13/template                   |  385 ++
 srcpkgs/electron13/update                     |    2 +
 44 files changed, 7165 insertions(+)
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-default-pthread-stacksize.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-crashpad.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-dns.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-fixes.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-hacks.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-libc++.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-sandbox.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-sync.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-xxx-ppc64le.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-no-mallinfo.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-resolver.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-88-glibc-2.33.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-browser-size_t.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-libc_malloc.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-musl-v8-monotonic-pthread-cont_timedwait.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-no-execinfo.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-no-getcontext.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-revert-drop-of-system-java.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-sandbox-membarrier.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-sandbox-sched_getparam.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-sndio.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-system-nodejs.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-webrtc-include.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-webrtc-r0.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-webrtc-size_t.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-libvpx.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-support.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-swiftshader.patch
 create mode 100644 srcpkgs/electron13/files/patches/electron-Add-a-script-to-list-patch-targets.patch.patch
 create mode 100644 srcpkgs/electron13/files/patches/electron-Build-fixes.patch.patch
 create mode 100644 srcpkgs/electron13/files/patches/electron-dont-assume-python-is-python2.patch
 create mode 100644 srcpkgs/electron13/files/patches/electron-exclude-content-test-patches.patch
 create mode 100644 srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.cc
 create mode 100644 srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.h
 create mode 100644 srcpkgs/electron13/files/sndio-files/sndio_input.cc
 create mode 100644 srcpkgs/electron13/files/sndio-files/sndio_input.h
 create mode 100644 srcpkgs/electron13/files/sndio-files/sndio_output.cc
 create mode 100644 srcpkgs/electron13/files/sndio-files/sndio_output.h
 create mode 100644 srcpkgs/electron13/files/sndio-patches/media_audio_linux_audio_manager_linux.cc.patch
 create mode 100644 srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_BUILD.gn.patch
 create mode 100644 srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_audio_BUILD.gn.patch
 create mode 100644 srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_media__options.gni.patch
 create mode 100644 srcpkgs/electron13/template
 create mode 100644 srcpkgs/electron13/update

diff --git a/srcpkgs/electron13/files/musl-patches/chromium-default-pthread-stacksize.patch b/srcpkgs/electron13/files/musl-patches/chromium-default-pthread-stacksize.patch
new file mode 100644
index 000000000000..16e4d21e6ed8
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-default-pthread-stacksize.patch
@@ -0,0 +1,29 @@
+--- base/threading/platform_thread_linux.cc.orig
++++ base/threading/platform_thread_linux.cc
+@@ -99 +99,2 @@ size_t GetDefaultThreadStackSize(const p
+-  return 0;
++  // use 8mb like glibc to avoid running out of space
++  return (1 << 23);
+--- chrome/app/shutdown_signal_handlers_posix.cc.orig
++++ chrome/app/shutdown_signal_handlers_posix.cc
+@@ -184,11 +184,19 @@
+   g_shutdown_pipe_read_fd = pipefd[0];
+   g_shutdown_pipe_write_fd = pipefd[1];
+ #if !defined(ADDRESS_SANITIZER)
++# if defined(__GLIBC__)
+   const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 2;
++# else
++  const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 2 * 8; // match up musls 2k PTHREAD_STACK_MIN with glibcs 16k
++# endif
+ #else
+   // ASan instrumentation bloats the stack frames, so we need to increase the
+   // stack size to avoid hitting the guard page.
++# if defined(__GLIBC__)
+   const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 4;
++# else
++  const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 4 * 8; // match up musls 2k PTHREAD_STACK_MIN with glibcs 16k
++# endif
+ #endif
+   ShutdownDetector* detector = new ShutdownDetector(
+       g_shutdown_pipe_read_fd, shutdown_callback, task_runner);
+
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-crashpad.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-crashpad.patch
new file mode 100644
index 000000000000..03a0c06f3ca6
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-crashpad.patch
@@ -0,0 +1,23 @@
+--- third_party/crashpad/crashpad/util/linux/ptracer.cc
++++ third_party/crashpad/crashpad/util/linux/ptracer.cc
+@@ -26,6 +26,7 @@
+ 
+ #if defined(ARCH_CPU_X86_FAMILY)
+ #include <asm/ldt.h>
++#include <asm/ptrace-abi.h>
+ #endif
+ 
+ namespace crashpad {
+
+--- third_party/crashpad/crashpad/compat/linux/sys/ptrace.h
++++ third_party/crashpad/crashpad/compat/linux/sys/ptrace.h
+@@ -17,7 +17,9 @@
+ 
+ #include_next <sys/ptrace.h>
+ 
++#if defined(__GLIBC__)
+ #include <sys/cdefs.h>
++#endif
+ 
+ // https://sourceware.org/bugzilla/show_bug.cgi?id=22433
+ #if !defined(PTRACE_GET_THREAD_AREA) && !defined(PT_GET_THREAD_AREA) && \
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-dns.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-dns.patch
new file mode 100644
index 000000000000..57cc0ac6c18a
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-dns.patch
@@ -0,0 +1,32 @@
+--- net/features.gni	2021-05-20 04:17:11.000000000 +0200
++++ -	2021-05-26 16:03:25.826113608 +0200
+@@ -28,6 +28,9 @@
+   # Reporting not used on iOS.
+   enable_reporting = !is_ios
+ 
++  # Force Posix dns config
++  force_posix_dns = true
++
+   # Includes the transport security state preload list. This list includes
+   # mechanisms (e.g. HSTS, HPKP) to enforce trusted connections to a significant
+   # set of hardcoded domains. While this list has a several hundred KB of binary
+--- net/dns/BUILD.gn	2021-05-20 04:17:11.000000000 +0200
++++ -	2021-05-26 16:05:01.510622102 +0200
+@@ -114,7 +114,7 @@
+         "dns_config_service_android.cc",
+         "dns_config_service_android.h",
+       ]
+-    } else if (is_linux) {
++    } else if (is_linux && !force_posix_dns) {
+       sources += [
+         "dns_config_service_linux.cc",
+         "dns_config_service_linux.h",
+@@ -433,7 +433,7 @@
+ 
+   if (is_android) {
+     sources += [ "dns_config_service_android_unittest.cc" ]
+-  } else if (is_linux) {
++  } else if (is_linux && !force_posix_dns) {
+     sources += [ "dns_config_service_linux_unittest.cc" ]
+   } else if (is_posix) {
+     sources += [ "dns_config_service_posix_unittest.cc" ]
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-fixes.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-fixes.patch
new file mode 100644
index 000000000000..d4eabc93db56
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-fixes.patch
@@ -0,0 +1,201 @@
+--- ./third_party/lss/linux_syscall_support.h.orig
++++ ./third_party/lss/linux_syscall_support.h
+@@ -1127,6 +1127,12 @@
+ #ifndef __NR_fallocate
+ #define __NR_fallocate          285
+ #endif
++
++#undef __NR_pread
++#define __NR_pread __NR_pread64
++#undef __NR_pwrite
++#define __NR_pwrite __NR_pwrite64
++
+ /* End of x86-64 definitions                                                 */
+ #elif defined(__mips__)
+ #if _MIPS_SIM == _MIPS_SIM_ABI32
+--- ./third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h.orig
++++ ./third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h
+@@ -37,6 +37,10 @@
+ #include "common/memory.h"
+ #include "google_breakpad/common/minidump_format.h"
+ 
++#if !defined(__GLIBC__)
++	#define _libc_fpstate _fpstate
++#endif
++
+ namespace google_breakpad {
+ 
+ // Wraps platform-dependent implementations of accessors to ucontext_t structs.
+--- ./third_party/breakpad/breakpad/src/common/linux/elf_core_dump.h.orig
++++ ./third_party/breakpad/breakpad/src/common/linux/elf_core_dump.h
+@@ -36,6 +36,7 @@
+ #include <elf.h>
+ #include <link.h>
+ #include <stddef.h>
++#include <limits.h>
+ 
+ #include "common/memory_range.h"
+ 
+--- ./sandbox/linux/suid/process_util.h.orig
++++ ./sandbox/linux/suid/process_util.h
+@@ -11,6 +11,14 @@
+ #include <stdbool.h>
+ #include <sys/types.h>
+ 
++// Some additional functions
++# define TEMP_FAILURE_RETRY(expression) \
++	(__extension__			\
++	 ({ long int __result;		\
++	  do __result = (long int) (expression); \
++	  while (__result == -1L && errno == EINTR); \
++	  __result; }))
++
+ // This adjusts /proc/process/oom_score_adj so the Linux OOM killer
+ // will prefer certain process types over others. The range for the
+ // adjustment is [-1000, 1000], with [0, 1000] being user accessible.
+--- ./sandbox/linux/seccomp-bpf/trap.cc.orig	2020-04-12 08:26:40.184159217 -0400
++++ ./sandbox/linux/seccomp-bpf/trap.cc	2020-04-12 08:46:16.737191222 -0400
+@@ -174,7 +174,7 @@
+   // If the version of glibc doesn't include this information in
+   // siginfo_t (older than 2.17), we need to explicitly copy it
+   // into an arch_sigsys structure.
+-  memcpy(&sigsys, &info->_sifields, sizeof(sigsys));
++  memcpy(&sigsys, &info->__sifields, sizeof(sigsys));
+ #endif
+ 
+ #if defined(__mips__)
+--- ./third_party/ffmpeg/libavutil/cpu.c.orig
++++ ./third_party/ffmpeg/libavutil/cpu.c
+@@ -38,7 +38,6 @@
+ #include <sys/param.h>
+ #endif
+ #include <sys/types.h>
+-#include <sys/sysctl.h>
+ #endif
+ #if HAVE_UNISTD_H
+ #include <unistd.h>
+diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
+--- chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc.orig	2021-03-10 07:23:00.145810088 -0500
++++ chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc	2021-03-10 10:57:19.405962671 -0500
+@@ -55,7 +55,9 @@
+ // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+ // of lacros-chrome is complete.
+ #if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
++#if defined(__GLIBC__)
+ #include <gnu/libc-version.h>
++#endif
+ 
+ #include "base/linux_util.h"
+ #include "base/strings/string_split.h"
+@@ -316,7 +318,7 @@
+ void RecordLinuxGlibcVersion() {
+ // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+ // of lacros-chrome is complete.
+-#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
++#if defined(__GLIBC__) || BUILDFLAG(IS_CHROMEOS_LACROS)
+   base::Version version(gnu_get_libc_version());
+ 
+   UMALinuxGlibcVersion glibc_version_result = UMA_LINUX_GLIBC_NOT_PARSEABLE;
+--- services/device/serial/serial_io_handler_posix.cc.orig	2019-07-03 10:57:32.568171835 -0400
++++ services/device/serial/serial_io_handler_posix.cc	2019-07-03 10:57:16.867983031 -0400
+@@ -6,6 +6,7 @@
+ 
+ #include <sys/ioctl.h>
+ #include <termios.h>
++#include <asm-generic/ioctls.h>
+ 
+ #include <algorithm>
+ #include <utility>
+diff --git a/third_party/ots/include/opentype-sanitiser.h b/third_party/ots/include/opentype-sanitiser.h
+--- third_party/ots/src/include/opentype-sanitiser.h
++++ third_party/ots/src/include/opentype-sanitiser.h
+@@ -20,6 +20,7 @@ typedef unsigned __int64 uint64_t;
+ #define htonl(x) _byteswap_ulong (x)
+ #define htons(x) _byteswap_ushort (x)
+ #else
++#include <sys/types.h>
+ #include <arpa/inet.h>
+ #include <stdint.h>
+ #endif
+--- ./base/logging.cc.orig	2021-01-20 12:09:54.227038757 -0500
++++ ./base/logging.cc	2021-01-20 12:24:32.600301351 -0500
+@@ -557,8 +557,7 @@
+ 
+ LogMessage::~LogMessage() {
+   size_t stack_start = stream_.tellp();
+-#if !defined(OFFICIAL_BUILD) && !defined(OS_NACL) && !defined(__UCLIBC__) && \
+-    !defined(OS_AIX)
++#if !defined(OFFICIAL_BUILD) && !defined(OS_NACL) && defined(__GLIBC__)
+   if (severity_ == LOGGING_FATAL && !base::debug::BeingDebugged()) {
+     // Include a stack trace on a fatal, unless a debugger is attached.
+     base::debug::StackTrace stack_trace;
+--- ./third_party/blink/renderer/platform/wtf/stack_util.cc.orig
++++ ./third_party/blink/renderer/platform/wtf/stack_util.cc
+@@ -28,7 +28,7 @@
+ // FIXME: On Mac OSX and Linux, this method cannot estimate stack size
+ // correctly for the main thread.
+ 
+-#elif defined(__GLIBC__) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
++#elif defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
+     defined(OS_FUCHSIA)
+   // pthread_getattr_np() can fail if the thread is not invoked by
+   // pthread_create() (e.g., the main thread of blink_unittests).
+@@ -96,7 +96,7 @@
+ }
+ 
+ void* GetStackStart() {
+-#if defined(__GLIBC__) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
++#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
+     defined(OS_FUCHSIA)
+   pthread_attr_t attr;
+   int error;
+--- third_party/swiftshader/third_party/llvm-subzero/lib/Support/Unix/Signals.inc.orig	2019-06-18 11:51:17.000000000 -0400
++++ third_party/swiftshader/third_party/llvm-subzero/lib/Support/Unix/Signals.inc	2019-07-03 12:32:50.938758186 -0400
+@@ -25,7 +25,7 @@
+ #include "llvm/Support/raw_ostream.h"
+ #include <algorithm>
+ #include <string>
+-#if HAVE_EXECINFO_H
++#if HAVE_EXECINFO_H && defined(__GLIBC__)
+ # include <execinfo.h>         // For backtrace().
+ #endif
+ #if HAVE_SIGNAL_H
+@@ -52,6 +52,7 @@
+ #include <unwind.h>
+ #else
+ #undef HAVE__UNWIND_BACKTRACE
++#undef HAVE_BACKTRACE
+ #endif
+ #endif
+ 
+--- third_party/nasm/nasmlib/realpath.c.orig	2019-07-03 12:23:05.021949895 -0400
++++ third_party/nasm/nasmlib/realpath.c	2019-07-03 12:24:24.246862665 -0400
+@@ -49,7 +49,7 @@
+ 
+ #include "nasmlib.h"
+ 
+-#ifdef HAVE_CANONICALIZE_FILE_NAME
++#if defined(__GLIBC__)
+ 
+ /*
+  * GNU-specific, but avoids the realpath(..., NULL)
+--- third_party/perfetto/include/perfetto/ext/base/thread_utils.h
++++ third_party/perfetto/include/perfetto/ext/base/thread_utils.h
+@@ -29,7 +29,7 @@
+ #include <algorithm>
+ #endif
+ 
+-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
++#if 1
+ #include <sys/prctl.h>
+ #endif
+ 
+@@ -58,7 +58,7 @@ inline bool MaybeSetThreadName(const std::string& name) {
+ 
+ inline bool GetThreadName(std::string& out_result) {
+   char buf[16] = {};
+-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
++#if 1
+   if (prctl(PR_GET_NAME, buf) != 0)
+     return false;
+ #else
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-hacks.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-hacks.patch
new file mode 100644
index 000000000000..edc1b060dfb0
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-hacks.patch
@@ -0,0 +1,22 @@
+--- base/debug/stack_trace.cc.orig	2018-12-08 14:11:25.303475116 +0100
++++ base/debug/stack_trace.cc	2018-12-08 18:00:43.874946999 +0100
+@@ -229,7 +229,7 @@
+ }
+ std::string StackTrace::ToStringWithPrefix(const char* prefix_string) const {
+   std::stringstream stream;
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+   OutputToStreamWithPrefix(&stream, prefix_string);
+ #endif
+   return stream.str();
+--- net/socket/udp_socket_posix.cc.orig	2019-07-03 13:13:46.034342649 -0400
++++ net/socket/udp_socket_posix.cc	2019-07-03 13:23:53.117081909 -0400
+@@ -1194,7 +1194,7 @@
+     msg_iov->push_back({const_cast<char*>(buffer->data()), buffer->length()});
+   msgvec->reserve(buffers.size());
+   for (size_t j = 0; j < buffers.size(); j++)
+-    msgvec->push_back({{nullptr, 0, &msg_iov[j], 1, nullptr, 0, 0}, 0});
++    msgvec->push_back({{nullptr, 0, &msg_iov[j], 1, 0, 0, 0}, 0});
+   int result = HANDLE_EINTR(Sendmmsg(fd, &msgvec[0], buffers.size(), 0));
+   SendResult send_result(0, 0, std::move(buffers));
+   if (result < 0) {
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-libc++.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-libc++.patch
new file mode 100644
index 000000000000..088d80fad52b
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-libc++.patch
@@ -0,0 +1,55 @@
+diff --git a/buildtools/third_party/libc++/trunk/include/locale b/buildtools/third_party/libc++/trunk/include/locale
+index d29a2dc..53998bc 100644
+--- buildtools/third_party/libc++/trunk/include/locale
++++ buildtools/third_party/libc++/trunk/include/locale
+@@ -11,6 +11,15 @@
+ #ifndef _LIBCPP_LOCALE
+ #define _LIBCPP_LOCALE
+ 
++// musl doesn't define _l (with locale) variants of functions, as it only supports UTF-8.
++// we can simply make macros that will call the non-localated ones if we're using musl, or rather not-using something that has the _l ones.
++// couldn't find anything glibc #defines when it creates strtoull_l (that it doesn't undefine a few lines later), so let's test against glibc and glibc-likes.
++// almost all glibc-likes define __GNU_LIBRARY__ for compatibility
++#ifndef __GNU_LIBRARY__
++#define strtoull_l(A, B, C, LOC) strtoull(A,B,C)
++#define strtoll_l(A, B, C, LOC) strtoll(A,B,C)
++#endif
++
+ /*
+     locale synopsis
+ 
+diff --git a/buildtools/third_party/libc++/trunk/src/locale.cpp b/buildtools/third_party/libc++/trunk/src/locale.cpp
+index 4163c2c..3d1902a 100644
+--- a/buildtools/third_party/libc++/trunk/src/locale.cpp
++++ buildtools/third_party/libc++/trunk/src/locale.cpp
+@@ -1028,11 +1028,11 @@ ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault,
+     return low;
+ }
+ 
+-#if defined(__EMSCRIPTEN__)
++//#if defined(__EMSCRIPTEN__)
+ extern "C" const unsigned short ** __ctype_b_loc();
+ extern "C" const int ** __ctype_tolower_loc();
+ extern "C" const int ** __ctype_toupper_loc();
+-#endif
++//#endif
+ 
+ #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
+ const ctype<char>::mask*
+@@ -1136,12 +1136,10 @@ ctype<char>::classic_table()  _NOEXCEPT
+ #elif defined(_AIX)
+     return (const unsigned int *)__lc_ctype_ptr->obj->mask;
+ #else
+-    // Platform not supported: abort so the person doing the port knows what to
+-    // fix
+-# warning  ctype<char>::classic_table() is not implemented
+-    printf("ctype<char>::classic_table() is not implemented\n");
+-    abort();
+-    return NULL;
++// not sure any other libc like this exists, but there is no way to differentiate musl as of right now
++// to be fair, with the change above, this should always work
++// also, #warning is a gcc extension
++    return (const unsigned long *)*__ctype_b_loc();
+ #endif
+ }
+ #endif
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-sandbox.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-sandbox.patch
new file mode 100644
index 000000000000..230bb7bbd297
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-sandbox.patch
@@ -0,0 +1,92 @@
+--- ./sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc.orig	2019-07-03 11:53:21.213479736 -0400
++++ ./sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc	2019-07-03 11:57:01.304998253 -0400
+@@ -140,31 +140,14 @@
+ ResultExpr RestrictCloneToThreadsAndEPERMFork() {
+   const Arg<unsigned long> flags(0);
+ 
+-  // TODO(mdempsky): Extend DSL to support (flags & ~mask1) == mask2.
+-  const uint64_t kAndroidCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES |
+-                                     CLONE_SIGHAND | CLONE_THREAD |
+-                                     CLONE_SYSVSEM;
+-  const uint64_t kObsoleteAndroidCloneMask = kAndroidCloneMask | CLONE_DETACHED;
++  const int required = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
++                       CLONE_THREAD | CLONE_SYSVSEM;
++  const int safe = CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | 
++                   CLONE_DETACHED;
++  const BoolExpr thread_clone_ok = (flags&~safe)==required;
+ 
+-  const uint64_t kGlibcPthreadFlags =
+-      CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD |
+-      CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
+-  const BoolExpr glibc_test = flags == kGlibcPthreadFlags;
+-
+-  const BoolExpr android_test =
+-      AnyOf(flags == kAndroidCloneMask, flags == kObsoleteAndroidCloneMask,
+-            flags == kGlibcPthreadFlags);
+-
+-  // The following two flags are the two important flags in any vfork-emulating
+-  // clone call. EPERM any clone call that contains both of them.
+-  const uint64_t kImportantCloneVforkFlags = CLONE_VFORK | CLONE_VM;
+-
+-  const BoolExpr is_fork_or_clone_vfork =
+-      AnyOf((flags & (CLONE_VM | CLONE_THREAD)) == 0,
+-            (flags & kImportantCloneVforkFlags) == kImportantCloneVforkFlags);
+-
+-  return If(IsAndroid() ? android_test : glibc_test, Allow())
+-      .ElseIf(is_fork_or_clone_vfork, Error(EPERM))
++  return If(thread_clone_ok, Allow())
++      .ElseIf((flags & (CLONE_VM | CLONE_THREAD)) == 0, Error(EPERM))
+       .Else(CrashSIGSYSClone());
+ }
+ 
+--- ./sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc.orig
++++ ./sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+@@ -494,6 +494,7 @@
+     case __NR_mlock:
+     case __NR_munlock:
+     case __NR_munmap:
++    case __NR_mremap:
+       return true;
+     case __NR_madvise:
+     case __NR_mincore:
+@@ -509,7 +510,6 @@
+     case __NR_modify_ldt:
+ #endif
+     case __NR_mprotect:
+-    case __NR_mremap:
+     case __NR_msync:
+     case __NR_munlockall:
+     case __NR_readahead:
+diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+index 80f02c0..21fbe21 100644
+--- sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
++++ sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+@@ -373,6 +373,7 @@ bool SyscallSets::IsAllowedProcessStartOrDeath(int sysno) {
+ #if defined(__i386__)
+     case __NR_waitpid:
+ #endif
++    case __NR_set_tid_address:
+       return true;
+     case __NR_clone:  // Should be parameter-restricted.
+     case __NR_setns:  // Privileged.
+@@ -385,7 +386,6 @@ bool SyscallSets::IsAllowedProcessStartOrDeath(int sysno) {
+ #if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
+     case __NR_set_thread_area:
+ #endif
+-    case __NR_set_tid_address:
+     case __NR_unshare:
+ #if !defined(__mips__) && !defined(__aarch64__)
+     case __NR_vfork:
+--- sandbox/policy/linux/bpf_renderer_policy_linux.cc
++++ sandbox/policy/linux/bpf_renderer_policy_linux.cc
+@@ -100,9 +100,9 @@
+     case __NR_uname:
+     case __NR_sched_getparam:
+     case __NR_sched_getscheduler:
++    case __NR_sched_setscheduler:
+       return Allow();
+     case __NR_sched_getaffinity:
+-    case __NR_sched_setscheduler:
+       return RestrictSchedTarget(GetPolicyPid(), sysno);
+     case __NR_prlimit64:
+       // See crbug.com/662450 and setrlimit comment above.
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-sync.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-sync.patch
new file mode 100644
index 000000000000..bc2fa1937bd3
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-sync.patch
@@ -0,0 +1,30 @@
+--- third_party/libsync/src/include/sync/sync.h.orig	2020-02-21 07:43:33.748325175 -0500
++++ third_party/libsync/src/include/sync/sync.h	2020-02-21 07:44:07.288328784 -0500
+@@ -19,12 +19,16 @@
+ #ifndef __SYS_CORE_SYNC_H
+ #define __SYS_CORE_SYNC_H
+ 
++#if defined(__GLIBC__)
+ #include <sys/cdefs.h>
++#endif
+ #include <stdint.h>
+ 
+ #include <linux/types.h>
+ 
+-__BEGIN_DECLS
++#ifdef __cplusplus
++extern "C" {
++#endif
+ 
+ struct sync_legacy_merge_data {
+  int32_t fd2;
+@@ -158,6 +162,8 @@
+                                   struct sync_pt_info *itr);
+ void sync_fence_info_free(struct sync_fence_info_data *info);
+ 
+-__END_DECLS
++#ifdef __cplusplus
++}
++#endif
+ 
+ #endif /* __SYS_CORE_SYNC_H */
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-xxx-ppc64le.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-xxx-ppc64le.patch
new file mode 100644
index 000000000000..9001a2a854d0
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-xxx-ppc64le.patch
@@ -0,0 +1,190 @@
+diff --git sandbox/linux/bpf_dsl/seccomp_macros.h sandbox/linux/bpf_dsl/seccomp_macros.h
+index a6aec544e..2a4a7f1bc 100644
+--- sandbox/linux/bpf_dsl/seccomp_macros.h
++++ sandbox/linux/bpf_dsl/seccomp_macros.h
+@@ -16,7 +16,7 @@
+ #if defined(__mips__)
+ // sys/user.h in eglibc misses size_t definition
+ #include <stddef.h>
+-#elif defined(__powerpc64__)
++#elif defined(__powerpc64__) && defined(__GLIBC__)
+ // Manually define greg_t on ppc64
+ typedef unsigned long long greg_t;
+ #endif
+@@ -361,11 +361,11 @@ typedef struct pt_regs regs_struct;
+ #define SECCOMP_ARCH AUDIT_ARCH_PPC64
+ #endif
+ 
+-#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.regs->gpr[_reg])
++#define SECCOMP_REG(_ctx, _reg) (((struct pt_regs *)(_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_IP(_ctx) ((struct pt_regs *)(_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)
+diff --git sandbox/linux/seccomp-bpf/syscall.cc sandbox/linux/seccomp-bpf/syscall.cc
+index d53a7ff56..c290f0e92 100644
+--- sandbox/linux/seccomp-bpf/syscall.cc
++++ sandbox/linux/seccomp-bpf/syscall.cc
+@@ -499,9 +499,9 @@ void Syscall::PutValueInUcontext(intptr_t ret_val, ucontext_t* ctx) {
+   // 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);
++    ((struct pt_regs *)ctx->uc_mcontext.regs)->ccr |= (1 << 28);
+   } else {
+-    ctx->uc_mcontext.regs->ccr &= ~(1 << 28);
++    ((struct pt_regs *)ctx->uc_mcontext.regs)->ccr &= ~(1 << 28);
+   }
+ #endif
+   SECCOMP_RESULT(ctx) = static_cast<greg_t>(ret_val);
+diff --git third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h
+index cdce9bf8..73d77dda 100644
+--- third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h
++++ third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h
+@@ -46,7 +46,7 @@
+ 
+ // The following platforms have an implementation of a hardware counter.
+ #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
+-  defined(__powerpc__) || defined(__ppc__) || \
++  ((defined(__powerpc__) || defined(__ppc__)) && defined(__GLIBC__)) || \
+   defined(_M_IX86) || defined(_M_X64)
+ #define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1
+ #else
+--- third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h
++++ third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h
+@@ -64,7 +64,7 @@
+ #elif defined(__i386__) || defined(__x86_64__)
+ #define ABSL_STACKTRACE_INL_HEADER \
+   "absl/debugging/internal/stacktrace_x86-inl.inc"
+-#elif defined(__ppc__) || defined(__PPC__)
++#elif (defined(__ppc__) || defined(__PPC__)) && defined(__GLIBC__)
+ #define ABSL_STACKTRACE_INL_HEADER \
+   "absl/debugging/internal/stacktrace_powerpc-inl.inc"
+ #elif defined(__aarch64__)
+diff --git third_party/breakpad/BUILD.gn third_party/breakpad/BUILD.gn
+index f9a60e37..25f3a0b7 100644
+--- third_party/breakpad/BUILD.gn
++++ third_party/breakpad/BUILD.gn
+@@ -637,6 +637,7 @@ if (is_linux || is_android) {
+ 
+     if (current_cpu == "ppc64") {
+         defines = [ "HAVE_GETCONTEXT" ]
++        libs += [ "ucontext" ]
+     } else {
+         sources += [
+             "breakpad/src/common/linux/breakpad_getcontext.S"
+diff --git third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
+index 03afec7a..0264ecf1 100644
+--- third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
++++ third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
+@@ -273,6 +273,9 @@ void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+ 
+ #elif defined(__powerpc64__)
+ 
++#include <asm/elf.h>
++#include <asm/ptrace.h>
++
+ uintptr_t ThreadInfo::GetInstructionPointer() const {
+     return mcontext.gp_regs[PT_NIP];
+ }
+@@ -290,9 +293,9 @@ void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+     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.fpregs[i] = ((uint64_t *)&mcontext.fp_regs)[i];
+ 
+-    out->float_save.fpscr = mcontext.fp_regs[NFPREG-1];
++    out->float_save.fpscr = ((uint64_t *)&mcontext.fp_regs)[ELF_NFPREG-1];
+ 
+     for (int i = 0; i < MD_VECTORSAVEAREA_PPC_VR_COUNT; i++)
+         out->vector_save.save_vr[i] = \
+diff --git third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
+index 1090470f..e580233d 100644
+--- third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
++++ third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
+@@ -257,6 +257,9 @@ void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc) {
+ 
+ #elif defined(__powerpc64__)
+ 
++#include <asm/elf.h>
++#include <asm/ptrace.h>
++
+ uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
+     return uc->uc_mcontext.gp_regs[MD_CONTEXT_PPC64_REG_SP];
+ }
+@@ -280,9 +283,9 @@ void UContextReader::FillCPUContext(RawContextCPU* out, const ucontext_t* uc,
+     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.fpregs[i] = ((uint64_t *)&uc->uc_mcontext.fp_regs)[i];
+ 
+-    out->float_save.fpscr = uc->uc_mcontext.fp_regs[NFPREG-1];
++    out->float_save.fpscr = ((uint64_t *)&uc->uc_mcontext.fp_regs)[ELF_NFPREG-1];
+ 
+     for (int i = 0; i < MD_VECTORSAVEAREA_PPC_VR_COUNT; i++)
+         out->vector_save.save_vr[i] =
+diff --git third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
+index 5a7ab50c..ee8b858c 100644
+--- third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
++++ third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
+@@ -105,6 +105,11 @@
+ #define PR_SET_PTRACER 0x59616d61
+ #endif
+ 
++/* musl hack, can't include asm/ptrace.h as that causes conflicts */
++#if defined(__powerpc64__) && !defined(PT_NIP)
++#define PT_NIP 32
++#endif
++
+ namespace google_breakpad {
+ 
+ namespace {
+diff --git third_party/crashpad/crashpad/snapshot/linux/signal_context.h third_party/crashpad/crashpad/snapshot/linux/signal_context.h
+index 8e335a09..b2a0f155 100644
+--- third_party/crashpad/crashpad/snapshot/linux/signal_context.h
++++ third_party/crashpad/crashpad/snapshot/linux/signal_context.h
+@@ -469,7 +469,7 @@ struct MContext64 {
+   SignalThreadContext64 gp_regs;
+   SignalFloatContext64  fp_regs;
+   SignalVectorContext64 *v_regs;
+-  int64_t vmx_reserve[69];
++  int64_t vmx_reserve[101];
+ };
+ 
+ struct ContextTraits64 : public Traits64 {
+diff --git third_party/crashpad/crashpad/util/linux/thread_info.h third_party/crashpad/crashpad/util/linux/thread_info.h
+index dea0d1f3..b203e5b2 100644
+--- third_party/crashpad/crashpad/util/linux/thread_info.h
++++ third_party/crashpad/crashpad/util/linux/thread_info.h
+@@ -30,6 +30,7 @@
+ 
+ #if defined(ARCH_CPU_PPC64_FAMILY)
+ #include <sys/ucontext.h>
++#include <asm/ptrace.h>
+ #endif
+ 
+ namespace crashpad {
+diff --git third_party/lss/linux_syscall_support.h third_party/lss/linux_syscall_support.h
+index 9955ce44..4c1cc488 100644
+--- third_party/lss/linux_syscall_support.h
++++ third_party/lss/linux_syscall_support.h
+@@ -4216,9 +4216,13 @@ struct kernel_statfs {
+     }
+   #endif
+   #if defined(__NR_fstatat64)
++    // musl does #define fstatat64 fstatat
++    #undef fstatat64
+     LSS_INLINE _syscall4(int,   fstatat64,        int,   d,
+                          const char *,      p,
+                          struct kernel_stat64 *,   b,    int,   f)
++    // set it back like it was
++    #define fstatat64 fstatat
+   #endif
+   #if defined(__NR_waitpid)
+     // waitpid is polyfilled below when not available.
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-no-mallinfo.patch b/srcpkgs/electron13/files/musl-patches/chromium-no-mallinfo.patch
new file mode 100644
index 000000000000..254a1f632da5
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-no-mallinfo.patch
@@ -0,0 +1,54 @@
+--- base/trace_event/malloc_dump_provider.cc.orig
++++ base/trace_event/malloc_dump_provider.cc
+@@ -243,7 +243,7 @@
+   allocated_objects_count = main_heap_info.block_count;
+ #elif defined(OS_FUCHSIA)
+ // TODO(fuchsia): Port, see https://crbug.com/706592.
+-#else
++#elif defined(__GLIBC__)
+   struct mallinfo info = mallinfo();
+   DCHECK_GE(info.arena + info.hblkhd, info.uordblks);
+ 
+--- base/process/process_metrics_posix.cc.orig	2020-11-18 23:50:33.958223497 -0500
++++ base/process/process_metrics_posix.cc	2020-11-18 23:53:52.024589316 -0500
+@@ -119,14 +119,14 @@
+   malloc_statistics_t stats = {0};
+   malloc_zone_statistics(nullptr, &stats);
+   return stats.size_in_use;
+-#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
++#elif defined(__GLIBC__) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
+   struct mallinfo minfo = mallinfo();
+ #if BUILDFLAG(USE_TCMALLOC)
+   return minfo.uordblks;
+ #else
+   return minfo.hblkhd + minfo.arena;
+ #endif
+-#elif defined(OS_FUCHSIA)
++#else
+   // TODO(fuchsia): Not currently exposed. https://crbug.com/735087.
+   return 0;
+ #endif
+--- third_party/swiftshader/third_party/llvm-subzero/lib/Support/Unix/Process.inc
++++ third_party/swiftshader/third_party/llvm-subzero/lib/Support/Unix/Process.inc.orig
+@@ -84,7 +84,7 @@
+ }
+ 
+ size_t Process::GetMallocUsage() {
+-#if defined(HAVE_MALLINFO)
++#if defined(HAVE_MALLINFO) && defined(__GLIBC__)
+   struct mallinfo mi;
+   mi = ::mallinfo();
+   return mi.uordblks;
+
+--- third_party/swiftshader/third_party/llvm-10.0/configs/linux/include/llvm/Config/config.h.orig	2019-09-30 13:03:42.556880537 -0400
++++ third_party/swiftshader/third_party/llvm-10.0/configs/linux/include/llvm/Config/config.h	2019-09-30 13:07:27.989821227 -0400
+@@ -122,7 +122,9 @@
+ /* #undef HAVE_MALLCTL */
+ 
+ /* Define to 1 if you have the `mallinfo' function. */
++#if defined(__GLIBC__)
+ #define HAVE_MALLINFO 1
++#endif
+ 
+ /* Define to 1 if you have the <malloc.h> header file. */
+ #define HAVE_MALLOC_H 1
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-resolver.patch b/srcpkgs/electron13/files/musl-patches/chromium-resolver.patch
new file mode 100644
index 000000000000..29fe2d2f1f3c
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-resolver.patch
@@ -0,0 +1,38 @@
+--- net/dns/host_resolver_manager.cc.orig	2020-10-09 16:39:12.064069835 -0400
++++ net/dns/host_resolver_manager.cc	2020-10-09 16:42:49.738302772 -0400
+@@ -2779,8 +2779,7 @@
+   NetworkChangeNotifier::AddConnectionTypeObserver(this);
+   if (system_dns_config_notifier_)
+     system_dns_config_notifier_->AddObserver(this);
+-#if defined(OS_POSIX) && !defined(OS_APPLE) && !defined(OS_OPENBSD) && \
+-    !defined(OS_ANDROID)
++#if defined(__GLIBC__)
+   EnsureDnsReloaderInit();
+ #endif
+ 
+--- net/dns/dns_reloader.cc.orig	2020-10-09 16:39:12.064069835 -0400
++++ net/dns/dns_reloader.cc	2020-10-09 16:44:30.442419823 -0400
+@@ -4,9 +4,8 @@
+ 
+ #include "net/dns/dns_reloader.h"
+ 
+-#if defined(OS_POSIX) && !defined(OS_APPLE) && !defined(OS_OPENBSD) && \
+-    !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+-
++#if defined(__GLIBC__)
++ 
+ #include <resolv.h>
+ 
+ #include "base/lazy_instance.h"
+--- net/dns/host_resolver_proc.cc.orig	2020-10-09 16:39:12.065069836 -0400
++++ net/dns/host_resolver_proc.cc	2020-10-09 16:45:09.641466644 -0400
+@@ -159,8 +159,7 @@
+   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                 base::BlockingType::WILL_BLOCK);
+ 
+-#if defined(OS_POSIX) && !defined(OS_APPLE) && !defined(OS_OPENBSD) && \
+-    !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
++#if defined(__GLIBC__)
+   DnsReloaderMaybeReload();
+ #endif
+   base::Optional<AddressInfo> ai;
diff --git a/srcpkgs/electron13/files/patches/chromium-88-glibc-2.33.patch b/srcpkgs/electron13/files/patches/chromium-88-glibc-2.33.patch
new file mode 100644
index 000000000000..64306d5e429e
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-88-glibc-2.33.patch
@@ -0,0 +1,144 @@
+# Patch made by Kevin Kofler <Kevin@tigcc.ticalc.org>
+# https://bugzilla.redhat.com/show_bug.cgi?id=1904652
+
+diff -up chromium-88.0.4324.96/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc.fstatfix chromium-88.0.4324.96/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
+--- sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc.fstatfix	2021-01-25 10:11:45.427436398 -0500
++++ sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc	2021-01-25 10:12:51.337699003 -0500
+@@ -257,6 +257,18 @@ ResultExpr EvaluateSyscallImpl(int fs_de
+     return RestrictKillTarget(current_pid, sysno);
+   }
+ 
++#if defined(__NR_newfstatat)
++  if (sysno == __NR_newfstatat) {
++    return RewriteFstatatSIGSYS();
++  }
++#endif
++
++#if defined(__NR_fstatat64)
++  if (sysno == __NR_fstatat64) {
++    return RewriteFstatatSIGSYS();
++  }
++#endif
++
+   if (SyscallSets::IsFileSystem(sysno) ||
+       SyscallSets::IsCurrentDirectory(sysno)) {
+     return Error(fs_denied_errno);
+diff -up chromium-88.0.4324.96/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc.fstatfix chromium-88.0.4324.96/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
+--- sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc.fstatfix	2021-01-25 10:13:10.179774081 -0500
++++ sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc	2021-01-25 10:16:18.790525746 -0500
+@@ -6,6 +6,8 @@
+ 
+ #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
+ 
++#include <errno.h>
++#include <fcntl.h>
+ #include <stddef.h>
+ #include <stdint.h>
+ #include <string.h>
+@@ -355,6 +357,35 @@ intptr_t SIGSYSSchedHandler(const struct
+   return -ENOSYS;
+ }
+ 
++intptr_t SIGSYSFstatatHandler(const struct arch_seccomp_data& args,
++                              void* aux) {
++  switch (args.nr) {
++#if defined(__NR_newfstatat)
++    case __NR_newfstatat:
++#endif
++#if defined(__NR_fstatat64)
++    case __NR_fstatat64:
++#endif
++#if defined(__NR_newfstatat) || defined(__NR_fstatat64)
++      if (*reinterpret_cast<const char *>(args.args[1]) == '\0'
++          && args.args[3] == static_cast<uint64_t>(AT_EMPTY_PATH)) {
++        return sandbox::sys_fstat64(static_cast<int>(args.args[0]),
++                                    reinterpret_cast<struct stat64 *>(args.args[2]));
++      } else {
++        errno = EACCES;
++        return -1;
++      }
++      break;
++#endif
++  }
++
++  CrashSIGSYS_Handler(args, aux);
++
++  // Should never be reached.
++  RAW_CHECK(false);
++  return -ENOSYS;
++}
++
+ bpf_dsl::ResultExpr CrashSIGSYS() {
+   return bpf_dsl::Trap(CrashSIGSYS_Handler, NULL);
+ }
+@@ -387,6 +418,10 @@ bpf_dsl::ResultExpr RewriteSchedSIGSYS()
+   return bpf_dsl::Trap(SIGSYSSchedHandler, NULL);
+ }
+ 
++bpf_dsl::ResultExpr RewriteFstatatSIGSYS() {
++  return bpf_dsl::Trap(SIGSYSFstatatHandler, NULL);
++}
++
+ void AllocateCrashKeys() {
+ #if !defined(OS_NACL_NONSFI)
+   if (seccomp_crash_key)
+diff -up chromium-88.0.4324.96/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h.fstatfix chromium-88.0.4324.96/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
+--- sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h.fstatfix	2021-01-25 10:16:36.982598236 -0500
++++ sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h	2021-01-25 10:18:45.705111027 -0500
+@@ -62,6 +62,10 @@ SANDBOX_EXPORT intptr_t SIGSYSPtraceFail
+ // sched_setparam(), sched_setscheduler()
+ SANDBOX_EXPORT intptr_t SIGSYSSchedHandler(const arch_seccomp_data& args,
+                                            void* aux);
++// If the fstatat syscall is actually a disguised fstat, calls the regular fstat
++// syscall, otherwise, crashes in the same way as CrashSIGSYS_Handler.
++SANDBOX_EXPORT intptr_t SIGSYSFstatatHandler(const struct arch_seccomp_data& args, 
++                                             void* aux);
+ 
+ // Variants of the above functions for use with bpf_dsl.
+ SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYS();
+@@ -72,6 +76,7 @@ SANDBOX_EXPORT bpf_dsl::ResultExpr Crash
+ SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSFutex();
+ SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSPtrace();
+ SANDBOX_EXPORT bpf_dsl::ResultExpr RewriteSchedSIGSYS();
++SANDBOX_EXPORT bpf_dsl::ResultExpr RewriteFstatatSIGSYS();
+ 
+ // Allocates a crash key so that Seccomp information can be recorded.
+ void AllocateCrashKeys();
+diff -up chromium-88.0.4324.96/sandbox/linux/services/syscall_wrappers.cc.fstatfix chromium-88.0.4324.96/sandbox/linux/services/syscall_wrappers.cc
+--- sandbox/linux/services/syscall_wrappers.cc.fstatfix	2021-01-25 10:18:53.307141311 -0500
++++ sandbox/linux/services/syscall_wrappers.cc	2021-01-25 10:19:46.982355293 -0500
+@@ -261,4 +261,13 @@ int sys_sigaction(int signum,
+ 
+ #endif  // defined(MEMORY_SANITIZER)
+ 
++SANDBOX_EXPORT int sys_fstat64(int fd, struct stat64 *buf)
++{
++#if defined(__NR_fstat64)
++    return syscall(__NR_fstat64, fd, buf);
++#else
++    return syscall(__NR_fstat, fd, buf);
++#endif
++}
++
+ }  // namespace sandbox
+diff -up chromium-88.0.4324.96/sandbox/linux/services/syscall_wrappers.h.fstatfix chromium-88.0.4324.96/sandbox/linux/services/syscall_wrappers.h
+--- sandbox/linux/services/syscall_wrappers.h.fstatfix	2021-01-25 10:19:53.115379741 -0500
++++ sandbox/linux/services/syscall_wrappers.h	2021-01-25 10:20:45.485588421 -0500
+@@ -17,6 +17,7 @@ struct sock_fprog;
+ struct rlimit64;
+ struct cap_hdr;
+ struct cap_data;
++struct stat64;
+ 
+ namespace sandbox {
+ 
+@@ -84,6 +85,9 @@ SANDBOX_EXPORT int sys_sigaction(int sig
+                                  const struct sigaction* act,
+                                  struct sigaction* oldact);
+ 
++// Recent glibc rewrites fstat to fstatat.
++SANDBOX_EXPORT int sys_fstat64(int fd, struct stat64 *buf);
++
+ }  // namespace sandbox
+ 
+ #endif  // SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
diff --git a/srcpkgs/electron13/files/patches/chromium-browser-size_t.patch b/srcpkgs/electron13/files/patches/chromium-browser-size_t.patch
new file mode 100644
index 000000000000..fa214d987d61
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-browser-size_t.patch
@@ -0,0 +1,10 @@
+--- chrome/browser/search/background/ntp_backgrounds.h	2020-08-10 20:39:20.000000000 +0200
++++ chrome/browser/search/background/ntp_backgrounds.h	2020-09-04 13:48:22.640023256 +0200
+@@ -6,6 +6,7 @@
+ #define CHROME_BROWSER_SEARCH_BACKGROUND_NTP_BACKGROUNDS_H_
+ 
+ #include <array>
++#include <cstddef>
+ 
+ class GURL;
+ 
diff --git a/srcpkgs/electron13/files/patches/chromium-libc_malloc.patch b/srcpkgs/electron13/files/patches/chromium-libc_malloc.patch
new file mode 100644
index 000000000000..eda11ec86637
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-libc_malloc.patch
@@ -0,0 +1,26 @@
+--- base/process/memory_linux.cc.orig	2017-09-15 08:41:43.000000000 +0000
++++ base/process/memory_linux.cc	2017-09-15 08:44:39.804995469 +0000
+@@ -21,6 +21,12 @@
+ #include "third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h"
+ #endif
+ 
++#if defined(LIBC_GLIBC)
++extern "C" {
++extern void *__libc_malloc(size_t size);
++}
++#endif
++
+ namespace base {
+ 
+ size_t g_oom_size = 0U;
+--- base/process/memory_linux.cc.orig	2020-08-30 14:18:35.401132593 -0400
++++ base/process/memory_linux.cc	2020-08-30 14:19:08.030199189 -0400
+@@ -141,7 +141,7 @@
+     (!defined(LIBC_GLIBC) && !BUILDFLAG(USE_TCMALLOC))
+   *result = malloc(size);
+ #elif defined(LIBC_GLIBC) && !BUILDFLAG(USE_TCMALLOC)
+-  *result = __libc_malloc(size);
++  *result = ::__libc_malloc(size);
+ #elif BUILDFLAG(USE_TCMALLOC)
+   *result = tc_malloc_skip_new_handler(size);
+ #endif
diff --git a/srcpkgs/electron13/files/patches/chromium-musl-v8-monotonic-pthread-cont_timedwait.patch b/srcpkgs/electron13/files/patches/chromium-musl-v8-monotonic-pthread-cont_timedwait.patch
new file mode 100644
index 000000000000..33a8ea32c9c1
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-musl-v8-monotonic-pthread-cont_timedwait.patch
@@ -0,0 +1,24 @@
+Use monotonic clock for pthread_cond_timedwait with musl too.
+
+diff --git a/v8/src/base/platform/condition-variable.cc b/v8/src/base/platform/condition-variable.cc
+index 5ea7083..c13027e 100644
+--- ./v8/src/base/platform/condition-variable.cc
++++ ./v8/src/base/platform/condition-variable.cc
+@@ -16,7 +16,7 @@ namespace base {
+ 
+ ConditionVariable::ConditionVariable() {
+ #if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
+-     (V8_OS_LINUX && V8_LIBC_GLIBC))
++     V8_OS_LINUX)
+   // On Free/Net/OpenBSD and Linux with glibc we can change the time
+   // source for pthread_cond_timedwait() to use the monotonic clock.
+   pthread_condattr_t attr;
+@@ -92,7 +92,7 @@ bool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) {
+       &native_handle_, &mutex->native_handle(), &ts);
+ #else
+ #if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
+-     (V8_OS_LINUX && V8_LIBC_GLIBC))
++     V8_OS_LINUX)
+   // On Free/Net/OpenBSD and Linux with glibc we can change the time
+   // source for pthread_cond_timedwait() to use the monotonic clock.
+   result = clock_gettime(CLOCK_MONOTONIC, &ts);
diff --git a/srcpkgs/electron13/files/patches/chromium-no-execinfo.patch b/srcpkgs/electron13/files/patches/chromium-no-execinfo.patch
new file mode 100644
index 000000000000..386997e8ed14
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-no-execinfo.patch
@@ -0,0 +1,72 @@
+--- base/debug/stack_trace_posix.cc.orig	2019-05-14 14:49:44.000000000 -0400
++++ base/debug/stack_trace_posix.cc	2019-07-02 10:43:43.490045013 -0400
+@@ -27,7 +27,7 @@
+ #if !defined(USE_SYMBOLIZE)
+ #include <cxxabi.h>
+ #endif
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+ #include <execinfo.h>
+ #endif
+ 
+@@ -86,7 +86,7 @@
+   // Note: code in this function is NOT async-signal safe (std::string uses
+   // malloc internally).
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+   std::string::size_type search_from = 0;
+   while (search_from < text->size()) {
+     // Look for the start of a mangled symbol, from search_from.
+@@ -121,7 +121,7 @@
+       search_from = mangled_start + 2;
+     }
+   }
+-#endif  // !defined(__UCLIBC__) && !defined(_AIX)
++#endif  // defined(__GLIBC__) && !defined(_AIX)
+ }
+ #endif  // !defined(USE_SYMBOLIZE)
+ 
+@@ -133,7 +133,7 @@
+   virtual ~BacktraceOutputHandler() = default;
+ };
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+ void OutputPointer(void* pointer, BacktraceOutputHandler* handler) {
+   // This should be more than enough to store a 64-bit number in hex:
+   // 16 hex digits + 1 for null-terminator.
+@@ -216,7 +216,7 @@
+   }
+ #endif  // defined(USE_SYMBOLIZE)
+ }
+-#endif  // !defined(__UCLIBC__) && !defined(_AIX)
++#endif  // defined(__GLIBC__) && !defined(_AIX)
+ 
+ void PrintToStderr(const char* output) {
+   // NOTE: This code MUST be async-signal safe (it's used by in-process
+@@ -812,7 +812,7 @@
+   // NOTE: This code MUST be async-signal safe (it's used by in-process
+   // stack dumping signal handler). NO malloc or stdio is allowed here.
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+   // Though the backtrace API man page does not list any possible negative
+   // return values, we take no chance.
+   return base::saturated_cast<size_t>(backtrace(trace, count));
+@@ -825,13 +825,13 @@
+ // NOTE: This code MUST be async-signal safe (it's used by in-process
+ // stack dumping signal handler). NO malloc or stdio is allowed here.
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+   PrintBacktraceOutputHandler handler;
+   ProcessBacktrace(trace_, count_, prefix_string, &handler);
+ #endif
+ }
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+ void StackTrace::OutputToStreamWithPrefix(std::ostream* os,
+                                           const char* prefix_string) const {
+   StreamBacktraceOutputHandler handler(os);
diff --git a/srcpkgs/electron13/files/patches/chromium-no-getcontext.patch b/srcpkgs/electron13/files/patches/chromium-no-getcontext.patch
new file mode 100644
index 000000000000..b2a498734c93
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-no-getcontext.patch
@@ -0,0 +1,27 @@
+--- third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc.orig	2015-12-06 09:59:55.554536646 +0100
++++ third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc	2015-12-06 10:01:16.818238035 +0100
+@@ -477,7 +477,9 @@ bool ExceptionHandler::SimulateSignalDel
+   siginfo.si_code = SI_USER;
+   siginfo.si_pid = getpid();
+   ucontext_t context;
++#if defined(__GLIBC__)
+   getcontext(&context);
++#endif
+   return HandleSignal(sig, &siginfo, &context);
+ }
+ 
+@@ -647,9 +649,14 @@ bool ExceptionHandler::WriteMinidump() {
+   sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
+ 
+   CrashContext context;
++
++#if defined(__GLIBC__)
+   int getcontext_result = getcontext(&context.context);
+   if (getcontext_result)
+     return false;
++#else
++  return false;
++#endif
+ 
+ #if defined(__i386__)
+   // In CPUFillFromUContext in minidumpwriter.cc the stack pointer is retrieved
diff --git a/srcpkgs/electron13/files/patches/chromium-revert-drop-of-system-java.patch b/srcpkgs/electron13/files/patches/chromium-revert-drop-of-system-java.patch
new file mode 100644
index 000000000000..69c16fc0c487
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-revert-drop-of-system-java.patch
@@ -0,0 +1,15 @@
+This was dropped for some reason in 6951c37cecd05979b232a39e5c10e6346a0f74ef
+--- third_party/closure_compiler/compiler.py	2021-05-20 04:17:53.000000000 +0200
++++ -	2021-05-25 20:31:10.102971765 +0200
+@@ -13,8 +13,9 @@
+ 
+ 
+ _CURRENT_DIR = os.path.join(os.path.dirname(__file__))
+-_JAVA_PATH = os.path.join(_CURRENT_DIR, "..", "jdk", "current", "bin", "java")
+-assert os.path.isfile(_JAVA_PATH), "java only allowed in android builds"
++_JAVA_BIN = "java"
++_JDK_PATH = os.path.join(_CURRENT_DIR, "..", "jdk", "current", "bin", "java")
++_JAVA_PATH = _JDK_PATH if os.path.isfile(_JDK_PATH) else _JAVA_BIN
+ 
+ class Compiler(object):
+   """Runs the Closure compiler on given source files to typecheck them
diff --git a/srcpkgs/electron13/files/patches/chromium-sandbox-membarrier.patch b/srcpkgs/electron13/files/patches/chromium-sandbox-membarrier.patch
new file mode 100644
index 000000000000..86ca16fc2d70
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-sandbox-membarrier.patch
@@ -0,0 +1,10 @@
+--- sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
++++ sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+@@ -370,6 +370,7 @@
+   switch (sysno) {
+     case __NR_exit:
+     case __NR_exit_group:
++    case __NR_membarrier:
+     case __NR_wait4:
+     case __NR_waitid:
+ #if defined(__i386__)
diff --git a/srcpkgs/electron13/files/patches/chromium-sandbox-sched_getparam.patch b/srcpkgs/electron13/files/patches/chromium-sandbox-sched_getparam.patch
new file mode 100644
index 000000000000..ba8af49c5f8f
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-sandbox-sched_getparam.patch
@@ -0,0 +1,20 @@
+Allow SYS_sched_getparam and SYS_sched_getscheduler
+musl uses them for pthread_getschedparam()
+
+source: https://git.alpinelinux.org/aports/commit/community/chromium?id=54af9f8ac24f52d382c5758e2445bf0206eff40e
+
+--- sandbox/policy/linux/bpf_renderer_policy_linux.cc.orig	2019-10-08 21:03:18.253080425 +0200
++++ sandbox/policy/linux/bpf_renderer_policy_linux.cc	2019-10-08 21:04:19.648549718 +0200
+@@ -88,10 +88,10 @@
+     case __NR_sysinfo:
+     case __NR_times:
+     case __NR_uname:
+-      return Allow();
+-    case __NR_sched_getaffinity:
+     case __NR_sched_getparam:
+     case __NR_sched_getscheduler:
++      return Allow();
++    case __NR_sched_getaffinity:
+     case __NR_sched_setscheduler:
+       return sandbox::RestrictSchedTarget(GetPolicyPid(), sysno);
+     case __NR_prlimit64:
diff --git a/srcpkgs/electron13/files/patches/chromium-sndio.patch b/srcpkgs/electron13/files/patches/chromium-sndio.patch
new file mode 100644
index 000000000000..d313b4a667c7
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-sndio.patch
@@ -0,0 +1,886 @@
+diff -Naur chromium-83.0.4103.97.orig/media/BUILD.gn chromium-83.0.4103.97/media/BUILD.gn
+--- media/BUILD.gn.orig	2020-06-03 20:40:26.000000000 +0200
++++ media/BUILD.gn	2020-06-13 17:32:28.510395975 +0200
+@@ -65,6 +65,9 @@
+       defines += [ "DLOPEN_PULSEAUDIO" ]
+     }
+   }
++  if (use_sndio) {
++    defines += [ "USE_SNDIO" ]
++  }
+   if (use_cras) {
+     defines += [ "USE_CRAS" ]
+   }
+diff -Naur chromium-83.0.4103.97.orig/media/audio/BUILD.gn chromium-83.0.4103.97/media/audio/BUILD.gn
+--- media/audio/BUILD.gn.orig	2020-06-03 20:39:37.000000000 +0200
++++ media/audio/BUILD.gn	2020-06-13 17:32:28.511395969 +0200
+@@ -236,6 +236,17 @@
+     sources += [ "linux/audio_manager_linux.cc" ]
+   }
+ 
++  if (use_sndio) {
++    libs += [ "sndio" ]
++    sources += [
++      "sndio/audio_manager_sndio.cc",
++      "sndio/sndio_input.cc",
++      "sndio/sndio_input.h",
++      "sndio/sndio_output.cc",
++      "sndio/sndio_output.h"
++    ]
++  }
++
+   if (use_alsa) {
+     libs += [ "asound" ]
+     sources += [
+diff -Naur chromium-83.0.4103.97.orig/media/audio/linux/audio_manager_linux.cc chromium-83.0.4103.97/media/audio/linux/audio_manager_linux.cc
+--- media/audio/linux/audio_manager_linux.cc.orig	2020-06-03 20:39:37.000000000 +0200
++++ media/audio/linux/audio_manager_linux.cc	2020-06-13 18:09:43.623333167 +0200
+@@ -19,6 +19,11 @@
+ #include "media/audio/pulse/audio_manager_pulse.h"
+ #include "media/audio/pulse/pulse_util.h"
+ #endif
++#if defined(USE_SNDIO)
++#include "media/audio/sndio/audio_manager_sndio.h"
++#include "media/audio/sndio/sndio_input.h"
++#include "media/audio/sndio/sndio_output.h"
++#endif
+ 
+ namespace media {
+ 
+@@ -26,7 +31,8 @@
+   kPulse,
+   kAlsa,
+   kCras,
+-  kAudioIOMax = kCras  // Must always be equal to largest logged entry.
++  kSndio,
++  kAudioIOMax = kSndio // Must always be equal to largest logged entry.
+ };
+ 
+ std::unique_ptr<media::AudioManager> CreateAudioManager(
+@@ -39,6 +45,16 @@
+                                               audio_log_factory);
+   }
+ 
++#if defined(USE_SNDIO)
++  struct sio_hdl *hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
++  if (hdl != NULL) {
++    sio_close(hdl);
++    UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kSndio, kAudioIOMax + 1);
++    return std::make_unique<AudioManagerSndio>(std::move(audio_thread),
++                                                  audio_log_factory);
++  }
++#endif
++
+ #if defined(USE_CRAS)
+   if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseCras)) {
+     UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kCras, kAudioIOMax + 1);
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/audio_manager_sndio.cc chromium-83.0.4103.97/media/audio/sndio/audio_manager_sndio.cc
+--- media/audio/sndio/audio_manager_sndio.cc.orig	1970-01-01 01:00:00.000000000 +0100
++++ media/audio/sndio/audio_manager_sndio.cc	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,148 @@
++// Copyright (c) 2012 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.
++
++#include "media/audio/sndio/audio_manager_sndio.h"
++
++#include "base/metrics/histogram_macros.h"
++#include "base/memory/ptr_util.h"
++#include "media/audio/audio_device_description.h"
++#include "media/audio/audio_output_dispatcher.h"
++#include "media/audio/sndio/sndio_input.h"
++#include "media/audio/sndio/sndio_output.h"
++#include "media/base/limits.h"
++#include "media/base/media_switches.h"
++
++namespace media {
++
++
++// Maximum number of output streams that can be open simultaneously.
++static const int kMaxOutputStreams = 4;
++
++// Default sample rate for input and output streams.
++static const int kDefaultSampleRate = 48000;
++
++void AddDefaultDevice(AudioDeviceNames* device_names) {
++  DCHECK(device_names->empty());
++  device_names->push_front(AudioDeviceName::CreateDefault());
++}
++
++bool AudioManagerSndio::HasAudioOutputDevices() {
++  return true;
++}
++
++bool AudioManagerSndio::HasAudioInputDevices() {
++  return true;
++}
++
++void AudioManagerSndio::GetAudioInputDeviceNames(
++    AudioDeviceNames* device_names) {
++  DCHECK(device_names->empty());
++  AddDefaultDevice(device_names);
++}
++
++void AudioManagerSndio::GetAudioOutputDeviceNames(
++    AudioDeviceNames* device_names) {
++  AddDefaultDevice(device_names);
++}
++
++const char* AudioManagerSndio::GetName() {
++  return "SNDIO";
++}
++
++AudioParameters AudioManagerSndio::GetInputStreamParameters(
++    const std::string& device_id) {
++  static const int kDefaultInputBufferSize = 1024;
++
++  int user_buffer_size = GetUserBufferSize();
++  int buffer_size = user_buffer_size ?
++      user_buffer_size : kDefaultInputBufferSize;
++
++  return AudioParameters(
++      AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
++      kDefaultSampleRate, buffer_size);
++}
++
++AudioManagerSndio::AudioManagerSndio(std::unique_ptr<AudioThread> audio_thread,
++                                         AudioLogFactory* audio_log_factory)
++    : AudioManagerBase(std::move(audio_thread),
++                       audio_log_factory) {
++  DLOG(WARNING) << "AudioManagerSndio";
++  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
++}
++
++AudioManagerSndio::~AudioManagerSndio() {
++  Shutdown();
++}
++
++AudioOutputStream* AudioManagerSndio::MakeLinearOutputStream(
++    const AudioParameters& params,
++    const LogCallback& log_callback) {
++  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
++  return MakeOutputStream(params);
++}
++
++AudioOutputStream* AudioManagerSndio::MakeLowLatencyOutputStream(
++    const AudioParameters& params,
++    const std::string& device_id,
++    const LogCallback& log_callback) {
++  DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
++  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
++  return MakeOutputStream(params);
++}
++
++AudioInputStream* AudioManagerSndio::MakeLinearInputStream(
++    const AudioParameters& params,
++    const std::string& device_id,
++    const LogCallback& log_callback) {
++  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
++  return MakeInputStream(params);
++}
++
++AudioInputStream* AudioManagerSndio::MakeLowLatencyInputStream(
++    const AudioParameters& params,
++    const std::string& device_id,
++    const LogCallback& log_callback) {
++  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
++  return MakeInputStream(params);
++}
++
++AudioParameters AudioManagerSndio::GetPreferredOutputStreamParameters(
++    const std::string& output_device_id,
++    const AudioParameters& input_params) {
++  // TODO(tommi): Support |output_device_id|.
++  DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
++  static const int kDefaultOutputBufferSize = 2048;
++
++  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
++  int sample_rate = kDefaultSampleRate;
++  int buffer_size = kDefaultOutputBufferSize;
++  if (input_params.IsValid()) {
++    sample_rate = input_params.sample_rate();
++    channel_layout = input_params.channel_layout();
++    buffer_size = std::min(buffer_size, input_params.frames_per_buffer());
++  }
++
++  int user_buffer_size = GetUserBufferSize();
++  if (user_buffer_size)
++    buffer_size = user_buffer_size;
++
++  return AudioParameters(
++      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
++      sample_rate, buffer_size);
++}
++
++AudioInputStream* AudioManagerSndio::MakeInputStream(
++    const AudioParameters& params) {
++  DLOG(WARNING) << "MakeInputStream";
++  return new SndioAudioInputStream(this,
++             AudioDeviceDescription::kDefaultDeviceId, params);
++}
++
++AudioOutputStream* AudioManagerSndio::MakeOutputStream(
++    const AudioParameters& params) {
++  DLOG(WARNING) << "MakeOutputStream";
++  return new SndioAudioOutputStream(params, this);
++}
++
++}  // namespace media
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/audio_manager_sndio.h chromium-83.0.4103.97/media/audio/sndio/audio_manager_sndio.h
+--- media/audio/sndio/audio_manager_sndio.h.orig	1970-01-01 01:00:00.000000000 +0100
++++ media/audio/sndio/audio_manager_sndio.h	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,65 @@
++// Copyright (c) 2012 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 MEDIA_AUDIO_SNDIO_AUDIO_MANAGER_SNDIO_H_
++#define MEDIA_AUDIO_SNDIO_AUDIO_MANAGER_SNDIO_H_
++
++#include <set>
++
++#include "base/compiler_specific.h"
++#include "base/macros.h"
++#include "base/memory/ref_counted.h"
++#include "base/threading/thread.h"
++#include "media/audio/audio_manager_base.h"
++
++namespace media {
++
++class MEDIA_EXPORT AudioManagerSndio : public AudioManagerBase {
++ public:
++  AudioManagerSndio(std::unique_ptr<AudioThread> audio_thread,
++                   AudioLogFactory* audio_log_factory);
++  ~AudioManagerSndio() override;
++
++  // Implementation of AudioManager.
++  bool HasAudioOutputDevices() override;
++  bool HasAudioInputDevices() override;
++  void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
++  void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override;
++  AudioParameters GetInputStreamParameters(
++      const std::string& device_id) override;
++  const char* GetName() override;
++
++  // Implementation of AudioManagerBase.
++  AudioOutputStream* MakeLinearOutputStream(
++      const AudioParameters& params,
++      const LogCallback& log_callback) override;
++  AudioOutputStream* MakeLowLatencyOutputStream(
++      const AudioParameters& params,
++      const std::string& device_id,
++      const LogCallback& log_callback) override;
++  AudioInputStream* MakeLinearInputStream(
++      const AudioParameters& params,
++      const std::string& device_id,
++      const LogCallback& log_callback) override;
++  AudioInputStream* MakeLowLatencyInputStream(
++      const AudioParameters& params,
++      const std::string& device_id,
++      const LogCallback& log_callback) override;
++
++ protected:
++  AudioParameters GetPreferredOutputStreamParameters(
++      const std::string& output_device_id,
++      const AudioParameters& input_params) override;
++
++ private:
++  // Called by MakeLinearOutputStream and MakeLowLatencyOutputStream.
++  AudioOutputStream* MakeOutputStream(const AudioParameters& params);
++  AudioInputStream* MakeInputStream(const AudioParameters& params);
++
++  DISALLOW_COPY_AND_ASSIGN(AudioManagerSndio);
++};
++
++}  // namespace media
++
++#endif  // MEDIA_AUDIO_SNDIO_AUDIO_MANAGER_SNDIO_H_
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/sndio_input.cc chromium-83.0.4103.97/media/audio/sndio/sndio_input.cc
+--- media/audio/sndio/sndio_input.cc.orig	1970-01-01 01:00:00.000000000 +0100
++++ media/audio/sndio/sndio_input.cc	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,200 @@
++// Copyright 2013 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.
++
++#include "base/bind.h"
++#include "base/logging.h"
++#include "base/macros.h"
++#include "media/base/audio_timestamp_helper.h"
++#include "media/audio/sndio/audio_manager_sndio.h"
++#include "media/audio/audio_manager.h"
++#include "media/audio/sndio/sndio_input.h"
++
++namespace media {
++
++static const SampleFormat kSampleFormat = kSampleFormatS16;
++
++void SndioAudioInputStream::OnMoveCallback(void *arg, int delta)
++{
++  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
++
++  self->hw_delay += delta;
++}
++
++void *SndioAudioInputStream::ThreadEntry(void *arg) {
++  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
++
++  self->ThreadLoop();
++  return NULL;
++}
++
++SndioAudioInputStream::SndioAudioInputStream(AudioManagerBase* manager,
++                                             const std::string& device_name,
++                                             const AudioParameters& params)
++    : manager(manager),
++      params(params),
++      audio_bus(AudioBus::Create(params)),
++      state(kClosed) {
++}
++
++SndioAudioInputStream::~SndioAudioInputStream() {
++  if (state != kClosed)
++    Close();
++}
++
++bool SndioAudioInputStream::Open() {
++  struct sio_par par;
++  int sig;
++
++  if (state != kClosed)
++    return false;
++
++  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
++      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
++    LOG(WARNING) << "Unsupported audio format.";
++    return false;
++  }
++
++  sio_initpar(&par);
++  par.rate = params.sample_rate();
++  par.rchan = params.channels();
++  par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
++  par.bps = par.bits / 8;
++  par.sig = sig = par.bits != 8 ? 1 : 0;
++  par.le = SIO_LE_NATIVE;
++  par.appbufsz = params.frames_per_buffer();
++
++  hdl = sio_open(SIO_DEVANY, SIO_REC, 0);
++
++  if (hdl == NULL) {
++    LOG(ERROR) << "Couldn't open audio device.";
++    return false;
++  }
++
++  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
++    LOG(ERROR) << "Couldn't set audio parameters.";
++    goto bad_close;
++  }
++
++  if (par.rate  != (unsigned int)params.sample_rate() ||
++      par.rchan != (unsigned int)params.channels() ||
++      par.bits  != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
++      par.sig   != (unsigned int)sig ||
++      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
++      (par.bits != par.bps * 8)) {
++    LOG(ERROR) << "Unsupported audio parameters.";
++    goto bad_close;
++  }
++  state = kStopped;
++  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
++  sio_onmove(hdl, &OnMoveCallback, this);
++  return true;
++bad_close:
++  sio_close(hdl);
++  return false;
++}
++
++void SndioAudioInputStream::Start(AudioInputCallback* cb) {
++
++  StartAgc();
++
++  state = kRunning;
++  hw_delay = 0;
++  callback = cb;
++  sio_start(hdl);
++  if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
++    LOG(ERROR) << "Failed to create real-time thread for recording.";
++    sio_stop(hdl);
++    state = kStopped;
++  }
++}
++
++void SndioAudioInputStream::Stop() {
++
++  if (state == kStopped)
++    return;
++
++  state = kStopWait;
++  pthread_join(thread, NULL);
++  sio_stop(hdl);
++  state = kStopped;
++
++  StopAgc();
++}
++
++void SndioAudioInputStream::Close() {
++
++  if (state == kClosed)
++    return;
++
++  if (state == kRunning)
++    Stop();
++
++  state = kClosed;
++  delete [] buffer;
++  sio_close(hdl);
++
++  manager->ReleaseInputStream(this);
++}
++
++double SndioAudioInputStream::GetMaxVolume() {
++  // Not supported
++  return 0.0;
++}
++
++void SndioAudioInputStream::SetVolume(double volume) {
++  // Not supported. Do nothing.
++}
++
++double SndioAudioInputStream::GetVolume() {
++  // Not supported.
++  return 0.0;
++}
++
++bool SndioAudioInputStream::IsMuted() {
++  // Not supported.
++  return false;
++}
++
++void SndioAudioInputStream::SetOutputDeviceForAec(
++    const std::string& output_device_id) {
++  // Not supported.
++}
++
++void SndioAudioInputStream::ThreadLoop(void) {
++  size_t todo, n;
++  char *data;
++  unsigned int nframes;
++  double normalized_volume = 0.0;
++
++  nframes = audio_bus->frames();
++
++  while (state == kRunning && !sio_eof(hdl)) {
++
++    GetAgcVolume(&normalized_volume);
++
++    // read one block
++    todo = nframes * params.GetBytesPerFrame(kSampleFormat);
++    data = buffer;
++    while (todo > 0) {
++      n = sio_read(hdl, data, todo);
++      if (n == 0)
++        return;	// unrecoverable I/O error
++      todo -= n;
++      data += n;
++    }
++    hw_delay -= nframes;
++
++    // convert frames count to TimeDelta
++    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
++      params.sample_rate());
++
++    // push into bus
++    audio_bus->FromInterleaved(buffer, nframes, SampleFormatToBytesPerChannel(kSampleFormat));
++
++    // invoke callback
++    callback->OnData(audio_bus.get(), base::TimeTicks::Now() - delay, 1.);
++  }
++}
++
++}  // namespace media
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/sndio_input.h chromium-83.0.4103.97/media/audio/sndio/sndio_input.h
+--- media/audio/sndio/sndio_input.h.orig	1970-01-01 01:00:00.000000000 +0100
++++ media/audio/sndio/sndio_input.h	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,91 @@
++// Copyright 2013 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 MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
++#define MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
++
++#include <stdint.h>
++#include <string>
++#include <sndio.h>
++
++#include "base/compiler_specific.h"
++#include "base/macros.h"
++#include "base/memory/weak_ptr.h"
++#include "base/time/time.h"
++#include "media/audio/agc_audio_stream.h"
++#include "media/audio/audio_io.h"
++#include "media/audio/audio_device_description.h"
++#include "media/base/audio_parameters.h"
++
++namespace media {
++
++class AudioManagerBase;
++
++// Implementation of AudioOutputStream using sndio(7)
++class SndioAudioInputStream : public AgcAudioStream<AudioInputStream> {
++ public:
++  // Pass this to the constructor if you want to attempt auto-selection
++  // of the audio recording device.
++  static const char kAutoSelectDevice[];
++
++  // Create a PCM Output stream for the SNDIO device identified by
++  // |device_name|. If unsure of what to use for |device_name|, use
++  // |kAutoSelectDevice|.
++  SndioAudioInputStream(AudioManagerBase* audio_manager,
++                     const std::string& device_name,
++                     const AudioParameters& params);
++
++  ~SndioAudioInputStream() override;
++
++  // Implementation of AudioInputStream.
++  bool Open() override;
++  void Start(AudioInputCallback* callback) override;
++  void Stop() override;
++  void Close() override;
++  double GetMaxVolume() override;
++  void SetVolume(double volume) override;
++  double GetVolume() override;
++  bool IsMuted() override;
++  void SetOutputDeviceForAec(const std::string& output_device_id) override;
++
++ private:
++
++  enum StreamState {
++    kClosed,            // Not opened yet
++    kStopped,           // Device opened, but not started yet
++    kRunning,           // Started, device playing
++    kStopWait           // Stopping, waiting for the real-time thread to exit
++  };
++
++  // C-style call-backs
++  static void OnMoveCallback(void *arg, int delta);
++  static void* ThreadEntry(void *arg);
++
++  // Continuously moves data from the device to the consumer
++  void ThreadLoop();
++  // Our creator, the audio manager needs to be notified when we close.
++  AudioManagerBase* manager;
++  // Parameters of the source
++  AudioParameters params;
++  // We store data here for consumer
++  std::unique_ptr<AudioBus> audio_bus;
++  // Call-back that consumes recorded data
++  AudioInputCallback* callback;  // Valid during a recording session.
++  // Handle of the audio device
++  struct sio_hdl* hdl;
++  // Current state of the stream
++  enum StreamState state;
++  // High priority thread running ThreadLoop()
++  pthread_t thread;
++  // Number of frames buffered in the hardware
++  int hw_delay;
++  // Temporary buffer where data is stored sndio-compatible format
++  char* buffer;
++
++  DISALLOW_COPY_AND_ASSIGN(SndioAudioInputStream);
++};
++
++}  // namespace media
++
++#endif  // MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/sndio_output.cc chromium-83.0.4103.97/media/audio/sndio/sndio_output.cc
+--- media/audio/sndio/sndio_output.cc.orig	1970-01-01 01:00:00.000000000 +0100
++++ media/audio/sndio/sndio_output.cc	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,183 @@
++// Copyright (c) 2012 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.
++
++#include "base/logging.h"
++#include "base/time/time.h"
++#include "base/time/default_tick_clock.h"
++#include "media/audio/audio_manager_base.h"
++#include "media/base/audio_timestamp_helper.h"
++#include "media/audio/sndio/sndio_output.h"
++
++namespace media {
++
++static const SampleFormat kSampleFormat = kSampleFormatS16;
++
++void SndioAudioOutputStream::OnMoveCallback(void *arg, int delta) {
++  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
++
++  self->hw_delay -= delta;
++}
++
++void SndioAudioOutputStream::OnVolCallback(void *arg, unsigned int vol) {
++  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
++
++  self->vol = vol;
++}
++
++void *SndioAudioOutputStream::ThreadEntry(void *arg) {
++  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
++
++  self->ThreadLoop();
++  return NULL;
++}
++
++SndioAudioOutputStream::SndioAudioOutputStream(const AudioParameters& params,
++                                               AudioManagerBase* manager)
++    : manager(manager),
++      params(params),
++      audio_bus(AudioBus::Create(params)),
++      state(kClosed),
++      mutex(PTHREAD_MUTEX_INITIALIZER) {
++}
++
++SndioAudioOutputStream::~SndioAudioOutputStream() {
++  if (state != kClosed)
++    Close();
++}
++
++bool SndioAudioOutputStream::Open() {
++  struct sio_par par;
++  int sig;
++
++  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
++      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
++    LOG(WARNING) << "Unsupported audio format.";
++    return false;
++  }
++  sio_initpar(&par);
++  par.rate = params.sample_rate();
++  par.pchan = params.channels();
++  par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
++  par.bps = par.bits / 8;
++  par.sig = sig = par.bits != 8 ? 1 : 0;
++  par.le = SIO_LE_NATIVE;
++  par.appbufsz = params.frames_per_buffer();
++
++  hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
++  if (hdl == NULL) {
++    LOG(ERROR) << "Couldn't open audio device.";
++    return false;
++  }
++  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
++    LOG(ERROR) << "Couldn't set audio parameters.";
++    goto bad_close;
++  }
++  if (par.rate  != (unsigned int)params.sample_rate() ||
++      par.pchan != (unsigned int)params.channels() ||
++      par.bits  != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
++      par.sig   != (unsigned int)sig ||
++      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
++      (par.bits != par.bps * 8)) {
++    LOG(ERROR) << "Unsupported audio parameters.";
++    goto bad_close;
++  }
++  state = kStopped;
++  volpending = 0;
++  vol = 0;
++  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
++  sio_onmove(hdl, &OnMoveCallback, this);
++  sio_onvol(hdl, &OnVolCallback, this);
++  return true;
++ bad_close:
++  sio_close(hdl);
++  return false;
++}
++
++void SndioAudioOutputStream::Close() {
++  if (state == kClosed)
++    return;
++  if (state == kRunning)
++    Stop();
++  state = kClosed;
++  delete [] buffer;
++  sio_close(hdl);
++  manager->ReleaseOutputStream(this);  // Calls the destructor
++}
++
++void SndioAudioOutputStream::Start(AudioSourceCallback* callback) {
++  state = kRunning;
++  hw_delay = 0;
++  source = callback;
++  sio_start(hdl);
++  if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
++    LOG(ERROR) << "Failed to create real-time thread.";
++    sio_stop(hdl);
++    state = kStopped;
++  }
++}
++
++void SndioAudioOutputStream::Stop() {
++  if (state == kStopped)
++    return;
++  state = kStopWait;
++  pthread_join(thread, NULL);
++  sio_stop(hdl);
++  state = kStopped;
++}
++
++void SndioAudioOutputStream::SetVolume(double v) {
++  pthread_mutex_lock(&mutex);
++  vol = v * SIO_MAXVOL;
++  volpending = 1;
++  pthread_mutex_unlock(&mutex);
++}
++
++void SndioAudioOutputStream::GetVolume(double* v) {
++  pthread_mutex_lock(&mutex);
++  *v = vol * (1. / SIO_MAXVOL);
++  pthread_mutex_unlock(&mutex);
++}
++
++// This stream is always used with sub second buffer sizes, where it's
++// sufficient to simply always flush upon Start().
++void SndioAudioOutputStream::Flush() {}
++
++void SndioAudioOutputStream::ThreadLoop(void) {
++  int avail, count, result;
++
++  while (state == kRunning) {
++    // Update volume if needed
++    pthread_mutex_lock(&mutex);
++    if (volpending) {
++      volpending = 0;
++      sio_setvol(hdl, vol);
++    }
++    pthread_mutex_unlock(&mutex);
++
++    // Get data to play
++    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
++	params.sample_rate());
++    count = source->OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get());
++    audio_bus->ToInterleaved(count, SampleFormatToBytesPerChannel(kSampleFormat), buffer);
++    if (count == 0) {
++      // We have to submit something to the device
++      count = audio_bus->frames();
++      memset(buffer, 0, count * params.GetBytesPerFrame(kSampleFormat));
++      LOG(WARNING) << "No data to play, running empty cycle.";
++    }
++
++    // Submit data to the device
++    avail = count * params.GetBytesPerFrame(kSampleFormat);
++    result = sio_write(hdl, buffer, avail);
++    if (result == 0) {
++      LOG(WARNING) << "Audio device disconnected.";
++      break;
++    }
++
++    // Update hardware pointer
++    hw_delay += count;
++  }
++}
++
++}  // namespace media
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/sndio_output.h chromium-83.0.4103.97/media/audio/sndio/sndio_output.h
+--- media/audio/sndio/sndio_output.h.orig	1970-01-01 01:00:00.000000000 +0100
++++ media/audio/sndio/sndio_output.h	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,86 @@
++// Copyright (c) 2012 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 MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
++#define MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
++
++#include <pthread.h>
++#include <sndio.h>
++
++#include "base/time/tick_clock.h"
++#include "base/time/time.h"
++#include "media/audio/audio_io.h"
++
++namespace media {
++
++class AudioManagerBase;
++
++// Implementation of AudioOutputStream using sndio(7)
++class SndioAudioOutputStream : public AudioOutputStream {
++ public:
++  // The manager is creating this object
++  SndioAudioOutputStream(const AudioParameters& params,
++                         AudioManagerBase* manager);
++  virtual ~SndioAudioOutputStream();
++
++  // Implementation of AudioOutputStream.
++  bool Open() override;
++  void Close() override;
++  void Start(AudioSourceCallback* callback) override;
++  void Stop() override;
++  void SetVolume(double volume) override;
++  void GetVolume(double* volume) override;
++  void Flush() override;
++
++  friend void sndio_onmove(void *arg, int delta);
++  friend void sndio_onvol(void *arg, unsigned int vol);
++  friend void *sndio_threadstart(void *arg);
++
++ private:
++  enum StreamState {
++    kClosed,            // Not opened yet
++    kStopped,           // Device opened, but not started yet
++    kRunning,           // Started, device playing
++    kStopWait           // Stopping, waiting for the real-time thread to exit
++  };
++
++  // C-style call-backs
++  static void OnMoveCallback(void *arg, int delta);
++  static void OnVolCallback(void *arg, unsigned int vol);
++  static void* ThreadEntry(void *arg);
++
++  // Continuously moves data from the producer to the device
++  void ThreadLoop(void);
++
++  // Our creator, the audio manager needs to be notified when we close.
++  AudioManagerBase* manager;
++  // Parameters of the source
++  AudioParameters params;
++  // Source stores data here
++  std::unique_ptr<AudioBus> audio_bus;
++  // Call-back that produces data to play
++  AudioSourceCallback* source;
++  // Handle of the audio device
++  struct sio_hdl* hdl;
++  // Current state of the stream
++  enum StreamState state;
++  // High priority thread running ThreadLoop()
++  pthread_t thread;
++  // Protects vol, volpending and hw_delay
++  pthread_mutex_t mutex;
++  // Current volume in the 0..SIO_MAXVOL range
++  int vol;
++  // Set to 1 if volumes must be refreshed in the realtime thread
++  int volpending;
++  // Number of frames buffered in the hardware
++  int hw_delay;
++  // Temporary buffer where data is stored sndio-compatible format
++  char* buffer;
++
++  DISALLOW_COPY_AND_ASSIGN(SndioAudioOutputStream);
++};
++
++}  // namespace media
++
++#endif  // MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
+diff -Naur chromium-83.0.4103.97.orig/media/media_options.gni chromium-83.0.4103.97/media/media_options.gni
+--- media/media_options.gni.orig	2020-06-03 20:40:26.000000000 +0200
++++ media/media_options.gni	2020-06-13 17:32:28.512395963 +0200
+@@ -119,6 +119,9 @@
+   # Enables runtime selection of ALSA library for audio.
+   use_alsa = false
+ 
++  # Enable runtime selection of sndio(7)
++  use_sndio = false
++
+   # Alsa should be used on non-Android, non-Mac POSIX systems.
+   # Alsa should be used on desktop Chromecast and audio-only Chromecast builds.
+   if (is_posix && !is_android && !is_mac &&
diff --git a/srcpkgs/electron13/files/patches/chromium-system-nodejs.patch b/srcpkgs/electron13/files/patches/chromium-system-nodejs.patch
new file mode 100644
index 000000000000..866b516656fd
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-system-nodejs.patch
@@ -0,0 +1,20 @@
+--- third_party/node/node.py	2021-05-20 04:17:54.000000000 +0200
++++ -	2021-05-25 11:57:32.895222559 +0200
+@@ -17,11 +17,12 @@
+   if platform.system() == 'Darwin' and platform.machine() == 'arm64':
+       return os.path.join(os_path.join(os_path.dirname(__file__), 'mac',
+                           'node-darwin-arm64', 'bin', 'node'))
+-  return os_path.join(os_path.dirname(__file__), *{
+-    'Darwin': ('mac', 'node-darwin-x64', 'bin', 'node'),
+-    'Linux': ('linux', 'node-linux-x64', 'bin', 'node'),
+-    'Windows': ('win', 'node.exe'),
+-  }[platform.system()])
++  return "/usr/bin/node"
++  #return os_path.join(os_path.dirname(__file__), *{
++  #  'Darwin': ('mac', 'node-darwin-x64', 'bin', 'node'),
++  #  'Linux': ('linux', 'node-linux-x64', 'bin', 'node'),
++  #  'Windows': ('win', 'node.exe'),
++  #}[platform.system()])
+ 
+ 
+ def RunNode(cmd_parts, stdout=None):
diff --git a/srcpkgs/electron13/files/patches/chromium-webrtc-include.patch b/srcpkgs/electron13/files/patches/chromium-webrtc-include.patch
new file mode 100644
index 000000000000..92ec272a89ac
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-webrtc-include.patch
@@ -0,0 +1,10 @@
+--- third_party/webrtc/modules/desktop_capture/linux/window_capturer_x11.cc.orig	2019-02-21 21:21:24.488058990 +0100
++++ third_party/webrtc/modules/desktop_capture/linux/window_capturer_x11.cc	2019-02-21 21:21:36.151961064 +0100
+@@ -16,6 +16,7 @@
+ 
+ #include <memory>
+ #include <string>
++#include <string.h>
+ #include <utility>
+ 
+ #include "modules/desktop_capture/desktop_frame.h"
diff --git a/srcpkgs/electron13/files/patches/chromium-webrtc-r0.patch b/srcpkgs/electron13/files/patches/chromium-webrtc-r0.patch
new file mode 100644
index 000000000000..70bbede472f4
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-webrtc-r0.patch
@@ -0,0 +1,33 @@
+Upstream: Yes, https://webrtc-review.googlesource.com/9384
+Reason: Fixes musl builds of webrtc
+
+From 7f90e2cceda0458cf56026eb6ccffb961a47804b Mon Sep 17 00:00:00 2001
+From: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com>
+Date: Fri, 13 Oct 2017 15:49:32 +0200
+Subject: [PATCH] IWYU: Include math.h for round(3).
+
+math.h was being implicitly included, which can break the build with
+alternative libc implementations.
+
+Bug: None
+Change-Id: I969b320b65d0f44abb33d3e1036cfbcb859a4952
+Reviewed-on: https://webrtc-review.googlesource.com/9384
+Reviewed-by: Tommi <tommi@webrtc.org>
+Commit-Queue: Raphael Kubo da Costa (rakuco) <raphael.kubo.da.costa@intel.com>
+Cr-Commit-Position: refs/heads/master@{#20292}
+---
+
+--- third_party/webrtc/p2p/base/port.cc
++++ third_party/webrtc/p2p/base/port.cc
+@@ -10,6 +10,8 @@
+ 
+ #include "p2p/base/port.h"
+ 
++#include <math.h>
++
+ #include <algorithm>
+ #include <vector>
+ 
+-- 
+2.15.0.rc2
+
diff --git a/srcpkgs/electron13/files/patches/chromium-webrtc-size_t.patch b/srcpkgs/electron13/files/patches/chromium-webrtc-size_t.patch
new file mode 100644
index 000000000000..ef7ea09cf632
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-webrtc-size_t.patch
@@ -0,0 +1,10 @@
+--- third_party/webrtc/modules/audio_processing/aec3/clockdrift_detector.h	2020-08-10 20:42:29.000000000 +0200
++++ third_party/webrtc/modules/audio_processing/aec3/clockdrift_detector.h	2020-09-04 12:47:07.014833633 +0200
+@@ -12,6 +12,7 @@
+ #define MODULES_AUDIO_PROCESSING_AEC3_CLOCKDRIFT_DETECTOR_H_
+ 
+ #include <array>
++#include <cstddef>
+ 
+ namespace webrtc {
+ 
diff --git a/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-libvpx.patch b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-libvpx.patch
new file mode 100644
index 000000000000..792befb3a39d
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-libvpx.patch
@@ -0,0 +1,72 @@
+Uses generic target for now. To use ppc64le, change --target to ppc64le-gnu
+and add --enable-vsx, and change generic to ppc for the rtcd header.
+
+From 18e6c5c55cfae0cfb458d8210d7bc709360a0e90 Mon Sep 17 00:00:00 2001
+From: q66 <daniel@octaforge.org>
+Date: Wed, 9 Sep 2020 19:08:25 +0200
+Subject: [PATCH] enable generation of ppc64 libvpx bits
+
+this doesn't update the gni file, that's done from
+the template by running the appropriate scripts
+---
+ third_party/libvpx/BUILD.gn        | 4 ++++
+ third_party/libvpx/generate_gni.sh | 9 +++++++++
+ 2 files changed, 13 insertions(+)
+
+diff --git third_party/libvpx/BUILD.gn third_party/libvpx/BUILD.gn
+index 7198e59..3300485 100644
+--- third_party/libvpx/BUILD.gn
++++ third_party/libvpx/BUILD.gn
+@@ -336,6 +336,8 @@ static_library("libvpx") {
+     } else {
+       sources = libvpx_srcs_arm64
+     }
++  } else if (current_cpu == "ppc64") {
++    sources = libvpx_srcs_ppc64
+   }
+ 
+   configs -= [ "//build/config/compiler:chromium_code" ]
+diff --git third_party/libvpx/generate_gni.sh third_party/libvpx/generate_gni.sh
+index bcf84b0..8a3f4f1 100755
+--- third_party/libvpx/generate_gni.sh
++++ third_party/libvpx/generate_gni.sh
+@@ -361,6 +361,7 @@ gen_config_files linux/arm-neon-highbd "--target=armv7-linux-gcc ${all_platforms
+ gen_config_files linux/arm64-highbd "--target=armv8-linux-gcc ${all_platforms} ${HIGHBD}"
+ gen_config_files linux/mipsel "--target=mips32-linux-gcc ${all_platforms}"
+ gen_config_files linux/mips64el "--target=mips64-linux-gcc ${all_platforms}"
++gen_config_files linux/ppc64 "--target=generic-gnu $HIGHBD ${all_platforms}"
+ gen_config_files linux/generic "--target=generic-gnu $HIGHBD ${all_platforms}"
+ gen_config_files win/arm64 "--target=arm64-win64-vs15 ${all_platforms} ${HIGHBD}"
+ gen_config_files win/ia32 "--target=x86-win32-vs14 ${all_platforms} ${x86_platforms}"
+@@ -386,6 +387,7 @@ lint_config linux/arm-neon-highbd
+ lint_config linux/arm64-highbd
+ lint_config linux/mipsel
+ lint_config linux/mips64el
++lint_config linux/ppc64
+ lint_config linux/generic
+ lint_config win/arm64
+ lint_config win/ia32
+@@ -415,6 +417,7 @@ gen_rtcd_header linux/arm-neon-highbd armv7
+ gen_rtcd_header linux/arm64-highbd armv8
+ gen_rtcd_header linux/mipsel mipsel
+ gen_rtcd_header linux/mips64el mips64el
++gen_rtcd_header linux/ppc64 generic
+ gen_rtcd_header linux/generic generic
+ gen_rtcd_header win/arm64 armv8
+ gen_rtcd_header win/ia32 x86 "${require_sse2}"
+@@ -500,6 +503,12 @@ if [ -z $ONLY_CONFIGS ]; then
+ 
+   echo "MIPS64 source list is identical to MIPS source list. No need to generate it."
+ 
++  echo "Generate ppc64 source list."
++  config=$(print_config_basic linux/ppc64)
++  make_clean
++  make libvpx_srcs.txt target=libs $config > /dev/null
++  convert_srcs_to_project_files libvpx_srcs.txt libvpx_srcs_ppc64
++
+   echo "Generate NaCl source list."
+   config=$(print_config_basic nacl)
+   make_clean
+-- 
+2.28.0
+
diff --git a/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-support.patch b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-support.patch
new file mode 100644
index 000000000000..bd0b0f654a96
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-support.patch
@@ -0,0 +1,3636 @@
+commit 2c013a317b1114ef67cdbbc30824b28907b9ea94
+Author: Daniel Kolesa <daniel@octaforge.org>
+Date:   Wed Mar 3 19:08:29 2021 +0100
+
+    ppc64le support
+
+diff --git build/download_nacl_toolchains.py build/download_nacl_toolchains.py
+index 286a92a27..ec36a85d3 100755
+--- build/download_nacl_toolchains.py
++++ 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 chrome/installer/linux/BUILD.gn chrome/installer/linux/BUILD.gn
+index 35f01d0a4..28f2e7475 100644
+--- chrome/installer/linux/BUILD.gn
++++ chrome/installer/linux/BUILD.gn
+@@ -94,8 +94,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") {
+@@ -315,7 +313,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 sandbox/features.gni sandbox/features.gni
+index db30ae6d6..9dc09bf53 100644
+--- sandbox/features.gni
++++ sandbox/features.gni
+@@ -11,7 +11,8 @@ import("//build/config/nacl/config.gni")
+ use_seccomp_bpf = (is_linux || is_chromeos || 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 sandbox/linux/BUILD.gn sandbox/linux/BUILD.gn
+index e9a94b461..cca1a5da5 100644
+--- sandbox/linux/BUILD.gn
++++ sandbox/linux/BUILD.gn
+@@ -427,6 +427,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 sandbox/linux/bpf_dsl/linux_syscall_ranges.h sandbox/linux/bpf_dsl/linux_syscall_ranges.h
+index 313511f22..0ca3a326f 100644
+--- sandbox/linux/bpf_dsl/linux_syscall_ranges.h
++++ 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 sandbox/linux/bpf_dsl/seccomp_macros.h sandbox/linux/bpf_dsl/seccomp_macros.h
+index 1a407b952..a6aec544e 100644
+--- sandbox/linux/bpf_dsl/seccomp_macros.h
++++ 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 sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
+index 6a1ec2389..f20c582dd 100644
+--- sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
++++ 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__)
+@@ -227,7 +228,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
+@@ -245,7 +246,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,
+@@ -285,7 +286,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 sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
+index 01c046dda..7e5a6be82 100644
+--- sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
++++ sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
+@@ -302,7 +302,7 @@
+ TEST_BASELINE_SIGSYS(__NR_syslog)
+ TEST_BASELINE_SIGSYS(__NR_timer_create)
+ 
+-#if !defined(__aarch64__)
++#if !defined(__aarch64__) && !defined(__powerpc64__)
+ TEST_BASELINE_SIGSYS(__NR_inotify_init)
+ TEST_BASELINE_SIGSYS(__NR_vserver)
+ #endif
+diff --git sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+index 2a97d3916..8e81aa6cf 100644
+--- sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
++++ sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+@@ -40,7 +40,8 @@
+ #include <sys/ptrace.h>
+ #if (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \
+     !defined(__arm__) && !defined(__aarch64__) &&           \
+-    !defined(PTRACE_GET_THREAD_AREA)
++    !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
+@@ -49,6 +50,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)
+@@ -98,6 +104,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
+@@ -239,6 +254,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);
+@@ -277,7 +277,15 @@
+               F_SETLKW,
+               F_GETLK,
+               F_DUPFD,
+-              F_DUPFD_CLOEXEC),
++              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()))
+@@ -287,7 +295,7 @@
+   // clang-format on
+ }
+ 
+-#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
+@@ -413,7 +439,7 @@ ResultExpr RestrictPtrace() {
+ #endif
+   return Switch(request)
+       .CASES((
+-#if !defined(__aarch64__)
++#if !defined(__aarch64__) && !defined(__powerpc64__)
+                  PTRACE_GETREGS, PTRACE_GETFPREGS, PTRACE_GET_THREAD_AREA,
+                  PTRACE_GETREGSET,
+ #endif
+diff --git sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
+index ba4289f05..9a4d5ab2d 100644
+--- sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
++++ 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 sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+index 642df7207..34f47eb73 100644
+--- sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
++++ 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;
+@@ -45,12 +46,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:
+@@ -116,7 +119,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))
+@@ -135,7 +138,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
+@@ -149,7 +152,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:
+@@ -159,7 +163,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.
+@@ -181,7 +186,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__)
+@@ -194,11 +200,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__) || \
+@@ -206,6 +213,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;
+@@ -231,7 +240,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;
+@@ -272,7 +282,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
+@@ -350,7 +350,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_rt_sigtimedwait_time64:
+     case __NR_sigaction:
+     case __NR_sigprocmask:
+@@ -339,7 +350,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
+@@ -363,7 +375,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;
+@@ -397,7 +409,7 @@ bool SyscallSets::IsAllowedProcessStartOrDeath(int sysno) {
+     case __NR_membarrier:
+     case __NR_wait4:
+     case __NR_waitid:
+-#if defined(__i386__)
++#if defined(__i386__) || defined(__powerpc64__)
+     case __NR_waitpid:
+ #endif
+       return true;
+@@ -414,7 +426,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:
+@@ -463,7 +475,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;
+@@ -473,7 +485,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:
+@@ -488,7 +500,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) {
+@@ -502,7 +515,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:
+@@ -527,7 +541,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__) || \
+@@ -557,7 +571,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__)
+@@ -569,26 +584,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
+@@ -645,7 +662,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:
+@@ -657,7 +675,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:
+@@ -673,7 +692,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:
+@@ -706,7 +726,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:
+@@ -722,7 +743,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:
+@@ -751,14 +772,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:
+@@ -792,7 +814,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
+@@ -854,8 +876,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) {
+@@ -887,7 +917,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) {
+@@ -907,7 +938,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
+ }
+@@ -960,7 +992,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:
+@@ -1019,18 +1052,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:
+@@ -1038,20 +1075,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 sandbox/linux/seccomp-bpf-helpers/syscall_sets.h sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
+index 923533ec9..411f72acd 100644
+--- sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
++++ 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 sandbox/linux/seccomp-bpf/syscall.cc sandbox/linux/seccomp-bpf/syscall.cc
+index e47e98bf5..d53a7ff56 100644
+--- sandbox/linux/seccomp-bpf/syscall.cc
++++ sandbox/linux/seccomp-bpf/syscall.cc
+@@ -18,7 +18,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
+@@ -310,12 +310,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]);
+ }
+@@ -429,6 +473,8 @@ intptr_t Syscall::Call(int nr,
+     ret = inout;
+   }
+ 
++#elif defined(__powerpc64__)
++  intptr_t ret = SyscallAsm(nr, args);
+ #else
+ #error "Unimplemented architecture"
+ #endif
+@@ -445,8 +491,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 sandbox/linux/seccomp-bpf/trap.cc sandbox/linux/seccomp-bpf/trap.cc
+index f5b86a73a..5e6c4a068 100644
+--- sandbox/linux/seccomp-bpf/trap.cc
++++ 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 sandbox/linux/services/credentials.cc sandbox/linux/services/credentials.cc
+index d7b5d8c44..4adc6d0d4 100644
+--- sandbox/linux/services/credentials.cc
++++ 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 sandbox/linux/services/syscall_wrappers.cc sandbox/linux/services/syscall_wrappers.cc
+index fcfd2aa12..f6eb32fb7 100644
+--- sandbox/linux/services/syscall_wrappers.cc
++++ 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 sandbox/linux/syscall_broker/broker_process.cc sandbox/linux/syscall_broker/broker_process.cc
+index d72c9d238..77f1d95f5 100644
+--- sandbox/linux/syscall_broker/broker_process.cc
++++ sandbox/linux/syscall_broker/broker_process.cc
+@@ -169,7 +169,7 @@ bool BrokerProcess::IsSyscallBrokerable(int sysno, bool fast_check) const {
+ #if defined(__NR_fstatat64)
+     case __NR_fstatat64:
+ #endif
+-#if defined(__x86_64__) || defined(__aarch64__)
++#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__)
+     case __NR_newfstatat:
+ #endif
+       return !fast_check || allowed_command_set_.test(COMMAND_STAT);
+diff --git sandbox/linux/system_headers/linux_seccomp.h sandbox/linux/system_headers/linux_seccomp.h
+index 1fa47ed09..39cc9ab53 100644
+--- sandbox/linux/system_headers/linux_seccomp.h
++++ sandbox/linux/system_headers/linux_seccomp.h
+@@ -41,6 +41,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
+@@ -73,6 +76,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 sandbox/linux/system_headers/linux_signal.h sandbox/linux/system_headers/linux_signal.h
+index f5a736761..515b21a5f 100644
+--- sandbox/linux/system_headers/linux_signal.h
++++ 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 sandbox/linux/system_headers/linux_syscalls.h sandbox/linux/system_headers/linux_syscalls.h
+index 2b78a0cc3..0a70f5ea5 100644
+--- sandbox/linux/system_headers/linux_syscalls.h
++++ 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 sandbox/linux/system_headers/linux_ucontext.h sandbox/linux/system_headers/linux_ucontext.h
+index 22ce78027..a69b024c2 100644
+--- sandbox/linux/system_headers/linux_ucontext.h
++++ 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 sandbox/linux/system_headers/ppc64_linux_syscalls.h sandbox/linux/system_headers/ppc64_linux_syscalls.h
+new file mode 100644
+index 000000000..ccacffe22
+--- /dev/null
++++ 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 sandbox/linux/system_headers/ppc64_linux_ucontext.h sandbox/linux/system_headers/ppc64_linux_ucontext.h
+new file mode 100644
+index 000000000..07728e087
+--- /dev/null
++++ 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 sandbox/policy/linux/bpf_renderer_policy_linux.cc sandbox/policy/linux/bpf_renderer_policy_linux.cc
+index 2588fc792..d455c4601 100644
+--- sandbox/policy/linux/bpf_renderer_policy_linux.cc
++++ sandbox/policy/linux/bpf_renderer_policy_linux.cc
+@@ -15,6 +15,11 @@
+ #include "sandbox/linux/system_headers/linux_syscalls.h"
+ #include "sandbox/policy/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 third_party/angle/src/compiler/translator/InfoSink.h third_party/angle/src/compiler/translator/InfoSink.h
+index 3a807e1e3..5258617a7 100644
+--- third_party/angle/src/compiler/translator/InfoSink.h
++++ 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 third_party/angle/src/libANGLE/Constants.h third_party/angle/src/libANGLE/Constants.h
+index fcbc9246a..39ae66148 100644
+--- third_party/angle/src/libANGLE/Constants.h
++++ 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 third_party/boringssl/BUILD.gn third_party/boringssl/BUILD.gn
+index 17cf9cda9..8ce96bd32 100644
+--- third_party/boringssl/BUILD.gn
++++ third_party/boringssl/BUILD.gn
+@@ -103,6 +103,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 third_party/breakpad/BUILD.gn third_party/breakpad/BUILD.gn
+index 4af3d7bbf..adbf54159 100644
+--- third_party/breakpad/BUILD.gn
++++ third_party/breakpad/BUILD.gn
+@@ -596,7 +596,6 @@ if (is_linux || is_chromeos || is_android) {
+       "breakpad/src/client/minidump_file_writer.h",
+       "breakpad/src/common/convert_UTF.cc",
+       "breakpad/src/common/convert_UTF.h",
+-      "breakpad/src/common/linux/breakpad_getcontext.S",
+       "breakpad/src/common/linux/elf_core_dump.cc",
+       "breakpad/src/common/linux/elf_core_dump.h",
+       "breakpad/src/common/linux/elfutils.cc",
+@@ -634,6 +633,14 @@ if (is_linux || is_chromeos || is_android) {
+ 
+     libs = [ "dl" ]
+ 
++    if (current_cpu == "ppc64") {
++        defines = [ "HAVE_GETCONTEXT" ]
++    } else {
++        sources += [
++            "breakpad/src/common/linux/breakpad_getcontext.S"
++        ]
++    }
++
+     include_dirs = [
+       ".",
+       "breakpad/src",
+@@ -682,7 +689,6 @@ if (is_linux || is_chromeos || is_android) {
+       "breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc",
+       "breakpad/src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc",
+       "breakpad/src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc",
+-      "breakpad/src/common/linux/breakpad_getcontext_unittest.cc",
+       "breakpad/src/common/linux/elf_core_dump_unittest.cc",
+       "breakpad/src/common/linux/file_id_unittest.cc",
+       "breakpad/src/common/linux/linux_libc_support_unittest.cc",
+diff --git third_party/breakpad/breakpad/src/client/linux/dump_writer_common/raw_context_cpu.h third_party/breakpad/breakpad/src/client/linux/dump_writer_common/raw_context_cpu.h
+index 07d9171a0..9aed4cb36 100644
+--- third_party/breakpad/breakpad/src/client/linux/dump_writer_common/raw_context_cpu.h
++++ 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 third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
+index aae1dc13b..03afec7a5 100644
+--- third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
++++ 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 third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.h third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.h
+index fb216fa6d..593aac822 100644
+--- third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.h
++++ 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 third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
+index 6eec1be24..741983a1a 100644
+--- third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
++++ 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 third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h
+index 7d4100881..c122ac92e 100644
+--- third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h
++++ third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h
+@@ -55,6 +55,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 third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
+index a6cb5f984..ae16b64d9 100644
+--- third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
++++ 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) {
+@@ -708,11 +715,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.
+@@ -733,6 +748,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 third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.h third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.h
+index f80843ea7..260dd10f7 100644
+--- third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.h
++++ 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 third_party/breakpad/breakpad/src/client/linux/handler/exception_handler_unittest.cc third_party/breakpad/breakpad/src/client/linux/handler/exception_handler_unittest.cc
+index 35dcbfd4d..7934370fd 100644
+--- third_party/breakpad/breakpad/src/client/linux/handler/exception_handler_unittest.cc
++++ 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 third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer.cc third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer.cc
+index fa3c1713a..6ce709e2f 100644
+--- third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer.cc
++++ 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 third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer_unittest.cc third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer_unittest.cc
+index 6339ac0cd..291af106b 100644
+--- third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer_unittest.cc
++++ third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer_unittest.cc
+@@ -279,10 +279,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 third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_core_dumper.cc third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_core_dumper.cc
+index 415068983..b93e4afcf 100644
+--- third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_core_dumper.cc
++++ 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 third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.cc third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.cc
+index 7fd6532ad..199cbfffd 100644
+--- third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.cc
++++ 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 third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.h third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.h
+index 7bee160f1..07bb2b81a 100644
+--- third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper.h
++++ 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 third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
+index 331f4bb34..3f722947f 100644
+--- third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
++++ 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 third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.cc third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
+index e3ddb81a6..fa28575ef 100644
+--- third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
++++ 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 third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
+index da71e15dc..12bfb317a 100644
+--- third_party/breakpad/breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
++++ 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 third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.cc third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.cc
+index 32634ef00..2a56948de 100644
+--- third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.cc
++++ 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 third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.h third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.h
+index e3b0b16da..ccd8aa0a4 100644
+--- third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.h
++++ third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer.h
+@@ -48,6 +48,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 std::remove_pointer<fpregset_t>::type fpstate_t;
+ #endif
+diff --git third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc
+index d192e5cbb..fc1bfa8d7 100644
+--- third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc
++++ third_party/breakpad/breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc
+@@ -715,6 +715,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 third_party/breakpad/breakpad/src/common/linux/memory_mapped_file.cc third_party/breakpad/breakpad/src/common/linux/memory_mapped_file.cc
+index 99362945c..c54ba7145 100644
+--- third_party/breakpad/breakpad/src/common/linux/memory_mapped_file.cc
++++ 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 third_party/breakpad/breakpad/src/common/linux/memory_mapped_file_unittest.cc third_party/breakpad/breakpad/src/common/linux/memory_mapped_file_unittest.cc
+index fad59f40c..616496d67 100644
+--- third_party/breakpad/breakpad/src/common/linux/memory_mapped_file_unittest.cc
++++ 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 third_party/breakpad/breakpad/src/common/memory_allocator_unittest.cc third_party/breakpad/breakpad/src/common/memory_allocator_unittest.cc
+index 5803b90d5..2a1cf14f0 100644
+--- third_party/breakpad/breakpad/src/common/memory_allocator_unittest.cc
++++ third_party/breakpad/breakpad/src/common/memory_allocator_unittest.cc
+@@ -57,8 +57,9 @@ TEST(PageAllocatorTest, LargeObject) {
+ 
+   EXPECT_EQ(0U, allocator.pages_allocated());
+   uint8_t* p = reinterpret_cast<uint8_t*>(allocator.Alloc(10000));
++  uint64_t expected_pages = 1 + ((10000 - 1) / getpagesize());
+   ASSERT_FALSE(p == NULL);
+-  EXPECT_EQ(3U, allocator.pages_allocated());
++  EXPECT_EQ(expected_pages, allocator.pages_allocated());
+   for (unsigned i = 1; i < 10; ++i) {
+     uint8_t* p = reinterpret_cast<uint8_t*>(allocator.Alloc(i));
+     ASSERT_FALSE(p == NULL);
+diff --git third_party/breakpad/breakpad/src/processor/exploitability_linux.cc third_party/breakpad/breakpad/src/processor/exploitability_linux.cc
+index 798056dfa..22bd81fff 100644
+--- third_party/breakpad/breakpad/src/processor/exploitability_linux.cc
++++ 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 third_party/breakpad/breakpad/src/processor/exploitability_unittest.cc third_party/breakpad/breakpad/src/processor/exploitability_unittest.cc
+index 528ee5f21..72764d6c1 100644
+--- third_party/breakpad/breakpad/src/processor/exploitability_unittest.cc
++++ 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 third_party/breakpad/breakpad/src/tools/linux/md2core/minidump-2-core.cc third_party/breakpad/breakpad/src/tools/linux/md2core/minidump-2-core.cc
+index aade82c99..195aa73f3 100644
+--- third_party/breakpad/breakpad/src/tools/linux/md2core/minidump-2-core.cc
++++ third_party/breakpad/breakpad/src/tools/linux/md2core/minidump-2-core.cc
+@@ -77,6 +77,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__)
+@@ -87,6 +89,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;
+@@ -321,6 +325,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;
+@@ -535,6 +542,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
+@@ -623,6 +662,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 third_party/crashpad/crashpad/CONTRIBUTORS third_party/crashpad/crashpad/CONTRIBUTORS
+index 8724b7f32..8e29424ef 100644
+--- third_party/crashpad/crashpad/CONTRIBUTORS
++++ 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 third_party/crashpad/crashpad/compat/linux/sys/user.h third_party/crashpad/crashpad/compat/linux/sys/user.h
+index 6ed77a98e..1fd83469a 100644
+--- third_party/crashpad/crashpad/compat/linux/sys/user.h
++++ 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 third_party/crashpad/crashpad/minidump/minidump_context.h third_party/crashpad/crashpad/minidump/minidump_context.h
+index 3a3e603cb..3118d9e9f 100644
+--- third_party/crashpad/crashpad/minidump/minidump_context.h
++++ 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 third_party/crashpad/crashpad/minidump/minidump_context_writer.cc third_party/crashpad/crashpad/minidump/minidump_context_writer.cc
+index d7e53a493..d89eb9e01 100644
+--- third_party/crashpad/crashpad/minidump/minidump_context_writer.cc
++++ 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 third_party/crashpad/crashpad/minidump/minidump_context_writer.h third_party/crashpad/crashpad/minidump/minidump_context_writer.h
+index d4ab936ee..1d22fc59c 100644
+--- third_party/crashpad/crashpad/minidump/minidump_context_writer.h
++++ 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 object’s 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 third_party/crashpad/crashpad/minidump/minidump_context_writer_test.cc third_party/crashpad/crashpad/minidump/minidump_context_writer_test.cc
+index 3216a906b..a9fcbe9d8 100644
+--- third_party/crashpad/crashpad/minidump/minidump_context_writer_test.cc
++++ 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 third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc
+index 0974e3ddf..b71ec5880 100644
+--- third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc
++++ third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc
+@@ -135,6 +135,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 third_party/crashpad/crashpad/snapshot/capture_memory.cc third_party/crashpad/crashpad/snapshot/capture_memory.cc
+index 7a1b2763c..beda8da9e 100644
+--- third_party/crashpad/crashpad/snapshot/capture_memory.cc
++++ third_party/crashpad/crashpad/snapshot/capture_memory.cc
+@@ -112,6 +112,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 third_party/crashpad/crashpad/snapshot/cpu_architecture.h third_party/crashpad/crashpad/snapshot/cpu_architecture.h
+index 811a72095..f4f83981d 100644
+--- third_party/crashpad/crashpad/snapshot/cpu_architecture.h
++++ 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 third_party/crashpad/crashpad/snapshot/cpu_context.cc third_party/crashpad/crashpad/snapshot/cpu_context.cc
+index c75b5555e..aeade577a 100644
+--- third_party/crashpad/crashpad/snapshot/cpu_context.cc
++++ 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 third_party/crashpad/crashpad/snapshot/cpu_context.h third_party/crashpad/crashpad/snapshot/cpu_context.h
+index fb23c4679..eebede63c 100644
+--- third_party/crashpad/crashpad/snapshot/cpu_context.h
++++ 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 third_party/crashpad/crashpad/snapshot/linux/cpu_context_linux.h third_party/crashpad/crashpad/snapshot/linux/cpu_context_linux.h
+index 9f46a4897..aa677c4eb 100644
+--- third_party/crashpad/crashpad/snapshot/linux/cpu_context_linux.h
++++ 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 third_party/crashpad/crashpad/snapshot/linux/debug_rendezvous_test.cc third_party/crashpad/crashpad/snapshot/linux/debug_rendezvous_test.cc
+index d32bd1937..2dd538c2b 100644
+--- third_party/crashpad/crashpad/snapshot/linux/debug_rendezvous_test.cc
++++ third_party/crashpad/crashpad/snapshot/linux/debug_rendezvous_test.cc
+@@ -192,6 +192,8 @@ void TestAgainstTarget(PtraceConnection* connection) {
+               device == 0 && inode == 0 && mapping_name == "[vdso]";
+ #if defined(ARCH_CPU_X86)
+           static constexpr char kPrefix[] = "linux-gate.so.";
++#elif defined(ARCH_CPU_PPC64)
++          static constexpr char kPrefix[] = "linux-vdso64.so.";
+ #else
+           static constexpr char kPrefix[] = "linux-vdso.so.";
+ #endif
+diff --git third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc
+index cd40b3b12..6bcf23b6f 100644
+--- third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc
++++ 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 third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h
+index ea0cd2106..e42df520f 100644
+--- third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h
++++ 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 third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc
+index c17170b43..b6a714cc6 100644
+--- third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc
++++ 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 third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc
+index ee246e8bc..9555dce04 100644
+--- third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc
++++ 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 third_party/crashpad/crashpad/snapshot/linux/signal_context.h third_party/crashpad/crashpad/snapshot/linux/signal_context.h
+index 110024680..a1f2da259 100644
+--- third_party/crashpad/crashpad/snapshot/linux/signal_context.h
++++ 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 third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
+index a99da3e4b..03b973083 100644
+--- third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
++++ third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
+@@ -204,6 +204,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
+@@ -219,6 +221,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
+@@ -239,6 +244,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
+@@ -372,6 +380,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 third_party/crashpad/crashpad/snapshot/linux/test_modules.cc third_party/crashpad/crashpad/snapshot/linux/test_modules.cc
+index b2450c206..7ba78b2ae 100644
+--- third_party/crashpad/crashpad/snapshot/linux/test_modules.cc
++++ third_party/crashpad/crashpad/snapshot/linux/test_modules.cc
+@@ -110,6 +110,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 third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc
+index e3e2bebdd..8ef43752e 100644
+--- third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc
++++ 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 third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h
+index 44cc6f6d9..d4136461e 100644
+--- third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h
++++ 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 third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc
+index d3d5ebdfb..3fd730cb5 100644
+--- third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc
++++ 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 third_party/crashpad/crashpad/util/linux/ptracer.cc third_party/crashpad/crashpad/util/linux/ptracer.cc
+index 557e0d363..08ae434b8 100644
+--- third_party/crashpad/crashpad/util/linux/ptracer.cc
++++ 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 third_party/crashpad/crashpad/util/linux/thread_info.h third_party/crashpad/crashpad/util/linux/thread_info.h
+index 5b55c24a7..dea0d1f39 100644
+--- third_party/crashpad/crashpad/util/linux/thread_info.h
++++ 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 third_party/crashpad/crashpad/util/misc/capture_context.h third_party/crashpad/crashpad/util/misc/capture_context.h
+index d21a24f19..acc325349 100644
+--- third_party/crashpad/crashpad/util/misc/capture_context.h
++++ third_party/crashpad/crashpad/util/misc/capture_context.h
+@@ -69,6 +69,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 third_party/crashpad/crashpad/util/misc/capture_context_linux.S third_party/crashpad/crashpad/util/misc/capture_context_linux.S
+index 52215ee5d..b3e4a3ec7 100644
+--- third_party/crashpad/crashpad/util/misc/capture_context_linux.S
++++ 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 third_party/crashpad/crashpad/util/misc/capture_context_test.cc third_party/crashpad/crashpad/util/misc/capture_context_test.cc
+index cf23c2def..5f264bc92 100644
+--- third_party/crashpad/crashpad/util/misc/capture_context_test.cc
++++ 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 third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc
+index 30a2ab21d..60509f21d 100644
+--- third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc
++++ third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc
+@@ -35,6 +35,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
+ }
+ 
+@@ -49,6 +51,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
+ }
+ 
+@@ -63,6 +67,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 third_party/crashpad/crashpad/util/posix/signals_test.cc third_party/crashpad/crashpad/util/posix/signals_test.cc
+index 54cc2f19f..298b5c993 100644
+--- third_party/crashpad/crashpad/util/posix/signals_test.cc
++++ third_party/crashpad/crashpad/util/posix/signals_test.cc
+@@ -46,9 +46,9 @@ 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)
+@@ -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 don’t generate a
+     // trap for divide-by-zero, so this doesn’t 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 third_party/dav1d/BUILD.gn third_party/dav1d/BUILD.gn
+index 6b4566fc3..c07f732ad 100644
+--- third_party/dav1d/BUILD.gn
++++ third_party/dav1d/BUILD.gn
+@@ -184,6 +184,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
+@@ -212,6 +214,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
+@@ -263,6 +267,21 @@ if (current_cpu == "x86" || current_cpu == "x64") {
+       defines = [ "PREFIX" ]
+     }
+ 
++    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
+   }
+ }
+@@ -292,5 +311,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 third_party/dav1d/config/linux/ppc64/config.h third_party/dav1d/config/linux/ppc64/config.h
+new file mode 100644
+index 000000000..9fbbf75cc
+--- /dev/null
++++ third_party/dav1d/config/linux/ppc64/config.h
+@@ -0,0 +1,39 @@
++/*
++ * 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 -- Logging is controlled by Chromium
++
++#define ENDIANNESS_BIG 0
++
++#define HAVE_ASM 1
++
++#define HAVE_CLOCK_GETTIME 1
++
++#define HAVE_DLSYM 1
++
++#define HAVE_GETAUXVAL 1
++
++#define HAVE_POSIX_MEMALIGN 1
++
++#define HAVE_UNISTD_H 1
++
+diff --git third_party/dav1d/dav1d_generated.gni third_party/dav1d/dav1d_generated.gni
+index c59cb0821..3060284a8 100644
+--- third_party/dav1d/dav1d_generated.gni
++++ third_party/dav1d/dav1d_generated.gni
+@@ -82,6 +82,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 third_party/dav1d/generate_source.py third_party/dav1d/generate_source.py
+index 9ab5e00b8..ad3feffee 100755
+--- third_party/dav1d/generate_source.py
++++ third_party/dav1d/generate_source.py
+@@ -57,6 +57,8 @@
+   _WriteArray(fd, "arm64_asm_sources", _Glob("libdav1d/src/arm/64/*.S"))
+   _WriteArray(fd, "arm_template_sources", _Glob("libdav1d/src/arm/*_tmpl.c"))
+ 
++  _WriteArray(fd, "ppc64_template_sources", _Glob("libdav1d/src/ppc/*_tmpl.c"))
++
+   template_sources = _Glob("libdav1d/src/*_tmpl.c")
+   _WriteArray(fd, "template_sources", template_sources)
+ 
+diff --git third_party/dav1d/libdav1d/src/ppc/types.h third_party/dav1d/libdav1d/src/ppc/types.h
+index 0b4bd72f0..a0caa5e71 100644
+--- third_party/dav1d/libdav1d/src/ppc/types.h
++++ 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 third_party/lss/linux_syscall_support.h third_party/lss/linux_syscall_support.h
+index e4ac22644..1c57015db 100644
+--- third_party/lss/linux_syscall_support.h
++++ third_party/lss/linux_syscall_support.h
+@@ -3947,7 +3947,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,
+@@ -4058,7 +4058,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 third_party/pffft/src/pffft.c third_party/pffft/src/pffft.c
+index bdac4d784..51e0f2cac 100644
+--- third_party/pffft/src/pffft.c
++++ 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 third_party/skia/src/sksl/SkSLString.cpp third_party/skia/src/sksl/SkSLString.cpp
+index ec3e56964..4cf8999a2 100644
+--- third_party/skia/src/sksl/SkSLString.cpp
++++ third_party/skia/src/sksl/SkSLString.cpp
+@@ -234,7 +234,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());
+ }
+ 
+ bool stod(const StringFragment& s, SKSL_FLOAT* value) {
+diff --git third_party/sqlite/src/amalgamation/sqlite3.c third_party/sqlite/src/amalgamation/sqlite3.c
+index 6b4a7899d..b8c7fe414 100644
+--- third_party/sqlite/src/amalgamation/sqlite3.c
++++ third_party/sqlite/src/amalgamation/sqlite3.c
+@@ -14474,7 +14474,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 third_party/sqlite/src/amalgamation_dev/sqlite3.c third_party/sqlite/src/amalgamation_dev/sqlite3.c
+index d30c9b7de..cf75a69d9 100644
+--- third_party/sqlite/src/amalgamation_dev/sqlite3.c
++++ third_party/sqlite/src/amalgamation_dev/sqlite3.c
+@@ -14487,7 +14487,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 third_party/sqlite/src/ext/rtree/rtree.c third_party/sqlite/src/ext/rtree/rtree.c
+index f5b57a5e2..80a2d0ad8 100644
+--- third_party/sqlite/src/ext/rtree/rtree.c
++++ third_party/sqlite/src/ext/rtree/rtree.c
+@@ -450,7 +450,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 third_party/sqlite/src/src/sqliteInt.h third_party/sqlite/src/src/sqliteInt.h
+index 245070d4f..b25164e95 100644
+--- third_party/sqlite/src/src/sqliteInt.h
++++ third_party/sqlite/src/src/sqliteInt.h
+@@ -877,7 +877,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 third_party/webrtc/modules/desktop_capture/differ_block.cc third_party/webrtc/modules/desktop_capture/differ_block.cc
+index 4f0c5430c..54ee0829e 100644
+--- third_party/webrtc/modules/desktop_capture/differ_block.cc
++++ 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 = 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 third_party/webrtc/rtc_base/system/arch.h third_party/webrtc/rtc_base/system/arch.h
+index be2367b85..be4ee4233 100644
+--- third_party/webrtc/rtc_base/system/arch.h
++++ third_party/webrtc/rtc_base/system/arch.h
+@@ -79,6 +79,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 v8/BUILD.gn v8/BUILD.gn
+index f39529a3a..e84fc449e 100644
+--- v8/BUILD.gn
++++ v8/BUILD.gn
+@@ -850,6 +850,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 ui/gl/features.gni ui/gl/features.gni
+index 5fda9b6..3d2dd8b 100644
+--- ui/gl/features.gni
++++ ui/gl/features.gni
+@@ -32,5 +32,6 @@ declare_args() {
+                         (is_mac && use_egl) || is_chromeos_ash || 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")
+ }
+diff --git v8/test/BUILD.gn v8/test/BUILD.gn
+index fb872ad39..45fc585dd 100644
+--- v8/test/BUILD.gn
++++ v8/test/BUILD.gn
+@@ -36,7 +36,7 @@ group("gn_all") {
+       "benchmarks/cpp:gn_all",
+       "cctest:cctest",
+       "cctest:generate-bytecode-expectations",
+-      "unittests:unittests",
++      #"unittests:unittests",
+     ]
+   }
+ }
+@@ -83,7 +83,7 @@
+     "message:v8_message",
+     "mjsunit:v8_mjsunit",
+     "mkgrokdump:mkgrokdump",
+-    "unittests:unittests",
++    #"unittests:unittests",
+     "webkit:v8_webkit",
+   ]
+ 
+@@ -108,7 +108,7 @@
+     "message:v8_message",
+     "mjsunit:v8_mjsunit",
+     "mkgrokdump:mkgrokdump",
+-    "unittests:unittests",
++    #"unittests:unittests",
+   ]
+ 
+   if (v8_enable_webassembly) {
+
+--- sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc	2021-05-25 17:42:20.431219407 +0200
++++ -	2021-05-25 18:33:06.801866145 +0200
diff --git a/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-swiftshader.patch b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-swiftshader.patch
new file mode 100644
index 000000000000..53549d17f5ac
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-swiftshader.patch
@@ -0,0 +1,18 @@
+--- third_party/swiftshader/third_party/llvm-10.0/BUILD.gn
++++ third_party/swiftshader/third_party/llvm-10.0/BUILD.gn
+@@ -574,6 +574,7 @@ swiftshader_llvm_source_set("swiftshader
+     "llvm/lib/MC/MCAsmInfoCOFF.cpp",
+     "llvm/lib/MC/MCAsmInfoDarwin.cpp",
+     "llvm/lib/MC/MCAsmInfoELF.cpp",
++    "llvm/lib/MC/MCAsmInfoXCOFF.cpp",
+     "llvm/lib/MC/MCAsmMacro.cpp",
+     "llvm/lib/MC/MCAsmStreamer.cpp",
+     "llvm/lib/MC/MCAssembler.cpp",
+@@ -629,6 +630,7 @@ swiftshader_llvm_source_set("swiftshader
+     "llvm/lib/MC/MCWinCOFFStreamer.cpp",
+     "llvm/lib/MC/MCWinEH.cpp",
+     "llvm/lib/MC/MCXCOFFStreamer.cpp",
++    "llvm/lib/MC/MCXCOFFObjectTargetWriter.cpp",
+     "llvm/lib/MC/MachObjectWriter.cpp",
+     "llvm/lib/MC/StringTableBuilder.cpp",
+     "llvm/lib/MC/SubtargetFeature.cpp",
diff --git a/srcpkgs/electron13/files/patches/electron-Add-a-script-to-list-patch-targets.patch.patch b/srcpkgs/electron13/files/patches/electron-Add-a-script-to-list-patch-targets.patch.patch
new file mode 100644
index 000000000000..916dba9dc3bc
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/electron-Add-a-script-to-list-patch-targets.patch.patch
@@ -0,0 +1,42 @@
+From ff4122f236b70c272c746d0c336cdbd588d78cd1 Mon Sep 17 00:00:00 2001
+From: Elvis Pranskevichus <elvis@magic.io>
+Date: Thu, 12 Dec 2019 16:12:18 -0500
+Subject: [PATCH] Add a script to list patch targets
+
+---
+ script/list_patch_targets.py | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+ create mode 100755 script/list_patch_targets.py
+
+diff --git a/script/list_patch_targets.py b/script/list_patch_targets.py
+new file mode 100755
+index 000000000..55173bac9
+--- /dev/null
++++ b/script/list_patch_targets.py
+@@ -0,0 +1,23 @@
++#!/usr/bin/env python
++
++import argparse
++import json
++
++
++def parse_args():
++  parser = argparse.ArgumentParser(description='Apply Electron patches')
++  parser.add_argument('config', nargs='+',
++                      type=argparse.FileType('r'),
++                      help='patches\' config(s) in the JSON format')
++  return parser.parse_args()
++
++
++def main():
++  configs = parse_args().config
++  for config_json in configs:
++    for patch_dir, repo in json.load(config_json).iteritems():
++      print(repo)
++
++
++if __name__ == '__main__':
++  main()
+-- 
+2.23.0
+
diff --git a/srcpkgs/electron13/files/patches/electron-Build-fixes.patch.patch b/srcpkgs/electron13/files/patches/electron-Build-fixes.patch.patch
new file mode 100644
index 000000000000..298bfa9bcb2b
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/electron-Build-fixes.patch.patch
@@ -0,0 +1,47 @@
+diff --git a/build/args/release.gn b/build/args/release.gn
+index e5017f6e1..59207b389 100644
+--- a/build/args/release.gn
++++ b/build/args/release.gn
+@@ -1,6 +1,4 @@
+ import("all.gn")
+-is_component_build = false
+-is_official_build = true
+ 
+ # This may be guarded behind is_chrome_branded alongside
+ # proprietary_codecs https://webrtc-review.googlesource.com/c/src/+/36321,
+@@ -8,9 +6,3 @@ is_official_build = true
+ # The initialization of the decoder depends on whether ffmpeg has
+ # been built with H.264 support.
+ rtc_use_h264 = proprietary_codecs
+-
+-# By default, Electron builds ffmpeg with proprietary codecs enabled. In order
+-# to facilitate users who don't want to ship proprietary codecs in ffmpeg, or
+-# who have an LGPL requirement to ship ffmpeg as a dynamically linked library,
+-# we build ffmpeg as a shared library.
+-is_component_ffmpeg = true
+diff --git a/build/npm.gni b/build/npm.gni
+index a1987d095..fb33a14c3 100644
+--- a/build/npm.gni
++++ b/build/npm.gni
+@@ -35,7 +35,6 @@ template("npm_action") {
+     if (!defined(deps)) {
+       deps = []
+     }
+-    deps += [ ":npm_pre_flight_" + target_name ]
+ 
+     script = "//electron/build/npm-run.py"
+     args = [
+diff --git a/patches/node/fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch b/patches/node/fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch
+index 0dc9916be..7eaa46bf5 100644
+--- a/patches/node/fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch
++++ b/patches/node/fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch
+@@ -30,7 +30,7 @@
+ +    # these values being accurate.
+ +    'build_v8_with_gn': 'false',
+ +    'enable_lto%': 'false',
+-+
+++    'openssl_fips': '',
+      'conditions': [
+        ['target_arch=="arm64"', {
+          # Disabled pending https://github.com/nodejs/node/issues/23913.
+
diff --git a/srcpkgs/electron13/files/patches/electron-dont-assume-python-is-python2.patch b/srcpkgs/electron13/files/patches/electron-dont-assume-python-is-python2.patch
new file mode 100644
index 000000000000..fb134748025b
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/electron-dont-assume-python-is-python2.patch
@@ -0,0 +1,17 @@
+--- a/build/zip.py.orig	2020-04-27 17:59:53.499281667 +0200
++++ b/build/zip.py	2020-04-27 17:59:57.655839143 +0200
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python2
+ from __future__ import print_function
+ import os
+ import subprocess
+
+--- a/build/npm-run.py.orig	2020-04-27 17:59:50.829351807 +0200
++++ b/build/npm-run.py	2020-04-27 18:00:02.702373256 +0200
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python2
+ from __future__ import print_function
+ import os
+ import subprocess
diff --git a/srcpkgs/electron13/files/patches/electron-exclude-content-test-patches.patch b/srcpkgs/electron13/files/patches/electron-exclude-content-test-patches.patch
new file mode 100644
index 000000000000..456223644278
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/electron-exclude-content-test-patches.patch
@@ -0,0 +1,10 @@
+--- a/script/apply_all_patches.py	2020-08-22 17:46:41.796707506 +0200
++++ -	2020-08-22 17:47:05.887813512 +0200
+@@ -14,6 +14,7 @@
+   for patch_dir, repo in dirs.items():
+     git.import_patches(repo=repo, patch_data=patch_from_dir(patch_dir),
+       threeway=threeway is not None,
++      exclude=['test/mjsunit/**', 'content/test/**', 'test/cctest/**', 'test/unittests/**', 'third_party/blink/web_tests/**'],
+       committer_name="Electron Scripts", committer_email="scripts@electron")
+ 
+ 
diff --git a/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.cc b/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.cc
new file mode 100644
index 000000000000..2c7aa8efa66f
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.cc
@@ -0,0 +1,148 @@
+// Copyright (c) 2012 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.
+
+#include "base/metrics/histogram_macros.h"
+#include "base/memory/ptr_util.h"
+
+#include "media/audio/openbsd/audio_manager_openbsd.h"
+
+#include "media/audio/audio_device_description.h"
+#include "media/audio/audio_output_dispatcher.h"
+#include "media/audio/sndio/sndio_input.h"
+#include "media/audio/sndio/sndio_output.h"
+#include "media/base/limits.h"
+#include "media/base/media_switches.h"
+
+namespace media {
+
+// Maximum number of output streams that can be open simultaneously.
+static const int kMaxOutputStreams = 4;
+
+// Default sample rate for input and output streams.
+static const int kDefaultSampleRate = 48000;
+
+void AddDefaultDevice(AudioDeviceNames* device_names) {
+  DCHECK(device_names->empty());
+  device_names->push_front(AudioDeviceName::CreateDefault());
+}
+
+bool AudioManagerOpenBSD::HasAudioOutputDevices() {
+  return true;
+}
+
+bool AudioManagerOpenBSD::HasAudioInputDevices() {
+  return true;
+}
+
+void AudioManagerOpenBSD::GetAudioInputDeviceNames(
+    AudioDeviceNames* device_names) {
+  DCHECK(device_names->empty());
+  AddDefaultDevice(device_names);
+}
+
+void AudioManagerOpenBSD::GetAudioOutputDeviceNames(
+    AudioDeviceNames* device_names) {
+  AddDefaultDevice(device_names);
+}
+
+const char* AudioManagerOpenBSD::GetName() {
+  return "SNDIO";
+}
+
+AudioParameters AudioManagerOpenBSD::GetInputStreamParameters(
+    const std::string& device_id) {
+  static const int kDefaultInputBufferSize = 1024;
+
+  int user_buffer_size = GetUserBufferSize();
+  int buffer_size = user_buffer_size ?
+      user_buffer_size : kDefaultInputBufferSize;
+
+  return AudioParameters(
+      AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
+      kDefaultSampleRate, buffer_size);
+}
+
+AudioManagerOpenBSD::AudioManagerOpenBSD(std::unique_ptr<AudioThread> audio_thread,
+                                         AudioLogFactory* audio_log_factory)
+    : AudioManagerBase(std::move(audio_thread),
+                       audio_log_factory) {
+  DLOG(WARNING) << "AudioManagerOpenBSD";
+  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
+}
+
+AudioManagerOpenBSD::~AudioManagerOpenBSD() {
+  Shutdown();
+}
+
+AudioOutputStream* AudioManagerOpenBSD::MakeLinearOutputStream(
+    const AudioParameters& params,
+    const LogCallback& log_callback) {
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
+  return MakeOutputStream(params);
+}
+
+AudioOutputStream* AudioManagerOpenBSD::MakeLowLatencyOutputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+  return MakeOutputStream(params);
+}
+
+AudioInputStream* AudioManagerOpenBSD::MakeLinearInputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
+  return MakeInputStream(params);
+}
+
+AudioInputStream* AudioManagerOpenBSD::MakeLowLatencyInputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+  return MakeInputStream(params);
+}
+
+AudioParameters AudioManagerOpenBSD::GetPreferredOutputStreamParameters(
+    const std::string& output_device_id,
+    const AudioParameters& input_params) {
+  // TODO(tommi): Support |output_device_id|.
+  DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
+  static const int kDefaultOutputBufferSize = 2048;
+
+  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
+  int sample_rate = kDefaultSampleRate;
+  int buffer_size = kDefaultOutputBufferSize;
+  if (input_params.IsValid()) {
+    sample_rate = input_params.sample_rate();
+    channel_layout = input_params.channel_layout();
+    buffer_size = std::min(buffer_size, input_params.frames_per_buffer());
+  }
+
+  int user_buffer_size = GetUserBufferSize();
+  if (user_buffer_size)
+    buffer_size = user_buffer_size;
+
+  return AudioParameters(
+      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
+      sample_rate, buffer_size);
+}
+
+AudioInputStream* AudioManagerOpenBSD::MakeInputStream(
+    const AudioParameters& params) {
+  DLOG(WARNING) << "MakeInputStream";
+  return new SndioAudioInputStream(this,
+             AudioDeviceDescription::kDefaultDeviceId, params);
+}
+
+AudioOutputStream* AudioManagerOpenBSD::MakeOutputStream(
+    const AudioParameters& params) {
+  DLOG(WARNING) << "MakeOutputStream";
+  return new SndioAudioOutputStream(params, this);
+}
+
+}  // namespace media
diff --git a/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.h b/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.h
new file mode 100644
index 000000000000..8c99db966d65
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2012 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 MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
+#define MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
+
+#include <set>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread.h"
+#include "media/audio/audio_manager_base.h"
+
+namespace media {
+
+class MEDIA_EXPORT AudioManagerOpenBSD : public AudioManagerBase {
+ public:
+  AudioManagerOpenBSD(std::unique_ptr<AudioThread> audio_thread,
+                   AudioLogFactory* audio_log_factory);
+  ~AudioManagerOpenBSD() override;
+
+  // Implementation of AudioManager.
+  bool HasAudioOutputDevices() override;
+  bool HasAudioInputDevices() override;
+  void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
+  void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override;
+  AudioParameters GetInputStreamParameters(
+      const std::string& device_id) override;
+  const char* GetName() override;
+
+  // Implementation of AudioManagerBase.
+  AudioOutputStream* MakeLinearOutputStream(
+      const AudioParameters& params,
+      const LogCallback& log_callback) override;
+  AudioOutputStream* MakeLowLatencyOutputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+  AudioInputStream* MakeLinearInputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+  AudioInputStream* MakeLowLatencyInputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+
+ protected:
+  AudioParameters GetPreferredOutputStreamParameters(
+      const std::string& output_device_id,
+      const AudioParameters& input_params) override;
+
+ private:
+  // Called by MakeLinearOutputStream and MakeLowLatencyOutputStream.
+  AudioOutputStream* MakeOutputStream(const AudioParameters& params);
+  AudioInputStream* MakeInputStream(const AudioParameters& params);
+
+  DISALLOW_COPY_AND_ASSIGN(AudioManagerOpenBSD);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
diff --git a/srcpkgs/electron13/files/sndio-files/sndio_input.cc b/srcpkgs/electron13/files/sndio-files/sndio_input.cc
new file mode 100644
index 000000000000..ef5439b49a07
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/sndio_input.cc
@@ -0,0 +1,200 @@
+// Copyright 2013 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.
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/audio/openbsd/audio_manager_openbsd.h"
+#include "media/audio/audio_manager.h"
+#include "media/audio/sndio/sndio_input.h"
+
+namespace media {
+
+static const SampleFormat kSampleFormat = kSampleFormatS16;
+
+void SndioAudioInputStream::OnMoveCallback(void *arg, int delta)
+{
+  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
+
+  self->hw_delay += delta;
+}
+
+void *SndioAudioInputStream::ThreadEntry(void *arg) {
+  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
+
+  self->ThreadLoop();
+  return NULL;
+}
+
+SndioAudioInputStream::SndioAudioInputStream(AudioManagerBase* manager,
+                                             const std::string& device_name,
+                                             const AudioParameters& params)
+    : manager(manager),
+      params(params),
+      audio_bus(AudioBus::Create(params)),
+      state(kClosed) {
+}
+
+SndioAudioInputStream::~SndioAudioInputStream() {
+  if (state != kClosed)
+    Close();
+}
+
+bool SndioAudioInputStream::Open() {
+  struct sio_par par;
+  int sig;
+
+  if (state != kClosed)
+    return false;
+
+  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
+      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
+    LOG(WARNING) << "Unsupported audio format.";
+    return false;
+  }
+
+  sio_initpar(&par);
+  par.rate = params.sample_rate();
+  par.rchan = params.channels();
+  par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
+  par.bps = par.bits / 8;
+  par.sig = sig = par.bits != 8 ? 1 : 0;
+  par.le = SIO_LE_NATIVE;
+  par.appbufsz = params.frames_per_buffer();
+
+  hdl = sio_open(SIO_DEVANY, SIO_REC, 0);
+
+  if (hdl == NULL) {
+    LOG(ERROR) << "Couldn't open audio device.";
+    return false;
+  }
+
+  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
+    LOG(ERROR) << "Couldn't set audio parameters.";
+    goto bad_close;
+  }
+
+  if (par.rate  != (unsigned int)params.sample_rate() ||
+      par.rchan != (unsigned int)params.channels() ||
+      par.bits  != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
+      par.sig   != (unsigned int)sig ||
+      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
+      (par.bits != par.bps * 8)) {
+    LOG(ERROR) << "Unsupported audio parameters.";
+    goto bad_close;
+  }
+  state = kStopped;
+  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
+  sio_onmove(hdl, &OnMoveCallback, this);
+  return true;
+bad_close:
+  sio_close(hdl);
+  return false;
+}
+
+void SndioAudioInputStream::Start(AudioInputCallback* cb) {
+
+  StartAgc();
+
+  state = kRunning;
+  hw_delay = 0;
+  callback = cb;
+  sio_start(hdl);
+  if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
+    LOG(ERROR) << "Failed to create real-time thread for recording.";
+    sio_stop(hdl);
+    state = kStopped;
+  }
+}
+
+void SndioAudioInputStream::Stop() {
+
+  if (state == kStopped)
+    return;
+
+  state = kStopWait;
+  pthread_join(thread, NULL);
+  sio_stop(hdl);
+  state = kStopped;
+
+  StopAgc();
+}
+
+void SndioAudioInputStream::Close() {
+
+  if (state == kClosed)
+    return;
+
+  if (state == kRunning)
+    Stop();
+
+  state = kClosed;
+  delete [] buffer;
+  sio_close(hdl);
+
+  manager->ReleaseInputStream(this);
+}
+
+double SndioAudioInputStream::GetMaxVolume() {
+  // Not supported
+  return 0.0;
+}
+
+void SndioAudioInputStream::SetVolume(double volume) {
+  // Not supported. Do nothing.
+}
+
+double SndioAudioInputStream::GetVolume() {
+  // Not supported.
+  return 0.0;
+}
+
+bool SndioAudioInputStream::IsMuted() {
+  // Not supported.
+  return false;
+}
+
+void SndioAudioInputStream::SetOutputDeviceForAec(
+    const std::string& output_device_id) {
+  // Not supported.
+}
+
+void SndioAudioInputStream::ThreadLoop(void) {
+  size_t todo, n;
+  char *data;
+  unsigned int nframes;
+  double normalized_volume = 0.0;
+
+  nframes = audio_bus->frames();
+
+  while (state == kRunning && !sio_eof(hdl)) {
+
+    GetAgcVolume(&normalized_volume);
+
+    // read one block
+    todo = nframes * params.GetBytesPerFrame(kSampleFormat);
+    data = buffer;
+    while (todo > 0) {
+      n = sio_read(hdl, data, todo);
+      if (n == 0)
+        return;	// unrecoverable I/O error
+      todo -= n;
+      data += n;
+    }
+    hw_delay -= nframes;
+
+    // convert frames count to TimeDelta
+    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
+      params.sample_rate());
+
+    // push into bus
+    audio_bus->FromInterleaved(buffer, nframes, SampleFormatToBytesPerChannel(kSampleFormat));
+
+    // invoke callback
+    callback->OnData(audio_bus.get(), base::TimeTicks::Now() - delay, 1.);
+  }
+}
+
+}  // namespace media
diff --git a/srcpkgs/electron13/files/sndio-files/sndio_input.h b/srcpkgs/electron13/files/sndio-files/sndio_input.h
new file mode 100644
index 000000000000..d868e0469db5
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/sndio_input.h
@@ -0,0 +1,91 @@
+// Copyright 2013 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 MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
+#define MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
+
+#include <stdint.h>
+#include <string>
+#include <sndio.h>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "media/audio/agc_audio_stream.h"
+#include "media/audio/audio_io.h"
+#include "media/audio/audio_device_description.h"
+#include "media/base/audio_parameters.h"
+
+namespace media {
+
+class AudioManagerBase;
+
+// Implementation of AudioOutputStream using sndio(7)
+class SndioAudioInputStream : public AgcAudioStream<AudioInputStream> {
+ public:
+  // Pass this to the constructor if you want to attempt auto-selection
+  // of the audio recording device.
+  static const char kAutoSelectDevice[];
+
+  // Create a PCM Output stream for the SNDIO device identified by
+  // |device_name|. If unsure of what to use for |device_name|, use
+  // |kAutoSelectDevice|.
+  SndioAudioInputStream(AudioManagerBase* audio_manager,
+                     const std::string& device_name,
+                     const AudioParameters& params);
+
+  ~SndioAudioInputStream() override;
+
+  // Implementation of AudioInputStream.
+  bool Open() override;
+  void Start(AudioInputCallback* callback) override;
+  void Stop() override;
+  void Close() override;
+  double GetMaxVolume() override;
+  void SetVolume(double volume) override;
+  double GetVolume() override;
+  bool IsMuted() override;
+  void SetOutputDeviceForAec(const std::string& output_device_id) override;
+
+ private:
+
+  enum StreamState {
+    kClosed,            // Not opened yet
+    kStopped,           // Device opened, but not started yet
+    kRunning,           // Started, device playing
+    kStopWait           // Stopping, waiting for the real-time thread to exit
+  };
+
+  // C-style call-backs
+  static void OnMoveCallback(void *arg, int delta);
+  static void* ThreadEntry(void *arg);
+
+  // Continuously moves data from the device to the consumer
+  void ThreadLoop();
+  // Our creator, the audio manager needs to be notified when we close.
+  AudioManagerBase* manager;
+  // Parameters of the source
+  AudioParameters params;
+  // We store data here for consumer
+  std::unique_ptr<AudioBus> audio_bus;
+  // Call-back that consumes recorded data
+  AudioInputCallback* callback;  // Valid during a recording session.
+  // Handle of the audio device
+  struct sio_hdl* hdl;
+  // Current state of the stream
+  enum StreamState state;
+  // High priority thread running ThreadLoop()
+  pthread_t thread;
+  // Number of frames buffered in the hardware
+  int hw_delay;
+  // Temporary buffer where data is stored sndio-compatible format
+  char* buffer;
+
+  DISALLOW_COPY_AND_ASSIGN(SndioAudioInputStream);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
diff --git a/srcpkgs/electron13/files/sndio-files/sndio_output.cc b/srcpkgs/electron13/files/sndio-files/sndio_output.cc
new file mode 100644
index 000000000000..a6719f9aac8d
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/sndio_output.cc
@@ -0,0 +1,183 @@
+// Copyright (c) 2012 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.
+
+#include "base/logging.h"
+#include "base/time/time.h"
+#include "base/time/default_tick_clock.h"
+#include "media/audio/audio_manager_base.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/audio/sndio/sndio_output.h"
+
+namespace media {
+
+static const SampleFormat kSampleFormat = kSampleFormatS16;
+
+void SndioAudioOutputStream::OnMoveCallback(void *arg, int delta) {
+  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
+
+  self->hw_delay -= delta;
+}
+
+void SndioAudioOutputStream::OnVolCallback(void *arg, unsigned int vol) {
+  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
+
+  self->vol = vol;
+}
+
+void *SndioAudioOutputStream::ThreadEntry(void *arg) {
+  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
+
+  self->ThreadLoop();
+  return NULL;
+}
+
+SndioAudioOutputStream::SndioAudioOutputStream(const AudioParameters& params,
+                                               AudioManagerBase* manager)
+    : manager(manager),
+      params(params),
+      audio_bus(AudioBus::Create(params)),
+      state(kClosed),
+      mutex(PTHREAD_MUTEX_INITIALIZER) {
+}
+
+SndioAudioOutputStream::~SndioAudioOutputStream() {
+  if (state != kClosed)
+    Close();
+}
+
+bool SndioAudioOutputStream::Open() {
+  struct sio_par par;
+  int sig;
+
+  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
+      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
+    LOG(WARNING) << "Unsupported audio format.";
+    return false;
+  }
+  sio_initpar(&par);
+  par.rate = params.sample_rate();
+  par.pchan = params.channels();
+  par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
+  par.bps = par.bits / 8;
+  par.sig = sig = par.bits != 8 ? 1 : 0;
+  par.le = SIO_LE_NATIVE;
+  par.appbufsz = params.frames_per_buffer();
+
+  hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
+  if (hdl == NULL) {
+    LOG(ERROR) << "Couldn't open audio device.";
+    return false;
+  }
+  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
+    LOG(ERROR) << "Couldn't set audio parameters.";
+    goto bad_close;
+  }
+  if (par.rate  != (unsigned int)params.sample_rate() ||
+      par.pchan != (unsigned int)params.channels() ||
+      par.bits  != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
+      par.sig   != (unsigned int)sig ||
+      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
+      (par.bits != par.bps * 8)) {
+    LOG(ERROR) << "Unsupported audio parameters.";
+    goto bad_close;
+  }
+  state = kStopped;
+  volpending = 0;
+  vol = 0;
+  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
+  sio_onmove(hdl, &OnMoveCallback, this);
+  sio_onvol(hdl, &OnVolCallback, this);
+  return true;
+ bad_close:
+  sio_close(hdl);
+  return false;
+}
+
+void SndioAudioOutputStream::Close() {
+  if (state == kClosed)
+    return;
+  if (state == kRunning)
+    Stop();
+  state = kClosed;
+  delete [] buffer;
+  sio_close(hdl);
+  manager->ReleaseOutputStream(this);  // Calls the destructor
+}
+
+void SndioAudioOutputStream::Start(AudioSourceCallback* callback) {
+  state = kRunning;
+  hw_delay = 0;
+  source = callback;
+  sio_start(hdl);
+  if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
+    LOG(ERROR) << "Failed to create real-time thread.";
+    sio_stop(hdl);
+    state = kStopped;
+  }
+}
+
+void SndioAudioOutputStream::Stop() {
+  if (state == kStopped)
+    return;
+  state = kStopWait;
+  pthread_join(thread, NULL);
+  sio_stop(hdl);
+  state = kStopped;
+}
+
+void SndioAudioOutputStream::SetVolume(double v) {
+  pthread_mutex_lock(&mutex);
+  vol = v * SIO_MAXVOL;
+  volpending = 1;
+  pthread_mutex_unlock(&mutex);
+}
+
+void SndioAudioOutputStream::GetVolume(double* v) {
+  pthread_mutex_lock(&mutex);
+  *v = vol * (1. / SIO_MAXVOL);
+  pthread_mutex_unlock(&mutex);
+}
+
+// This stream is always used with sub second buffer sizes, where it's
+// sufficient to simply always flush upon Start().
+void SndioAudioOutputStream::Flush() {}
+
+void SndioAudioOutputStream::ThreadLoop(void) {
+  int avail, count, result;
+
+  while (state == kRunning) {
+    // Update volume if needed
+    pthread_mutex_lock(&mutex);
+    if (volpending) {
+      volpending = 0;
+      sio_setvol(hdl, vol);
+    }
+    pthread_mutex_unlock(&mutex);
+
+    // Get data to play
+    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
+	params.sample_rate());
+    count = source->OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get());
+    audio_bus->ToInterleaved(count, SampleFormatToBytesPerChannel(kSampleFormat), buffer);
+    if (count == 0) {
+      // We have to submit something to the device
+      count = audio_bus->frames();
+      memset(buffer, 0, count * params.GetBytesPerFrame(kSampleFormat));
+      LOG(WARNING) << "No data to play, running empty cycle.";
+    }
+
+    // Submit data to the device
+    avail = count * params.GetBytesPerFrame(kSampleFormat);
+    result = sio_write(hdl, buffer, avail);
+    if (result == 0) {
+      LOG(WARNING) << "Audio device disconnected.";
+      break;
+    }
+
+    // Update hardware pointer
+    hw_delay += count;
+  }
+}
+
+}  // namespace media
diff --git a/srcpkgs/electron13/files/sndio-files/sndio_output.h b/srcpkgs/electron13/files/sndio-files/sndio_output.h
new file mode 100644
index 000000000000..ead220ca96e7
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/sndio_output.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2012 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 MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
+#define MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
+
+#include <pthread.h>
+#include <sndio.h>
+
+#include "base/time/tick_clock.h"
+#include "base/time/time.h"
+#include "media/audio/audio_io.h"
+
+namespace media {
+
+class AudioManagerBase;
+
+// Implementation of AudioOutputStream using sndio(7)
+class SndioAudioOutputStream : public AudioOutputStream {
+ public:
+  // The manager is creating this object
+  SndioAudioOutputStream(const AudioParameters& params,
+                         AudioManagerBase* manager);
+  virtual ~SndioAudioOutputStream();
+
+  // Implementation of AudioOutputStream.
+  bool Open() override;
+  void Close() override;
+  void Start(AudioSourceCallback* callback) override;
+  void Stop() override;
+  void SetVolume(double volume) override;
+  void GetVolume(double* volume) override;
+  void Flush() override;
+
+  friend void sndio_onmove(void *arg, int delta);
+  friend void sndio_onvol(void *arg, unsigned int vol);
+  friend void *sndio_threadstart(void *arg);
+
+ private:
+  enum StreamState {
+    kClosed,            // Not opened yet
+    kStopped,           // Device opened, but not started yet
+    kRunning,           // Started, device playing
+    kStopWait           // Stopping, waiting for the real-time thread to exit
+  };
+
+  // C-style call-backs
+  static void OnMoveCallback(void *arg, int delta);
+  static void OnVolCallback(void *arg, unsigned int vol);
+  static void* ThreadEntry(void *arg);
+
+  // Continuously moves data from the producer to the device
+  void ThreadLoop(void);
+
+  // Our creator, the audio manager needs to be notified when we close.
+  AudioManagerBase* manager;
+  // Parameters of the source
+  AudioParameters params;
+  // Source stores data here
+  std::unique_ptr<AudioBus> audio_bus;
+  // Call-back that produces data to play
+  AudioSourceCallback* source;
+  // Handle of the audio device
+  struct sio_hdl* hdl;
+  // Current state of the stream
+  enum StreamState state;
+  // High priority thread running ThreadLoop()
+  pthread_t thread;
+  // Protects vol, volpending and hw_delay
+  pthread_mutex_t mutex;
+  // Current volume in the 0..SIO_MAXVOL range
+  int vol;
+  // Set to 1 if volumes must be refreshed in the realtime thread
+  int volpending;
+  // Number of frames buffered in the hardware
+  int hw_delay;
+  // Temporary buffer where data is stored sndio-compatible format
+  char* buffer;
+
+  DISALLOW_COPY_AND_ASSIGN(SndioAudioOutputStream);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
diff --git a/srcpkgs/electron13/files/sndio-patches/media_audio_linux_audio_manager_linux.cc.patch b/srcpkgs/electron13/files/sndio-patches/media_audio_linux_audio_manager_linux.cc.patch
new file mode 100644
index 000000000000..cf8e81b11d67
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-patches/media_audio_linux_audio_manager_linux.cc.patch
@@ -0,0 +1,43 @@
+diff --git a/chromium/media/audio/linux/audio_manager_linux.cc b/chromium/media/audio/linux/audio_manager_linux.cc
+index 5d703549372..9e60b40c749 100644
+--- media/audio/linux/audio_manager_linux.cc
++++ media/audio/linux/audio_manager_linux.cc
+@@ -20,6 +20,10 @@
+ #include "media/audio/pulse/audio_manager_pulse.h"
+ #include "media/audio/pulse/pulse_util.h"
+ #endif
++#if defined(USE_SNDIO)
++#include <sndio.h>
++#include "media/audio/openbsd/audio_manager_openbsd.h"
++#endif
+ 
+ namespace media {
+ 
+@@ -27,7 +31,8 @@ enum LinuxAudioIO {
+   kPulse,
+   kAlsa,
+   kCras,
+-  kAudioIOMax = kCras  // Must always be equal to largest logged entry.
++  kSndio,
++  kAudioIOMax = kSndio  // Must always be equal to largest logged entry.
+ };
+ 
+ std::unique_ptr<media::AudioManager> CreateAudioManager(
+@@ -41,6 +46,17 @@ std::unique_ptr<media::AudioManager> CreateAudioManager(
+   }
+ #endif
+ 
++#if defined(USE_SNDIO)
++  struct sio_hdl * hdl = NULL;
++  if ((hdl=sio_open(SIO_DEVANY, SIO_PLAY, 1)) != NULL) {
++    sio_close(hdl);
++    UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kSndio, kAudioIOMax +1);
++    return std::make_unique<AudioManagerOpenBSD>(std::move(audio_thread),
++                                               audio_log_factory);
++  }
++  DVLOG(1) << "Sndio is not available on the OS";
++#endif
++
+ #if defined(USE_PULSEAUDIO)
+   pa_threaded_mainloop* pa_mainloop = nullptr;
+   pa_context* pa_context = nullptr;
diff --git a/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_BUILD.gn.patch b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_BUILD.gn.patch
new file mode 100644
index 000000000000..ec6040026688
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_BUILD.gn.patch
@@ -0,0 +1,12 @@
+--- media/BUILD.gn	2020-03-24 10:16:30.000000000 +0100
++++ -	2020-04-06 14:32:27.960817513 +0200
+@@ -65,6 +65,9 @@
+   if (use_cras) {
+     defines += [ "USE_CRAS" ]
+   }
++  if (use_sndio) {
++    defines += [ "USE_SNDIO" ]
++  }
+ }
+ 
+ # Internal grouping of the configs necessary to support sub-folders having their
diff --git a/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_audio_BUILD.gn.patch b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_audio_BUILD.gn.patch
new file mode 100644
index 000000000000..c856de0bf2ec
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_audio_BUILD.gn.patch
@@ -0,0 +1,23 @@
+--- media/audio/BUILD.gn	2020-03-24 10:16:30.000000000 +0100
++++ -	2020-04-06 14:31:28.871450217 +0200
+@@ -232,9 +232,19 @@
+     deps += [ "//media/base/android:media_jni_headers" ]
+   }
+ 
+-  if (is_linux) {
++  if (is_linux) {
+     sources += [ "linux/audio_manager_linux.cc" ]
+   }
++  if (use_sndio) {
++    libs += [ "sndio" ]
++    sources += [
++      "openbsd/audio_manager_openbsd.cc",
++      "sndio/sndio_input.cc",
++      "sndio/sndio_input.h",
++      "sndio/sndio_output.cc",
++      "sndio/sndio_output.h"
++   ]
++ }
+ 
+   if (use_alsa) {
+     libs += [ "asound" ]
diff --git a/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_media__options.gni.patch b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_media__options.gni.patch
new file mode 100644
index 000000000000..14807d8e1d36
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_media__options.gni.patch
@@ -0,0 +1,12 @@
+--- media/media_options.gni	2020-03-24 10:16:30.000000000 +0100
++++ -	2020-04-06 14:29:22.958630783 +0200
+@@ -114,6 +114,9 @@
+   # Enables runtime selection of ALSA library for audio.
+   use_alsa = false
+ 
++  # Enables runtime selection of sndio library for audio.
++  use_sndio = false
++
+   # Alsa should be used on non-Android, non-Mac POSIX systems.
+   # Alsa should be used on desktop Chromecast and audio-only Chromecast builds.
+   if (is_posix && !is_android && !is_mac &&
diff --git a/srcpkgs/electron13/template b/srcpkgs/electron13/template
new file mode 100644
index 000000000000..9d39382f377a
--- /dev/null
+++ b/srcpkgs/electron13/template
@@ -0,0 +1,385 @@
+# Template file for 'electron13'
+pkgname=electron13
+version=13.0.0
+_nodever=14.16.0
+_chromiumver=91.0.4472.69
+revision=1
+archs="x86_64* i686* aarch64* ppc64le*"
+build_wrksrc="src"
+create_wrksrc=yes
+hostmakedepends="$(vopt_if clang clang) python pkgconf perl gperf bison ninja nodejs hwids
+ libwebp-devel freetype-devel harfbuzz-devel libpng-devel nss-devel which git libevent-devel
+ pciutils-devel libatomic-devel ffmpeg-devel libxml2-devel libglib-devel yarn openjdk libxslt-devel
+ opus-devel libXcursor-devel libXcomposite-devel libXtst-devel libXrandr-devel libXScrnSaver-devel
+ alsa-lib-devel re2-devel snappy-devel mit-krb5-devel $(vopt_if pulseaudio pulseaudio-devel)
+ $(vopt_if sndio sndio-devel) jq"
+makedepends="libpng-devel gtk+-devel gtk+3-devel nss-devel pciutils-devel
+ libXi-devel libgcrypt-devel libgnome-keyring-devel cups-devel elfutils-devel
+ libXcomposite-devel speech-dispatcher-devel libXrandr-devel mit-krb5-devel
+ libXScrnSaver-devel alsa-lib-devel snappy-devel libdrm-devel
+ libxml2-devel libxslt-devel $(vopt_if pulseaudio pulseaudio-devel) libexif-devel
+ libXcursor-devel libflac-devel speex-devel libmtp-devel libwebp-devel
+ libjpeg-turbo-devel libevent-devel json-c-devel harfbuzz-devel
+ minizip-devel jsoncpp-devel zlib-devel libcap-devel libXdamage-devel
+ re2-devel fontconfig-devel freetype-devel opus-devel libatomic-devel
+ $(vopt_if sndio sndio-devel) ffmpeg-devel libva-devel libuv-devel c-ares-devel libnotify-devel
+ $(vopt_if pipewire pipewire-devel) wayland-devel libcurl-devel"
+short_desc="Cross platform application development framework based on web technologies"
+maintainer="John <me@johnnynator.dev>"
+license="BSD-3-Clause"
+homepage="https://electronjs.org"
+distfiles="https://github.com/electron/electron/archive/v$version.tar.gz>electron-${version}.tar.gz
+ https://commondatastorage.googleapis.com/chromium-browser-official/chromium-$_chromiumver.tar.xz
+ https://github.com/nodejs/node/archive/v$_nodever.tar.gz>node-$_nodever.tar.gz"
+checksum="c807da851b9d952dffad9466fb35d8c50801fecdf07d98986ca32d19dbc203d3
+ 1f6843c636f4adee6b06c301193810cce103ee3e4582d4cbc31c915efc3d0c7b
+ bcdf869b0743405515ee897b1047b5e851a717e426b4974d26537c9b10dfd53a"
+
+case "$XBPS_TARGET_MACHINE" in
+	ppc64*-musl) makedepends+=" libucontext-devel" ;;
+esac
+
+no_generic_pkgconfig_link=yes
+lib32disabled=yes
+nopie=yes  # contains tools that are not PIE, enables PIE itself
+
+build_options="pulseaudio sndio clang pipewire"
+build_options_default="pulseaudio clang pipewire"
+
+if [ "$build_option_clang" ]; then
+	nocross="No proper setup for using clang as cross compiler in void yet"
+elif [ "${XBPS_TARGET_MACHINE%%-musl}" = "aarch64" ]; then
+	broken="Falls apart at runtime when compiled with gcc"
+fi
+
+_buildtype=Release
+_is_debug=false
+
+CFLAGS="-Wno-unknown-warning-option -fPIC"
+CXXFLAGS="-Wno-unknown-warning-option -fPIC"
+
+_apply_patch() {
+	local args="$1" pname="$(basename $2)"
+
+	if [ ! -f ".${pname}_done" ]; then
+		msg_normal "$pkgver: patching: ${pname}.\n"
+		patch -N $args -i $2
+		touch .${pname}_done
+	fi
+}
+
+_get_chromium_arch() {
+	case "$1" in
+		x86_64*) echo x64 ;;
+		i686*) echo x86 ;;
+		arm*) echo arm ;;
+		aarch64*) echo arm64 ;;
+		ppc64*) echo ppc64 ;;
+		ppc*) echo ppc ;;
+		mipsel*) echo mipsel ;;
+		mips*) echo mips ;;
+		*) msg_error "$pkgver: cannot be compiled for ${XBPS_TARGET_MACHINE}.\n" ;;
+	esac
+}
+
+post_extract() {
+	ln -s chromium-$_chromiumver src
+	mkdir -p src/third_party/
+	ln -s ../../node-$_nodever src/third_party/electron_node
+	ln -s ../electron-${version} src/electron
+
+}
+post_patch() {
+	cd $wrksrc
+	for x in $FILESDIR/patches/*; do
+		case "${x##*/}" in
+			electron*.patch)
+				cd src/electron
+				_apply_patch -p1 "$x"
+				cd "$wrksrc";;
+		esac
+	done
+
+	# Sigh, electron uses git am...
+	if [ ! -f ".electron_patches_done" ]; then
+	mv src/electron/patches/config.json config.json.old
+	jq 'del(."src/electron/patches/Mantle", ."src/electron/patches/ReactiveObjC",
+		."src/electron/patches/squirrel.mac", ."src/electron/patches/nan")' \
+		config.json.old > src/electron/patches/config.json
+	
+	python2 src/electron/script/list_patch_targets.py src/electron/patches/config.json | while read -r repopath; do
+		cd "$wrksrc"/"$repopath"
+		git init -q
+		git config "gc.auto" 0
+		if [ "$repopath" != "src" ]; then
+			echo "/${repopath#src/}" >> "$wrksrc/$build_wrksrc/.gitignore"
+		fi
+		git add .
+		git -c 'user.name=Electron build' -c 'user.email=electron@ebuild' \
+			commit -q -m "." || true
+	done
+	cd $wrksrc
+	python2 src/electron/script/apply_all_patches.py src/electron/patches/config.json
+	touch .electron_patches_done
+	fi
+
+	for x in $FILESDIR/patches/*; do
+		case "${x##*/}" in
+			chromium*.patch)
+				cd src
+				_apply_patch -p0 "$x"
+				cd "$wrksrc";;
+		esac
+	done
+
+	if [ "$XBPS_TARGET_LIBC" = "musl" ]; then
+	for x in $FILESDIR/musl-patches/*; do
+		case "${x##*/}" in
+			chromium*.patch)
+				cd src
+				_apply_patch -p0 "$x"
+				cd "$wrksrc";;
+			electron*.patch)
+				cd src/electron
+				_apply_patch -p1 "$x"
+				cd "$wrksrc";;
+		esac
+	done
+	fi
+	if [ "$build_option_sndio" ]; then
+		mkdir -p ${wrksrc}/${build_wrksrc}/media/audio/{sndio,openbsd}
+		cp ${FILESDIR}/sndio-files/sndio_*put.* \
+			${wrksrc}/${build_wrksrc}/media/audio/sndio
+		cp ${FILESDIR}/sndio-files/audio_manager_openbsd.* \
+			${wrksrc}/${build_wrksrc}/media/audio/openbsd
+		for f in "${FILESDIR}"/sndio-patches/*.patch; do
+			cd src
+			_apply_patch -p0 "$f"
+			cd "$wrksrc"
+		done
+	fi
+}
+
+pre_configure() {
+	cd "$wrksrc/$build_wrksrc"
+
+	# https://groups.google.com/a/chromium.org/d/topic/chromium-packagers/9JX1N2nf4PU/discussion
+	touch chrome/test/data/webui/i18n_process_css_test.html
+	# Use the file at run time instead of effectively compiling it in
+	sed 's|//third_party/usb_ids/usb.ids|/usr/share/hwdata/usb.ids|g' \
+		-i services/device/public/cpp/usb/BUILD.gn
+
+	mkdir -p third_party/node/linux/node-linux-x64/bin
+	ln -s /usr/bin/node third_party/node/linux/node-linux-x64/bin/
+
+	# compile gn early, so it can be used to generate gni stuff
+	msg_normal "Bootstrapping GN\n"
+	CC="${CC_FOR_BUILD:-$CC}" CXX="${CXX_FOR_BUILD:-$CXX}" LD="${LD_FOR_BUILD:-$LD}" \
+	CFLAGS="${CFLAGS_FOR_BUILD:-$CFLAGS}" CXXFLAGS="${CXXFLAGS_FOR_BUILD:-$CXXFLAGS}" \
+	LDFLAGS="${XBPS_LDFLAGS}" \
+		python2 tools/gn/bootstrap/bootstrap.py -s -v --skip-generate-buildfiles
+
+	# we need to generate ppc64 stuff for libvpx as it's not shipped
+	# this has to be done before unbundling, but after gn is built
+	# comment out if we switch back to system libvpx again later
+	case "$XBPS_TARGET_MACHINE" in
+		ppc64*)
+			pushd third_party/libvpx
+			mkdir -p source/config/linux/ppc64
+			# need PATH to find gn
+			PATH="${wrksrc}/${build_wrksrc}/out/Release:$PATH" \
+				./generate_gni.sh || \
+					msg_error "failed to generate libvpx gni"
+			popd
+			;;
+	esac
+
+	# reusable system library settings
+	local use_system="
+		ffmpeg
+		flac
+		fontconfig
+		freetype
+		harfbuzz-ng
+		libdrm
+		libevent
+		libjpeg
+		libpng
+		libwebp
+		libxml
+		libxslt
+		opus
+		re2
+		snappy
+		"
+	for _lib in $use_system libjpeg_turbo; do
+		msg_normal "Removing buildscripts for system provided $_lib\n"
+		find -type f -path "*third_party/$_lib/*" \
+			\! -path "*third_party/$_lib/chromium/*" \
+			\! -path "*third_party/$_lib/google/*" \
+			\! -path './base/third_party/icu/*' \
+			\! -path './third_party/pdfium/third_party/freetype/include/pstables.h' \
+			\! -path './third_party/harfbuzz-ng/utils/hb_scoped.h' \
+			\! -regex '.*\.\(gn\|gni\|isolate\|py\)' \
+			-delete
+	done
+
+
+	msg_normal "Replacing gn files\n"
+	python2 build/linux/unbundle/replace_gn_files.py --system-libraries \
+		$use_system
+	third_party/libaddressinput/chromium/tools/update-strings.py
+}
+
+do_configure() {
+	local target_arch="$(_get_chromium_arch ${XBPS_TARGET_MACHINE})"
+	local host_arch="$(_get_chromium_arch ${XBPS_MACHINE})"
+	# the build system will set march for use, adding it to cflags will break builds
+	export CXXFLAGS=$( shopt -s extglob; echo ${CXXFLAGS/-march=*([^ ])} )
+	export CFLAGS=$( shopt -s extglob; echo ${CFLAGS/-march=*([^ ])} )
+	export CFLAGS=${CFLAGS/-g/}
+	export CXXFLAGS=${CXXFLAGS/-g/}
+	local conf=()
+	cd third_party/electron_node
+	if [ "$CROSS_BUILD" ]; then
+		conf_args=" --dest-cpu=${target_arch} --cross-compiling"
+	fi
+	./configure --prefix=/usr \
+		--shared-zlib \
+		--shared-libuv \
+		--shared-openssl \
+		--shared-cares \
+		--openssl-use-def-ca-store \
+		--without-npm \
+		--without-dtrace \
+		--without-bundled-v8 \
+		${conf_args}
+
+	cd "$wrksrc/$build_wrksrc"/electron
+	yarn install
+	cd "$wrksrc/$build_wrksrc"
+
+	if [ "$build_option_clang" ]; then
+		export CC=clang
+		export CXX=clang++
+		export HOST_CC=clang
+		export HOST_CXX=clang++
+	else
+		export CXXFLAGS="$CXXFLAGS -fpermissive"
+		export BUILD_CXXFLAGS="$BUILD_CXXFLAGS -fpermissive"
+		export BUILD_AR="$AR_host"
+		export BUILD_NM="$NM_host"
+	fi
+
+	# Google API keys (see http://www.chromium.org/developers/how-tos/api-keys)
+	# Note: These are for Void Linux use ONLY.
+	conf+=(
+		'google_api_key="AIzaSyA9gWazKaHaNIPPg2hrMj6_ZSG8AFmq738"'
+		'google_default_client_id="126659149423-hoo6ickbk3p1u2qjsdsp0ddciurfvb4t.apps.googleusercontent.com"'
+		'google_default_client_secret="_ozIx2D-DKm_se_2NPwV4l5b"'
+	)
+
+	conf+=(
+		'blink_symbol_level=0'
+		'clang_use_chrome_plugins=false'
+		'custom_toolchain="//build/toolchain/linux/unbundle:default"'
+	)
+	if [ "$CROSS_BUILD" ]; then
+		conf+=(
+			'host_toolchain="//build/toolchain/linux/unbundle:host"'
+			'v8_snapshot_toolchain="//build/toolchain/linux/unbundle:host"'
+			"host_pkg_config=\"$PKG_CONFIG_FOR_BUILD\""
+			"pkg_config=\"$PKG_CONFIG\""
+		)
+	else
+		conf+=(
+			'host_toolchain="//build/toolchain/linux/unbundle:default"'
+			'v8_snapshot_toolchain="//build/toolchain/linux/unbundle:default"'
+		)
+	fi
+	if [ "$build_option_sndio" ]; then
+		conf+=(
+			'use_sndio=true'
+		)
+	fi
+	if [ -n "$XBPS_DEBUG_PKGS" ]; then
+		conf+=('symbol_level=1')
+	else
+		conf+=('symbol_level=0')
+	fi
+	conf+=(
+		'enable_hangout_services_extension=true'
+		'enable_nacl_nonsfi=false'
+		'enable_nacl=false'
+		'enable_precompiled_headers=false'
+		'fatal_linker_warnings=false'
+		'ffmpeg_branding="Chrome"'
+		'fieldtrial_testing_like_official_build=true'
+		'gold_path="/usr/bin/ld.gold"'
+		'icu_use_data_file=true'
+		"is_clang=$(vopt_if clang true false)"
+		'is_component_build=false'
+		"is_debug=$_is_debug"
+		'proprietary_codecs=true'
+		'treat_warnings_as_errors=false'
+		'use_allocator_shim=false'
+		'use_allocator="none"'
+		'use_cups=true'
+		'use_custom_libcxx=false'
+		'use_gnome_keyring=false'
+		'use_gold=false'
+		'use_lld=false'
+		'use_system_libwayland=true'
+		"use_pulseaudio=$(vopt_if pulseaudio 'true' 'false')"
+		"rtc_use_pipewire=$(vopt_if pipewire true false)"
+		'rtc_pipewire_version="0.3"'
+		'use_sysroot=false'
+		'use_system_harfbuzz=true'
+		"target_cpu=\"$target_arch\""
+		"host_cpu=\"$host_arch\""
+		'import("//electron/build/args/release.gn")'
+	)
+
+	msg_normal "Configuring build\n"
+	out/Release/gn gen out/$_buildtype --args="${conf[*]}"
+}
+
+do_build() {
+	export CXXFLAGS=$( shopt -s extglob; echo ${CXXFLAGS/-march=*([^ ])} )
+	export CFLAGS=$( shopt -s extglob; echo ${CFLAGS/-march=*([^ ])} )
+	export CFLAGS=${CFLAGS/-g/}
+	export CXXFLAGS=${CXXFLAGS/-g/}
+	if [ "$build_option_clang" ]; then
+		export CC=clang
+		export CXX=clang++
+		export HOST_CC=clang
+		export HOST_CXX=clang++
+	else
+		export BUILD_CXXFLAGS="$BUILD_CXXFLAGS -fpermissive"
+		export CXXFLAGS="$CXXFLAGS -fpermissive"
+		export BUILD_AR="$AR_host"
+		export BUILD_NM="$NM_host"
+	fi
+	msg_normal "Ninja turtles GO!\n"
+	ninja ${makejobs} -C out/$_buildtype electron third_party/electron_node:headers
+	# finish rest of the build
+	strip -s out/$_buildtype/electron
+	ninja ${makejobs} -C out/$_buildtype electron_dist_zip
+}
+
+do_install() {
+	vmkdir /usr/lib/$pkgname
+	vmkdir /usr/include/$pkgname
+	bsdtar -xf out/$_buildtype/dist.zip -C "$DESTDIR/usr/lib/$pkgname"
+
+	chmod u+s "$DESTDIR/usr/lib/$pkgname/chrome-sandbox"
+
+	cp out/$_buildtype/gen/node_headers.tar.gz "$DESTDIR"/usr/include/$pkgname
+
+	vlicense ${wrksrc}/src/LICENSE chromium.LICENSE
+	vlicense ${wrksrc}/src/electron/LICENSE electron.LICENSE
+	vlicense ${wrksrc}/src/third_party/electron_node/LICENSE node.LICENSE
+
+	vmkdir /usr/bin
+	ln -s ../lib/$pkgname/electron "$DESTDIR"/usr/bin/$pkgname
+}
diff --git a/srcpkgs/electron13/update b/srcpkgs/electron13/update
new file mode 100644
index 000000000000..3af8e58b5358
--- /dev/null
+++ b/srcpkgs/electron13/update
@@ -0,0 +1,2 @@
+site=https://www.electronjs.org/releases/stable?version=${version%%.*}
+pattern='tag/v\K[\d\.]+(?=")'

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PR PATCH] [Updated] [WiP] New package: electron13-13.0.0
  2021-05-26 19:41 [PR PATCH] [WiP] New package: electron13-13.0.0 Johnnynator
@ 2021-08-29  0:24 ` Johnnynator
  2021-08-29  0:26 ` [PR PATCH] [Updated] electron13-13.2.2 Johnnynator
  2021-08-29 15:59 ` [PR PATCH] [Merged]: electron13-13.2.2 Johnnynator
  2 siblings, 0 replies; 4+ messages in thread
From: Johnnynator @ 2021-08-29  0:24 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 1771 bytes --]

There is an updated pull request by Johnnynator against master on the void-packages repository

https://github.com/Johnnynator/void-packages electron13
https://github.com/void-linux/void-packages/pull/31136

[WiP] New package: electron13-13.0.0
<!-- Mark items with [x] where applicable -->

#### General
- [ ] This is a new package and it conforms to the [quality requirements](https://github.com/void-linux/void-packages/blob/master/Manual.md#quality-requirements)

#### Have the results of the proposed changes been tested?
- [ ] I use the packages affected by the proposed changes on a regular basis and confirm this PR works for me
- [ ] I generally don't use the affected packages but briefly tested this PR

- This doesn't compile yet on musl, they move a lot of dns stuff from generic posix to a linux specific file, that ofc only works for glibc.

[ci skip]

<!--
If GitHub CI cannot be used to validate the build result (for example, if the
build is likely to take several hours), make sure to
[skip CI](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#continuous-integration).
When skipping CI, uncomment and fill out the following section.
Note: for builds that are likely to complete in less than 2 hours, it is not
acceptable to skip CI.
-->
<!-- 
#### Does it build and run successfully? 
(Please choose at least one native build and, if supported, at least one cross build. More are better.)
- [ ] I built this PR locally for my native architecture, (ARCH-LIBC)
- [ ] I built this PR locally for these architectures (if supported. mark crossbuilds):
  - [ ] aarch64-musl
  - [ ] armv7l
  - [ ] armv6l-musl
-->


A patch file from https://github.com/void-linux/void-packages/pull/31136.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-electron13-31136.patch --]
[-- Type: text/x-diff, Size: 294714 bytes --]

From dd21a739a7822b0e9a32a3a7d037eee6a1b5c8e6 Mon Sep 17 00:00:00 2001
From: John <me@johnnynator.dev>
Date: Wed, 26 May 2021 21:38:32 +0200
Subject: [PATCH 1/3] New package: electron13-13.2.2

---
 .../chromium-default-pthread-stacksize.patch  |   29 +
 .../musl-patches/chromium-musl-crashpad.patch |   23 +
 .../musl-patches/chromium-musl-dns.patch      |   32 +
 .../musl-patches/chromium-musl-fixes.patch    |  212 +
 .../musl-patches/chromium-musl-hacks.patch    |   34 +
 .../musl-patches/chromium-musl-libc++.patch   |   55 +
 .../musl-patches/chromium-musl-sandbox.patch  |   92 +
 .../musl-patches/chromium-musl-sync.patch     |   30 +
 .../chromium-musl-xxx-ppc64le.patch           |  190 +
 .../musl-patches/chromium-no-mallinfo.patch   |   54 +
 .../musl-patches/chromium-resolver.patch      |   38 +
 .../patches/chromium-browser-size_t.patch     |   10 +
 .../files/patches/chromium-libc_malloc.patch  |   26 +
 ...-v8-monotonic-pthread-cont_timedwait.patch |   24 +
 .../files/patches/chromium-no-execinfo.patch  |   72 +
 .../patches/chromium-no-getcontext.patch      |   27 +
 .../chromium-revert-drop-of-system-java.patch |   15 +
 .../patches/chromium-sandbox-membarrier.patch |   10 +
 .../chromium-sandbox-sched_getparam.patch     |   20 +
 .../files/patches/chromium-sndio.patch        |  886 ++++
 .../patches/chromium-system-nodejs.patch      |   20 +
 .../patches/chromium-webrtc-include.patch     |   10 +
 .../files/patches/chromium-webrtc-r0.patch    |   33 +
 .../patches/chromium-webrtc-size_t.patch      |   10 +
 .../patches/chromium-xxx-ppc64le-libvpx.patch |   72 +
 .../chromium-xxx-ppc64le-support.patch        | 3707 +++++++++++++++++
 .../chromium-xxx-ppc64le-swiftshader.patch    |   18 +
 ...a-script-to-list-patch-targets.patch.patch |   42 +
 .../patches/electron-Build-fixes.patch.patch  |   47 +
 ...ectron-dont-assume-python-is-python2.patch |   17 +
 ...lectron-exclude-content-test-patches.patch |   10 +
 .../sndio-files/audio_manager_openbsd.cc      |  148 +
 .../files/sndio-files/audio_manager_openbsd.h |   65 +
 .../files/sndio-files/sndio_input.cc          |  200 +
 .../files/sndio-files/sndio_input.h           |   91 +
 .../files/sndio-files/sndio_output.cc         |  183 +
 .../files/sndio-files/sndio_output.h          |   86 +
 ...a_audio_linux_audio_manager_linux.cc.patch |   43 +
 ...src_3rdparty_chromium_media_BUILD.gn.patch |   12 +
 ...dparty_chromium_media_audio_BUILD.gn.patch |   23 +
 ...ty_chromium_media_media__options.gni.patch |   12 +
 srcpkgs/electron13/template                   |  377 ++
 srcpkgs/electron13/update                     |    2 +
 43 files changed, 7107 insertions(+)
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-default-pthread-stacksize.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-crashpad.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-dns.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-fixes.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-hacks.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-libc++.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-sandbox.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-sync.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-xxx-ppc64le.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-no-mallinfo.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-resolver.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-browser-size_t.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-libc_malloc.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-musl-v8-monotonic-pthread-cont_timedwait.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-no-execinfo.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-no-getcontext.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-revert-drop-of-system-java.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-sandbox-membarrier.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-sandbox-sched_getparam.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-sndio.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-system-nodejs.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-webrtc-include.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-webrtc-r0.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-webrtc-size_t.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-libvpx.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-support.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-swiftshader.patch
 create mode 100644 srcpkgs/electron13/files/patches/electron-Add-a-script-to-list-patch-targets.patch.patch
 create mode 100644 srcpkgs/electron13/files/patches/electron-Build-fixes.patch.patch
 create mode 100644 srcpkgs/electron13/files/patches/electron-dont-assume-python-is-python2.patch
 create mode 100644 srcpkgs/electron13/files/patches/electron-exclude-content-test-patches.patch
 create mode 100644 srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.cc
 create mode 100644 srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.h
 create mode 100644 srcpkgs/electron13/files/sndio-files/sndio_input.cc
 create mode 100644 srcpkgs/electron13/files/sndio-files/sndio_input.h
 create mode 100644 srcpkgs/electron13/files/sndio-files/sndio_output.cc
 create mode 100644 srcpkgs/electron13/files/sndio-files/sndio_output.h
 create mode 100644 srcpkgs/electron13/files/sndio-patches/media_audio_linux_audio_manager_linux.cc.patch
 create mode 100644 srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_BUILD.gn.patch
 create mode 100644 srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_audio_BUILD.gn.patch
 create mode 100644 srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_media__options.gni.patch
 create mode 100644 srcpkgs/electron13/template
 create mode 100644 srcpkgs/electron13/update

diff --git a/srcpkgs/electron13/files/musl-patches/chromium-default-pthread-stacksize.patch b/srcpkgs/electron13/files/musl-patches/chromium-default-pthread-stacksize.patch
new file mode 100644
index 000000000000..16e4d21e6ed8
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-default-pthread-stacksize.patch
@@ -0,0 +1,29 @@
+--- base/threading/platform_thread_linux.cc.orig
++++ base/threading/platform_thread_linux.cc
+@@ -99 +99,2 @@ size_t GetDefaultThreadStackSize(const p
+-  return 0;
++  // use 8mb like glibc to avoid running out of space
++  return (1 << 23);
+--- chrome/app/shutdown_signal_handlers_posix.cc.orig
++++ chrome/app/shutdown_signal_handlers_posix.cc
+@@ -184,11 +184,19 @@
+   g_shutdown_pipe_read_fd = pipefd[0];
+   g_shutdown_pipe_write_fd = pipefd[1];
+ #if !defined(ADDRESS_SANITIZER)
++# if defined(__GLIBC__)
+   const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 2;
++# else
++  const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 2 * 8; // match up musls 2k PTHREAD_STACK_MIN with glibcs 16k
++# endif
+ #else
+   // ASan instrumentation bloats the stack frames, so we need to increase the
+   // stack size to avoid hitting the guard page.
++# if defined(__GLIBC__)
+   const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 4;
++# else
++  const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 4 * 8; // match up musls 2k PTHREAD_STACK_MIN with glibcs 16k
++# endif
+ #endif
+   ShutdownDetector* detector = new ShutdownDetector(
+       g_shutdown_pipe_read_fd, shutdown_callback, task_runner);
+
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-crashpad.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-crashpad.patch
new file mode 100644
index 000000000000..03a0c06f3ca6
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-crashpad.patch
@@ -0,0 +1,23 @@
+--- third_party/crashpad/crashpad/util/linux/ptracer.cc
++++ third_party/crashpad/crashpad/util/linux/ptracer.cc
+@@ -26,6 +26,7 @@
+ 
+ #if defined(ARCH_CPU_X86_FAMILY)
+ #include <asm/ldt.h>
++#include <asm/ptrace-abi.h>
+ #endif
+ 
+ namespace crashpad {
+
+--- third_party/crashpad/crashpad/compat/linux/sys/ptrace.h
++++ third_party/crashpad/crashpad/compat/linux/sys/ptrace.h
+@@ -17,7 +17,9 @@
+ 
+ #include_next <sys/ptrace.h>
+ 
++#if defined(__GLIBC__)
+ #include <sys/cdefs.h>
++#endif
+ 
+ // https://sourceware.org/bugzilla/show_bug.cgi?id=22433
+ #if !defined(PTRACE_GET_THREAD_AREA) && !defined(PT_GET_THREAD_AREA) && \
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-dns.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-dns.patch
new file mode 100644
index 000000000000..57cc0ac6c18a
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-dns.patch
@@ -0,0 +1,32 @@
+--- net/features.gni	2021-05-20 04:17:11.000000000 +0200
++++ -	2021-05-26 16:03:25.826113608 +0200
+@@ -28,6 +28,9 @@
+   # Reporting not used on iOS.
+   enable_reporting = !is_ios
+ 
++  # Force Posix dns config
++  force_posix_dns = true
++
+   # Includes the transport security state preload list. This list includes
+   # mechanisms (e.g. HSTS, HPKP) to enforce trusted connections to a significant
+   # set of hardcoded domains. While this list has a several hundred KB of binary
+--- net/dns/BUILD.gn	2021-05-20 04:17:11.000000000 +0200
++++ -	2021-05-26 16:05:01.510622102 +0200
+@@ -114,7 +114,7 @@
+         "dns_config_service_android.cc",
+         "dns_config_service_android.h",
+       ]
+-    } else if (is_linux) {
++    } else if (is_linux && !force_posix_dns) {
+       sources += [
+         "dns_config_service_linux.cc",
+         "dns_config_service_linux.h",
+@@ -433,7 +433,7 @@
+ 
+   if (is_android) {
+     sources += [ "dns_config_service_android_unittest.cc" ]
+-  } else if (is_linux) {
++  } else if (is_linux && !force_posix_dns) {
+     sources += [ "dns_config_service_linux_unittest.cc" ]
+   } else if (is_posix) {
+     sources += [ "dns_config_service_posix_unittest.cc" ]
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-fixes.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-fixes.patch
new file mode 100644
index 000000000000..728f2b473ce3
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-fixes.patch
@@ -0,0 +1,212 @@
+--- ./third_party/lss/linux_syscall_support.h.orig
++++ ./third_party/lss/linux_syscall_support.h
+@@ -1127,6 +1127,12 @@
+ #ifndef __NR_fallocate
+ #define __NR_fallocate          285
+ #endif
++
++#undef __NR_pread
++#define __NR_pread __NR_pread64
++#undef __NR_pwrite
++#define __NR_pwrite __NR_pwrite64
++
+ /* End of x86-64 definitions                                                 */
+ #elif defined(__mips__)
+ #if _MIPS_SIM == _MIPS_SIM_ABI32
+--- ./third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h.orig
++++ ./third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h
+@@ -37,6 +37,10 @@
+ #include "common/memory.h"
+ #include "google_breakpad/common/minidump_format.h"
+ 
++#if !defined(__GLIBC__)
++	#define _libc_fpstate _fpstate
++#endif
++
+ namespace google_breakpad {
+ 
+ // Wraps platform-dependent implementations of accessors to ucontext_t structs.
+--- ./third_party/breakpad/breakpad/src/common/linux/elf_core_dump.h.orig
++++ ./third_party/breakpad/breakpad/src/common/linux/elf_core_dump.h
+@@ -36,6 +36,7 @@
+ #include <elf.h>
+ #include <link.h>
+ #include <stddef.h>
++#include <limits.h>
+ 
+ #include "common/memory_range.h"
+ 
+--- ./sandbox/linux/suid/process_util.h.orig
++++ ./sandbox/linux/suid/process_util.h
+@@ -11,6 +11,14 @@
+ #include <stdbool.h>
+ #include <sys/types.h>
+ 
++// Some additional functions
++# define TEMP_FAILURE_RETRY(expression) \
++	(__extension__			\
++	 ({ long int __result;		\
++	  do __result = (long int) (expression); \
++	  while (__result == -1L && errno == EINTR); \
++	  __result; }))
++
+ // This adjusts /proc/process/oom_score_adj so the Linux OOM killer
+ // will prefer certain process types over others. The range for the
+ // adjustment is [-1000, 1000], with [0, 1000] being user accessible.
+--- ./sandbox/linux/seccomp-bpf/trap.cc.orig	2020-04-12 08:26:40.184159217 -0400
++++ ./sandbox/linux/seccomp-bpf/trap.cc	2020-04-12 08:46:16.737191222 -0400
+@@ -174,7 +174,7 @@
+   // If the version of glibc doesn't include this information in
+   // siginfo_t (older than 2.17), we need to explicitly copy it
+   // into an arch_sigsys structure.
+-  memcpy(&sigsys, &info->_sifields, sizeof(sigsys));
++  memcpy(&sigsys, &info->__sifields, sizeof(sigsys));
+ #endif
+ 
+ #if defined(__mips__)
+--- ./third_party/ffmpeg/libavutil/cpu.c.orig
++++ ./third_party/ffmpeg/libavutil/cpu.c
+@@ -38,7 +38,6 @@
+ #include <sys/param.h>
+ #endif
+ #include <sys/types.h>
+-#include <sys/sysctl.h>
+ #endif
+ #if HAVE_UNISTD_H
+ #include <unistd.h>
+diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
+--- chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc.orig	2021-03-10 07:23:00.145810088 -0500
++++ chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc	2021-03-10 10:57:19.405962671 -0500
+@@ -55,7 +55,9 @@
+ // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+ // of lacros-chrome is complete.
+ #if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
++#if defined(__GLIBC__)
+ #include <gnu/libc-version.h>
++#endif
+ 
+ #include "base/linux_util.h"
+ #include "base/strings/string_split.h"
+@@ -316,7 +318,7 @@
+ void RecordLinuxGlibcVersion() {
+ // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+ // of lacros-chrome is complete.
+-#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
++#if defined(__GLIBC__) || BUILDFLAG(IS_CHROMEOS_LACROS)
+   base::Version version(gnu_get_libc_version());
+ 
+   UMALinuxGlibcVersion glibc_version_result = UMA_LINUX_GLIBC_NOT_PARSEABLE;
+--- services/device/serial/serial_io_handler_posix.cc.orig	2019-07-03 10:57:32.568171835 -0400
++++ services/device/serial/serial_io_handler_posix.cc	2019-07-03 10:57:16.867983031 -0400
+@@ -6,6 +6,7 @@
+ 
+ #include <sys/ioctl.h>
+ #include <termios.h>
++#include <asm-generic/ioctls.h>
+ 
+ #include <algorithm>
+ #include <utility>
+diff --git a/third_party/ots/include/opentype-sanitiser.h b/third_party/ots/include/opentype-sanitiser.h
+--- third_party/ots/src/include/opentype-sanitiser.h
++++ third_party/ots/src/include/opentype-sanitiser.h
+@@ -20,6 +20,7 @@ typedef unsigned __int64 uint64_t;
+ #define htonl(x) _byteswap_ulong (x)
+ #define htons(x) _byteswap_ushort (x)
+ #else
++#include <sys/types.h>
+ #include <arpa/inet.h>
+ #include <stdint.h>
+ #endif
+--- ./base/logging.cc.orig	2021-01-20 12:09:54.227038757 -0500
++++ ./base/logging.cc	2021-01-20 12:24:32.600301351 -0500
+@@ -557,8 +557,7 @@
+ 
+ LogMessage::~LogMessage() {
+   size_t stack_start = stream_.tellp();
+-#if !defined(OFFICIAL_BUILD) && !defined(OS_NACL) && !defined(__UCLIBC__) && \
+-    !defined(OS_AIX)
++#if !defined(OFFICIAL_BUILD) && !defined(OS_NACL) && defined(__GLIBC__)
+   if (severity_ == LOGGING_FATAL && !base::debug::BeingDebugged()) {
+     // Include a stack trace on a fatal, unless a debugger is attached.
+     base::debug::StackTrace stack_trace;
+--- ./third_party/blink/renderer/platform/wtf/stack_util.cc.orig
++++ ./third_party/blink/renderer/platform/wtf/stack_util.cc
+@@ -28,7 +28,7 @@
+ // FIXME: On Mac OSX and Linux, this method cannot estimate stack size
+ // correctly for the main thread.
+ 
+-#elif defined(__GLIBC__) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
++#elif defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
+     defined(OS_FUCHSIA)
+   // pthread_getattr_np() can fail if the thread is not invoked by
+   // pthread_create() (e.g., the main thread of blink_unittests).
+@@ -96,7 +96,7 @@
+ }
+ 
+ void* GetStackStart() {
+-#if defined(__GLIBC__) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
++#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
+     defined(OS_FUCHSIA)
+   pthread_attr_t attr;
+   int error;
+--- ./net/dns/dns_config_service_posix.cc.orig
++++ ./net/dns/dns_config_service_posix.cc
+@@ -122,7 +122,7 @@
+   ConfigParsePosixResult result;
+   config->unhandled_options = false;
+ // TODO(fuchsia): Use res_ninit() when it's implemented on Fuchsia.
+-#if defined(OS_OPENBSD) || defined(OS_FUCHSIA)
++#if defined(OS_OPENBSD) || defined(OS_FUCHSIA) || defined(_GNU_SOURCE)
+   // Note: res_ninit in glibc always returns 0 and sets RES_INIT.
+   // res_init behaves the same way.
+   memset(&_res, 0, sizeof(_res));
+--- third_party/swiftshader/third_party/llvm-subzero/lib/Support/Unix/Signals.inc.orig	2019-06-18 11:51:17.000000000 -0400
++++ third_party/swiftshader/third_party/llvm-subzero/lib/Support/Unix/Signals.inc	2019-07-03 12:32:50.938758186 -0400
+@@ -25,7 +25,7 @@
+ #include "llvm/Support/raw_ostream.h"
+ #include <algorithm>
+ #include <string>
+-#if HAVE_EXECINFO_H
++#if HAVE_EXECINFO_H && defined(__GLIBC__)
+ # include <execinfo.h>         // For backtrace().
+ #endif
+ #if HAVE_SIGNAL_H
+@@ -52,6 +52,7 @@
+ #include <unwind.h>
+ #else
+ #undef HAVE__UNWIND_BACKTRACE
++#undef HAVE_BACKTRACE
+ #endif
+ #endif
+ 
+--- third_party/nasm/nasmlib/realpath.c.orig	2019-07-03 12:23:05.021949895 -0400
++++ third_party/nasm/nasmlib/realpath.c	2019-07-03 12:24:24.246862665 -0400
+@@ -49,7 +49,7 @@
+ 
+ #include "nasmlib.h"
+ 
+-#ifdef HAVE_CANONICALIZE_FILE_NAME
++#if defined(__GLIBC__)
+ 
+ /*
+  * GNU-specific, but avoids the realpath(..., NULL)
+--- third_party/perfetto/include/perfetto/ext/base/thread_utils.h
++++ third_party/perfetto/include/perfetto/ext/base/thread_utils.h
+@@ -29,7 +29,7 @@
+ #include <algorithm>
+ #endif
+ 
+-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
++#if 1
+ #include <sys/prctl.h>
+ #endif
+ 
+@@ -58,7 +58,7 @@ inline bool MaybeSetThreadName(const std::string& name) {
+ 
+ inline bool GetThreadName(std::string& out_result) {
+   char buf[16] = {};
+-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
++#if 1
+   if (prctl(PR_GET_NAME, buf) != 0)
+     return false;
+ #else
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-hacks.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-hacks.patch
new file mode 100644
index 000000000000..4b4e9695a9d8
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-hacks.patch
@@ -0,0 +1,34 @@
+--- base/debug/stack_trace.cc.orig	2018-12-08 14:11:25.303475116 +0100
++++ base/debug/stack_trace.cc	2018-12-08 18:00:43.874946999 +0100
+@@ -229,7 +229,7 @@
+ }
+ std::string StackTrace::ToStringWithPrefix(const char* prefix_string) const {
+   std::stringstream stream;
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+   OutputToStreamWithPrefix(&stream, prefix_string);
+ #endif
+   return stream.str();
+--- net/socket/udp_socket_posix.cc.orig	2019-07-03 13:13:46.034342649 -0400
++++ net/socket/udp_socket_posix.cc	2019-07-03 13:23:53.117081909 -0400
+@@ -1194,7 +1194,7 @@
+     msg_iov->push_back({const_cast<char*>(buffer->data()), buffer->length()});
+   msgvec->reserve(buffers.size());
+   for (size_t j = 0; j < buffers.size(); j++)
+-    msgvec->push_back({{nullptr, 0, &msg_iov[j], 1, nullptr, 0, 0}, 0});
++    msgvec->push_back({{nullptr, 0, &msg_iov[j], 1, 0, 0, 0}, 0});
+   int result = HANDLE_EINTR(Sendmmsg(fd, &msgvec[0], buffers.size(), 0));
+   SendResult send_result(0, 0, std::move(buffers));
+   if (result < 0) {
+--- base/debug/stack_trace.cc   2021-05-25 00:05:31.000000000 +0200
++++ -   2021-05-27 13:46:43.740380140 +0200
+@@ -217,7 +217,9 @@
+ }
+ 
+ void StackTrace::OutputToStream(std::ostream* os) const {
++#if defined(__GLIBC__)
+   OutputToStreamWithPrefix(os, nullptr);
++#endif
+ }
+ 
+ std::string StackTrace::ToString() const {
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-libc++.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-libc++.patch
new file mode 100644
index 000000000000..088d80fad52b
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-libc++.patch
@@ -0,0 +1,55 @@
+diff --git a/buildtools/third_party/libc++/trunk/include/locale b/buildtools/third_party/libc++/trunk/include/locale
+index d29a2dc..53998bc 100644
+--- buildtools/third_party/libc++/trunk/include/locale
++++ buildtools/third_party/libc++/trunk/include/locale
+@@ -11,6 +11,15 @@
+ #ifndef _LIBCPP_LOCALE
+ #define _LIBCPP_LOCALE
+ 
++// musl doesn't define _l (with locale) variants of functions, as it only supports UTF-8.
++// we can simply make macros that will call the non-localated ones if we're using musl, or rather not-using something that has the _l ones.
++// couldn't find anything glibc #defines when it creates strtoull_l (that it doesn't undefine a few lines later), so let's test against glibc and glibc-likes.
++// almost all glibc-likes define __GNU_LIBRARY__ for compatibility
++#ifndef __GNU_LIBRARY__
++#define strtoull_l(A, B, C, LOC) strtoull(A,B,C)
++#define strtoll_l(A, B, C, LOC) strtoll(A,B,C)
++#endif
++
+ /*
+     locale synopsis
+ 
+diff --git a/buildtools/third_party/libc++/trunk/src/locale.cpp b/buildtools/third_party/libc++/trunk/src/locale.cpp
+index 4163c2c..3d1902a 100644
+--- a/buildtools/third_party/libc++/trunk/src/locale.cpp
++++ buildtools/third_party/libc++/trunk/src/locale.cpp
+@@ -1028,11 +1028,11 @@ ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault,
+     return low;
+ }
+ 
+-#if defined(__EMSCRIPTEN__)
++//#if defined(__EMSCRIPTEN__)
+ extern "C" const unsigned short ** __ctype_b_loc();
+ extern "C" const int ** __ctype_tolower_loc();
+ extern "C" const int ** __ctype_toupper_loc();
+-#endif
++//#endif
+ 
+ #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
+ const ctype<char>::mask*
+@@ -1136,12 +1136,10 @@ ctype<char>::classic_table()  _NOEXCEPT
+ #elif defined(_AIX)
+     return (const unsigned int *)__lc_ctype_ptr->obj->mask;
+ #else
+-    // Platform not supported: abort so the person doing the port knows what to
+-    // fix
+-# warning  ctype<char>::classic_table() is not implemented
+-    printf("ctype<char>::classic_table() is not implemented\n");
+-    abort();
+-    return NULL;
++// not sure any other libc like this exists, but there is no way to differentiate musl as of right now
++// to be fair, with the change above, this should always work
++// also, #warning is a gcc extension
++    return (const unsigned long *)*__ctype_b_loc();
+ #endif
+ }
+ #endif
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-sandbox.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-sandbox.patch
new file mode 100644
index 000000000000..230bb7bbd297
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-sandbox.patch
@@ -0,0 +1,92 @@
+--- ./sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc.orig	2019-07-03 11:53:21.213479736 -0400
++++ ./sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc	2019-07-03 11:57:01.304998253 -0400
+@@ -140,31 +140,14 @@
+ ResultExpr RestrictCloneToThreadsAndEPERMFork() {
+   const Arg<unsigned long> flags(0);
+ 
+-  // TODO(mdempsky): Extend DSL to support (flags & ~mask1) == mask2.
+-  const uint64_t kAndroidCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES |
+-                                     CLONE_SIGHAND | CLONE_THREAD |
+-                                     CLONE_SYSVSEM;
+-  const uint64_t kObsoleteAndroidCloneMask = kAndroidCloneMask | CLONE_DETACHED;
++  const int required = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
++                       CLONE_THREAD | CLONE_SYSVSEM;
++  const int safe = CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | 
++                   CLONE_DETACHED;
++  const BoolExpr thread_clone_ok = (flags&~safe)==required;
+ 
+-  const uint64_t kGlibcPthreadFlags =
+-      CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD |
+-      CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
+-  const BoolExpr glibc_test = flags == kGlibcPthreadFlags;
+-
+-  const BoolExpr android_test =
+-      AnyOf(flags == kAndroidCloneMask, flags == kObsoleteAndroidCloneMask,
+-            flags == kGlibcPthreadFlags);
+-
+-  // The following two flags are the two important flags in any vfork-emulating
+-  // clone call. EPERM any clone call that contains both of them.
+-  const uint64_t kImportantCloneVforkFlags = CLONE_VFORK | CLONE_VM;
+-
+-  const BoolExpr is_fork_or_clone_vfork =
+-      AnyOf((flags & (CLONE_VM | CLONE_THREAD)) == 0,
+-            (flags & kImportantCloneVforkFlags) == kImportantCloneVforkFlags);
+-
+-  return If(IsAndroid() ? android_test : glibc_test, Allow())
+-      .ElseIf(is_fork_or_clone_vfork, Error(EPERM))
++  return If(thread_clone_ok, Allow())
++      .ElseIf((flags & (CLONE_VM | CLONE_THREAD)) == 0, Error(EPERM))
+       .Else(CrashSIGSYSClone());
+ }
+ 
+--- ./sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc.orig
++++ ./sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+@@ -494,6 +494,7 @@
+     case __NR_mlock:
+     case __NR_munlock:
+     case __NR_munmap:
++    case __NR_mremap:
+       return true;
+     case __NR_madvise:
+     case __NR_mincore:
+@@ -509,7 +510,6 @@
+     case __NR_modify_ldt:
+ #endif
+     case __NR_mprotect:
+-    case __NR_mremap:
+     case __NR_msync:
+     case __NR_munlockall:
+     case __NR_readahead:
+diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+index 80f02c0..21fbe21 100644
+--- sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
++++ sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+@@ -373,6 +373,7 @@ bool SyscallSets::IsAllowedProcessStartOrDeath(int sysno) {
+ #if defined(__i386__)
+     case __NR_waitpid:
+ #endif
++    case __NR_set_tid_address:
+       return true;
+     case __NR_clone:  // Should be parameter-restricted.
+     case __NR_setns:  // Privileged.
+@@ -385,7 +386,6 @@ bool SyscallSets::IsAllowedProcessStartOrDeath(int sysno) {
+ #if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
+     case __NR_set_thread_area:
+ #endif
+-    case __NR_set_tid_address:
+     case __NR_unshare:
+ #if !defined(__mips__) && !defined(__aarch64__)
+     case __NR_vfork:
+--- sandbox/policy/linux/bpf_renderer_policy_linux.cc
++++ sandbox/policy/linux/bpf_renderer_policy_linux.cc
+@@ -100,9 +100,9 @@
+     case __NR_uname:
+     case __NR_sched_getparam:
+     case __NR_sched_getscheduler:
++    case __NR_sched_setscheduler:
+       return Allow();
+     case __NR_sched_getaffinity:
+-    case __NR_sched_setscheduler:
+       return RestrictSchedTarget(GetPolicyPid(), sysno);
+     case __NR_prlimit64:
+       // See crbug.com/662450 and setrlimit comment above.
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-sync.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-sync.patch
new file mode 100644
index 000000000000..bc2fa1937bd3
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-sync.patch
@@ -0,0 +1,30 @@
+--- third_party/libsync/src/include/sync/sync.h.orig	2020-02-21 07:43:33.748325175 -0500
++++ third_party/libsync/src/include/sync/sync.h	2020-02-21 07:44:07.288328784 -0500
+@@ -19,12 +19,16 @@
+ #ifndef __SYS_CORE_SYNC_H
+ #define __SYS_CORE_SYNC_H
+ 
++#if defined(__GLIBC__)
+ #include <sys/cdefs.h>
++#endif
+ #include <stdint.h>
+ 
+ #include <linux/types.h>
+ 
+-__BEGIN_DECLS
++#ifdef __cplusplus
++extern "C" {
++#endif
+ 
+ struct sync_legacy_merge_data {
+  int32_t fd2;
+@@ -158,6 +162,8 @@
+                                   struct sync_pt_info *itr);
+ void sync_fence_info_free(struct sync_fence_info_data *info);
+ 
+-__END_DECLS
++#ifdef __cplusplus
++}
++#endif
+ 
+ #endif /* __SYS_CORE_SYNC_H */
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-xxx-ppc64le.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-xxx-ppc64le.patch
new file mode 100644
index 000000000000..9001a2a854d0
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-xxx-ppc64le.patch
@@ -0,0 +1,190 @@
+diff --git sandbox/linux/bpf_dsl/seccomp_macros.h sandbox/linux/bpf_dsl/seccomp_macros.h
+index a6aec544e..2a4a7f1bc 100644
+--- sandbox/linux/bpf_dsl/seccomp_macros.h
++++ sandbox/linux/bpf_dsl/seccomp_macros.h
+@@ -16,7 +16,7 @@
+ #if defined(__mips__)
+ // sys/user.h in eglibc misses size_t definition
+ #include <stddef.h>
+-#elif defined(__powerpc64__)
++#elif defined(__powerpc64__) && defined(__GLIBC__)
+ // Manually define greg_t on ppc64
+ typedef unsigned long long greg_t;
+ #endif
+@@ -361,11 +361,11 @@ typedef struct pt_regs regs_struct;
+ #define SECCOMP_ARCH AUDIT_ARCH_PPC64
+ #endif
+ 
+-#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.regs->gpr[_reg])
++#define SECCOMP_REG(_ctx, _reg) (((struct pt_regs *)(_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_IP(_ctx) ((struct pt_regs *)(_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)
+diff --git sandbox/linux/seccomp-bpf/syscall.cc sandbox/linux/seccomp-bpf/syscall.cc
+index d53a7ff56..c290f0e92 100644
+--- sandbox/linux/seccomp-bpf/syscall.cc
++++ sandbox/linux/seccomp-bpf/syscall.cc
+@@ -499,9 +499,9 @@ void Syscall::PutValueInUcontext(intptr_t ret_val, ucontext_t* ctx) {
+   // 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);
++    ((struct pt_regs *)ctx->uc_mcontext.regs)->ccr |= (1 << 28);
+   } else {
+-    ctx->uc_mcontext.regs->ccr &= ~(1 << 28);
++    ((struct pt_regs *)ctx->uc_mcontext.regs)->ccr &= ~(1 << 28);
+   }
+ #endif
+   SECCOMP_RESULT(ctx) = static_cast<greg_t>(ret_val);
+diff --git third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h
+index cdce9bf8..73d77dda 100644
+--- third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h
++++ third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h
+@@ -46,7 +46,7 @@
+ 
+ // The following platforms have an implementation of a hardware counter.
+ #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
+-  defined(__powerpc__) || defined(__ppc__) || \
++  ((defined(__powerpc__) || defined(__ppc__)) && defined(__GLIBC__)) || \
+   defined(_M_IX86) || defined(_M_X64)
+ #define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1
+ #else
+--- third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h
++++ third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h
+@@ -64,7 +64,7 @@
+ #elif defined(__i386__) || defined(__x86_64__)
+ #define ABSL_STACKTRACE_INL_HEADER \
+   "absl/debugging/internal/stacktrace_x86-inl.inc"
+-#elif defined(__ppc__) || defined(__PPC__)
++#elif (defined(__ppc__) || defined(__PPC__)) && defined(__GLIBC__)
+ #define ABSL_STACKTRACE_INL_HEADER \
+   "absl/debugging/internal/stacktrace_powerpc-inl.inc"
+ #elif defined(__aarch64__)
+diff --git third_party/breakpad/BUILD.gn third_party/breakpad/BUILD.gn
+index f9a60e37..25f3a0b7 100644
+--- third_party/breakpad/BUILD.gn
++++ third_party/breakpad/BUILD.gn
+@@ -637,6 +637,7 @@ if (is_linux || is_android) {
+ 
+     if (current_cpu == "ppc64") {
+         defines = [ "HAVE_GETCONTEXT" ]
++        libs += [ "ucontext" ]
+     } else {
+         sources += [
+             "breakpad/src/common/linux/breakpad_getcontext.S"
+diff --git third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
+index 03afec7a..0264ecf1 100644
+--- third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
++++ third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
+@@ -273,6 +273,9 @@ void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+ 
+ #elif defined(__powerpc64__)
+ 
++#include <asm/elf.h>
++#include <asm/ptrace.h>
++
+ uintptr_t ThreadInfo::GetInstructionPointer() const {
+     return mcontext.gp_regs[PT_NIP];
+ }
+@@ -290,9 +293,9 @@ void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+     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.fpregs[i] = ((uint64_t *)&mcontext.fp_regs)[i];
+ 
+-    out->float_save.fpscr = mcontext.fp_regs[NFPREG-1];
++    out->float_save.fpscr = ((uint64_t *)&mcontext.fp_regs)[ELF_NFPREG-1];
+ 
+     for (int i = 0; i < MD_VECTORSAVEAREA_PPC_VR_COUNT; i++)
+         out->vector_save.save_vr[i] = \
+diff --git third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
+index 1090470f..e580233d 100644
+--- third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
++++ third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
+@@ -257,6 +257,9 @@ void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc) {
+ 
+ #elif defined(__powerpc64__)
+ 
++#include <asm/elf.h>
++#include <asm/ptrace.h>
++
+ uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
+     return uc->uc_mcontext.gp_regs[MD_CONTEXT_PPC64_REG_SP];
+ }
+@@ -280,9 +283,9 @@ void UContextReader::FillCPUContext(RawContextCPU* out, const ucontext_t* uc,
+     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.fpregs[i] = ((uint64_t *)&uc->uc_mcontext.fp_regs)[i];
+ 
+-    out->float_save.fpscr = uc->uc_mcontext.fp_regs[NFPREG-1];
++    out->float_save.fpscr = ((uint64_t *)&uc->uc_mcontext.fp_regs)[ELF_NFPREG-1];
+ 
+     for (int i = 0; i < MD_VECTORSAVEAREA_PPC_VR_COUNT; i++)
+         out->vector_save.save_vr[i] =
+diff --git third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
+index 5a7ab50c..ee8b858c 100644
+--- third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
++++ third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
+@@ -105,6 +105,11 @@
+ #define PR_SET_PTRACER 0x59616d61
+ #endif
+ 
++/* musl hack, can't include asm/ptrace.h as that causes conflicts */
++#if defined(__powerpc64__) && !defined(PT_NIP)
++#define PT_NIP 32
++#endif
++
+ namespace google_breakpad {
+ 
+ namespace {
+diff --git third_party/crashpad/crashpad/snapshot/linux/signal_context.h third_party/crashpad/crashpad/snapshot/linux/signal_context.h
+index 8e335a09..b2a0f155 100644
+--- third_party/crashpad/crashpad/snapshot/linux/signal_context.h
++++ third_party/crashpad/crashpad/snapshot/linux/signal_context.h
+@@ -469,7 +469,7 @@ struct MContext64 {
+   SignalThreadContext64 gp_regs;
+   SignalFloatContext64  fp_regs;
+   SignalVectorContext64 *v_regs;
+-  int64_t vmx_reserve[69];
++  int64_t vmx_reserve[101];
+ };
+ 
+ struct ContextTraits64 : public Traits64 {
+diff --git third_party/crashpad/crashpad/util/linux/thread_info.h third_party/crashpad/crashpad/util/linux/thread_info.h
+index dea0d1f3..b203e5b2 100644
+--- third_party/crashpad/crashpad/util/linux/thread_info.h
++++ third_party/crashpad/crashpad/util/linux/thread_info.h
+@@ -30,6 +30,7 @@
+ 
+ #if defined(ARCH_CPU_PPC64_FAMILY)
+ #include <sys/ucontext.h>
++#include <asm/ptrace.h>
+ #endif
+ 
+ namespace crashpad {
+diff --git third_party/lss/linux_syscall_support.h third_party/lss/linux_syscall_support.h
+index 9955ce44..4c1cc488 100644
+--- third_party/lss/linux_syscall_support.h
++++ third_party/lss/linux_syscall_support.h
+@@ -4216,9 +4216,13 @@ struct kernel_statfs {
+     }
+   #endif
+   #if defined(__NR_fstatat64)
++    // musl does #define fstatat64 fstatat
++    #undef fstatat64
+     LSS_INLINE _syscall4(int,   fstatat64,        int,   d,
+                          const char *,      p,
+                          struct kernel_stat64 *,   b,    int,   f)
++    // set it back like it was
++    #define fstatat64 fstatat
+   #endif
+   #if defined(__NR_waitpid)
+     // waitpid is polyfilled below when not available.
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-no-mallinfo.patch b/srcpkgs/electron13/files/musl-patches/chromium-no-mallinfo.patch
new file mode 100644
index 000000000000..254a1f632da5
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-no-mallinfo.patch
@@ -0,0 +1,54 @@
+--- base/trace_event/malloc_dump_provider.cc.orig
++++ base/trace_event/malloc_dump_provider.cc
+@@ -243,7 +243,7 @@
+   allocated_objects_count = main_heap_info.block_count;
+ #elif defined(OS_FUCHSIA)
+ // TODO(fuchsia): Port, see https://crbug.com/706592.
+-#else
++#elif defined(__GLIBC__)
+   struct mallinfo info = mallinfo();
+   DCHECK_GE(info.arena + info.hblkhd, info.uordblks);
+ 
+--- base/process/process_metrics_posix.cc.orig	2020-11-18 23:50:33.958223497 -0500
++++ base/process/process_metrics_posix.cc	2020-11-18 23:53:52.024589316 -0500
+@@ -119,14 +119,14 @@
+   malloc_statistics_t stats = {0};
+   malloc_zone_statistics(nullptr, &stats);
+   return stats.size_in_use;
+-#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
++#elif defined(__GLIBC__) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
+   struct mallinfo minfo = mallinfo();
+ #if BUILDFLAG(USE_TCMALLOC)
+   return minfo.uordblks;
+ #else
+   return minfo.hblkhd + minfo.arena;
+ #endif
+-#elif defined(OS_FUCHSIA)
++#else
+   // TODO(fuchsia): Not currently exposed. https://crbug.com/735087.
+   return 0;
+ #endif
+--- third_party/swiftshader/third_party/llvm-subzero/lib/Support/Unix/Process.inc
++++ third_party/swiftshader/third_party/llvm-subzero/lib/Support/Unix/Process.inc.orig
+@@ -84,7 +84,7 @@
+ }
+ 
+ size_t Process::GetMallocUsage() {
+-#if defined(HAVE_MALLINFO)
++#if defined(HAVE_MALLINFO) && defined(__GLIBC__)
+   struct mallinfo mi;
+   mi = ::mallinfo();
+   return mi.uordblks;
+
+--- third_party/swiftshader/third_party/llvm-10.0/configs/linux/include/llvm/Config/config.h.orig	2019-09-30 13:03:42.556880537 -0400
++++ third_party/swiftshader/third_party/llvm-10.0/configs/linux/include/llvm/Config/config.h	2019-09-30 13:07:27.989821227 -0400
+@@ -122,7 +122,9 @@
+ /* #undef HAVE_MALLCTL */
+ 
+ /* Define to 1 if you have the `mallinfo' function. */
++#if defined(__GLIBC__)
+ #define HAVE_MALLINFO 1
++#endif
+ 
+ /* Define to 1 if you have the <malloc.h> header file. */
+ #define HAVE_MALLOC_H 1
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-resolver.patch b/srcpkgs/electron13/files/musl-patches/chromium-resolver.patch
new file mode 100644
index 000000000000..29fe2d2f1f3c
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-resolver.patch
@@ -0,0 +1,38 @@
+--- net/dns/host_resolver_manager.cc.orig	2020-10-09 16:39:12.064069835 -0400
++++ net/dns/host_resolver_manager.cc	2020-10-09 16:42:49.738302772 -0400
+@@ -2779,8 +2779,7 @@
+   NetworkChangeNotifier::AddConnectionTypeObserver(this);
+   if (system_dns_config_notifier_)
+     system_dns_config_notifier_->AddObserver(this);
+-#if defined(OS_POSIX) && !defined(OS_APPLE) && !defined(OS_OPENBSD) && \
+-    !defined(OS_ANDROID)
++#if defined(__GLIBC__)
+   EnsureDnsReloaderInit();
+ #endif
+ 
+--- net/dns/dns_reloader.cc.orig	2020-10-09 16:39:12.064069835 -0400
++++ net/dns/dns_reloader.cc	2020-10-09 16:44:30.442419823 -0400
+@@ -4,9 +4,8 @@
+ 
+ #include "net/dns/dns_reloader.h"
+ 
+-#if defined(OS_POSIX) && !defined(OS_APPLE) && !defined(OS_OPENBSD) && \
+-    !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+-
++#if defined(__GLIBC__)
++ 
+ #include <resolv.h>
+ 
+ #include "base/lazy_instance.h"
+--- net/dns/host_resolver_proc.cc.orig	2020-10-09 16:39:12.065069836 -0400
++++ net/dns/host_resolver_proc.cc	2020-10-09 16:45:09.641466644 -0400
+@@ -159,8 +159,7 @@
+   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                 base::BlockingType::WILL_BLOCK);
+ 
+-#if defined(OS_POSIX) && !defined(OS_APPLE) && !defined(OS_OPENBSD) && \
+-    !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
++#if defined(__GLIBC__)
+   DnsReloaderMaybeReload();
+ #endif
+   base::Optional<AddressInfo> ai;
diff --git a/srcpkgs/electron13/files/patches/chromium-browser-size_t.patch b/srcpkgs/electron13/files/patches/chromium-browser-size_t.patch
new file mode 100644
index 000000000000..36af0ec6c4a7
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-browser-size_t.patch
@@ -0,0 +1,10 @@
+--- a/chrome/browser/search/background/ntp_backgrounds.h	2020-08-10 20:39:20.000000000 +0200
++++ b/chrome/browser/search/background/ntp_backgrounds.h	2020-09-04 13:48:22.640023256 +0200
+@@ -6,6 +6,7 @@
+ #define CHROME_BROWSER_SEARCH_BACKGROUND_NTP_BACKGROUNDS_H_
+ 
+ #include <array>
++#include <cstddef>
+ 
+ class GURL;
+ 
diff --git a/srcpkgs/electron13/files/patches/chromium-libc_malloc.patch b/srcpkgs/electron13/files/patches/chromium-libc_malloc.patch
new file mode 100644
index 000000000000..364666caa749
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-libc_malloc.patch
@@ -0,0 +1,26 @@
+--- a/base/process/memory_linux.cc.orig	2017-09-15 08:41:43.000000000 +0000
++++ a/base/process/memory_linux.cc	2017-09-15 08:44:39.804995469 +0000
+@@ -21,6 +21,12 @@
+ #include "third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h"
+ #endif
+ 
++#if defined(LIBC_GLIBC)
++extern "C" {
++extern void *__libc_malloc(size_t size);
++}
++#endif
++
+ namespace base {
+ 
+ size_t g_oom_size = 0U;
+--- a/base/process/memory_linux.cc.orig	2020-08-30 14:18:35.401132593 -0400
++++ a/base/process/memory_linux.cc	2020-08-30 14:19:08.030199189 -0400
+@@ -141,7 +141,7 @@
+     (!defined(LIBC_GLIBC) && !BUILDFLAG(USE_TCMALLOC))
+   *result = malloc(size);
+ #elif defined(LIBC_GLIBC) && !BUILDFLAG(USE_TCMALLOC)
+-  *result = __libc_malloc(size);
++  *result = ::__libc_malloc(size);
+ #elif BUILDFLAG(USE_TCMALLOC)
+   *result = tc_malloc_skip_new_handler(size);
+ #endif
diff --git a/srcpkgs/electron13/files/patches/chromium-musl-v8-monotonic-pthread-cont_timedwait.patch b/srcpkgs/electron13/files/patches/chromium-musl-v8-monotonic-pthread-cont_timedwait.patch
new file mode 100644
index 000000000000..cb2e715fe206
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-musl-v8-monotonic-pthread-cont_timedwait.patch
@@ -0,0 +1,24 @@
+Use monotonic clock for pthread_cond_timedwait with musl too.
+
+diff --git a/v8/src/base/platform/condition-variable.cc b/v8/src/base/platform/condition-variable.cc
+index 5ea7083..c13027e 100644
+--- a/v8/src/base/platform/condition-variable.cc
++++ a/v8/src/base/platform/condition-variable.cc
+@@ -16,7 +16,7 @@ namespace base {
+ 
+ ConditionVariable::ConditionVariable() {
+ #if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
+-     (V8_OS_LINUX && V8_LIBC_GLIBC))
++     V8_OS_LINUX)
+   // On Free/Net/OpenBSD and Linux with glibc we can change the time
+   // source for pthread_cond_timedwait() to use the monotonic clock.
+   pthread_condattr_t attr;
+@@ -92,7 +92,7 @@ bool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) {
+       &native_handle_, &mutex->native_handle(), &ts);
+ #else
+ #if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
+-     (V8_OS_LINUX && V8_LIBC_GLIBC))
++     V8_OS_LINUX)
+   // On Free/Net/OpenBSD and Linux with glibc we can change the time
+   // source for pthread_cond_timedwait() to use the monotonic clock.
+   result = clock_gettime(CLOCK_MONOTONIC, &ts);
diff --git a/srcpkgs/electron13/files/patches/chromium-no-execinfo.patch b/srcpkgs/electron13/files/patches/chromium-no-execinfo.patch
new file mode 100644
index 000000000000..3cede1b0a571
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-no-execinfo.patch
@@ -0,0 +1,72 @@
+--- a/base/debug/stack_trace_posix.cc.orig	2019-05-14 14:49:44.000000000 -0400
++++ a/base/debug/stack_trace_posix.cc	2019-07-02 10:43:43.490045013 -0400
+@@ -27,7 +27,7 @@
+ #if !defined(USE_SYMBOLIZE)
+ #include <cxxabi.h>
+ #endif
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+ #include <execinfo.h>
+ #endif
+ 
+@@ -86,7 +86,7 @@
+   // Note: code in this function is NOT async-signal safe (std::string uses
+   // malloc internally).
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+   std::string::size_type search_from = 0;
+   while (search_from < text->size()) {
+     // Look for the start of a mangled symbol, from search_from.
+@@ -121,7 +121,7 @@
+       search_from = mangled_start + 2;
+     }
+   }
+-#endif  // !defined(__UCLIBC__) && !defined(_AIX)
++#endif  // defined(__GLIBC__) && !defined(_AIX)
+ }
+ #endif  // !defined(USE_SYMBOLIZE)
+ 
+@@ -133,7 +133,7 @@
+   virtual ~BacktraceOutputHandler() = default;
+ };
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+ void OutputPointer(void* pointer, BacktraceOutputHandler* handler) {
+   // This should be more than enough to store a 64-bit number in hex:
+   // 16 hex digits + 1 for null-terminator.
+@@ -216,7 +216,7 @@
+   }
+ #endif  // defined(USE_SYMBOLIZE)
+ }
+-#endif  // !defined(__UCLIBC__) && !defined(_AIX)
++#endif  // defined(__GLIBC__) && !defined(_AIX)
+ 
+ void PrintToStderr(const char* output) {
+   // NOTE: This code MUST be async-signal safe (it's used by in-process
+@@ -812,7 +812,7 @@
+   // NOTE: This code MUST be async-signal safe (it's used by in-process
+   // stack dumping signal handler). NO malloc or stdio is allowed here.
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+   // Though the backtrace API man page does not list any possible negative
+   // return values, we take no chance.
+   return base::saturated_cast<size_t>(backtrace(trace, count));
+@@ -825,13 +825,13 @@
+ // NOTE: This code MUST be async-signal safe (it's used by in-process
+ // stack dumping signal handler). NO malloc or stdio is allowed here.
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+   PrintBacktraceOutputHandler handler;
+   ProcessBacktrace(trace_, count_, prefix_string, &handler);
+ #endif
+ }
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+ void StackTrace::OutputToStreamWithPrefix(std::ostream* os,
+                                           const char* prefix_string) const {
+   StreamBacktraceOutputHandler handler(os);
diff --git a/srcpkgs/electron13/files/patches/chromium-no-getcontext.patch b/srcpkgs/electron13/files/patches/chromium-no-getcontext.patch
new file mode 100644
index 000000000000..2502b5a06acb
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-no-getcontext.patch
@@ -0,0 +1,27 @@
+--- a/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc.orig	2015-12-06 09:59:55.554536646 +0100
++++ a/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc	2015-12-06 10:01:16.818238035 +0100
+@@ -477,7 +477,9 @@ bool ExceptionHandler::SimulateSignalDel
+   siginfo.si_code = SI_USER;
+   siginfo.si_pid = getpid();
+   ucontext_t context;
++#if defined(__GLIBC__)
+   getcontext(&context);
++#endif
+   return HandleSignal(sig, &siginfo, &context);
+ }
+ 
+@@ -647,9 +649,14 @@ bool ExceptionHandler::WriteMinidump() {
+   sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
+ 
+   CrashContext context;
++
++#if defined(__GLIBC__)
+   int getcontext_result = getcontext(&context.context);
+   if (getcontext_result)
+     return false;
++#else
++  return false;
++#endif
+ 
+ #if defined(__i386__)
+   // In CPUFillFromUContext in minidumpwriter.cc the stack pointer is retrieved
diff --git a/srcpkgs/electron13/files/patches/chromium-revert-drop-of-system-java.patch b/srcpkgs/electron13/files/patches/chromium-revert-drop-of-system-java.patch
new file mode 100644
index 000000000000..c3f97c7c4d1c
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-revert-drop-of-system-java.patch
@@ -0,0 +1,15 @@
+This was dropped for some reason in 6951c37cecd05979b232a39e5c10e6346a0f74ef
+--- a/third_party/closure_compiler/compiler.py	2021-05-20 04:17:53.000000000 +0200
++++ -	2021-05-25 20:31:10.102971765 +0200
+@@ -13,8 +13,9 @@
+ 
+ 
+ _CURRENT_DIR = os.path.join(os.path.dirname(__file__))
+-_JAVA_PATH = os.path.join(_CURRENT_DIR, "..", "jdk", "current", "bin", "java")
+-assert os.path.isfile(_JAVA_PATH), "java only allowed in android builds"
++_JAVA_BIN = "java"
++_JDK_PATH = os.path.join(_CURRENT_DIR, "..", "jdk", "current", "bin", "java")
++_JAVA_PATH = _JDK_PATH if os.path.isfile(_JDK_PATH) else _JAVA_BIN
+ 
+ class Compiler(object):
+   """Runs the Closure compiler on given source files to typecheck them
diff --git a/srcpkgs/electron13/files/patches/chromium-sandbox-membarrier.patch b/srcpkgs/electron13/files/patches/chromium-sandbox-membarrier.patch
new file mode 100644
index 000000000000..998552c2f9e7
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-sandbox-membarrier.patch
@@ -0,0 +1,10 @@
+--- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
++++ a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+@@ -370,6 +370,7 @@
+   switch (sysno) {
+     case __NR_exit:
+     case __NR_exit_group:
++    case __NR_membarrier:
+     case __NR_wait4:
+     case __NR_waitid:
+ #if defined(__i386__)
diff --git a/srcpkgs/electron13/files/patches/chromium-sandbox-sched_getparam.patch b/srcpkgs/electron13/files/patches/chromium-sandbox-sched_getparam.patch
new file mode 100644
index 000000000000..87f11af43c04
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-sandbox-sched_getparam.patch
@@ -0,0 +1,20 @@
+Allow SYS_sched_getparam and SYS_sched_getscheduler
+musl uses them for pthread_getschedparam()
+
+source: https://git.alpinelinux.org/aports/commit/community/chromium?id=54af9f8ac24f52d382c5758e2445bf0206eff40e
+
+--- a/sandbox/policy/linux/bpf_renderer_policy_linux.cc.orig	2019-10-08 21:03:18.253080425 +0200
++++ a/sandbox/policy/linux/bpf_renderer_policy_linux.cc	2019-10-08 21:04:19.648549718 +0200
+@@ -88,10 +88,10 @@
+     case __NR_sysinfo:
+     case __NR_times:
+     case __NR_uname:
+-      return Allow();
+-    case __NR_sched_getaffinity:
+     case __NR_sched_getparam:
+     case __NR_sched_getscheduler:
++      return Allow();
++    case __NR_sched_getaffinity:
+     case __NR_sched_setscheduler:
+       return sandbox::RestrictSchedTarget(GetPolicyPid(), sysno);
+     case __NR_prlimit64:
diff --git a/srcpkgs/electron13/files/patches/chromium-sndio.patch b/srcpkgs/electron13/files/patches/chromium-sndio.patch
new file mode 100644
index 000000000000..4cab48d50821
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-sndio.patch
@@ -0,0 +1,886 @@
+diff -Naur chromium-83.0.4103.97.orig/media/BUILD.gn chromium-83.0.4103.97/media/BUILD.gn
+--- a/media/BUILD.gn.orig	2020-06-03 20:40:26.000000000 +0200
++++ a/media/BUILD.gn	2020-06-13 17:32:28.510395975 +0200
+@@ -65,6 +65,9 @@
+       defines += [ "DLOPEN_PULSEAUDIO" ]
+     }
+   }
++  if (use_sndio) {
++    defines += [ "USE_SNDIO" ]
++  }
+   if (use_cras) {
+     defines += [ "USE_CRAS" ]
+   }
+diff -Naur chromium-83.0.4103.97.orig/media/audio/BUILD.gn chromium-83.0.4103.97/media/audio/BUILD.gn
+--- a/media/audio/BUILD.gn.orig	2020-06-03 20:39:37.000000000 +0200
++++ a/media/audio/BUILD.gn	2020-06-13 17:32:28.511395969 +0200
+@@ -236,6 +236,17 @@
+     sources += [ "linux/audio_manager_linux.cc" ]
+   }
+ 
++  if (use_sndio) {
++    libs += [ "sndio" ]
++    sources += [
++      "sndio/audio_manager_sndio.cc",
++      "sndio/sndio_input.cc",
++      "sndio/sndio_input.h",
++      "sndio/sndio_output.cc",
++      "sndio/sndio_output.h"
++    ]
++  }
++
+   if (use_alsa) {
+     libs += [ "asound" ]
+     sources += [
+diff -Naur chromium-83.0.4103.97.orig/media/audio/linux/audio_manager_linux.cc chromium-83.0.4103.97/media/audio/linux/audio_manager_linux.cc
+--- a/media/audio/linux/audio_manager_linux.cc.orig	2020-06-03 20:39:37.000000000 +0200
++++ a/media/audio/linux/audio_manager_linux.cc	2020-06-13 18:09:43.623333167 +0200
+@@ -19,6 +19,11 @@
+ #include "media/audio/pulse/audio_manager_pulse.h"
+ #include "media/audio/pulse/pulse_util.h"
+ #endif
++#if defined(USE_SNDIO)
++#include "media/audio/sndio/audio_manager_sndio.h"
++#include "media/audio/sndio/sndio_input.h"
++#include "media/audio/sndio/sndio_output.h"
++#endif
+ 
+ namespace media {
+ 
+@@ -26,7 +31,8 @@
+   kPulse,
+   kAlsa,
+   kCras,
+-  kAudioIOMax = kCras  // Must always be equal to largest logged entry.
++  kSndio,
++  kAudioIOMax = kSndio // Must always be equal to largest logged entry.
+ };
+ 
+ std::unique_ptr<media::AudioManager> CreateAudioManager(
+@@ -39,6 +45,16 @@
+                                               audio_log_factory);
+   }
+ 
++#if defined(USE_SNDIO)
++  struct sio_hdl *hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
++  if (hdl != NULL) {
++    sio_close(hdl);
++    UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kSndio, kAudioIOMax + 1);
++    return std::make_unique<AudioManagerSndio>(std::move(audio_thread),
++                                                  audio_log_factory);
++  }
++#endif
++
+ #if defined(USE_CRAS)
+   if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseCras)) {
+     UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kCras, kAudioIOMax + 1);
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/audio_manager_sndio.cc chromium-83.0.4103.97/media/audio/sndio/audio_manager_sndio.cc
+--- a/media/audio/sndio/audio_manager_sndio.cc.orig	1970-01-01 01:00:00.000000000 +0100
++++ a/media/audio/sndio/audio_manager_sndio.cc	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,148 @@
++// Copyright (c) 2012 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.
++
++#include "media/audio/sndio/audio_manager_sndio.h"
++
++#include "base/metrics/histogram_macros.h"
++#include "base/memory/ptr_util.h"
++#include "media/audio/audio_device_description.h"
++#include "media/audio/audio_output_dispatcher.h"
++#include "media/audio/sndio/sndio_input.h"
++#include "media/audio/sndio/sndio_output.h"
++#include "media/base/limits.h"
++#include "media/base/media_switches.h"
++
++namespace media {
++
++
++// Maximum number of output streams that can be open simultaneously.
++static const int kMaxOutputStreams = 4;
++
++// Default sample rate for input and output streams.
++static const int kDefaultSampleRate = 48000;
++
++void AddDefaultDevice(AudioDeviceNames* device_names) {
++  DCHECK(device_names->empty());
++  device_names->push_front(AudioDeviceName::CreateDefault());
++}
++
++bool AudioManagerSndio::HasAudioOutputDevices() {
++  return true;
++}
++
++bool AudioManagerSndio::HasAudioInputDevices() {
++  return true;
++}
++
++void AudioManagerSndio::GetAudioInputDeviceNames(
++    AudioDeviceNames* device_names) {
++  DCHECK(device_names->empty());
++  AddDefaultDevice(device_names);
++}
++
++void AudioManagerSndio::GetAudioOutputDeviceNames(
++    AudioDeviceNames* device_names) {
++  AddDefaultDevice(device_names);
++}
++
++const char* AudioManagerSndio::GetName() {
++  return "SNDIO";
++}
++
++AudioParameters AudioManagerSndio::GetInputStreamParameters(
++    const std::string& device_id) {
++  static const int kDefaultInputBufferSize = 1024;
++
++  int user_buffer_size = GetUserBufferSize();
++  int buffer_size = user_buffer_size ?
++      user_buffer_size : kDefaultInputBufferSize;
++
++  return AudioParameters(
++      AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
++      kDefaultSampleRate, buffer_size);
++}
++
++AudioManagerSndio::AudioManagerSndio(std::unique_ptr<AudioThread> audio_thread,
++                                         AudioLogFactory* audio_log_factory)
++    : AudioManagerBase(std::move(audio_thread),
++                       audio_log_factory) {
++  DLOG(WARNING) << "AudioManagerSndio";
++  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
++}
++
++AudioManagerSndio::~AudioManagerSndio() {
++  Shutdown();
++}
++
++AudioOutputStream* AudioManagerSndio::MakeLinearOutputStream(
++    const AudioParameters& params,
++    const LogCallback& log_callback) {
++  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
++  return MakeOutputStream(params);
++}
++
++AudioOutputStream* AudioManagerSndio::MakeLowLatencyOutputStream(
++    const AudioParameters& params,
++    const std::string& device_id,
++    const LogCallback& log_callback) {
++  DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
++  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
++  return MakeOutputStream(params);
++}
++
++AudioInputStream* AudioManagerSndio::MakeLinearInputStream(
++    const AudioParameters& params,
++    const std::string& device_id,
++    const LogCallback& log_callback) {
++  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
++  return MakeInputStream(params);
++}
++
++AudioInputStream* AudioManagerSndio::MakeLowLatencyInputStream(
++    const AudioParameters& params,
++    const std::string& device_id,
++    const LogCallback& log_callback) {
++  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
++  return MakeInputStream(params);
++}
++
++AudioParameters AudioManagerSndio::GetPreferredOutputStreamParameters(
++    const std::string& output_device_id,
++    const AudioParameters& input_params) {
++  // TODO(tommi): Support |output_device_id|.
++  DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
++  static const int kDefaultOutputBufferSize = 2048;
++
++  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
++  int sample_rate = kDefaultSampleRate;
++  int buffer_size = kDefaultOutputBufferSize;
++  if (input_params.IsValid()) {
++    sample_rate = input_params.sample_rate();
++    channel_layout = input_params.channel_layout();
++    buffer_size = std::min(buffer_size, input_params.frames_per_buffer());
++  }
++
++  int user_buffer_size = GetUserBufferSize();
++  if (user_buffer_size)
++    buffer_size = user_buffer_size;
++
++  return AudioParameters(
++      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
++      sample_rate, buffer_size);
++}
++
++AudioInputStream* AudioManagerSndio::MakeInputStream(
++    const AudioParameters& params) {
++  DLOG(WARNING) << "MakeInputStream";
++  return new SndioAudioInputStream(this,
++             AudioDeviceDescription::kDefaultDeviceId, params);
++}
++
++AudioOutputStream* AudioManagerSndio::MakeOutputStream(
++    const AudioParameters& params) {
++  DLOG(WARNING) << "MakeOutputStream";
++  return new SndioAudioOutputStream(params, this);
++}
++
++}  // namespace media
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/audio_manager_sndio.h chromium-83.0.4103.97/media/audio/sndio/audio_manager_sndio.h
+--- a/media/audio/sndio/audio_manager_sndio.h.orig	1970-01-01 01:00:00.000000000 +0100
++++ a/media/audio/sndio/audio_manager_sndio.h	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,65 @@
++// Copyright (c) 2012 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 MEDIA_AUDIO_SNDIO_AUDIO_MANAGER_SNDIO_H_
++#define MEDIA_AUDIO_SNDIO_AUDIO_MANAGER_SNDIO_H_
++
++#include <set>
++
++#include "base/compiler_specific.h"
++#include "base/macros.h"
++#include "base/memory/ref_counted.h"
++#include "base/threading/thread.h"
++#include "media/audio/audio_manager_base.h"
++
++namespace media {
++
++class MEDIA_EXPORT AudioManagerSndio : public AudioManagerBase {
++ public:
++  AudioManagerSndio(std::unique_ptr<AudioThread> audio_thread,
++                   AudioLogFactory* audio_log_factory);
++  ~AudioManagerSndio() override;
++
++  // Implementation of AudioManager.
++  bool HasAudioOutputDevices() override;
++  bool HasAudioInputDevices() override;
++  void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
++  void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override;
++  AudioParameters GetInputStreamParameters(
++      const std::string& device_id) override;
++  const char* GetName() override;
++
++  // Implementation of AudioManagerBase.
++  AudioOutputStream* MakeLinearOutputStream(
++      const AudioParameters& params,
++      const LogCallback& log_callback) override;
++  AudioOutputStream* MakeLowLatencyOutputStream(
++      const AudioParameters& params,
++      const std::string& device_id,
++      const LogCallback& log_callback) override;
++  AudioInputStream* MakeLinearInputStream(
++      const AudioParameters& params,
++      const std::string& device_id,
++      const LogCallback& log_callback) override;
++  AudioInputStream* MakeLowLatencyInputStream(
++      const AudioParameters& params,
++      const std::string& device_id,
++      const LogCallback& log_callback) override;
++
++ protected:
++  AudioParameters GetPreferredOutputStreamParameters(
++      const std::string& output_device_id,
++      const AudioParameters& input_params) override;
++
++ private:
++  // Called by MakeLinearOutputStream and MakeLowLatencyOutputStream.
++  AudioOutputStream* MakeOutputStream(const AudioParameters& params);
++  AudioInputStream* MakeInputStream(const AudioParameters& params);
++
++  DISALLOW_COPY_AND_ASSIGN(AudioManagerSndio);
++};
++
++}  // namespace media
++
++#endif  // MEDIA_AUDIO_SNDIO_AUDIO_MANAGER_SNDIO_H_
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/sndio_input.cc chromium-83.0.4103.97/media/audio/sndio/sndio_input.cc
+--- a/media/audio/sndio/sndio_input.cc.orig	1970-01-01 01:00:00.000000000 +0100
++++ a/media/audio/sndio/sndio_input.cc	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,200 @@
++// Copyright 2013 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.
++
++#include "base/bind.h"
++#include "base/logging.h"
++#include "base/macros.h"
++#include "media/base/audio_timestamp_helper.h"
++#include "media/audio/sndio/audio_manager_sndio.h"
++#include "media/audio/audio_manager.h"
++#include "media/audio/sndio/sndio_input.h"
++
++namespace media {
++
++static const SampleFormat kSampleFormat = kSampleFormatS16;
++
++void SndioAudioInputStream::OnMoveCallback(void *arg, int delta)
++{
++  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
++
++  self->hw_delay += delta;
++}
++
++void *SndioAudioInputStream::ThreadEntry(void *arg) {
++  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
++
++  self->ThreadLoop();
++  return NULL;
++}
++
++SndioAudioInputStream::SndioAudioInputStream(AudioManagerBase* manager,
++                                             const std::string& device_name,
++                                             const AudioParameters& params)
++    : manager(manager),
++      params(params),
++      audio_bus(AudioBus::Create(params)),
++      state(kClosed) {
++}
++
++SndioAudioInputStream::~SndioAudioInputStream() {
++  if (state != kClosed)
++    Close();
++}
++
++bool SndioAudioInputStream::Open() {
++  struct sio_par par;
++  int sig;
++
++  if (state != kClosed)
++    return false;
++
++  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
++      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
++    LOG(WARNING) << "Unsupported audio format.";
++    return false;
++  }
++
++  sio_initpar(&par);
++  par.rate = params.sample_rate();
++  par.rchan = params.channels();
++  par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
++  par.bps = par.bits / 8;
++  par.sig = sig = par.bits != 8 ? 1 : 0;
++  par.le = SIO_LE_NATIVE;
++  par.appbufsz = params.frames_per_buffer();
++
++  hdl = sio_open(SIO_DEVANY, SIO_REC, 0);
++
++  if (hdl == NULL) {
++    LOG(ERROR) << "Couldn't open audio device.";
++    return false;
++  }
++
++  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
++    LOG(ERROR) << "Couldn't set audio parameters.";
++    goto bad_close;
++  }
++
++  if (par.rate  != (unsigned int)params.sample_rate() ||
++      par.rchan != (unsigned int)params.channels() ||
++      par.bits  != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
++      par.sig   != (unsigned int)sig ||
++      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
++      (par.bits != par.bps * 8)) {
++    LOG(ERROR) << "Unsupported audio parameters.";
++    goto bad_close;
++  }
++  state = kStopped;
++  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
++  sio_onmove(hdl, &OnMoveCallback, this);
++  return true;
++bad_close:
++  sio_close(hdl);
++  return false;
++}
++
++void SndioAudioInputStream::Start(AudioInputCallback* cb) {
++
++  StartAgc();
++
++  state = kRunning;
++  hw_delay = 0;
++  callback = cb;
++  sio_start(hdl);
++  if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
++    LOG(ERROR) << "Failed to create real-time thread for recording.";
++    sio_stop(hdl);
++    state = kStopped;
++  }
++}
++
++void SndioAudioInputStream::Stop() {
++
++  if (state == kStopped)
++    return;
++
++  state = kStopWait;
++  pthread_join(thread, NULL);
++  sio_stop(hdl);
++  state = kStopped;
++
++  StopAgc();
++}
++
++void SndioAudioInputStream::Close() {
++
++  if (state == kClosed)
++    return;
++
++  if (state == kRunning)
++    Stop();
++
++  state = kClosed;
++  delete [] buffer;
++  sio_close(hdl);
++
++  manager->ReleaseInputStream(this);
++}
++
++double SndioAudioInputStream::GetMaxVolume() {
++  // Not supported
++  return 0.0;
++}
++
++void SndioAudioInputStream::SetVolume(double volume) {
++  // Not supported. Do nothing.
++}
++
++double SndioAudioInputStream::GetVolume() {
++  // Not supported.
++  return 0.0;
++}
++
++bool SndioAudioInputStream::IsMuted() {
++  // Not supported.
++  return false;
++}
++
++void SndioAudioInputStream::SetOutputDeviceForAec(
++    const std::string& output_device_id) {
++  // Not supported.
++}
++
++void SndioAudioInputStream::ThreadLoop(void) {
++  size_t todo, n;
++  char *data;
++  unsigned int nframes;
++  double normalized_volume = 0.0;
++
++  nframes = audio_bus->frames();
++
++  while (state == kRunning && !sio_eof(hdl)) {
++
++    GetAgcVolume(&normalized_volume);
++
++    // read one block
++    todo = nframes * params.GetBytesPerFrame(kSampleFormat);
++    data = buffer;
++    while (todo > 0) {
++      n = sio_read(hdl, data, todo);
++      if (n == 0)
++        return;	// unrecoverable I/O error
++      todo -= n;
++      data += n;
++    }
++    hw_delay -= nframes;
++
++    // convert frames count to TimeDelta
++    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
++      params.sample_rate());
++
++    // push into bus
++    audio_bus->FromInterleaved(buffer, nframes, SampleFormatToBytesPerChannel(kSampleFormat));
++
++    // invoke callback
++    callback->OnData(audio_bus.get(), base::TimeTicks::Now() - delay, 1.);
++  }
++}
++
++}  // namespace media
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/sndio_input.h chromium-83.0.4103.97/media/audio/sndio/sndio_input.h
+--- a/media/audio/sndio/sndio_input.h.orig	1970-01-01 01:00:00.000000000 +0100
++++ a/media/audio/sndio/sndio_input.h	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,91 @@
++// Copyright 2013 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 MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
++#define MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
++
++#include <stdint.h>
++#include <string>
++#include <sndio.h>
++
++#include "base/compiler_specific.h"
++#include "base/macros.h"
++#include "base/memory/weak_ptr.h"
++#include "base/time/time.h"
++#include "media/audio/agc_audio_stream.h"
++#include "media/audio/audio_io.h"
++#include "media/audio/audio_device_description.h"
++#include "media/base/audio_parameters.h"
++
++namespace media {
++
++class AudioManagerBase;
++
++// Implementation of AudioOutputStream using sndio(7)
++class SndioAudioInputStream : public AgcAudioStream<AudioInputStream> {
++ public:
++  // Pass this to the constructor if you want to attempt auto-selection
++  // of the audio recording device.
++  static const char kAutoSelectDevice[];
++
++  // Create a PCM Output stream for the SNDIO device identified by
++  // |device_name|. If unsure of what to use for |device_name|, use
++  // |kAutoSelectDevice|.
++  SndioAudioInputStream(AudioManagerBase* audio_manager,
++                     const std::string& device_name,
++                     const AudioParameters& params);
++
++  ~SndioAudioInputStream() override;
++
++  // Implementation of AudioInputStream.
++  bool Open() override;
++  void Start(AudioInputCallback* callback) override;
++  void Stop() override;
++  void Close() override;
++  double GetMaxVolume() override;
++  void SetVolume(double volume) override;
++  double GetVolume() override;
++  bool IsMuted() override;
++  void SetOutputDeviceForAec(const std::string& output_device_id) override;
++
++ private:
++
++  enum StreamState {
++    kClosed,            // Not opened yet
++    kStopped,           // Device opened, but not started yet
++    kRunning,           // Started, device playing
++    kStopWait           // Stopping, waiting for the real-time thread to exit
++  };
++
++  // C-style call-backs
++  static void OnMoveCallback(void *arg, int delta);
++  static void* ThreadEntry(void *arg);
++
++  // Continuously moves data from the device to the consumer
++  void ThreadLoop();
++  // Our creator, the audio manager needs to be notified when we close.
++  AudioManagerBase* manager;
++  // Parameters of the source
++  AudioParameters params;
++  // We store data here for consumer
++  std::unique_ptr<AudioBus> audio_bus;
++  // Call-back that consumes recorded data
++  AudioInputCallback* callback;  // Valid during a recording session.
++  // Handle of the audio device
++  struct sio_hdl* hdl;
++  // Current state of the stream
++  enum StreamState state;
++  // High priority thread running ThreadLoop()
++  pthread_t thread;
++  // Number of frames buffered in the hardware
++  int hw_delay;
++  // Temporary buffer where data is stored sndio-compatible format
++  char* buffer;
++
++  DISALLOW_COPY_AND_ASSIGN(SndioAudioInputStream);
++};
++
++}  // namespace media
++
++#endif  // MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/sndio_output.cc chromium-83.0.4103.97/media/audio/sndio/sndio_output.cc
+--- a/media/audio/sndio/sndio_output.cc.orig	1970-01-01 01:00:00.000000000 +0100
++++ a/media/audio/sndio/sndio_output.cc	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,183 @@
++// Copyright (c) 2012 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.
++
++#include "base/logging.h"
++#include "base/time/time.h"
++#include "base/time/default_tick_clock.h"
++#include "media/audio/audio_manager_base.h"
++#include "media/base/audio_timestamp_helper.h"
++#include "media/audio/sndio/sndio_output.h"
++
++namespace media {
++
++static const SampleFormat kSampleFormat = kSampleFormatS16;
++
++void SndioAudioOutputStream::OnMoveCallback(void *arg, int delta) {
++  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
++
++  self->hw_delay -= delta;
++}
++
++void SndioAudioOutputStream::OnVolCallback(void *arg, unsigned int vol) {
++  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
++
++  self->vol = vol;
++}
++
++void *SndioAudioOutputStream::ThreadEntry(void *arg) {
++  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
++
++  self->ThreadLoop();
++  return NULL;
++}
++
++SndioAudioOutputStream::SndioAudioOutputStream(const AudioParameters& params,
++                                               AudioManagerBase* manager)
++    : manager(manager),
++      params(params),
++      audio_bus(AudioBus::Create(params)),
++      state(kClosed),
++      mutex(PTHREAD_MUTEX_INITIALIZER) {
++}
++
++SndioAudioOutputStream::~SndioAudioOutputStream() {
++  if (state != kClosed)
++    Close();
++}
++
++bool SndioAudioOutputStream::Open() {
++  struct sio_par par;
++  int sig;
++
++  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
++      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
++    LOG(WARNING) << "Unsupported audio format.";
++    return false;
++  }
++  sio_initpar(&par);
++  par.rate = params.sample_rate();
++  par.pchan = params.channels();
++  par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
++  par.bps = par.bits / 8;
++  par.sig = sig = par.bits != 8 ? 1 : 0;
++  par.le = SIO_LE_NATIVE;
++  par.appbufsz = params.frames_per_buffer();
++
++  hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
++  if (hdl == NULL) {
++    LOG(ERROR) << "Couldn't open audio device.";
++    return false;
++  }
++  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
++    LOG(ERROR) << "Couldn't set audio parameters.";
++    goto bad_close;
++  }
++  if (par.rate  != (unsigned int)params.sample_rate() ||
++      par.pchan != (unsigned int)params.channels() ||
++      par.bits  != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
++      par.sig   != (unsigned int)sig ||
++      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
++      (par.bits != par.bps * 8)) {
++    LOG(ERROR) << "Unsupported audio parameters.";
++    goto bad_close;
++  }
++  state = kStopped;
++  volpending = 0;
++  vol = 0;
++  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
++  sio_onmove(hdl, &OnMoveCallback, this);
++  sio_onvol(hdl, &OnVolCallback, this);
++  return true;
++ bad_close:
++  sio_close(hdl);
++  return false;
++}
++
++void SndioAudioOutputStream::Close() {
++  if (state == kClosed)
++    return;
++  if (state == kRunning)
++    Stop();
++  state = kClosed;
++  delete [] buffer;
++  sio_close(hdl);
++  manager->ReleaseOutputStream(this);  // Calls the destructor
++}
++
++void SndioAudioOutputStream::Start(AudioSourceCallback* callback) {
++  state = kRunning;
++  hw_delay = 0;
++  source = callback;
++  sio_start(hdl);
++  if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
++    LOG(ERROR) << "Failed to create real-time thread.";
++    sio_stop(hdl);
++    state = kStopped;
++  }
++}
++
++void SndioAudioOutputStream::Stop() {
++  if (state == kStopped)
++    return;
++  state = kStopWait;
++  pthread_join(thread, NULL);
++  sio_stop(hdl);
++  state = kStopped;
++}
++
++void SndioAudioOutputStream::SetVolume(double v) {
++  pthread_mutex_lock(&mutex);
++  vol = v * SIO_MAXVOL;
++  volpending = 1;
++  pthread_mutex_unlock(&mutex);
++}
++
++void SndioAudioOutputStream::GetVolume(double* v) {
++  pthread_mutex_lock(&mutex);
++  *v = vol * (1. / SIO_MAXVOL);
++  pthread_mutex_unlock(&mutex);
++}
++
++// This stream is always used with sub second buffer sizes, where it's
++// sufficient to simply always flush upon Start().
++void SndioAudioOutputStream::Flush() {}
++
++void SndioAudioOutputStream::ThreadLoop(void) {
++  int avail, count, result;
++
++  while (state == kRunning) {
++    // Update volume if needed
++    pthread_mutex_lock(&mutex);
++    if (volpending) {
++      volpending = 0;
++      sio_setvol(hdl, vol);
++    }
++    pthread_mutex_unlock(&mutex);
++
++    // Get data to play
++    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
++	params.sample_rate());
++    count = source->OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get());
++    audio_bus->ToInterleaved(count, SampleFormatToBytesPerChannel(kSampleFormat), buffer);
++    if (count == 0) {
++      // We have to submit something to the device
++      count = audio_bus->frames();
++      memset(buffer, 0, count * params.GetBytesPerFrame(kSampleFormat));
++      LOG(WARNING) << "No data to play, running empty cycle.";
++    }
++
++    // Submit data to the device
++    avail = count * params.GetBytesPerFrame(kSampleFormat);
++    result = sio_write(hdl, buffer, avail);
++    if (result == 0) {
++      LOG(WARNING) << "Audio device disconnected.";
++      break;
++    }
++
++    // Update hardware pointer
++    hw_delay += count;
++  }
++}
++
++}  // namespace media
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/sndio_output.h chromium-83.0.4103.97/media/audio/sndio/sndio_output.h
+--- a/media/audio/sndio/sndio_output.h.orig	1970-01-01 01:00:00.000000000 +0100
++++ a/media/audio/sndio/sndio_output.h	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,86 @@
++// Copyright (c) 2012 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 MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
++#define MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
++
++#include <pthread.h>
++#include <sndio.h>
++
++#include "base/time/tick_clock.h"
++#include "base/time/time.h"
++#include "media/audio/audio_io.h"
++
++namespace media {
++
++class AudioManagerBase;
++
++// Implementation of AudioOutputStream using sndio(7)
++class SndioAudioOutputStream : public AudioOutputStream {
++ public:
++  // The manager is creating this object
++  SndioAudioOutputStream(const AudioParameters& params,
++                         AudioManagerBase* manager);
++  virtual ~SndioAudioOutputStream();
++
++  // Implementation of AudioOutputStream.
++  bool Open() override;
++  void Close() override;
++  void Start(AudioSourceCallback* callback) override;
++  void Stop() override;
++  void SetVolume(double volume) override;
++  void GetVolume(double* volume) override;
++  void Flush() override;
++
++  friend void sndio_onmove(void *arg, int delta);
++  friend void sndio_onvol(void *arg, unsigned int vol);
++  friend void *sndio_threadstart(void *arg);
++
++ private:
++  enum StreamState {
++    kClosed,            // Not opened yet
++    kStopped,           // Device opened, but not started yet
++    kRunning,           // Started, device playing
++    kStopWait           // Stopping, waiting for the real-time thread to exit
++  };
++
++  // C-style call-backs
++  static void OnMoveCallback(void *arg, int delta);
++  static void OnVolCallback(void *arg, unsigned int vol);
++  static void* ThreadEntry(void *arg);
++
++  // Continuously moves data from the producer to the device
++  void ThreadLoop(void);
++
++  // Our creator, the audio manager needs to be notified when we close.
++  AudioManagerBase* manager;
++  // Parameters of the source
++  AudioParameters params;
++  // Source stores data here
++  std::unique_ptr<AudioBus> audio_bus;
++  // Call-back that produces data to play
++  AudioSourceCallback* source;
++  // Handle of the audio device
++  struct sio_hdl* hdl;
++  // Current state of the stream
++  enum StreamState state;
++  // High priority thread running ThreadLoop()
++  pthread_t thread;
++  // Protects vol, volpending and hw_delay
++  pthread_mutex_t mutex;
++  // Current volume in the 0..SIO_MAXVOL range
++  int vol;
++  // Set to 1 if volumes must be refreshed in the realtime thread
++  int volpending;
++  // Number of frames buffered in the hardware
++  int hw_delay;
++  // Temporary buffer where data is stored sndio-compatible format
++  char* buffer;
++
++  DISALLOW_COPY_AND_ASSIGN(SndioAudioOutputStream);
++};
++
++}  // namespace media
++
++#endif  // MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
+diff -Naur chromium-83.0.4103.97.orig/media/media_options.gni chromium-83.0.4103.97/media/media_options.gni
+--- a/media/media_options.gni.orig	2020-06-03 20:40:26.000000000 +0200
++++ a/media/media_options.gni	2020-06-13 17:32:28.512395963 +0200
+@@ -119,6 +119,9 @@
+   # Enables runtime selection of ALSA library for audio.
+   use_alsa = false
+ 
++  # Enable runtime selection of sndio(7)
++  use_sndio = false
++
+   # Alsa should be used on non-Android, non-Mac POSIX systems.
+   # Alsa should be used on desktop Chromecast and audio-only Chromecast builds.
+   if (is_posix && !is_android && !is_mac &&
diff --git a/srcpkgs/electron13/files/patches/chromium-system-nodejs.patch b/srcpkgs/electron13/files/patches/chromium-system-nodejs.patch
new file mode 100644
index 000000000000..1610887f5309
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-system-nodejs.patch
@@ -0,0 +1,20 @@
+--- a/third_party/node/node.py	2021-05-20 04:17:54.000000000 +0200
++++ -	2021-05-25 11:57:32.895222559 +0200
+@@ -17,11 +17,12 @@
+   if platform.system() == 'Darwin' and platform.machine() == 'arm64':
+       return os.path.join(os_path.join(os_path.dirname(__file__), 'mac',
+                           'node-darwin-arm64', 'bin', 'node'))
+-  return os_path.join(os_path.dirname(__file__), *{
+-    'Darwin': ('mac', 'node-darwin-x64', 'bin', 'node'),
+-    'Linux': ('linux', 'node-linux-x64', 'bin', 'node'),
+-    'Windows': ('win', 'node.exe'),
+-  }[platform.system()])
++  return "/usr/bin/node"
++  #return os_path.join(os_path.dirname(__file__), *{
++  #  'Darwin': ('mac', 'node-darwin-x64', 'bin', 'node'),
++  #  'Linux': ('linux', 'node-linux-x64', 'bin', 'node'),
++  #  'Windows': ('win', 'node.exe'),
++  #}[platform.system()])
+ 
+ 
+ def RunNode(cmd_parts, stdout=None):
diff --git a/srcpkgs/electron13/files/patches/chromium-webrtc-include.patch b/srcpkgs/electron13/files/patches/chromium-webrtc-include.patch
new file mode 100644
index 000000000000..41ba7f2846c2
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-webrtc-include.patch
@@ -0,0 +1,10 @@
+--- a/third_party/webrtc/modules/desktop_capture/linux/window_capturer_x11.cc.orig	2019-02-21 21:21:24.488058990 +0100
++++ a/third_party/webrtc/modules/desktop_capture/linux/window_capturer_x11.cc	2019-02-21 21:21:36.151961064 +0100
+@@ -16,6 +16,7 @@
+ 
+ #include <memory>
+ #include <string>
++#include <string.h>
+ #include <utility>
+ 
+ #include "modules/desktop_capture/desktop_frame.h"
diff --git a/srcpkgs/electron13/files/patches/chromium-webrtc-r0.patch b/srcpkgs/electron13/files/patches/chromium-webrtc-r0.patch
new file mode 100644
index 000000000000..c9b6e086ef00
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-webrtc-r0.patch
@@ -0,0 +1,33 @@
+Upstream: Yes, https://webrtc-review.googlesource.com/9384
+Reason: Fixes musl builds of webrtc
+
+From 7f90e2cceda0458cf56026eb6ccffb961a47804b Mon Sep 17 00:00:00 2001
+From: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com>
+Date: Fri, 13 Oct 2017 15:49:32 +0200
+Subject: [PATCH] IWYU: Include math.h for round(3).
+
+math.h was being implicitly included, which can break the build with
+alternative libc implementations.
+
+Bug: None
+Change-Id: I969b320b65d0f44abb33d3e1036cfbcb859a4952
+Reviewed-on: https://webrtc-review.googlesource.com/9384
+Reviewed-by: Tommi <tommi@webrtc.org>
+Commit-Queue: Raphael Kubo da Costa (rakuco) <raphael.kubo.da.costa@intel.com>
+Cr-Commit-Position: refs/heads/master@{#20292}
+---
+
+--- a/third_party/webrtc/p2p/base/port.cc
++++ a/third_party/webrtc/p2p/base/port.cc
+@@ -10,6 +10,8 @@
+ 
+ #include "p2p/base/port.h"
+ 
++#include <math.h>
++
+ #include <algorithm>
+ #include <vector>
+ 
+-- 
+2.15.0.rc2
+
diff --git a/srcpkgs/electron13/files/patches/chromium-webrtc-size_t.patch b/srcpkgs/electron13/files/patches/chromium-webrtc-size_t.patch
new file mode 100644
index 000000000000..a1fbd43b3013
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-webrtc-size_t.patch
@@ -0,0 +1,10 @@
+--- a/third_party/webrtc/modules/audio_processing/aec3/clockdrift_detector.h	2020-08-10 20:42:29.000000000 +0200
++++ a/third_party/webrtc/modules/audio_processing/aec3/clockdrift_detector.h	2020-09-04 12:47:07.014833633 +0200
+@@ -12,6 +12,7 @@
+ #define MODULES_AUDIO_PROCESSING_AEC3_CLOCKDRIFT_DETECTOR_H_
+ 
+ #include <array>
++#include <cstddef>
+ 
+ namespace webrtc {
+ 
diff --git a/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-libvpx.patch b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-libvpx.patch
new file mode 100644
index 000000000000..6d423d4091c5
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-libvpx.patch
@@ -0,0 +1,72 @@
+Uses generic target for now. To use ppc64le, change --target to ppc64le-gnu
+and add --enable-vsx, and change generic to ppc for the rtcd header.
+
+From 18e6c5c55cfae0cfb458d8210d7bc709360a0e90 Mon Sep 17 00:00:00 2001
+From: q66 <daniel@octaforge.org>
+Date: Wed, 9 Sep 2020 19:08:25 +0200
+Subject: [PATCH] enable generation of ppc64 libvpx bits
+
+this doesn't update the gni file, that's done from
+the template by running the appropriate scripts
+---
+ third_party/libvpx/BUILD.gn        | 4 ++++
+ third_party/libvpx/generate_gni.sh | 9 +++++++++
+ 2 files changed, 13 insertions(+)
+
+diff --git third_party/libvpx/BUILD.gn third_party/libvpx/BUILD.gn
+index 7198e59..3300485 100644
+--- a/third_party/libvpx/BUILD.gn
++++ b/third_party/libvpx/BUILD.gn
+@@ -336,6 +336,8 @@ static_library("libvpx") {
+     } else {
+       sources = libvpx_srcs_arm64
+     }
++  } else if (current_cpu == "ppc64") {
++    sources = libvpx_srcs_ppc64
+   }
+ 
+   configs -= [ "//build/config/compiler:chromium_code" ]
+diff --git third_party/libvpx/generate_gni.sh third_party/libvpx/generate_gni.sh
+index bcf84b0..8a3f4f1 100755
+--- a/third_party/libvpx/generate_gni.sh
++++ b/third_party/libvpx/generate_gni.sh
+@@ -361,6 +361,7 @@ gen_config_files linux/arm-neon-highbd "--target=armv7-linux-gcc ${all_platforms
+ gen_config_files linux/arm64-highbd "--target=armv8-linux-gcc ${all_platforms} ${HIGHBD}"
+ gen_config_files linux/mipsel "--target=mips32-linux-gcc ${all_platforms}"
+ gen_config_files linux/mips64el "--target=mips64-linux-gcc ${all_platforms}"
++gen_config_files linux/ppc64 "--target=generic-gnu $HIGHBD ${all_platforms}"
+ gen_config_files linux/generic "--target=generic-gnu $HIGHBD ${all_platforms}"
+ gen_config_files win/arm64 "--target=arm64-win64-vs15 ${all_platforms} ${HIGHBD}"
+ gen_config_files win/ia32 "--target=x86-win32-vs14 ${all_platforms} ${x86_platforms}"
+@@ -386,6 +387,7 @@ lint_config linux/arm-neon-highbd
+ lint_config linux/arm64-highbd
+ lint_config linux/mipsel
+ lint_config linux/mips64el
++lint_config linux/ppc64
+ lint_config linux/generic
+ lint_config win/arm64
+ lint_config win/ia32
+@@ -415,6 +417,7 @@ gen_rtcd_header linux/arm-neon-highbd armv7
+ gen_rtcd_header linux/arm64-highbd armv8
+ gen_rtcd_header linux/mipsel mipsel
+ gen_rtcd_header linux/mips64el mips64el
++gen_rtcd_header linux/ppc64 generic
+ gen_rtcd_header linux/generic generic
+ gen_rtcd_header win/arm64 armv8
+ gen_rtcd_header win/ia32 x86 "${require_sse2}"
+@@ -500,6 +503,12 @@ if [ -z $ONLY_CONFIGS ]; then
+ 
+   echo "MIPS64 source list is identical to MIPS source list. No need to generate it."
+ 
++  echo "Generate ppc64 source list."
++  config=$(print_config_basic linux/ppc64)
++  make_clean
++  make libvpx_srcs.txt target=libs $config > /dev/null
++  convert_srcs_to_project_files libvpx_srcs.txt libvpx_srcs_ppc64
++
+   echo "Generate NaCl source list."
+   config=$(print_config_basic nacl)
+   make_clean
+-- 
+2.28.0
+
diff --git a/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-support.patch b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-support.patch
new file mode 100644
index 000000000000..a40ed9d5ac73
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-support.patch
@@ -0,0 +1,3707 @@
+commit 2c013a317b1114ef67cdbbc30824b28907b9ea94
+Author: Daniel Kolesa <daniel@octaforge.org>
+Date:   Wed Mar 3 19:08:29 2021 +0100
+
+    ppc64le support
+
+diff --git a/build/download_nacl_toolchains.py b/build/download_nacl_toolchains.py
+index 286a92a27..ec36a85d3 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 35f01d0a4..28f2e7475 100644
+--- a/chrome/installer/linux/BUILD.gn
++++ b/chrome/installer/linux/BUILD.gn
+@@ -94,8 +94,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") {
+@@ -315,7 +313,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 db30ae6d6..9dc09bf53 100644
+--- a/sandbox/features.gni
++++ b/sandbox/features.gni
+@@ -11,7 +11,8 @@ import("//build/config/nacl/config.gni")
+ use_seccomp_bpf = (is_linux || is_chromeos || 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 e9a94b461..cca1a5da5 100644
+--- a/sandbox/linux/BUILD.gn
++++ b/sandbox/linux/BUILD.gn
+@@ -427,6 +427,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 313511f22..0ca3a326f 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 1a407b952..a6aec544e 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 6a1ec2389..f20c582dd 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__)
+@@ -227,7 +228,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
+@@ -245,7 +246,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,
+@@ -285,7 +286,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 01c046dda..7e5a6be82 100644
+--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc	2021-04-15 13:11:10.481579470 -0400
++++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc	2021-04-15 13:12:43.524831376 -0400
+@@ -302,7 +302,7 @@
+ TEST_BASELINE_SIGSYS(__NR_syslog)
+ TEST_BASELINE_SIGSYS(__NR_timer_create)
+ 
+-#if !defined(__aarch64__)
++#if !defined(__aarch64__) && !defined(__powerpc64__)
+ TEST_BASELINE_SIGSYS(__NR_inotify_init)
+ TEST_BASELINE_SIGSYS(__NR_vserver)
+ #endif
+diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+index 2a97d3916..8e81aa6cf 100644
+--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc	2021-04-14 14:41:08.000000000 -0400
++++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc	2021-04-15 13:17:57.808715733 -0400
+@@ -40,7 +40,8 @@
+ #include <sys/ptrace.h>
+ #if (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \
+     !defined(__arm__) && !defined(__aarch64__) &&           \
+-    !defined(PTRACE_GET_THREAD_AREA)
++    !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
+@@ -49,6 +50,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)
+@@ -98,6 +104,15 @@
+ #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
+@@ -239,6 +254,8 @@
+   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);
+@@ -256,7 +273,16 @@
+               F_SETLKW,
+               F_GETLK,
+               F_DUPFD,
+-              F_DUPFD_CLOEXEC),
++              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()))
+@@ -266,7 +292,7 @@
+   // clang-format on
+ }
+ 
+-#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
+@@ -419,7 +445,7 @@
+ #endif
+   return Switch(request)
+       .CASES((
+-#if !defined(__aarch64__)
++#if !defined(__aarch64__) && !defined(__powerpc64__)
+                  PTRACE_GETREGS, PTRACE_GETFPREGS, PTRACE_GET_THREAD_AREA,
+                  PTRACE_GETREGSET,
+ #endif
+diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
+index ba4289f05..9a4d5ab2d 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 642df7207..34f47eb73 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;
+@@ -52,12 +53,14 @@ bool SyscallSets::IsAllowedGettime(int sysno) {
+     case __NR_clock_nanosleep_time64:  // Parameters filtered by RestrictClockID().
+ #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_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:
+@@ -135,7 +138,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))
+@@ -154,7 +157,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
+@@ -168,7 +171,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:
+@@ -178,7 +182,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.
+@@ -203,7 +208,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__)
+@@ -216,11 +222,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__) || \
+@@ -228,6 +235,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;
+@@ -248,7 +257,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;
+@@ -289,7 +299,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
+@@ -340,8 +350,11 @@ 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__)
++#ifndef __powerpc64__
+     case __NR_rt_sigtimedwait_time64:
++#endif
+     case __NR_sigaction:
+     case __NR_sigprocmask:
+     case __NR_sigreturn:
+@@ -357,7 +370,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
+@@ -381,7 +395,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;
+@@ -414,7 +428,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;
+@@ -431,7 +445,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:
+@@ -484,7 +498,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;
+@@ -494,7 +508,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:
+@@ -509,7 +523,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) {
+@@ -523,7 +538,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:
+@@ -548,7 +564,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__) || \
+@@ -578,7 +594,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__)
+@@ -598,26 +615,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
+@@ -673,7 +692,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:
+@@ -685,7 +705,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:
+@@ -701,7 +722,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:
+@@ -734,7 +756,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:
+@@ -750,7 +773,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:
+@@ -785,14 +808,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:
+@@ -826,7 +850,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
+@@ -892,8 +916,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) {
+@@ -925,7 +957,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) {
+@@ -945,7 +978,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
+ }
+@@ -1002,7 +1036,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:
+@@ -1084,18 +1119,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:
+@@ -1103,20 +1142,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 923533ec9..411f72acd 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 e47e98bf5..d53a7ff56 100644
+--- a/sandbox/linux/seccomp-bpf/syscall.cc
++++ b/sandbox/linux/seccomp-bpf/syscall.cc
+@@ -18,7 +18,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
+@@ -310,12 +310,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]);
+ }
+@@ -429,6 +473,8 @@ intptr_t Syscall::Call(int nr,
+     ret = inout;
+   }
+ 
++#elif defined(__powerpc64__)
++  intptr_t ret = SyscallAsm(nr, args);
+ #else
+ #error "Unimplemented architecture"
+ #endif
+@@ -445,8 +491,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 f5b86a73a..5e6c4a068 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 d7b5d8c44..4adc6d0d4 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 fcfd2aa12..f6eb32fb7 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 d72c9d238..77f1d95f5 100644
+--- a/sandbox/linux/syscall_broker/broker_process.cc
++++ b/sandbox/linux/syscall_broker/broker_process.cc
+@@ -169,7 +169,7 @@ bool BrokerProcess::IsSyscallBrokerable(int sysno, bool fast_check) const {
+ #if defined(__NR_fstatat64)
+     case __NR_fstatat64:
+ #endif
+-#if defined(__x86_64__) || defined(__aarch64__)
++#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__)
+     case __NR_newfstatat:
+ #endif
+       return !fast_check || 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 1fa47ed09..39cc9ab53 100644
+--- a/sandbox/linux/system_headers/linux_seccomp.h
++++ b/sandbox/linux/system_headers/linux_seccomp.h
+@@ -41,6 +41,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
+@@ -73,6 +76,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 f5a736761..515b21a5f 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 2b78a0cc3..0a70f5ea5 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 22ce78027..a69b024c2 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 000000000..ccacffe22
+--- /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 000000000..07728e087
+--- /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/sandbox/policy/linux/bpf_renderer_policy_linux.cc b/sandbox/policy/linux/bpf_renderer_policy_linux.cc
+index 2588fc792..d455c4601 100644
+--- a/sandbox/policy/linux/bpf_renderer_policy_linux.cc
++++ b/sandbox/policy/linux/bpf_renderer_policy_linux.cc
+@@ -15,6 +15,11 @@
+ #include "sandbox/linux/system_headers/linux_syscalls.h"
+ #include "sandbox/policy/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 3a807e1e3..5258617a7 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 fcbc9246a..39ae66148 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 17cf9cda9..8ce96bd32 100644
+--- a/third_party/boringssl/BUILD.gn
++++ b/third_party/boringssl/BUILD.gn
+@@ -103,6 +103,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/BUILD.gn b/third_party/breakpad/BUILD.gn
+index 4af3d7bbf..adbf54159 100644
+--- a/third_party/breakpad/BUILD.gn
++++ b/third_party/breakpad/BUILD.gn
+@@ -596,7 +596,6 @@ if (is_linux || is_chromeos || is_android) {
+       "breakpad/src/client/minidump_file_writer.h",
+       "breakpad/src/common/convert_UTF.cc",
+       "breakpad/src/common/convert_UTF.h",
+-      "breakpad/src/common/linux/breakpad_getcontext.S",
+       "breakpad/src/common/linux/elf_core_dump.cc",
+       "breakpad/src/common/linux/elf_core_dump.h",
+       "breakpad/src/common/linux/elfutils.cc",
+@@ -634,6 +633,14 @@ if (is_linux || is_chromeos || is_android) {
+ 
+     libs = [ "dl" ]
+ 
++    if (current_cpu == "ppc64") {
++        defines = [ "HAVE_GETCONTEXT" ]
++    } else {
++        sources += [
++            "breakpad/src/common/linux/breakpad_getcontext.S"
++        ]
++    }
++
+     include_dirs = [
+       ".",
+       "breakpad/src",
+@@ -682,7 +689,6 @@ if (is_linux || is_chromeos || is_android) {
+       "breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc",
+       "breakpad/src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc",
+       "breakpad/src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc",
+-      "breakpad/src/common/linux/breakpad_getcontext_unittest.cc",
+       "breakpad/src/common/linux/elf_core_dump_unittest.cc",
+       "breakpad/src/common/linux/file_id_unittest.cc",
+       "breakpad/src/common/linux/linux_libc_support_unittest.cc",
+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 07d9171a0..9aed4cb36 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 aae1dc13b..03afec7a5 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 fb216fa6d..593aac822 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 6eec1be24..741983a1a 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 7d4100881..c122ac92e 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
+@@ -55,6 +55,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 a6cb5f984..ae16b64d9 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) {
+@@ -708,11 +715,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.
+@@ -733,6 +748,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 f80843ea7..260dd10f7 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 35dcbfd4d..7934370fd 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 fa3c1713a..6ce709e2f 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 6339ac0cd..291af106b 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
+@@ -279,10 +279,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 415068983..b93e4afcf 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 7fd6532ad..199cbfffd 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 7bee160f1..07bb2b81a 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 331f4bb34..3f722947f 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 e3ddb81a6..fa28575ef 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 da71e15dc..12bfb317a 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 32634ef00..2a56948de 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 e3b0b16da..ccd8aa0a4 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
+@@ -48,6 +48,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 std::remove_pointer<fpregset_t>::type 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 d192e5cbb..fc1bfa8d7 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
+@@ -715,6 +715,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 99362945c..c54ba7145 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 fad59f40c..616496d67 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/common/memory_allocator_unittest.cc b/third_party/breakpad/breakpad/src/common/memory_allocator_unittest.cc
+index 5803b90d5..2a1cf14f0 100644
+--- a/third_party/breakpad/breakpad/src/common/memory_allocator_unittest.cc
++++ b/third_party/breakpad/breakpad/src/common/memory_allocator_unittest.cc
+@@ -57,8 +57,9 @@ TEST(PageAllocatorTest, LargeObject) {
+ 
+   EXPECT_EQ(0U, allocator.pages_allocated());
+   uint8_t* p = reinterpret_cast<uint8_t*>(allocator.Alloc(10000));
++  uint64_t expected_pages = 1 + ((10000 - 1) / getpagesize());
+   ASSERT_FALSE(p == NULL);
+-  EXPECT_EQ(3U, allocator.pages_allocated());
++  EXPECT_EQ(expected_pages, allocator.pages_allocated());
+   for (unsigned i = 1; i < 10; ++i) {
+     uint8_t* p = reinterpret_cast<uint8_t*>(allocator.Alloc(i));
+     ASSERT_FALSE(p == NULL);
+diff --git a/third_party/breakpad/breakpad/src/processor/exploitability_linux.cc b/third_party/breakpad/breakpad/src/processor/exploitability_linux.cc
+index 798056dfa..22bd81fff 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 528ee5f21..72764d6c1 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 aade82c99..195aa73f3 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
+@@ -77,6 +77,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__)
+@@ -87,6 +89,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;
+@@ -321,6 +325,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;
+@@ -535,6 +542,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
+@@ -623,6 +662,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 8724b7f32..8e29424ef 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 6ed77a98e..1fd83469a 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 3a3e603cb..3118d9e9f 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 d7e53a493..d89eb9e01 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 d4ab936ee..1d22fc59c 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 object’s 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 3216a906b..a9fcbe9d8 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 0974e3ddf..b71ec5880 100644
+--- a/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc
++++ b/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc
+@@ -135,6 +135,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 7a1b2763c..beda8da9e 100644
+--- a/third_party/crashpad/crashpad/snapshot/capture_memory.cc
++++ b/third_party/crashpad/crashpad/snapshot/capture_memory.cc
+@@ -112,6 +112,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 811a72095..f4f83981d 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 c75b5555e..aeade577a 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 fb23c4679..eebede63c 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 9f46a4897..aa677c4eb 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 d32bd1937..2dd538c2b 100644
+--- a/third_party/crashpad/crashpad/snapshot/linux/debug_rendezvous_test.cc
++++ b/third_party/crashpad/crashpad/snapshot/linux/debug_rendezvous_test.cc
+@@ -192,6 +192,8 @@ void TestAgainstTarget(PtraceConnection* connection) {
+               device == 0 && inode == 0 && mapping_name == "[vdso]";
+ #if defined(ARCH_CPU_X86)
+           static constexpr char kPrefix[] = "linux-gate.so.";
++#elif defined(ARCH_CPU_PPC64)
++          static constexpr char kPrefix[] = "linux-vdso64.so.";
+ #else
+           static constexpr char kPrefix[] = "linux-vdso.so.";
+ #endif
+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 cd40b3b12..6bcf23b6f 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 ea0cd2106..e42df520f 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 c17170b43..b6a714cc6 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 ee246e8bc..9555dce04 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/signal_context.h b/third_party/crashpad/crashpad/snapshot/linux/signal_context.h
+index 110024680..a1f2da259 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 a99da3e4b..03b973083 100644
+--- a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
++++ b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
+@@ -204,6 +204,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
+@@ -219,6 +221,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
+@@ -239,6 +244,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
+@@ -372,6 +380,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/test_modules.cc b/third_party/crashpad/crashpad/snapshot/linux/test_modules.cc
+index b2450c206..7ba78b2ae 100644
+--- a/third_party/crashpad/crashpad/snapshot/linux/test_modules.cc
++++ b/third_party/crashpad/crashpad/snapshot/linux/test_modules.cc
+@@ -110,6 +110,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/thread_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc
+index e3e2bebdd..8ef43752e 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 44cc6f6d9..d4136461e 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
+--- a/third_party/crashpad/crashpad/util/net/http_transport_libcurl.cc
++++ b/third_party/crashpad/crashpad/util/net/http_transport_libcurl.cc
+@@ -236,6 +236,12 @@
+ #elif defined(ARCH_CPU_BIG_ENDIAN)
+     static constexpr char arch[] = "aarch64_be";
+ #endif
++#elif defined(__powerpc64__)
++#if defined(ARCH_CPU_LITTLE_ENDIAN)
++    static constexpr char arch[] = "ppc64le";
++#elif defined(ARCH_CPU_BIG_ENDIAN)
++    static constexpr char arch[] = "ppc64";
++#endif
+ #else
+ #error Port
+ #endif
+diff --git a/third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc b/third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc
+index d3d5ebdfb..3fd730cb5 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/ptracer.cc b/third_party/crashpad/crashpad/util/linux/ptracer.cc
+index 557e0d363..08ae434b8 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 5b55c24a7..dea0d1f39 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 d21a24f19..acc325349 100644
+--- a/third_party/crashpad/crashpad/util/misc/capture_context.h
++++ b/third_party/crashpad/crashpad/util/misc/capture_context.h
+@@ -69,6 +69,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 52215ee5d..b3e4a3ec7 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 cf23c2def..5f264bc92 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 30a2ab21d..60509f21d 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
+@@ -35,6 +35,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
+ }
+ 
+@@ -49,6 +51,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
+ }
+ 
+@@ -63,6 +67,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 54cc2f19f..298b5c993 100644
+--- a/third_party/crashpad/crashpad/util/posix/signals_test.cc
++++ b/third_party/crashpad/crashpad/util/posix/signals_test.cc
+@@ -46,9 +46,9 @@ 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)
+@@ -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 don’t generate a
+     // trap for divide-by-zero, so this doesn’t 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 6b4566fc3..c07f732ad 100644
+--- a/third_party/dav1d/BUILD.gn
++++ b/third_party/dav1d/BUILD.gn
+@@ -184,6 +184,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
+@@ -212,6 +214,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
+@@ -263,6 +267,21 @@ if (current_cpu == "x86" || current_cpu == "x64") {
+       defines = [ "PREFIX" ]
+     }
+ 
++    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
+   }
+ }
+@@ -292,5 +311,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 000000000..9fbbf75cc
+--- /dev/null
++++ b/third_party/dav1d/config/linux/ppc64/config.h
+@@ -0,0 +1,39 @@
++/*
++ * 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 -- Logging is controlled by Chromium
++
++#define ENDIANNESS_BIG 0
++
++#define HAVE_ASM 1
++
++#define HAVE_CLOCK_GETTIME 1
++
++#define HAVE_DLSYM 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 c59cb0821..3060284a8 100644
+--- a/third_party/dav1d/dav1d_generated.gni
++++ b/third_party/dav1d/dav1d_generated.gni
+@@ -82,6 +82,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 9ab5e00b8..ad3feffee 100755
+--- a/third_party/dav1d/generate_source.py	2021-04-15 13:11:10.489579490 -0400
++++ b/third_party/dav1d/generate_source.py	2021-04-15 13:19:08.229913892 -0400
+@@ -57,6 +57,8 @@
+   _WriteArray(fd, "arm64_asm_sources", _Glob("libdav1d/src/arm/64/*.S"))
+   _WriteArray(fd, "arm_template_sources", _Glob("libdav1d/src/arm/*_tmpl.c"))
+ 
++  _WriteArray(fd, "ppc64_template_sources", _Glob("libdav1d/src/ppc/*_tmpl.c"))
++
+   template_sources = _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 0b4bd72f0..a0caa5e71 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/eigen3/BUILD.gn b/third_party/eigen3/BUILD.gn
+index 0d4e184..f2ce484 100644
+--- a/third_party/eigen3/BUILD.gn
++++ b/third_party/eigen3/BUILD.gn
+@@ -22,4 +22,8 @@ config("eigen_includes") {
+     # for this component on Windows on Arm due to compilation errors.
+     defines += [ "EIGEN_DONT_VECTORIZE" ]
+   }
++
++  if (target_cpu == "ppc64") {
++    defines += [ "EIGEN_DONT_VECTORIZE" ]
++  }
+ }
+
+diff --git a/third_party/libaom/BUILD.gn b/third_party/libaom/BUILD.gn
+index 9b065bd..df3af02 100644
+--- a/third_party/libaom/BUILD.gn
++++ b/third_party/libaom/BUILD.gn
+@@ -36,6 +36,8 @@ if (enable_libaom) {
+     } else {
+       cpu_arch_full = "arm"
+     }
++  } else if (current_cpu == "ppc64") {
++    cpu_arch_full = "generic"
+   } else {
+     cpu_arch_full = current_cpu
+   }
+diff --git a/third_party/libgav1/options.gni b/third_party/libgav1/options.gni
+index 11af801..4b13d05 100644
+--- a/third_party/libgav1/options.gni
++++ b/third_party/libgav1/options.gni
+@@ -12,5 +12,5 @@ declare_args() {
+       is_chromeos_ash && (target_cpu == "arm" || target_cpu == "arm64")
+   use_libgav1_parser =
+       (is_chromeos || is_linux || is_win) &&
+-      (target_cpu == "x86" || target_cpu == "x64" || target_cpu == "arm64")
++      (target_cpu == "x86" || target_cpu == "x64" || target_cpu == "arm64" || target_cpu == "ppc64")
+ }
+diff --git a/third_party/lss/linux_syscall_support.h b/third_party/lss/linux_syscall_support.h
+index e4ac22644..1c57015db 100644
+--- a/third_party/lss/linux_syscall_support.h
++++ b/third_party/lss/linux_syscall_support.h
+@@ -3947,7 +3947,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,
+@@ -4058,7 +4058,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/pdfium/third_party/libpng16/pngpriv.h b/third_party/pdfium/third_party/libpng16/pngpriv.h
+index 583c26f..e03d697 100644
+--- a/third_party/pdfium/third_party/libpng16/pngpriv.h
++++ b/third_party/pdfium/third_party/libpng16/pngpriv.h
+@@ -196,11 +196,7 @@
+ #endif
+ 
+ #ifndef PNG_POWERPC_VSX_OPT
+-#  if defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__)
+-#     define PNG_POWERPC_VSX_OPT 2
+-#  else
+-#     define PNG_POWERPC_VSX_OPT 0
+-#  endif
++#  define PNG_POWERPC_VSX_OPT 0
+ #endif
+ 
+ #ifndef PNG_INTEL_SSE_OPT
+diff --git a/third_party/pffft/src/pffft.c b/third_party/pffft/src/pffft.c
+index bdac4d784..51e0f2cac 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 ec3e56964..4cf8999a2 100644
+--- a/third_party/skia/src/sksl/SkSLString.cpp
++++ b/third_party/skia/src/sksl/SkSLString.cpp
+@@ -234,7 +234,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());
+ }
+ 
+ bool stod(const StringFragment& s, SKSL_FLOAT* value) {
+diff --git a/third_party/sqlite/src/amalgamation/sqlite3.c b/third_party/sqlite/src/amalgamation/sqlite3.c
+index 6b4a7899d..b8c7fe414 100644
+--- a/third_party/sqlite/src/amalgamation/sqlite3.c
++++ b/third_party/sqlite/src/amalgamation/sqlite3.c
+@@ -14474,7 +14474,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 d30c9b7de..cf75a69d9 100644
+--- a/third_party/sqlite/src/amalgamation_dev/sqlite3.c
++++ b/third_party/sqlite/src/amalgamation_dev/sqlite3.c
+@@ -14487,7 +14487,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 f5b57a5e2..80a2d0ad8 100644
+--- a/third_party/sqlite/src/ext/rtree/rtree.c
++++ b/third_party/sqlite/src/ext/rtree/rtree.c
+@@ -450,7 +450,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 245070d4f..b25164e95 100644
+--- a/third_party/sqlite/src/src/sqliteInt.h
++++ b/third_party/sqlite/src/src/sqliteInt.h
+@@ -877,7 +877,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 4f0c5430c..54ee0829e 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 = 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 be2367b85..be4ee4233 100644
+--- a/third_party/webrtc/rtc_base/system/arch.h
++++ b/third_party/webrtc/rtc_base/system/arch.h
+@@ -79,6 +79,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/v8/BUILD.gn b/v8/BUILD.gn
+index f39529a3a..e84fc449e 100644
+--- a/v8/BUILD.gn
++++ b/v8/BUILD.gn
+@@ -850,6 +850,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/ui/gl/features.gni b/ui/gl/features.gni
+index 5fda9b6..3d2dd8b 100644
+--- a/ui/gl/features.gni
++++ b/ui/gl/features.gni
+@@ -32,5 +32,6 @@ declare_args() {
+                         (is_mac && use_egl) || is_chromeos_ash || 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")
+ }
+diff --git a/v8/test/BUILD.gn b/v8/test/BUILD.gn
+index fb872ad39..45fc585dd 100644
+--- a/v8/test/BUILD.gn
++++ b/v8/test/BUILD.gn
+@@ -36,7 +36,7 @@ group("gn_all") {
+       "benchmarks/cpp:gn_all",
+       "cctest:cctest",
+       "cctest:generate-bytecode-expectations",
+-      "unittests:unittests",
++      #"unittests:unittests",
+     ]
+   }
+ }
+@@ -83,7 +83,7 @@
+     "message:v8_message",
+     "mjsunit:v8_mjsunit",
+     "mkgrokdump:mkgrokdump",
+-    "unittests:unittests",
++    #"unittests:unittests",
+     "webkit:v8_webkit",
+   ]
+ 
+@@ -108,7 +108,7 @@
+     "message:v8_message",
+     "mjsunit:v8_mjsunit",
+     "mkgrokdump:mkgrokdump",
+-    "unittests:unittests",
++    #"unittests:unittests",
+   ]
+ 
+   if (v8_enable_webassembly) {
diff --git a/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-swiftshader.patch b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-swiftshader.patch
new file mode 100644
index 000000000000..df453f491d8c
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-swiftshader.patch
@@ -0,0 +1,18 @@
+--- a/third_party/swiftshader/third_party/llvm-10.0/BUILD.gn
++++ b/third_party/swiftshader/third_party/llvm-10.0/BUILD.gn
+@@ -574,6 +574,7 @@ swiftshader_llvm_source_set("swiftshader
+     "llvm/lib/MC/MCAsmInfoCOFF.cpp",
+     "llvm/lib/MC/MCAsmInfoDarwin.cpp",
+     "llvm/lib/MC/MCAsmInfoELF.cpp",
++    "llvm/lib/MC/MCAsmInfoXCOFF.cpp",
+     "llvm/lib/MC/MCAsmMacro.cpp",
+     "llvm/lib/MC/MCAsmStreamer.cpp",
+     "llvm/lib/MC/MCAssembler.cpp",
+@@ -629,6 +630,7 @@ swiftshader_llvm_source_set("swiftshader
+     "llvm/lib/MC/MCWinCOFFStreamer.cpp",
+     "llvm/lib/MC/MCWinEH.cpp",
+     "llvm/lib/MC/MCXCOFFStreamer.cpp",
++    "llvm/lib/MC/MCXCOFFObjectTargetWriter.cpp",
+     "llvm/lib/MC/MachObjectWriter.cpp",
+     "llvm/lib/MC/StringTableBuilder.cpp",
+     "llvm/lib/MC/SubtargetFeature.cpp",
diff --git a/srcpkgs/electron13/files/patches/electron-Add-a-script-to-list-patch-targets.patch.patch b/srcpkgs/electron13/files/patches/electron-Add-a-script-to-list-patch-targets.patch.patch
new file mode 100644
index 000000000000..916dba9dc3bc
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/electron-Add-a-script-to-list-patch-targets.patch.patch
@@ -0,0 +1,42 @@
+From ff4122f236b70c272c746d0c336cdbd588d78cd1 Mon Sep 17 00:00:00 2001
+From: Elvis Pranskevichus <elvis@magic.io>
+Date: Thu, 12 Dec 2019 16:12:18 -0500
+Subject: [PATCH] Add a script to list patch targets
+
+---
+ script/list_patch_targets.py | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+ create mode 100755 script/list_patch_targets.py
+
+diff --git a/script/list_patch_targets.py b/script/list_patch_targets.py
+new file mode 100755
+index 000000000..55173bac9
+--- /dev/null
++++ b/script/list_patch_targets.py
+@@ -0,0 +1,23 @@
++#!/usr/bin/env python
++
++import argparse
++import json
++
++
++def parse_args():
++  parser = argparse.ArgumentParser(description='Apply Electron patches')
++  parser.add_argument('config', nargs='+',
++                      type=argparse.FileType('r'),
++                      help='patches\' config(s) in the JSON format')
++  return parser.parse_args()
++
++
++def main():
++  configs = parse_args().config
++  for config_json in configs:
++    for patch_dir, repo in json.load(config_json).iteritems():
++      print(repo)
++
++
++if __name__ == '__main__':
++  main()
+-- 
+2.23.0
+
diff --git a/srcpkgs/electron13/files/patches/electron-Build-fixes.patch.patch b/srcpkgs/electron13/files/patches/electron-Build-fixes.patch.patch
new file mode 100644
index 000000000000..298bfa9bcb2b
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/electron-Build-fixes.patch.patch
@@ -0,0 +1,47 @@
+diff --git a/build/args/release.gn b/build/args/release.gn
+index e5017f6e1..59207b389 100644
+--- a/build/args/release.gn
++++ b/build/args/release.gn
+@@ -1,6 +1,4 @@
+ import("all.gn")
+-is_component_build = false
+-is_official_build = true
+ 
+ # This may be guarded behind is_chrome_branded alongside
+ # proprietary_codecs https://webrtc-review.googlesource.com/c/src/+/36321,
+@@ -8,9 +6,3 @@ is_official_build = true
+ # The initialization of the decoder depends on whether ffmpeg has
+ # been built with H.264 support.
+ rtc_use_h264 = proprietary_codecs
+-
+-# By default, Electron builds ffmpeg with proprietary codecs enabled. In order
+-# to facilitate users who don't want to ship proprietary codecs in ffmpeg, or
+-# who have an LGPL requirement to ship ffmpeg as a dynamically linked library,
+-# we build ffmpeg as a shared library.
+-is_component_ffmpeg = true
+diff --git a/build/npm.gni b/build/npm.gni
+index a1987d095..fb33a14c3 100644
+--- a/build/npm.gni
++++ b/build/npm.gni
+@@ -35,7 +35,6 @@ template("npm_action") {
+     if (!defined(deps)) {
+       deps = []
+     }
+-    deps += [ ":npm_pre_flight_" + target_name ]
+ 
+     script = "//electron/build/npm-run.py"
+     args = [
+diff --git a/patches/node/fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch b/patches/node/fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch
+index 0dc9916be..7eaa46bf5 100644
+--- a/patches/node/fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch
++++ b/patches/node/fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch
+@@ -30,7 +30,7 @@
+ +    # these values being accurate.
+ +    'build_v8_with_gn': 'false',
+ +    'enable_lto%': 'false',
+-+
+++    'openssl_fips': '',
+      'conditions': [
+        ['target_arch=="arm64"', {
+          # Disabled pending https://github.com/nodejs/node/issues/23913.
+
diff --git a/srcpkgs/electron13/files/patches/electron-dont-assume-python-is-python2.patch b/srcpkgs/electron13/files/patches/electron-dont-assume-python-is-python2.patch
new file mode 100644
index 000000000000..fb134748025b
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/electron-dont-assume-python-is-python2.patch
@@ -0,0 +1,17 @@
+--- a/build/zip.py.orig	2020-04-27 17:59:53.499281667 +0200
++++ b/build/zip.py	2020-04-27 17:59:57.655839143 +0200
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python2
+ from __future__ import print_function
+ import os
+ import subprocess
+
+--- a/build/npm-run.py.orig	2020-04-27 17:59:50.829351807 +0200
++++ b/build/npm-run.py	2020-04-27 18:00:02.702373256 +0200
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python2
+ from __future__ import print_function
+ import os
+ import subprocess
diff --git a/srcpkgs/electron13/files/patches/electron-exclude-content-test-patches.patch b/srcpkgs/electron13/files/patches/electron-exclude-content-test-patches.patch
new file mode 100644
index 000000000000..456223644278
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/electron-exclude-content-test-patches.patch
@@ -0,0 +1,10 @@
+--- a/script/apply_all_patches.py	2020-08-22 17:46:41.796707506 +0200
++++ -	2020-08-22 17:47:05.887813512 +0200
+@@ -14,6 +14,7 @@
+   for patch_dir, repo in dirs.items():
+     git.import_patches(repo=repo, patch_data=patch_from_dir(patch_dir),
+       threeway=threeway is not None,
++      exclude=['test/mjsunit/**', 'content/test/**', 'test/cctest/**', 'test/unittests/**', 'third_party/blink/web_tests/**'],
+       committer_name="Electron Scripts", committer_email="scripts@electron")
+ 
+ 
diff --git a/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.cc b/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.cc
new file mode 100644
index 000000000000..2c7aa8efa66f
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.cc
@@ -0,0 +1,148 @@
+// Copyright (c) 2012 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.
+
+#include "base/metrics/histogram_macros.h"
+#include "base/memory/ptr_util.h"
+
+#include "media/audio/openbsd/audio_manager_openbsd.h"
+
+#include "media/audio/audio_device_description.h"
+#include "media/audio/audio_output_dispatcher.h"
+#include "media/audio/sndio/sndio_input.h"
+#include "media/audio/sndio/sndio_output.h"
+#include "media/base/limits.h"
+#include "media/base/media_switches.h"
+
+namespace media {
+
+// Maximum number of output streams that can be open simultaneously.
+static const int kMaxOutputStreams = 4;
+
+// Default sample rate for input and output streams.
+static const int kDefaultSampleRate = 48000;
+
+void AddDefaultDevice(AudioDeviceNames* device_names) {
+  DCHECK(device_names->empty());
+  device_names->push_front(AudioDeviceName::CreateDefault());
+}
+
+bool AudioManagerOpenBSD::HasAudioOutputDevices() {
+  return true;
+}
+
+bool AudioManagerOpenBSD::HasAudioInputDevices() {
+  return true;
+}
+
+void AudioManagerOpenBSD::GetAudioInputDeviceNames(
+    AudioDeviceNames* device_names) {
+  DCHECK(device_names->empty());
+  AddDefaultDevice(device_names);
+}
+
+void AudioManagerOpenBSD::GetAudioOutputDeviceNames(
+    AudioDeviceNames* device_names) {
+  AddDefaultDevice(device_names);
+}
+
+const char* AudioManagerOpenBSD::GetName() {
+  return "SNDIO";
+}
+
+AudioParameters AudioManagerOpenBSD::GetInputStreamParameters(
+    const std::string& device_id) {
+  static const int kDefaultInputBufferSize = 1024;
+
+  int user_buffer_size = GetUserBufferSize();
+  int buffer_size = user_buffer_size ?
+      user_buffer_size : kDefaultInputBufferSize;
+
+  return AudioParameters(
+      AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
+      kDefaultSampleRate, buffer_size);
+}
+
+AudioManagerOpenBSD::AudioManagerOpenBSD(std::unique_ptr<AudioThread> audio_thread,
+                                         AudioLogFactory* audio_log_factory)
+    : AudioManagerBase(std::move(audio_thread),
+                       audio_log_factory) {
+  DLOG(WARNING) << "AudioManagerOpenBSD";
+  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
+}
+
+AudioManagerOpenBSD::~AudioManagerOpenBSD() {
+  Shutdown();
+}
+
+AudioOutputStream* AudioManagerOpenBSD::MakeLinearOutputStream(
+    const AudioParameters& params,
+    const LogCallback& log_callback) {
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
+  return MakeOutputStream(params);
+}
+
+AudioOutputStream* AudioManagerOpenBSD::MakeLowLatencyOutputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+  return MakeOutputStream(params);
+}
+
+AudioInputStream* AudioManagerOpenBSD::MakeLinearInputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
+  return MakeInputStream(params);
+}
+
+AudioInputStream* AudioManagerOpenBSD::MakeLowLatencyInputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+  return MakeInputStream(params);
+}
+
+AudioParameters AudioManagerOpenBSD::GetPreferredOutputStreamParameters(
+    const std::string& output_device_id,
+    const AudioParameters& input_params) {
+  // TODO(tommi): Support |output_device_id|.
+  DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
+  static const int kDefaultOutputBufferSize = 2048;
+
+  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
+  int sample_rate = kDefaultSampleRate;
+  int buffer_size = kDefaultOutputBufferSize;
+  if (input_params.IsValid()) {
+    sample_rate = input_params.sample_rate();
+    channel_layout = input_params.channel_layout();
+    buffer_size = std::min(buffer_size, input_params.frames_per_buffer());
+  }
+
+  int user_buffer_size = GetUserBufferSize();
+  if (user_buffer_size)
+    buffer_size = user_buffer_size;
+
+  return AudioParameters(
+      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
+      sample_rate, buffer_size);
+}
+
+AudioInputStream* AudioManagerOpenBSD::MakeInputStream(
+    const AudioParameters& params) {
+  DLOG(WARNING) << "MakeInputStream";
+  return new SndioAudioInputStream(this,
+             AudioDeviceDescription::kDefaultDeviceId, params);
+}
+
+AudioOutputStream* AudioManagerOpenBSD::MakeOutputStream(
+    const AudioParameters& params) {
+  DLOG(WARNING) << "MakeOutputStream";
+  return new SndioAudioOutputStream(params, this);
+}
+
+}  // namespace media
diff --git a/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.h b/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.h
new file mode 100644
index 000000000000..8c99db966d65
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2012 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 MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
+#define MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
+
+#include <set>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread.h"
+#include "media/audio/audio_manager_base.h"
+
+namespace media {
+
+class MEDIA_EXPORT AudioManagerOpenBSD : public AudioManagerBase {
+ public:
+  AudioManagerOpenBSD(std::unique_ptr<AudioThread> audio_thread,
+                   AudioLogFactory* audio_log_factory);
+  ~AudioManagerOpenBSD() override;
+
+  // Implementation of AudioManager.
+  bool HasAudioOutputDevices() override;
+  bool HasAudioInputDevices() override;
+  void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
+  void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override;
+  AudioParameters GetInputStreamParameters(
+      const std::string& device_id) override;
+  const char* GetName() override;
+
+  // Implementation of AudioManagerBase.
+  AudioOutputStream* MakeLinearOutputStream(
+      const AudioParameters& params,
+      const LogCallback& log_callback) override;
+  AudioOutputStream* MakeLowLatencyOutputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+  AudioInputStream* MakeLinearInputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+  AudioInputStream* MakeLowLatencyInputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+
+ protected:
+  AudioParameters GetPreferredOutputStreamParameters(
+      const std::string& output_device_id,
+      const AudioParameters& input_params) override;
+
+ private:
+  // Called by MakeLinearOutputStream and MakeLowLatencyOutputStream.
+  AudioOutputStream* MakeOutputStream(const AudioParameters& params);
+  AudioInputStream* MakeInputStream(const AudioParameters& params);
+
+  DISALLOW_COPY_AND_ASSIGN(AudioManagerOpenBSD);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
diff --git a/srcpkgs/electron13/files/sndio-files/sndio_input.cc b/srcpkgs/electron13/files/sndio-files/sndio_input.cc
new file mode 100644
index 000000000000..ef5439b49a07
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/sndio_input.cc
@@ -0,0 +1,200 @@
+// Copyright 2013 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.
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/audio/openbsd/audio_manager_openbsd.h"
+#include "media/audio/audio_manager.h"
+#include "media/audio/sndio/sndio_input.h"
+
+namespace media {
+
+static const SampleFormat kSampleFormat = kSampleFormatS16;
+
+void SndioAudioInputStream::OnMoveCallback(void *arg, int delta)
+{
+  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
+
+  self->hw_delay += delta;
+}
+
+void *SndioAudioInputStream::ThreadEntry(void *arg) {
+  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
+
+  self->ThreadLoop();
+  return NULL;
+}
+
+SndioAudioInputStream::SndioAudioInputStream(AudioManagerBase* manager,
+                                             const std::string& device_name,
+                                             const AudioParameters& params)
+    : manager(manager),
+      params(params),
+      audio_bus(AudioBus::Create(params)),
+      state(kClosed) {
+}
+
+SndioAudioInputStream::~SndioAudioInputStream() {
+  if (state != kClosed)
+    Close();
+}
+
+bool SndioAudioInputStream::Open() {
+  struct sio_par par;
+  int sig;
+
+  if (state != kClosed)
+    return false;
+
+  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
+      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
+    LOG(WARNING) << "Unsupported audio format.";
+    return false;
+  }
+
+  sio_initpar(&par);
+  par.rate = params.sample_rate();
+  par.rchan = params.channels();
+  par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
+  par.bps = par.bits / 8;
+  par.sig = sig = par.bits != 8 ? 1 : 0;
+  par.le = SIO_LE_NATIVE;
+  par.appbufsz = params.frames_per_buffer();
+
+  hdl = sio_open(SIO_DEVANY, SIO_REC, 0);
+
+  if (hdl == NULL) {
+    LOG(ERROR) << "Couldn't open audio device.";
+    return false;
+  }
+
+  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
+    LOG(ERROR) << "Couldn't set audio parameters.";
+    goto bad_close;
+  }
+
+  if (par.rate  != (unsigned int)params.sample_rate() ||
+      par.rchan != (unsigned int)params.channels() ||
+      par.bits  != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
+      par.sig   != (unsigned int)sig ||
+      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
+      (par.bits != par.bps * 8)) {
+    LOG(ERROR) << "Unsupported audio parameters.";
+    goto bad_close;
+  }
+  state = kStopped;
+  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
+  sio_onmove(hdl, &OnMoveCallback, this);
+  return true;
+bad_close:
+  sio_close(hdl);
+  return false;
+}
+
+void SndioAudioInputStream::Start(AudioInputCallback* cb) {
+
+  StartAgc();
+
+  state = kRunning;
+  hw_delay = 0;
+  callback = cb;
+  sio_start(hdl);
+  if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
+    LOG(ERROR) << "Failed to create real-time thread for recording.";
+    sio_stop(hdl);
+    state = kStopped;
+  }
+}
+
+void SndioAudioInputStream::Stop() {
+
+  if (state == kStopped)
+    return;
+
+  state = kStopWait;
+  pthread_join(thread, NULL);
+  sio_stop(hdl);
+  state = kStopped;
+
+  StopAgc();
+}
+
+void SndioAudioInputStream::Close() {
+
+  if (state == kClosed)
+    return;
+
+  if (state == kRunning)
+    Stop();
+
+  state = kClosed;
+  delete [] buffer;
+  sio_close(hdl);
+
+  manager->ReleaseInputStream(this);
+}
+
+double SndioAudioInputStream::GetMaxVolume() {
+  // Not supported
+  return 0.0;
+}
+
+void SndioAudioInputStream::SetVolume(double volume) {
+  // Not supported. Do nothing.
+}
+
+double SndioAudioInputStream::GetVolume() {
+  // Not supported.
+  return 0.0;
+}
+
+bool SndioAudioInputStream::IsMuted() {
+  // Not supported.
+  return false;
+}
+
+void SndioAudioInputStream::SetOutputDeviceForAec(
+    const std::string& output_device_id) {
+  // Not supported.
+}
+
+void SndioAudioInputStream::ThreadLoop(void) {
+  size_t todo, n;
+  char *data;
+  unsigned int nframes;
+  double normalized_volume = 0.0;
+
+  nframes = audio_bus->frames();
+
+  while (state == kRunning && !sio_eof(hdl)) {
+
+    GetAgcVolume(&normalized_volume);
+
+    // read one block
+    todo = nframes * params.GetBytesPerFrame(kSampleFormat);
+    data = buffer;
+    while (todo > 0) {
+      n = sio_read(hdl, data, todo);
+      if (n == 0)
+        return;	// unrecoverable I/O error
+      todo -= n;
+      data += n;
+    }
+    hw_delay -= nframes;
+
+    // convert frames count to TimeDelta
+    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
+      params.sample_rate());
+
+    // push into bus
+    audio_bus->FromInterleaved(buffer, nframes, SampleFormatToBytesPerChannel(kSampleFormat));
+
+    // invoke callback
+    callback->OnData(audio_bus.get(), base::TimeTicks::Now() - delay, 1.);
+  }
+}
+
+}  // namespace media
diff --git a/srcpkgs/electron13/files/sndio-files/sndio_input.h b/srcpkgs/electron13/files/sndio-files/sndio_input.h
new file mode 100644
index 000000000000..d868e0469db5
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/sndio_input.h
@@ -0,0 +1,91 @@
+// Copyright 2013 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 MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
+#define MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
+
+#include <stdint.h>
+#include <string>
+#include <sndio.h>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "media/audio/agc_audio_stream.h"
+#include "media/audio/audio_io.h"
+#include "media/audio/audio_device_description.h"
+#include "media/base/audio_parameters.h"
+
+namespace media {
+
+class AudioManagerBase;
+
+// Implementation of AudioOutputStream using sndio(7)
+class SndioAudioInputStream : public AgcAudioStream<AudioInputStream> {
+ public:
+  // Pass this to the constructor if you want to attempt auto-selection
+  // of the audio recording device.
+  static const char kAutoSelectDevice[];
+
+  // Create a PCM Output stream for the SNDIO device identified by
+  // |device_name|. If unsure of what to use for |device_name|, use
+  // |kAutoSelectDevice|.
+  SndioAudioInputStream(AudioManagerBase* audio_manager,
+                     const std::string& device_name,
+                     const AudioParameters& params);
+
+  ~SndioAudioInputStream() override;
+
+  // Implementation of AudioInputStream.
+  bool Open() override;
+  void Start(AudioInputCallback* callback) override;
+  void Stop() override;
+  void Close() override;
+  double GetMaxVolume() override;
+  void SetVolume(double volume) override;
+  double GetVolume() override;
+  bool IsMuted() override;
+  void SetOutputDeviceForAec(const std::string& output_device_id) override;
+
+ private:
+
+  enum StreamState {
+    kClosed,            // Not opened yet
+    kStopped,           // Device opened, but not started yet
+    kRunning,           // Started, device playing
+    kStopWait           // Stopping, waiting for the real-time thread to exit
+  };
+
+  // C-style call-backs
+  static void OnMoveCallback(void *arg, int delta);
+  static void* ThreadEntry(void *arg);
+
+  // Continuously moves data from the device to the consumer
+  void ThreadLoop();
+  // Our creator, the audio manager needs to be notified when we close.
+  AudioManagerBase* manager;
+  // Parameters of the source
+  AudioParameters params;
+  // We store data here for consumer
+  std::unique_ptr<AudioBus> audio_bus;
+  // Call-back that consumes recorded data
+  AudioInputCallback* callback;  // Valid during a recording session.
+  // Handle of the audio device
+  struct sio_hdl* hdl;
+  // Current state of the stream
+  enum StreamState state;
+  // High priority thread running ThreadLoop()
+  pthread_t thread;
+  // Number of frames buffered in the hardware
+  int hw_delay;
+  // Temporary buffer where data is stored sndio-compatible format
+  char* buffer;
+
+  DISALLOW_COPY_AND_ASSIGN(SndioAudioInputStream);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
diff --git a/srcpkgs/electron13/files/sndio-files/sndio_output.cc b/srcpkgs/electron13/files/sndio-files/sndio_output.cc
new file mode 100644
index 000000000000..a6719f9aac8d
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/sndio_output.cc
@@ -0,0 +1,183 @@
+// Copyright (c) 2012 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.
+
+#include "base/logging.h"
+#include "base/time/time.h"
+#include "base/time/default_tick_clock.h"
+#include "media/audio/audio_manager_base.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/audio/sndio/sndio_output.h"
+
+namespace media {
+
+static const SampleFormat kSampleFormat = kSampleFormatS16;
+
+void SndioAudioOutputStream::OnMoveCallback(void *arg, int delta) {
+  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
+
+  self->hw_delay -= delta;
+}
+
+void SndioAudioOutputStream::OnVolCallback(void *arg, unsigned int vol) {
+  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
+
+  self->vol = vol;
+}
+
+void *SndioAudioOutputStream::ThreadEntry(void *arg) {
+  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
+
+  self->ThreadLoop();
+  return NULL;
+}
+
+SndioAudioOutputStream::SndioAudioOutputStream(const AudioParameters& params,
+                                               AudioManagerBase* manager)
+    : manager(manager),
+      params(params),
+      audio_bus(AudioBus::Create(params)),
+      state(kClosed),
+      mutex(PTHREAD_MUTEX_INITIALIZER) {
+}
+
+SndioAudioOutputStream::~SndioAudioOutputStream() {
+  if (state != kClosed)
+    Close();
+}
+
+bool SndioAudioOutputStream::Open() {
+  struct sio_par par;
+  int sig;
+
+  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
+      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
+    LOG(WARNING) << "Unsupported audio format.";
+    return false;
+  }
+  sio_initpar(&par);
+  par.rate = params.sample_rate();
+  par.pchan = params.channels();
+  par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
+  par.bps = par.bits / 8;
+  par.sig = sig = par.bits != 8 ? 1 : 0;
+  par.le = SIO_LE_NATIVE;
+  par.appbufsz = params.frames_per_buffer();
+
+  hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
+  if (hdl == NULL) {
+    LOG(ERROR) << "Couldn't open audio device.";
+    return false;
+  }
+  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
+    LOG(ERROR) << "Couldn't set audio parameters.";
+    goto bad_close;
+  }
+  if (par.rate  != (unsigned int)params.sample_rate() ||
+      par.pchan != (unsigned int)params.channels() ||
+      par.bits  != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
+      par.sig   != (unsigned int)sig ||
+      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
+      (par.bits != par.bps * 8)) {
+    LOG(ERROR) << "Unsupported audio parameters.";
+    goto bad_close;
+  }
+  state = kStopped;
+  volpending = 0;
+  vol = 0;
+  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
+  sio_onmove(hdl, &OnMoveCallback, this);
+  sio_onvol(hdl, &OnVolCallback, this);
+  return true;
+ bad_close:
+  sio_close(hdl);
+  return false;
+}
+
+void SndioAudioOutputStream::Close() {
+  if (state == kClosed)
+    return;
+  if (state == kRunning)
+    Stop();
+  state = kClosed;
+  delete [] buffer;
+  sio_close(hdl);
+  manager->ReleaseOutputStream(this);  // Calls the destructor
+}
+
+void SndioAudioOutputStream::Start(AudioSourceCallback* callback) {
+  state = kRunning;
+  hw_delay = 0;
+  source = callback;
+  sio_start(hdl);
+  if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
+    LOG(ERROR) << "Failed to create real-time thread.";
+    sio_stop(hdl);
+    state = kStopped;
+  }
+}
+
+void SndioAudioOutputStream::Stop() {
+  if (state == kStopped)
+    return;
+  state = kStopWait;
+  pthread_join(thread, NULL);
+  sio_stop(hdl);
+  state = kStopped;
+}
+
+void SndioAudioOutputStream::SetVolume(double v) {
+  pthread_mutex_lock(&mutex);
+  vol = v * SIO_MAXVOL;
+  volpending = 1;
+  pthread_mutex_unlock(&mutex);
+}
+
+void SndioAudioOutputStream::GetVolume(double* v) {
+  pthread_mutex_lock(&mutex);
+  *v = vol * (1. / SIO_MAXVOL);
+  pthread_mutex_unlock(&mutex);
+}
+
+// This stream is always used with sub second buffer sizes, where it's
+// sufficient to simply always flush upon Start().
+void SndioAudioOutputStream::Flush() {}
+
+void SndioAudioOutputStream::ThreadLoop(void) {
+  int avail, count, result;
+
+  while (state == kRunning) {
+    // Update volume if needed
+    pthread_mutex_lock(&mutex);
+    if (volpending) {
+      volpending = 0;
+      sio_setvol(hdl, vol);
+    }
+    pthread_mutex_unlock(&mutex);
+
+    // Get data to play
+    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
+	params.sample_rate());
+    count = source->OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get());
+    audio_bus->ToInterleaved(count, SampleFormatToBytesPerChannel(kSampleFormat), buffer);
+    if (count == 0) {
+      // We have to submit something to the device
+      count = audio_bus->frames();
+      memset(buffer, 0, count * params.GetBytesPerFrame(kSampleFormat));
+      LOG(WARNING) << "No data to play, running empty cycle.";
+    }
+
+    // Submit data to the device
+    avail = count * params.GetBytesPerFrame(kSampleFormat);
+    result = sio_write(hdl, buffer, avail);
+    if (result == 0) {
+      LOG(WARNING) << "Audio device disconnected.";
+      break;
+    }
+
+    // Update hardware pointer
+    hw_delay += count;
+  }
+}
+
+}  // namespace media
diff --git a/srcpkgs/electron13/files/sndio-files/sndio_output.h b/srcpkgs/electron13/files/sndio-files/sndio_output.h
new file mode 100644
index 000000000000..ead220ca96e7
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/sndio_output.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2012 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 MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
+#define MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
+
+#include <pthread.h>
+#include <sndio.h>
+
+#include "base/time/tick_clock.h"
+#include "base/time/time.h"
+#include "media/audio/audio_io.h"
+
+namespace media {
+
+class AudioManagerBase;
+
+// Implementation of AudioOutputStream using sndio(7)
+class SndioAudioOutputStream : public AudioOutputStream {
+ public:
+  // The manager is creating this object
+  SndioAudioOutputStream(const AudioParameters& params,
+                         AudioManagerBase* manager);
+  virtual ~SndioAudioOutputStream();
+
+  // Implementation of AudioOutputStream.
+  bool Open() override;
+  void Close() override;
+  void Start(AudioSourceCallback* callback) override;
+  void Stop() override;
+  void SetVolume(double volume) override;
+  void GetVolume(double* volume) override;
+  void Flush() override;
+
+  friend void sndio_onmove(void *arg, int delta);
+  friend void sndio_onvol(void *arg, unsigned int vol);
+  friend void *sndio_threadstart(void *arg);
+
+ private:
+  enum StreamState {
+    kClosed,            // Not opened yet
+    kStopped,           // Device opened, but not started yet
+    kRunning,           // Started, device playing
+    kStopWait           // Stopping, waiting for the real-time thread to exit
+  };
+
+  // C-style call-backs
+  static void OnMoveCallback(void *arg, int delta);
+  static void OnVolCallback(void *arg, unsigned int vol);
+  static void* ThreadEntry(void *arg);
+
+  // Continuously moves data from the producer to the device
+  void ThreadLoop(void);
+
+  // Our creator, the audio manager needs to be notified when we close.
+  AudioManagerBase* manager;
+  // Parameters of the source
+  AudioParameters params;
+  // Source stores data here
+  std::unique_ptr<AudioBus> audio_bus;
+  // Call-back that produces data to play
+  AudioSourceCallback* source;
+  // Handle of the audio device
+  struct sio_hdl* hdl;
+  // Current state of the stream
+  enum StreamState state;
+  // High priority thread running ThreadLoop()
+  pthread_t thread;
+  // Protects vol, volpending and hw_delay
+  pthread_mutex_t mutex;
+  // Current volume in the 0..SIO_MAXVOL range
+  int vol;
+  // Set to 1 if volumes must be refreshed in the realtime thread
+  int volpending;
+  // Number of frames buffered in the hardware
+  int hw_delay;
+  // Temporary buffer where data is stored sndio-compatible format
+  char* buffer;
+
+  DISALLOW_COPY_AND_ASSIGN(SndioAudioOutputStream);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
diff --git a/srcpkgs/electron13/files/sndio-patches/media_audio_linux_audio_manager_linux.cc.patch b/srcpkgs/electron13/files/sndio-patches/media_audio_linux_audio_manager_linux.cc.patch
new file mode 100644
index 000000000000..cf8e81b11d67
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-patches/media_audio_linux_audio_manager_linux.cc.patch
@@ -0,0 +1,43 @@
+diff --git a/chromium/media/audio/linux/audio_manager_linux.cc b/chromium/media/audio/linux/audio_manager_linux.cc
+index 5d703549372..9e60b40c749 100644
+--- media/audio/linux/audio_manager_linux.cc
++++ media/audio/linux/audio_manager_linux.cc
+@@ -20,6 +20,10 @@
+ #include "media/audio/pulse/audio_manager_pulse.h"
+ #include "media/audio/pulse/pulse_util.h"
+ #endif
++#if defined(USE_SNDIO)
++#include <sndio.h>
++#include "media/audio/openbsd/audio_manager_openbsd.h"
++#endif
+ 
+ namespace media {
+ 
+@@ -27,7 +31,8 @@ enum LinuxAudioIO {
+   kPulse,
+   kAlsa,
+   kCras,
+-  kAudioIOMax = kCras  // Must always be equal to largest logged entry.
++  kSndio,
++  kAudioIOMax = kSndio  // Must always be equal to largest logged entry.
+ };
+ 
+ std::unique_ptr<media::AudioManager> CreateAudioManager(
+@@ -41,6 +46,17 @@ std::unique_ptr<media::AudioManager> CreateAudioManager(
+   }
+ #endif
+ 
++#if defined(USE_SNDIO)
++  struct sio_hdl * hdl = NULL;
++  if ((hdl=sio_open(SIO_DEVANY, SIO_PLAY, 1)) != NULL) {
++    sio_close(hdl);
++    UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kSndio, kAudioIOMax +1);
++    return std::make_unique<AudioManagerOpenBSD>(std::move(audio_thread),
++                                               audio_log_factory);
++  }
++  DVLOG(1) << "Sndio is not available on the OS";
++#endif
++
+ #if defined(USE_PULSEAUDIO)
+   pa_threaded_mainloop* pa_mainloop = nullptr;
+   pa_context* pa_context = nullptr;
diff --git a/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_BUILD.gn.patch b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_BUILD.gn.patch
new file mode 100644
index 000000000000..ec6040026688
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_BUILD.gn.patch
@@ -0,0 +1,12 @@
+--- media/BUILD.gn	2020-03-24 10:16:30.000000000 +0100
++++ -	2020-04-06 14:32:27.960817513 +0200
+@@ -65,6 +65,9 @@
+   if (use_cras) {
+     defines += [ "USE_CRAS" ]
+   }
++  if (use_sndio) {
++    defines += [ "USE_SNDIO" ]
++  }
+ }
+ 
+ # Internal grouping of the configs necessary to support sub-folders having their
diff --git a/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_audio_BUILD.gn.patch b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_audio_BUILD.gn.patch
new file mode 100644
index 000000000000..c856de0bf2ec
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_audio_BUILD.gn.patch
@@ -0,0 +1,23 @@
+--- media/audio/BUILD.gn	2020-03-24 10:16:30.000000000 +0100
++++ -	2020-04-06 14:31:28.871450217 +0200
+@@ -232,9 +232,19 @@
+     deps += [ "//media/base/android:media_jni_headers" ]
+   }
+ 
+-  if (is_linux) {
++  if (is_linux) {
+     sources += [ "linux/audio_manager_linux.cc" ]
+   }
++  if (use_sndio) {
++    libs += [ "sndio" ]
++    sources += [
++      "openbsd/audio_manager_openbsd.cc",
++      "sndio/sndio_input.cc",
++      "sndio/sndio_input.h",
++      "sndio/sndio_output.cc",
++      "sndio/sndio_output.h"
++   ]
++ }
+ 
+   if (use_alsa) {
+     libs += [ "asound" ]
diff --git a/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_media__options.gni.patch b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_media__options.gni.patch
new file mode 100644
index 000000000000..14807d8e1d36
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_media__options.gni.patch
@@ -0,0 +1,12 @@
+--- media/media_options.gni	2020-03-24 10:16:30.000000000 +0100
++++ -	2020-04-06 14:29:22.958630783 +0200
+@@ -114,6 +114,9 @@
+   # Enables runtime selection of ALSA library for audio.
+   use_alsa = false
+ 
++  # Enables runtime selection of sndio library for audio.
++  use_sndio = false
++
+   # Alsa should be used on non-Android, non-Mac POSIX systems.
+   # Alsa should be used on desktop Chromecast and audio-only Chromecast builds.
+   if (is_posix && !is_android && !is_mac &&
diff --git a/srcpkgs/electron13/template b/srcpkgs/electron13/template
new file mode 100644
index 000000000000..fb03bf641a2b
--- /dev/null
+++ b/srcpkgs/electron13/template
@@ -0,0 +1,377 @@
+# Template file for 'electron13'
+pkgname=electron13
+version=13.2.2
+_nodever=14.16.0
+_chromiumver=91.0.4472.69
+revision=1
+archs="x86_64* i686* aarch64* ppc64le*"
+build_wrksrc="src"
+create_wrksrc=yes
+hostmakedepends="$(vopt_if clang clang) python pkgconf perl gperf bison ninja nodejs hwids
+ libwebp-devel freetype-devel harfbuzz-devel libpng-devel nss-devel which git libevent-devel
+ pciutils-devel libatomic-devel ffmpeg-devel libxml2-devel libglib-devel yarn openjdk libxslt-devel
+ opus-devel libXcursor-devel libXcomposite-devel libXtst-devel libXrandr-devel libXScrnSaver-devel
+ alsa-lib-devel re2-devel snappy-devel mit-krb5-devel $(vopt_if pulseaudio pulseaudio-devel)
+ $(vopt_if sndio sndio-devel) jq"
+makedepends="libpng-devel gtk+-devel gtk+3-devel nss-devel pciutils-devel
+ libXi-devel libgcrypt-devel libgnome-keyring-devel cups-devel elfutils-devel
+ libXcomposite-devel speech-dispatcher-devel libXrandr-devel mit-krb5-devel
+ libXScrnSaver-devel alsa-lib-devel snappy-devel libdrm-devel
+ libxml2-devel libxslt-devel $(vopt_if pulseaudio pulseaudio-devel) libexif-devel
+ libXcursor-devel libflac-devel speex-devel libmtp-devel libwebp-devel
+ libjpeg-turbo-devel libevent-devel json-c-devel harfbuzz-devel
+ minizip-devel jsoncpp-devel zlib-devel libcap-devel libXdamage-devel
+ re2-devel fontconfig-devel freetype-devel opus-devel libatomic-devel
+ $(vopt_if sndio sndio-devel) ffmpeg-devel libva-devel libuv-devel c-ares-devel libnotify-devel
+ $(vopt_if pipewire pipewire-devel) wayland-devel libcurl-devel"
+short_desc="Cross platform application development framework based on web technologies"
+maintainer="John <me@johnnynator.dev>"
+license="BSD-3-Clause"
+homepage="https://electronjs.org"
+distfiles="https://github.com/electron/electron/archive/v$version.tar.gz>electron-${version}.tar.gz
+ https://commondatastorage.googleapis.com/chromium-browser-official/chromium-$_chromiumver.tar.xz
+ https://github.com/nodejs/node/archive/v$_nodever.tar.gz>node-$_nodever.tar.gz"
+checksum="d5e35b412fc055e6fc5636717392193004b37fdd669302f528eee7232b34d9c5
+ 1f6843c636f4adee6b06c301193810cce103ee3e4582d4cbc31c915efc3d0c7b
+ bcdf869b0743405515ee897b1047b5e851a717e426b4974d26537c9b10dfd53a"
+
+case "$XBPS_TARGET_MACHINE" in
+	ppc64*-musl) makedepends+=" libucontext-devel" ;;
+esac
+
+no_generic_pkgconfig_link=yes
+lib32disabled=yes
+nopie=yes  # contains tools that are not PIE, enables PIE itself
+
+build_options="pulseaudio sndio clang pipewire"
+build_options_default="pulseaudio clang pipewire"
+
+if [ "$build_option_clang" ]; then
+	nocross="No proper setup for using clang as cross compiler in void yet"
+elif [ "${XBPS_TARGET_MACHINE%%-musl}" = "aarch64" ]; then
+	broken="Falls apart at runtime when compiled with gcc"
+fi
+
+_buildtype=Release
+_is_debug=false
+
+CFLAGS="-Wno-unknown-warning-option -fPIC"
+CXXFLAGS="-Wno-unknown-warning-option -fPIC"
+
+_apply_patch() {
+	local args="$1" pname="$(basename $2)"
+
+	if [ ! -f ".${pname}_done" ]; then
+		msg_normal "$pkgver: patching: ${pname}.\n"
+		patch -N $args -i $2
+		touch .${pname}_done
+	fi
+}
+
+_get_chromium_arch() {
+	case "$1" in
+		x86_64*) echo x64 ;;
+		i686*) echo x86 ;;
+		arm*) echo arm ;;
+		aarch64*) echo arm64 ;;
+		ppc64*) echo ppc64 ;;
+		ppc*) echo ppc ;;
+		mipsel*) echo mipsel ;;
+		mips*) echo mips ;;
+		*) msg_error "$pkgver: cannot be compiled for ${XBPS_TARGET_MACHINE}.\n" ;;
+	esac
+}
+
+post_extract() {
+	ln -s chromium-$_chromiumver src
+	mkdir -p src/third_party/
+	ln -s ../../node-$_nodever src/third_party/electron_node
+	ln -s ../electron-${version} src/electron
+
+}
+post_patch() {
+	cd $wrksrc
+	for x in $FILESDIR/patches/*; do
+		case "${x##*/}" in
+			electron*.patch)
+				cd src/electron
+				_apply_patch -p1 "$x"
+				cd "$wrksrc";;
+		esac
+	done
+
+	# Sigh, electron uses git am...
+	if [ ! -f ".electron_patches_done" ]; then
+	mv src/electron/patches/config.json config.json.old
+	jq 'del(."src/electron/patches/Mantle", ."src/electron/patches/ReactiveObjC",
+		."src/electron/patches/squirrel.mac", ."src/electron/patches/nan")' \
+		config.json.old > src/electron/patches/config.json
+	
+	python2 src/electron/script/list_patch_targets.py src/electron/patches/config.json | while read -r repopath; do
+		cd "$wrksrc"/"$repopath"
+		git init -q
+		git config "gc.auto" 0
+		if [ "$repopath" != "src" ]; then
+			echo "/${repopath#src/}" >> "$wrksrc/$build_wrksrc/.gitignore"
+		fi
+		git add .
+		git -c 'user.name=Electron build' -c 'user.email=electron@ebuild' \
+			commit -q -m "." || true
+	done
+	cd $wrksrc
+	python2 src/electron/script/apply_all_patches.py src/electron/patches/config.json
+	touch .electron_patches_done
+	fi
+
+	for x in $FILESDIR/patches/*; do
+		case "${x##*/}" in
+			chromium*.patch)
+				cd src
+				_apply_patch -p1 "$x"
+				cd "$wrksrc";;
+		esac
+	done
+
+	if [ "$XBPS_TARGET_LIBC" = "musl" ]; then
+	for x in $FILESDIR/musl-patches/*; do
+		case "${x##*/}" in
+			chromium*.patch)
+				cd src
+				_apply_patch -p0 "$x"
+				cd "$wrksrc";;
+			electron*.patch)
+				cd src/electron
+				_apply_patch -p1 "$x"
+				cd "$wrksrc";;
+		esac
+	done
+	fi
+	if [ "$build_option_sndio" ]; then
+		mkdir -p ${wrksrc}/${build_wrksrc}/media/audio/{sndio,openbsd}
+		cp ${FILESDIR}/sndio-files/sndio_*put.* \
+			${wrksrc}/${build_wrksrc}/media/audio/sndio
+		cp ${FILESDIR}/sndio-files/audio_manager_openbsd.* \
+			${wrksrc}/${build_wrksrc}/media/audio/openbsd
+		for f in "${FILESDIR}"/sndio-patches/*.patch; do
+			cd src
+			_apply_patch -p0 "$f"
+			cd "$wrksrc"
+		done
+	fi
+}
+
+pre_configure() {
+	cd "$wrksrc/$build_wrksrc"
+
+	# https://groups.google.com/a/chromium.org/d/topic/chromium-packagers/9JX1N2nf4PU/discussion
+	touch chrome/test/data/webui/i18n_process_css_test.html
+	# Use the file at run time instead of effectively compiling it in
+	sed 's|//third_party/usb_ids/usb.ids|/usr/share/hwdata/usb.ids|g' \
+		-i services/device/public/cpp/usb/BUILD.gn
+
+	mkdir -p third_party/node/linux/node-linux-x64/bin
+	ln -s /usr/bin/node third_party/node/linux/node-linux-x64/bin/
+
+	# compile gn early, so it can be used to generate gni stuff
+	msg_normal "Bootstrapping GN\n"
+	CC="${CC_FOR_BUILD:-$CC}" CXX="${CXX_FOR_BUILD:-$CXX}" LD="${LD_FOR_BUILD:-$LD}" \
+	CFLAGS="${CFLAGS_FOR_BUILD:-$CFLAGS}" CXXFLAGS="${CXXFLAGS_FOR_BUILD:-$CXXFLAGS}" \
+	LDFLAGS="${XBPS_LDFLAGS}" \
+		python2 tools/gn/bootstrap/bootstrap.py -s -v --skip-generate-buildfiles
+
+	# we need to generate ppc64 stuff for libvpx as it's not shipped
+	# this has to be done before unbundling, but after gn is built
+	# comment out if we switch back to system libvpx again later
+	case "$XBPS_TARGET_MACHINE" in
+		ppc64*)
+			pushd third_party/libvpx
+			mkdir -p source/config/linux/ppc64
+			# need PATH to find gn
+			PATH="${wrksrc}/${build_wrksrc}/out/Release:$PATH" \
+				./generate_gni.sh || \
+					msg_error "failed to generate libvpx gni"
+			popd
+			;;
+	esac
+
+	# reusable system library settings
+	local use_system="
+		ffmpeg
+		flac
+		fontconfig
+		freetype
+		harfbuzz-ng
+		libdrm
+		libevent
+		libjpeg
+		libpng
+		libwebp
+		libxml
+		libxslt
+		opus
+		re2
+		snappy
+		"
+	for _lib in $use_system libjpeg_turbo; do
+		msg_normal "Removing buildscripts for system provided $_lib\n"
+		find -type f -path "*third_party/$_lib/*" \
+			\! -path "*third_party/$_lib/chromium/*" \
+			\! -path "*third_party/$_lib/google/*" \
+			\! -path './base/third_party/icu/*' \
+			\! -path './third_party/pdfium/third_party/freetype/include/pstables.h' \
+			\! -path './third_party/harfbuzz-ng/utils/hb_scoped.h' \
+			\! -regex '.*\.\(gn\|gni\|isolate\|py\)' \
+			-delete
+	done
+
+
+	msg_normal "Replacing gn files\n"
+	python2 build/linux/unbundle/replace_gn_files.py --system-libraries \
+		$use_system
+	third_party/libaddressinput/chromium/tools/update-strings.py
+}
+
+do_configure() {
+	local target_arch="$(_get_chromium_arch ${XBPS_TARGET_MACHINE})"
+	local host_arch="$(_get_chromium_arch ${XBPS_MACHINE})"
+	# the build system will set march for use, adding it to cflags will break builds
+	export CXXFLAGS=$( shopt -s extglob; echo ${CXXFLAGS/-march=*([^ ])} )
+	export CFLAGS=$( shopt -s extglob; echo ${CFLAGS/-march=*([^ ])} )
+	export CFLAGS=${CFLAGS/-g/}
+	export CXXFLAGS=${CXXFLAGS/-g/}
+	local conf=()
+	cd third_party/electron_node
+	if [ "$CROSS_BUILD" ]; then
+		conf_args=" --dest-cpu=${target_arch} --cross-compiling"
+	fi
+	./configure --prefix=/usr \
+		--shared-zlib \
+		--shared-libuv \
+		--shared-openssl \
+		--shared-cares \
+		--openssl-use-def-ca-store \
+		--without-npm \
+		--without-dtrace \
+		--without-bundled-v8 \
+		${conf_args}
+
+	cd "$wrksrc/$build_wrksrc"/electron
+	yarn install
+	cd "$wrksrc/$build_wrksrc"
+
+	if [ "$build_option_clang" ]; then
+		export CC=clang
+		export CXX=clang++
+		export HOST_CC=clang
+		export HOST_CXX=clang++
+	else
+		export CXXFLAGS="$CXXFLAGS -fpermissive"
+		export BUILD_CXXFLAGS="$BUILD_CXXFLAGS -fpermissive"
+		export BUILD_AR="$AR_host"
+		export BUILD_NM="$NM_host"
+	fi
+
+	conf+=(
+		'blink_symbol_level=0'
+		'clang_use_chrome_plugins=false'
+		'custom_toolchain="//build/toolchain/linux/unbundle:default"'
+	)
+	if [ "$CROSS_BUILD" ]; then
+		conf+=(
+			'host_toolchain="//build/toolchain/linux/unbundle:host"'
+			'v8_snapshot_toolchain="//build/toolchain/linux/unbundle:host"'
+			"host_pkg_config=\"$PKG_CONFIG_FOR_BUILD\""
+			"pkg_config=\"$PKG_CONFIG\""
+		)
+	else
+		conf+=(
+			'host_toolchain="//build/toolchain/linux/unbundle:default"'
+			'v8_snapshot_toolchain="//build/toolchain/linux/unbundle:default"'
+		)
+	fi
+	if [ "$build_option_sndio" ]; then
+		conf+=(
+			'use_sndio=true'
+		)
+	fi
+	if [ -n "$XBPS_DEBUG_PKGS" ]; then
+		conf+=('symbol_level=1')
+	else
+		conf+=('symbol_level=0')
+	fi
+	conf+=(
+		'enable_hangout_services_extension=true'
+		'enable_nacl_nonsfi=false'
+		'enable_nacl=false'
+		'enable_precompiled_headers=false'
+		'fatal_linker_warnings=false'
+		'ffmpeg_branding="Chrome"'
+		'fieldtrial_testing_like_official_build=true'
+		'gold_path="/usr/bin/ld.gold"'
+		'icu_use_data_file=true'
+		"is_clang=$(vopt_if clang true false)"
+		'is_component_build=false'
+		"is_debug=$_is_debug"
+		'proprietary_codecs=true'
+		'treat_warnings_as_errors=false'
+		'use_allocator_shim=false'
+		'use_allocator="none"'
+		'use_cups=true'
+		'use_custom_libcxx=false'
+		'use_gnome_keyring=false'
+		'use_gold=false'
+		'use_lld=false'
+		'use_system_libwayland=true'
+		"use_pulseaudio=$(vopt_if pulseaudio 'true' 'false')"
+		"rtc_use_pipewire=$(vopt_if pipewire true false)"
+		'rtc_pipewire_version="0.3"'
+		'use_sysroot=false'
+		'use_system_harfbuzz=true'
+		"target_cpu=\"$target_arch\""
+		"host_cpu=\"$host_arch\""
+		'import("//electron/build/args/release.gn")'
+	)
+
+	msg_normal "Configuring build\n"
+	out/Release/gn gen out/$_buildtype --args="${conf[*]}"
+}
+
+do_build() {
+	export CXXFLAGS=$( shopt -s extglob; echo ${CXXFLAGS/-march=*([^ ])} )
+	export CFLAGS=$( shopt -s extglob; echo ${CFLAGS/-march=*([^ ])} )
+	export CFLAGS=${CFLAGS/-g/}
+	export CXXFLAGS=${CXXFLAGS/-g/}
+	if [ "$build_option_clang" ]; then
+		export CC=clang
+		export CXX=clang++
+		export HOST_CC=clang
+		export HOST_CXX=clang++
+	else
+		export BUILD_CXXFLAGS="$BUILD_CXXFLAGS -fpermissive"
+		export CXXFLAGS="$CXXFLAGS -fpermissive"
+		export BUILD_AR="$AR_host"
+		export BUILD_NM="$NM_host"
+	fi
+	msg_normal "Ninja turtles GO!\n"
+	ninja ${makejobs} -C out/$_buildtype electron third_party/electron_node:headers
+	# finish rest of the build
+	strip -s out/$_buildtype/electron
+	ninja ${makejobs} -C out/$_buildtype electron_dist_zip
+}
+
+do_install() {
+	vmkdir /usr/lib/$pkgname
+	vmkdir /usr/include/$pkgname
+	bsdtar -xf out/$_buildtype/dist.zip -C "$DESTDIR/usr/lib/$pkgname"
+
+	chmod u+s "$DESTDIR/usr/lib/$pkgname/chrome-sandbox"
+
+	cp out/$_buildtype/gen/node_headers.tar.gz "$DESTDIR"/usr/include/$pkgname
+
+	vlicense ${wrksrc}/src/LICENSE chromium.LICENSE
+	vlicense ${wrksrc}/src/electron/LICENSE electron.LICENSE
+	vlicense ${wrksrc}/src/third_party/electron_node/LICENSE node.LICENSE
+
+	vmkdir /usr/bin
+	ln -s ../lib/$pkgname/electron "$DESTDIR"/usr/bin/$pkgname
+}
diff --git a/srcpkgs/electron13/update b/srcpkgs/electron13/update
new file mode 100644
index 000000000000..3af8e58b5358
--- /dev/null
+++ b/srcpkgs/electron13/update
@@ -0,0 +1,2 @@
+site=https://www.electronjs.org/releases/stable?version=${version%%.*}
+pattern='tag/v\K[\d\.]+(?=")'

From d53ebe53d510d575c8ff8af985981186a5aa0166 Mon Sep 17 00:00:00 2001
From: John <me@johnnynator.dev>
Date: Sat, 28 Aug 2021 12:43:48 +0200
Subject: [PATCH 2/3] vscode: use electron13

---
 .../patches/disable-crash-reporter.patch      | 71 +++++++++++++++++++
 srcpkgs/vscode/template                       |  8 +--
 2 files changed, 75 insertions(+), 4 deletions(-)
 create mode 100644 srcpkgs/vscode/patches/disable-crash-reporter.patch

diff --git a/srcpkgs/vscode/patches/disable-crash-reporter.patch b/srcpkgs/vscode/patches/disable-crash-reporter.patch
new file mode 100644
index 000000000000..59553fabf753
--- /dev/null
+++ b/srcpkgs/vscode/patches/disable-crash-reporter.patch
@@ -0,0 +1,71 @@
+From afa206dc466066c3d273dfc879103700505b3d7b Mon Sep 17 00:00:00 2001
+From: Joshua Strobl <joshua@streambits.io>
+Date: Sun, 22 Aug 2021 14:02:05 +0300
+Subject: [PATCH 1/1] Disable crash reporter since Microsoft refuses to fix
+ this upstream.
+
+Unfortunately a PR submitted by a third-party was rejected by Microsoft, which would change the default for crash reporting from true to false and move the telemetry configuration to ensure crash reporting was not being forced on, placed in the argv.json, and cause a crash when improperly set.
+
+So, disable it entirely. No cookies for you, Visual Studio Code team.
+---
+ src/bootstrap-fork.js            |  3 ---
+ src/main.js                      | 16 ----------------
+ src/vs/code/electron-main/app.ts |  2 +-
+ 3 files changed, 1 insertion(+), 20 deletions(-)
+
+diff --git a/src/bootstrap-fork.js b/src/bootstrap-fork.js
+index 55303d9a556..ead5d08663f 100644
+--- a/src/bootstrap-fork.js
++++ b/src/bootstrap-fork.js
+@@ -37,9 +37,6 @@ if (process.env['VSCODE_PARENT_PID']) {
+ 	terminateWhenParentTerminates();
+ }
+ 
+-// Configure Crash Reporter
+-configureCrashReporter();
+-
+ // Load AMD entry point
+ require('./bootstrap-amd').load(process.env['VSCODE_AMD_ENTRYPOINT']);
+ 
+diff --git a/src/main.js b/src/main.js
+index 9cf737e0649..1d779632498 100644
+--- a/src/main.js
++++ b/src/main.js
+@@ -46,22 +46,6 @@ const codeCachePath = getCodeCachePath();
+ // Configure static command line arguments
+ const argvConfig = configureCommandlineSwitchesSync(args);
+ 
+-// Configure crash reporter
+-perf.mark('code/willStartCrashReporter');
+-// If a crash-reporter-directory is specified we store the crash reports
+-// in the specified directory and don't upload them to the crash server.
+-//
+-// Appcenter crash reporting is enabled if
+-// * enable-crash-reporter runtime argument is set to 'true'
+-// * --disable-crash-reporter command line parameter is not set
+-//
+-// Disable crash reporting in all other cases.
+-if (args['crash-reporter-directory'] ||
+-	(argvConfig['enable-crash-reporter'] && !args['disable-crash-reporter'])) {
+-	configureCrashReporter();
+-}
+-perf.mark('code/didStartCrashReporter');
+-
+ // Set logs path before app 'ready' event if running portable
+ // to ensure that no 'logs' folder is created on disk at a
+ // location outside of the portable directory
+diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts
+index 135f444bdbf..9d207a91bcf 100644
+--- a/src/vs/code/electron-main/app.ts
++++ b/src/vs/code/electron-main/app.ts
+@@ -982,7 +982,7 @@ export class CodeApplication extends Disposable {
+ 			const argvJSON = JSON.parse(stripComments(argvString));
+ 			if (argvJSON['enable-crash-reporter'] === undefined) {
+ 				const enableCrashReporterSetting = this.configurationService.getValue('telemetry.enableCrashReporter');
+-				const enableCrashReporter = typeof enableCrashReporterSetting === 'boolean' ? enableCrashReporterSetting : true;
++				const enableCrashReporter = typeof enableCrashReporterSetting === 'boolean' ? enableCrashReporterSetting : false;
+ 				const additionalArgvContent = [
+ 					'',
+ 					'	// Allows to disable crash reporting.',
+-- 
+2.32.0
diff --git a/srcpkgs/vscode/template b/srcpkgs/vscode/template
index da7d5cbe5bcf..4a141543c9c2 100644
--- a/srcpkgs/vscode/template
+++ b/srcpkgs/vscode/template
@@ -1,11 +1,11 @@
 # Template file for 'vscode'
 pkgname=vscode
 version=1.59.1
-revision=2
-_electronver=12.0.14
+revision=3
+_electronver=13.2.2
 hostmakedepends="pkg-config python nodejs yarn tar git"
-makedepends="libxkbfile-devel libsecret-devel electron12"
-depends="libXtst libxkbfile nss dejavu-fonts-ttf xdg-utils ripgrep electron12"
+makedepends="libxkbfile-devel libsecret-devel electron13"
+depends="libXtst libxkbfile nss dejavu-fonts-ttf xdg-utils ripgrep electron13"
 short_desc="Microsoft Code for Linux"
 maintainer="shizonic <realtiaz@gmail.com>"
 license="MIT"

From e7536fafe13f528e05c321fe6129139f6fc1e1b5 Mon Sep 17 00:00:00 2001
From: John <me@johnnynator.dev>
Date: Sat, 28 Aug 2021 12:45:45 +0200
Subject: [PATCH 3/3] Rocket.Chat-Desktop: update to 3.4.0.

---
 srcpkgs/Rocket.Chat-Desktop/files/Rocket.Chat-Desktop | 2 +-
 srcpkgs/Rocket.Chat-Desktop/template                  | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/srcpkgs/Rocket.Chat-Desktop/files/Rocket.Chat-Desktop b/srcpkgs/Rocket.Chat-Desktop/files/Rocket.Chat-Desktop
index 90d482ab178d..214b977b5989 100644
--- a/srcpkgs/Rocket.Chat-Desktop/files/Rocket.Chat-Desktop
+++ b/srcpkgs/Rocket.Chat-Desktop/files/Rocket.Chat-Desktop
@@ -1,2 +1,2 @@
 #!/bin/sh
-exec electron10 /usr/lib/Rocket.Chat-Desktop.asar "$@"
+exec electron13 /usr/lib/Rocket.Chat-Desktop.asar "$@"
diff --git a/srcpkgs/Rocket.Chat-Desktop/template b/srcpkgs/Rocket.Chat-Desktop/template
index d866c3c51852..b2d47097ec35 100644
--- a/srcpkgs/Rocket.Chat-Desktop/template
+++ b/srcpkgs/Rocket.Chat-Desktop/template
@@ -1,8 +1,8 @@
 # Template file for 'Rocket.Chat-Desktop'
 pkgname=Rocket.Chat-Desktop
-version=3.3.0
+version=3.4.0
 revision=1
-_electron_ver=10
+_electron_ver=13
 wrksrc="Rocket.Chat.Electron-${version}"
 hostmakedepends="yarn nodejs python3 pkg-config app-builder"
 makedepends="electron${_electron_ver} libvips-devel"
@@ -12,7 +12,7 @@ maintainer="John <me@johnnynator.dev>"
 license="MIT"
 homepage="https://rocket.chat/"
 distfiles="https://github.com/RocketChat/Rocket.Chat.Electron/archive/${version}.tar.gz"
-checksum=a08d79c20b89d4e954b3f91d728d51f0d24094878da6b24c930cebc1ce7ce64c
+checksum=fd77cf5a05e8866e9647fef8e793365148490bdc8c1c8986eb246b4540a4b728
 
 export USE_SYSTEM_APP_BUILDER=true
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PR PATCH] [Updated] electron13-13.2.2
  2021-05-26 19:41 [PR PATCH] [WiP] New package: electron13-13.0.0 Johnnynator
  2021-08-29  0:24 ` [PR PATCH] [Updated] " Johnnynator
@ 2021-08-29  0:26 ` Johnnynator
  2021-08-29 15:59 ` [PR PATCH] [Merged]: electron13-13.2.2 Johnnynator
  2 siblings, 0 replies; 4+ messages in thread
From: Johnnynator @ 2021-08-29  0:26 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 1752 bytes --]

There is an updated pull request by Johnnynator against master on the void-packages repository

https://github.com/Johnnynator/void-packages electron13
https://github.com/void-linux/void-packages/pull/31136

electron13-13.2.2
<!-- Mark items with [x] where applicable -->

#### General
- [ ] This is a new package and it conforms to the [quality requirements](https://github.com/void-linux/void-packages/blob/master/Manual.md#quality-requirements)

#### Have the results of the proposed changes been tested?
- [ ] I use the packages affected by the proposed changes on a regular basis and confirm this PR works for me
- [ ] I generally don't use the affected packages but briefly tested this PR

- This doesn't compile yet on musl, they move a lot of dns stuff from generic posix to a linux specific file, that ofc only works for glibc.

[ci skip]

<!--
If GitHub CI cannot be used to validate the build result (for example, if the
build is likely to take several hours), make sure to
[skip CI](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#continuous-integration).
When skipping CI, uncomment and fill out the following section.
Note: for builds that are likely to complete in less than 2 hours, it is not
acceptable to skip CI.
-->
<!-- 
#### Does it build and run successfully? 
(Please choose at least one native build and, if supported, at least one cross build. More are better.)
- [ ] I built this PR locally for my native architecture, (ARCH-LIBC)
- [ ] I built this PR locally for these architectures (if supported. mark crossbuilds):
  - [ ] aarch64-musl
  - [ ] armv7l
  - [ ] armv6l-musl
-->


A patch file from https://github.com/void-linux/void-packages/pull/31136.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-electron13-31136.patch --]
[-- Type: text/x-diff, Size: 294701 bytes --]

From e6a2fa6947ea9d2ebd0b7524c869f5f6aadb9af6 Mon Sep 17 00:00:00 2001
From: John <me@johnnynator.dev>
Date: Wed, 26 May 2021 21:38:32 +0200
Subject: [PATCH 1/3] New package: electron13-13.2.2

---
 .../chromium-default-pthread-stacksize.patch  |   29 +
 .../musl-patches/chromium-musl-crashpad.patch |   23 +
 .../musl-patches/chromium-musl-dns.patch      |   32 +
 .../musl-patches/chromium-musl-fixes.patch    |  212 +
 .../musl-patches/chromium-musl-hacks.patch    |   34 +
 .../musl-patches/chromium-musl-libc++.patch   |   55 +
 .../musl-patches/chromium-musl-sandbox.patch  |   92 +
 .../musl-patches/chromium-musl-sync.patch     |   30 +
 .../chromium-musl-xxx-ppc64le.patch           |  190 +
 .../musl-patches/chromium-no-mallinfo.patch   |   54 +
 .../musl-patches/chromium-resolver.patch      |   38 +
 .../patches/chromium-browser-size_t.patch     |   10 +
 .../files/patches/chromium-libc_malloc.patch  |   26 +
 ...-v8-monotonic-pthread-cont_timedwait.patch |   24 +
 .../files/patches/chromium-no-execinfo.patch  |   72 +
 .../patches/chromium-no-getcontext.patch      |   27 +
 .../chromium-revert-drop-of-system-java.patch |   15 +
 .../patches/chromium-sandbox-membarrier.patch |   10 +
 .../chromium-sandbox-sched_getparam.patch     |   20 +
 .../files/patches/chromium-sndio.patch        |  886 ++++
 .../patches/chromium-system-nodejs.patch      |   20 +
 .../patches/chromium-webrtc-include.patch     |   10 +
 .../files/patches/chromium-webrtc-r0.patch    |   33 +
 .../patches/chromium-webrtc-size_t.patch      |   10 +
 .../patches/chromium-xxx-ppc64le-libvpx.patch |   72 +
 .../chromium-xxx-ppc64le-support.patch        | 3707 +++++++++++++++++
 .../chromium-xxx-ppc64le-swiftshader.patch    |   18 +
 ...a-script-to-list-patch-targets.patch.patch |   42 +
 .../patches/electron-Build-fixes.patch.patch  |   47 +
 ...ectron-dont-assume-python-is-python2.patch |   17 +
 ...lectron-exclude-content-test-patches.patch |   10 +
 .../sndio-files/audio_manager_openbsd.cc      |  148 +
 .../files/sndio-files/audio_manager_openbsd.h |   65 +
 .../files/sndio-files/sndio_input.cc          |  200 +
 .../files/sndio-files/sndio_input.h           |   91 +
 .../files/sndio-files/sndio_output.cc         |  183 +
 .../files/sndio-files/sndio_output.h          |   86 +
 ...a_audio_linux_audio_manager_linux.cc.patch |   43 +
 ...src_3rdparty_chromium_media_BUILD.gn.patch |   12 +
 ...dparty_chromium_media_audio_BUILD.gn.patch |   23 +
 ...ty_chromium_media_media__options.gni.patch |   12 +
 srcpkgs/electron13/template                   |  377 ++
 srcpkgs/electron13/update                     |    2 +
 43 files changed, 7107 insertions(+)
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-default-pthread-stacksize.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-crashpad.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-dns.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-fixes.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-hacks.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-libc++.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-sandbox.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-sync.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-musl-xxx-ppc64le.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-no-mallinfo.patch
 create mode 100644 srcpkgs/electron13/files/musl-patches/chromium-resolver.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-browser-size_t.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-libc_malloc.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-musl-v8-monotonic-pthread-cont_timedwait.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-no-execinfo.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-no-getcontext.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-revert-drop-of-system-java.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-sandbox-membarrier.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-sandbox-sched_getparam.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-sndio.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-system-nodejs.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-webrtc-include.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-webrtc-r0.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-webrtc-size_t.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-libvpx.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-support.patch
 create mode 100644 srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-swiftshader.patch
 create mode 100644 srcpkgs/electron13/files/patches/electron-Add-a-script-to-list-patch-targets.patch.patch
 create mode 100644 srcpkgs/electron13/files/patches/electron-Build-fixes.patch.patch
 create mode 100644 srcpkgs/electron13/files/patches/electron-dont-assume-python-is-python2.patch
 create mode 100644 srcpkgs/electron13/files/patches/electron-exclude-content-test-patches.patch
 create mode 100644 srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.cc
 create mode 100644 srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.h
 create mode 100644 srcpkgs/electron13/files/sndio-files/sndio_input.cc
 create mode 100644 srcpkgs/electron13/files/sndio-files/sndio_input.h
 create mode 100644 srcpkgs/electron13/files/sndio-files/sndio_output.cc
 create mode 100644 srcpkgs/electron13/files/sndio-files/sndio_output.h
 create mode 100644 srcpkgs/electron13/files/sndio-patches/media_audio_linux_audio_manager_linux.cc.patch
 create mode 100644 srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_BUILD.gn.patch
 create mode 100644 srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_audio_BUILD.gn.patch
 create mode 100644 srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_media__options.gni.patch
 create mode 100644 srcpkgs/electron13/template
 create mode 100644 srcpkgs/electron13/update

diff --git a/srcpkgs/electron13/files/musl-patches/chromium-default-pthread-stacksize.patch b/srcpkgs/electron13/files/musl-patches/chromium-default-pthread-stacksize.patch
new file mode 100644
index 000000000000..16e4d21e6ed8
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-default-pthread-stacksize.patch
@@ -0,0 +1,29 @@
+--- base/threading/platform_thread_linux.cc.orig
++++ base/threading/platform_thread_linux.cc
+@@ -99 +99,2 @@ size_t GetDefaultThreadStackSize(const p
+-  return 0;
++  // use 8mb like glibc to avoid running out of space
++  return (1 << 23);
+--- chrome/app/shutdown_signal_handlers_posix.cc.orig
++++ chrome/app/shutdown_signal_handlers_posix.cc
+@@ -184,11 +184,19 @@
+   g_shutdown_pipe_read_fd = pipefd[0];
+   g_shutdown_pipe_write_fd = pipefd[1];
+ #if !defined(ADDRESS_SANITIZER)
++# if defined(__GLIBC__)
+   const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 2;
++# else
++  const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 2 * 8; // match up musls 2k PTHREAD_STACK_MIN with glibcs 16k
++# endif
+ #else
+   // ASan instrumentation bloats the stack frames, so we need to increase the
+   // stack size to avoid hitting the guard page.
++# if defined(__GLIBC__)
+   const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 4;
++# else
++  const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 4 * 8; // match up musls 2k PTHREAD_STACK_MIN with glibcs 16k
++# endif
+ #endif
+   ShutdownDetector* detector = new ShutdownDetector(
+       g_shutdown_pipe_read_fd, shutdown_callback, task_runner);
+
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-crashpad.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-crashpad.patch
new file mode 100644
index 000000000000..03a0c06f3ca6
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-crashpad.patch
@@ -0,0 +1,23 @@
+--- third_party/crashpad/crashpad/util/linux/ptracer.cc
++++ third_party/crashpad/crashpad/util/linux/ptracer.cc
+@@ -26,6 +26,7 @@
+ 
+ #if defined(ARCH_CPU_X86_FAMILY)
+ #include <asm/ldt.h>
++#include <asm/ptrace-abi.h>
+ #endif
+ 
+ namespace crashpad {
+
+--- third_party/crashpad/crashpad/compat/linux/sys/ptrace.h
++++ third_party/crashpad/crashpad/compat/linux/sys/ptrace.h
+@@ -17,7 +17,9 @@
+ 
+ #include_next <sys/ptrace.h>
+ 
++#if defined(__GLIBC__)
+ #include <sys/cdefs.h>
++#endif
+ 
+ // https://sourceware.org/bugzilla/show_bug.cgi?id=22433
+ #if !defined(PTRACE_GET_THREAD_AREA) && !defined(PT_GET_THREAD_AREA) && \
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-dns.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-dns.patch
new file mode 100644
index 000000000000..57cc0ac6c18a
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-dns.patch
@@ -0,0 +1,32 @@
+--- net/features.gni	2021-05-20 04:17:11.000000000 +0200
++++ -	2021-05-26 16:03:25.826113608 +0200
+@@ -28,6 +28,9 @@
+   # Reporting not used on iOS.
+   enable_reporting = !is_ios
+ 
++  # Force Posix dns config
++  force_posix_dns = true
++
+   # Includes the transport security state preload list. This list includes
+   # mechanisms (e.g. HSTS, HPKP) to enforce trusted connections to a significant
+   # set of hardcoded domains. While this list has a several hundred KB of binary
+--- net/dns/BUILD.gn	2021-05-20 04:17:11.000000000 +0200
++++ -	2021-05-26 16:05:01.510622102 +0200
+@@ -114,7 +114,7 @@
+         "dns_config_service_android.cc",
+         "dns_config_service_android.h",
+       ]
+-    } else if (is_linux) {
++    } else if (is_linux && !force_posix_dns) {
+       sources += [
+         "dns_config_service_linux.cc",
+         "dns_config_service_linux.h",
+@@ -433,7 +433,7 @@
+ 
+   if (is_android) {
+     sources += [ "dns_config_service_android_unittest.cc" ]
+-  } else if (is_linux) {
++  } else if (is_linux && !force_posix_dns) {
+     sources += [ "dns_config_service_linux_unittest.cc" ]
+   } else if (is_posix) {
+     sources += [ "dns_config_service_posix_unittest.cc" ]
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-fixes.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-fixes.patch
new file mode 100644
index 000000000000..728f2b473ce3
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-fixes.patch
@@ -0,0 +1,212 @@
+--- ./third_party/lss/linux_syscall_support.h.orig
++++ ./third_party/lss/linux_syscall_support.h
+@@ -1127,6 +1127,12 @@
+ #ifndef __NR_fallocate
+ #define __NR_fallocate          285
+ #endif
++
++#undef __NR_pread
++#define __NR_pread __NR_pread64
++#undef __NR_pwrite
++#define __NR_pwrite __NR_pwrite64
++
+ /* End of x86-64 definitions                                                 */
+ #elif defined(__mips__)
+ #if _MIPS_SIM == _MIPS_SIM_ABI32
+--- ./third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h.orig
++++ ./third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.h
+@@ -37,6 +37,10 @@
+ #include "common/memory.h"
+ #include "google_breakpad/common/minidump_format.h"
+ 
++#if !defined(__GLIBC__)
++	#define _libc_fpstate _fpstate
++#endif
++
+ namespace google_breakpad {
+ 
+ // Wraps platform-dependent implementations of accessors to ucontext_t structs.
+--- ./third_party/breakpad/breakpad/src/common/linux/elf_core_dump.h.orig
++++ ./third_party/breakpad/breakpad/src/common/linux/elf_core_dump.h
+@@ -36,6 +36,7 @@
+ #include <elf.h>
+ #include <link.h>
+ #include <stddef.h>
++#include <limits.h>
+ 
+ #include "common/memory_range.h"
+ 
+--- ./sandbox/linux/suid/process_util.h.orig
++++ ./sandbox/linux/suid/process_util.h
+@@ -11,6 +11,14 @@
+ #include <stdbool.h>
+ #include <sys/types.h>
+ 
++// Some additional functions
++# define TEMP_FAILURE_RETRY(expression) \
++	(__extension__			\
++	 ({ long int __result;		\
++	  do __result = (long int) (expression); \
++	  while (__result == -1L && errno == EINTR); \
++	  __result; }))
++
+ // This adjusts /proc/process/oom_score_adj so the Linux OOM killer
+ // will prefer certain process types over others. The range for the
+ // adjustment is [-1000, 1000], with [0, 1000] being user accessible.
+--- ./sandbox/linux/seccomp-bpf/trap.cc.orig	2020-04-12 08:26:40.184159217 -0400
++++ ./sandbox/linux/seccomp-bpf/trap.cc	2020-04-12 08:46:16.737191222 -0400
+@@ -174,7 +174,7 @@
+   // If the version of glibc doesn't include this information in
+   // siginfo_t (older than 2.17), we need to explicitly copy it
+   // into an arch_sigsys structure.
+-  memcpy(&sigsys, &info->_sifields, sizeof(sigsys));
++  memcpy(&sigsys, &info->__sifields, sizeof(sigsys));
+ #endif
+ 
+ #if defined(__mips__)
+--- ./third_party/ffmpeg/libavutil/cpu.c.orig
++++ ./third_party/ffmpeg/libavutil/cpu.c
+@@ -38,7 +38,6 @@
+ #include <sys/param.h>
+ #endif
+ #include <sys/types.h>
+-#include <sys/sysctl.h>
+ #endif
+ #if HAVE_UNISTD_H
+ #include <unistd.h>
+diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
+--- chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc.orig	2021-03-10 07:23:00.145810088 -0500
++++ chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc	2021-03-10 10:57:19.405962671 -0500
+@@ -55,7 +55,9 @@
+ // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+ // of lacros-chrome is complete.
+ #if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
++#if defined(__GLIBC__)
+ #include <gnu/libc-version.h>
++#endif
+ 
+ #include "base/linux_util.h"
+ #include "base/strings/string_split.h"
+@@ -316,7 +318,7 @@
+ void RecordLinuxGlibcVersion() {
+ // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
+ // of lacros-chrome is complete.
+-#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
++#if defined(__GLIBC__) || BUILDFLAG(IS_CHROMEOS_LACROS)
+   base::Version version(gnu_get_libc_version());
+ 
+   UMALinuxGlibcVersion glibc_version_result = UMA_LINUX_GLIBC_NOT_PARSEABLE;
+--- services/device/serial/serial_io_handler_posix.cc.orig	2019-07-03 10:57:32.568171835 -0400
++++ services/device/serial/serial_io_handler_posix.cc	2019-07-03 10:57:16.867983031 -0400
+@@ -6,6 +6,7 @@
+ 
+ #include <sys/ioctl.h>
+ #include <termios.h>
++#include <asm-generic/ioctls.h>
+ 
+ #include <algorithm>
+ #include <utility>
+diff --git a/third_party/ots/include/opentype-sanitiser.h b/third_party/ots/include/opentype-sanitiser.h
+--- third_party/ots/src/include/opentype-sanitiser.h
++++ third_party/ots/src/include/opentype-sanitiser.h
+@@ -20,6 +20,7 @@ typedef unsigned __int64 uint64_t;
+ #define htonl(x) _byteswap_ulong (x)
+ #define htons(x) _byteswap_ushort (x)
+ #else
++#include <sys/types.h>
+ #include <arpa/inet.h>
+ #include <stdint.h>
+ #endif
+--- ./base/logging.cc.orig	2021-01-20 12:09:54.227038757 -0500
++++ ./base/logging.cc	2021-01-20 12:24:32.600301351 -0500
+@@ -557,8 +557,7 @@
+ 
+ LogMessage::~LogMessage() {
+   size_t stack_start = stream_.tellp();
+-#if !defined(OFFICIAL_BUILD) && !defined(OS_NACL) && !defined(__UCLIBC__) && \
+-    !defined(OS_AIX)
++#if !defined(OFFICIAL_BUILD) && !defined(OS_NACL) && defined(__GLIBC__)
+   if (severity_ == LOGGING_FATAL && !base::debug::BeingDebugged()) {
+     // Include a stack trace on a fatal, unless a debugger is attached.
+     base::debug::StackTrace stack_trace;
+--- ./third_party/blink/renderer/platform/wtf/stack_util.cc.orig
++++ ./third_party/blink/renderer/platform/wtf/stack_util.cc
+@@ -28,7 +28,7 @@
+ // FIXME: On Mac OSX and Linux, this method cannot estimate stack size
+ // correctly for the main thread.
+ 
+-#elif defined(__GLIBC__) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
++#elif defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
+     defined(OS_FUCHSIA)
+   // pthread_getattr_np() can fail if the thread is not invoked by
+   // pthread_create() (e.g., the main thread of blink_unittests).
+@@ -96,7 +96,7 @@
+ }
+ 
+ void* GetStackStart() {
+-#if defined(__GLIBC__) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
++#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FREEBSD) || \
+     defined(OS_FUCHSIA)
+   pthread_attr_t attr;
+   int error;
+--- ./net/dns/dns_config_service_posix.cc.orig
++++ ./net/dns/dns_config_service_posix.cc
+@@ -122,7 +122,7 @@
+   ConfigParsePosixResult result;
+   config->unhandled_options = false;
+ // TODO(fuchsia): Use res_ninit() when it's implemented on Fuchsia.
+-#if defined(OS_OPENBSD) || defined(OS_FUCHSIA)
++#if defined(OS_OPENBSD) || defined(OS_FUCHSIA) || defined(_GNU_SOURCE)
+   // Note: res_ninit in glibc always returns 0 and sets RES_INIT.
+   // res_init behaves the same way.
+   memset(&_res, 0, sizeof(_res));
+--- third_party/swiftshader/third_party/llvm-subzero/lib/Support/Unix/Signals.inc.orig	2019-06-18 11:51:17.000000000 -0400
++++ third_party/swiftshader/third_party/llvm-subzero/lib/Support/Unix/Signals.inc	2019-07-03 12:32:50.938758186 -0400
+@@ -25,7 +25,7 @@
+ #include "llvm/Support/raw_ostream.h"
+ #include <algorithm>
+ #include <string>
+-#if HAVE_EXECINFO_H
++#if HAVE_EXECINFO_H && defined(__GLIBC__)
+ # include <execinfo.h>         // For backtrace().
+ #endif
+ #if HAVE_SIGNAL_H
+@@ -52,6 +52,7 @@
+ #include <unwind.h>
+ #else
+ #undef HAVE__UNWIND_BACKTRACE
++#undef HAVE_BACKTRACE
+ #endif
+ #endif
+ 
+--- third_party/nasm/nasmlib/realpath.c.orig	2019-07-03 12:23:05.021949895 -0400
++++ third_party/nasm/nasmlib/realpath.c	2019-07-03 12:24:24.246862665 -0400
+@@ -49,7 +49,7 @@
+ 
+ #include "nasmlib.h"
+ 
+-#ifdef HAVE_CANONICALIZE_FILE_NAME
++#if defined(__GLIBC__)
+ 
+ /*
+  * GNU-specific, but avoids the realpath(..., NULL)
+--- third_party/perfetto/include/perfetto/ext/base/thread_utils.h
++++ third_party/perfetto/include/perfetto/ext/base/thread_utils.h
+@@ -29,7 +29,7 @@
+ #include <algorithm>
+ #endif
+ 
+-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
++#if 1
+ #include <sys/prctl.h>
+ #endif
+ 
+@@ -58,7 +58,7 @@ inline bool MaybeSetThreadName(const std::string& name) {
+ 
+ inline bool GetThreadName(std::string& out_result) {
+   char buf[16] = {};
+-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
++#if 1
+   if (prctl(PR_GET_NAME, buf) != 0)
+     return false;
+ #else
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-hacks.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-hacks.patch
new file mode 100644
index 000000000000..4b4e9695a9d8
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-hacks.patch
@@ -0,0 +1,34 @@
+--- base/debug/stack_trace.cc.orig	2018-12-08 14:11:25.303475116 +0100
++++ base/debug/stack_trace.cc	2018-12-08 18:00:43.874946999 +0100
+@@ -229,7 +229,7 @@
+ }
+ std::string StackTrace::ToStringWithPrefix(const char* prefix_string) const {
+   std::stringstream stream;
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+   OutputToStreamWithPrefix(&stream, prefix_string);
+ #endif
+   return stream.str();
+--- net/socket/udp_socket_posix.cc.orig	2019-07-03 13:13:46.034342649 -0400
++++ net/socket/udp_socket_posix.cc	2019-07-03 13:23:53.117081909 -0400
+@@ -1194,7 +1194,7 @@
+     msg_iov->push_back({const_cast<char*>(buffer->data()), buffer->length()});
+   msgvec->reserve(buffers.size());
+   for (size_t j = 0; j < buffers.size(); j++)
+-    msgvec->push_back({{nullptr, 0, &msg_iov[j], 1, nullptr, 0, 0}, 0});
++    msgvec->push_back({{nullptr, 0, &msg_iov[j], 1, 0, 0, 0}, 0});
+   int result = HANDLE_EINTR(Sendmmsg(fd, &msgvec[0], buffers.size(), 0));
+   SendResult send_result(0, 0, std::move(buffers));
+   if (result < 0) {
+--- base/debug/stack_trace.cc   2021-05-25 00:05:31.000000000 +0200
++++ -   2021-05-27 13:46:43.740380140 +0200
+@@ -217,7 +217,9 @@
+ }
+ 
+ void StackTrace::OutputToStream(std::ostream* os) const {
++#if defined(__GLIBC__)
+   OutputToStreamWithPrefix(os, nullptr);
++#endif
+ }
+ 
+ std::string StackTrace::ToString() const {
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-libc++.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-libc++.patch
new file mode 100644
index 000000000000..088d80fad52b
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-libc++.patch
@@ -0,0 +1,55 @@
+diff --git a/buildtools/third_party/libc++/trunk/include/locale b/buildtools/third_party/libc++/trunk/include/locale
+index d29a2dc..53998bc 100644
+--- buildtools/third_party/libc++/trunk/include/locale
++++ buildtools/third_party/libc++/trunk/include/locale
+@@ -11,6 +11,15 @@
+ #ifndef _LIBCPP_LOCALE
+ #define _LIBCPP_LOCALE
+ 
++// musl doesn't define _l (with locale) variants of functions, as it only supports UTF-8.
++// we can simply make macros that will call the non-localated ones if we're using musl, or rather not-using something that has the _l ones.
++// couldn't find anything glibc #defines when it creates strtoull_l (that it doesn't undefine a few lines later), so let's test against glibc and glibc-likes.
++// almost all glibc-likes define __GNU_LIBRARY__ for compatibility
++#ifndef __GNU_LIBRARY__
++#define strtoull_l(A, B, C, LOC) strtoull(A,B,C)
++#define strtoll_l(A, B, C, LOC) strtoll(A,B,C)
++#endif
++
+ /*
+     locale synopsis
+ 
+diff --git a/buildtools/third_party/libc++/trunk/src/locale.cpp b/buildtools/third_party/libc++/trunk/src/locale.cpp
+index 4163c2c..3d1902a 100644
+--- a/buildtools/third_party/libc++/trunk/src/locale.cpp
++++ buildtools/third_party/libc++/trunk/src/locale.cpp
+@@ -1028,11 +1028,11 @@ ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault,
+     return low;
+ }
+ 
+-#if defined(__EMSCRIPTEN__)
++//#if defined(__EMSCRIPTEN__)
+ extern "C" const unsigned short ** __ctype_b_loc();
+ extern "C" const int ** __ctype_tolower_loc();
+ extern "C" const int ** __ctype_toupper_loc();
+-#endif
++//#endif
+ 
+ #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
+ const ctype<char>::mask*
+@@ -1136,12 +1136,10 @@ ctype<char>::classic_table()  _NOEXCEPT
+ #elif defined(_AIX)
+     return (const unsigned int *)__lc_ctype_ptr->obj->mask;
+ #else
+-    // Platform not supported: abort so the person doing the port knows what to
+-    // fix
+-# warning  ctype<char>::classic_table() is not implemented
+-    printf("ctype<char>::classic_table() is not implemented\n");
+-    abort();
+-    return NULL;
++// not sure any other libc like this exists, but there is no way to differentiate musl as of right now
++// to be fair, with the change above, this should always work
++// also, #warning is a gcc extension
++    return (const unsigned long *)*__ctype_b_loc();
+ #endif
+ }
+ #endif
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-sandbox.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-sandbox.patch
new file mode 100644
index 000000000000..230bb7bbd297
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-sandbox.patch
@@ -0,0 +1,92 @@
+--- ./sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc.orig	2019-07-03 11:53:21.213479736 -0400
++++ ./sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc	2019-07-03 11:57:01.304998253 -0400
+@@ -140,31 +140,14 @@
+ ResultExpr RestrictCloneToThreadsAndEPERMFork() {
+   const Arg<unsigned long> flags(0);
+ 
+-  // TODO(mdempsky): Extend DSL to support (flags & ~mask1) == mask2.
+-  const uint64_t kAndroidCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES |
+-                                     CLONE_SIGHAND | CLONE_THREAD |
+-                                     CLONE_SYSVSEM;
+-  const uint64_t kObsoleteAndroidCloneMask = kAndroidCloneMask | CLONE_DETACHED;
++  const int required = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
++                       CLONE_THREAD | CLONE_SYSVSEM;
++  const int safe = CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | 
++                   CLONE_DETACHED;
++  const BoolExpr thread_clone_ok = (flags&~safe)==required;
+ 
+-  const uint64_t kGlibcPthreadFlags =
+-      CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD |
+-      CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
+-  const BoolExpr glibc_test = flags == kGlibcPthreadFlags;
+-
+-  const BoolExpr android_test =
+-      AnyOf(flags == kAndroidCloneMask, flags == kObsoleteAndroidCloneMask,
+-            flags == kGlibcPthreadFlags);
+-
+-  // The following two flags are the two important flags in any vfork-emulating
+-  // clone call. EPERM any clone call that contains both of them.
+-  const uint64_t kImportantCloneVforkFlags = CLONE_VFORK | CLONE_VM;
+-
+-  const BoolExpr is_fork_or_clone_vfork =
+-      AnyOf((flags & (CLONE_VM | CLONE_THREAD)) == 0,
+-            (flags & kImportantCloneVforkFlags) == kImportantCloneVforkFlags);
+-
+-  return If(IsAndroid() ? android_test : glibc_test, Allow())
+-      .ElseIf(is_fork_or_clone_vfork, Error(EPERM))
++  return If(thread_clone_ok, Allow())
++      .ElseIf((flags & (CLONE_VM | CLONE_THREAD)) == 0, Error(EPERM))
+       .Else(CrashSIGSYSClone());
+ }
+ 
+--- ./sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc.orig
++++ ./sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+@@ -494,6 +494,7 @@
+     case __NR_mlock:
+     case __NR_munlock:
+     case __NR_munmap:
++    case __NR_mremap:
+       return true;
+     case __NR_madvise:
+     case __NR_mincore:
+@@ -509,7 +510,6 @@
+     case __NR_modify_ldt:
+ #endif
+     case __NR_mprotect:
+-    case __NR_mremap:
+     case __NR_msync:
+     case __NR_munlockall:
+     case __NR_readahead:
+diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+index 80f02c0..21fbe21 100644
+--- sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
++++ sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+@@ -373,6 +373,7 @@ bool SyscallSets::IsAllowedProcessStartOrDeath(int sysno) {
+ #if defined(__i386__)
+     case __NR_waitpid:
+ #endif
++    case __NR_set_tid_address:
+       return true;
+     case __NR_clone:  // Should be parameter-restricted.
+     case __NR_setns:  // Privileged.
+@@ -385,7 +386,6 @@ bool SyscallSets::IsAllowedProcessStartOrDeath(int sysno) {
+ #if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
+     case __NR_set_thread_area:
+ #endif
+-    case __NR_set_tid_address:
+     case __NR_unshare:
+ #if !defined(__mips__) && !defined(__aarch64__)
+     case __NR_vfork:
+--- sandbox/policy/linux/bpf_renderer_policy_linux.cc
++++ sandbox/policy/linux/bpf_renderer_policy_linux.cc
+@@ -100,9 +100,9 @@
+     case __NR_uname:
+     case __NR_sched_getparam:
+     case __NR_sched_getscheduler:
++    case __NR_sched_setscheduler:
+       return Allow();
+     case __NR_sched_getaffinity:
+-    case __NR_sched_setscheduler:
+       return RestrictSchedTarget(GetPolicyPid(), sysno);
+     case __NR_prlimit64:
+       // See crbug.com/662450 and setrlimit comment above.
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-sync.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-sync.patch
new file mode 100644
index 000000000000..bc2fa1937bd3
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-sync.patch
@@ -0,0 +1,30 @@
+--- third_party/libsync/src/include/sync/sync.h.orig	2020-02-21 07:43:33.748325175 -0500
++++ third_party/libsync/src/include/sync/sync.h	2020-02-21 07:44:07.288328784 -0500
+@@ -19,12 +19,16 @@
+ #ifndef __SYS_CORE_SYNC_H
+ #define __SYS_CORE_SYNC_H
+ 
++#if defined(__GLIBC__)
+ #include <sys/cdefs.h>
++#endif
+ #include <stdint.h>
+ 
+ #include <linux/types.h>
+ 
+-__BEGIN_DECLS
++#ifdef __cplusplus
++extern "C" {
++#endif
+ 
+ struct sync_legacy_merge_data {
+  int32_t fd2;
+@@ -158,6 +162,8 @@
+                                   struct sync_pt_info *itr);
+ void sync_fence_info_free(struct sync_fence_info_data *info);
+ 
+-__END_DECLS
++#ifdef __cplusplus
++}
++#endif
+ 
+ #endif /* __SYS_CORE_SYNC_H */
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-musl-xxx-ppc64le.patch b/srcpkgs/electron13/files/musl-patches/chromium-musl-xxx-ppc64le.patch
new file mode 100644
index 000000000000..9001a2a854d0
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-musl-xxx-ppc64le.patch
@@ -0,0 +1,190 @@
+diff --git sandbox/linux/bpf_dsl/seccomp_macros.h sandbox/linux/bpf_dsl/seccomp_macros.h
+index a6aec544e..2a4a7f1bc 100644
+--- sandbox/linux/bpf_dsl/seccomp_macros.h
++++ sandbox/linux/bpf_dsl/seccomp_macros.h
+@@ -16,7 +16,7 @@
+ #if defined(__mips__)
+ // sys/user.h in eglibc misses size_t definition
+ #include <stddef.h>
+-#elif defined(__powerpc64__)
++#elif defined(__powerpc64__) && defined(__GLIBC__)
+ // Manually define greg_t on ppc64
+ typedef unsigned long long greg_t;
+ #endif
+@@ -361,11 +361,11 @@ typedef struct pt_regs regs_struct;
+ #define SECCOMP_ARCH AUDIT_ARCH_PPC64
+ #endif
+ 
+-#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.regs->gpr[_reg])
++#define SECCOMP_REG(_ctx, _reg) (((struct pt_regs *)(_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_IP(_ctx) ((struct pt_regs *)(_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)
+diff --git sandbox/linux/seccomp-bpf/syscall.cc sandbox/linux/seccomp-bpf/syscall.cc
+index d53a7ff56..c290f0e92 100644
+--- sandbox/linux/seccomp-bpf/syscall.cc
++++ sandbox/linux/seccomp-bpf/syscall.cc
+@@ -499,9 +499,9 @@ void Syscall::PutValueInUcontext(intptr_t ret_val, ucontext_t* ctx) {
+   // 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);
++    ((struct pt_regs *)ctx->uc_mcontext.regs)->ccr |= (1 << 28);
+   } else {
+-    ctx->uc_mcontext.regs->ccr &= ~(1 << 28);
++    ((struct pt_regs *)ctx->uc_mcontext.regs)->ccr &= ~(1 << 28);
+   }
+ #endif
+   SECCOMP_RESULT(ctx) = static_cast<greg_t>(ret_val);
+diff --git third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h
+index cdce9bf8..73d77dda 100644
+--- third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h
++++ third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h
+@@ -46,7 +46,7 @@
+ 
+ // The following platforms have an implementation of a hardware counter.
+ #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
+-  defined(__powerpc__) || defined(__ppc__) || \
++  ((defined(__powerpc__) || defined(__ppc__)) && defined(__GLIBC__)) || \
+   defined(_M_IX86) || defined(_M_X64)
+ #define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1
+ #else
+--- third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h
++++ third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h
+@@ -64,7 +64,7 @@
+ #elif defined(__i386__) || defined(__x86_64__)
+ #define ABSL_STACKTRACE_INL_HEADER \
+   "absl/debugging/internal/stacktrace_x86-inl.inc"
+-#elif defined(__ppc__) || defined(__PPC__)
++#elif (defined(__ppc__) || defined(__PPC__)) && defined(__GLIBC__)
+ #define ABSL_STACKTRACE_INL_HEADER \
+   "absl/debugging/internal/stacktrace_powerpc-inl.inc"
+ #elif defined(__aarch64__)
+diff --git third_party/breakpad/BUILD.gn third_party/breakpad/BUILD.gn
+index f9a60e37..25f3a0b7 100644
+--- third_party/breakpad/BUILD.gn
++++ third_party/breakpad/BUILD.gn
+@@ -637,6 +637,7 @@ if (is_linux || is_android) {
+ 
+     if (current_cpu == "ppc64") {
+         defines = [ "HAVE_GETCONTEXT" ]
++        libs += [ "ucontext" ]
+     } else {
+         sources += [
+             "breakpad/src/common/linux/breakpad_getcontext.S"
+diff --git third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
+index 03afec7a..0264ecf1 100644
+--- third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
++++ third_party/breakpad/breakpad/src/client/linux/dump_writer_common/thread_info.cc
+@@ -273,6 +273,9 @@ void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+ 
+ #elif defined(__powerpc64__)
+ 
++#include <asm/elf.h>
++#include <asm/ptrace.h>
++
+ uintptr_t ThreadInfo::GetInstructionPointer() const {
+     return mcontext.gp_regs[PT_NIP];
+ }
+@@ -290,9 +293,9 @@ void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+     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.fpregs[i] = ((uint64_t *)&mcontext.fp_regs)[i];
+ 
+-    out->float_save.fpscr = mcontext.fp_regs[NFPREG-1];
++    out->float_save.fpscr = ((uint64_t *)&mcontext.fp_regs)[ELF_NFPREG-1];
+ 
+     for (int i = 0; i < MD_VECTORSAVEAREA_PPC_VR_COUNT; i++)
+         out->vector_save.save_vr[i] = \
+diff --git third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
+index 1090470f..e580233d 100644
+--- third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
++++ third_party/breakpad/breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc
+@@ -257,6 +257,9 @@ void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc) {
+ 
+ #elif defined(__powerpc64__)
+ 
++#include <asm/elf.h>
++#include <asm/ptrace.h>
++
+ uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
+     return uc->uc_mcontext.gp_regs[MD_CONTEXT_PPC64_REG_SP];
+ }
+@@ -280,9 +283,9 @@ void UContextReader::FillCPUContext(RawContextCPU* out, const ucontext_t* uc,
+     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.fpregs[i] = ((uint64_t *)&uc->uc_mcontext.fp_regs)[i];
+ 
+-    out->float_save.fpscr = uc->uc_mcontext.fp_regs[NFPREG-1];
++    out->float_save.fpscr = ((uint64_t *)&uc->uc_mcontext.fp_regs)[ELF_NFPREG-1];
+ 
+     for (int i = 0; i < MD_VECTORSAVEAREA_PPC_VR_COUNT; i++)
+         out->vector_save.save_vr[i] =
+diff --git third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
+index 5a7ab50c..ee8b858c 100644
+--- third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
++++ third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc
+@@ -105,6 +105,11 @@
+ #define PR_SET_PTRACER 0x59616d61
+ #endif
+ 
++/* musl hack, can't include asm/ptrace.h as that causes conflicts */
++#if defined(__powerpc64__) && !defined(PT_NIP)
++#define PT_NIP 32
++#endif
++
+ namespace google_breakpad {
+ 
+ namespace {
+diff --git third_party/crashpad/crashpad/snapshot/linux/signal_context.h third_party/crashpad/crashpad/snapshot/linux/signal_context.h
+index 8e335a09..b2a0f155 100644
+--- third_party/crashpad/crashpad/snapshot/linux/signal_context.h
++++ third_party/crashpad/crashpad/snapshot/linux/signal_context.h
+@@ -469,7 +469,7 @@ struct MContext64 {
+   SignalThreadContext64 gp_regs;
+   SignalFloatContext64  fp_regs;
+   SignalVectorContext64 *v_regs;
+-  int64_t vmx_reserve[69];
++  int64_t vmx_reserve[101];
+ };
+ 
+ struct ContextTraits64 : public Traits64 {
+diff --git third_party/crashpad/crashpad/util/linux/thread_info.h third_party/crashpad/crashpad/util/linux/thread_info.h
+index dea0d1f3..b203e5b2 100644
+--- third_party/crashpad/crashpad/util/linux/thread_info.h
++++ third_party/crashpad/crashpad/util/linux/thread_info.h
+@@ -30,6 +30,7 @@
+ 
+ #if defined(ARCH_CPU_PPC64_FAMILY)
+ #include <sys/ucontext.h>
++#include <asm/ptrace.h>
+ #endif
+ 
+ namespace crashpad {
+diff --git third_party/lss/linux_syscall_support.h third_party/lss/linux_syscall_support.h
+index 9955ce44..4c1cc488 100644
+--- third_party/lss/linux_syscall_support.h
++++ third_party/lss/linux_syscall_support.h
+@@ -4216,9 +4216,13 @@ struct kernel_statfs {
+     }
+   #endif
+   #if defined(__NR_fstatat64)
++    // musl does #define fstatat64 fstatat
++    #undef fstatat64
+     LSS_INLINE _syscall4(int,   fstatat64,        int,   d,
+                          const char *,      p,
+                          struct kernel_stat64 *,   b,    int,   f)
++    // set it back like it was
++    #define fstatat64 fstatat
+   #endif
+   #if defined(__NR_waitpid)
+     // waitpid is polyfilled below when not available.
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-no-mallinfo.patch b/srcpkgs/electron13/files/musl-patches/chromium-no-mallinfo.patch
new file mode 100644
index 000000000000..254a1f632da5
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-no-mallinfo.patch
@@ -0,0 +1,54 @@
+--- base/trace_event/malloc_dump_provider.cc.orig
++++ base/trace_event/malloc_dump_provider.cc
+@@ -243,7 +243,7 @@
+   allocated_objects_count = main_heap_info.block_count;
+ #elif defined(OS_FUCHSIA)
+ // TODO(fuchsia): Port, see https://crbug.com/706592.
+-#else
++#elif defined(__GLIBC__)
+   struct mallinfo info = mallinfo();
+   DCHECK_GE(info.arena + info.hblkhd, info.uordblks);
+ 
+--- base/process/process_metrics_posix.cc.orig	2020-11-18 23:50:33.958223497 -0500
++++ base/process/process_metrics_posix.cc	2020-11-18 23:53:52.024589316 -0500
+@@ -119,14 +119,14 @@
+   malloc_statistics_t stats = {0};
+   malloc_zone_statistics(nullptr, &stats);
+   return stats.size_in_use;
+-#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
++#elif defined(__GLIBC__) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
+   struct mallinfo minfo = mallinfo();
+ #if BUILDFLAG(USE_TCMALLOC)
+   return minfo.uordblks;
+ #else
+   return minfo.hblkhd + minfo.arena;
+ #endif
+-#elif defined(OS_FUCHSIA)
++#else
+   // TODO(fuchsia): Not currently exposed. https://crbug.com/735087.
+   return 0;
+ #endif
+--- third_party/swiftshader/third_party/llvm-subzero/lib/Support/Unix/Process.inc
++++ third_party/swiftshader/third_party/llvm-subzero/lib/Support/Unix/Process.inc.orig
+@@ -84,7 +84,7 @@
+ }
+ 
+ size_t Process::GetMallocUsage() {
+-#if defined(HAVE_MALLINFO)
++#if defined(HAVE_MALLINFO) && defined(__GLIBC__)
+   struct mallinfo mi;
+   mi = ::mallinfo();
+   return mi.uordblks;
+
+--- third_party/swiftshader/third_party/llvm-10.0/configs/linux/include/llvm/Config/config.h.orig	2019-09-30 13:03:42.556880537 -0400
++++ third_party/swiftshader/third_party/llvm-10.0/configs/linux/include/llvm/Config/config.h	2019-09-30 13:07:27.989821227 -0400
+@@ -122,7 +122,9 @@
+ /* #undef HAVE_MALLCTL */
+ 
+ /* Define to 1 if you have the `mallinfo' function. */
++#if defined(__GLIBC__)
+ #define HAVE_MALLINFO 1
++#endif
+ 
+ /* Define to 1 if you have the <malloc.h> header file. */
+ #define HAVE_MALLOC_H 1
diff --git a/srcpkgs/electron13/files/musl-patches/chromium-resolver.patch b/srcpkgs/electron13/files/musl-patches/chromium-resolver.patch
new file mode 100644
index 000000000000..29fe2d2f1f3c
--- /dev/null
+++ b/srcpkgs/electron13/files/musl-patches/chromium-resolver.patch
@@ -0,0 +1,38 @@
+--- net/dns/host_resolver_manager.cc.orig	2020-10-09 16:39:12.064069835 -0400
++++ net/dns/host_resolver_manager.cc	2020-10-09 16:42:49.738302772 -0400
+@@ -2779,8 +2779,7 @@
+   NetworkChangeNotifier::AddConnectionTypeObserver(this);
+   if (system_dns_config_notifier_)
+     system_dns_config_notifier_->AddObserver(this);
+-#if defined(OS_POSIX) && !defined(OS_APPLE) && !defined(OS_OPENBSD) && \
+-    !defined(OS_ANDROID)
++#if defined(__GLIBC__)
+   EnsureDnsReloaderInit();
+ #endif
+ 
+--- net/dns/dns_reloader.cc.orig	2020-10-09 16:39:12.064069835 -0400
++++ net/dns/dns_reloader.cc	2020-10-09 16:44:30.442419823 -0400
+@@ -4,9 +4,8 @@
+ 
+ #include "net/dns/dns_reloader.h"
+ 
+-#if defined(OS_POSIX) && !defined(OS_APPLE) && !defined(OS_OPENBSD) && \
+-    !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+-
++#if defined(__GLIBC__)
++ 
+ #include <resolv.h>
+ 
+ #include "base/lazy_instance.h"
+--- net/dns/host_resolver_proc.cc.orig	2020-10-09 16:39:12.065069836 -0400
++++ net/dns/host_resolver_proc.cc	2020-10-09 16:45:09.641466644 -0400
+@@ -159,8 +159,7 @@
+   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                 base::BlockingType::WILL_BLOCK);
+ 
+-#if defined(OS_POSIX) && !defined(OS_APPLE) && !defined(OS_OPENBSD) && \
+-    !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
++#if defined(__GLIBC__)
+   DnsReloaderMaybeReload();
+ #endif
+   base::Optional<AddressInfo> ai;
diff --git a/srcpkgs/electron13/files/patches/chromium-browser-size_t.patch b/srcpkgs/electron13/files/patches/chromium-browser-size_t.patch
new file mode 100644
index 000000000000..36af0ec6c4a7
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-browser-size_t.patch
@@ -0,0 +1,10 @@
+--- a/chrome/browser/search/background/ntp_backgrounds.h	2020-08-10 20:39:20.000000000 +0200
++++ b/chrome/browser/search/background/ntp_backgrounds.h	2020-09-04 13:48:22.640023256 +0200
+@@ -6,6 +6,7 @@
+ #define CHROME_BROWSER_SEARCH_BACKGROUND_NTP_BACKGROUNDS_H_
+ 
+ #include <array>
++#include <cstddef>
+ 
+ class GURL;
+ 
diff --git a/srcpkgs/electron13/files/patches/chromium-libc_malloc.patch b/srcpkgs/electron13/files/patches/chromium-libc_malloc.patch
new file mode 100644
index 000000000000..364666caa749
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-libc_malloc.patch
@@ -0,0 +1,26 @@
+--- a/base/process/memory_linux.cc.orig	2017-09-15 08:41:43.000000000 +0000
++++ a/base/process/memory_linux.cc	2017-09-15 08:44:39.804995469 +0000
+@@ -21,6 +21,12 @@
+ #include "third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h"
+ #endif
+ 
++#if defined(LIBC_GLIBC)
++extern "C" {
++extern void *__libc_malloc(size_t size);
++}
++#endif
++
+ namespace base {
+ 
+ size_t g_oom_size = 0U;
+--- a/base/process/memory_linux.cc.orig	2020-08-30 14:18:35.401132593 -0400
++++ a/base/process/memory_linux.cc	2020-08-30 14:19:08.030199189 -0400
+@@ -141,7 +141,7 @@
+     (!defined(LIBC_GLIBC) && !BUILDFLAG(USE_TCMALLOC))
+   *result = malloc(size);
+ #elif defined(LIBC_GLIBC) && !BUILDFLAG(USE_TCMALLOC)
+-  *result = __libc_malloc(size);
++  *result = ::__libc_malloc(size);
+ #elif BUILDFLAG(USE_TCMALLOC)
+   *result = tc_malloc_skip_new_handler(size);
+ #endif
diff --git a/srcpkgs/electron13/files/patches/chromium-musl-v8-monotonic-pthread-cont_timedwait.patch b/srcpkgs/electron13/files/patches/chromium-musl-v8-monotonic-pthread-cont_timedwait.patch
new file mode 100644
index 000000000000..cb2e715fe206
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-musl-v8-monotonic-pthread-cont_timedwait.patch
@@ -0,0 +1,24 @@
+Use monotonic clock for pthread_cond_timedwait with musl too.
+
+diff --git a/v8/src/base/platform/condition-variable.cc b/v8/src/base/platform/condition-variable.cc
+index 5ea7083..c13027e 100644
+--- a/v8/src/base/platform/condition-variable.cc
++++ a/v8/src/base/platform/condition-variable.cc
+@@ -16,7 +16,7 @@ namespace base {
+ 
+ ConditionVariable::ConditionVariable() {
+ #if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
+-     (V8_OS_LINUX && V8_LIBC_GLIBC))
++     V8_OS_LINUX)
+   // On Free/Net/OpenBSD and Linux with glibc we can change the time
+   // source for pthread_cond_timedwait() to use the monotonic clock.
+   pthread_condattr_t attr;
+@@ -92,7 +92,7 @@ bool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) {
+       &native_handle_, &mutex->native_handle(), &ts);
+ #else
+ #if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
+-     (V8_OS_LINUX && V8_LIBC_GLIBC))
++     V8_OS_LINUX)
+   // On Free/Net/OpenBSD and Linux with glibc we can change the time
+   // source for pthread_cond_timedwait() to use the monotonic clock.
+   result = clock_gettime(CLOCK_MONOTONIC, &ts);
diff --git a/srcpkgs/electron13/files/patches/chromium-no-execinfo.patch b/srcpkgs/electron13/files/patches/chromium-no-execinfo.patch
new file mode 100644
index 000000000000..3cede1b0a571
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-no-execinfo.patch
@@ -0,0 +1,72 @@
+--- a/base/debug/stack_trace_posix.cc.orig	2019-05-14 14:49:44.000000000 -0400
++++ a/base/debug/stack_trace_posix.cc	2019-07-02 10:43:43.490045013 -0400
+@@ -27,7 +27,7 @@
+ #if !defined(USE_SYMBOLIZE)
+ #include <cxxabi.h>
+ #endif
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+ #include <execinfo.h>
+ #endif
+ 
+@@ -86,7 +86,7 @@
+   // Note: code in this function is NOT async-signal safe (std::string uses
+   // malloc internally).
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+   std::string::size_type search_from = 0;
+   while (search_from < text->size()) {
+     // Look for the start of a mangled symbol, from search_from.
+@@ -121,7 +121,7 @@
+       search_from = mangled_start + 2;
+     }
+   }
+-#endif  // !defined(__UCLIBC__) && !defined(_AIX)
++#endif  // defined(__GLIBC__) && !defined(_AIX)
+ }
+ #endif  // !defined(USE_SYMBOLIZE)
+ 
+@@ -133,7 +133,7 @@
+   virtual ~BacktraceOutputHandler() = default;
+ };
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+ void OutputPointer(void* pointer, BacktraceOutputHandler* handler) {
+   // This should be more than enough to store a 64-bit number in hex:
+   // 16 hex digits + 1 for null-terminator.
+@@ -216,7 +216,7 @@
+   }
+ #endif  // defined(USE_SYMBOLIZE)
+ }
+-#endif  // !defined(__UCLIBC__) && !defined(_AIX)
++#endif  // defined(__GLIBC__) && !defined(_AIX)
+ 
+ void PrintToStderr(const char* output) {
+   // NOTE: This code MUST be async-signal safe (it's used by in-process
+@@ -812,7 +812,7 @@
+   // NOTE: This code MUST be async-signal safe (it's used by in-process
+   // stack dumping signal handler). NO malloc or stdio is allowed here.
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+   // Though the backtrace API man page does not list any possible negative
+   // return values, we take no chance.
+   return base::saturated_cast<size_t>(backtrace(trace, count));
+@@ -825,13 +825,13 @@
+ // NOTE: This code MUST be async-signal safe (it's used by in-process
+ // stack dumping signal handler). NO malloc or stdio is allowed here.
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+   PrintBacktraceOutputHandler handler;
+   ProcessBacktrace(trace_, count_, prefix_string, &handler);
+ #endif
+ }
+ 
+-#if !defined(__UCLIBC__) && !defined(_AIX)
++#if defined(__GLIBC__) && !defined(_AIX)
+ void StackTrace::OutputToStreamWithPrefix(std::ostream* os,
+                                           const char* prefix_string) const {
+   StreamBacktraceOutputHandler handler(os);
diff --git a/srcpkgs/electron13/files/patches/chromium-no-getcontext.patch b/srcpkgs/electron13/files/patches/chromium-no-getcontext.patch
new file mode 100644
index 000000000000..2502b5a06acb
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-no-getcontext.patch
@@ -0,0 +1,27 @@
+--- a/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc.orig	2015-12-06 09:59:55.554536646 +0100
++++ a/third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.cc	2015-12-06 10:01:16.818238035 +0100
+@@ -477,7 +477,9 @@ bool ExceptionHandler::SimulateSignalDel
+   siginfo.si_code = SI_USER;
+   siginfo.si_pid = getpid();
+   ucontext_t context;
++#if defined(__GLIBC__)
+   getcontext(&context);
++#endif
+   return HandleSignal(sig, &siginfo, &context);
+ }
+ 
+@@ -647,9 +649,14 @@ bool ExceptionHandler::WriteMinidump() {
+   sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
+ 
+   CrashContext context;
++
++#if defined(__GLIBC__)
+   int getcontext_result = getcontext(&context.context);
+   if (getcontext_result)
+     return false;
++#else
++  return false;
++#endif
+ 
+ #if defined(__i386__)
+   // In CPUFillFromUContext in minidumpwriter.cc the stack pointer is retrieved
diff --git a/srcpkgs/electron13/files/patches/chromium-revert-drop-of-system-java.patch b/srcpkgs/electron13/files/patches/chromium-revert-drop-of-system-java.patch
new file mode 100644
index 000000000000..c3f97c7c4d1c
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-revert-drop-of-system-java.patch
@@ -0,0 +1,15 @@
+This was dropped for some reason in 6951c37cecd05979b232a39e5c10e6346a0f74ef
+--- a/third_party/closure_compiler/compiler.py	2021-05-20 04:17:53.000000000 +0200
++++ -	2021-05-25 20:31:10.102971765 +0200
+@@ -13,8 +13,9 @@
+ 
+ 
+ _CURRENT_DIR = os.path.join(os.path.dirname(__file__))
+-_JAVA_PATH = os.path.join(_CURRENT_DIR, "..", "jdk", "current", "bin", "java")
+-assert os.path.isfile(_JAVA_PATH), "java only allowed in android builds"
++_JAVA_BIN = "java"
++_JDK_PATH = os.path.join(_CURRENT_DIR, "..", "jdk", "current", "bin", "java")
++_JAVA_PATH = _JDK_PATH if os.path.isfile(_JDK_PATH) else _JAVA_BIN
+ 
+ class Compiler(object):
+   """Runs the Closure compiler on given source files to typecheck them
diff --git a/srcpkgs/electron13/files/patches/chromium-sandbox-membarrier.patch b/srcpkgs/electron13/files/patches/chromium-sandbox-membarrier.patch
new file mode 100644
index 000000000000..998552c2f9e7
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-sandbox-membarrier.patch
@@ -0,0 +1,10 @@
+--- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
++++ a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+@@ -370,6 +370,7 @@
+   switch (sysno) {
+     case __NR_exit:
+     case __NR_exit_group:
++    case __NR_membarrier:
+     case __NR_wait4:
+     case __NR_waitid:
+ #if defined(__i386__)
diff --git a/srcpkgs/electron13/files/patches/chromium-sandbox-sched_getparam.patch b/srcpkgs/electron13/files/patches/chromium-sandbox-sched_getparam.patch
new file mode 100644
index 000000000000..87f11af43c04
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-sandbox-sched_getparam.patch
@@ -0,0 +1,20 @@
+Allow SYS_sched_getparam and SYS_sched_getscheduler
+musl uses them for pthread_getschedparam()
+
+source: https://git.alpinelinux.org/aports/commit/community/chromium?id=54af9f8ac24f52d382c5758e2445bf0206eff40e
+
+--- a/sandbox/policy/linux/bpf_renderer_policy_linux.cc.orig	2019-10-08 21:03:18.253080425 +0200
++++ a/sandbox/policy/linux/bpf_renderer_policy_linux.cc	2019-10-08 21:04:19.648549718 +0200
+@@ -88,10 +88,10 @@
+     case __NR_sysinfo:
+     case __NR_times:
+     case __NR_uname:
+-      return Allow();
+-    case __NR_sched_getaffinity:
+     case __NR_sched_getparam:
+     case __NR_sched_getscheduler:
++      return Allow();
++    case __NR_sched_getaffinity:
+     case __NR_sched_setscheduler:
+       return sandbox::RestrictSchedTarget(GetPolicyPid(), sysno);
+     case __NR_prlimit64:
diff --git a/srcpkgs/electron13/files/patches/chromium-sndio.patch b/srcpkgs/electron13/files/patches/chromium-sndio.patch
new file mode 100644
index 000000000000..4cab48d50821
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-sndio.patch
@@ -0,0 +1,886 @@
+diff -Naur chromium-83.0.4103.97.orig/media/BUILD.gn chromium-83.0.4103.97/media/BUILD.gn
+--- a/media/BUILD.gn.orig	2020-06-03 20:40:26.000000000 +0200
++++ a/media/BUILD.gn	2020-06-13 17:32:28.510395975 +0200
+@@ -65,6 +65,9 @@
+       defines += [ "DLOPEN_PULSEAUDIO" ]
+     }
+   }
++  if (use_sndio) {
++    defines += [ "USE_SNDIO" ]
++  }
+   if (use_cras) {
+     defines += [ "USE_CRAS" ]
+   }
+diff -Naur chromium-83.0.4103.97.orig/media/audio/BUILD.gn chromium-83.0.4103.97/media/audio/BUILD.gn
+--- a/media/audio/BUILD.gn.orig	2020-06-03 20:39:37.000000000 +0200
++++ a/media/audio/BUILD.gn	2020-06-13 17:32:28.511395969 +0200
+@@ -236,6 +236,17 @@
+     sources += [ "linux/audio_manager_linux.cc" ]
+   }
+ 
++  if (use_sndio) {
++    libs += [ "sndio" ]
++    sources += [
++      "sndio/audio_manager_sndio.cc",
++      "sndio/sndio_input.cc",
++      "sndio/sndio_input.h",
++      "sndio/sndio_output.cc",
++      "sndio/sndio_output.h"
++    ]
++  }
++
+   if (use_alsa) {
+     libs += [ "asound" ]
+     sources += [
+diff -Naur chromium-83.0.4103.97.orig/media/audio/linux/audio_manager_linux.cc chromium-83.0.4103.97/media/audio/linux/audio_manager_linux.cc
+--- a/media/audio/linux/audio_manager_linux.cc.orig	2020-06-03 20:39:37.000000000 +0200
++++ a/media/audio/linux/audio_manager_linux.cc	2020-06-13 18:09:43.623333167 +0200
+@@ -19,6 +19,11 @@
+ #include "media/audio/pulse/audio_manager_pulse.h"
+ #include "media/audio/pulse/pulse_util.h"
+ #endif
++#if defined(USE_SNDIO)
++#include "media/audio/sndio/audio_manager_sndio.h"
++#include "media/audio/sndio/sndio_input.h"
++#include "media/audio/sndio/sndio_output.h"
++#endif
+ 
+ namespace media {
+ 
+@@ -26,7 +31,8 @@
+   kPulse,
+   kAlsa,
+   kCras,
+-  kAudioIOMax = kCras  // Must always be equal to largest logged entry.
++  kSndio,
++  kAudioIOMax = kSndio // Must always be equal to largest logged entry.
+ };
+ 
+ std::unique_ptr<media::AudioManager> CreateAudioManager(
+@@ -39,6 +45,16 @@
+                                               audio_log_factory);
+   }
+ 
++#if defined(USE_SNDIO)
++  struct sio_hdl *hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
++  if (hdl != NULL) {
++    sio_close(hdl);
++    UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kSndio, kAudioIOMax + 1);
++    return std::make_unique<AudioManagerSndio>(std::move(audio_thread),
++                                                  audio_log_factory);
++  }
++#endif
++
+ #if defined(USE_CRAS)
+   if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseCras)) {
+     UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kCras, kAudioIOMax + 1);
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/audio_manager_sndio.cc chromium-83.0.4103.97/media/audio/sndio/audio_manager_sndio.cc
+--- a/media/audio/sndio/audio_manager_sndio.cc.orig	1970-01-01 01:00:00.000000000 +0100
++++ a/media/audio/sndio/audio_manager_sndio.cc	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,148 @@
++// Copyright (c) 2012 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.
++
++#include "media/audio/sndio/audio_manager_sndio.h"
++
++#include "base/metrics/histogram_macros.h"
++#include "base/memory/ptr_util.h"
++#include "media/audio/audio_device_description.h"
++#include "media/audio/audio_output_dispatcher.h"
++#include "media/audio/sndio/sndio_input.h"
++#include "media/audio/sndio/sndio_output.h"
++#include "media/base/limits.h"
++#include "media/base/media_switches.h"
++
++namespace media {
++
++
++// Maximum number of output streams that can be open simultaneously.
++static const int kMaxOutputStreams = 4;
++
++// Default sample rate for input and output streams.
++static const int kDefaultSampleRate = 48000;
++
++void AddDefaultDevice(AudioDeviceNames* device_names) {
++  DCHECK(device_names->empty());
++  device_names->push_front(AudioDeviceName::CreateDefault());
++}
++
++bool AudioManagerSndio::HasAudioOutputDevices() {
++  return true;
++}
++
++bool AudioManagerSndio::HasAudioInputDevices() {
++  return true;
++}
++
++void AudioManagerSndio::GetAudioInputDeviceNames(
++    AudioDeviceNames* device_names) {
++  DCHECK(device_names->empty());
++  AddDefaultDevice(device_names);
++}
++
++void AudioManagerSndio::GetAudioOutputDeviceNames(
++    AudioDeviceNames* device_names) {
++  AddDefaultDevice(device_names);
++}
++
++const char* AudioManagerSndio::GetName() {
++  return "SNDIO";
++}
++
++AudioParameters AudioManagerSndio::GetInputStreamParameters(
++    const std::string& device_id) {
++  static const int kDefaultInputBufferSize = 1024;
++
++  int user_buffer_size = GetUserBufferSize();
++  int buffer_size = user_buffer_size ?
++      user_buffer_size : kDefaultInputBufferSize;
++
++  return AudioParameters(
++      AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
++      kDefaultSampleRate, buffer_size);
++}
++
++AudioManagerSndio::AudioManagerSndio(std::unique_ptr<AudioThread> audio_thread,
++                                         AudioLogFactory* audio_log_factory)
++    : AudioManagerBase(std::move(audio_thread),
++                       audio_log_factory) {
++  DLOG(WARNING) << "AudioManagerSndio";
++  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
++}
++
++AudioManagerSndio::~AudioManagerSndio() {
++  Shutdown();
++}
++
++AudioOutputStream* AudioManagerSndio::MakeLinearOutputStream(
++    const AudioParameters& params,
++    const LogCallback& log_callback) {
++  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
++  return MakeOutputStream(params);
++}
++
++AudioOutputStream* AudioManagerSndio::MakeLowLatencyOutputStream(
++    const AudioParameters& params,
++    const std::string& device_id,
++    const LogCallback& log_callback) {
++  DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
++  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
++  return MakeOutputStream(params);
++}
++
++AudioInputStream* AudioManagerSndio::MakeLinearInputStream(
++    const AudioParameters& params,
++    const std::string& device_id,
++    const LogCallback& log_callback) {
++  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
++  return MakeInputStream(params);
++}
++
++AudioInputStream* AudioManagerSndio::MakeLowLatencyInputStream(
++    const AudioParameters& params,
++    const std::string& device_id,
++    const LogCallback& log_callback) {
++  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
++  return MakeInputStream(params);
++}
++
++AudioParameters AudioManagerSndio::GetPreferredOutputStreamParameters(
++    const std::string& output_device_id,
++    const AudioParameters& input_params) {
++  // TODO(tommi): Support |output_device_id|.
++  DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
++  static const int kDefaultOutputBufferSize = 2048;
++
++  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
++  int sample_rate = kDefaultSampleRate;
++  int buffer_size = kDefaultOutputBufferSize;
++  if (input_params.IsValid()) {
++    sample_rate = input_params.sample_rate();
++    channel_layout = input_params.channel_layout();
++    buffer_size = std::min(buffer_size, input_params.frames_per_buffer());
++  }
++
++  int user_buffer_size = GetUserBufferSize();
++  if (user_buffer_size)
++    buffer_size = user_buffer_size;
++
++  return AudioParameters(
++      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
++      sample_rate, buffer_size);
++}
++
++AudioInputStream* AudioManagerSndio::MakeInputStream(
++    const AudioParameters& params) {
++  DLOG(WARNING) << "MakeInputStream";
++  return new SndioAudioInputStream(this,
++             AudioDeviceDescription::kDefaultDeviceId, params);
++}
++
++AudioOutputStream* AudioManagerSndio::MakeOutputStream(
++    const AudioParameters& params) {
++  DLOG(WARNING) << "MakeOutputStream";
++  return new SndioAudioOutputStream(params, this);
++}
++
++}  // namespace media
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/audio_manager_sndio.h chromium-83.0.4103.97/media/audio/sndio/audio_manager_sndio.h
+--- a/media/audio/sndio/audio_manager_sndio.h.orig	1970-01-01 01:00:00.000000000 +0100
++++ a/media/audio/sndio/audio_manager_sndio.h	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,65 @@
++// Copyright (c) 2012 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 MEDIA_AUDIO_SNDIO_AUDIO_MANAGER_SNDIO_H_
++#define MEDIA_AUDIO_SNDIO_AUDIO_MANAGER_SNDIO_H_
++
++#include <set>
++
++#include "base/compiler_specific.h"
++#include "base/macros.h"
++#include "base/memory/ref_counted.h"
++#include "base/threading/thread.h"
++#include "media/audio/audio_manager_base.h"
++
++namespace media {
++
++class MEDIA_EXPORT AudioManagerSndio : public AudioManagerBase {
++ public:
++  AudioManagerSndio(std::unique_ptr<AudioThread> audio_thread,
++                   AudioLogFactory* audio_log_factory);
++  ~AudioManagerSndio() override;
++
++  // Implementation of AudioManager.
++  bool HasAudioOutputDevices() override;
++  bool HasAudioInputDevices() override;
++  void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
++  void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override;
++  AudioParameters GetInputStreamParameters(
++      const std::string& device_id) override;
++  const char* GetName() override;
++
++  // Implementation of AudioManagerBase.
++  AudioOutputStream* MakeLinearOutputStream(
++      const AudioParameters& params,
++      const LogCallback& log_callback) override;
++  AudioOutputStream* MakeLowLatencyOutputStream(
++      const AudioParameters& params,
++      const std::string& device_id,
++      const LogCallback& log_callback) override;
++  AudioInputStream* MakeLinearInputStream(
++      const AudioParameters& params,
++      const std::string& device_id,
++      const LogCallback& log_callback) override;
++  AudioInputStream* MakeLowLatencyInputStream(
++      const AudioParameters& params,
++      const std::string& device_id,
++      const LogCallback& log_callback) override;
++
++ protected:
++  AudioParameters GetPreferredOutputStreamParameters(
++      const std::string& output_device_id,
++      const AudioParameters& input_params) override;
++
++ private:
++  // Called by MakeLinearOutputStream and MakeLowLatencyOutputStream.
++  AudioOutputStream* MakeOutputStream(const AudioParameters& params);
++  AudioInputStream* MakeInputStream(const AudioParameters& params);
++
++  DISALLOW_COPY_AND_ASSIGN(AudioManagerSndio);
++};
++
++}  // namespace media
++
++#endif  // MEDIA_AUDIO_SNDIO_AUDIO_MANAGER_SNDIO_H_
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/sndio_input.cc chromium-83.0.4103.97/media/audio/sndio/sndio_input.cc
+--- a/media/audio/sndio/sndio_input.cc.orig	1970-01-01 01:00:00.000000000 +0100
++++ a/media/audio/sndio/sndio_input.cc	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,200 @@
++// Copyright 2013 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.
++
++#include "base/bind.h"
++#include "base/logging.h"
++#include "base/macros.h"
++#include "media/base/audio_timestamp_helper.h"
++#include "media/audio/sndio/audio_manager_sndio.h"
++#include "media/audio/audio_manager.h"
++#include "media/audio/sndio/sndio_input.h"
++
++namespace media {
++
++static const SampleFormat kSampleFormat = kSampleFormatS16;
++
++void SndioAudioInputStream::OnMoveCallback(void *arg, int delta)
++{
++  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
++
++  self->hw_delay += delta;
++}
++
++void *SndioAudioInputStream::ThreadEntry(void *arg) {
++  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
++
++  self->ThreadLoop();
++  return NULL;
++}
++
++SndioAudioInputStream::SndioAudioInputStream(AudioManagerBase* manager,
++                                             const std::string& device_name,
++                                             const AudioParameters& params)
++    : manager(manager),
++      params(params),
++      audio_bus(AudioBus::Create(params)),
++      state(kClosed) {
++}
++
++SndioAudioInputStream::~SndioAudioInputStream() {
++  if (state != kClosed)
++    Close();
++}
++
++bool SndioAudioInputStream::Open() {
++  struct sio_par par;
++  int sig;
++
++  if (state != kClosed)
++    return false;
++
++  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
++      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
++    LOG(WARNING) << "Unsupported audio format.";
++    return false;
++  }
++
++  sio_initpar(&par);
++  par.rate = params.sample_rate();
++  par.rchan = params.channels();
++  par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
++  par.bps = par.bits / 8;
++  par.sig = sig = par.bits != 8 ? 1 : 0;
++  par.le = SIO_LE_NATIVE;
++  par.appbufsz = params.frames_per_buffer();
++
++  hdl = sio_open(SIO_DEVANY, SIO_REC, 0);
++
++  if (hdl == NULL) {
++    LOG(ERROR) << "Couldn't open audio device.";
++    return false;
++  }
++
++  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
++    LOG(ERROR) << "Couldn't set audio parameters.";
++    goto bad_close;
++  }
++
++  if (par.rate  != (unsigned int)params.sample_rate() ||
++      par.rchan != (unsigned int)params.channels() ||
++      par.bits  != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
++      par.sig   != (unsigned int)sig ||
++      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
++      (par.bits != par.bps * 8)) {
++    LOG(ERROR) << "Unsupported audio parameters.";
++    goto bad_close;
++  }
++  state = kStopped;
++  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
++  sio_onmove(hdl, &OnMoveCallback, this);
++  return true;
++bad_close:
++  sio_close(hdl);
++  return false;
++}
++
++void SndioAudioInputStream::Start(AudioInputCallback* cb) {
++
++  StartAgc();
++
++  state = kRunning;
++  hw_delay = 0;
++  callback = cb;
++  sio_start(hdl);
++  if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
++    LOG(ERROR) << "Failed to create real-time thread for recording.";
++    sio_stop(hdl);
++    state = kStopped;
++  }
++}
++
++void SndioAudioInputStream::Stop() {
++
++  if (state == kStopped)
++    return;
++
++  state = kStopWait;
++  pthread_join(thread, NULL);
++  sio_stop(hdl);
++  state = kStopped;
++
++  StopAgc();
++}
++
++void SndioAudioInputStream::Close() {
++
++  if (state == kClosed)
++    return;
++
++  if (state == kRunning)
++    Stop();
++
++  state = kClosed;
++  delete [] buffer;
++  sio_close(hdl);
++
++  manager->ReleaseInputStream(this);
++}
++
++double SndioAudioInputStream::GetMaxVolume() {
++  // Not supported
++  return 0.0;
++}
++
++void SndioAudioInputStream::SetVolume(double volume) {
++  // Not supported. Do nothing.
++}
++
++double SndioAudioInputStream::GetVolume() {
++  // Not supported.
++  return 0.0;
++}
++
++bool SndioAudioInputStream::IsMuted() {
++  // Not supported.
++  return false;
++}
++
++void SndioAudioInputStream::SetOutputDeviceForAec(
++    const std::string& output_device_id) {
++  // Not supported.
++}
++
++void SndioAudioInputStream::ThreadLoop(void) {
++  size_t todo, n;
++  char *data;
++  unsigned int nframes;
++  double normalized_volume = 0.0;
++
++  nframes = audio_bus->frames();
++
++  while (state == kRunning && !sio_eof(hdl)) {
++
++    GetAgcVolume(&normalized_volume);
++
++    // read one block
++    todo = nframes * params.GetBytesPerFrame(kSampleFormat);
++    data = buffer;
++    while (todo > 0) {
++      n = sio_read(hdl, data, todo);
++      if (n == 0)
++        return;	// unrecoverable I/O error
++      todo -= n;
++      data += n;
++    }
++    hw_delay -= nframes;
++
++    // convert frames count to TimeDelta
++    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
++      params.sample_rate());
++
++    // push into bus
++    audio_bus->FromInterleaved(buffer, nframes, SampleFormatToBytesPerChannel(kSampleFormat));
++
++    // invoke callback
++    callback->OnData(audio_bus.get(), base::TimeTicks::Now() - delay, 1.);
++  }
++}
++
++}  // namespace media
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/sndio_input.h chromium-83.0.4103.97/media/audio/sndio/sndio_input.h
+--- a/media/audio/sndio/sndio_input.h.orig	1970-01-01 01:00:00.000000000 +0100
++++ a/media/audio/sndio/sndio_input.h	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,91 @@
++// Copyright 2013 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 MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
++#define MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
++
++#include <stdint.h>
++#include <string>
++#include <sndio.h>
++
++#include "base/compiler_specific.h"
++#include "base/macros.h"
++#include "base/memory/weak_ptr.h"
++#include "base/time/time.h"
++#include "media/audio/agc_audio_stream.h"
++#include "media/audio/audio_io.h"
++#include "media/audio/audio_device_description.h"
++#include "media/base/audio_parameters.h"
++
++namespace media {
++
++class AudioManagerBase;
++
++// Implementation of AudioOutputStream using sndio(7)
++class SndioAudioInputStream : public AgcAudioStream<AudioInputStream> {
++ public:
++  // Pass this to the constructor if you want to attempt auto-selection
++  // of the audio recording device.
++  static const char kAutoSelectDevice[];
++
++  // Create a PCM Output stream for the SNDIO device identified by
++  // |device_name|. If unsure of what to use for |device_name|, use
++  // |kAutoSelectDevice|.
++  SndioAudioInputStream(AudioManagerBase* audio_manager,
++                     const std::string& device_name,
++                     const AudioParameters& params);
++
++  ~SndioAudioInputStream() override;
++
++  // Implementation of AudioInputStream.
++  bool Open() override;
++  void Start(AudioInputCallback* callback) override;
++  void Stop() override;
++  void Close() override;
++  double GetMaxVolume() override;
++  void SetVolume(double volume) override;
++  double GetVolume() override;
++  bool IsMuted() override;
++  void SetOutputDeviceForAec(const std::string& output_device_id) override;
++
++ private:
++
++  enum StreamState {
++    kClosed,            // Not opened yet
++    kStopped,           // Device opened, but not started yet
++    kRunning,           // Started, device playing
++    kStopWait           // Stopping, waiting for the real-time thread to exit
++  };
++
++  // C-style call-backs
++  static void OnMoveCallback(void *arg, int delta);
++  static void* ThreadEntry(void *arg);
++
++  // Continuously moves data from the device to the consumer
++  void ThreadLoop();
++  // Our creator, the audio manager needs to be notified when we close.
++  AudioManagerBase* manager;
++  // Parameters of the source
++  AudioParameters params;
++  // We store data here for consumer
++  std::unique_ptr<AudioBus> audio_bus;
++  // Call-back that consumes recorded data
++  AudioInputCallback* callback;  // Valid during a recording session.
++  // Handle of the audio device
++  struct sio_hdl* hdl;
++  // Current state of the stream
++  enum StreamState state;
++  // High priority thread running ThreadLoop()
++  pthread_t thread;
++  // Number of frames buffered in the hardware
++  int hw_delay;
++  // Temporary buffer where data is stored sndio-compatible format
++  char* buffer;
++
++  DISALLOW_COPY_AND_ASSIGN(SndioAudioInputStream);
++};
++
++}  // namespace media
++
++#endif  // MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/sndio_output.cc chromium-83.0.4103.97/media/audio/sndio/sndio_output.cc
+--- a/media/audio/sndio/sndio_output.cc.orig	1970-01-01 01:00:00.000000000 +0100
++++ a/media/audio/sndio/sndio_output.cc	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,183 @@
++// Copyright (c) 2012 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.
++
++#include "base/logging.h"
++#include "base/time/time.h"
++#include "base/time/default_tick_clock.h"
++#include "media/audio/audio_manager_base.h"
++#include "media/base/audio_timestamp_helper.h"
++#include "media/audio/sndio/sndio_output.h"
++
++namespace media {
++
++static const SampleFormat kSampleFormat = kSampleFormatS16;
++
++void SndioAudioOutputStream::OnMoveCallback(void *arg, int delta) {
++  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
++
++  self->hw_delay -= delta;
++}
++
++void SndioAudioOutputStream::OnVolCallback(void *arg, unsigned int vol) {
++  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
++
++  self->vol = vol;
++}
++
++void *SndioAudioOutputStream::ThreadEntry(void *arg) {
++  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
++
++  self->ThreadLoop();
++  return NULL;
++}
++
++SndioAudioOutputStream::SndioAudioOutputStream(const AudioParameters& params,
++                                               AudioManagerBase* manager)
++    : manager(manager),
++      params(params),
++      audio_bus(AudioBus::Create(params)),
++      state(kClosed),
++      mutex(PTHREAD_MUTEX_INITIALIZER) {
++}
++
++SndioAudioOutputStream::~SndioAudioOutputStream() {
++  if (state != kClosed)
++    Close();
++}
++
++bool SndioAudioOutputStream::Open() {
++  struct sio_par par;
++  int sig;
++
++  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
++      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
++    LOG(WARNING) << "Unsupported audio format.";
++    return false;
++  }
++  sio_initpar(&par);
++  par.rate = params.sample_rate();
++  par.pchan = params.channels();
++  par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
++  par.bps = par.bits / 8;
++  par.sig = sig = par.bits != 8 ? 1 : 0;
++  par.le = SIO_LE_NATIVE;
++  par.appbufsz = params.frames_per_buffer();
++
++  hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
++  if (hdl == NULL) {
++    LOG(ERROR) << "Couldn't open audio device.";
++    return false;
++  }
++  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
++    LOG(ERROR) << "Couldn't set audio parameters.";
++    goto bad_close;
++  }
++  if (par.rate  != (unsigned int)params.sample_rate() ||
++      par.pchan != (unsigned int)params.channels() ||
++      par.bits  != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
++      par.sig   != (unsigned int)sig ||
++      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
++      (par.bits != par.bps * 8)) {
++    LOG(ERROR) << "Unsupported audio parameters.";
++    goto bad_close;
++  }
++  state = kStopped;
++  volpending = 0;
++  vol = 0;
++  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
++  sio_onmove(hdl, &OnMoveCallback, this);
++  sio_onvol(hdl, &OnVolCallback, this);
++  return true;
++ bad_close:
++  sio_close(hdl);
++  return false;
++}
++
++void SndioAudioOutputStream::Close() {
++  if (state == kClosed)
++    return;
++  if (state == kRunning)
++    Stop();
++  state = kClosed;
++  delete [] buffer;
++  sio_close(hdl);
++  manager->ReleaseOutputStream(this);  // Calls the destructor
++}
++
++void SndioAudioOutputStream::Start(AudioSourceCallback* callback) {
++  state = kRunning;
++  hw_delay = 0;
++  source = callback;
++  sio_start(hdl);
++  if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
++    LOG(ERROR) << "Failed to create real-time thread.";
++    sio_stop(hdl);
++    state = kStopped;
++  }
++}
++
++void SndioAudioOutputStream::Stop() {
++  if (state == kStopped)
++    return;
++  state = kStopWait;
++  pthread_join(thread, NULL);
++  sio_stop(hdl);
++  state = kStopped;
++}
++
++void SndioAudioOutputStream::SetVolume(double v) {
++  pthread_mutex_lock(&mutex);
++  vol = v * SIO_MAXVOL;
++  volpending = 1;
++  pthread_mutex_unlock(&mutex);
++}
++
++void SndioAudioOutputStream::GetVolume(double* v) {
++  pthread_mutex_lock(&mutex);
++  *v = vol * (1. / SIO_MAXVOL);
++  pthread_mutex_unlock(&mutex);
++}
++
++// This stream is always used with sub second buffer sizes, where it's
++// sufficient to simply always flush upon Start().
++void SndioAudioOutputStream::Flush() {}
++
++void SndioAudioOutputStream::ThreadLoop(void) {
++  int avail, count, result;
++
++  while (state == kRunning) {
++    // Update volume if needed
++    pthread_mutex_lock(&mutex);
++    if (volpending) {
++      volpending = 0;
++      sio_setvol(hdl, vol);
++    }
++    pthread_mutex_unlock(&mutex);
++
++    // Get data to play
++    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
++	params.sample_rate());
++    count = source->OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get());
++    audio_bus->ToInterleaved(count, SampleFormatToBytesPerChannel(kSampleFormat), buffer);
++    if (count == 0) {
++      // We have to submit something to the device
++      count = audio_bus->frames();
++      memset(buffer, 0, count * params.GetBytesPerFrame(kSampleFormat));
++      LOG(WARNING) << "No data to play, running empty cycle.";
++    }
++
++    // Submit data to the device
++    avail = count * params.GetBytesPerFrame(kSampleFormat);
++    result = sio_write(hdl, buffer, avail);
++    if (result == 0) {
++      LOG(WARNING) << "Audio device disconnected.";
++      break;
++    }
++
++    // Update hardware pointer
++    hw_delay += count;
++  }
++}
++
++}  // namespace media
+diff -Naur chromium-83.0.4103.97.orig/media/audio/sndio/sndio_output.h chromium-83.0.4103.97/media/audio/sndio/sndio_output.h
+--- a/media/audio/sndio/sndio_output.h.orig	1970-01-01 01:00:00.000000000 +0100
++++ a/media/audio/sndio/sndio_output.h	2020-06-13 17:32:28.511395969 +0200
+@@ -0,0 +1,86 @@
++// Copyright (c) 2012 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 MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
++#define MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
++
++#include <pthread.h>
++#include <sndio.h>
++
++#include "base/time/tick_clock.h"
++#include "base/time/time.h"
++#include "media/audio/audio_io.h"
++
++namespace media {
++
++class AudioManagerBase;
++
++// Implementation of AudioOutputStream using sndio(7)
++class SndioAudioOutputStream : public AudioOutputStream {
++ public:
++  // The manager is creating this object
++  SndioAudioOutputStream(const AudioParameters& params,
++                         AudioManagerBase* manager);
++  virtual ~SndioAudioOutputStream();
++
++  // Implementation of AudioOutputStream.
++  bool Open() override;
++  void Close() override;
++  void Start(AudioSourceCallback* callback) override;
++  void Stop() override;
++  void SetVolume(double volume) override;
++  void GetVolume(double* volume) override;
++  void Flush() override;
++
++  friend void sndio_onmove(void *arg, int delta);
++  friend void sndio_onvol(void *arg, unsigned int vol);
++  friend void *sndio_threadstart(void *arg);
++
++ private:
++  enum StreamState {
++    kClosed,            // Not opened yet
++    kStopped,           // Device opened, but not started yet
++    kRunning,           // Started, device playing
++    kStopWait           // Stopping, waiting for the real-time thread to exit
++  };
++
++  // C-style call-backs
++  static void OnMoveCallback(void *arg, int delta);
++  static void OnVolCallback(void *arg, unsigned int vol);
++  static void* ThreadEntry(void *arg);
++
++  // Continuously moves data from the producer to the device
++  void ThreadLoop(void);
++
++  // Our creator, the audio manager needs to be notified when we close.
++  AudioManagerBase* manager;
++  // Parameters of the source
++  AudioParameters params;
++  // Source stores data here
++  std::unique_ptr<AudioBus> audio_bus;
++  // Call-back that produces data to play
++  AudioSourceCallback* source;
++  // Handle of the audio device
++  struct sio_hdl* hdl;
++  // Current state of the stream
++  enum StreamState state;
++  // High priority thread running ThreadLoop()
++  pthread_t thread;
++  // Protects vol, volpending and hw_delay
++  pthread_mutex_t mutex;
++  // Current volume in the 0..SIO_MAXVOL range
++  int vol;
++  // Set to 1 if volumes must be refreshed in the realtime thread
++  int volpending;
++  // Number of frames buffered in the hardware
++  int hw_delay;
++  // Temporary buffer where data is stored sndio-compatible format
++  char* buffer;
++
++  DISALLOW_COPY_AND_ASSIGN(SndioAudioOutputStream);
++};
++
++}  // namespace media
++
++#endif  // MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
+diff -Naur chromium-83.0.4103.97.orig/media/media_options.gni chromium-83.0.4103.97/media/media_options.gni
+--- a/media/media_options.gni.orig	2020-06-03 20:40:26.000000000 +0200
++++ a/media/media_options.gni	2020-06-13 17:32:28.512395963 +0200
+@@ -119,6 +119,9 @@
+   # Enables runtime selection of ALSA library for audio.
+   use_alsa = false
+ 
++  # Enable runtime selection of sndio(7)
++  use_sndio = false
++
+   # Alsa should be used on non-Android, non-Mac POSIX systems.
+   # Alsa should be used on desktop Chromecast and audio-only Chromecast builds.
+   if (is_posix && !is_android && !is_mac &&
diff --git a/srcpkgs/electron13/files/patches/chromium-system-nodejs.patch b/srcpkgs/electron13/files/patches/chromium-system-nodejs.patch
new file mode 100644
index 000000000000..1610887f5309
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-system-nodejs.patch
@@ -0,0 +1,20 @@
+--- a/third_party/node/node.py	2021-05-20 04:17:54.000000000 +0200
++++ -	2021-05-25 11:57:32.895222559 +0200
+@@ -17,11 +17,12 @@
+   if platform.system() == 'Darwin' and platform.machine() == 'arm64':
+       return os.path.join(os_path.join(os_path.dirname(__file__), 'mac',
+                           'node-darwin-arm64', 'bin', 'node'))
+-  return os_path.join(os_path.dirname(__file__), *{
+-    'Darwin': ('mac', 'node-darwin-x64', 'bin', 'node'),
+-    'Linux': ('linux', 'node-linux-x64', 'bin', 'node'),
+-    'Windows': ('win', 'node.exe'),
+-  }[platform.system()])
++  return "/usr/bin/node"
++  #return os_path.join(os_path.dirname(__file__), *{
++  #  'Darwin': ('mac', 'node-darwin-x64', 'bin', 'node'),
++  #  'Linux': ('linux', 'node-linux-x64', 'bin', 'node'),
++  #  'Windows': ('win', 'node.exe'),
++  #}[platform.system()])
+ 
+ 
+ def RunNode(cmd_parts, stdout=None):
diff --git a/srcpkgs/electron13/files/patches/chromium-webrtc-include.patch b/srcpkgs/electron13/files/patches/chromium-webrtc-include.patch
new file mode 100644
index 000000000000..41ba7f2846c2
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-webrtc-include.patch
@@ -0,0 +1,10 @@
+--- a/third_party/webrtc/modules/desktop_capture/linux/window_capturer_x11.cc.orig	2019-02-21 21:21:24.488058990 +0100
++++ a/third_party/webrtc/modules/desktop_capture/linux/window_capturer_x11.cc	2019-02-21 21:21:36.151961064 +0100
+@@ -16,6 +16,7 @@
+ 
+ #include <memory>
+ #include <string>
++#include <string.h>
+ #include <utility>
+ 
+ #include "modules/desktop_capture/desktop_frame.h"
diff --git a/srcpkgs/electron13/files/patches/chromium-webrtc-r0.patch b/srcpkgs/electron13/files/patches/chromium-webrtc-r0.patch
new file mode 100644
index 000000000000..c9b6e086ef00
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-webrtc-r0.patch
@@ -0,0 +1,33 @@
+Upstream: Yes, https://webrtc-review.googlesource.com/9384
+Reason: Fixes musl builds of webrtc
+
+From 7f90e2cceda0458cf56026eb6ccffb961a47804b Mon Sep 17 00:00:00 2001
+From: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com>
+Date: Fri, 13 Oct 2017 15:49:32 +0200
+Subject: [PATCH] IWYU: Include math.h for round(3).
+
+math.h was being implicitly included, which can break the build with
+alternative libc implementations.
+
+Bug: None
+Change-Id: I969b320b65d0f44abb33d3e1036cfbcb859a4952
+Reviewed-on: https://webrtc-review.googlesource.com/9384
+Reviewed-by: Tommi <tommi@webrtc.org>
+Commit-Queue: Raphael Kubo da Costa (rakuco) <raphael.kubo.da.costa@intel.com>
+Cr-Commit-Position: refs/heads/master@{#20292}
+---
+
+--- a/third_party/webrtc/p2p/base/port.cc
++++ a/third_party/webrtc/p2p/base/port.cc
+@@ -10,6 +10,8 @@
+ 
+ #include "p2p/base/port.h"
+ 
++#include <math.h>
++
+ #include <algorithm>
+ #include <vector>
+ 
+-- 
+2.15.0.rc2
+
diff --git a/srcpkgs/electron13/files/patches/chromium-webrtc-size_t.patch b/srcpkgs/electron13/files/patches/chromium-webrtc-size_t.patch
new file mode 100644
index 000000000000..a1fbd43b3013
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-webrtc-size_t.patch
@@ -0,0 +1,10 @@
+--- a/third_party/webrtc/modules/audio_processing/aec3/clockdrift_detector.h	2020-08-10 20:42:29.000000000 +0200
++++ a/third_party/webrtc/modules/audio_processing/aec3/clockdrift_detector.h	2020-09-04 12:47:07.014833633 +0200
+@@ -12,6 +12,7 @@
+ #define MODULES_AUDIO_PROCESSING_AEC3_CLOCKDRIFT_DETECTOR_H_
+ 
+ #include <array>
++#include <cstddef>
+ 
+ namespace webrtc {
+ 
diff --git a/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-libvpx.patch b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-libvpx.patch
new file mode 100644
index 000000000000..6d423d4091c5
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-libvpx.patch
@@ -0,0 +1,72 @@
+Uses generic target for now. To use ppc64le, change --target to ppc64le-gnu
+and add --enable-vsx, and change generic to ppc for the rtcd header.
+
+From 18e6c5c55cfae0cfb458d8210d7bc709360a0e90 Mon Sep 17 00:00:00 2001
+From: q66 <daniel@octaforge.org>
+Date: Wed, 9 Sep 2020 19:08:25 +0200
+Subject: [PATCH] enable generation of ppc64 libvpx bits
+
+this doesn't update the gni file, that's done from
+the template by running the appropriate scripts
+---
+ third_party/libvpx/BUILD.gn        | 4 ++++
+ third_party/libvpx/generate_gni.sh | 9 +++++++++
+ 2 files changed, 13 insertions(+)
+
+diff --git third_party/libvpx/BUILD.gn third_party/libvpx/BUILD.gn
+index 7198e59..3300485 100644
+--- a/third_party/libvpx/BUILD.gn
++++ b/third_party/libvpx/BUILD.gn
+@@ -336,6 +336,8 @@ static_library("libvpx") {
+     } else {
+       sources = libvpx_srcs_arm64
+     }
++  } else if (current_cpu == "ppc64") {
++    sources = libvpx_srcs_ppc64
+   }
+ 
+   configs -= [ "//build/config/compiler:chromium_code" ]
+diff --git third_party/libvpx/generate_gni.sh third_party/libvpx/generate_gni.sh
+index bcf84b0..8a3f4f1 100755
+--- a/third_party/libvpx/generate_gni.sh
++++ b/third_party/libvpx/generate_gni.sh
+@@ -361,6 +361,7 @@ gen_config_files linux/arm-neon-highbd "--target=armv7-linux-gcc ${all_platforms
+ gen_config_files linux/arm64-highbd "--target=armv8-linux-gcc ${all_platforms} ${HIGHBD}"
+ gen_config_files linux/mipsel "--target=mips32-linux-gcc ${all_platforms}"
+ gen_config_files linux/mips64el "--target=mips64-linux-gcc ${all_platforms}"
++gen_config_files linux/ppc64 "--target=generic-gnu $HIGHBD ${all_platforms}"
+ gen_config_files linux/generic "--target=generic-gnu $HIGHBD ${all_platforms}"
+ gen_config_files win/arm64 "--target=arm64-win64-vs15 ${all_platforms} ${HIGHBD}"
+ gen_config_files win/ia32 "--target=x86-win32-vs14 ${all_platforms} ${x86_platforms}"
+@@ -386,6 +387,7 @@ lint_config linux/arm-neon-highbd
+ lint_config linux/arm64-highbd
+ lint_config linux/mipsel
+ lint_config linux/mips64el
++lint_config linux/ppc64
+ lint_config linux/generic
+ lint_config win/arm64
+ lint_config win/ia32
+@@ -415,6 +417,7 @@ gen_rtcd_header linux/arm-neon-highbd armv7
+ gen_rtcd_header linux/arm64-highbd armv8
+ gen_rtcd_header linux/mipsel mipsel
+ gen_rtcd_header linux/mips64el mips64el
++gen_rtcd_header linux/ppc64 generic
+ gen_rtcd_header linux/generic generic
+ gen_rtcd_header win/arm64 armv8
+ gen_rtcd_header win/ia32 x86 "${require_sse2}"
+@@ -500,6 +503,12 @@ if [ -z $ONLY_CONFIGS ]; then
+ 
+   echo "MIPS64 source list is identical to MIPS source list. No need to generate it."
+ 
++  echo "Generate ppc64 source list."
++  config=$(print_config_basic linux/ppc64)
++  make_clean
++  make libvpx_srcs.txt target=libs $config > /dev/null
++  convert_srcs_to_project_files libvpx_srcs.txt libvpx_srcs_ppc64
++
+   echo "Generate NaCl source list."
+   config=$(print_config_basic nacl)
+   make_clean
+-- 
+2.28.0
+
diff --git a/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-support.patch b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-support.patch
new file mode 100644
index 000000000000..a40ed9d5ac73
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-support.patch
@@ -0,0 +1,3707 @@
+commit 2c013a317b1114ef67cdbbc30824b28907b9ea94
+Author: Daniel Kolesa <daniel@octaforge.org>
+Date:   Wed Mar 3 19:08:29 2021 +0100
+
+    ppc64le support
+
+diff --git a/build/download_nacl_toolchains.py b/build/download_nacl_toolchains.py
+index 286a92a27..ec36a85d3 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 35f01d0a4..28f2e7475 100644
+--- a/chrome/installer/linux/BUILD.gn
++++ b/chrome/installer/linux/BUILD.gn
+@@ -94,8 +94,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") {
+@@ -315,7 +313,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 db30ae6d6..9dc09bf53 100644
+--- a/sandbox/features.gni
++++ b/sandbox/features.gni
+@@ -11,7 +11,8 @@ import("//build/config/nacl/config.gni")
+ use_seccomp_bpf = (is_linux || is_chromeos || 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 e9a94b461..cca1a5da5 100644
+--- a/sandbox/linux/BUILD.gn
++++ b/sandbox/linux/BUILD.gn
+@@ -427,6 +427,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 313511f22..0ca3a326f 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 1a407b952..a6aec544e 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 6a1ec2389..f20c582dd 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__)
+@@ -227,7 +228,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
+@@ -245,7 +246,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,
+@@ -285,7 +286,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 01c046dda..7e5a6be82 100644
+--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc	2021-04-15 13:11:10.481579470 -0400
++++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc	2021-04-15 13:12:43.524831376 -0400
+@@ -302,7 +302,7 @@
+ TEST_BASELINE_SIGSYS(__NR_syslog)
+ TEST_BASELINE_SIGSYS(__NR_timer_create)
+ 
+-#if !defined(__aarch64__)
++#if !defined(__aarch64__) && !defined(__powerpc64__)
+ TEST_BASELINE_SIGSYS(__NR_inotify_init)
+ TEST_BASELINE_SIGSYS(__NR_vserver)
+ #endif
+diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+index 2a97d3916..8e81aa6cf 100644
+--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc	2021-04-14 14:41:08.000000000 -0400
++++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc	2021-04-15 13:17:57.808715733 -0400
+@@ -40,7 +40,8 @@
+ #include <sys/ptrace.h>
+ #if (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \
+     !defined(__arm__) && !defined(__aarch64__) &&           \
+-    !defined(PTRACE_GET_THREAD_AREA)
++    !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
+@@ -49,6 +50,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)
+@@ -98,6 +104,15 @@
+ #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
+@@ -239,6 +254,8 @@
+   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);
+@@ -256,7 +273,16 @@
+               F_SETLKW,
+               F_GETLK,
+               F_DUPFD,
+-              F_DUPFD_CLOEXEC),
++              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()))
+@@ -266,7 +292,7 @@
+   // clang-format on
+ }
+ 
+-#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
+@@ -419,7 +445,7 @@
+ #endif
+   return Switch(request)
+       .CASES((
+-#if !defined(__aarch64__)
++#if !defined(__aarch64__) && !defined(__powerpc64__)
+                  PTRACE_GETREGS, PTRACE_GETFPREGS, PTRACE_GET_THREAD_AREA,
+                  PTRACE_GETREGSET,
+ #endif
+diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
+index ba4289f05..9a4d5ab2d 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 642df7207..34f47eb73 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;
+@@ -52,12 +53,14 @@ bool SyscallSets::IsAllowedGettime(int sysno) {
+     case __NR_clock_nanosleep_time64:  // Parameters filtered by RestrictClockID().
+ #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_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:
+@@ -135,7 +138,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))
+@@ -154,7 +157,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
+@@ -168,7 +171,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:
+@@ -178,7 +182,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.
+@@ -203,7 +208,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__)
+@@ -216,11 +222,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__) || \
+@@ -228,6 +235,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;
+@@ -248,7 +257,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;
+@@ -289,7 +299,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
+@@ -340,8 +350,11 @@ 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__)
++#ifndef __powerpc64__
+     case __NR_rt_sigtimedwait_time64:
++#endif
+     case __NR_sigaction:
+     case __NR_sigprocmask:
+     case __NR_sigreturn:
+@@ -357,7 +370,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
+@@ -381,7 +395,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;
+@@ -414,7 +428,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;
+@@ -431,7 +445,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:
+@@ -484,7 +498,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;
+@@ -494,7 +508,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:
+@@ -509,7 +523,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) {
+@@ -523,7 +538,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:
+@@ -548,7 +564,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__) || \
+@@ -578,7 +594,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__)
+@@ -598,26 +615,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
+@@ -673,7 +692,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:
+@@ -685,7 +705,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:
+@@ -701,7 +722,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:
+@@ -734,7 +756,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:
+@@ -750,7 +773,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:
+@@ -785,14 +808,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:
+@@ -826,7 +850,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
+@@ -892,8 +916,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) {
+@@ -925,7 +957,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) {
+@@ -945,7 +978,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
+ }
+@@ -1002,7 +1036,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:
+@@ -1084,18 +1119,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:
+@@ -1103,20 +1142,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 923533ec9..411f72acd 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 e47e98bf5..d53a7ff56 100644
+--- a/sandbox/linux/seccomp-bpf/syscall.cc
++++ b/sandbox/linux/seccomp-bpf/syscall.cc
+@@ -18,7 +18,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
+@@ -310,12 +310,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]);
+ }
+@@ -429,6 +473,8 @@ intptr_t Syscall::Call(int nr,
+     ret = inout;
+   }
+ 
++#elif defined(__powerpc64__)
++  intptr_t ret = SyscallAsm(nr, args);
+ #else
+ #error "Unimplemented architecture"
+ #endif
+@@ -445,8 +491,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 f5b86a73a..5e6c4a068 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 d7b5d8c44..4adc6d0d4 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 fcfd2aa12..f6eb32fb7 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 d72c9d238..77f1d95f5 100644
+--- a/sandbox/linux/syscall_broker/broker_process.cc
++++ b/sandbox/linux/syscall_broker/broker_process.cc
+@@ -169,7 +169,7 @@ bool BrokerProcess::IsSyscallBrokerable(int sysno, bool fast_check) const {
+ #if defined(__NR_fstatat64)
+     case __NR_fstatat64:
+ #endif
+-#if defined(__x86_64__) || defined(__aarch64__)
++#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__)
+     case __NR_newfstatat:
+ #endif
+       return !fast_check || 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 1fa47ed09..39cc9ab53 100644
+--- a/sandbox/linux/system_headers/linux_seccomp.h
++++ b/sandbox/linux/system_headers/linux_seccomp.h
+@@ -41,6 +41,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
+@@ -73,6 +76,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 f5a736761..515b21a5f 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 2b78a0cc3..0a70f5ea5 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 22ce78027..a69b024c2 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 000000000..ccacffe22
+--- /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 000000000..07728e087
+--- /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/sandbox/policy/linux/bpf_renderer_policy_linux.cc b/sandbox/policy/linux/bpf_renderer_policy_linux.cc
+index 2588fc792..d455c4601 100644
+--- a/sandbox/policy/linux/bpf_renderer_policy_linux.cc
++++ b/sandbox/policy/linux/bpf_renderer_policy_linux.cc
+@@ -15,6 +15,11 @@
+ #include "sandbox/linux/system_headers/linux_syscalls.h"
+ #include "sandbox/policy/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 3a807e1e3..5258617a7 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 fcbc9246a..39ae66148 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 17cf9cda9..8ce96bd32 100644
+--- a/third_party/boringssl/BUILD.gn
++++ b/third_party/boringssl/BUILD.gn
+@@ -103,6 +103,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/BUILD.gn b/third_party/breakpad/BUILD.gn
+index 4af3d7bbf..adbf54159 100644
+--- a/third_party/breakpad/BUILD.gn
++++ b/third_party/breakpad/BUILD.gn
+@@ -596,7 +596,6 @@ if (is_linux || is_chromeos || is_android) {
+       "breakpad/src/client/minidump_file_writer.h",
+       "breakpad/src/common/convert_UTF.cc",
+       "breakpad/src/common/convert_UTF.h",
+-      "breakpad/src/common/linux/breakpad_getcontext.S",
+       "breakpad/src/common/linux/elf_core_dump.cc",
+       "breakpad/src/common/linux/elf_core_dump.h",
+       "breakpad/src/common/linux/elfutils.cc",
+@@ -634,6 +633,14 @@ if (is_linux || is_chromeos || is_android) {
+ 
+     libs = [ "dl" ]
+ 
++    if (current_cpu == "ppc64") {
++        defines = [ "HAVE_GETCONTEXT" ]
++    } else {
++        sources += [
++            "breakpad/src/common/linux/breakpad_getcontext.S"
++        ]
++    }
++
+     include_dirs = [
+       ".",
+       "breakpad/src",
+@@ -682,7 +689,6 @@ if (is_linux || is_chromeos || is_android) {
+       "breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc",
+       "breakpad/src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc",
+       "breakpad/src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc",
+-      "breakpad/src/common/linux/breakpad_getcontext_unittest.cc",
+       "breakpad/src/common/linux/elf_core_dump_unittest.cc",
+       "breakpad/src/common/linux/file_id_unittest.cc",
+       "breakpad/src/common/linux/linux_libc_support_unittest.cc",
+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 07d9171a0..9aed4cb36 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 aae1dc13b..03afec7a5 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 fb216fa6d..593aac822 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 6eec1be24..741983a1a 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 7d4100881..c122ac92e 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
+@@ -55,6 +55,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 a6cb5f984..ae16b64d9 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) {
+@@ -708,11 +715,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.
+@@ -733,6 +748,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 f80843ea7..260dd10f7 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 35dcbfd4d..7934370fd 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 fa3c1713a..6ce709e2f 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 6339ac0cd..291af106b 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
+@@ -279,10 +279,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 415068983..b93e4afcf 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 7fd6532ad..199cbfffd 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 7bee160f1..07bb2b81a 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 331f4bb34..3f722947f 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 e3ddb81a6..fa28575ef 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 da71e15dc..12bfb317a 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 32634ef00..2a56948de 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 e3b0b16da..ccd8aa0a4 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
+@@ -48,6 +48,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 std::remove_pointer<fpregset_t>::type 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 d192e5cbb..fc1bfa8d7 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
+@@ -715,6 +715,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 99362945c..c54ba7145 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 fad59f40c..616496d67 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/common/memory_allocator_unittest.cc b/third_party/breakpad/breakpad/src/common/memory_allocator_unittest.cc
+index 5803b90d5..2a1cf14f0 100644
+--- a/third_party/breakpad/breakpad/src/common/memory_allocator_unittest.cc
++++ b/third_party/breakpad/breakpad/src/common/memory_allocator_unittest.cc
+@@ -57,8 +57,9 @@ TEST(PageAllocatorTest, LargeObject) {
+ 
+   EXPECT_EQ(0U, allocator.pages_allocated());
+   uint8_t* p = reinterpret_cast<uint8_t*>(allocator.Alloc(10000));
++  uint64_t expected_pages = 1 + ((10000 - 1) / getpagesize());
+   ASSERT_FALSE(p == NULL);
+-  EXPECT_EQ(3U, allocator.pages_allocated());
++  EXPECT_EQ(expected_pages, allocator.pages_allocated());
+   for (unsigned i = 1; i < 10; ++i) {
+     uint8_t* p = reinterpret_cast<uint8_t*>(allocator.Alloc(i));
+     ASSERT_FALSE(p == NULL);
+diff --git a/third_party/breakpad/breakpad/src/processor/exploitability_linux.cc b/third_party/breakpad/breakpad/src/processor/exploitability_linux.cc
+index 798056dfa..22bd81fff 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 528ee5f21..72764d6c1 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 aade82c99..195aa73f3 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
+@@ -77,6 +77,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__)
+@@ -87,6 +89,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;
+@@ -321,6 +325,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;
+@@ -535,6 +542,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
+@@ -623,6 +662,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 8724b7f32..8e29424ef 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 6ed77a98e..1fd83469a 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 3a3e603cb..3118d9e9f 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 d7e53a493..d89eb9e01 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 d4ab936ee..1d22fc59c 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 object’s 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 3216a906b..a9fcbe9d8 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 0974e3ddf..b71ec5880 100644
+--- a/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc
++++ b/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc
+@@ -135,6 +135,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 7a1b2763c..beda8da9e 100644
+--- a/third_party/crashpad/crashpad/snapshot/capture_memory.cc
++++ b/third_party/crashpad/crashpad/snapshot/capture_memory.cc
+@@ -112,6 +112,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 811a72095..f4f83981d 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 c75b5555e..aeade577a 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 fb23c4679..eebede63c 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 9f46a4897..aa677c4eb 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 d32bd1937..2dd538c2b 100644
+--- a/third_party/crashpad/crashpad/snapshot/linux/debug_rendezvous_test.cc
++++ b/third_party/crashpad/crashpad/snapshot/linux/debug_rendezvous_test.cc
+@@ -192,6 +192,8 @@ void TestAgainstTarget(PtraceConnection* connection) {
+               device == 0 && inode == 0 && mapping_name == "[vdso]";
+ #if defined(ARCH_CPU_X86)
+           static constexpr char kPrefix[] = "linux-gate.so.";
++#elif defined(ARCH_CPU_PPC64)
++          static constexpr char kPrefix[] = "linux-vdso64.so.";
+ #else
+           static constexpr char kPrefix[] = "linux-vdso.so.";
+ #endif
+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 cd40b3b12..6bcf23b6f 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 ea0cd2106..e42df520f 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 c17170b43..b6a714cc6 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 ee246e8bc..9555dce04 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/signal_context.h b/third_party/crashpad/crashpad/snapshot/linux/signal_context.h
+index 110024680..a1f2da259 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 a99da3e4b..03b973083 100644
+--- a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
++++ b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
+@@ -204,6 +204,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
+@@ -219,6 +221,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
+@@ -239,6 +244,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
+@@ -372,6 +380,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/test_modules.cc b/third_party/crashpad/crashpad/snapshot/linux/test_modules.cc
+index b2450c206..7ba78b2ae 100644
+--- a/third_party/crashpad/crashpad/snapshot/linux/test_modules.cc
++++ b/third_party/crashpad/crashpad/snapshot/linux/test_modules.cc
+@@ -110,6 +110,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/thread_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc
+index e3e2bebdd..8ef43752e 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 44cc6f6d9..d4136461e 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
+--- a/third_party/crashpad/crashpad/util/net/http_transport_libcurl.cc
++++ b/third_party/crashpad/crashpad/util/net/http_transport_libcurl.cc
+@@ -236,6 +236,12 @@
+ #elif defined(ARCH_CPU_BIG_ENDIAN)
+     static constexpr char arch[] = "aarch64_be";
+ #endif
++#elif defined(__powerpc64__)
++#if defined(ARCH_CPU_LITTLE_ENDIAN)
++    static constexpr char arch[] = "ppc64le";
++#elif defined(ARCH_CPU_BIG_ENDIAN)
++    static constexpr char arch[] = "ppc64";
++#endif
+ #else
+ #error Port
+ #endif
+diff --git a/third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc b/third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc
+index d3d5ebdfb..3fd730cb5 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/ptracer.cc b/third_party/crashpad/crashpad/util/linux/ptracer.cc
+index 557e0d363..08ae434b8 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 5b55c24a7..dea0d1f39 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 d21a24f19..acc325349 100644
+--- a/third_party/crashpad/crashpad/util/misc/capture_context.h
++++ b/third_party/crashpad/crashpad/util/misc/capture_context.h
+@@ -69,6 +69,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 52215ee5d..b3e4a3ec7 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 cf23c2def..5f264bc92 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 30a2ab21d..60509f21d 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
+@@ -35,6 +35,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
+ }
+ 
+@@ -49,6 +51,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
+ }
+ 
+@@ -63,6 +67,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 54cc2f19f..298b5c993 100644
+--- a/third_party/crashpad/crashpad/util/posix/signals_test.cc
++++ b/third_party/crashpad/crashpad/util/posix/signals_test.cc
+@@ -46,9 +46,9 @@ 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)
+@@ -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 don’t generate a
+     // trap for divide-by-zero, so this doesn’t 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 6b4566fc3..c07f732ad 100644
+--- a/third_party/dav1d/BUILD.gn
++++ b/third_party/dav1d/BUILD.gn
+@@ -184,6 +184,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
+@@ -212,6 +214,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
+@@ -263,6 +267,21 @@ if (current_cpu == "x86" || current_cpu == "x64") {
+       defines = [ "PREFIX" ]
+     }
+ 
++    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
+   }
+ }
+@@ -292,5 +311,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 000000000..9fbbf75cc
+--- /dev/null
++++ b/third_party/dav1d/config/linux/ppc64/config.h
+@@ -0,0 +1,39 @@
++/*
++ * 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 -- Logging is controlled by Chromium
++
++#define ENDIANNESS_BIG 0
++
++#define HAVE_ASM 1
++
++#define HAVE_CLOCK_GETTIME 1
++
++#define HAVE_DLSYM 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 c59cb0821..3060284a8 100644
+--- a/third_party/dav1d/dav1d_generated.gni
++++ b/third_party/dav1d/dav1d_generated.gni
+@@ -82,6 +82,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 9ab5e00b8..ad3feffee 100755
+--- a/third_party/dav1d/generate_source.py	2021-04-15 13:11:10.489579490 -0400
++++ b/third_party/dav1d/generate_source.py	2021-04-15 13:19:08.229913892 -0400
+@@ -57,6 +57,8 @@
+   _WriteArray(fd, "arm64_asm_sources", _Glob("libdav1d/src/arm/64/*.S"))
+   _WriteArray(fd, "arm_template_sources", _Glob("libdav1d/src/arm/*_tmpl.c"))
+ 
++  _WriteArray(fd, "ppc64_template_sources", _Glob("libdav1d/src/ppc/*_tmpl.c"))
++
+   template_sources = _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 0b4bd72f0..a0caa5e71 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/eigen3/BUILD.gn b/third_party/eigen3/BUILD.gn
+index 0d4e184..f2ce484 100644
+--- a/third_party/eigen3/BUILD.gn
++++ b/third_party/eigen3/BUILD.gn
+@@ -22,4 +22,8 @@ config("eigen_includes") {
+     # for this component on Windows on Arm due to compilation errors.
+     defines += [ "EIGEN_DONT_VECTORIZE" ]
+   }
++
++  if (target_cpu == "ppc64") {
++    defines += [ "EIGEN_DONT_VECTORIZE" ]
++  }
+ }
+
+diff --git a/third_party/libaom/BUILD.gn b/third_party/libaom/BUILD.gn
+index 9b065bd..df3af02 100644
+--- a/third_party/libaom/BUILD.gn
++++ b/third_party/libaom/BUILD.gn
+@@ -36,6 +36,8 @@ if (enable_libaom) {
+     } else {
+       cpu_arch_full = "arm"
+     }
++  } else if (current_cpu == "ppc64") {
++    cpu_arch_full = "generic"
+   } else {
+     cpu_arch_full = current_cpu
+   }
+diff --git a/third_party/libgav1/options.gni b/third_party/libgav1/options.gni
+index 11af801..4b13d05 100644
+--- a/third_party/libgav1/options.gni
++++ b/third_party/libgav1/options.gni
+@@ -12,5 +12,5 @@ declare_args() {
+       is_chromeos_ash && (target_cpu == "arm" || target_cpu == "arm64")
+   use_libgav1_parser =
+       (is_chromeos || is_linux || is_win) &&
+-      (target_cpu == "x86" || target_cpu == "x64" || target_cpu == "arm64")
++      (target_cpu == "x86" || target_cpu == "x64" || target_cpu == "arm64" || target_cpu == "ppc64")
+ }
+diff --git a/third_party/lss/linux_syscall_support.h b/third_party/lss/linux_syscall_support.h
+index e4ac22644..1c57015db 100644
+--- a/third_party/lss/linux_syscall_support.h
++++ b/third_party/lss/linux_syscall_support.h
+@@ -3947,7 +3947,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,
+@@ -4058,7 +4058,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/pdfium/third_party/libpng16/pngpriv.h b/third_party/pdfium/third_party/libpng16/pngpriv.h
+index 583c26f..e03d697 100644
+--- a/third_party/pdfium/third_party/libpng16/pngpriv.h
++++ b/third_party/pdfium/third_party/libpng16/pngpriv.h
+@@ -196,11 +196,7 @@
+ #endif
+ 
+ #ifndef PNG_POWERPC_VSX_OPT
+-#  if defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__)
+-#     define PNG_POWERPC_VSX_OPT 2
+-#  else
+-#     define PNG_POWERPC_VSX_OPT 0
+-#  endif
++#  define PNG_POWERPC_VSX_OPT 0
+ #endif
+ 
+ #ifndef PNG_INTEL_SSE_OPT
+diff --git a/third_party/pffft/src/pffft.c b/third_party/pffft/src/pffft.c
+index bdac4d784..51e0f2cac 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 ec3e56964..4cf8999a2 100644
+--- a/third_party/skia/src/sksl/SkSLString.cpp
++++ b/third_party/skia/src/sksl/SkSLString.cpp
+@@ -234,7 +234,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());
+ }
+ 
+ bool stod(const StringFragment& s, SKSL_FLOAT* value) {
+diff --git a/third_party/sqlite/src/amalgamation/sqlite3.c b/third_party/sqlite/src/amalgamation/sqlite3.c
+index 6b4a7899d..b8c7fe414 100644
+--- a/third_party/sqlite/src/amalgamation/sqlite3.c
++++ b/third_party/sqlite/src/amalgamation/sqlite3.c
+@@ -14474,7 +14474,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 d30c9b7de..cf75a69d9 100644
+--- a/third_party/sqlite/src/amalgamation_dev/sqlite3.c
++++ b/third_party/sqlite/src/amalgamation_dev/sqlite3.c
+@@ -14487,7 +14487,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 f5b57a5e2..80a2d0ad8 100644
+--- a/third_party/sqlite/src/ext/rtree/rtree.c
++++ b/third_party/sqlite/src/ext/rtree/rtree.c
+@@ -450,7 +450,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 245070d4f..b25164e95 100644
+--- a/third_party/sqlite/src/src/sqliteInt.h
++++ b/third_party/sqlite/src/src/sqliteInt.h
+@@ -877,7 +877,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 4f0c5430c..54ee0829e 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 = 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 be2367b85..be4ee4233 100644
+--- a/third_party/webrtc/rtc_base/system/arch.h
++++ b/third_party/webrtc/rtc_base/system/arch.h
+@@ -79,6 +79,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/v8/BUILD.gn b/v8/BUILD.gn
+index f39529a3a..e84fc449e 100644
+--- a/v8/BUILD.gn
++++ b/v8/BUILD.gn
+@@ -850,6 +850,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/ui/gl/features.gni b/ui/gl/features.gni
+index 5fda9b6..3d2dd8b 100644
+--- a/ui/gl/features.gni
++++ b/ui/gl/features.gni
+@@ -32,5 +32,6 @@ declare_args() {
+                         (is_mac && use_egl) || is_chromeos_ash || 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")
+ }
+diff --git a/v8/test/BUILD.gn b/v8/test/BUILD.gn
+index fb872ad39..45fc585dd 100644
+--- a/v8/test/BUILD.gn
++++ b/v8/test/BUILD.gn
+@@ -36,7 +36,7 @@ group("gn_all") {
+       "benchmarks/cpp:gn_all",
+       "cctest:cctest",
+       "cctest:generate-bytecode-expectations",
+-      "unittests:unittests",
++      #"unittests:unittests",
+     ]
+   }
+ }
+@@ -83,7 +83,7 @@
+     "message:v8_message",
+     "mjsunit:v8_mjsunit",
+     "mkgrokdump:mkgrokdump",
+-    "unittests:unittests",
++    #"unittests:unittests",
+     "webkit:v8_webkit",
+   ]
+ 
+@@ -108,7 +108,7 @@
+     "message:v8_message",
+     "mjsunit:v8_mjsunit",
+     "mkgrokdump:mkgrokdump",
+-    "unittests:unittests",
++    #"unittests:unittests",
+   ]
+ 
+   if (v8_enable_webassembly) {
diff --git a/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-swiftshader.patch b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-swiftshader.patch
new file mode 100644
index 000000000000..df453f491d8c
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/chromium-xxx-ppc64le-swiftshader.patch
@@ -0,0 +1,18 @@
+--- a/third_party/swiftshader/third_party/llvm-10.0/BUILD.gn
++++ b/third_party/swiftshader/third_party/llvm-10.0/BUILD.gn
+@@ -574,6 +574,7 @@ swiftshader_llvm_source_set("swiftshader
+     "llvm/lib/MC/MCAsmInfoCOFF.cpp",
+     "llvm/lib/MC/MCAsmInfoDarwin.cpp",
+     "llvm/lib/MC/MCAsmInfoELF.cpp",
++    "llvm/lib/MC/MCAsmInfoXCOFF.cpp",
+     "llvm/lib/MC/MCAsmMacro.cpp",
+     "llvm/lib/MC/MCAsmStreamer.cpp",
+     "llvm/lib/MC/MCAssembler.cpp",
+@@ -629,6 +630,7 @@ swiftshader_llvm_source_set("swiftshader
+     "llvm/lib/MC/MCWinCOFFStreamer.cpp",
+     "llvm/lib/MC/MCWinEH.cpp",
+     "llvm/lib/MC/MCXCOFFStreamer.cpp",
++    "llvm/lib/MC/MCXCOFFObjectTargetWriter.cpp",
+     "llvm/lib/MC/MachObjectWriter.cpp",
+     "llvm/lib/MC/StringTableBuilder.cpp",
+     "llvm/lib/MC/SubtargetFeature.cpp",
diff --git a/srcpkgs/electron13/files/patches/electron-Add-a-script-to-list-patch-targets.patch.patch b/srcpkgs/electron13/files/patches/electron-Add-a-script-to-list-patch-targets.patch.patch
new file mode 100644
index 000000000000..916dba9dc3bc
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/electron-Add-a-script-to-list-patch-targets.patch.patch
@@ -0,0 +1,42 @@
+From ff4122f236b70c272c746d0c336cdbd588d78cd1 Mon Sep 17 00:00:00 2001
+From: Elvis Pranskevichus <elvis@magic.io>
+Date: Thu, 12 Dec 2019 16:12:18 -0500
+Subject: [PATCH] Add a script to list patch targets
+
+---
+ script/list_patch_targets.py | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+ create mode 100755 script/list_patch_targets.py
+
+diff --git a/script/list_patch_targets.py b/script/list_patch_targets.py
+new file mode 100755
+index 000000000..55173bac9
+--- /dev/null
++++ b/script/list_patch_targets.py
+@@ -0,0 +1,23 @@
++#!/usr/bin/env python
++
++import argparse
++import json
++
++
++def parse_args():
++  parser = argparse.ArgumentParser(description='Apply Electron patches')
++  parser.add_argument('config', nargs='+',
++                      type=argparse.FileType('r'),
++                      help='patches\' config(s) in the JSON format')
++  return parser.parse_args()
++
++
++def main():
++  configs = parse_args().config
++  for config_json in configs:
++    for patch_dir, repo in json.load(config_json).iteritems():
++      print(repo)
++
++
++if __name__ == '__main__':
++  main()
+-- 
+2.23.0
+
diff --git a/srcpkgs/electron13/files/patches/electron-Build-fixes.patch.patch b/srcpkgs/electron13/files/patches/electron-Build-fixes.patch.patch
new file mode 100644
index 000000000000..298bfa9bcb2b
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/electron-Build-fixes.patch.patch
@@ -0,0 +1,47 @@
+diff --git a/build/args/release.gn b/build/args/release.gn
+index e5017f6e1..59207b389 100644
+--- a/build/args/release.gn
++++ b/build/args/release.gn
+@@ -1,6 +1,4 @@
+ import("all.gn")
+-is_component_build = false
+-is_official_build = true
+ 
+ # This may be guarded behind is_chrome_branded alongside
+ # proprietary_codecs https://webrtc-review.googlesource.com/c/src/+/36321,
+@@ -8,9 +6,3 @@ is_official_build = true
+ # The initialization of the decoder depends on whether ffmpeg has
+ # been built with H.264 support.
+ rtc_use_h264 = proprietary_codecs
+-
+-# By default, Electron builds ffmpeg with proprietary codecs enabled. In order
+-# to facilitate users who don't want to ship proprietary codecs in ffmpeg, or
+-# who have an LGPL requirement to ship ffmpeg as a dynamically linked library,
+-# we build ffmpeg as a shared library.
+-is_component_ffmpeg = true
+diff --git a/build/npm.gni b/build/npm.gni
+index a1987d095..fb33a14c3 100644
+--- a/build/npm.gni
++++ b/build/npm.gni
+@@ -35,7 +35,6 @@ template("npm_action") {
+     if (!defined(deps)) {
+       deps = []
+     }
+-    deps += [ ":npm_pre_flight_" + target_name ]
+ 
+     script = "//electron/build/npm-run.py"
+     args = [
+diff --git a/patches/node/fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch b/patches/node/fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch
+index 0dc9916be..7eaa46bf5 100644
+--- a/patches/node/fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch
++++ b/patches/node/fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch
+@@ -30,7 +30,7 @@
+ +    # these values being accurate.
+ +    'build_v8_with_gn': 'false',
+ +    'enable_lto%': 'false',
+-+
+++    'openssl_fips': '',
+      'conditions': [
+        ['target_arch=="arm64"', {
+          # Disabled pending https://github.com/nodejs/node/issues/23913.
+
diff --git a/srcpkgs/electron13/files/patches/electron-dont-assume-python-is-python2.patch b/srcpkgs/electron13/files/patches/electron-dont-assume-python-is-python2.patch
new file mode 100644
index 000000000000..fb134748025b
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/electron-dont-assume-python-is-python2.patch
@@ -0,0 +1,17 @@
+--- a/build/zip.py.orig	2020-04-27 17:59:53.499281667 +0200
++++ b/build/zip.py	2020-04-27 17:59:57.655839143 +0200
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python2
+ from __future__ import print_function
+ import os
+ import subprocess
+
+--- a/build/npm-run.py.orig	2020-04-27 17:59:50.829351807 +0200
++++ b/build/npm-run.py	2020-04-27 18:00:02.702373256 +0200
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python2
+ from __future__ import print_function
+ import os
+ import subprocess
diff --git a/srcpkgs/electron13/files/patches/electron-exclude-content-test-patches.patch b/srcpkgs/electron13/files/patches/electron-exclude-content-test-patches.patch
new file mode 100644
index 000000000000..456223644278
--- /dev/null
+++ b/srcpkgs/electron13/files/patches/electron-exclude-content-test-patches.patch
@@ -0,0 +1,10 @@
+--- a/script/apply_all_patches.py	2020-08-22 17:46:41.796707506 +0200
++++ -	2020-08-22 17:47:05.887813512 +0200
+@@ -14,6 +14,7 @@
+   for patch_dir, repo in dirs.items():
+     git.import_patches(repo=repo, patch_data=patch_from_dir(patch_dir),
+       threeway=threeway is not None,
++      exclude=['test/mjsunit/**', 'content/test/**', 'test/cctest/**', 'test/unittests/**', 'third_party/blink/web_tests/**'],
+       committer_name="Electron Scripts", committer_email="scripts@electron")
+ 
+ 
diff --git a/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.cc b/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.cc
new file mode 100644
index 000000000000..2c7aa8efa66f
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.cc
@@ -0,0 +1,148 @@
+// Copyright (c) 2012 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.
+
+#include "base/metrics/histogram_macros.h"
+#include "base/memory/ptr_util.h"
+
+#include "media/audio/openbsd/audio_manager_openbsd.h"
+
+#include "media/audio/audio_device_description.h"
+#include "media/audio/audio_output_dispatcher.h"
+#include "media/audio/sndio/sndio_input.h"
+#include "media/audio/sndio/sndio_output.h"
+#include "media/base/limits.h"
+#include "media/base/media_switches.h"
+
+namespace media {
+
+// Maximum number of output streams that can be open simultaneously.
+static const int kMaxOutputStreams = 4;
+
+// Default sample rate for input and output streams.
+static const int kDefaultSampleRate = 48000;
+
+void AddDefaultDevice(AudioDeviceNames* device_names) {
+  DCHECK(device_names->empty());
+  device_names->push_front(AudioDeviceName::CreateDefault());
+}
+
+bool AudioManagerOpenBSD::HasAudioOutputDevices() {
+  return true;
+}
+
+bool AudioManagerOpenBSD::HasAudioInputDevices() {
+  return true;
+}
+
+void AudioManagerOpenBSD::GetAudioInputDeviceNames(
+    AudioDeviceNames* device_names) {
+  DCHECK(device_names->empty());
+  AddDefaultDevice(device_names);
+}
+
+void AudioManagerOpenBSD::GetAudioOutputDeviceNames(
+    AudioDeviceNames* device_names) {
+  AddDefaultDevice(device_names);
+}
+
+const char* AudioManagerOpenBSD::GetName() {
+  return "SNDIO";
+}
+
+AudioParameters AudioManagerOpenBSD::GetInputStreamParameters(
+    const std::string& device_id) {
+  static const int kDefaultInputBufferSize = 1024;
+
+  int user_buffer_size = GetUserBufferSize();
+  int buffer_size = user_buffer_size ?
+      user_buffer_size : kDefaultInputBufferSize;
+
+  return AudioParameters(
+      AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
+      kDefaultSampleRate, buffer_size);
+}
+
+AudioManagerOpenBSD::AudioManagerOpenBSD(std::unique_ptr<AudioThread> audio_thread,
+                                         AudioLogFactory* audio_log_factory)
+    : AudioManagerBase(std::move(audio_thread),
+                       audio_log_factory) {
+  DLOG(WARNING) << "AudioManagerOpenBSD";
+  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
+}
+
+AudioManagerOpenBSD::~AudioManagerOpenBSD() {
+  Shutdown();
+}
+
+AudioOutputStream* AudioManagerOpenBSD::MakeLinearOutputStream(
+    const AudioParameters& params,
+    const LogCallback& log_callback) {
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
+  return MakeOutputStream(params);
+}
+
+AudioOutputStream* AudioManagerOpenBSD::MakeLowLatencyOutputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+  return MakeOutputStream(params);
+}
+
+AudioInputStream* AudioManagerOpenBSD::MakeLinearInputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
+  return MakeInputStream(params);
+}
+
+AudioInputStream* AudioManagerOpenBSD::MakeLowLatencyInputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+  return MakeInputStream(params);
+}
+
+AudioParameters AudioManagerOpenBSD::GetPreferredOutputStreamParameters(
+    const std::string& output_device_id,
+    const AudioParameters& input_params) {
+  // TODO(tommi): Support |output_device_id|.
+  DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
+  static const int kDefaultOutputBufferSize = 2048;
+
+  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
+  int sample_rate = kDefaultSampleRate;
+  int buffer_size = kDefaultOutputBufferSize;
+  if (input_params.IsValid()) {
+    sample_rate = input_params.sample_rate();
+    channel_layout = input_params.channel_layout();
+    buffer_size = std::min(buffer_size, input_params.frames_per_buffer());
+  }
+
+  int user_buffer_size = GetUserBufferSize();
+  if (user_buffer_size)
+    buffer_size = user_buffer_size;
+
+  return AudioParameters(
+      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
+      sample_rate, buffer_size);
+}
+
+AudioInputStream* AudioManagerOpenBSD::MakeInputStream(
+    const AudioParameters& params) {
+  DLOG(WARNING) << "MakeInputStream";
+  return new SndioAudioInputStream(this,
+             AudioDeviceDescription::kDefaultDeviceId, params);
+}
+
+AudioOutputStream* AudioManagerOpenBSD::MakeOutputStream(
+    const AudioParameters& params) {
+  DLOG(WARNING) << "MakeOutputStream";
+  return new SndioAudioOutputStream(params, this);
+}
+
+}  // namespace media
diff --git a/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.h b/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.h
new file mode 100644
index 000000000000..8c99db966d65
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/audio_manager_openbsd.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2012 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 MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
+#define MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
+
+#include <set>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread.h"
+#include "media/audio/audio_manager_base.h"
+
+namespace media {
+
+class MEDIA_EXPORT AudioManagerOpenBSD : public AudioManagerBase {
+ public:
+  AudioManagerOpenBSD(std::unique_ptr<AudioThread> audio_thread,
+                   AudioLogFactory* audio_log_factory);
+  ~AudioManagerOpenBSD() override;
+
+  // Implementation of AudioManager.
+  bool HasAudioOutputDevices() override;
+  bool HasAudioInputDevices() override;
+  void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
+  void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override;
+  AudioParameters GetInputStreamParameters(
+      const std::string& device_id) override;
+  const char* GetName() override;
+
+  // Implementation of AudioManagerBase.
+  AudioOutputStream* MakeLinearOutputStream(
+      const AudioParameters& params,
+      const LogCallback& log_callback) override;
+  AudioOutputStream* MakeLowLatencyOutputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+  AudioInputStream* MakeLinearInputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+  AudioInputStream* MakeLowLatencyInputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+
+ protected:
+  AudioParameters GetPreferredOutputStreamParameters(
+      const std::string& output_device_id,
+      const AudioParameters& input_params) override;
+
+ private:
+  // Called by MakeLinearOutputStream and MakeLowLatencyOutputStream.
+  AudioOutputStream* MakeOutputStream(const AudioParameters& params);
+  AudioInputStream* MakeInputStream(const AudioParameters& params);
+
+  DISALLOW_COPY_AND_ASSIGN(AudioManagerOpenBSD);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
diff --git a/srcpkgs/electron13/files/sndio-files/sndio_input.cc b/srcpkgs/electron13/files/sndio-files/sndio_input.cc
new file mode 100644
index 000000000000..ef5439b49a07
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/sndio_input.cc
@@ -0,0 +1,200 @@
+// Copyright 2013 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.
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/audio/openbsd/audio_manager_openbsd.h"
+#include "media/audio/audio_manager.h"
+#include "media/audio/sndio/sndio_input.h"
+
+namespace media {
+
+static const SampleFormat kSampleFormat = kSampleFormatS16;
+
+void SndioAudioInputStream::OnMoveCallback(void *arg, int delta)
+{
+  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
+
+  self->hw_delay += delta;
+}
+
+void *SndioAudioInputStream::ThreadEntry(void *arg) {
+  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
+
+  self->ThreadLoop();
+  return NULL;
+}
+
+SndioAudioInputStream::SndioAudioInputStream(AudioManagerBase* manager,
+                                             const std::string& device_name,
+                                             const AudioParameters& params)
+    : manager(manager),
+      params(params),
+      audio_bus(AudioBus::Create(params)),
+      state(kClosed) {
+}
+
+SndioAudioInputStream::~SndioAudioInputStream() {
+  if (state != kClosed)
+    Close();
+}
+
+bool SndioAudioInputStream::Open() {
+  struct sio_par par;
+  int sig;
+
+  if (state != kClosed)
+    return false;
+
+  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
+      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
+    LOG(WARNING) << "Unsupported audio format.";
+    return false;
+  }
+
+  sio_initpar(&par);
+  par.rate = params.sample_rate();
+  par.rchan = params.channels();
+  par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
+  par.bps = par.bits / 8;
+  par.sig = sig = par.bits != 8 ? 1 : 0;
+  par.le = SIO_LE_NATIVE;
+  par.appbufsz = params.frames_per_buffer();
+
+  hdl = sio_open(SIO_DEVANY, SIO_REC, 0);
+
+  if (hdl == NULL) {
+    LOG(ERROR) << "Couldn't open audio device.";
+    return false;
+  }
+
+  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
+    LOG(ERROR) << "Couldn't set audio parameters.";
+    goto bad_close;
+  }
+
+  if (par.rate  != (unsigned int)params.sample_rate() ||
+      par.rchan != (unsigned int)params.channels() ||
+      par.bits  != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
+      par.sig   != (unsigned int)sig ||
+      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
+      (par.bits != par.bps * 8)) {
+    LOG(ERROR) << "Unsupported audio parameters.";
+    goto bad_close;
+  }
+  state = kStopped;
+  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
+  sio_onmove(hdl, &OnMoveCallback, this);
+  return true;
+bad_close:
+  sio_close(hdl);
+  return false;
+}
+
+void SndioAudioInputStream::Start(AudioInputCallback* cb) {
+
+  StartAgc();
+
+  state = kRunning;
+  hw_delay = 0;
+  callback = cb;
+  sio_start(hdl);
+  if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
+    LOG(ERROR) << "Failed to create real-time thread for recording.";
+    sio_stop(hdl);
+    state = kStopped;
+  }
+}
+
+void SndioAudioInputStream::Stop() {
+
+  if (state == kStopped)
+    return;
+
+  state = kStopWait;
+  pthread_join(thread, NULL);
+  sio_stop(hdl);
+  state = kStopped;
+
+  StopAgc();
+}
+
+void SndioAudioInputStream::Close() {
+
+  if (state == kClosed)
+    return;
+
+  if (state == kRunning)
+    Stop();
+
+  state = kClosed;
+  delete [] buffer;
+  sio_close(hdl);
+
+  manager->ReleaseInputStream(this);
+}
+
+double SndioAudioInputStream::GetMaxVolume() {
+  // Not supported
+  return 0.0;
+}
+
+void SndioAudioInputStream::SetVolume(double volume) {
+  // Not supported. Do nothing.
+}
+
+double SndioAudioInputStream::GetVolume() {
+  // Not supported.
+  return 0.0;
+}
+
+bool SndioAudioInputStream::IsMuted() {
+  // Not supported.
+  return false;
+}
+
+void SndioAudioInputStream::SetOutputDeviceForAec(
+    const std::string& output_device_id) {
+  // Not supported.
+}
+
+void SndioAudioInputStream::ThreadLoop(void) {
+  size_t todo, n;
+  char *data;
+  unsigned int nframes;
+  double normalized_volume = 0.0;
+
+  nframes = audio_bus->frames();
+
+  while (state == kRunning && !sio_eof(hdl)) {
+
+    GetAgcVolume(&normalized_volume);
+
+    // read one block
+    todo = nframes * params.GetBytesPerFrame(kSampleFormat);
+    data = buffer;
+    while (todo > 0) {
+      n = sio_read(hdl, data, todo);
+      if (n == 0)
+        return;	// unrecoverable I/O error
+      todo -= n;
+      data += n;
+    }
+    hw_delay -= nframes;
+
+    // convert frames count to TimeDelta
+    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
+      params.sample_rate());
+
+    // push into bus
+    audio_bus->FromInterleaved(buffer, nframes, SampleFormatToBytesPerChannel(kSampleFormat));
+
+    // invoke callback
+    callback->OnData(audio_bus.get(), base::TimeTicks::Now() - delay, 1.);
+  }
+}
+
+}  // namespace media
diff --git a/srcpkgs/electron13/files/sndio-files/sndio_input.h b/srcpkgs/electron13/files/sndio-files/sndio_input.h
new file mode 100644
index 000000000000..d868e0469db5
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/sndio_input.h
@@ -0,0 +1,91 @@
+// Copyright 2013 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 MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
+#define MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
+
+#include <stdint.h>
+#include <string>
+#include <sndio.h>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "media/audio/agc_audio_stream.h"
+#include "media/audio/audio_io.h"
+#include "media/audio/audio_device_description.h"
+#include "media/base/audio_parameters.h"
+
+namespace media {
+
+class AudioManagerBase;
+
+// Implementation of AudioOutputStream using sndio(7)
+class SndioAudioInputStream : public AgcAudioStream<AudioInputStream> {
+ public:
+  // Pass this to the constructor if you want to attempt auto-selection
+  // of the audio recording device.
+  static const char kAutoSelectDevice[];
+
+  // Create a PCM Output stream for the SNDIO device identified by
+  // |device_name|. If unsure of what to use for |device_name|, use
+  // |kAutoSelectDevice|.
+  SndioAudioInputStream(AudioManagerBase* audio_manager,
+                     const std::string& device_name,
+                     const AudioParameters& params);
+
+  ~SndioAudioInputStream() override;
+
+  // Implementation of AudioInputStream.
+  bool Open() override;
+  void Start(AudioInputCallback* callback) override;
+  void Stop() override;
+  void Close() override;
+  double GetMaxVolume() override;
+  void SetVolume(double volume) override;
+  double GetVolume() override;
+  bool IsMuted() override;
+  void SetOutputDeviceForAec(const std::string& output_device_id) override;
+
+ private:
+
+  enum StreamState {
+    kClosed,            // Not opened yet
+    kStopped,           // Device opened, but not started yet
+    kRunning,           // Started, device playing
+    kStopWait           // Stopping, waiting for the real-time thread to exit
+  };
+
+  // C-style call-backs
+  static void OnMoveCallback(void *arg, int delta);
+  static void* ThreadEntry(void *arg);
+
+  // Continuously moves data from the device to the consumer
+  void ThreadLoop();
+  // Our creator, the audio manager needs to be notified when we close.
+  AudioManagerBase* manager;
+  // Parameters of the source
+  AudioParameters params;
+  // We store data here for consumer
+  std::unique_ptr<AudioBus> audio_bus;
+  // Call-back that consumes recorded data
+  AudioInputCallback* callback;  // Valid during a recording session.
+  // Handle of the audio device
+  struct sio_hdl* hdl;
+  // Current state of the stream
+  enum StreamState state;
+  // High priority thread running ThreadLoop()
+  pthread_t thread;
+  // Number of frames buffered in the hardware
+  int hw_delay;
+  // Temporary buffer where data is stored sndio-compatible format
+  char* buffer;
+
+  DISALLOW_COPY_AND_ASSIGN(SndioAudioInputStream);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
diff --git a/srcpkgs/electron13/files/sndio-files/sndio_output.cc b/srcpkgs/electron13/files/sndio-files/sndio_output.cc
new file mode 100644
index 000000000000..a6719f9aac8d
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/sndio_output.cc
@@ -0,0 +1,183 @@
+// Copyright (c) 2012 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.
+
+#include "base/logging.h"
+#include "base/time/time.h"
+#include "base/time/default_tick_clock.h"
+#include "media/audio/audio_manager_base.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/audio/sndio/sndio_output.h"
+
+namespace media {
+
+static const SampleFormat kSampleFormat = kSampleFormatS16;
+
+void SndioAudioOutputStream::OnMoveCallback(void *arg, int delta) {
+  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
+
+  self->hw_delay -= delta;
+}
+
+void SndioAudioOutputStream::OnVolCallback(void *arg, unsigned int vol) {
+  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
+
+  self->vol = vol;
+}
+
+void *SndioAudioOutputStream::ThreadEntry(void *arg) {
+  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
+
+  self->ThreadLoop();
+  return NULL;
+}
+
+SndioAudioOutputStream::SndioAudioOutputStream(const AudioParameters& params,
+                                               AudioManagerBase* manager)
+    : manager(manager),
+      params(params),
+      audio_bus(AudioBus::Create(params)),
+      state(kClosed),
+      mutex(PTHREAD_MUTEX_INITIALIZER) {
+}
+
+SndioAudioOutputStream::~SndioAudioOutputStream() {
+  if (state != kClosed)
+    Close();
+}
+
+bool SndioAudioOutputStream::Open() {
+  struct sio_par par;
+  int sig;
+
+  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
+      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
+    LOG(WARNING) << "Unsupported audio format.";
+    return false;
+  }
+  sio_initpar(&par);
+  par.rate = params.sample_rate();
+  par.pchan = params.channels();
+  par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
+  par.bps = par.bits / 8;
+  par.sig = sig = par.bits != 8 ? 1 : 0;
+  par.le = SIO_LE_NATIVE;
+  par.appbufsz = params.frames_per_buffer();
+
+  hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
+  if (hdl == NULL) {
+    LOG(ERROR) << "Couldn't open audio device.";
+    return false;
+  }
+  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
+    LOG(ERROR) << "Couldn't set audio parameters.";
+    goto bad_close;
+  }
+  if (par.rate  != (unsigned int)params.sample_rate() ||
+      par.pchan != (unsigned int)params.channels() ||
+      par.bits  != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
+      par.sig   != (unsigned int)sig ||
+      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
+      (par.bits != par.bps * 8)) {
+    LOG(ERROR) << "Unsupported audio parameters.";
+    goto bad_close;
+  }
+  state = kStopped;
+  volpending = 0;
+  vol = 0;
+  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
+  sio_onmove(hdl, &OnMoveCallback, this);
+  sio_onvol(hdl, &OnVolCallback, this);
+  return true;
+ bad_close:
+  sio_close(hdl);
+  return false;
+}
+
+void SndioAudioOutputStream::Close() {
+  if (state == kClosed)
+    return;
+  if (state == kRunning)
+    Stop();
+  state = kClosed;
+  delete [] buffer;
+  sio_close(hdl);
+  manager->ReleaseOutputStream(this);  // Calls the destructor
+}
+
+void SndioAudioOutputStream::Start(AudioSourceCallback* callback) {
+  state = kRunning;
+  hw_delay = 0;
+  source = callback;
+  sio_start(hdl);
+  if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
+    LOG(ERROR) << "Failed to create real-time thread.";
+    sio_stop(hdl);
+    state = kStopped;
+  }
+}
+
+void SndioAudioOutputStream::Stop() {
+  if (state == kStopped)
+    return;
+  state = kStopWait;
+  pthread_join(thread, NULL);
+  sio_stop(hdl);
+  state = kStopped;
+}
+
+void SndioAudioOutputStream::SetVolume(double v) {
+  pthread_mutex_lock(&mutex);
+  vol = v * SIO_MAXVOL;
+  volpending = 1;
+  pthread_mutex_unlock(&mutex);
+}
+
+void SndioAudioOutputStream::GetVolume(double* v) {
+  pthread_mutex_lock(&mutex);
+  *v = vol * (1. / SIO_MAXVOL);
+  pthread_mutex_unlock(&mutex);
+}
+
+// This stream is always used with sub second buffer sizes, where it's
+// sufficient to simply always flush upon Start().
+void SndioAudioOutputStream::Flush() {}
+
+void SndioAudioOutputStream::ThreadLoop(void) {
+  int avail, count, result;
+
+  while (state == kRunning) {
+    // Update volume if needed
+    pthread_mutex_lock(&mutex);
+    if (volpending) {
+      volpending = 0;
+      sio_setvol(hdl, vol);
+    }
+    pthread_mutex_unlock(&mutex);
+
+    // Get data to play
+    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
+	params.sample_rate());
+    count = source->OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get());
+    audio_bus->ToInterleaved(count, SampleFormatToBytesPerChannel(kSampleFormat), buffer);
+    if (count == 0) {
+      // We have to submit something to the device
+      count = audio_bus->frames();
+      memset(buffer, 0, count * params.GetBytesPerFrame(kSampleFormat));
+      LOG(WARNING) << "No data to play, running empty cycle.";
+    }
+
+    // Submit data to the device
+    avail = count * params.GetBytesPerFrame(kSampleFormat);
+    result = sio_write(hdl, buffer, avail);
+    if (result == 0) {
+      LOG(WARNING) << "Audio device disconnected.";
+      break;
+    }
+
+    // Update hardware pointer
+    hw_delay += count;
+  }
+}
+
+}  // namespace media
diff --git a/srcpkgs/electron13/files/sndio-files/sndio_output.h b/srcpkgs/electron13/files/sndio-files/sndio_output.h
new file mode 100644
index 000000000000..ead220ca96e7
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-files/sndio_output.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2012 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 MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
+#define MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
+
+#include <pthread.h>
+#include <sndio.h>
+
+#include "base/time/tick_clock.h"
+#include "base/time/time.h"
+#include "media/audio/audio_io.h"
+
+namespace media {
+
+class AudioManagerBase;
+
+// Implementation of AudioOutputStream using sndio(7)
+class SndioAudioOutputStream : public AudioOutputStream {
+ public:
+  // The manager is creating this object
+  SndioAudioOutputStream(const AudioParameters& params,
+                         AudioManagerBase* manager);
+  virtual ~SndioAudioOutputStream();
+
+  // Implementation of AudioOutputStream.
+  bool Open() override;
+  void Close() override;
+  void Start(AudioSourceCallback* callback) override;
+  void Stop() override;
+  void SetVolume(double volume) override;
+  void GetVolume(double* volume) override;
+  void Flush() override;
+
+  friend void sndio_onmove(void *arg, int delta);
+  friend void sndio_onvol(void *arg, unsigned int vol);
+  friend void *sndio_threadstart(void *arg);
+
+ private:
+  enum StreamState {
+    kClosed,            // Not opened yet
+    kStopped,           // Device opened, but not started yet
+    kRunning,           // Started, device playing
+    kStopWait           // Stopping, waiting for the real-time thread to exit
+  };
+
+  // C-style call-backs
+  static void OnMoveCallback(void *arg, int delta);
+  static void OnVolCallback(void *arg, unsigned int vol);
+  static void* ThreadEntry(void *arg);
+
+  // Continuously moves data from the producer to the device
+  void ThreadLoop(void);
+
+  // Our creator, the audio manager needs to be notified when we close.
+  AudioManagerBase* manager;
+  // Parameters of the source
+  AudioParameters params;
+  // Source stores data here
+  std::unique_ptr<AudioBus> audio_bus;
+  // Call-back that produces data to play
+  AudioSourceCallback* source;
+  // Handle of the audio device
+  struct sio_hdl* hdl;
+  // Current state of the stream
+  enum StreamState state;
+  // High priority thread running ThreadLoop()
+  pthread_t thread;
+  // Protects vol, volpending and hw_delay
+  pthread_mutex_t mutex;
+  // Current volume in the 0..SIO_MAXVOL range
+  int vol;
+  // Set to 1 if volumes must be refreshed in the realtime thread
+  int volpending;
+  // Number of frames buffered in the hardware
+  int hw_delay;
+  // Temporary buffer where data is stored sndio-compatible format
+  char* buffer;
+
+  DISALLOW_COPY_AND_ASSIGN(SndioAudioOutputStream);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
diff --git a/srcpkgs/electron13/files/sndio-patches/media_audio_linux_audio_manager_linux.cc.patch b/srcpkgs/electron13/files/sndio-patches/media_audio_linux_audio_manager_linux.cc.patch
new file mode 100644
index 000000000000..cf8e81b11d67
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-patches/media_audio_linux_audio_manager_linux.cc.patch
@@ -0,0 +1,43 @@
+diff --git a/chromium/media/audio/linux/audio_manager_linux.cc b/chromium/media/audio/linux/audio_manager_linux.cc
+index 5d703549372..9e60b40c749 100644
+--- media/audio/linux/audio_manager_linux.cc
++++ media/audio/linux/audio_manager_linux.cc
+@@ -20,6 +20,10 @@
+ #include "media/audio/pulse/audio_manager_pulse.h"
+ #include "media/audio/pulse/pulse_util.h"
+ #endif
++#if defined(USE_SNDIO)
++#include <sndio.h>
++#include "media/audio/openbsd/audio_manager_openbsd.h"
++#endif
+ 
+ namespace media {
+ 
+@@ -27,7 +31,8 @@ enum LinuxAudioIO {
+   kPulse,
+   kAlsa,
+   kCras,
+-  kAudioIOMax = kCras  // Must always be equal to largest logged entry.
++  kSndio,
++  kAudioIOMax = kSndio  // Must always be equal to largest logged entry.
+ };
+ 
+ std::unique_ptr<media::AudioManager> CreateAudioManager(
+@@ -41,6 +46,17 @@ std::unique_ptr<media::AudioManager> CreateAudioManager(
+   }
+ #endif
+ 
++#if defined(USE_SNDIO)
++  struct sio_hdl * hdl = NULL;
++  if ((hdl=sio_open(SIO_DEVANY, SIO_PLAY, 1)) != NULL) {
++    sio_close(hdl);
++    UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kSndio, kAudioIOMax +1);
++    return std::make_unique<AudioManagerOpenBSD>(std::move(audio_thread),
++                                               audio_log_factory);
++  }
++  DVLOG(1) << "Sndio is not available on the OS";
++#endif
++
+ #if defined(USE_PULSEAUDIO)
+   pa_threaded_mainloop* pa_mainloop = nullptr;
+   pa_context* pa_context = nullptr;
diff --git a/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_BUILD.gn.patch b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_BUILD.gn.patch
new file mode 100644
index 000000000000..ec6040026688
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_BUILD.gn.patch
@@ -0,0 +1,12 @@
+--- media/BUILD.gn	2020-03-24 10:16:30.000000000 +0100
++++ -	2020-04-06 14:32:27.960817513 +0200
+@@ -65,6 +65,9 @@
+   if (use_cras) {
+     defines += [ "USE_CRAS" ]
+   }
++  if (use_sndio) {
++    defines += [ "USE_SNDIO" ]
++  }
+ }
+ 
+ # Internal grouping of the configs necessary to support sub-folders having their
diff --git a/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_audio_BUILD.gn.patch b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_audio_BUILD.gn.patch
new file mode 100644
index 000000000000..c856de0bf2ec
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_audio_BUILD.gn.patch
@@ -0,0 +1,23 @@
+--- media/audio/BUILD.gn	2020-03-24 10:16:30.000000000 +0100
++++ -	2020-04-06 14:31:28.871450217 +0200
+@@ -232,9 +232,19 @@
+     deps += [ "//media/base/android:media_jni_headers" ]
+   }
+ 
+-  if (is_linux) {
++  if (is_linux) {
+     sources += [ "linux/audio_manager_linux.cc" ]
+   }
++  if (use_sndio) {
++    libs += [ "sndio" ]
++    sources += [
++      "openbsd/audio_manager_openbsd.cc",
++      "sndio/sndio_input.cc",
++      "sndio/sndio_input.h",
++      "sndio/sndio_output.cc",
++      "sndio/sndio_output.h"
++   ]
++ }
+ 
+   if (use_alsa) {
+     libs += [ "asound" ]
diff --git a/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_media__options.gni.patch b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_media__options.gni.patch
new file mode 100644
index 000000000000..14807d8e1d36
--- /dev/null
+++ b/srcpkgs/electron13/files/sndio-patches/src_3rdparty_chromium_media_media__options.gni.patch
@@ -0,0 +1,12 @@
+--- media/media_options.gni	2020-03-24 10:16:30.000000000 +0100
++++ -	2020-04-06 14:29:22.958630783 +0200
+@@ -114,6 +114,9 @@
+   # Enables runtime selection of ALSA library for audio.
+   use_alsa = false
+ 
++  # Enables runtime selection of sndio library for audio.
++  use_sndio = false
++
+   # Alsa should be used on non-Android, non-Mac POSIX systems.
+   # Alsa should be used on desktop Chromecast and audio-only Chromecast builds.
+   if (is_posix && !is_android && !is_mac &&
diff --git a/srcpkgs/electron13/template b/srcpkgs/electron13/template
new file mode 100644
index 000000000000..4cb13d333b3e
--- /dev/null
+++ b/srcpkgs/electron13/template
@@ -0,0 +1,377 @@
+# Template file for 'electron13'
+pkgname=electron13
+version=13.2.2
+revision=1
+_nodever=14.16.0
+_chromiumver=91.0.4472.69
+archs="x86_64* i686* aarch64* ppc64le*"
+create_wrksrc=yes
+build_wrksrc="src"
+hostmakedepends="$(vopt_if clang clang) python pkgconf perl gperf bison ninja nodejs hwids
+ libwebp-devel freetype-devel harfbuzz-devel libpng-devel nss-devel which git libevent-devel
+ pciutils-devel libatomic-devel ffmpeg-devel libxml2-devel libglib-devel yarn openjdk libxslt-devel
+ opus-devel libXcursor-devel libXcomposite-devel libXtst-devel libXrandr-devel libXScrnSaver-devel
+ alsa-lib-devel re2-devel snappy-devel mit-krb5-devel $(vopt_if pulseaudio pulseaudio-devel)
+ $(vopt_if sndio sndio-devel) jq"
+makedepends="libpng-devel gtk+-devel gtk+3-devel nss-devel pciutils-devel
+ libXi-devel libgcrypt-devel libgnome-keyring-devel cups-devel elfutils-devel
+ libXcomposite-devel speech-dispatcher-devel libXrandr-devel mit-krb5-devel
+ libXScrnSaver-devel alsa-lib-devel snappy-devel libdrm-devel
+ libxml2-devel libxslt-devel $(vopt_if pulseaudio pulseaudio-devel) libexif-devel
+ libXcursor-devel libflac-devel speex-devel libmtp-devel libwebp-devel
+ libjpeg-turbo-devel libevent-devel json-c-devel harfbuzz-devel
+ minizip-devel jsoncpp-devel zlib-devel libcap-devel libXdamage-devel
+ re2-devel fontconfig-devel freetype-devel opus-devel libatomic-devel
+ $(vopt_if sndio sndio-devel) ffmpeg-devel libva-devel libuv-devel c-ares-devel libnotify-devel
+ $(vopt_if pipewire pipewire-devel) wayland-devel libcurl-devel"
+short_desc="Cross platform application framework based on web technologies"
+maintainer="John <me@johnnynator.dev>"
+license="BSD-3-Clause"
+homepage="https://electronjs.org"
+distfiles="https://github.com/electron/electron/archive/v$version.tar.gz>electron-${version}.tar.gz
+ https://commondatastorage.googleapis.com/chromium-browser-official/chromium-$_chromiumver.tar.xz
+ https://github.com/nodejs/node/archive/v$_nodever.tar.gz>node-$_nodever.tar.gz"
+checksum="d5e35b412fc055e6fc5636717392193004b37fdd669302f528eee7232b34d9c5
+ 1f6843c636f4adee6b06c301193810cce103ee3e4582d4cbc31c915efc3d0c7b
+ bcdf869b0743405515ee897b1047b5e851a717e426b4974d26537c9b10dfd53a"
+
+case "$XBPS_TARGET_MACHINE" in
+	ppc64*-musl) makedepends+=" libucontext-devel" ;;
+esac
+
+no_generic_pkgconfig_link=yes
+lib32disabled=yes
+nopie=yes  # contains tools that are not PIE, enables PIE itself
+
+build_options="pulseaudio sndio clang pipewire"
+build_options_default="pulseaudio clang pipewire"
+
+if [ "$build_option_clang" ]; then
+	nocross="No proper setup for using clang as cross compiler in void yet"
+elif [ "${XBPS_TARGET_MACHINE%%-musl}" = "aarch64" ]; then
+	broken="Falls apart at runtime when compiled with gcc"
+fi
+
+_buildtype=Release
+_is_debug=false
+
+CFLAGS="-Wno-unknown-warning-option -fPIC"
+CXXFLAGS="-Wno-unknown-warning-option -fPIC"
+
+_apply_patch() {
+	local args="$1" pname="$(basename $2)"
+
+	if [ ! -f ".${pname}_done" ]; then
+		msg_normal "$pkgver: patching: ${pname}.\n"
+		patch -N $args -i $2
+		touch .${pname}_done
+	fi
+}
+
+_get_chromium_arch() {
+	case "$1" in
+		x86_64*) echo x64 ;;
+		i686*) echo x86 ;;
+		arm*) echo arm ;;
+		aarch64*) echo arm64 ;;
+		ppc64*) echo ppc64 ;;
+		ppc*) echo ppc ;;
+		mipsel*) echo mipsel ;;
+		mips*) echo mips ;;
+		*) msg_error "$pkgver: cannot be compiled for ${XBPS_TARGET_MACHINE}.\n" ;;
+	esac
+}
+
+post_extract() {
+	ln -s chromium-$_chromiumver src
+	mkdir -p src/third_party/
+	ln -s ../../node-$_nodever src/third_party/electron_node
+	ln -s ../electron-${version} src/electron
+
+}
+post_patch() {
+	cd $wrksrc
+	for x in $FILESDIR/patches/*; do
+		case "${x##*/}" in
+			electron*.patch)
+				cd src/electron
+				_apply_patch -p1 "$x"
+				cd "$wrksrc";;
+		esac
+	done
+
+	# Sigh, electron uses git am...
+	if [ ! -f ".electron_patches_done" ]; then
+	mv src/electron/patches/config.json config.json.old
+	jq 'del(."src/electron/patches/Mantle", ."src/electron/patches/ReactiveObjC",
+		."src/electron/patches/squirrel.mac", ."src/electron/patches/nan")' \
+		config.json.old > src/electron/patches/config.json
+
+	python2 src/electron/script/list_patch_targets.py src/electron/patches/config.json | while read -r repopath; do
+		cd "$wrksrc"/"$repopath"
+		git init -q
+		git config "gc.auto" 0
+		if [ "$repopath" != "src" ]; then
+			echo "/${repopath#src/}" >> "$wrksrc/$build_wrksrc/.gitignore"
+		fi
+		git add .
+		git -c 'user.name=Electron build' -c 'user.email=electron@ebuild' \
+			commit -q -m "." || true
+	done
+	cd $wrksrc
+	python2 src/electron/script/apply_all_patches.py src/electron/patches/config.json
+	touch .electron_patches_done
+	fi
+
+	for x in $FILESDIR/patches/*; do
+		case "${x##*/}" in
+			chromium*.patch)
+				cd src
+				_apply_patch -p1 "$x"
+				cd "$wrksrc";;
+		esac
+	done
+
+	if [ "$XBPS_TARGET_LIBC" = "musl" ]; then
+	for x in $FILESDIR/musl-patches/*; do
+		case "${x##*/}" in
+			chromium*.patch)
+				cd src
+				_apply_patch -p0 "$x"
+				cd "$wrksrc";;
+			electron*.patch)
+				cd src/electron
+				_apply_patch -p1 "$x"
+				cd "$wrksrc";;
+		esac
+	done
+	fi
+	if [ "$build_option_sndio" ]; then
+		mkdir -p ${wrksrc}/${build_wrksrc}/media/audio/{sndio,openbsd}
+		cp ${FILESDIR}/sndio-files/sndio_*put.* \
+			${wrksrc}/${build_wrksrc}/media/audio/sndio
+		cp ${FILESDIR}/sndio-files/audio_manager_openbsd.* \
+			${wrksrc}/${build_wrksrc}/media/audio/openbsd
+		for f in "${FILESDIR}"/sndio-patches/*.patch; do
+			cd src
+			_apply_patch -p0 "$f"
+			cd "$wrksrc"
+		done
+	fi
+}
+
+pre_configure() {
+	cd "$wrksrc/$build_wrksrc"
+
+	# https://groups.google.com/a/chromium.org/d/topic/chromium-packagers/9JX1N2nf4PU/discussion
+	touch chrome/test/data/webui/i18n_process_css_test.html
+	# Use the file at run time instead of effectively compiling it in
+	sed 's|//third_party/usb_ids/usb.ids|/usr/share/hwdata/usb.ids|g' \
+		-i services/device/public/cpp/usb/BUILD.gn
+
+	mkdir -p third_party/node/linux/node-linux-x64/bin
+	ln -s /usr/bin/node third_party/node/linux/node-linux-x64/bin/
+
+	# compile gn early, so it can be used to generate gni stuff
+	msg_normal "Bootstrapping GN\n"
+	CC="${CC_FOR_BUILD:-$CC}" CXX="${CXX_FOR_BUILD:-$CXX}" LD="${LD_FOR_BUILD:-$LD}" \
+	CFLAGS="${CFLAGS_FOR_BUILD:-$CFLAGS}" CXXFLAGS="${CXXFLAGS_FOR_BUILD:-$CXXFLAGS}" \
+	LDFLAGS="${XBPS_LDFLAGS}" \
+		python2 tools/gn/bootstrap/bootstrap.py -s -v --skip-generate-buildfiles
+
+	# we need to generate ppc64 stuff for libvpx as it's not shipped
+	# this has to be done before unbundling, but after gn is built
+	# comment out if we switch back to system libvpx again later
+	case "$XBPS_TARGET_MACHINE" in
+		ppc64*)
+			pushd third_party/libvpx
+			mkdir -p source/config/linux/ppc64
+			# need PATH to find gn
+			PATH="${wrksrc}/${build_wrksrc}/out/Release:$PATH" \
+				./generate_gni.sh || \
+					msg_error "failed to generate libvpx gni"
+			popd
+			;;
+	esac
+
+	# reusable system library settings
+	local use_system="
+		ffmpeg
+		flac
+		fontconfig
+		freetype
+		harfbuzz-ng
+		libdrm
+		libevent
+		libjpeg
+		libpng
+		libwebp
+		libxml
+		libxslt
+		opus
+		re2
+		snappy
+		"
+	for _lib in $use_system libjpeg_turbo; do
+		msg_normal "Removing buildscripts for system provided $_lib\n"
+		find -type f -path "*third_party/$_lib/*" \
+			\! -path "*third_party/$_lib/chromium/*" \
+			\! -path "*third_party/$_lib/google/*" \
+			\! -path './base/third_party/icu/*' \
+			\! -path './third_party/pdfium/third_party/freetype/include/pstables.h' \
+			\! -path './third_party/harfbuzz-ng/utils/hb_scoped.h' \
+			\! -regex '.*\.\(gn\|gni\|isolate\|py\)' \
+			-delete
+	done
+
+
+	msg_normal "Replacing gn files\n"
+	python2 build/linux/unbundle/replace_gn_files.py --system-libraries \
+		$use_system
+	third_party/libaddressinput/chromium/tools/update-strings.py
+}
+
+do_configure() {
+	local target_arch="$(_get_chromium_arch ${XBPS_TARGET_MACHINE})"
+	local host_arch="$(_get_chromium_arch ${XBPS_MACHINE})"
+	# the build system will set march for use, adding it to cflags will break builds
+	export CXXFLAGS=$( shopt -s extglob; echo ${CXXFLAGS/-march=*([^ ])} )
+	export CFLAGS=$( shopt -s extglob; echo ${CFLAGS/-march=*([^ ])} )
+	export CFLAGS=${CFLAGS/-g/}
+	export CXXFLAGS=${CXXFLAGS/-g/}
+	local conf=()
+	cd third_party/electron_node
+	if [ "$CROSS_BUILD" ]; then
+		conf_args=" --dest-cpu=${target_arch} --cross-compiling"
+	fi
+	./configure --prefix=/usr \
+		--shared-zlib \
+		--shared-libuv \
+		--shared-openssl \
+		--shared-cares \
+		--openssl-use-def-ca-store \
+		--without-npm \
+		--without-dtrace \
+		--without-bundled-v8 \
+		${conf_args}
+
+	cd "$wrksrc/$build_wrksrc"/electron
+	yarn install
+	cd "$wrksrc/$build_wrksrc"
+
+	if [ "$build_option_clang" ]; then
+		export CC=clang
+		export CXX=clang++
+		export HOST_CC=clang
+		export HOST_CXX=clang++
+	else
+		export CXXFLAGS="$CXXFLAGS -fpermissive"
+		export BUILD_CXXFLAGS="$BUILD_CXXFLAGS -fpermissive"
+		export BUILD_AR="$AR_host"
+		export BUILD_NM="$NM_host"
+	fi
+
+	conf+=(
+		'blink_symbol_level=0'
+		'clang_use_chrome_plugins=false'
+		'custom_toolchain="//build/toolchain/linux/unbundle:default"'
+	)
+	if [ "$CROSS_BUILD" ]; then
+		conf+=(
+			'host_toolchain="//build/toolchain/linux/unbundle:host"'
+			'v8_snapshot_toolchain="//build/toolchain/linux/unbundle:host"'
+			"host_pkg_config=\"$PKG_CONFIG_FOR_BUILD\""
+			"pkg_config=\"$PKG_CONFIG\""
+		)
+	else
+		conf+=(
+			'host_toolchain="//build/toolchain/linux/unbundle:default"'
+			'v8_snapshot_toolchain="//build/toolchain/linux/unbundle:default"'
+		)
+	fi
+	if [ "$build_option_sndio" ]; then
+		conf+=(
+			'use_sndio=true'
+		)
+	fi
+	if [ -n "$XBPS_DEBUG_PKGS" ]; then
+		conf+=('symbol_level=1')
+	else
+		conf+=('symbol_level=0')
+	fi
+	conf+=(
+		'enable_hangout_services_extension=true'
+		'enable_nacl_nonsfi=false'
+		'enable_nacl=false'
+		'enable_precompiled_headers=false'
+		'fatal_linker_warnings=false'
+		'ffmpeg_branding="Chrome"'
+		'fieldtrial_testing_like_official_build=true'
+		'gold_path="/usr/bin/ld.gold"'
+		'icu_use_data_file=true'
+		"is_clang=$(vopt_if clang true false)"
+		'is_component_build=false'
+		"is_debug=$_is_debug"
+		'proprietary_codecs=true'
+		'treat_warnings_as_errors=false'
+		'use_allocator_shim=false'
+		'use_allocator="none"'
+		'use_cups=true'
+		'use_custom_libcxx=false'
+		'use_gnome_keyring=false'
+		'use_gold=false'
+		'use_lld=false'
+		'use_system_libwayland=true'
+		"use_pulseaudio=$(vopt_if pulseaudio 'true' 'false')"
+		"rtc_use_pipewire=$(vopt_if pipewire true false)"
+		'rtc_pipewire_version="0.3"'
+		'use_sysroot=false'
+		'use_system_harfbuzz=true'
+		"target_cpu=\"$target_arch\""
+		"host_cpu=\"$host_arch\""
+		'import("//electron/build/args/release.gn")'
+	)
+
+	msg_normal "Configuring build\n"
+	out/Release/gn gen out/$_buildtype --args="${conf[*]}"
+}
+
+do_build() {
+	export CXXFLAGS=$( shopt -s extglob; echo ${CXXFLAGS/-march=*([^ ])} )
+	export CFLAGS=$( shopt -s extglob; echo ${CFLAGS/-march=*([^ ])} )
+	export CFLAGS=${CFLAGS/-g/}
+	export CXXFLAGS=${CXXFLAGS/-g/}
+	if [ "$build_option_clang" ]; then
+		export CC=clang
+		export CXX=clang++
+		export HOST_CC=clang
+		export HOST_CXX=clang++
+	else
+		export BUILD_CXXFLAGS="$BUILD_CXXFLAGS -fpermissive"
+		export CXXFLAGS="$CXXFLAGS -fpermissive"
+		export BUILD_AR="$AR_host"
+		export BUILD_NM="$NM_host"
+	fi
+	msg_normal "Ninja turtles GO!\n"
+	ninja ${makejobs} -C out/$_buildtype electron third_party/electron_node:headers
+	# finish rest of the build
+	strip -s out/$_buildtype/electron
+	ninja ${makejobs} -C out/$_buildtype electron_dist_zip
+}
+
+do_install() {
+	vmkdir /usr/lib/$pkgname
+	vmkdir /usr/include/$pkgname
+	bsdtar -xf out/$_buildtype/dist.zip -C "$DESTDIR/usr/lib/$pkgname"
+
+	chmod u+s "$DESTDIR/usr/lib/$pkgname/chrome-sandbox"
+
+	cp out/$_buildtype/gen/node_headers.tar.gz "$DESTDIR"/usr/include/$pkgname
+
+	vlicense ${wrksrc}/src/LICENSE chromium.LICENSE
+	vlicense ${wrksrc}/src/electron/LICENSE electron.LICENSE
+	vlicense ${wrksrc}/src/third_party/electron_node/LICENSE node.LICENSE
+
+	vmkdir /usr/bin
+	ln -s ../lib/$pkgname/electron "$DESTDIR"/usr/bin/$pkgname
+}
diff --git a/srcpkgs/electron13/update b/srcpkgs/electron13/update
new file mode 100644
index 000000000000..3af8e58b5358
--- /dev/null
+++ b/srcpkgs/electron13/update
@@ -0,0 +1,2 @@
+site=https://www.electronjs.org/releases/stable?version=${version%%.*}
+pattern='tag/v\K[\d\.]+(?=")'

From 8e16d741e1e152b3a5c5f6b4e7a2ac46f4d25dfb Mon Sep 17 00:00:00 2001
From: John <me@johnnynator.dev>
Date: Sat, 28 Aug 2021 12:43:48 +0200
Subject: [PATCH 2/3] vscode: use electron13

---
 .../patches/disable-crash-reporter.patch      | 71 +++++++++++++++++++
 srcpkgs/vscode/template                       |  8 +--
 2 files changed, 75 insertions(+), 4 deletions(-)
 create mode 100644 srcpkgs/vscode/patches/disable-crash-reporter.patch

diff --git a/srcpkgs/vscode/patches/disable-crash-reporter.patch b/srcpkgs/vscode/patches/disable-crash-reporter.patch
new file mode 100644
index 000000000000..59553fabf753
--- /dev/null
+++ b/srcpkgs/vscode/patches/disable-crash-reporter.patch
@@ -0,0 +1,71 @@
+From afa206dc466066c3d273dfc879103700505b3d7b Mon Sep 17 00:00:00 2001
+From: Joshua Strobl <joshua@streambits.io>
+Date: Sun, 22 Aug 2021 14:02:05 +0300
+Subject: [PATCH 1/1] Disable crash reporter since Microsoft refuses to fix
+ this upstream.
+
+Unfortunately a PR submitted by a third-party was rejected by Microsoft, which would change the default for crash reporting from true to false and move the telemetry configuration to ensure crash reporting was not being forced on, placed in the argv.json, and cause a crash when improperly set.
+
+So, disable it entirely. No cookies for you, Visual Studio Code team.
+---
+ src/bootstrap-fork.js            |  3 ---
+ src/main.js                      | 16 ----------------
+ src/vs/code/electron-main/app.ts |  2 +-
+ 3 files changed, 1 insertion(+), 20 deletions(-)
+
+diff --git a/src/bootstrap-fork.js b/src/bootstrap-fork.js
+index 55303d9a556..ead5d08663f 100644
+--- a/src/bootstrap-fork.js
++++ b/src/bootstrap-fork.js
+@@ -37,9 +37,6 @@ if (process.env['VSCODE_PARENT_PID']) {
+ 	terminateWhenParentTerminates();
+ }
+ 
+-// Configure Crash Reporter
+-configureCrashReporter();
+-
+ // Load AMD entry point
+ require('./bootstrap-amd').load(process.env['VSCODE_AMD_ENTRYPOINT']);
+ 
+diff --git a/src/main.js b/src/main.js
+index 9cf737e0649..1d779632498 100644
+--- a/src/main.js
++++ b/src/main.js
+@@ -46,22 +46,6 @@ const codeCachePath = getCodeCachePath();
+ // Configure static command line arguments
+ const argvConfig = configureCommandlineSwitchesSync(args);
+ 
+-// Configure crash reporter
+-perf.mark('code/willStartCrashReporter');
+-// If a crash-reporter-directory is specified we store the crash reports
+-// in the specified directory and don't upload them to the crash server.
+-//
+-// Appcenter crash reporting is enabled if
+-// * enable-crash-reporter runtime argument is set to 'true'
+-// * --disable-crash-reporter command line parameter is not set
+-//
+-// Disable crash reporting in all other cases.
+-if (args['crash-reporter-directory'] ||
+-	(argvConfig['enable-crash-reporter'] && !args['disable-crash-reporter'])) {
+-	configureCrashReporter();
+-}
+-perf.mark('code/didStartCrashReporter');
+-
+ // Set logs path before app 'ready' event if running portable
+ // to ensure that no 'logs' folder is created on disk at a
+ // location outside of the portable directory
+diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts
+index 135f444bdbf..9d207a91bcf 100644
+--- a/src/vs/code/electron-main/app.ts
++++ b/src/vs/code/electron-main/app.ts
+@@ -982,7 +982,7 @@ export class CodeApplication extends Disposable {
+ 			const argvJSON = JSON.parse(stripComments(argvString));
+ 			if (argvJSON['enable-crash-reporter'] === undefined) {
+ 				const enableCrashReporterSetting = this.configurationService.getValue('telemetry.enableCrashReporter');
+-				const enableCrashReporter = typeof enableCrashReporterSetting === 'boolean' ? enableCrashReporterSetting : true;
++				const enableCrashReporter = typeof enableCrashReporterSetting === 'boolean' ? enableCrashReporterSetting : false;
+ 				const additionalArgvContent = [
+ 					'',
+ 					'	// Allows to disable crash reporting.',
+-- 
+2.32.0
diff --git a/srcpkgs/vscode/template b/srcpkgs/vscode/template
index da7d5cbe5bcf..4a141543c9c2 100644
--- a/srcpkgs/vscode/template
+++ b/srcpkgs/vscode/template
@@ -1,11 +1,11 @@
 # Template file for 'vscode'
 pkgname=vscode
 version=1.59.1
-revision=2
-_electronver=12.0.14
+revision=3
+_electronver=13.2.2
 hostmakedepends="pkg-config python nodejs yarn tar git"
-makedepends="libxkbfile-devel libsecret-devel electron12"
-depends="libXtst libxkbfile nss dejavu-fonts-ttf xdg-utils ripgrep electron12"
+makedepends="libxkbfile-devel libsecret-devel electron13"
+depends="libXtst libxkbfile nss dejavu-fonts-ttf xdg-utils ripgrep electron13"
 short_desc="Microsoft Code for Linux"
 maintainer="shizonic <realtiaz@gmail.com>"
 license="MIT"

From 1a698abc9e4e74356c335226f1c58a74cc516a3e Mon Sep 17 00:00:00 2001
From: John <me@johnnynator.dev>
Date: Sat, 28 Aug 2021 12:45:45 +0200
Subject: [PATCH 3/3] Rocket.Chat-Desktop: update to 3.4.0.

---
 srcpkgs/Rocket.Chat-Desktop/files/Rocket.Chat-Desktop | 2 +-
 srcpkgs/Rocket.Chat-Desktop/template                  | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/srcpkgs/Rocket.Chat-Desktop/files/Rocket.Chat-Desktop b/srcpkgs/Rocket.Chat-Desktop/files/Rocket.Chat-Desktop
index 90d482ab178d..214b977b5989 100644
--- a/srcpkgs/Rocket.Chat-Desktop/files/Rocket.Chat-Desktop
+++ b/srcpkgs/Rocket.Chat-Desktop/files/Rocket.Chat-Desktop
@@ -1,2 +1,2 @@
 #!/bin/sh
-exec electron10 /usr/lib/Rocket.Chat-Desktop.asar "$@"
+exec electron13 /usr/lib/Rocket.Chat-Desktop.asar "$@"
diff --git a/srcpkgs/Rocket.Chat-Desktop/template b/srcpkgs/Rocket.Chat-Desktop/template
index d866c3c51852..b2d47097ec35 100644
--- a/srcpkgs/Rocket.Chat-Desktop/template
+++ b/srcpkgs/Rocket.Chat-Desktop/template
@@ -1,8 +1,8 @@
 # Template file for 'Rocket.Chat-Desktop'
 pkgname=Rocket.Chat-Desktop
-version=3.3.0
+version=3.4.0
 revision=1
-_electron_ver=10
+_electron_ver=13
 wrksrc="Rocket.Chat.Electron-${version}"
 hostmakedepends="yarn nodejs python3 pkg-config app-builder"
 makedepends="electron${_electron_ver} libvips-devel"
@@ -12,7 +12,7 @@ maintainer="John <me@johnnynator.dev>"
 license="MIT"
 homepage="https://rocket.chat/"
 distfiles="https://github.com/RocketChat/Rocket.Chat.Electron/archive/${version}.tar.gz"
-checksum=a08d79c20b89d4e954b3f91d728d51f0d24094878da6b24c930cebc1ce7ce64c
+checksum=fd77cf5a05e8866e9647fef8e793365148490bdc8c1c8986eb246b4540a4b728
 
 export USE_SYSTEM_APP_BUILDER=true
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PR PATCH] [Merged]: electron13-13.2.2
  2021-05-26 19:41 [PR PATCH] [WiP] New package: electron13-13.0.0 Johnnynator
  2021-08-29  0:24 ` [PR PATCH] [Updated] " Johnnynator
  2021-08-29  0:26 ` [PR PATCH] [Updated] electron13-13.2.2 Johnnynator
@ 2021-08-29 15:59 ` Johnnynator
  2 siblings, 0 replies; 4+ messages in thread
From: Johnnynator @ 2021-08-29 15:59 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 1585 bytes --]

There's a merged pull request on the void-packages repository

electron13-13.2.2
https://github.com/void-linux/void-packages/pull/31136

Description:
<!-- Mark items with [x] where applicable -->

#### General
- [ ] This is a new package and it conforms to the [quality requirements](https://github.com/void-linux/void-packages/blob/master/Manual.md#quality-requirements)

#### Have the results of the proposed changes been tested?
- [ ] I use the packages affected by the proposed changes on a regular basis and confirm this PR works for me
- [ ] I generally don't use the affected packages but briefly tested this PR

- This doesn't compile yet on musl, they move a lot of dns stuff from generic posix to a linux specific file, that ofc only works for glibc.

[ci skip]

<!--
If GitHub CI cannot be used to validate the build result (for example, if the
build is likely to take several hours), make sure to
[skip CI](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#continuous-integration).
When skipping CI, uncomment and fill out the following section.
Note: for builds that are likely to complete in less than 2 hours, it is not
acceptable to skip CI.
-->
<!-- 
#### Does it build and run successfully? 
(Please choose at least one native build and, if supported, at least one cross build. More are better.)
- [ ] I built this PR locally for my native architecture, (ARCH-LIBC)
- [ ] I built this PR locally for these architectures (if supported. mark crossbuilds):
  - [ ] aarch64-musl
  - [ ] armv7l
  - [ ] armv6l-musl
-->


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-08-29 15:59 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-26 19:41 [PR PATCH] [WiP] New package: electron13-13.0.0 Johnnynator
2021-08-29  0:24 ` [PR PATCH] [Updated] " Johnnynator
2021-08-29  0:26 ` [PR PATCH] [Updated] electron13-13.2.2 Johnnynator
2021-08-29 15:59 ` [PR PATCH] [Merged]: electron13-13.2.2 Johnnynator

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).