Bug 1309172 - Updated breakpad to version 69c2c51dd89965d234eec16e3a9353634831916b; r=ted.mielczarek
☠☠ backed out by e96c47860e6e ☠ ☠
authorGabriele Svelto <gsvelto@mozilla.com>
Tue, 19 Jun 2018 13:47:13 +0200
changeset 479876 07a62b4e792399774c6c056140f1a6bf9102b164
parent 479875 34fc2ff698c3796600e79073daa6011f24aecc06
child 479877 7aaaed1a9ef133175a7f18054302e890e451f9eb
push id1757
push userffxbld-merge
push dateFri, 24 Aug 2018 17:02:43 +0000
treeherdermozilla-release@736023aebdb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs1309172
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1309172 - Updated breakpad to version 69c2c51dd89965d234eec16e3a9353634831916b; r=ted.mielczarek This includes both the vanilla sources we haven't forked and the client sources that we have. Client patches were applied manually up to version 69c2c51dd89965d234eec16e3a9353634831916b. The following changes were not included as they break merging segments corresponding to libxul.so in the module list: 8915f7be39448d9257b6da3ad0233944d1d9a92a 17ad0c18b179c135fc5a3d2bba199c3fa4276035 94b6309aecaddfcf11672f6cfad9575d68ad3b40 With these changes applied two entries for libxul.so are generated, the second one is bogus and prevents symbolication from working correctly. The build system and some of the tools relying on breakpad were also updated to work with the new version.
toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_server.cc
toolkit/crashreporter/breakpad-client/linux/dump_writer_common/mapping_info.h
toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.cc
toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.h
toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.cc
toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.h
toolkit/crashreporter/breakpad-client/linux/handler/exception_handler_unittest.cc
toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.cc
toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.h
toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.cc
toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.h
toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer_unittest.cc
toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper.cc
toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper_unittest.cc
toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc
toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.h
toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper_unittest_helper.cc
toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.cc
toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.h
toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.cc
toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.h
toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest.cc
toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.h
toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc
toolkit/crashreporter/breakpad-client/mac/handler/minidump_test.xcodeproj/project.pbxproj
toolkit/crashreporter/breakpad-client/mac/tests/exception_handler_test.cc
toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test.cc
toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.cc
toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.cc
toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.h
toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.cc
toolkit/crashreporter/breakpad-client/windows/unittests/crash_generation_server_test.cc
toolkit/crashreporter/breakpad-client/windows/unittests/dump_analysis.cc
toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_death_test.cc
toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_test.cc
toolkit/crashreporter/breakpad-client/windows/unittests/minidump_test.cc
toolkit/crashreporter/google-breakpad/.gitignore
toolkit/crashreporter/google-breakpad/DEPS
toolkit/crashreporter/google-breakpad/GIT-INFO
toolkit/crashreporter/google-breakpad/Makefile.am
toolkit/crashreporter/google-breakpad/README.md
toolkit/crashreporter/google-breakpad/aclocal.m4
toolkit/crashreporter/google-breakpad/autotools/compile
toolkit/crashreporter/google-breakpad/autotools/config.guess
toolkit/crashreporter/google-breakpad/autotools/config.sub
toolkit/crashreporter/google-breakpad/autotools/depcomp
toolkit/crashreporter/google-breakpad/autotools/install-sh
toolkit/crashreporter/google-breakpad/autotools/ltmain.sh
toolkit/crashreporter/google-breakpad/autotools/missing
toolkit/crashreporter/google-breakpad/autotools/test-driver
toolkit/crashreporter/google-breakpad/configure
toolkit/crashreporter/google-breakpad/configure.ac
toolkit/crashreporter/google-breakpad/default.xml
toolkit/crashreporter/google-breakpad/m4/ax_pthread.m4
toolkit/crashreporter/google-breakpad/m4/libtool.m4
toolkit/crashreporter/google-breakpad/m4/ltoptions.m4
toolkit/crashreporter/google-breakpad/m4/ltsugar.m4
toolkit/crashreporter/google-breakpad/m4/ltversion.m4
toolkit/crashreporter/google-breakpad/m4/lt~obsolete.m4
toolkit/crashreporter/google-breakpad/src/build/common.gypi
toolkit/crashreporter/google-breakpad/src/build/testing.gyp
toolkit/crashreporter/google-breakpad/src/build/testing.gypi
toolkit/crashreporter/google-breakpad/src/common/android/breakpad_getcontext.S
toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/README.md
toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/asm.h
toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/fpregdef.h
toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/regdef.h
toolkit/crashreporter/google-breakpad/src/common/android/include/link.h
toolkit/crashreporter/google-breakpad/src/common/android/include/sgidefs.h
toolkit/crashreporter/google-breakpad/src/common/android/include/sys/user.h
toolkit/crashreporter/google-breakpad/src/common/common.gyp
toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.cc
toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.h
toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2enums.h
toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.cc
toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.h
toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_cfi_unittest.cc
toolkit/crashreporter/google-breakpad/src/common/dwarf/elf_reader.h
toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.cc
toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.h
toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.cc
toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.h
toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module_unittest.cc
toolkit/crashreporter/google-breakpad/src/common/language.cc
toolkit/crashreporter/google-breakpad/src/common/language.h
toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.cc
toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.h
toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc
toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h
toolkit/crashreporter/google-breakpad/src/common/linux/file_id_unittest.cc
toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc
toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.cc
toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary.cc
toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary.h
toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary_unittest.cc
toolkit/crashreporter/google-breakpad/src/common/mac/GTMDefines.h
toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.m
toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.cc
toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.cc
toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader_unittest.cc
toolkit/crashreporter/google-breakpad/src/common/md5.cc
toolkit/crashreporter/google-breakpad/src/common/module.cc
toolkit/crashreporter/google-breakpad/src/common/moz.build
toolkit/crashreporter/google-breakpad/src/common/path_helper.cc
toolkit/crashreporter/google-breakpad/src/common/path_helper.h
toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary.h
toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary_unittest.cc
toolkit/crashreporter/google-breakpad/src/common/string_conversion.cc
toolkit/crashreporter/google-breakpad/src/common/windows/omap.cc
toolkit/crashreporter/google-breakpad/src/common/windows/omap_internal.h
toolkit/crashreporter/google-breakpad/src/common/windows/omap_unittest.cc
toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc
toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h
toolkit/crashreporter/google-breakpad/src/config.h.in
toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_linux.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_mac.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_win32.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_format.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/basic_source_line_resolver.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/code_module.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/microdump.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/microdump_processor.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/proc_maps_linux.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_state.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_symbolizer.h
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stackwalker.h
toolkit/crashreporter/google-breakpad/src/processor/basic_code_module.h
toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver.cc
toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_types.h
toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/dump_context.cc
toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.cc
toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/logging.cc
toolkit/crashreporter/google-breakpad/src/processor/logging.h
toolkit/crashreporter/google-breakpad/src/processor/microdump.cc
toolkit/crashreporter/google-breakpad/src/processor/microdump_processor.cc
toolkit/crashreporter/google-breakpad/src/processor/microdump_processor_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk.cc
toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_machine_readable_test
toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test
toolkit/crashreporter/google-breakpad/src/processor/minidump.cc
toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc
toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc
toolkit/crashreporter/google-breakpad/src/processor/minidump_processor_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk.cc
toolkit/crashreporter/google-breakpad/src/processor/minidump_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/moz.build
toolkit/crashreporter/google-breakpad/src/processor/process_state.cc
toolkit/crashreporter/google-breakpad/src/processor/processor.gyp
toolkit/crashreporter/google-breakpad/src/processor/proto/README
toolkit/crashreporter/google-breakpad/src/processor/range_map-inl.h
toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base_types.h
toolkit/crashreporter/google-breakpad/src/processor/stack_frame_symbolizer.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.h
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips64_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_unittest_utils.h
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.cc
toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.cc
toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.h
toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc
toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.h
toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/LICENSE
toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/README.breakpad
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/gflags/gflags.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/lib/gflags/libgflags.a
toolkit/crashreporter/google-breakpad/src/third_party/linux/lib/glog/libglog.a
toolkit/crashreporter/google-breakpad/src/third_party/lss/README.md
toolkit/crashreporter/google-breakpad/src/third_party/lss/codereview.settings
toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h
toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine.h
toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump-2-core.cc
toolkit/crashreporter/google-breakpad/src/tools/linux/tools_linux.gypi
toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj
toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.mm
toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/macho_dump.cc
toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/arch_constants.h
toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/arch_reader.go
toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/upload_system_symbols.go
toolkit/crashreporter/google-breakpad/src/tools/python/deps-to-manifest.py
toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/dump_syms.exe
toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/symupload.exe
toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc
toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.cc
toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms_unittest.cc
toolkit/crashreporter/google-breakpad/src/tools/windows/refresh_binaries.bat
toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc
toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.gyp
toolkit/crashreporter/google-breakpad/src/tools/windows/tools_windows.gyp
toolkit/crashreporter/minidump-analyzer/MozStackFrameSymbolizer.cpp
toolkit/crashreporter/minidump-analyzer/MozStackFrameSymbolizer.h
toolkit/crashreporter/update-breakpad.sh
--- a/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_server.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_server.cc
@@ -250,17 +250,17 @@ CrashGenerationServer::ClientEvent(short
     } else if (hdr->cmsg_type == SCM_CREDENTIALS) {
       const struct ucred *cred =
           reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
       crashing_pid = cred->pid;
     }
   }
 
   if (crashing_pid == -1 || signal_fd == -1) {
-    if (signal_fd)
+    if (signal_fd != -1)
       close(signal_fd);
     return true;
   }
 
   string minidump_filename;
   if (!MakeMinidumpFilename(minidump_filename))
     return true;
 
--- a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/mapping_info.h
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/mapping_info.h
@@ -36,18 +36,31 @@
 
 #include "google_breakpad/common/minidump_format.h"
 
 namespace google_breakpad {
 
 // One of these is produced for each mapping in the process (i.e. line in
 // /proc/$x/maps).
 struct MappingInfo {
+  // On Android, relocation packing can mean that the reported start
+  // address of the mapping must be adjusted by a bias in order to
+  // compensate for the compression of the relocation section. The
+  // following two members hold (after LateInit) the adjusted mapping
+  // range. See crbug.com/606972 for more information.
   uintptr_t start_addr;
   size_t size;
+  // When Android relocation packing causes |start_addr| and |size| to
+  // be modified with a load bias, we need to remember the unbiased
+  // address range. The following structure holds the original mapping
+  // address range as reported by the operating system.
+  struct {
+    uintptr_t start_addr;
+    uintptr_t end_addr;
+  } system_mapping_info;
   size_t offset;  // offset into the backed file.
   bool exec;  // true if the mapping has the execute bit set.
   char name[NAME_MAX];
 };
 
 struct MappingEntry {
   MappingInfo first;
   uint8_t second[sizeof(MDGUID)];
--- a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.cc
@@ -31,17 +31,17 @@
 
 #include "common/linux/linux_libc_support.h"
 #include "google_breakpad/common/minidump_format.h"
 
 namespace google_breakpad {
 
 // Minidump defines register structures which are different from the raw
 // structures which we get from the kernel. These are platform specific
-// functions to juggle the ucontext and user structures into minidump format.
+// functions to juggle the ucontext_t and user structures into minidump format.
 
 #if defined(__i386__)
 
 uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
   return uc->uc_mcontext.gregs[REG_ESP];
 }
 
 uintptr_t UContextReader::GetInstructionPointer(const ucontext_t* uc) {
--- a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.h
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.h
@@ -34,17 +34,17 @@
 #include <sys/user.h>
 
 #include "linux/dump_writer_common/raw_context_cpu.h"
 #include "common/memory_allocator.h"
 #include "google_breakpad/common/minidump_format.h"
 
 namespace google_breakpad {
 
-// Wraps platform-dependent implementations of accessors to ucontext structs.
+// Wraps platform-dependent implementations of accessors to ucontext_t structs.
 struct UContextReader {
   static uintptr_t GetStackPointer(const ucontext_t* uc);
 
   static uintptr_t GetInstructionPointer(const ucontext_t* uc);
 
   // Juggle a arch-specific ucontext into a minidump format
   //   out: the minidump structure
   //   info: the collection of register structures.
--- a/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.cc
@@ -100,22 +100,16 @@
 #if defined(__ANDROID__)
 #include "linux/sched.h"
 #endif
 
 #ifndef PR_SET_PTRACER
 #define PR_SET_PTRACER 0x59616d61
 #endif
 
-// A wrapper for the tgkill syscall: send a signal to a specific thread.
-static int _tgkill(pid_t tgid, pid_t tid, int sig) {
-  return syscall(__NR_tgkill, tgid, tid, sig);
-  return 0;
-}
-
 namespace google_breakpad {
 
 namespace {
 // The list of signals which we consider to be crashes. The default action for
 // all these signals must be Core (see man 7 signal) because we rethrow the
 // signal after handling it and expect that it'll be fatal.
 const int kExceptionSignals[] = {
   SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, SIGTRAP
@@ -213,16 +207,17 @@ std::vector<ExceptionHandler*>* g_handle
 pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER;
 
 // sizeof(CrashContext) can be too big w.r.t the size of alternatate stack
 // for SignalHandler(). Keep the crash context as a .bss field. Exception
 // handlers are serialized by the |g_handler_stack_mutex_| and at most one at a
 // time can use |g_crash_context_|.
 ExceptionHandler::CrashContext g_crash_context_;
 
+FirstChanceHandler g_first_chance_handler_ = nullptr;
 }  // namespace
 
 // Runs before crashing: normal context.
 ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor,
                                    FilterCallback filter,
                                    MinidumpCallback callback,
                                    void* callback_context,
                                    bool install_handler,
@@ -326,31 +321,44 @@ void ExceptionHandler::RestoreHandlersLo
 // void ExceptionHandler::set_crash_handler(HandlerCallback callback) {
 //   crash_handler_ = callback;
 // }
 
 // This function runs in a compromised context: see the top of the file.
 // Runs on the crashing thread.
 // static
 void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
+
+  // Give the first chance handler a chance to recover from this signal
+  //
+  // This is primarily used by V8. V8 uses guard regions to guarantee memory
+  // safety in WebAssembly. This means some signals might be expected if they
+  // originate from Wasm code while accessing the guard region. We give V8 the
+  // chance to handle and recover from these signals first.
+  if (g_first_chance_handler_ != nullptr &&
+      g_first_chance_handler_(sig, info, uc)) {
+    return;
+  }
+
   // All the exception signals are blocked at this point.
   pthread_mutex_lock(&g_handler_stack_mutex_);
 
   // Sometimes, Breakpad runs inside a process where some other buggy code
   // saves and restores signal handlers temporarily with 'signal'
   // instead of 'sigaction'. This loses the SA_SIGINFO flag associated
   // with this function. As a consequence, the values of 'info' and 'uc'
   // become totally bogus, generally inducing a crash.
   //
   // The following code tries to detect this case. When it does, it
   // resets the signal handlers with sigaction + SA_SIGINFO and returns.
   // This forces the signal to be thrown again, but this time the kernel
   // will call the function with the right arguments.
   struct sigaction cur_handler;
   if (sigaction(sig, NULL, &cur_handler) == 0 &&
+      cur_handler.sa_sigaction == SignalHandler &&
       (cur_handler.sa_flags & SA_SIGINFO) == 0) {
     // Reset signal handler with the right flags.
     sigemptyset(&cur_handler.sa_mask);
     sigaddset(&cur_handler.sa_mask, sig);
 
     cur_handler.sa_sigaction = SignalHandler;
     cur_handler.sa_flags = SA_ONSTACK | SA_SIGINFO;
 
@@ -382,17 +390,17 @@ void ExceptionHandler::SignalHandler(int
   pthread_mutex_unlock(&g_handler_stack_mutex_);
 
   // info->si_code <= 0 iff SI_FROMUSER (SI_FROMKERNEL otherwise).
   if (info->si_code <= 0 || sig == SIGABRT) {
     // This signal was triggered by somebody sending us the signal with kill().
     // In order to retrigger it, we have to queue a new signal by calling
     // kill() ourselves.  The special case (si_pid == 0 && sig == SIGABRT) is
     // due to the kernel sending a SIGABRT from a user request via SysRQ.
-    if (_tgkill(getpid(), syscall(__NR_gettid), sig) < 0) {
+    if (sys_tgkill(getpid(), syscall(__NR_gettid), sig) < 0) {
       // If we failed to kill ourselves (e.g. because a sandbox disallows us
       // to do so), we instead resort to terminating our process. This will
       // result in an incorrect exit code.
       _exit(1);
     }
   } else {
     // This was a synchronous signal triggered by a hard fault (e.g. SIGSEGV).
     // No need to reissue the signal. It will automatically trigger again,
@@ -409,27 +417,32 @@ struct ThreadArgument {
 };
 
 // This is the entry function for the cloned process. We are in a compromised
 // context here: see the top of the file.
 // static
 int ExceptionHandler::ThreadEntry(void *arg) {
   const ThreadArgument *thread_arg = reinterpret_cast<ThreadArgument*>(arg);
 
+  // Close the write end of the pipe. This allows us to fail if the parent dies
+  // while waiting for the continue signal.
+  sys_close(thread_arg->handler->fdes[1]);
+
   // Block here until the crashing process unblocks us when
   // we're allowed to use ptrace
   thread_arg->handler->WaitForContinueSignal();
+  sys_close(thread_arg->handler->fdes[0]);
 
   return thread_arg->handler->DoDump(thread_arg->pid, thread_arg->context,
                                      thread_arg->context_size) == false;
 }
 
 // This function runs in a compromised context: see the top of the file.
 // Runs on the crashing thread.
-bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) {
+bool ExceptionHandler::HandleSignal(int /*sig*/, siginfo_t* info, void* uc) {
   if (filter_ && !filter_(callback_context_))
     return false;
 
   // Allow ourselves to be dumped if the signal is trusted.
   bool signal_trusted = info->si_code > 0;
   bool signal_pid_trusted = info->si_code == SI_USER ||
       info->si_code == SI_TKILL;
   if (signal_trusted || (signal_pid_trusted && info->si_pid == getpid())) {
@@ -518,18 +531,18 @@ bool ExceptionHandler::GenerateDump(Cras
     logger::write(strerror(errno), strlen(strerror(errno)));
     logger::write("\n", 1);
 
     // Ensure fdes[0] and fdes[1] are invalid file descriptors.
     fdes[0] = fdes[1] = -1;
   }
 
   const pid_t child = sys_clone(
-      ThreadEntry, stack, CLONE_FILES | CLONE_FS | CLONE_UNTRACED,
-      &thread_arg, NULL, NULL, NULL);
+      ThreadEntry, stack, CLONE_FS | CLONE_UNTRACED, &thread_arg, NULL, NULL,
+      NULL);
   if (child == -1) {
     sys_close(fdes[0]);
     sys_close(fdes[1]);
     return false;
   }
 
   if (child != 0) {
     static const char clonedMsg[] =
@@ -543,23 +556,24 @@ bool ExceptionHandler::GenerateDump(Cras
     logger::write(pidMsg, pidLen);
     logger::write("\n", 1);
   } else {
     static const char childMsg[] =
       "ExceptionHandler::GenerateDump I'm the child\n";
     logger::write(childMsg, my_strlen(childMsg));
   }
 
+  // Close the read end of the pipe.
+  sys_close(fdes[0]);
   // Allow the child to ptrace us
   sys_prctl(PR_SET_PTRACER, child, 0, 0, 0);
   SendContinueSignalToChild();
-  int status;
+  int status = 0;
   const int r = HANDLE_EINTR(sys_waitpid(child, &status, __WALL));
 
-  sys_close(fdes[0]);
   sys_close(fdes[1]);
 
   if (r == -1) {
     static const char msg[] = "ExceptionHandler::GenerateDump waitpid failed:";
     logger::write(msg, sizeof(msg) - 1);
     logger::write(strerror(errno), strlen(strerror(errno)));
     logger::write("\n", 1);
   }
@@ -605,40 +619,54 @@ void ExceptionHandler::WaitForContinueSi
     logger::write("\n", 1);
   }
 }
 
 // This function runs in a compromised context: see the top of the file.
 // Runs on the cloned process.
 bool ExceptionHandler::DoDump(pid_t crashing_process, const void* context,
                               size_t context_size) {
+  const bool may_skip_dump =
+      minidump_descriptor_.skip_dump_if_principal_mapping_not_referenced();
+  const uintptr_t principal_mapping_address =
+      minidump_descriptor_.address_within_principal_mapping();
+  const bool sanitize_stacks = minidump_descriptor_.sanitize_stacks();
   if (minidump_descriptor_.IsMicrodumpOnConsole()) {
     return google_breakpad::WriteMicrodump(
         crashing_process,
         context,
         context_size,
         mapping_list_,
+        may_skip_dump,
+        principal_mapping_address,
+        sanitize_stacks,
         *minidump_descriptor_.microdump_extra_info());
   }
   if (minidump_descriptor_.IsFD()) {
     return google_breakpad::WriteMinidump(minidump_descriptor_.fd(),
                                           minidump_descriptor_.size_limit(),
                                           crashing_process,
                                           context,
                                           context_size,
                                           mapping_list_,
-                                          app_memory_list_);
+                                          app_memory_list_,
+                                          may_skip_dump,
+                                          principal_mapping_address,
+                                          sanitize_stacks);
   }
   return google_breakpad::WriteMinidump(minidump_descriptor_.path(),
                                         minidump_descriptor_.size_limit(),
                                         crashing_process,
                                         context,
                                         context_size,
                                         mapping_list_,
-                                        app_memory_list_);
+                                        app_memory_list_,
+                                        may_skip_dump,
+                                        principal_mapping_address,
+                                        sanitize_stacks);
 }
 
 // static
 bool ExceptionHandler::WriteMinidump(const string& dump_path,
                                      MinidumpCallback callback,
                                      void* callback_context) {
   MinidumpDescriptor descriptor(dump_path);
   ExceptionHandler eh(descriptor, NULL, callback, callback_context, false, -1);
@@ -781,9 +809,13 @@ bool ExceptionHandler::WriteMinidumpForC
   if (!google_breakpad::WriteMinidump(descriptor.path(),
                                       child,
                                       child_blamed_thread))
       return false;
 
   return callback ? callback(descriptor, callback_context, true) : true;
 }
 
+void SetFirstChanceExceptionHandler(FirstChanceHandler callback) {
+  g_first_chance_handler_ = callback;
+}
+
 }  // namespace google_breakpad
--- a/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.h
+++ b/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.h
@@ -189,18 +189,18 @@ class ExceptionHandler {
   // This structure is passed to minidump_writer.h:WriteMinidump via an opaque
   // blob. It shouldn't be needed in any user code.
   struct CrashContext {
     siginfo_t siginfo;
     pid_t tid;  // the crashing thread.
     ucontext_t context;
 #if !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 struct
-    // ucontext so 'float_state' is not required.
+    // In case of MIPS Linux FP state is already part of ucontext_t so
+    // 'float_state' is not required.
     fpstate_t float_state;
 #endif
   };
 
   // Returns whether out-of-process dump generation is used or not.
   bool IsOutOfProcess() const {
     return crash_generation_client_.get() != NULL;
   }
@@ -257,22 +257,26 @@ class ExceptionHandler {
   // believes are never read.
   volatile HandlerCallback crash_handler_;
 
   // We need to explicitly enable ptrace of parent processes on some
   // kernels, but we need to know the PID of the cloned process before we
   // can do this. We create a pipe which we can use to block the
   // cloned process after creating it, until we have explicitly enabled
   // ptrace. This is used to store the file descriptors for the pipe
-  int fdes[2];
+  int fdes[2] = {-1, -1};
 
   // Callers can add extra info about mappings for cases where the
   // dumper code cannot extract enough information from /proc/<pid>/maps.
   MappingList mapping_list_;
 
   // Callers can request additional memory regions to be included in
   // the dump.
   AppMemoryList app_memory_list_;
 };
 
+
+typedef bool (*FirstChanceHandler)(int, void*, void*);
+void SetFirstChanceExceptionHandler(FirstChanceHandler callback);
+
 }  // namespace google_breakpad
 
 #endif  // CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_
--- a/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler_unittest.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler_unittest.cc
@@ -22,16 +22,17 @@
 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include <pthread.h>
 #include <stdint.h>
 #include <unistd.h>
 #include <signal.h>
 #include <sys/mman.h>
 #include <sys/poll.h>
 #include <sys/socket.h>
 #include <sys/uio.h>
 #include <sys/wait.h>
@@ -252,16 +253,76 @@ void ChildCrash(bool use_fd) {
 TEST(ExceptionHandlerTest, ChildCrashWithPath) {
   ASSERT_NO_FATAL_FAILURE(ChildCrash(false));
 }
 
 TEST(ExceptionHandlerTest, ChildCrashWithFD) {
   ASSERT_NO_FATAL_FAILURE(ChildCrash(true));
 }
 
+#if !defined(__ANDROID_API__) || __ANDROID_API__ >= __ANDROID_API_N__
+static void* SleepFunction(void* unused) {
+  while (true) usleep(1000000);
+  return NULL;
+}
+
+static void* CrashFunction(void* b_ptr) {
+  pthread_barrier_t* b = reinterpret_cast<pthread_barrier_t*>(b_ptr);
+  pthread_barrier_wait(b);
+  DoNullPointerDereference();
+  return NULL;
+}
+
+// Tests that concurrent crashes do not enter a loop by alternately triggering
+// the signal handler.
+TEST(ExceptionHandlerTest, ParallelChildCrashesDontHang) {
+  AutoTempDir temp_dir;
+  const pid_t child = fork();
+  if (child == 0) {
+    google_breakpad::scoped_ptr<ExceptionHandler> handler(
+      new ExceptionHandler(MinidumpDescriptor(temp_dir.path()), NULL, NULL,
+                            NULL, true, -1));
+
+    // We start a number of threads to make sure handling the signal takes
+    // enough time for the second thread to enter the signal handler.
+    int num_sleep_threads = 100;
+    google_breakpad::scoped_array<pthread_t> sleep_threads(
+        new pthread_t[num_sleep_threads]);
+    for (int i = 0; i < num_sleep_threads; ++i) {
+      ASSERT_EQ(0, pthread_create(&sleep_threads[i], NULL, SleepFunction,
+                                  NULL));
+    }
+
+    int num_crash_threads = 2;
+    google_breakpad::scoped_array<pthread_t> crash_threads(
+        new pthread_t[num_crash_threads]);
+    // Barrier to synchronize crashing both threads at the same time.
+    pthread_barrier_t b;
+    ASSERT_EQ(0, pthread_barrier_init(&b, NULL, num_crash_threads + 1));
+    for (int i = 0; i < num_crash_threads; ++i) {
+      ASSERT_EQ(0, pthread_create(&crash_threads[i], NULL, CrashFunction, &b));
+    }
+    pthread_barrier_wait(&b);
+    for (int i = 0; i < num_crash_threads; ++i) {
+      ASSERT_EQ(0, pthread_join(crash_threads[i], NULL));
+    }
+  }
+
+  // Wait a while until the child should have crashed.
+  usleep(1000000);
+  // Kill the child if it is still running.
+  kill(child, SIGKILL);
+
+  // If the child process terminated by itself, it will have returned SIGSEGV.
+  // If however it got stuck in a loop, it will have been killed by the
+  // SIGKILL.
+  ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
+}
+#endif  // !defined(__ANDROID_API__) || __ANDROID_API__ >= __ANDROID_API_N__
+
 static bool DoneCallbackReturnFalse(const MinidumpDescriptor& descriptor,
                                     void* context,
                                     bool succeeded) {
   return false;
 }
 
 static bool DoneCallbackReturnTrue(const MinidumpDescriptor& descriptor,
                                    void* context,
@@ -460,16 +521,39 @@ TEST(ExceptionHandlerTest, StackedHandle
                             NULL,
                             true,
                             -1);
     CrashWithCallbacks(NULL, DoneCallbackReturnFalse, temp_dir.path());
   }
   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
 }
 
+namespace {
+const int kSimpleFirstChanceReturnStatus = 42;
+bool SimpleFirstChanceHandler(int, void*, void*) {
+  _exit(kSimpleFirstChanceReturnStatus);
+}
+}
+
+TEST(ExceptionHandlerTest, FirstChanceHandlerRuns) {
+  AutoTempDir temp_dir;
+
+  const pid_t child = fork();
+  if (child == 0) {
+    ExceptionHandler handler(
+        MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
+    google_breakpad::SetFirstChanceExceptionHandler(SimpleFirstChanceHandler);
+    DoNullPointerDereference();
+  }
+  int status;
+  ASSERT_NE(HANDLE_EINTR(waitpid(child, &status, 0)), -1);
+  ASSERT_TRUE(WIFEXITED(status));
+  ASSERT_EQ(kSimpleFirstChanceReturnStatus, WEXITSTATUS(status));
+}
+
 #endif  // !ADDRESS_SANITIZER
 
 const unsigned char kIllegalInstruction[] = {
 #if defined(__mips__)
   // mfc2 zero,Impl - usually illegal in userspace.
   0x48, 0x00, 0x00, 0x48
 #else
   // This crashes with SIGILL on x86/x86-64/arm.
--- a/toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.cc
@@ -39,16 +39,21 @@ const MinidumpDescriptor::MicrodumpOnCon
     MinidumpDescriptor::kMicrodumpOnConsole = {};
 
 MinidumpDescriptor::MinidumpDescriptor(const MinidumpDescriptor& descriptor)
     : mode_(descriptor.mode_),
       fd_(descriptor.fd_),
       directory_(descriptor.directory_),
       c_path_(NULL),
       size_limit_(descriptor.size_limit_),
+      address_within_principal_mapping_(
+          descriptor.address_within_principal_mapping_),
+      skip_dump_if_principal_mapping_not_referenced_(
+          descriptor.skip_dump_if_principal_mapping_not_referenced_),
+      sanitize_stacks_(descriptor.sanitize_stacks_),
       microdump_extra_info_(descriptor.microdump_extra_info_) {
   // The copy constructor is not allowed to be called on a MinidumpDescriptor
   // with a valid path_, as getting its c_path_ would require the heap which
   // can cause problems in compromised environments.
   assert(descriptor.path_.empty());
 }
 
 MinidumpDescriptor& MinidumpDescriptor::operator=(
@@ -60,16 +65,21 @@ MinidumpDescriptor& MinidumpDescriptor::
   directory_ = descriptor.directory_;
   path_.clear();
   if (c_path_) {
     // This descriptor already had a path set, so generate a new one.
     c_path_ = NULL;
     UpdatePath();
   }
   size_limit_ = descriptor.size_limit_;
+  address_within_principal_mapping_ =
+      descriptor.address_within_principal_mapping_;
+  skip_dump_if_principal_mapping_not_referenced_ =
+      descriptor.skip_dump_if_principal_mapping_not_referenced_;
+  sanitize_stacks_ = descriptor.sanitize_stacks_;
   microdump_extra_info_ = descriptor.microdump_extra_info_;
   return *this;
 }
 
 void MinidumpDescriptor::UpdatePath() {
   assert(mode_ == kWriteMinidumpToFile && !directory_.empty());
 
   GUID guid;
--- a/toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.h
+++ b/toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.h
@@ -48,39 +48,50 @@ namespace google_breakpad {
 class MinidumpDescriptor {
  public:
   struct MicrodumpOnConsole {};
   static const MicrodumpOnConsole kMicrodumpOnConsole;
 
   MinidumpDescriptor()
       : mode_(kUninitialized),
         fd_(-1),
-        size_limit_(-1) {}
+        size_limit_(-1),
+        address_within_principal_mapping_(0),
+        skip_dump_if_principal_mapping_not_referenced_(false) {}
 
   explicit MinidumpDescriptor(const string& directory)
       : mode_(kWriteMinidumpToFile),
         fd_(-1),
         directory_(directory),
         c_path_(NULL),
-        size_limit_(-1) {
+        size_limit_(-1),
+        address_within_principal_mapping_(0),
+        skip_dump_if_principal_mapping_not_referenced_(false),
+        sanitize_stacks_(false) {
     assert(!directory.empty());
   }
 
   explicit MinidumpDescriptor(int fd)
       : mode_(kWriteMinidumpToFd),
         fd_(fd),
         c_path_(NULL),
-        size_limit_(-1) {
+        size_limit_(-1),
+        address_within_principal_mapping_(0),
+        skip_dump_if_principal_mapping_not_referenced_(false),
+        sanitize_stacks_(false) {
     assert(fd != -1);
   }
 
   explicit MinidumpDescriptor(const MicrodumpOnConsole&)
       : mode_(kWriteMicrodumpToConsole),
         fd_(-1),
-        size_limit_(-1) {}
+        size_limit_(-1),
+        address_within_principal_mapping_(0),
+        skip_dump_if_principal_mapping_not_referenced_(false),
+        sanitize_stacks_(false) {}
 
   explicit MinidumpDescriptor(const MinidumpDescriptor& descriptor);
   MinidumpDescriptor& operator=(const MinidumpDescriptor& descriptor);
 
   static MinidumpDescriptor getMicrodumpDescriptor();
 
   bool IsFD() const { return mode_ == kWriteMinidumpToFd; }
 
@@ -96,16 +107,38 @@ class MinidumpDescriptor {
 
   // Updates the path so it is unique.
   // Should be called from a normal context: this methods uses the heap.
   void UpdatePath();
 
   off_t size_limit() const { return size_limit_; }
   void set_size_limit(off_t limit) { size_limit_ = limit; }
 
+  uintptr_t address_within_principal_mapping() const {
+    return address_within_principal_mapping_;
+  }
+  void set_address_within_principal_mapping(
+      uintptr_t address_within_principal_mapping) {
+    address_within_principal_mapping_ = address_within_principal_mapping;
+  }
+
+  bool skip_dump_if_principal_mapping_not_referenced() {
+    return skip_dump_if_principal_mapping_not_referenced_;
+  }
+  void set_skip_dump_if_principal_mapping_not_referenced(
+      bool skip_dump_if_principal_mapping_not_referenced) {
+    skip_dump_if_principal_mapping_not_referenced_ =
+        skip_dump_if_principal_mapping_not_referenced;
+  }
+
+  bool sanitize_stacks() const { return sanitize_stacks_; }
+  void set_sanitize_stacks(bool sanitize_stacks) {
+    sanitize_stacks_ = sanitize_stacks;
+  }
+
   MicrodumpExtraInfo* microdump_extra_info() {
     assert(IsMicrodumpOnConsole());
     return &microdump_extra_info_;
   };
 
  private:
   enum DumpMode {
     kUninitialized = 0,
@@ -127,16 +160,33 @@ class MinidumpDescriptor {
   string path_;
 
   // The C string of |path_|. Precomputed so it can be access from a compromised
   // context.
   const char* c_path_;
 
   off_t size_limit_;
 
+  // This member points somewhere into the main module for this
+  // process (the module that is considerered interesting for the
+  // purposes of debugging crashes).
+  uintptr_t address_within_principal_mapping_;
+
+  // If set, threads that do not reference the address range
+  // associated with |address_within_principal_mapping_| will not have their
+  // stacks logged.
+  bool skip_dump_if_principal_mapping_not_referenced_;
+
+  // If set, stacks are sanitized to remove PII. This involves
+  // overwriting any pointer-aligned words that are not either
+  // pointers into a process mapping or small integers (+/-4096). This
+  // leaves enough information to unwind stacks, and preserve some
+  // register values, but elides strings and other program data.
+  bool sanitize_stacks_;
+
   // The extra microdump data (e.g. product name/version, build
   // fingerprint, gpu fingerprint) that should be appended to the dump
   // (microdump only). Microdumps don't have the ability of appending
   // extra metadata after the dump is generated (as opposite to
   // minidumps MIME fields), therefore the extra data must be provided
   // upfront. Any memory pointed to by members of the
   // MicrodumpExtraInfo struct must be valid for the lifetime of the
   // process (read: the caller has to guarantee that it is stored in
--- a/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.cc
@@ -127,26 +127,37 @@ size_t NextOrderedMapping(
 }
 
 #endif  // !__LP64__
 
 class MicrodumpWriter {
  public:
   MicrodumpWriter(const ExceptionHandler::CrashContext* context,
                   const MappingList& mappings,
+                  bool skip_dump_if_principal_mapping_not_referenced,
+                  uintptr_t address_within_principal_mapping,
+                  bool sanitize_stack,
                   const MicrodumpExtraInfo& microdump_extra_info,
                   LinuxDumper* dumper)
       : ucontext_(context ? &context->context : NULL),
 #if !defined(__ARM_EABI__) && !defined(__mips__)
         float_state_(context ? &context->float_state : NULL),
 #endif
         dumper_(dumper),
         mapping_list_(mappings),
+        skip_dump_if_principal_mapping_not_referenced_(
+            skip_dump_if_principal_mapping_not_referenced),
+        address_within_principal_mapping_(address_within_principal_mapping),
+        sanitize_stack_(sanitize_stack),
         microdump_extra_info_(microdump_extra_info),
-        log_line_(NULL) {
+        log_line_(NULL),
+        stack_copy_(NULL),
+        stack_len_(0),
+        stack_lower_bound_(0),
+        stack_pointer_(0) {
     log_line_ = reinterpret_cast<char*>(Alloc(kLineBufferSize));
     if (log_line_)
       log_line_[0] = '\0';  // Clear out the log line buffer.
   }
 
   ~MicrodumpWriter() { dumper_->ThreadsResume(); }
 
   bool Init() {
@@ -154,35 +165,42 @@ class MicrodumpWriter {
     // wasn't even room to allocate the line buffer, bail out. There is nothing
     // useful we can possibly achieve without the ability to Log. At least let's
     // try to not crash.
     if (!dumper_->Init() || !log_line_)
       return false;
     return dumper_->ThreadsSuspend() && dumper_->LateInit();
   }
 
-  bool Dump() {
-    bool success;
+  void Dump() {
+    CaptureResult stack_capture_result = CaptureCrashingThreadStack(-1);
+    if (stack_capture_result == CAPTURE_UNINTERESTING) {
+      LogLine("Microdump skipped (uninteresting)");
+      return;
+    }
+
     LogLine("-----BEGIN BREAKPAD MICRODUMP-----");
     DumpProductInformation();
     DumpOSInformation();
     DumpProcessType();
+    DumpCrashReason();
     DumpGPUInformation();
 #if !defined(__LP64__)
     DumpFreeSpace();
 #endif
-    success = DumpCrashingThread();
-    if (success)
-      success = DumpMappings();
+    if (stack_capture_result == CAPTURE_OK)
+      DumpThreadStack();
+    DumpCPUState();
+    DumpMappings();
     LogLine("-----END BREAKPAD MICRODUMP-----");
-    dumper_->ThreadsResume();
-    return success;
   }
 
  private:
+  enum CaptureResult { CAPTURE_OK, CAPTURE_FAILED, CAPTURE_UNINTERESTING };
+
   // Writes one line to the system log.
   void LogLine(const char* msg) {
 #if defined(__ANDROID__)
     logger::writeToCrashLog(msg);
 #else
     logger::write(msg, my_strlen(msg));
     logger::write("\n", 1);
 #endif
@@ -216,17 +234,54 @@ class MicrodumpWriter {
     const uint8_t* ptr = reinterpret_cast<const uint8_t*>(buf);
     for (size_t i = 0; i < length; ++i, ++ptr)
       LogAppend(*ptr);
   }
 
   // Writes out the current line buffer on the system log.
   void LogCommitLine() {
     LogLine(log_line_);
-    my_strlcpy(log_line_, "", kLineBufferSize);
+    log_line_[0] = 0;
+  }
+
+  CaptureResult CaptureCrashingThreadStack(int max_stack_len) {
+    stack_pointer_ = UContextReader::GetStackPointer(ucontext_);
+
+    if (!dumper_->GetStackInfo(reinterpret_cast<const void**>(&stack_lower_bound_),
+                               &stack_len_, stack_pointer_)) {
+      return CAPTURE_FAILED;
+    }
+
+    if (max_stack_len >= 0 &&
+        stack_len_ > static_cast<size_t>(max_stack_len)) {
+      stack_len_ = max_stack_len;
+    }
+
+    stack_copy_ = reinterpret_cast<uint8_t*>(Alloc(stack_len_));
+    dumper_->CopyFromProcess(stack_copy_, dumper_->crash_thread(),
+                             reinterpret_cast<const void*>(stack_lower_bound_),
+                             stack_len_);
+
+    if (!skip_dump_if_principal_mapping_not_referenced_) return CAPTURE_OK;
+
+    const MappingInfo* principal_mapping =
+        dumper_->FindMappingNoBias(address_within_principal_mapping_);
+    if (!principal_mapping) return CAPTURE_UNINTERESTING;
+
+    uintptr_t low_addr = principal_mapping->system_mapping_info.start_addr;
+    uintptr_t high_addr = principal_mapping->system_mapping_info.end_addr;
+    uintptr_t pc = UContextReader::GetInstructionPointer(ucontext_);
+    if (low_addr <= pc && pc <= high_addr) return CAPTURE_OK;
+
+    if (dumper_->StackHasPointerToMapping(stack_copy_, stack_len_,
+                                          stack_pointer_ - stack_lower_bound_,
+                                          *principal_mapping)) {
+      return CAPTURE_OK;
+    }
+    return CAPTURE_UNINTERESTING;
   }
 
   void DumpProductInformation() {
     LogAppend("V ");
     if (microdump_extra_info_.product_info) {
       LogAppend(microdump_extra_info_.product_info);
     } else {
       LogAppend("UNKNOWN:0.0.0.0");
@@ -239,16 +294,26 @@ class MicrodumpWriter {
     if (microdump_extra_info_.process_type) {
       LogAppend(microdump_extra_info_.process_type);
     } else {
       LogAppend("UNKNOWN");
     }
     LogCommitLine();
   }
 
+  void DumpCrashReason() {
+    LogAppend("R ");
+    LogAppend(dumper_->crash_signal());
+    LogAppend(" ");
+    LogAppend(dumper_->GetCrashSignalString());
+    LogAppend(" ");
+    LogAppend(dumper_->crash_address());
+    LogCommitLine();
+  }
+
   void DumpOSInformation() {
     const uint8_t n_cpus = static_cast<uint8_t>(sysconf(_SC_NPROCESSORS_CONF));
 
 #if defined(__ANDROID__)
     const char kOSId[] = "A";
 #else
     const char kOSId[] = "L";
 #endif
@@ -310,97 +375,52 @@ class MicrodumpWriter {
     if (microdump_extra_info_.gpu_fingerprint) {
       LogAppend(microdump_extra_info_.gpu_fingerprint);
     } else {
       LogAppend("UNKNOWN");
     }
     LogCommitLine();
   }
 
-  bool DumpThreadStack(uint32_t thread_id,
-                       uintptr_t stack_pointer,
-                       int max_stack_len,
-                       uint8_t** stack_copy) {
-    *stack_copy = NULL;
-    const void* stack;
-    size_t stack_len;
-
-    if (!dumper_->GetStackInfo(&stack, &stack_len, stack_pointer)) {
-      // The stack pointer might not be available. In this case we don't hard
-      // fail, just produce a (almost useless) microdump w/o a stack section.
-      return true;
+  void DumpThreadStack() {
+    if (sanitize_stack_) {
+      dumper_->SanitizeStackCopy(stack_copy_, stack_len_, stack_pointer_,
+                                 stack_pointer_ - stack_lower_bound_);
     }
 
     LogAppend("S 0 ");
-    LogAppend(stack_pointer);
+    LogAppend(stack_pointer_);
     LogAppend(" ");
-    LogAppend(reinterpret_cast<uintptr_t>(stack));
+    LogAppend(stack_lower_bound_);
     LogAppend(" ");
-    LogAppend(stack_len);
+    LogAppend(stack_len_);
     LogCommitLine();
 
-    if (max_stack_len >= 0 &&
-        stack_len > static_cast<unsigned int>(max_stack_len)) {
-      stack_len = max_stack_len;
-    }
-
-    *stack_copy = reinterpret_cast<uint8_t*>(Alloc(stack_len));
-    dumper_->CopyFromProcess(*stack_copy, thread_id, stack, stack_len);
-
-    // Dump the content of the stack, splicing it into chunks which size is
-    // compatible with the max logcat line size (see LOGGER_ENTRY_MAX_PAYLOAD).
     const size_t STACK_DUMP_CHUNK_SIZE = 384;
-    for (size_t stack_off = 0; stack_off < stack_len;
+    for (size_t stack_off = 0; stack_off < stack_len_;
          stack_off += STACK_DUMP_CHUNK_SIZE) {
       LogAppend("S ");
-      LogAppend(reinterpret_cast<uintptr_t>(stack) + stack_off);
+      LogAppend(stack_lower_bound_ + stack_off);
       LogAppend(" ");
-      LogAppend(*stack_copy + stack_off,
-                std::min(STACK_DUMP_CHUNK_SIZE, stack_len - stack_off));
+      LogAppend(stack_copy_ + stack_off,
+                std::min(STACK_DUMP_CHUNK_SIZE, stack_len_ - stack_off));
       LogCommitLine();
     }
-    return true;
   }
 
-  // Write information about the crashing thread.
-  bool DumpCrashingThread() {
-    const unsigned num_threads = dumper_->threads().size();
-
-    for (unsigned i = 0; i < num_threads; ++i) {
-      MDRawThread thread;
-      my_memset(&thread, 0, sizeof(thread));
-      thread.thread_id = dumper_->threads()[i];
-
-      // Dump only the crashing thread.
-      if (static_cast<pid_t>(thread.thread_id) != dumper_->crash_thread())
-        continue;
-
-      assert(ucontext_);
-      assert(!dumper_->IsPostMortem());
-
-      uint8_t* stack_copy;
-      const uintptr_t stack_ptr = UContextReader::GetStackPointer(ucontext_);
-      if (!DumpThreadStack(thread.thread_id, stack_ptr, -1, &stack_copy))
-        return false;
-
-      RawContextCPU cpu;
-      my_memset(&cpu, 0, sizeof(RawContextCPU));
+  void DumpCPUState() {
+    RawContextCPU cpu;
+    my_memset(&cpu, 0, sizeof(RawContextCPU));
 #if !defined(__ARM_EABI__) && !defined(__mips__)
-      UContextReader::FillCPUContext(&cpu, ucontext_, float_state_);
+    UContextReader::FillCPUContext(&cpu, ucontext_, float_state_);
 #else
-      UContextReader::FillCPUContext(&cpu, ucontext_);
+    UContextReader::FillCPUContext(&cpu, ucontext_);
 #endif
-      DumpCPUState(&cpu);
-    }
-    return true;
-  }
-
-  void DumpCPUState(RawContextCPU* cpu) {
     LogAppend("C ");
-    LogAppend(cpu, sizeof(*cpu));
+    LogAppend(&cpu, sizeof(cpu));
     LogCommitLine();
   }
 
   // If there is caller-provided information about this mapping
   // in the mapping_list_ list, return true. Otherwise, return false.
   bool HaveMappingInfo(const MappingInfo& mapping) {
     for (MappingList::const_iterator iter = mapping_list_.begin();
          iter != mapping_list_.end();
@@ -469,16 +489,22 @@ class MicrodumpWriter {
     LogAppend(module_identifier.data4[7]);
     LogAppend("0 ");  // Age is always 0 on Linux.
     LogAppend(file_name);
     LogCommitLine();
   }
 
 #if !defined(__LP64__)
   void DumpFreeSpace() {
+    const MappingInfo* stack_mapping = nullptr;
+    ThreadInfo info;
+    if (dumper_->GetThreadInfoByIndex(dumper_->GetMainThreadIndex(), &info)) {
+      stack_mapping = dumper_->FindMappingNoBias(info.stack_pointer);
+    }
+
     const google_breakpad::wasteful_vector<MappingInfo*>& mappings =
         dumper_->mappings();
     if (mappings.size() == 0) return;
 
     // This is complicated by the fact that mappings is not in order. It should
     // be mostly in order, however the mapping that contains the entry point for
     // the process is always at the front of the vector.
 
@@ -501,16 +527,24 @@ class MicrodumpWriter {
     while (true) {
       // Skip to the end of an adjacent run of mappings. This is an optimization
       // for the fact that mappings is mostly sorted.
       while (curr != mappings.size() - 1 &&
              MappingsAreAdjacent(*mappings[curr], *mappings[curr + 1])) {
         ++curr;
       }
 
+      if (mappings[curr] == stack_mapping) {
+        // Because we can't determine the top of userspace mappable
+        // memory we treat the start of the process stack as the top
+        // of the allocatable address space. Once we reach
+        // |stack_mapping| we are done scanning for free space regions.
+        break;
+      }
+
       size_t next = NextOrderedMapping(mappings, curr);
       if (next == std::numeric_limits<size_t>::max())
         break;
 
       uintptr_t hole_lo = mappings[curr]->start_addr + mappings[curr]->size;
       uintptr_t hole_hi = mappings[next]->start_addr;
 
       if (hole_hi > hole_lo) {
@@ -542,17 +576,17 @@ class MicrodumpWriter {
       LogAppend(":");
       LogAppend(saturated_cast<uint8_t>(hole_histogram[i]));
     }
     LogCommitLine();
   }
 #endif
 
   // Write information about the mappings in effect.
-  bool DumpMappings() {
+  void DumpMappings() {
     // First write all the mappings from the dumper
     for (unsigned i = 0; i < dumper_->mappings().size(); ++i) {
       const MappingInfo& mapping = *dumper_->mappings()[i];
       if (mapping.name[0] == 0 ||  // only want modules with filenames.
           !mapping.exec ||  // only want executable mappings.
           mapping.size < 4096 || // too small to get a signature for.
           HaveMappingInfo(mapping)) {
         continue;
@@ -561,49 +595,70 @@ class MicrodumpWriter {
       DumpModule(mapping, true, i, NULL);
     }
     // Next write all the mappings provided by the caller
     for (MappingList::const_iterator iter = mapping_list_.begin();
          iter != mapping_list_.end();
          ++iter) {
       DumpModule(iter->first, false, 0, iter->second);
     }
-    return true;
   }
 
   void* Alloc(unsigned bytes) { return dumper_->allocator()->Alloc(bytes); }
 
   const ucontext_t* const ucontext_;
 #if !defined(__ARM_EABI__) && !defined(__mips__)
   const google_breakpad::fpstate_t* const float_state_;
 #endif
   LinuxDumper* dumper_;
   const MappingList& mapping_list_;
+  bool skip_dump_if_principal_mapping_not_referenced_;
+  uintptr_t address_within_principal_mapping_;
+  bool sanitize_stack_;
   const MicrodumpExtraInfo microdump_extra_info_;
   char* log_line_;
+
+  // The local copy of crashed process stack memory, beginning at
+  // |stack_lower_bound_|.
+  uint8_t* stack_copy_;
+
+  // The length of crashed process stack copy.
+  size_t stack_len_;
+
+  // The address of the page containing the stack pointer in the
+  // crashed process. |stack_lower_bound_| <= |stack_pointer_|
+  uintptr_t stack_lower_bound_;
+
+  // The stack pointer of the crashed thread.
+  uintptr_t stack_pointer_;
 };
 }  // namespace
 
 namespace google_breakpad {
 
 bool WriteMicrodump(pid_t crashing_process,
                     const void* blob,
                     size_t blob_size,
                     const MappingList& mappings,
+                    bool skip_dump_if_principal_mapping_not_referenced,
+                    uintptr_t address_within_principal_mapping,
+                    bool sanitize_stack,
                     const MicrodumpExtraInfo& microdump_extra_info) {
   LinuxPtraceDumper dumper(crashing_process);
   const ExceptionHandler::CrashContext* context = NULL;
   if (blob) {
     if (blob_size != sizeof(ExceptionHandler::CrashContext))
       return false;
     context = reinterpret_cast<const ExceptionHandler::CrashContext*>(blob);
-    dumper.set_crash_address(
-        reinterpret_cast<uintptr_t>(context->siginfo.si_addr));
-    dumper.set_crash_signal(context->siginfo.si_signo);
+    dumper.SetCrashInfoFromSigInfo(context->siginfo);
     dumper.set_crash_thread(context->tid);
   }
-  MicrodumpWriter writer(context, mappings, microdump_extra_info, &dumper);
+  MicrodumpWriter writer(context, mappings,
+                         skip_dump_if_principal_mapping_not_referenced,
+                         address_within_principal_mapping, sanitize_stack,
+                         microdump_extra_info, &dumper);
   if (!writer.Init())
     return false;
-  return writer.Dump();
+  writer.Dump();
+  return true;
 }
 
 }  // namespace google_breakpad
--- a/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.h
+++ b/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.h
@@ -53,13 +53,16 @@ struct MicrodumpExtraInfo;
 //   product_info: a (optional) C string which determines the product name and
 //     version (e.g., WebView:42.0.2311.136).
 //
 // Returns true iff successful.
 bool WriteMicrodump(pid_t crashing_process,
                     const void* blob,
                     size_t blob_size,
                     const MappingList& mappings,
+                    bool skip_dump_if_main_module_not_referenced,
+                    uintptr_t address_within_main_module,
+                    bool sanitize_stack,
                     const MicrodumpExtraInfo& microdump_extra_info);
 
 }  // namespace google_breakpad
 
 #endif  // CLIENT_LINUX_MINIDUMP_WRITER_MICRODUMP_WRITER_H_
--- a/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer_unittest.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer_unittest.cc
@@ -26,108 +26,163 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <ctype.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <ucontext.h>
 
 #include <sstream>
 #include <string>
 
 #include "breakpad_googletest_includes.h"
 #include "linux/handler/exception_handler.h"
 #include "linux/handler/microdump_extra_info.h"
 #include "linux/microdump_writer/microdump_writer.h"
 #include "common/linux/eintr_wrapper.h"
 #include "common/linux/ignore_ret.h"
 #include "common/scoped_ptr.h"
 #include "common/tests/auto_tempdir.h"
 #include "common/using_std_string.h"
 
 using namespace google_breakpad;
 
+extern "C" {
+extern char __executable_start;
+extern char __etext;
+}
+
 namespace {
 
 typedef testing::Test MicrodumpWriterTest;
 
 MicrodumpExtraInfo MakeMicrodumpExtraInfo(
     const char* build_fingerprint,
     const char* product_info,
     const char* gpu_fingerprint) {
   MicrodumpExtraInfo info;
   info.build_fingerprint = build_fingerprint;
   info.product_info = product_info;
   info.gpu_fingerprint = gpu_fingerprint;
+  info.process_type = "Browser";
   return info;
 }
 
-void CrashAndGetMicrodump(
-    const MappingList& mappings,
-    const MicrodumpExtraInfo& microdump_extra_info,
-    scoped_array<char>* buf) {
+bool ContainsMicrodump(const std::string& buf) {
+  return std::string::npos != buf.find("-----BEGIN BREAKPAD MICRODUMP-----") &&
+         std::string::npos != buf.find("-----END BREAKPAD MICRODUMP-----");
+}
+
+const char kIdentifiableString[] = "_IDENTIFIABLE_";
+const uintptr_t kCrashAddress = 0xdeaddeadu;
+
+void CrashAndGetMicrodump(const MappingList& mappings,
+                          const MicrodumpExtraInfo& microdump_extra_info,
+                          std::string* microdump,
+                          bool skip_dump_if_principal_mapping_not_referenced = false,
+                          uintptr_t address_within_principal_mapping = 0,
+                          bool sanitize_stack = false) {
   int fds[2];
   ASSERT_NE(-1, pipe(fds));
 
   AutoTempDir temp_dir;
   string stderr_file = temp_dir.path() + "/stderr.log";
   int err_fd = open(stderr_file.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
   ASSERT_NE(-1, err_fd);
 
+  char identifiable_string[sizeof(kIdentifiableString)];
+
+  // This string should not appear in the resulting microdump if it
+  // has been sanitized.
+  strcpy(identifiable_string, kIdentifiableString);
+  // Force the strcpy to not be optimized away.
+  IGNORE_RET(write(STDOUT_FILENO, identifiable_string, 0));
+
   const pid_t child = fork();
   if (child == 0) {
     close(fds[1]);
     char b;
     IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
     close(fds[0]);
     syscall(__NR_exit);
   }
   close(fds[0]);
 
   ExceptionHandler::CrashContext context;
   memset(&context, 0, sizeof(context));
-
+  // Pretend the current context is the child context (which is
+  // approximately right) so that we have a valid stack pointer, and
+  // can fetch child stack data via ptrace.
+  getcontext(&context.context);
   // Set a non-zero tid to avoid tripping asserts.
   context.tid = child;
+  context.siginfo.si_signo = MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED;
+  context.siginfo.si_addr = reinterpret_cast<void*>(kCrashAddress);
 
   // Redirect temporarily stderr to the stderr.log file.
   int save_err = dup(STDERR_FILENO);
   ASSERT_NE(-1, save_err);
   ASSERT_NE(-1, dup2(err_fd, STDERR_FILENO));
 
   ASSERT_TRUE(WriteMicrodump(child, &context, sizeof(context), mappings,
+                             skip_dump_if_principal_mapping_not_referenced,
+                             address_within_principal_mapping, sanitize_stack,
                              microdump_extra_info));
 
   // Revert stderr back to the console.
   dup2(save_err, STDERR_FILENO);
   close(save_err);
 
   // Read back the stderr file and check for the microdump marker.
   fsync(err_fd);
   lseek(err_fd, 0, SEEK_SET);
-  const size_t kBufSize = 64 * 1024;
-  buf->reset(new char[kBufSize]);
-  ASSERT_GT(read(err_fd, buf->get(), kBufSize), 0);
+
+  microdump->clear();
+  char buf[1024];
 
+  while (true) {
+    int bytes_read = IGNORE_EINTR(read(err_fd, buf, 1024));
+    if (bytes_read <= 0) break;
+    microdump->append(buf, buf + bytes_read);
+  }
   close(err_fd);
   close(fds[1]);
+}
 
-  ASSERT_NE(static_cast<char*>(0), strstr(
-      buf->get(), "-----BEGIN BREAKPAD MICRODUMP-----"));
-  ASSERT_NE(static_cast<char*>(0), strstr(
-      buf->get(), "-----END BREAKPAD MICRODUMP-----"));
+void ExtractMicrodumpStackContents(const string& microdump_content,
+                                   string* result) {
+  std::istringstream iss(microdump_content);
+  result->clear();
+  for (string line; std::getline(iss, line);) {
+    if (line.find("S ") == 0) {
+      std::istringstream stack_data(line);
+      std::string key;
+      std::string addr;
+      std::string data;
+      stack_data >> key >> addr >> data;
+      EXPECT_TRUE((data.size() & 1u) == 0u);
+      result->reserve(result->size() + data.size() / 2);
+      for (size_t i = 0; i < data.size(); i += 2) {
+        std::string byte = data.substr(i, 2);
+        result->push_back(static_cast<char>(strtoul(byte.c_str(), NULL, 16)));
+      }
+    }
+  }
 }
 
 void CheckMicrodumpContents(const string& microdump_content,
                             const MicrodumpExtraInfo& expected_info) {
   std::istringstream iss(microdump_content);
   bool did_find_os_info = false;
   bool did_find_product_info = false;
+  bool did_find_process_type = false;
+  bool did_find_crash_reason = false;
   bool did_find_gpu_info = false;
   for (string line; std::getline(iss, line);) {
     if (line.find("O ") == 0) {
       std::istringstream os_info_tokens(line);
       string token;
       os_info_tokens.ignore(2); // Ignore the "O " preamble.
       // Check the OS descriptor char (L=Linux, A=Android).
       os_info_tokens >> token;
@@ -136,34 +191,62 @@ void CheckMicrodumpContents(const string
       os_info_tokens >> token; // HW architecture.
       os_info_tokens >> token; // Number of cpus.
       for (size_t i = 0; i < token.size(); ++i)
         ASSERT_TRUE(isxdigit(token[i]));
       os_info_tokens >> token; // SW architecture.
 
       // Check that the build fingerprint is in the right place.
       os_info_tokens >> token;
+      ASSERT_FALSE(os_info_tokens.fail());
       if (expected_info.build_fingerprint)
         ASSERT_EQ(expected_info.build_fingerprint, token);
       did_find_os_info = true;
+    } else if (line.find("P ") == 0) {
+      if (expected_info.process_type)
+        ASSERT_EQ(string("P ") + expected_info.process_type, line);
+      did_find_process_type = true;
+    } else if (line.find("R ") == 0) {
+      std::istringstream crash_reason_tokens(line);
+      string token;
+      unsigned crash_reason;
+      string crash_reason_str;
+      intptr_t crash_address;
+      crash_reason_tokens.ignore(2); // Ignore the "R " preamble.
+      crash_reason_tokens >> std::hex >> crash_reason >> crash_reason_str >>
+          crash_address;
+      ASSERT_FALSE(crash_reason_tokens.fail());
+      ASSERT_EQ(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED, crash_reason);
+      ASSERT_EQ("DUMP_REQUESTED", crash_reason_str);
+      ASSERT_EQ(0xDEADDEADu, kCrashAddress);
+      did_find_crash_reason = true;
     } else if (line.find("V ") == 0) {
       if (expected_info.product_info)
         ASSERT_EQ(string("V ") + expected_info.product_info, line);
       did_find_product_info = true;
     } else if (line.find("G ") == 0) {
       if (expected_info.gpu_fingerprint)
         ASSERT_EQ(string("G ") + expected_info.gpu_fingerprint, line);
       did_find_gpu_info = true;
     }
   }
   ASSERT_TRUE(did_find_os_info);
   ASSERT_TRUE(did_find_product_info);
+  ASSERT_TRUE(did_find_process_type);
+  ASSERT_TRUE(did_find_crash_reason);
   ASSERT_TRUE(did_find_gpu_info);
 }
 
+bool MicrodumpStackContains(const string& microdump_content,
+                            const string& expected_content) {
+  string result;
+  ExtractMicrodumpStackContents(microdump_content, &result);
+  return result.find(kIdentifiableString) != string::npos;
+}
+
 void CheckMicrodumpContents(const string& microdump_content,
                             const string& expected_fingerprint,
                             const string& expected_product_info,
                             const string& expected_gpu_fingerprint) {
   CheckMicrodumpContents(
       microdump_content,
       MakeMicrodumpExtraInfo(expected_fingerprint.c_str(),
                              expected_product_info.c_str(),
@@ -186,72 +269,152 @@ TEST(MicrodumpWriterTest, BasicWithMappi
   strcpy(info.name, kMemoryName);
 
   MappingList mappings;
   MappingEntry mapping;
   mapping.first = info;
   memcpy(mapping.second, kModuleGUID, sizeof(MDGUID));
   mappings.push_back(mapping);
 
-  scoped_array<char> buf;
+  std::string buf;
   CrashAndGetMicrodump(mappings, MicrodumpExtraInfo(), &buf);
+  ASSERT_TRUE(ContainsMicrodump(buf));
 
 #ifdef __LP64__
-  ASSERT_NE(static_cast<char*>(0), strstr(
-      buf.get(), "M 0000000000001000 000000000000002A 0000000000001000 "
-      "33221100554477668899AABBCCDDEEFF0 libfoo.so"));
+  ASSERT_NE(std::string::npos,
+            buf.find("M 0000000000001000 000000000000002A 0000000000001000 "
+                     "33221100554477668899AABBCCDDEEFF0 libfoo.so"));
 #else
-  ASSERT_NE(static_cast<char*>(0), strstr(
-      buf.get(), "M 00001000 0000002A 00001000 "
-      "33221100554477668899AABBCCDDEEFF0 libfoo.so"));
+  ASSERT_NE(std::string::npos,
+            buf.find("M 00001000 0000002A 00001000 "
+                     "33221100554477668899AABBCCDDEEFF0 libfoo.so"));
 #endif
 
   // In absence of a product info in the minidump, the writer should just write
   // an unknown marker.
-  ASSERT_NE(static_cast<char*>(0), strstr(
-      buf.get(), "V UNKNOWN:0.0.0.0"));
+  ASSERT_NE(std::string::npos, buf.find("V UNKNOWN:0.0.0.0"));
+}
+
+// Ensure that no output occurs if the interest region is set, but
+// doesn't overlap anything on the stack.
+TEST(MicrodumpWriterTest, NoOutputIfUninteresting) {
+  const char kProductInfo[] = "MockProduct:42.0.2311.99";
+  const char kBuildFingerprint[] =
+      "aosp/occam/mako:5.1.1/LMY47W/12345678:userdegbug/dev-keys";
+  const char kGPUFingerprint[] =
+      "Qualcomm;Adreno (TM) 330;OpenGL ES 3.0 V@104.0 AU@  (GIT@Id3510ff6dc)";
+  const MicrodumpExtraInfo kMicrodumpExtraInfo(
+      MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint));
+
+  std::string buf;
+  MappingList no_mappings;
+
+  CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf, true, 0);
+  ASSERT_FALSE(ContainsMicrodump(buf));
+}
+
+// Ensure that stack content does not contain an identifiable string if the
+// stack is sanitized.
+TEST(MicrodumpWriterTest, StringRemovedBySanitization) {
+  const char kProductInfo[] = "MockProduct:42.0.2311.99";
+  const char kBuildFingerprint[] =
+      "aosp/occam/mako:5.1.1/LMY47W/12345678:userdegbug/dev-keys";
+  const char kGPUFingerprint[] =
+      "Qualcomm;Adreno (TM) 330;OpenGL ES 3.0 V@104.0 AU@  (GIT@Id3510ff6dc)";
+
+  const MicrodumpExtraInfo kMicrodumpExtraInfo(
+      MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint));
+
+  std::string buf;
+  MappingList no_mappings;
+
+  CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf, false, 0u, true);
+  ASSERT_TRUE(ContainsMicrodump(buf));
+  ASSERT_FALSE(MicrodumpStackContains(buf, kIdentifiableString));
+}
+
+// Ensure that stack content does contain an identifiable string if the
+// stack is not sanitized.
+TEST(MicrodumpWriterTest, StringPresentIfNotSanitized) {
+  const char kProductInfo[] = "MockProduct:42.0.2311.99";
+  const char kBuildFingerprint[] =
+      "aosp/occam/mako:5.1.1/LMY47W/12345678:userdegbug/dev-keys";
+  const char kGPUFingerprint[] =
+      "Qualcomm;Adreno (TM) 330;OpenGL ES 3.0 V@104.0 AU@  (GIT@Id3510ff6dc)";
+
+  const MicrodumpExtraInfo kMicrodumpExtraInfo(
+      MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint));
+
+  std::string buf;
+  MappingList no_mappings;
+
+  CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf, false, 0u, false);
+  ASSERT_TRUE(ContainsMicrodump(buf));
+  ASSERT_TRUE(MicrodumpStackContains(buf, kIdentifiableString));
+}
+
+// Ensure that output occurs if the interest region is set, and
+// does overlap something on the stack.
+TEST(MicrodumpWriterTest, OutputIfInteresting) {
+  const char kProductInfo[] = "MockProduct:42.0.2311.99";
+  const char kBuildFingerprint[] =
+      "aosp/occam/mako:5.1.1/LMY47W/12345678:userdegbug/dev-keys";
+  const char kGPUFingerprint[] =
+      "Qualcomm;Adreno (TM) 330;OpenGL ES 3.0 V@104.0 AU@  (GIT@Id3510ff6dc)";
+
+  const MicrodumpExtraInfo kMicrodumpExtraInfo(
+      MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint));
+
+  std::string buf;
+  MappingList no_mappings;
+
+  CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf, true,
+                       reinterpret_cast<uintptr_t>(CrashAndGetMicrodump));
+  ASSERT_TRUE(ContainsMicrodump(buf));
 }
 
 // Ensure that the product info and build fingerprint metadata show up in the
 // final microdump if present.
 TEST(MicrodumpWriterTest, BuildFingerprintAndProductInfo) {
   const char kProductInfo[] = "MockProduct:42.0.2311.99";
   const char kBuildFingerprint[] =
       "aosp/occam/mako:5.1.1/LMY47W/12345678:userdegbug/dev-keys";
   const char kGPUFingerprint[] =
       "Qualcomm;Adreno (TM) 330;OpenGL ES 3.0 V@104.0 AU@  (GIT@Id3510ff6dc)";
   const MicrodumpExtraInfo kMicrodumpExtraInfo(
       MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint));
-  scoped_array<char> buf;
+  std::string buf;
   MappingList no_mappings;
 
   CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf);
-  CheckMicrodumpContents(string(buf.get()), kMicrodumpExtraInfo);
+  ASSERT_TRUE(ContainsMicrodump(buf));
+  CheckMicrodumpContents(buf, kMicrodumpExtraInfo);
 }
 
 TEST(MicrodumpWriterTest, NoProductInfo) {
   const char kBuildFingerprint[] = "foobar";
   const char kGPUFingerprint[] = "bazqux";
-  scoped_array<char> buf;
+  std::string buf;
   MappingList no_mappings;
 
   const MicrodumpExtraInfo kMicrodumpExtraInfoNoProductInfo(
       MakeMicrodumpExtraInfo(kBuildFingerprint, NULL, kGPUFingerprint));
 
   CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfoNoProductInfo, &buf);
-  CheckMicrodumpContents(string(buf.get()), kBuildFingerprint,
-                         "UNKNOWN:0.0.0.0", kGPUFingerprint);
+  ASSERT_TRUE(ContainsMicrodump(buf));
+  CheckMicrodumpContents(buf, kBuildFingerprint, "UNKNOWN:0.0.0.0",
+                         kGPUFingerprint);
 }
 
 TEST(MicrodumpWriterTest, NoGPUInfo) {
   const char kProductInfo[] = "bazqux";
   const char kBuildFingerprint[] = "foobar";
-  scoped_array<char> buf;
+  std::string buf;
   MappingList no_mappings;
 
   const MicrodumpExtraInfo kMicrodumpExtraInfoNoGPUInfo(
       MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, NULL));
 
   CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfoNoGPUInfo, &buf);
-  CheckMicrodumpContents(string(buf.get()), kBuildFingerprint,
-                         kProductInfo, "UNKNOWN");
+  ASSERT_TRUE(ContainsMicrodump(buf));
+  CheckMicrodumpContents(buf, kBuildFingerprint, kProductInfo, "UNKNOWN");
 }
 }  // namespace
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper.cc
@@ -207,16 +207,17 @@ bool LinuxCoreDumper::EnumerateThreads()
         info.mcontext.mdhi = status->pr_reg[EF_HI];
         info.mcontext.pc = status->pr_reg[EF_CP0_EPC];
 #else  // __mips__
         memcpy(&info.regs, status->pr_reg, sizeof(info.regs));
 #endif  // __mips__
         if (first_thread) {
           crash_thread_ = pid;
           crash_signal_ = status->pr_info.si_signo;
+          crash_signal_code_ = status->pr_info.si_code;
         }
         first_thread = false;
         threads_.push_back(pid);
         thread_infos_.push_back(info);
         break;
       }
 #if defined(__i386) || defined(__x86_64)
       case NT_FPREGSET: {
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper_unittest.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper_unittest.cc
@@ -36,17 +36,17 @@
 #include "linux/minidump_writer/linux_core_dumper.h"
 #include "common/linux/tests/crash_generator.h"
 #include "common/using_std_string.h"
 
 using namespace google_breakpad;
 
 TEST(LinuxCoreDumperTest, GetMappingAbsolutePath) {
   const LinuxCoreDumper dumper(getpid(), "core", "/tmp", "/mnt/root");
-  const MappingInfo mapping = { 0, 0, 0, false, "/usr/lib/libc.so" };
+  const MappingInfo mapping = {0, 0, {0, 0}, 0, false, "/usr/lib/libc.so"};
 
   char path[PATH_MAX];
   dumper.GetMappingAbsolutePath(mapping, path);
 
   EXPECT_STREQ("/mnt/root/usr/lib/libc.so", path);
 }
 
 TEST(LinuxCoreDumperTest, BuildProcPath) {
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc
@@ -45,16 +45,17 @@
 #include <string.h>
 
 #include "linux/minidump_writer/line_reader.h"
 #include "common/linux/elfutils.h"
 #include "common/linux/file_id.h"
 #include "common/linux/linux_libc_support.h"
 #include "common/linux/memory_mapped_file.h"
 #include "common/linux/safe_readlink.h"
+#include "google_breakpad/common/minidump_exception_linux.h"
 #include "third_party/lss/linux_syscall_support.h"
 
 #if defined(__ANDROID__)
 
 // Android packed relocations definitions are not yet available from the
 // NDK header files, so we have to provide them manually here.
 #ifndef DT_LOOS
 #define DT_LOOS 0x6000000d
@@ -80,19 +81,24 @@ inline static bool IsMappedFileOpenUnsaf
   // ELF file identifier anyways.
   return my_strncmp(mapping.name,
                     kMappedFileUnsafePrefix,
                     sizeof(kMappedFileUnsafePrefix) - 1) == 0;
 }
 
 namespace google_breakpad {
 
-#if defined(__CHROMEOS__)
+namespace {
 
-namespace {
+bool MappingContainsAddress(const MappingInfo& mapping, uintptr_t address) {
+  return mapping.system_mapping_info.start_addr <= address &&
+         address < mapping.system_mapping_info.end_addr;
+}
+
+#if defined(__CHROMEOS__)
 
 // Recover memory mappings before writing dump on ChromeOS
 //
 // On Linux, breakpad relies on /proc/[pid]/maps to associate symbols from
 // addresses. ChromeOS' hugepage implementation replaces some segments with
 // anonymous private pages, which is a restriction of current implementation
 // in Linux kernel at the time of writing. Thus, breakpad can no longer
 // symbolize addresses from those text segments replaced with hugepages.
@@ -220,51 +226,70 @@ void CrOSPostProcessMappings(wasteful_ve
   while (l < r) {
     int m = (l + r) / 2;
     if (mappings[m]->start_addr > mappings[0]->start_addr)
       r = next = m;
     else
       l = m + 1;
   }
 
-  // Try to merge segments into the first.
-  if (next < mappings.size()) {
-    TryRecoverMappings(mappings[0], mappings[next]);
-    if (next - 1 > 0)
-      TryRecoverMappings(mappings[next - 1], mappings[0], mappings[next]);
-  }
+  // Shows the range that contains the entry point is
+  // [first_start_addr, first_end_addr)
+  size_t first_start_addr = mappings[0]->start_addr;
+  size_t first_end_addr = mappings[0]->start_addr + mappings[0]->size;
+
+  // Put the out-of-order segment in order.
+  std::rotate(mappings.begin(), mappings.begin() + 1, mappings.begin() + next);
 
   // Iterate through normal, sorted cases.
   // Normal case 1.
-  for (size_t i = 1; i < mappings.size() - 1; i++)
+  for (size_t i = 0; i < mappings.size() - 1; i++)
     TryRecoverMappings(mappings[i], mappings[i + 1]);
 
   // Normal case 2.
-  for (size_t i = 1; i < mappings.size() - 2; i++)
+  for (size_t i = 0; i < mappings.size() - 2; i++)
     TryRecoverMappings(mappings[i], mappings[i + 1], mappings[i + 2]);
 
   // Collect merged (size == 0) segments.
   size_t f, e;
   for (f = e = 0; e < mappings.size(); e++)
     if (mappings[e]->size > 0)
       mappings[f++] = mappings[e];
   mappings.resize(f);
+
+  // The entry point is in the first mapping. We want to find the location
+  // of the entry point after merging segment. To do this, we want to find
+  // the mapping that covers the first mapping from the original mapping list.
+  // If the mapping is not in the beginning, we move it to the begining via
+  // a right rotate by using reverse iterators.
+  for (l = 0; l < mappings.size(); l++) {
+    if (mappings[l]->start_addr <= first_start_addr
+        && (mappings[l]->start_addr + mappings[l]->size >= first_end_addr))
+      break;
+  }
+  if (l > 0) {
+    r = mappings.size();
+    std::rotate(mappings.rbegin() + r - l - 1, mappings.rbegin() + r - l,
+                mappings.rend());
+  }
 }
 
+#endif  // __CHROMEOS__
+
 }  // namespace
-#endif  // __CHROMEOS__
 
 // All interesting auvx entry types are below AT_SYSINFO_EHDR
 #define AT_MAX AT_SYSINFO_EHDR
 
 LinuxDumper::LinuxDumper(pid_t pid, const char* root_prefix)
     : pid_(pid),
       root_prefix_(root_prefix),
       crash_address_(0),
       crash_signal_(0),
+      crash_signal_code_(0),
       crash_thread_(pid),
       threads_(&allocator_, 8),
       mappings_(&allocator_),
       auxv_(&allocator_, AT_MAX + 1) {
   assert(root_prefix_ && my_strlen(root_prefix_) < PATH_MAX);
   // The passed-in size to the constructor (above) is only a hint.
   // Must call .resize() to do actual initialization of the elements.
   auxv_.resize(AT_MAX + 1);
@@ -326,43 +351,119 @@ LinuxDumper::ElfFileIdentifierForMapping
   if (success && member && filename_modified) {
     mappings_[mapping_id]->name[my_strlen(mapping.name) -
                                 sizeof(kDeletedSuffix) + 1] = '\0';
   }
 
   return success;
 }
 
+void LinuxDumper::SetCrashInfoFromSigInfo(const siginfo_t& siginfo) {
+  set_crash_address(reinterpret_cast<uintptr_t>(siginfo.si_addr));
+  set_crash_signal(siginfo.si_signo);
+  set_crash_signal_code(siginfo.si_code);
+}
+
+const char* LinuxDumper::GetCrashSignalString() const {
+  switch (static_cast<unsigned int>(crash_signal_)) {
+    case MD_EXCEPTION_CODE_LIN_SIGHUP:
+      return "SIGHUP";
+    case MD_EXCEPTION_CODE_LIN_SIGINT:
+      return "SIGINT";
+    case MD_EXCEPTION_CODE_LIN_SIGQUIT:
+      return "SIGQUIT";
+    case MD_EXCEPTION_CODE_LIN_SIGILL:
+      return "SIGILL";
+    case MD_EXCEPTION_CODE_LIN_SIGTRAP:
+      return "SIGTRAP";
+    case MD_EXCEPTION_CODE_LIN_SIGABRT:
+      return "SIGABRT";
+    case MD_EXCEPTION_CODE_LIN_SIGBUS:
+      return "SIGBUS";
+    case MD_EXCEPTION_CODE_LIN_SIGFPE:
+      return "SIGFPE";
+    case MD_EXCEPTION_CODE_LIN_SIGKILL:
+      return "SIGKILL";
+    case MD_EXCEPTION_CODE_LIN_SIGUSR1:
+      return "SIGUSR1";
+    case MD_EXCEPTION_CODE_LIN_SIGSEGV:
+      return "SIGSEGV";
+    case MD_EXCEPTION_CODE_LIN_SIGUSR2:
+      return "SIGUSR2";
+    case MD_EXCEPTION_CODE_LIN_SIGPIPE:
+      return "SIGPIPE";
+    case MD_EXCEPTION_CODE_LIN_SIGALRM:
+      return "SIGALRM";
+    case MD_EXCEPTION_CODE_LIN_SIGTERM:
+      return "SIGTERM";
+    case MD_EXCEPTION_CODE_LIN_SIGSTKFLT:
+      return "SIGSTKFLT";
+    case MD_EXCEPTION_CODE_LIN_SIGCHLD:
+      return "SIGCHLD";
+    case MD_EXCEPTION_CODE_LIN_SIGCONT:
+      return "SIGCONT";
+    case MD_EXCEPTION_CODE_LIN_SIGSTOP:
+      return "SIGSTOP";
+    case MD_EXCEPTION_CODE_LIN_SIGTSTP:
+      return "SIGTSTP";
+    case MD_EXCEPTION_CODE_LIN_SIGTTIN:
+      return "SIGTTIN";
+    case MD_EXCEPTION_CODE_LIN_SIGTTOU:
+      return "SIGTTOU";
+    case MD_EXCEPTION_CODE_LIN_SIGURG:
+      return "SIGURG";
+    case MD_EXCEPTION_CODE_LIN_SIGXCPU:
+      return "SIGXCPU";
+    case MD_EXCEPTION_CODE_LIN_SIGXFSZ:
+      return "SIGXFSZ";
+    case MD_EXCEPTION_CODE_LIN_SIGVTALRM:
+      return "SIGVTALRM";
+    case MD_EXCEPTION_CODE_LIN_SIGPROF:
+      return "SIGPROF";
+    case MD_EXCEPTION_CODE_LIN_SIGWINCH:
+      return "SIGWINCH";
+    case MD_EXCEPTION_CODE_LIN_SIGIO:
+      return "SIGIO";
+    case MD_EXCEPTION_CODE_LIN_SIGPWR:
+      return "SIGPWR";
+    case MD_EXCEPTION_CODE_LIN_SIGSYS:
+      return "SIGSYS";
+    case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED:
+      return "DUMP_REQUESTED";
+    default:
+      return "UNKNOWN";
+  }
+}
+
 bool LinuxDumper::GetMappingAbsolutePath(const MappingInfo& mapping,
                                          char path[PATH_MAX]) const {
   return my_strlcpy(path, root_prefix_, PATH_MAX) < PATH_MAX &&
          my_strlcat(path, mapping.name, PATH_MAX) < PATH_MAX;
 }
 
 namespace {
 bool ElfFileSoNameFromMappedFile(
     const void* elf_base, char* soname, size_t soname_size) {
   if (!IsValidElf(elf_base)) {
     // Not ELF
     return false;
   }
 
   const void* segment_start;
   size_t segment_size;
-  int elf_class;
-  if (!FindElfSection(elf_base, ".dynamic", SHT_DYNAMIC,
-                      &segment_start, &segment_size, &elf_class)) {
+  if (!FindElfSection(elf_base, ".dynamic", SHT_DYNAMIC, &segment_start,
+                      &segment_size)) {
     // No dynamic section
     return false;
   }
 
   const void* dynstr_start;
   size_t dynstr_size;
-  if (!FindElfSection(elf_base, ".dynstr", SHT_STRTAB,
-                      &dynstr_start, &dynstr_size, &elf_class)) {
+  if (!FindElfSection(elf_base, ".dynstr", SHT_STRTAB, &dynstr_start,
+                      &dynstr_size)) {
     // No dynstr section
     return false;
   }
 
   const ElfW(Dyn)* dynamic = static_cast<const ElfW(Dyn)*>(segment_start);
   size_t dcount = segment_size / sizeof(ElfW(Dyn));
   for (const ElfW(Dyn)* dyn = dynamic; dyn < dynamic + dcount; ++dyn) {
     if (dyn->d_tag == DT_SONAME) {
@@ -541,51 +642,55 @@ bool LinuxDumper::EnumerateMappings() {
                                           kReservedFlags,
                                           sizeof(kReservedFlags) - 1) == 0) {
               module->size = end_addr - module->start_addr;
               line_reader->PopLine(line_len);
               continue;
             }
           }
           MappingInfo* const module = new(allocator_) MappingInfo;
+          mappings_.push_back(module);
           my_memset(module, 0, sizeof(MappingInfo));
+          module->system_mapping_info.start_addr = start_addr;
+          module->system_mapping_info.end_addr = end_addr;
           module->start_addr = start_addr;
           module->size = end_addr - start_addr;
           module->offset = offset;
           module->exec = exec;
           if (name != NULL) {
             const unsigned l = my_strlen(name);
             if (l < sizeof(module->name))
               my_memcpy(module->name, name, l);
           }
-          // If this is the entry-point mapping, and it's not already the
-          // first one, then we need to make it be first.  This is because
-          // the minidump format assumes the first module is the one that
-          // corresponds to the main executable (as codified in
-          // processor/minidump.cc:MinidumpModuleList::GetMainModule()).
-          if (entry_point_loc &&
-              (entry_point_loc >=
-                  reinterpret_cast<void*>(module->start_addr)) &&
-              (entry_point_loc <
-                  reinterpret_cast<void*>(module->start_addr+module->size)) &&
-              !mappings_.empty()) {
-            // push the module onto the front of the list.
-            mappings_.resize(mappings_.size() + 1);
-            for (size_t idx = mappings_.size() - 1; idx > 0; idx--)
-              mappings_[idx] = mappings_[idx - 1];
-            mappings_[0] = module;
-          } else {
-            mappings_.push_back(module);
-          }
         }
       }
     }
     line_reader->PopLine(line_len);
   }
 
+  if (entry_point_loc) {
+    for (size_t i = 0; i < mappings_.size(); ++i) {
+      MappingInfo* module = mappings_[i];
+
+      // If this module contains the entry-point, and it's not already the first
+      // one, then we need to make it be first.  This is because the minidump
+      // format assumes the first module is the one that corresponds to the main
+      // executable (as codified in
+      // processor/minidump.cc:MinidumpModuleList::GetMainModule()).
+      if ((entry_point_loc >= reinterpret_cast<void*>(module->start_addr)) &&
+          (entry_point_loc <
+           reinterpret_cast<void*>(module->start_addr + module->size))) {
+        for (size_t j = i; j > 0; j--)
+          mappings_[j] = mappings_[j - 1];
+        mappings_[0] = module;
+        break;
+      }
+    }
+  }
+
   sys_close(fd);
 
   return !mappings_.empty();
 }
 
 #if defined(__ANDROID__)
 
 bool LinuxDumper::GetLoadedElfHeader(uintptr_t start_addr, ElfW(Ehdr)* ehdr) {
@@ -715,29 +820,162 @@ bool LinuxDumper::GetStackInfo(const voi
   const ptrdiff_t distance_to_end =
       static_cast<ptrdiff_t>(mapping->size) - offset;
   *stack_len = distance_to_end > kStackToCapture ?
       kStackToCapture : distance_to_end;
   *stack = stack_pointer;
   return true;
 }
 
+void LinuxDumper::SanitizeStackCopy(uint8_t* stack_copy, size_t stack_len,
+                                    uintptr_t stack_pointer,
+                                    uintptr_t sp_offset) {
+  // We optimize the search for containing mappings in three ways:
+  // 1) We expect that pointers into the stack mapping will be common, so
+  //    we cache that address range.
+  // 2) The last referenced mapping is a reasonable predictor for the next
+  //    referenced mapping, so we test that first.
+  // 3) We precompute a bitfield based upon bits 32:32-n of the start and
+  //    stop addresses, and use that to short circuit any values that can
+  //    not be pointers. (n=11)
+  const uintptr_t defaced =
+#if defined(__LP64__)
+      0x0defaced0defaced;
+#else
+      0x0defaced;
+#endif
+  // the bitfield length is 2^test_bits long.
+  const unsigned int test_bits = 11;
+  // byte length of the corresponding array.
+  const unsigned int array_size = 1 << (test_bits - 3);
+  const unsigned int array_mask = array_size - 1;
+  // The amount to right shift pointers by. This captures the top bits
+  // on 32 bit architectures. On 64 bit architectures this would be
+  // uninformative so we take the same range of bits.
+  const unsigned int shift = 32 - 11;
+  const MappingInfo* last_hit_mapping = nullptr;
+  const MappingInfo* hit_mapping = nullptr;
+  const MappingInfo* stack_mapping = FindMappingNoBias(stack_pointer);
+  // The magnitude below which integers are considered to be to be
+  // 'small', and not constitute a PII risk. These are included to
+  // avoid eliding useful register values.
+  const ssize_t small_int_magnitude = 4096;
+
+  char could_hit_mapping[array_size];
+  my_memset(could_hit_mapping, 0, array_size);
+
+  // Initialize the bitfield such that if the (pointer >> shift)'th
+  // bit, modulo the bitfield size, is not set then there does not
+  // exist a mapping in mappings_ that would contain that pointer.
+  for (size_t i = 0; i < mappings_.size(); ++i) {
+    if (!mappings_[i]->exec) continue;
+    // For each mapping, work out the (unmodulo'ed) range of bits to
+    // set.
+    uintptr_t start = mappings_[i]->start_addr;
+    uintptr_t end = start + mappings_[i]->size;
+    start >>= shift;
+    end >>= shift;
+    for (size_t bit = start; bit <= end; ++bit) {
+      // Set each bit in the range, applying the modulus.
+      could_hit_mapping[(bit >> 3) & array_mask] |= 1 << (bit & 7);
+    }
+  }
+
+  // Zero memory that is below the current stack pointer.
+  const uintptr_t offset =
+      (sp_offset + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1);
+  if (offset) {
+    my_memset(stack_copy, 0, offset);
+  }
+
+  // Apply sanitization to each complete pointer-aligned word in the
+  // stack.
+  uint8_t* sp;
+  for (sp = stack_copy + offset;
+       sp <= stack_copy + stack_len - sizeof(uintptr_t);
+       sp += sizeof(uintptr_t)) {
+    uintptr_t addr;
+    my_memcpy(&addr, sp, sizeof(uintptr_t));
+    if (static_cast<intptr_t>(addr) <= small_int_magnitude &&
+        static_cast<intptr_t>(addr) >= -small_int_magnitude) {
+      continue;
+    }
+    if (stack_mapping && MappingContainsAddress(*stack_mapping, addr)) {
+      continue;
+    }
+    if (last_hit_mapping && MappingContainsAddress(*last_hit_mapping, addr)) {
+      continue;
+    }
+    uintptr_t test = addr >> shift;
+    if (could_hit_mapping[(test >> 3) & array_mask] & (1 << (test & 7)) &&
+        (hit_mapping = FindMappingNoBias(addr)) != nullptr &&
+        hit_mapping->exec) {
+      last_hit_mapping = hit_mapping;
+      continue;
+    }
+    my_memcpy(sp, &defaced, sizeof(uintptr_t));
+  }
+  // Zero any partial word at the top of the stack, if alignment is
+  // such that that is required.
+  if (sp < stack_copy + stack_len) {
+    my_memset(sp, 0, stack_copy + stack_len - sp);
+  }
+}
+
+bool LinuxDumper::StackHasPointerToMapping(const uint8_t* stack_copy,
+                                           size_t stack_len,
+                                           uintptr_t sp_offset,
+                                           const MappingInfo& mapping) {
+  // Loop over all stack words that would have been on the stack in
+  // the target process (i.e. are word aligned, and at addresses >=
+  // the stack pointer).  Regardless of the alignment of |stack_copy|,
+  // the memory starting at |stack_copy| + |offset| represents an
+  // aligned word in the target process.
+  const uintptr_t low_addr = mapping.system_mapping_info.start_addr;
+  const uintptr_t high_addr = mapping.system_mapping_info.end_addr;
+  const uintptr_t offset =
+      (sp_offset + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1);
+
+  for (const uint8_t* sp = stack_copy + offset;
+       sp <= stack_copy + stack_len - sizeof(uintptr_t);
+       sp += sizeof(uintptr_t)) {
+    uintptr_t addr;
+    my_memcpy(&addr, sp, sizeof(uintptr_t));
+    if (low_addr <= addr && addr <= high_addr)
+      return true;
+  }
+  return false;
+}
+
 // Find the mapping which the given memory address falls in.
 const MappingInfo* LinuxDumper::FindMapping(const void* address) const {
   const uintptr_t addr = (uintptr_t) address;
 
   for (size_t i = 0; i < mappings_.size(); ++i) {
     const uintptr_t start = static_cast<uintptr_t>(mappings_[i]->start_addr);
     if (addr >= start && addr - start < mappings_[i]->size)
       return mappings_[i];
   }
 
   return NULL;
 }
 
+// Find the mapping which the given memory address falls in. Uses the
+// unadjusted mapping address range from the kernel, rather than the
+// biased range.
+const MappingInfo* LinuxDumper::FindMappingNoBias(uintptr_t address) const {
+  for (size_t i = 0; i < mappings_.size(); ++i) {
+    if (address >= mappings_[i]->system_mapping_info.start_addr &&
+        address < mappings_[i]->system_mapping_info.end_addr) {
+      return mappings_[i];
+    }
+  }
+  return NULL;
+}
+
 bool LinuxDumper::HandleDeletedFileInMapping(char* path) const {
   static const size_t kDeletedSuffixLen = sizeof(kDeletedSuffix) - 1;
 
   // Check for ' (deleted)' in |path|.
   // |path| has to be at least as long as "/x (deleted)".
   const size_t path_len = my_strlen(path);
   if (path_len < kDeletedSuffixLen + 2)
     return false;
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.h
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.h
@@ -94,28 +94,66 @@ class LinuxDumper {
   // Suspend/resume all threads in the given process.
   virtual bool ThreadsSuspend() = 0;
   virtual bool ThreadsResume() = 0;
 
   // Read information about the |index|-th thread of |threads_|.
   // Returns true on success. One must have called |ThreadsSuspend| first.
   virtual bool GetThreadInfoByIndex(size_t index, ThreadInfo* info) = 0;
 
+  size_t GetMainThreadIndex() const {
+    for (size_t i = 0; i < threads_.size(); ++i) {
+      if (threads_[i] == pid_) return i;
+    }
+    return -1u;
+  }
+
   // These are only valid after a call to |Init|.
   const wasteful_vector<pid_t> &threads() { return threads_; }
   const wasteful_vector<MappingInfo*> &mappings() { return mappings_; }
   const MappingInfo* FindMapping(const void* address) const;
+  // Find the mapping which the given memory address falls in. Unlike
+  // FindMapping, this method uses the unadjusted mapping address
+  // ranges from the kernel, rather than the ranges that have had the
+  // load bias applied.
+  const MappingInfo* FindMappingNoBias(uintptr_t address) const;
   const wasteful_vector<elf_aux_val_t>& auxv() { return auxv_; }
 
   // Find a block of memory to take as the stack given the top of stack pointer.
   //   stack: (output) the lowest address in the memory area
   //   stack_len: (output) the length of the memory area
   //   stack_top: the current top of the stack
   bool GetStackInfo(const void** stack, size_t* stack_len, uintptr_t stack_top);
 
+  // Sanitize a copy of the stack by overwriting words that are not
+  // pointers with a sentinel (0x0defaced).
+  //   stack_copy: a copy of the stack to sanitize. |stack_copy| might
+  //               not be word aligned, but it represents word aligned
+  //               data copied from another location.
+  //   stack_len: the length of the allocation pointed to by |stack_copy|.
+  //   stack_pointer: the address of the stack pointer (used to locate
+  //                  the stack mapping, as an optimization).
+  //   sp_offset: the offset relative to stack_copy that reflects the
+  //              current value of the stack pointer.
+  void SanitizeStackCopy(uint8_t* stack_copy, size_t stack_len,
+                         uintptr_t stack_pointer, uintptr_t sp_offset);
+
+  // Test whether |stack_copy| contains a pointer-aligned word that
+  // could be an address within a given mapping.
+  //   stack_copy: a copy of the stack to check. |stack_copy| might
+  //               not be word aligned, but it represents word aligned
+  //               data copied from another location.
+  //   stack_len: the length of the allocation pointed to by |stack_copy|.
+  //   sp_offset: the offset relative to stack_copy that reflects the
+  //              current value of the stack pointer.
+  //   mapping: the mapping against which to test stack words.
+  bool StackHasPointerToMapping(const uint8_t* stack_copy, size_t stack_len,
+                                uintptr_t sp_offset,
+                                const MappingInfo& mapping);
+
   PageAllocator* allocator() { return &allocator_; }
 
   // Copy content of |length| bytes from a given process |child|,
   // starting from |src|, into |dest|. Returns true on success.
   virtual bool CopyFromProcess(void* dest, pid_t child, const void* src,
                                size_t length) = 0;
 
   // Builds a proc path for a certain pid for a node (/proc/<pid>/<node>).
@@ -127,23 +165,29 @@ class LinuxDumper {
   // Generate a File ID from the .text section of a mapped entry.
   // If not a member, mapping_id is ignored. This method can also manipulate the
   // |mapping|.name to truncate "(deleted)" from the file name if necessary.
   bool ElfFileIdentifierForMapping(const MappingInfo& mapping,
                                    bool member,
                                    unsigned int mapping_id,
                                    wasteful_vector<uint8_t>& identifier);
 
+  void SetCrashInfoFromSigInfo(const siginfo_t& siginfo);
+
   uintptr_t crash_address() const { return crash_address_; }
   void set_crash_address(uintptr_t crash_address) {
     crash_address_ = crash_address;
   }
 
   int crash_signal() const { return crash_signal_; }
   void set_crash_signal(int crash_signal) { crash_signal_ = crash_signal; }
+  const char* GetCrashSignalString() const;
+
+  void set_crash_signal_code(int code) { crash_signal_code_ = code; }
+  int crash_signal_code() const { return crash_signal_code_; }
 
   pid_t crash_thread() const { return crash_thread_; }
   void set_crash_thread(pid_t crash_thread) { crash_thread_ = crash_thread; }
 
   // Concatenates the |root_prefix_| and |mapping| path. Writes into |path| and
   // returns true unless the string is too long.
   bool GetMappingAbsolutePath(const MappingInfo& mapping,
                               char path[PATH_MAX]) const;
@@ -184,16 +228,19 @@ class LinuxDumper {
   const char* const root_prefix_;
 
   // Virtual address at which the process crashed.
   uintptr_t crash_address_;
 
   // Signal that terminated the crashed process.
   int crash_signal_;
 
+  // The code associated with |crash_signal_|.
+  int crash_signal_code_;
+
   // ID of the crashed thread.
   pid_t crash_thread_;
 
   mutable PageAllocator allocator_;
 
   // IDs of all the threads.
   wasteful_vector<pid_t> threads_;
 
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper_unittest_helper.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper_unittest_helper.cc
@@ -52,24 +52,25 @@
 #elif defined(__mips__)
 #define TID_PTR_REGISTER "$1"
 #else
 #error This test has not been ported to this platform.
 #endif
 
 void *thread_function(void *data) {
   int pipefd = *static_cast<int *>(data);
-  volatile pid_t thread_id = syscall(__NR_gettid);
+  volatile pid_t* thread_id = new pid_t;
+  *thread_id = syscall(__NR_gettid);
   // Signal parent that a thread has started.
   uint8_t byte = 1;
   if (write(pipefd, &byte, sizeof(byte)) != sizeof(byte)) {
     perror("ERROR: parent notification failed");
     return NULL;
   }
-  register volatile pid_t *thread_id_ptr asm(TID_PTR_REGISTER) = &thread_id;
+  register volatile pid_t *thread_id_ptr asm(TID_PTR_REGISTER) = thread_id;
   while (true)
     asm volatile ("" : : "r" (thread_id_ptr));
   return NULL;
 }
 
 int main(int argc, char *argv[]) {
   if (argc < 3) {
     fprintf(stderr,
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.cc
@@ -144,16 +144,60 @@ bool LinuxPtraceDumper::CopyFromProcess(
       tmp = 0;
     }
     my_memcpy(local + done, &tmp, l);
     done += l;
   }
   return true;
 }
 
+bool LinuxPtraceDumper::ReadRegisterSet(ThreadInfo* info, pid_t tid)
+{
+#ifdef PTRACE_GETREGSET
+  struct iovec io;
+  info->GetGeneralPurposeRegisters(&io.iov_base, &io.iov_len);
+  if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_PRSTATUS, (void*)&io) == -1) {
+    return false;
+  }
+
+  info->GetFloatingPointRegisters(&io.iov_base, &io.iov_len);
+  if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_FPREGSET, (void*)&io) == -1) {
+    return false;
+  }
+  return true;
+#else
+  return false;
+#endif
+}
+
+bool LinuxPtraceDumper::ReadRegisters(ThreadInfo* info, pid_t tid) {
+#ifdef PTRACE_GETREGS
+  void* gp_addr;
+  info->GetGeneralPurposeRegisters(&gp_addr, NULL);
+  if (sys_ptrace(PTRACE_GETREGS, tid, NULL, gp_addr) == -1) {
+    return false;
+  }
+
+#if !(defined(__ANDROID__) && defined(__ARM_EABI__))
+  // When running an arm build on an arm64 device, attempting to get the
+  // floating point registers fails. On Android, the floating point registers
+  // aren't written to the cpu context anyway, so just don't get them here.
+  // See http://crbug.com/508324
+  void* fp_addr;
+  info->GetFloatingPointRegisters(&fp_addr, NULL);
+  if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, fp_addr) == -1) {
+    return false;
+  }
+#endif  // !(defined(__ANDROID__) && defined(__ARM_EABI__))
+  return true;
+#else  // PTRACE_GETREGS
+  return false;
+#endif
+}
+
 // Read thread info from /proc/$pid/status.
 // Fill out the |tgid|, |ppid| and |pid| members of |info|. If unavailable,
 // these members are set to -1. Returns true iff all three members are
 // available.
 bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
   if (index >= threads_.size())
     return false;
 
@@ -183,46 +227,21 @@ bool LinuxPtraceDumper::GetThreadInfoByI
 
     line_reader->PopLine(line_len);
   }
   sys_close(fd);
 
   if (info->ppid == -1 || info->tgid == -1)
     return false;
 
-#ifdef PTRACE_GETREGSET
-  struct iovec io;
-  info->GetGeneralPurposeRegisters(&io.iov_base, &io.iov_len);
-  if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_PRSTATUS, (void*)&io) == -1) {
-    return false;
-  }
-
-  info->GetFloatingPointRegisters(&io.iov_base, &io.iov_len);
-  if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_FPREGSET, (void*)&io) == -1) {
-    return false;
+  if (!ReadRegisterSet(info, tid)) {
+    if (!ReadRegisters(info, tid)) {
+      return false;
+    }
   }
-#else  // PTRACE_GETREGSET
-  void* gp_addr;
-  info->GetGeneralPurposeRegisters(&gp_addr, NULL);
-  if (sys_ptrace(PTRACE_GETREGS, tid, NULL, gp_addr) == -1) {
-    return false;
-  }
-
-#if !(defined(__ANDROID__) && defined(__ARM_EABI__))
-  // When running an arm build on an arm64 device, attempting to get the
-  // floating point registers fails. On Android, the floating point registers
-  // aren't written to the cpu context anyway, so just don't get them here.
-  // See http://crbug.com/508324
-  void* fp_addr;
-  info->GetFloatingPointRegisters(&fp_addr, NULL);
-  if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, fp_addr) == -1) {
-    return false;
-  }
-#endif
-#endif  // PTRACE_GETREGSET
 
 #if defined(__i386)
 #if !defined(bit_FXSAVE)  // e.g. Clang
 #define bit_FXSAVE bit_FXSR
 #endif
   // Detect if the CPU supports the FXSAVE/FXRSTOR instructions
   int eax, ebx, ecx, edx;
   __cpuid(1, eax, ebx, ecx, edx);
@@ -245,16 +264,18 @@ bool LinuxPtraceDumper::GetThreadInfoByI
         &info->dregs[i]) == -1) {
       return false;
     }
   }
 #endif
 
 #if defined(__mips__)
   sys_ptrace(PTRACE_PEEKUSER, tid,
+             reinterpret_cast<void*>(PC), &info->mcontext.pc);
+  sys_ptrace(PTRACE_PEEKUSER, tid,
              reinterpret_cast<void*>(DSP_BASE), &info->mcontext.hi1);
   sys_ptrace(PTRACE_PEEKUSER, tid,
              reinterpret_cast<void*>(DSP_BASE + 1), &info->mcontext.lo1);
   sys_ptrace(PTRACE_PEEKUSER, tid,
              reinterpret_cast<void*>(DSP_BASE + 2), &info->mcontext.hi2);
   sys_ptrace(PTRACE_PEEKUSER, tid,
              reinterpret_cast<void*>(DSP_BASE + 3), &info->mcontext.lo2);
   sys_ptrace(PTRACE_PEEKUSER, tid,
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.h
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.h
@@ -80,13 +80,22 @@ class LinuxPtraceDumper : public LinuxDu
  protected:
   // Implements LinuxDumper::EnumerateThreads().
   // Enumerates all threads of the given process into |threads_|.
   virtual bool EnumerateThreads();
 
  private:
   // Set to true if all threads of the crashed process are suspended.
   bool threads_suspended_;
+
+  // Read the tracee's registers on kernel with PTRACE_GETREGSET support.
+  // Returns false if PTRACE_GETREGSET is not defined.
+  // Returns true on success.
+  bool ReadRegisterSet(ThreadInfo* info, pid_t tid);
+
+  // Read the tracee's registers on kernel with PTRACE_GETREGS support.
+  // Returns true on success.
+  bool ReadRegisters(ThreadInfo* info, pid_t tid);
 };
 
 }  // namespace google_breakpad
 
 #endif  // CLIENT_LINUX_HANDLER_LINUX_PTRACE_DUMPER_H_
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
@@ -61,16 +61,73 @@
 #ifndef PR_SET_PTRACER
 #define PR_SET_PTRACER 0x59616d61
 #endif
 
 using namespace google_breakpad;
 
 namespace {
 
+pid_t SetupChildProcess(int number_of_threads) {
+  char kNumberOfThreadsArgument[2];
+  sprintf(kNumberOfThreadsArgument, "%d", number_of_threads);
+
+  int fds[2];
+  EXPECT_NE(-1, pipe(fds));
+
+  pid_t child_pid = fork();
+  if (child_pid == 0) {
+    // In child process.
+    close(fds[0]);
+
+    string helper_path(GetHelperBinary());
+    if (helper_path.empty()) {
+      fprintf(stderr, "Couldn't find helper binary\n");
+      _exit(1);
+    }
+
+    // Pass the pipe fd and the number of threads as arguments.
+    char pipe_fd_string[8];
+    sprintf(pipe_fd_string, "%d", fds[1]);
+    execl(helper_path.c_str(),
+          "linux_dumper_unittest_helper",
+          pipe_fd_string,
+          kNumberOfThreadsArgument,
+          NULL);
+    // Kill if we get here.
+    printf("Errno from exec: %d", errno);
+    std::string err_str = "Exec of  " + helper_path + " failed";
+    perror(err_str.c_str());
+    _exit(1);
+  }
+  close(fds[1]);
+
+  // Wait for all child threads to indicate that they have started
+  for (int threads = 0; threads < number_of_threads; threads++) {
+    struct pollfd pfd;
+    memset(&pfd, 0, sizeof(pfd));
+    pfd.fd = fds[0];
+    pfd.events = POLLIN | POLLERR;
+
+    const int r = HANDLE_EINTR(poll(&pfd, 1, 1000));
+    EXPECT_EQ(1, r);
+    EXPECT_TRUE(pfd.revents & POLLIN);
+    uint8_t junk;
+    EXPECT_EQ(read(fds[0], &junk, sizeof(junk)),
+              static_cast<ssize_t>(sizeof(junk)));
+  }
+  close(fds[0]);
+
+  // There is a race here because we may stop a child thread before
+  // it is actually running the busy loop. Empirically this sleep
+  // is sufficient to avoid the race.
+  usleep(100000);
+  return child_pid;
+}
+
 typedef wasteful_vector<uint8_t> id_vector;
 typedef testing::Test LinuxPtraceDumperTest;
 
 /* Fixture for running tests in a child process. */
 class LinuxPtraceDumperChildTest : public testing::Test {
  protected:
   virtual void SetUp() {
     child_pid_ = fork();
@@ -365,68 +422,19 @@ TEST_F(LinuxPtraceDumperChildTest, FileI
   EXPECT_EQ(identifier_string1, identifier_string2);
 }
 
 /* Get back to normal behavior of TEST*() macros wrt TestBody. */
 #undef TestBody
 
 TEST(LinuxPtraceDumperTest, VerifyStackReadWithMultipleThreads) {
   static const int kNumberOfThreadsInHelperProgram = 5;
-  char kNumberOfThreadsArgument[2];
-  sprintf(kNumberOfThreadsArgument, "%d", kNumberOfThreadsInHelperProgram);
 
-  int fds[2];
-  ASSERT_NE(-1, pipe(fds));
-
-  pid_t child_pid = fork();
-  if (child_pid == 0) {
-    // In child process.
-    close(fds[0]);
-
-    string helper_path(GetHelperBinary());
-    if (helper_path.empty()) {
-      FAIL() << "Couldn't find helper binary";
-      exit(1);
-    }
-
-    // Pass the pipe fd and the number of threads as arguments.
-    char pipe_fd_string[8];
-    sprintf(pipe_fd_string, "%d", fds[1]);
-    execl(helper_path.c_str(),
-          "linux_dumper_unittest_helper",
-          pipe_fd_string,
-          kNumberOfThreadsArgument,
-          NULL);
-    // Kill if we get here.
-    printf("Errno from exec: %d", errno);
-    FAIL() << "Exec of " << helper_path << " failed: " << strerror(errno);
-    exit(0);
-  }
-  close(fds[1]);
-
-  // Wait for all child threads to indicate that they have started
-  for (int threads = 0; threads < kNumberOfThreadsInHelperProgram; threads++) {
-    struct pollfd pfd;
-    memset(&pfd, 0, sizeof(pfd));
-    pfd.fd = fds[0];
-    pfd.events = POLLIN | POLLERR;
-
-    const int r = HANDLE_EINTR(poll(&pfd, 1, 1000));
-    ASSERT_EQ(1, r);
-    ASSERT_TRUE(pfd.revents & POLLIN);
-    uint8_t junk;
-    ASSERT_EQ(read(fds[0], &junk, sizeof(junk)),
-              static_cast<ssize_t>(sizeof(junk)));
-  }
-  close(fds[0]);
-
-  // There is a race here because we may stop a child thread before
-  // it is actually running the busy loop. Empirically this sleep
-  // is sufficient to avoid the race.
-  usleep(100000);
+  pid_t child_pid = SetupChildProcess(kNumberOfThreadsInHelperProgram);
+  ASSERT_NE(child_pid, -1);
 
   // Children are ready now.
   LinuxPtraceDumper dumper(child_pid);
   ASSERT_TRUE(dumper.Init());
   EXPECT_EQ((size_t)kNumberOfThreadsInHelperProgram, dumper.threads().size());
   EXPECT_TRUE(dumper.ThreadsSuspend());
 
   ThreadInfo one_thread;
@@ -463,8 +471,104 @@ TEST(LinuxPtraceDumperTest, VerifyStackR
   kill(child_pid, SIGKILL);
 
   // Reap child
   int status;
   ASSERT_NE(-1, HANDLE_EINTR(waitpid(child_pid, &status, 0)));
   ASSERT_TRUE(WIFSIGNALED(status));
   ASSERT_EQ(SIGKILL, WTERMSIG(status));
 }
+
+TEST_F(LinuxPtraceDumperTest, SanitizeStackCopy) {
+  static const int kNumberOfThreadsInHelperProgram = 1;
+
+  pid_t child_pid = SetupChildProcess(kNumberOfThreadsInHelperProgram);
+  ASSERT_NE(child_pid, -1);
+
+  LinuxPtraceDumper dumper(child_pid);
+  ASSERT_TRUE(dumper.Init());
+  EXPECT_TRUE(dumper.ThreadsSuspend());
+
+  ThreadInfo thread_info;
+  EXPECT_TRUE(dumper.GetThreadInfoByIndex(0, &thread_info));
+
+  const uintptr_t defaced =
+#if defined(__LP64__)
+      0x0defaced0defaced;
+#else
+      0x0defaced;
+#endif
+
+  uintptr_t simulated_stack[2];
+
+  // Pointers into the stack shouldn't be sanitized.
+  memset(simulated_stack, 0xff, sizeof(simulated_stack));
+  simulated_stack[1] = thread_info.stack_pointer;
+  dumper.SanitizeStackCopy(reinterpret_cast<uint8_t*>(&simulated_stack),
+                           sizeof(simulated_stack), thread_info.stack_pointer,
+                           sizeof(uintptr_t));
+  ASSERT_NE(simulated_stack[1], defaced);
+
+  // Memory prior to the stack pointer should be cleared.
+  ASSERT_EQ(simulated_stack[0], 0u);
+
+  // Small integers should not be sanitized.
+  for (int i = -4096; i <= 4096; ++i) {
+    memset(simulated_stack, 0, sizeof(simulated_stack));
+    simulated_stack[0] = static_cast<uintptr_t>(i);
+    dumper.SanitizeStackCopy(reinterpret_cast<uint8_t*>(&simulated_stack),
+                             sizeof(simulated_stack), thread_info.stack_pointer,
+                             0u);
+    ASSERT_NE(simulated_stack[0], defaced);
+  }
+
+  // The instruction pointer definitely should point into an executable mapping.
+  const MappingInfo* mapping_info = dumper.FindMappingNoBias(
+      reinterpret_cast<uintptr_t>(thread_info.GetInstructionPointer()));
+  ASSERT_NE(mapping_info, nullptr);
+  ASSERT_TRUE(mapping_info->exec);
+
+  // Pointers to code shouldn't be sanitized.
+  memset(simulated_stack, 0, sizeof(simulated_stack));
+  simulated_stack[1] = thread_info.GetInstructionPointer();
+  dumper.SanitizeStackCopy(reinterpret_cast<uint8_t*>(&simulated_stack),
+                           sizeof(simulated_stack), thread_info.stack_pointer,
+                           0u);
+  ASSERT_NE(simulated_stack[0], defaced);
+
+  // String fragments should be sanitized.
+  memcpy(simulated_stack, "abcdefghijklmnop", sizeof(simulated_stack));
+  dumper.SanitizeStackCopy(reinterpret_cast<uint8_t*>(&simulated_stack),
+                           sizeof(simulated_stack), thread_info.stack_pointer,
+                           0u);
+  ASSERT_EQ(simulated_stack[0], defaced);
+  ASSERT_EQ(simulated_stack[1], defaced);
+
+  // Heap pointers should be sanititzed.
+#if defined(__ARM_EABI__)
+  uintptr_t heap_addr = thread_info.regs.uregs[3];
+#elif defined(__aarch64__)
+  uintptr_t heap_addr = thread_info.regs.regs[3];
+#elif defined(__i386)
+  uintptr_t heap_addr = thread_info.regs.ecx;
+#elif defined(__x86_64)
+  uintptr_t heap_addr = thread_info.regs.rcx;
+#elif defined(__mips__)
+  uintptr_t heap_addr = thread_info.mcontext.gregs[1];
+#else
+#error This test has not been ported to this platform.
+#endif
+  memset(simulated_stack, 0, sizeof(simulated_stack));
+  simulated_stack[0] = heap_addr;
+  dumper.SanitizeStackCopy(reinterpret_cast<uint8_t*>(&simulated_stack),
+                           sizeof(simulated_stack), thread_info.stack_pointer,
+                           0u);
+  ASSERT_EQ(simulated_stack[0], defaced);
+
+  EXPECT_TRUE(dumper.ThreadsResume());
+  kill(child_pid, SIGKILL);
+
+  // Reap child.
+  int status;
+  ASSERT_NE(-1, HANDLE_EINTR(waitpid(child_pid, &status, 0)));
+  ASSERT_TRUE(WIFSIGNALED(status));
+  ASSERT_EQ(SIGKILL, WTERMSIG(status));
+}
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.cc
@@ -124,53 +124,103 @@ class MinidumpWriter {
   // (exclude the stack data).
   static const unsigned kLimitMinidumpFudgeFactor = 64 * 1024;
 
   MinidumpWriter(const char* minidump_path,
                  int minidump_fd,
                  const ExceptionHandler::CrashContext* context,
                  const MappingList& mappings,
                  const AppMemoryList& appmem,
+                 bool skip_stacks_if_mapping_unreferenced,
+                 uintptr_t principal_mapping_address,
+                 bool sanitize_stacks,
                  LinuxDumper* dumper)
       : fd_(minidump_fd),
         path_(minidump_path),
         ucontext_(context ? &context->context : NULL),
 #if !defined(__ARM_EABI__) && !defined(__mips__)
         float_state_(context ? &context->float_state : NULL),
 #endif
         dumper_(dumper),
         minidump_size_limit_(-1),
         memory_blocks_(dumper_->allocator()),
         mapping_list_(mappings),
-        app_memory_list_(appmem) {
+        app_memory_list_(appmem),
+        skip_stacks_if_mapping_unreferenced_(
+            skip_stacks_if_mapping_unreferenced),
+        principal_mapping_address_(principal_mapping_address),
+        principal_mapping_(nullptr),
+    sanitize_stacks_(sanitize_stacks) {
     // Assert there should be either a valid fd or a valid path, not both.
     assert(fd_ != -1 || minidump_path);
     assert(fd_ == -1 || !minidump_path);
   }
 
   bool Init() {
     if (!dumper_->Init())
       return false;
 
+    if (!dumper_->ThreadsSuspend() || !dumper_->LateInit())
+      return false;
+
+    if (skip_stacks_if_mapping_unreferenced_) {
+      principal_mapping_ =
+          dumper_->FindMappingNoBias(principal_mapping_address_);
+      if (!CrashingThreadReferencesPrincipalMapping())
+        return false;
+    }
+
     if (fd_ != -1)
       minidump_writer_.SetFile(fd_);
     else if (!minidump_writer_.Open(path_))
       return false;
 
-    return dumper_->ThreadsSuspend() && dumper_->LateInit();
+    return true;
   }
 
   ~MinidumpWriter() {
     // Don't close the file descriptor when it's been provided explicitly.
     // Callers might still need to use it.
     if (fd_ == -1)
       minidump_writer_.Close();
     dumper_->ThreadsResume();
   }
 
+  bool CrashingThreadReferencesPrincipalMapping() {
+    if (!ucontext_ || !principal_mapping_)
+      return false;
+
+    const uintptr_t low_addr =
+        principal_mapping_->system_mapping_info.start_addr;
+    const uintptr_t high_addr =
+        principal_mapping_->system_mapping_info.end_addr;
+
+    const uintptr_t stack_pointer = UContextReader::GetStackPointer(ucontext_);
+    const uintptr_t pc = UContextReader::GetInstructionPointer(ucontext_);
+
+    if (pc >= low_addr && pc < high_addr)
+      return true;
+
+    uint8_t* stack_copy;
+    const void* stack;
+    size_t stack_len;
+
+    if (!dumper_->GetStackInfo(&stack, &stack_len, stack_pointer))
+      return false;
+
+    stack_copy = reinterpret_cast<uint8_t*>(Alloc(stack_len));
+    dumper_->CopyFromProcess(stack_copy, GetCrashThread(), stack, stack_len);
+
+    uintptr_t stack_pointer_offset =
+        stack_pointer - reinterpret_cast<uintptr_t>(stack);
+
+    return dumper_->StackHasPointerToMapping(
+        stack_copy, stack_len, stack_pointer_offset, *principal_mapping_);
+  }
+
   bool Dump() {
     // A minidump file contains a number of tagged streams. This is the number
     // of stream which we write.
     unsigned kNumWriters = 13;
 
     TypedMDRVA<MDRawDirectory> dir(&minidump_writer_);
     {
       // Ensure the header gets flushed, as that happens in the destructor.
@@ -260,48 +310,70 @@ class MinidumpWriter {
     // If you add more directory entries, don't forget to update kNumWriters,
     // above.
 
     dumper_->ThreadsResume();
     return true;
   }
 
   bool FillThreadStack(MDRawThread* thread, uintptr_t stack_pointer,
-                       int max_stack_len, uint8_t** stack_copy) {
+                       uintptr_t pc, int max_stack_len, uint8_t** stack_copy) {
     *stack_copy = NULL;
     const void* stack;
     size_t stack_len;
+
+    thread->stack.start_of_memory_range = stack_pointer;
+    thread->stack.memory.data_size = 0;
+    thread->stack.memory.rva = minidump_writer_.position();
+
     if (dumper_->GetStackInfo(&stack, &stack_len, stack_pointer)) {
-      UntypedMDRVA memory(&minidump_writer_);
       if (max_stack_len >= 0 &&
           stack_len > static_cast<unsigned int>(max_stack_len)) {
         stack_len = max_stack_len;
         // Skip empty chunks of length max_stack_len.
         uintptr_t int_stack = reinterpret_cast<uintptr_t>(stack);
         if (max_stack_len > 0) {
           while (int_stack + max_stack_len < stack_pointer) {
             int_stack += max_stack_len;
           }
         }
         stack = reinterpret_cast<const void*>(int_stack);
       }
-      if (!memory.Allocate(stack_len))
-        return false;
       *stack_copy = reinterpret_cast<uint8_t*>(Alloc(stack_len));
       dumper_->CopyFromProcess(*stack_copy, thread->thread_id, stack,
                                stack_len);
+
+      uintptr_t stack_pointer_offset =
+          stack_pointer - reinterpret_cast<uintptr_t>(stack);
+      if (skip_stacks_if_mapping_unreferenced_) {
+        if (!principal_mapping_) {
+          return true;
+        }
+        uintptr_t low_addr = principal_mapping_->system_mapping_info.start_addr;
+        uintptr_t high_addr = principal_mapping_->system_mapping_info.end_addr;
+        if ((pc < low_addr || pc > high_addr) &&
+            !dumper_->StackHasPointerToMapping(*stack_copy, stack_len,
+                                               stack_pointer_offset,
+                                               *principal_mapping_)) {
+          return true;
+        }
+      }
+
+      if (sanitize_stacks_) {
+        dumper_->SanitizeStackCopy(*stack_copy, stack_len, stack_pointer,
+                                   stack_pointer_offset);
+      }
+
+      UntypedMDRVA memory(&minidump_writer_);
+      if (!memory.Allocate(stack_len))
+        return false;
       memory.Copy(*stack_copy, stack_len);
-      thread->stack.start_of_memory_range =
-          reinterpret_cast<uintptr_t>(stack);
+      thread->stack.start_of_memory_range = reinterpret_cast<uintptr_t>(stack);
       thread->stack.memory = memory.location();
       memory_blocks_.push_back(thread->stack);
-    } else {
-      thread->stack.start_of_memory_range = stack_pointer;
-      thread->stack.memory.data_size = 0;
-      thread->stack.memory.rva = minidump_writer_.position();
     }
     return true;
   }
 
   // Write information about the threads.
   bool WriteThreadListStream(MDRawDirectory* dirent) {
     const unsigned num_threads = dumper_->threads().size();
 
@@ -338,17 +410,19 @@ class MinidumpWriter {
       // we used the actual state of the thread we would find it running in the
       // signal handler with the alternative stack, which would be deeply
       // unhelpful.
       if (static_cast<pid_t>(thread.thread_id) == GetCrashThread() &&
           ucontext_ &&
           !dumper_->IsPostMortem()) {
         uint8_t* stack_copy;
         const uintptr_t stack_ptr = UContextReader::GetStackPointer(ucontext_);
-        if (!FillThreadStack(&thread, stack_ptr, -1, &stack_copy))
+        if (!FillThreadStack(&thread, stack_ptr,
+                             UContextReader::GetInstructionPointer(ucontext_),
+                             -1, &stack_copy))
           return false;
 
         // Copy 256 bytes around crashing instruction pointer to minidump.
         const size_t kIPMemorySize = 256;
         uint64_t ip = UContextReader::GetInstructionPointer(ucontext_);
         // Bound it to the upper and lower bounds of the memory map
         // it's contained within. If it's not in mapped memory,
         // don't bother trying to write it.
@@ -404,18 +478,19 @@ class MinidumpWriter {
         ThreadInfo info;
         if (!dumper_->GetThreadInfoByIndex(i, &info))
           return false;
 
         uint8_t* stack_copy;
         int max_stack_len = -1;  // default to no maximum for this thread
         if (minidump_size_limit_ >= 0 && i >= kLimitBaseThreadCount)
           max_stack_len = extra_thread_stack_len;
-        if (!FillThreadStack(&thread, info.stack_pointer, max_stack_len,
-            &stack_copy))
+        if (!FillThreadStack(&thread, info.stack_pointer,
+                             info.GetInstructionPointer(), max_stack_len,
+                             &stack_copy))
           return false;
 
         TypedMDRVA<RawContextCPU> cpu(&minidump_writer_);
         if (!cpu.Allocate())
           return false;
         my_memset(cpu.get(), 0, sizeof(RawContextCPU));
         info.FillCPUContext(cpu.get());
         thread.thread_context = cpu.location();
@@ -621,25 +696,28 @@ class MinidumpWriter {
     }
     return true;
   }
 
   bool WriteExceptionStream(MDRawDirectory* dirent) {
     TypedMDRVA<MDRawExceptionStream> exc(&minidump_writer_);
     if (!exc.Allocate())
       return false;
-    my_memset(exc.get(), 0, sizeof(MDRawExceptionStream));
+
+    MDRawExceptionStream* stream = exc.get();
+    my_memset(stream, 0, sizeof(MDRawExceptionStream));
 
     dirent->stream_type = MD_EXCEPTION_STREAM;
     dirent->location = exc.location();
 
-    exc.get()->thread_id = GetCrashThread();
-    exc.get()->exception_record.exception_code = dumper_->crash_signal();
-    exc.get()->exception_record.exception_address = dumper_->crash_address();
-    exc.get()->thread_context = crashing_thread_context_;
+    stream->thread_id = GetCrashThread();
+    stream->exception_record.exception_code = dumper_->crash_signal();
+    stream->exception_record.exception_flags = dumper_->crash_signal_code();
+    stream->exception_record.exception_address = dumper_->crash_address();
+    stream->thread_context = crashing_thread_context_;
 
     return true;
   }
 
   bool WriteSystemInfoStream(MDRawDirectory* dirent) {
     TypedMDRVA<MDRawSystemInfo> si(&minidump_writer_);
     if (!si.Allocate())
       return false;
@@ -1259,118 +1337,164 @@ class MinidumpWriter {
   // written while writing the thread list stream, but saved here
   // so a memory list stream can be written afterwards.
   wasteful_vector<MDMemoryDescriptor> memory_blocks_;
   // Additional information about some mappings provided by the caller.
   const MappingList& mapping_list_;
   // Additional memory regions to be included in the dump,
   // provided by the caller.
   const AppMemoryList& app_memory_list_;
+  // If set, skip recording any threads that do not reference the
+  // mapping containing principal_mapping_address_.
+  bool skip_stacks_if_mapping_unreferenced_;
+  uintptr_t principal_mapping_address_;
+  const MappingInfo* principal_mapping_;
+  // If true, apply stack sanitization to stored stack data.
+  bool sanitize_stacks_;
 };
 
 
 bool WriteMinidumpImpl(const char* minidump_path,
                        int minidump_fd,
                        off_t minidump_size_limit,
                        pid_t crashing_process,
                        const void* blob, size_t blob_size,
                        const MappingList& mappings,
-                       const AppMemoryList& appmem) {
+                       const AppMemoryList& appmem,
+                       bool skip_stacks_if_mapping_unreferenced,
+                       uintptr_t principal_mapping_address,
+                       bool sanitize_stacks) {
   LinuxPtraceDumper dumper(crashing_process);
   const ExceptionHandler::CrashContext* context = NULL;
   if (blob) {
     if (blob_size != sizeof(ExceptionHandler::CrashContext))
       return false;
     context = reinterpret_cast<const ExceptionHandler::CrashContext*>(blob);
-    dumper.set_crash_address(
-        reinterpret_cast<uintptr_t>(context->siginfo.si_addr));
-    dumper.set_crash_signal(context->siginfo.si_signo);
+    dumper.SetCrashInfoFromSigInfo(context->siginfo);
     dumper.set_crash_thread(context->tid);
   }
   MinidumpWriter writer(minidump_path, minidump_fd, context, mappings,
-                        appmem, &dumper);
+                        appmem, skip_stacks_if_mapping_unreferenced,
+                        principal_mapping_address, sanitize_stacks, &dumper);
   // Set desired limit for file size of minidump (-1 means no limit).
   writer.set_minidump_size_limit(minidump_size_limit);
   if (!writer.Init())
     return false;
   return writer.Dump();
 }
 
 }  // namespace
 
 namespace google_breakpad {
 
 bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
-                   const void* blob, size_t blob_size) {
+                   const void* blob, size_t blob_size,
+                   bool skip_stacks_if_mapping_unreferenced,
+                   uintptr_t principal_mapping_address,
+                   bool sanitize_stacks) {
   return WriteMinidumpImpl(minidump_path, -1, -1,
                            crashing_process, blob, blob_size,
-                           MappingList(), AppMemoryList());
+                           MappingList(), AppMemoryList(),
+                           skip_stacks_if_mapping_unreferenced,
+                           principal_mapping_address,
+                           sanitize_stacks);
 }
 
 bool WriteMinidump(int minidump_fd, pid_t crashing_process,
-                   const void* blob, size_t blob_size) {
+                   const void* blob, size_t blob_size,
+                   bool skip_stacks_if_mapping_unreferenced,
+                   uintptr_t principal_mapping_address,
+                   bool sanitize_stacks) {
   return WriteMinidumpImpl(NULL, minidump_fd, -1,
                            crashing_process, blob, blob_size,
-                           MappingList(), AppMemoryList());
+                           MappingList(), AppMemoryList(),
+                           skip_stacks_if_mapping_unreferenced,
+                           principal_mapping_address,
+                           sanitize_stacks);
 }
 
 bool WriteMinidump(const char* minidump_path, pid_t process,
                    pid_t process_blamed_thread) {
   LinuxPtraceDumper dumper(process);
   // MinidumpWriter will set crash address
   dumper.set_crash_signal(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED);
   dumper.set_crash_thread(process_blamed_thread);
   MinidumpWriter writer(minidump_path, -1, NULL, MappingList(),
-                        AppMemoryList(), &dumper);
+                        AppMemoryList(), false, 0, false, &dumper);
   if (!writer.Init())
     return false;
   return writer.Dump();
 }
 
 bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
                    const void* blob, size_t blob_size,
                    const MappingList& mappings,
-                   const AppMemoryList& appmem) {
+                   const AppMemoryList& appmem,
+                   bool skip_stacks_if_mapping_unreferenced,
+                   uintptr_t principal_mapping_address,
+                   bool sanitize_stacks) {
   return WriteMinidumpImpl(minidump_path, -1, -1, crashing_process,
                            blob, blob_size,
-                           mappings, appmem);
+                           mappings, appmem,
+                           skip_stacks_if_mapping_unreferenced,
+                           principal_mapping_address,
+                           sanitize_stacks);
 }
 
 bool WriteMinidump(int minidump_fd, pid_t crashing_process,
                    const void* blob, size_t blob_size,
                    const MappingList& mappings,
-                   const AppMemoryList& appmem) {
+                   const AppMemoryList& appmem,
+                   bool skip_stacks_if_mapping_unreferenced,
+                   uintptr_t principal_mapping_address,
+                   bool sanitize_stacks) {
   return WriteMinidumpImpl(NULL, minidump_fd, -1, crashing_process,
                            blob, blob_size,
-                           mappings, appmem);
+                           mappings, appmem,
+                           skip_stacks_if_mapping_unreferenced,
+                           principal_mapping_address,
+                           sanitize_stacks);
 }
 
 bool WriteMinidump(const char* minidump_path, off_t minidump_size_limit,
                    pid_t crashing_process,
                    const void* blob, size_t blob_size,
                    const MappingList& mappings,
-                   const AppMemoryList& appmem) {
+                   const AppMemoryList& appmem,
+                   bool skip_stacks_if_mapping_unreferenced,
+                   uintptr_t principal_mapping_address,
+                   bool sanitize_stacks) {
   return WriteMinidumpImpl(minidump_path, -1, minidump_size_limit,
                            crashing_process, blob, blob_size,
-                           mappings, appmem);
+                           mappings, appmem,
+                           skip_stacks_if_mapping_unreferenced,
+                           principal_mapping_address,
+                           sanitize_stacks);
 }
 
 bool WriteMinidump(int minidump_fd, off_t minidump_size_limit,
                    pid_t crashing_process,
                    const void* blob, size_t blob_size,
                    const MappingList& mappings,
-                   const AppMemoryList& appmem) {
+                   const AppMemoryList& appmem,
+                   bool skip_stacks_if_mapping_unreferenced,
+                   uintptr_t principal_mapping_address,
+                   bool sanitize_stacks) {
   return WriteMinidumpImpl(NULL, minidump_fd, minidump_size_limit,
                            crashing_process, blob, blob_size,
-                           mappings, appmem);
+                           mappings, appmem,
+                           skip_stacks_if_mapping_unreferenced,
+                           principal_mapping_address,
+                           sanitize_stacks);
 }
 
 bool WriteMinidump(const char* filename,
                    const MappingList& mappings,
                    const AppMemoryList& appmem,
                    LinuxDumper* dumper) {
-  MinidumpWriter writer(filename, -1, NULL, mappings, appmem, dumper);
+  MinidumpWriter writer(filename, -1, NULL, mappings, appmem,
+                        false, 0, false, dumper);
   if (!writer.Init())
     return false;
   return writer.Dump();
 }
 
 }  // namespace google_breakpad
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.h
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.h
@@ -73,51 +73,69 @@ typedef std::list<AppMemory> AppMemoryLi
 //   minidump_path: the path to the file to write to. This is opened O_EXCL and
 //     fails open fails.
 //   crashing_process: the pid of the crashing process. This must be trusted.
 //   blob: a blob of data from the crashing process. See exception_handler.h
 //   blob_size: the length of |blob|, in bytes
 //
 // Returns true iff successful.
 bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
-                   const void* blob, size_t blob_size);
+                   const void* blob, size_t blob_size,
+                   bool skip_stacks_if_mapping_unreferenced = false,
+                   uintptr_t principal_mapping_address = 0,
+                   bool sanitize_stacks = false);
 // Same as above but takes an open file descriptor instead of a path.
 bool WriteMinidump(int minidump_fd, pid_t crashing_process,
-                   const void* blob, size_t blob_size);
+                   const void* blob, size_t blob_size,
+                   bool skip_stacks_if_mapping_unreferenced = false,
+                   uintptr_t principal_mapping_address = 0,
+                   bool sanitize_stacks = false);
 
 // Alternate form of WriteMinidump() that works with processes that
 // are not expected to have crashed.  If |process_blamed_thread| is
 // meaningful, it will be the one from which a crash signature is
 // extracted.  It is not expected that this function will be called
 // from a compromised context, but it is safe to do so.
 bool WriteMinidump(const char* minidump_path, pid_t process,
                    pid_t process_blamed_thread);
 
 // These overloads also allow passing a list of known mappings and
 // a list of additional memory regions to be included in the minidump.
 bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
                    const void* blob, size_t blob_size,
                    const MappingList& mappings,
-                   const AppMemoryList& appdata);
+                   const AppMemoryList& appdata,
+                   bool skip_stacks_if_mapping_unreferenced = false,
+                   uintptr_t principal_mapping_address = 0,
+                   bool sanitize_stacks = false);
 bool WriteMinidump(int minidump_fd, pid_t crashing_process,
                    const void* blob, size_t blob_size,
                    const MappingList& mappings,
-                   const AppMemoryList& appdata);
+                   const AppMemoryList& appdata,
+                   bool skip_stacks_if_mapping_unreferenced = false,
+                   uintptr_t principal_mapping_address = 0,
+                   bool sanitize_stacks = false);
 
 // These overloads also allow passing a file size limit for the minidump.
 bool WriteMinidump(const char* minidump_path, off_t minidump_size_limit,
                    pid_t crashing_process,
                    const void* blob, size_t blob_size,
                    const MappingList& mappings,
-                   const AppMemoryList& appdata);
+                   const AppMemoryList& appdata,
+                   bool skip_stacks_if_mapping_unreferenced = false,
+                   uintptr_t principal_mapping_address = 0,
+                   bool sanitize_stacks = false);
 bool WriteMinidump(int minidump_fd, off_t minidump_size_limit,
                    pid_t crashing_process,
                    const void* blob, size_t blob_size,
                    const MappingList& mappings,
-                   const AppMemoryList& appdata);
+                   const AppMemoryList& appdata,
+                   bool skip_stacks_if_mapping_unreferenced = false,
+                   uintptr_t principal_mapping_address = 0,
+                   bool sanitize_stacks = false);
 
 bool WriteMinidump(const char* filename,
                    const MappingList& mappings,
                    const AppMemoryList& appdata,
                    LinuxDumper* dumper);
 
 }  // namespace google_breakpad
 
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest.cc
@@ -65,46 +65,47 @@ TEST(MinidumpWriterTest, SetupWithPath) 
   ASSERT_NE(-1, pipe(fds));
 
   const pid_t child = fork();
   if (child == 0) {
     close(fds[1]);
     char b;
     IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
     close(fds[0]);
-    syscall(__NR_exit);
+    syscall(__NR_exit_group);
   }
   close(fds[0]);
 
   ExceptionHandler::CrashContext context;
   memset(&context, 0, sizeof(context));
 
   AutoTempDir temp_dir;
   string templ = temp_dir.path() + kMDWriterUnitTestFileName;
   // Set a non-zero tid to avoid tripping asserts.
   context.tid = child;
   ASSERT_TRUE(WriteMinidump(templ.c_str(), child, &context, sizeof(context)));
   struct stat st;
   ASSERT_EQ(0, stat(templ.c_str(), &st));
   ASSERT_GT(st.st_size, 0);
 
   close(fds[1]);
+  IGNORE_EINTR(waitpid(child, nullptr, 0));
 }
 
 TEST(MinidumpWriterTest, SetupWithFD) {
   int fds[2];
   ASSERT_NE(-1, pipe(fds));
 
   const pid_t child = fork();
   if (child == 0) {
     close(fds[1]);
     char b;
     HANDLE_EINTR(read(fds[0], &b, sizeof(b)));
     close(fds[0]);
-    syscall(__NR_exit);
+    syscall(__NR_exit_group);
   }
   close(fds[0]);
 
   ExceptionHandler::CrashContext context;
   memset(&context, 0, sizeof(context));
 
   AutoTempDir temp_dir;
   string templ = temp_dir.path() + kMDWriterUnitTestFileName;
@@ -112,16 +113,17 @@ TEST(MinidumpWriterTest, SetupWithFD) {
   // Set a non-zero tid to avoid tripping asserts.
   context.tid = child;
   ASSERT_TRUE(WriteMinidump(fd, child, &context, sizeof(context)));
   struct stat st;
   ASSERT_EQ(0, stat(templ.c_str(), &st));
   ASSERT_GT(st.st_size, 0);
 
   close(fds[1]);
+  IGNORE_EINTR(waitpid(child, nullptr, 0));
 }
 
 // Test that mapping info can be specified when writing a minidump,
 // and that it ends up in the module list of the minidump.
 TEST(MinidumpWriterTest, MappingInfo) {
   int fds[2];
   ASSERT_NE(-1, pipe(fds));
 
@@ -147,17 +149,17 @@ TEST(MinidumpWriterTest, MappingInfo) {
   ASSERT_TRUE(memory);
 
   const pid_t child = fork();
   if (child == 0) {
     close(fds[1]);
     char b;
     IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
     close(fds[0]);
-    syscall(__NR_exit);
+    syscall(__NR_exit_group);
   }
   close(fds[0]);
 
   ExceptionHandler::CrashContext context;
   memset(&context, 0, sizeof(context));
   ASSERT_EQ(0, getcontext(&context.context));
   context.tid = child;
 
@@ -174,17 +176,17 @@ TEST(MinidumpWriterTest, MappingInfo) {
 
   MappingList mappings;
   AppMemoryList memory_list;
   MappingEntry mapping;
   mapping.first = info;
   memcpy(mapping.second, kModuleGUID, sizeof(MDGUID));
   mappings.push_back(mapping);
   ASSERT_TRUE(WriteMinidump(templ.c_str(), child, &context, sizeof(context),
-                            mappings, memory_list));
+                            mappings, memory_list, false, 0, false));
 
   // Read the minidump. Load the module list, and ensure that
   // the mmap'ed |memory| is listed with the given module name
   // and debug ID.
   Minidump minidump(templ);
   ASSERT_TRUE(minidump.Read());
 
   MinidumpModuleList* module_list = minidump.GetModuleList();
@@ -208,33 +210,177 @@ TEST(MinidumpWriterTest, MappingInfo) {
   EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_PROC_STATUS, &len));
   EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_CMD_LINE, &len));
   EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_ENVIRON, &len));
   EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_AUXV, &len));
   EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_MAPS, &len));
   EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_DSO_DEBUG, &len));
 
   close(fds[1]);
+  IGNORE_EINTR(waitpid(child, nullptr, 0));
+}
+
+// Test that minidumping is skipped while writing minidumps if principal mapping
+// is not referenced.
+TEST(MinidumpWriterTest, MinidumpSkippedIfRequested) {
+  int fds[2];
+  ASSERT_NE(-1, pipe(fds));
+
+  const pid_t child = fork();
+  if (child == 0) {
+    close(fds[1]);
+    char b;
+    IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
+    close(fds[0]);
+    syscall(__NR_exit_group);
+  }
+  close(fds[0]);
+
+  ExceptionHandler::CrashContext context;
+  memset(&context, 0, sizeof(context));
+  ASSERT_EQ(0, getcontext(&context.context));
+  context.tid = child;
+
+  AutoTempDir temp_dir;
+  string templ = temp_dir.path() + kMDWriterUnitTestFileName;
+
+  // pass an invalid principal mapping address, which will force
+  // WriteMinidump to not write a minidump.
+  ASSERT_FALSE(WriteMinidump(templ.c_str(), child, &context, sizeof(context),
+                            true, static_cast<uintptr_t>(0x0102030405060708ull),
+                            false));
+  close(fds[1]);
+  IGNORE_EINTR(waitpid(child, nullptr, 0));
+}
+
+// Test that minidumping is skipped while writing minidumps if principal mapping
+// is not referenced.
+TEST(MinidumpWriterTest, MinidumpStacksSkippedIfRequested) {
+  int fds[2];
+  ASSERT_NE(-1, pipe(fds));
+
+  const pid_t child = fork();
+  if (child == 0) {
+    close(fds[1]);
+
+    // Create a thread that does not return, and only references libc (not the
+    // current executable). This thread should not be captured in the minidump.
+    pthread_t thread;
+    pthread_attr_t thread_attributes;
+    pthread_attr_init(&thread_attributes);
+    pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_DETACHED);
+    sigset_t sigset;
+    sigemptyset(&sigset);
+    pthread_create(&thread, &thread_attributes,
+                   reinterpret_cast<void* (*)(void*)>(&sigsuspend), &sigset);
+
+    char b;
+    IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
+    close(fds[0]);
+    syscall(__NR_exit_group);
+  }
+  close(fds[0]);
+
+  ExceptionHandler::CrashContext context;
+  memset(&context, 0, sizeof(context));
+  ASSERT_EQ(0, getcontext(&context.context));
+  context.tid = child;
+
+  AutoTempDir temp_dir;
+  string templ = temp_dir.path() + kMDWriterUnitTestFileName;
+
+  // Pass an invalid principal mapping address, which will force
+  // WriteMinidump to not dump any thread stacks.
+  ASSERT_TRUE(WriteMinidump(
+      templ.c_str(), child, &context, sizeof(context), true,
+      reinterpret_cast<uintptr_t>(google_breakpad::WriteFile), false));
+
+  // Read the minidump. And ensure that thread memory was dumped only for the
+  // main thread.
+  Minidump minidump(templ);
+  ASSERT_TRUE(minidump.Read());
+
+  MinidumpThreadList *threads = minidump.GetThreadList();
+  int threads_with_stacks = 0;
+  for (unsigned int i = 0; i < threads->thread_count(); ++i) {
+    MinidumpThread *thread = threads->GetThreadAtIndex(i);
+    if (thread->GetMemory()) {
+      ++threads_with_stacks;
+    }
+  }
+  ASSERT_EQ(1, threads_with_stacks);
+  close(fds[1]);
+  IGNORE_EINTR(waitpid(child, nullptr, 0));
+}
+
+// Test that stacks can be sanitized while writing minidumps.
+TEST(MinidumpWriterTest, StacksAreSanitizedIfRequested) {
+  int fds[2];
+  ASSERT_NE(-1, pipe(fds));
+
+  const pid_t child = fork();
+  if (child == 0) {
+    close(fds[1]);
+    char b;
+    IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
+    close(fds[0]);
+    syscall(__NR_exit_group);
+  }
+  close(fds[0]);
+
+  ExceptionHandler::CrashContext context;
+  memset(&context, 0, sizeof(context));
+  ASSERT_EQ(0, getcontext(&context.context));
+  context.tid = child;
+
+  AutoTempDir temp_dir;
+  string templ = temp_dir.path() + kMDWriterUnitTestFileName;
+  // pass an invalid principal mapping address, which will force
+  // WriteMinidump to not dump any thread stacks.
+  ASSERT_TRUE(WriteMinidump(templ.c_str(), child, &context, sizeof(context),
+                            false, 0, true));
+
+  // Read the minidump. And ensure that thread memory contains a defaced value.
+  Minidump minidump(templ);
+  ASSERT_TRUE(minidump.Read());
+
+  const uintptr_t defaced =
+#if defined(__LP64__)
+      0x0defaced0defaced;
+#else
+      0x0defaced;
+#endif
+  MinidumpThreadList *threads = minidump.GetThreadList();
+  for (unsigned int i = 0; i < threads->thread_count(); ++i) {
+    MinidumpThread *thread = threads->GetThreadAtIndex(i);
+    MinidumpMemoryRegion *mem = thread->GetMemory();
+    ASSERT_TRUE(mem != nullptr);
+    uint32_t sz = mem->GetSize();
+    const uint8_t *data = mem->GetMemory();
+    ASSERT_TRUE(memmem(data, sz, &defaced, sizeof(defaced)) != nullptr);
+  }
+  close(fds[1]);
+  IGNORE_EINTR(waitpid(child, nullptr, 0));
 }
 
 // Test that a binary with a longer-than-usual build id note
 // makes its way all the way through to the minidump unscathed.
 // The linux_client_unittest is linked with an explicit --build-id
 // in Makefile.am.
 TEST(MinidumpWriterTest, BuildIDLong) {
   int fds[2];
   ASSERT_NE(-1, pipe(fds));
 
   const pid_t child = fork();
   if (child == 0) {
     close(fds[1]);
     char b;
     IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
     close(fds[0]);
-    syscall(__NR_exit);
+    syscall(__NR_exit_group);
   }
   close(fds[0]);
 
   ExceptionHandler::CrashContext context;
   memset(&context, 0, sizeof(context));
   ASSERT_EQ(0, getcontext(&context.context));
   context.tid = child;
 
@@ -255,16 +401,18 @@ TEST(MinidumpWriterTest, BuildIDLong) {
   const MinidumpModule* module = module_list->GetMainModule();
   ASSERT_TRUE(module);
   const string module_identifier = "030201000504070608090A0B0C0D0E0F0";
   // This is passed explicitly to the linker in Makefile.am
   const string build_id =
       "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
   EXPECT_EQ(module_identifier, module->debug_identifier());
   EXPECT_EQ(build_id, module->code_identifier());
+
+  IGNORE_EINTR(waitpid(child, nullptr, 0));
 }
 
 // Test that mapping info can be specified, and that it overrides
 // existing mappings that are wholly contained within the specified
 // range.
 TEST(MinidumpWriterTest, MappingInfoContained) {
   int fds[2];
   ASSERT_NE(-1, pipe(fds));
@@ -303,17 +451,17 @@ TEST(MinidumpWriterTest, MappingInfoCont
   close(fd);
 
   const pid_t child = fork();
   if (child == 0) {
     close(fds[1]);
     char b;
     IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
     close(fds[0]);
-    syscall(__NR_exit);
+    syscall(__NR_exit_group);
   }
   close(fds[0]);
 
   ExceptionHandler::CrashContext context;
   memset(&context, 0, sizeof(context));
   context.tid = 1;
 
   string dumpfile = temp_dir.path() + kMDWriterUnitTestFileName;
@@ -349,16 +497,17 @@ TEST(MinidumpWriterTest, MappingInfoCont
   ASSERT_TRUE(module);
 
   EXPECT_EQ(info.start_addr, module->base_address());
   EXPECT_EQ(info.size, module->size());
   EXPECT_EQ(kMemoryName, module->code_file());
   EXPECT_EQ(module_identifier, module->debug_identifier());
 
   close(fds[1]);
+  IGNORE_EINTR(waitpid(child, nullptr, 0));
 }
 
 TEST(MinidumpWriterTest, DeletedBinary) {
   const string kNumberOfThreadsArgument = "1";
   const string helper_path(GetHelperBinary());
   if (helper_path.empty()) {
     FAIL() << "Couldn't find helper binary";
     exit(1);
@@ -440,16 +589,18 @@ TEST(MinidumpWriterTest, DeletedBinary) 
   size_t pos;
   while ((pos = module_identifier.find('-')) != string::npos) {
     module_identifier.erase(pos, 1);
   }
   // And append a zero, because module IDs include an "age" field
   // which is always zero on Linux.
   module_identifier += "0";
   EXPECT_EQ(module_identifier, module->debug_identifier());
+
+  IGNORE_EINTR(waitpid(child_pid, nullptr, 0));
 }
 
 // Test that an additional memory region can be added to the minidump.
 TEST(MinidumpWriterTest, AdditionalMemory) {
   int fds[2];
   ASSERT_NE(-1, pipe(fds));
 
   // These are defined here so the parent can use them to check the
@@ -467,17 +618,17 @@ TEST(MinidumpWriterTest, AdditionalMemor
   }
 
   const pid_t child = fork();
   if (child == 0) {
     close(fds[1]);
     char b;
     HANDLE_EINTR(read(fds[0], &b, sizeof(b)));
     close(fds[0]);
-    syscall(__NR_exit);
+    syscall(__NR_exit_group);
   }
   close(fds[0]);
 
   ExceptionHandler::CrashContext context;
 
   // This needs a valid context for minidump writing to work, but getting
   // a useful one from the child is too much work, so just use one from
   // the parent since the child is just a forked copy anyway.
@@ -512,30 +663,31 @@ TEST(MinidumpWriterTest, AdditionalMemor
   EXPECT_EQ(kMemoryAddress, region->GetBase());
   EXPECT_EQ(kMemorySize, region->GetSize());
 
   // Verify memory contents.
   EXPECT_EQ(0, memcmp(region->GetMemory(), memory, kMemorySize));
 
   delete[] memory;
   close(fds[1]);
+  IGNORE_EINTR(waitpid(child, nullptr, 0));
 }
 
 // Test that an invalid thread stack pointer still results in a minidump.
 TEST(MinidumpWriterTest, InvalidStackPointer) {
   int fds[2];
   ASSERT_NE(-1, pipe(fds));
 
   const pid_t child = fork();
   if (child == 0) {
     close(fds[1]);
     char b;
     HANDLE_EINTR(read(fds[0], &b, sizeof(b)));
     close(fds[0]);
-    syscall(__NR_exit);
+    syscall(__NR_exit_group);
   }
   close(fds[0]);
 
   ExceptionHandler::CrashContext context;
 
   // This needs a valid context for minidump writing to work, but getting
   // a useful one from the child is too much work, so just use one from
   // the parent since the child is just a forked copy anyway.
@@ -591,16 +743,17 @@ TEST(MinidumpWriterTest, InvalidStackPoi
     }
   }
   // NOTE: If you fail this, first make sure that "invalid_stack_pointer"
   // above is indeed set to an invalid address.
   ASSERT_TRUE(found_empty_stack);
 #endif
 
   close(fds[1]);
+  IGNORE_EINTR(waitpid(child, nullptr, 0));
 }
 
 // Test that limiting the size of the minidump works.
 TEST(MinidumpWriterTest, MinidumpSizeLimit) {
   static const int kNumberOfThreadsInHelperProgram = 40;
 
   char number_of_threads_arg[3];
   sprintf(number_of_threads_arg, "%d", kNumberOfThreadsInHelperProgram);
@@ -765,11 +918,12 @@ TEST(MinidumpWriterTest, MinidumpSizeLim
     const int min_expected_reduction = (kNumberOfThreadsInHelperProgram -
         kLimitBaseThreadCount) * kMinPerExtraThreadStackReduction;
     EXPECT_LT(total_limit_stack_size,
               total_normal_stack_size - min_expected_reduction);
   }
 
   // Kill the helper program.
   kill(child_pid, SIGKILL);
+  IGNORE_EINTR(waitpid(child_pid, nullptr, 0));
 }
 
 }  // namespace
--- a/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.h
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.h
@@ -27,16 +27,17 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // breakpad_nlist.h
 //
 // This file is meant to provide a header for clients of the modified
 // nlist function implemented to work on 64-bit.
 
 #ifndef CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__
+#define CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__
 
 #include <mach/machine.h>
 
 int breakpad_nlist(const char *name,
                    struct nlist *list,
                    const char **symbolNames,
                    cpu_type_t cpu_type);
 int breakpad_nlist(const char *name,
--- a/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc
@@ -121,17 +121,17 @@ EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARIT
 
 #if !TARGET_OS_IPHONE
 extern "C" {
   // Forward declarations for functions that need "C" style compilation
   boolean_t exc_server(mach_msg_header_t* request,
                        mach_msg_header_t* reply);
 
   // This symbol must be visible to dlsym() - see
-  // http://code.google.com/p/google-breakpad/issues/detail?id=345 for details.
+  // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=345 for details.
   kern_return_t catch_exception_raise(mach_port_t target_port,
                                       mach_port_t failed_thread,
                                       mach_port_t task,
                                       exception_type_t exception,
                                       exception_data_t code,
                                       mach_msg_type_number_t code_count)
       __attribute__((visibility("default")));
 }
@@ -351,16 +351,21 @@ bool ExceptionHandler::WriteMinidumpWith
     int exception_code,
     int exception_subcode,
     breakpad_ucontext_t* task_context,
     mach_port_t thread_name,
     bool exit_after_write,
     bool report_current_thread) {
   bool result = false;
 
+#if TARGET_OS_IPHONE
+  // _exit() should never be called on iOS.
+  exit_after_write = false;
+#endif
+
   if (directCallback_) {
     if (directCallback_(callback_context_,
                         exception_type,
                         exception_code,
                         exception_subcode,
                         thread_name) ) {
       if (exit_after_write)
         _exit(exception_type);
@@ -454,17 +459,17 @@ kern_return_t ForwardException(mach_port
     exit(KERN_FAILURE);
   }
 
   mach_port_t target_port = current.ports[found];
   exception_behavior_t target_behavior = current.behaviors[found];
 
   kern_return_t result;
   // TODO: Handle the case where |target_behavior| has MACH_EXCEPTION_CODES
-  // set. https://code.google.com/p/google-breakpad/issues/detail?id=551
+  // set. https://bugs.chromium.org/p/google-breakpad/issues/detail?id=551
   switch (target_behavior) {
     case EXCEPTION_DEFAULT:
       result = exception_raise(target_port, failed_thread, task, exception,
                                code, code_count);
       break;
     default:
       fprintf(stderr, "** Unknown exception behavior: %d\n", target_behavior);
       result = KERN_FAILURE;
--- a/toolkit/crashreporter/breakpad-client/mac/handler/minidump_test.xcodeproj/project.pbxproj
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_test.xcodeproj/project.pbxproj
@@ -63,17 +63,17 @@
 		D2F6511E0BEF973600920385 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FC0BEF947200920385 /* macho_id.cc */; };
 		D2F6511F0BEF973900920385 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FE0BEF947200920385 /* macho_utilities.cc */; };
 		D2F651210BEF975400920385 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F6510C0BEF94EB00920385 /* macho_walker.cc */; };
 		F93A887D0E8B4C8C0026AF89 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F6510C0BEF94EB00920385 /* macho_walker.cc */; };
 		F93A887E0E8B4C8C0026AF89 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FC0BEF947200920385 /* macho_id.cc */; };
 		F93A887F0E8B4C8C0026AF89 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FE0BEF947200920385 /* macho_utilities.cc */; };
 		F93A88800E8B4C8C0026AF89 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FA0BEF947200920385 /* file_id.cc */; };
 		F93A88860E8B4C9A0026AF89 /* dwarftests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F9721F310E8B07E800D7E813 /* dwarftests.mm */; };
-		F93A88870E8B4C9A0026AF89 /* dump_syms.mm in Sources */ = {isa = PBXBuildFile; fileRef = F9721F390E8B0D0D00D7E813 /* dump_syms.mm */; };
+		F93A88870E8B4C9A0026AF89 /* dump_syms.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F390E8B0D0D00D7E813 /* dump_syms.cc */; };
 		F93A88880E8B4C9A0026AF89 /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F760E8B0DC700D7E813 /* bytereader.cc */; };
 		F93A88890E8B4C9A0026AF89 /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */; };
 		F93A888A0E8B4C9A0026AF89 /* functioninfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F780E8B0DC700D7E813 /* functioninfo.cc */; };
 		F93A888B0E8B4C9A0026AF89 /* md5.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721FA80E8B0E4800D7E813 /* md5.cc */; };
 		F9721F6C0E8B0D7000D7E813 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */; };
 		F9721FA20E8B0E2300D7E813 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */; };
 		F982089C0DB3280D0017AECA /* breakpad_nlist_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */; };
 		F98208A30DB32CAE0017AECA /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */; };
@@ -146,17 +146,17 @@
 		D2F6510D0BEF94EB00920385 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; };
 		F917C4F70E03265A00F86017 /* breakpad_exc_server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = breakpad_exc_server.c; sourceTree = "<group>"; };
 		F917C4F80E03265A00F86017 /* breakpad_exc_server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_exc_server.h; sourceTree = "<group>"; };
 		F93A88750E8B4C700026AF89 /* octestcases.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = octestcases.octest; sourceTree = BUILT_PRODUCTS_DIR; };
 		F93A88760E8B4C700026AF89 /* obj-cTestCases-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "obj-cTestCases-Info.plist"; sourceTree = "<group>"; };
 		F9721F300E8B07E800D7E813 /* dwarftests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dwarftests.h; sourceTree = "<group>"; };
 		F9721F310E8B07E800D7E813 /* dwarftests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = dwarftests.mm; sourceTree = "<group>"; };
 		F9721F380E8B0CFC00D7E813 /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = SOURCE_ROOT; };
-		F9721F390E8B0D0D00D7E813 /* dump_syms.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = dump_syms.mm; path = ../../../common/mac/dump_syms.mm; sourceTree = SOURCE_ROOT; };
+		F9721F390E8B0D0D00D7E813 /* dump_syms.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = dump_syms.cc; path = ../../../common/mac/dump_syms.cc; sourceTree = SOURCE_ROOT; };
 		F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
 		F9721F760E8B0DC700D7E813 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
 		F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
 		F9721F780E8B0DC700D7E813 /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
 		F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
 		F9721FA80E8B0E4800D7E813 /* md5.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = md5.cc; path = ../../../common/md5.cc; sourceTree = SOURCE_ROOT; };
 		F982089A0DB3280D0017AECA /* breakpad_nlist_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_nlist_test.h; sourceTree = "<group>"; };
 		F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = breakpad_nlist_test.cc; sourceTree = "<group>"; };
@@ -235,17 +235,17 @@
 			children = (
 				8BFC812011FF99D5002CB4DC /* Breakpad.xcconfig */,
 				8BFC812111FF99D5002CB4DC /* BreakpadDebug.xcconfig */,
 				8BFC812211FF99D5002CB4DC /* BreakpadRelease.xcconfig */,
 				F9721FA80E8B0E4800D7E813 /* md5.cc */,
 				F9721F760E8B0DC700D7E813 /* bytereader.cc */,
 				F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */,
 				F9721F780E8B0DC700D7E813 /* functioninfo.cc */,
-				F9721F390E8B0D0D00D7E813 /* dump_syms.mm */,
+				F9721F390E8B0D0D00D7E813 /* dump_syms.cc */,
 				F9721F380E8B0CFC00D7E813 /* dump_syms.h */,
 				F917C4F70E03265A00F86017 /* breakpad_exc_server.c */,
 				F917C4F80E03265A00F86017 /* breakpad_exc_server.h */,
 				F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */,
 				F98208A20DB32CAE0017AECA /* breakpad_nlist_64.h */,
 				D2F6510C0BEF94EB00920385 /* macho_walker.cc */,
 				D2F6510D0BEF94EB00920385 /* macho_walker.h */,
 				D2F651070BEF949A00920385 /* dynamic_images.cc */,
@@ -592,17 +592,17 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		F93A88710E8B4C700026AF89 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 				F93A88860E8B4C9A0026AF89 /* dwarftests.mm in Sources */,
-				F93A88870E8B4C9A0026AF89 /* dump_syms.mm in Sources */,
+				F93A88870E8B4C9A0026AF89 /* dump_syms.cc in Sources */,
 				F93A88880E8B4C9A0026AF89 /* bytereader.cc in Sources */,
 				F93A88890E8B4C9A0026AF89 /* dwarf2reader.cc in Sources */,
 				F93A888A0E8B4C9A0026AF89 /* functioninfo.cc in Sources */,
 				F93A888B0E8B4C9A0026AF89 /* md5.cc in Sources */,
 				F93A887D0E8B4C8C0026AF89 /* macho_walker.cc in Sources */,
 				F93A887E0E8B4C8C0026AF89 /* macho_id.cc in Sources */,
 				F93A887F0E8B4C8C0026AF89 /* macho_utilities.cc in Sources */,
 				F93A88800E8B4C8C0026AF89 /* file_id.cc in Sources */,
--- a/toolkit/crashreporter/breakpad-client/mac/tests/exception_handler_test.cc
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/exception_handler_test.cc
@@ -31,16 +31,17 @@
 
 #include <pthread.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
 #include "breakpad_googletest_includes.h"
 #include "client/mac/handler/exception_handler.h"
+#include "common/linux/ignore_ret.h"
 #include "common/mac/MachIPC.h"
 #include "common/tests/auto_tempdir.h"
 #include "google_breakpad/processor/minidump.h"
 
 namespace google_breakpad {
 // This acts as the log sink for INFO logging from the processor
 // logging code. The logging output confuses XCode and makes it think
 // there are unit test failures. testlogging.h handles the overriding.
@@ -88,17 +89,17 @@ static void SoonToCrash(void(*crasher)()
 static bool MDCallback(const char *dump_dir, const char *file_name,
                        void *context, bool success) {
   string path(dump_dir);
   path.append("/");
   path.append(file_name);
   path.append(".dmp");
 
   int fd = *reinterpret_cast<int*>(context);
-  (void)write(fd, path.c_str(), path.length() + 1);
+  IGNORE_RET(write(fd, path.c_str(), path.length() + 1));
   close(fd);
   exit(0);
   // not reached
   return true;
 }
 
 void ExceptionHandlerTest::InProcessCrash(bool aborting) {
   // Give the child process a pipe to report back on.
@@ -288,17 +289,17 @@ TEST_F(ExceptionHandlerTest, DumpChildPr
   // Ensure that minidump file exists and is > 0 bytes.
   ASSERT_FALSE(lastDumpName.empty());
   struct stat st;
   ASSERT_EQ(0, stat(lastDumpName.c_str(), &st));
   ASSERT_LT(0, st.st_size);
 
   // Unblock child process
   uint8_t data = 1;
-  (void)write(fds[1], &data, 1);
+  IGNORE_RET(write(fds[1], &data, 1));
 
   // Child process should have exited with a zero status.
   int ret;
   ASSERT_EQ(pid, waitpid(pid, &ret, 0));
   EXPECT_NE(0, WIFEXITED(ret));
   EXPECT_EQ(0, WEXITSTATUS(ret));
 }
 
--- a/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test.cc
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test.cc
@@ -37,16 +37,17 @@
 #include <unistd.h>
 
 #include <string>
 #include <vector>
 
 #include "breakpad_googletest_includes.h"
 #include "client/mac/handler/minidump_generator.h"
 #include "client/mac/tests/spawn_child_process.h"
+#include "common/linux/ignore_ret.h"
 #include "common/mac/MachIPC.h"
 #include "common/tests/auto_tempdir.h"
 #include "google_breakpad/processor/minidump.h"
 
 namespace google_breakpad {
 // This acts as the log sink for INFO logging from the processor
 // logging code. The logging output confuses XCode and makes it think
 // there are unit test failures. testlogging.h handles the overriding.
@@ -185,17 +186,17 @@ TEST_F(MinidumpGeneratorTest, OutOfProce
 
   // Ensure that minidump file exists and is > 0 bytes.
   struct stat st;
   ASSERT_EQ(0, stat(dump_filename.c_str(), &st));
   ASSERT_LT(0, st.st_size);
 
   // Unblock child process
   uint8_t data = 1;
-  (void)write(fds[1], &data, 1);
+  IGNORE_RET(write(fds[1], &data, 1));
 
   // Child process should have exited with a zero status.
   int ret;
   ASSERT_EQ(pid, waitpid(pid, &ret, 0));
   EXPECT_NE(0, WIFEXITED(ret));
   EXPECT_EQ(0, WEXITSTATUS(ret));
 
   // Read the minidump, sanity check some data.
--- a/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.cc
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.cc
@@ -963,15 +963,26 @@ bool CrashGenerationServer::GenerateDump
     callback_context.end = app_memory_info_.cend();
 
     callback.CallbackRoutine = MinidumpWriteDumpCallback;
     callback.CallbackParam = &callback_context;
 
     dump_generator.SetCallback(&callback);
   }
 
- if (!dump_generator.GenerateDumpFile(dump_path)) {
+  if (!dump_generator.GenerateDumpFile(dump_path)) {
     return false;
   }
+
+  // If the client requests a full memory dump, we will write a normal mini
+  // dump and a full memory dump. Both dump files use the same uuid as file
+  // name prefix.
+  if (client.dump_type() & MiniDumpWithFullMemory) {
+    std::wstring full_dump_path;
+    if (!dump_generator.GenerateFullDumpFile(&full_dump_path)) {
+      return false;
+    }
+  }
+
   return dump_generator.WriteMinidump();
 }
 
 }  // namespace google_breakpad
--- a/toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.cc
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.cc
@@ -171,17 +171,17 @@ bool HandleTraceData::CollectHandleData(
       reinterpret_cast<MINIDUMP_HANDLE_OPERATION_LIST*>(
           &stream_.front());
   stream_data->SizeOfHeader = sizeof(MINIDUMP_HANDLE_OPERATION_LIST);
   stream_data->SizeOfEntry = sizeof(AVRF_HANDLE_OPERATION);
   stream_data->NumberOfEntries = static_cast<ULONG32>(operations_.size());
   stream_data->Reserved = 0;
   std::copy(operations_.begin(),
             operations_.end(),
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER)
             stdext::checked_array_iterator<AVRF_HANDLE_OPERATION*>(
                 reinterpret_cast<AVRF_HANDLE_OPERATION*>(stream_data + 1),
                 operations_.size())
 #else
             reinterpret_cast<AVRF_HANDLE_OPERATION*>(stream_data + 1)
 #endif
             );
 
@@ -266,22 +266,24 @@ MinidumpGenerator::MinidumpGenerator(
       process_id_(process_id),
       thread_id_(thread_id),
       requesting_thread_id_(requesting_thread_id),
       exception_pointers_(exception_pointers),
       assert_info_(assert_info),
       dump_type_(dump_type),
       is_client_pointers_(is_client_pointers),
       dump_path_(dump_path),
+      uuid_generated_(false),
       dump_file_(INVALID_HANDLE_VALUE),
       full_dump_file_(INVALID_HANDLE_VALUE),
       dump_file_is_internal_(false),
       full_dump_file_is_internal_(false),
       additional_streams_(NULL),
       callback_info_(NULL) {
+  uuid_ = {0};
   InitializeCriticalSection(&module_load_sync_);
   InitializeCriticalSection(&get_proc_address_sync_);
 }
 
 MinidumpGenerator::~MinidumpGenerator() {
   if (dump_file_is_internal_ && dump_file_ != INVALID_HANDLE_VALUE) {
     CloseHandle(dump_file_);
   }
@@ -557,23 +559,25 @@ MinidumpGenerator::UuidCreateType Minidu
       create_uuid_ = reinterpret_cast<UuidCreateType>(proc);
     }
   }
 
   return create_uuid_;
 }
 
 bool MinidumpGenerator::GenerateDumpFilePath(wstring* file_path) {
-  UUID id = {0};
+  if (!uuid_generated_) {
+    UuidCreateType create_uuid = GetCreateUuid();
+    if (!create_uuid) {
+      return false;
+    }
 
-  UuidCreateType create_uuid = GetCreateUuid();
-  if (!create_uuid) {
-    return false;
+    create_uuid(&uuid_);
+    uuid_generated_ = true;
   }
 
-  create_uuid(&id);
-  wstring id_str = GUIDString::GUIDToWString(&id);
+  wstring id_str = GUIDString::GUIDToWString(&uuid_);
 
   *file_path = dump_path_ + TEXT("\\") + id_str + TEXT(".dmp");
   return true;
 }
 
 }  // namespace google_breakpad
--- a/toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.h
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.h
@@ -163,16 +163,20 @@ class MinidumpGenerator {
 
   // Specifies whether the exception_pointers_ reference memory in the crashing
   // process.
   bool is_client_pointers_;
 
   // Folder path to store dump files.
   std::wstring dump_path_;
 
+  // UUID used to make dump file names.
+  UUID uuid_;
+  bool uuid_generated_;
+
   // The file where the dump will be written.
   HANDLE dump_file_;
 
   // The file where the full dump will be written.
   HANDLE full_dump_file_;
 
   // Tracks whether the dump file handle is managed externally.
   bool dump_file_is_internal_;
--- a/toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.cc
+++ b/toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.cc
@@ -36,16 +36,21 @@
 #include "common/windows/string_utils-inl.h"
 
 #include "windows/common/ipc_protocol.h"
 #include "windows/handler/exception_handler.h"
 #include "common/windows/guid_string.h"
 
 namespace google_breakpad {
 
+// This define is new to Windows 10.
+#ifndef DBG_PRINTEXCEPTION_WIDE_C
+#define DBG_PRINTEXCEPTION_WIDE_C ((DWORD)0x4001000A)
+#endif
+
 vector<ExceptionHandler*>* ExceptionHandler::handler_stack_ = NULL;
 LONG ExceptionHandler::handler_stack_index_ = 0;
 CRITICAL_SECTION ExceptionHandler::handler_stack_critical_section_;
 volatile LONG ExceptionHandler::instance_count_ = 0;
 
 ExceptionHandler::ExceptionHandler(const wstring& dump_path,
                                    FilterCallback filter,
                                    MinidumpCallback callback,
@@ -468,17 +473,19 @@ LONG ExceptionHandler::HandleException(E
   // Ignore EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP exceptions.  This
   // logic will short-circuit before calling WriteMinidumpOnHandlerThread,
   // allowing something else to handle the breakpoint without incurring the
   // overhead transitioning to and from the handler thread.  This behavior
   // can be overridden by calling ExceptionHandler::set_handle_debug_exceptions.
   DWORD code = exinfo->ExceptionRecord->ExceptionCode;
   LONG action;
   bool is_debug_exception = (code == EXCEPTION_BREAKPOINT) ||
-                            (code == EXCEPTION_SINGLE_STEP);
+                            (code == EXCEPTION_SINGLE_STEP) ||
+                            (code == DBG_PRINTEXCEPTION_C) ||
+                            (code == DBG_PRINTEXCEPTION_WIDE_C);
 
   if (code == EXCEPTION_INVALID_HANDLE &&
       current_handler->consume_invalid_handle_exceptions_) {
     return EXCEPTION_CONTINUE_EXECUTION;
   }
 
   bool success = false;
 
--- a/toolkit/crashreporter/breakpad-client/windows/unittests/crash_generation_server_test.cc
+++ b/toolkit/crashreporter/breakpad-client/windows/unittests/crash_generation_server_test.cc
@@ -23,19 +23,17 @@
 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/include/gmock/gmock.h"
-
+#include "breakpad_googletest_includes.h"
 #include "client/windows/crash_generation/crash_generation_server.h"
 #include "client/windows/common/ipc_protocol.h"
 
 using testing::_;
 
 namespace {
 
 const wchar_t kPipeName[] =
--- a/toolkit/crashreporter/breakpad-client/windows/unittests/dump_analysis.cc
+++ b/toolkit/crashreporter/breakpad-client/windows/unittests/dump_analysis.cc
@@ -26,18 +26,18 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <windows.h>
 #include <objbase.h>
 #include <dbghelp.h>
 
+#include "breakpad_googletest_includes.h"
 #include "client/windows/unittests/dump_analysis.h"  // NOLINT
-#include "testing/gtest/include/gtest/gtest.h"
 
 DumpAnalysis::~DumpAnalysis() {
   if (dump_file_view_ != NULL) {
     EXPECT_TRUE(::UnmapViewOfFile(dump_file_view_));
     ::CloseHandle(dump_file_mapping_);
     dump_file_mapping_ = NULL;
   }
 
--- a/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_death_test.cc
+++ b/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_death_test.cc
@@ -77,17 +77,17 @@ void ExceptionHandlerDeathTest::SetUp() 
   TCHAR temp_path[MAX_PATH] = { '\0' };
   TCHAR test_name_wide[MAX_PATH] = { '\0' };
   // We want the temporary directory to be what the OS returns
   // to us, + the test case name.
   GetTempPath(MAX_PATH, temp_path);
   // The test case name is exposed as a c-style string,
   // convert it to a wchar_t string.
   int dwRet = MultiByteToWideChar(CP_ACP, 0, test_info->name(),
-                                  strlen(test_info->name()),
+                                  static_cast<int>(strlen(test_info->name())),
                                   test_name_wide,
                                   MAX_PATH);
   if (!dwRet) {
     assert(false);
   }
   StringCchPrintfW(temp_path_, MAX_PATH, L"%s%s", temp_path, test_name_wide);
   CreateDirectory(temp_path_, NULL);
 }
@@ -288,18 +288,18 @@ wstring find_minidump_in_directory(const
   WIN32_FIND_DATA find_data;
   HANDLE find_handle = FindFirstFileW(search_path.c_str(), &find_data);
   if (find_handle == INVALID_HANDLE_VALUE)
     return wstring();
 
   wstring filename;
   do {
     const wchar_t extension[] = L".dmp";
-    const int extension_length = sizeof(extension) / sizeof(extension[0]) - 1;
-    const int filename_length = wcslen(find_data.cFileName);
+    const size_t extension_length = sizeof(extension) / sizeof(extension[0]) - 1;
+    const size_t filename_length = wcslen(find_data.cFileName);
     if (filename_length > extension_length &&
     wcsncmp(extension,
             find_data.cFileName + filename_length - extension_length,
             extension_length) == 0) {
       filename = directory + L"\\" + find_data.cFileName;
       break;
     }
   } while (FindNextFile(find_handle, &find_data));
@@ -352,18 +352,18 @@ TEST_F(ExceptionHandlerDeathTest, Instru
   wstring minidump_filename_wide = find_minidump_in_directory(temp_path_);
   ASSERT_FALSE(minidump_filename_wide.empty());
   string minidump_filename;
   ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(minidump_filename_wide,
                                                 &minidump_filename));
 
   // Read the minidump. Locate the exception record and the
   // memory list, and then ensure that there is a memory region
-  // in the memory list that covers the instruction pointer from
-  // the exception record.
+  // in the memory list that covers at least 128 bytes on either
+  // side of the instruction pointer from the exception record.
   {
     Minidump minidump(minidump_filename);
     ASSERT_TRUE(minidump.Read());
 
     MinidumpException* exception = minidump.GetException();
     MinidumpMemoryList* memory_list = minidump.GetMemoryList();
     ASSERT_TRUE(exception);
     ASSERT_TRUE(memory_list);
@@ -374,28 +374,33 @@ TEST_F(ExceptionHandlerDeathTest, Instru
 
     uint64_t instruction_pointer;
     ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
 
     MinidumpMemoryRegion* region =
         memory_list->GetMemoryRegionForAddress(instruction_pointer);
     ASSERT_TRUE(region);
 
-    EXPECT_EQ(kMemorySize, region->GetSize());
+    EXPECT_LE(kMemorySize, region->GetSize());
     const uint8_t* bytes = region->GetMemory();
     ASSERT_TRUE(bytes);
 
+    uint64_t ip_offset = instruction_pointer - region->GetBase();
+    EXPECT_GE(region->GetSize() - kOffset, ip_offset);
+    EXPECT_LE(kOffset, ip_offset);
+
     uint8_t prefix_bytes[kOffset];
     uint8_t suffix_bytes[kMemorySize - kOffset - sizeof(instructions)];
     memset(prefix_bytes, 0, sizeof(prefix_bytes));
     memset(suffix_bytes, 0, sizeof(suffix_bytes));
-    EXPECT_EQ(0, memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)));
-    EXPECT_EQ(0, memcmp(bytes + kOffset, instructions, sizeof(instructions)));
-    EXPECT_EQ(0, memcmp(bytes + kOffset + sizeof(instructions),
-                        suffix_bytes, sizeof(suffix_bytes)));
+    EXPECT_EQ(0, memcmp(bytes + ip_offset - kOffset, prefix_bytes,
+                        sizeof(prefix_bytes)));
+    EXPECT_EQ(0, memcmp(bytes + ip_offset, instructions, sizeof(instructions)));
+    EXPECT_EQ(0, memcmp(bytes + ip_offset + sizeof(instructions), suffix_bytes,
+                        sizeof(suffix_bytes)));
   }
 
   DeleteFileW(minidump_filename_wide.c_str());
 }
 
 TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemoryMinBound) {
   ASSERT_TRUE(DoesPathExist(temp_path_));
   scoped_ptr<google_breakpad::ExceptionHandler> exc(
--- a/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_test.cc
+++ b/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_test.cc
@@ -115,17 +115,17 @@ void ExceptionHandlerTest::SetUp() {
   TCHAR temp_path[MAX_PATH] = { '\0' };
   TCHAR test_name_wide[MAX_PATH] = { '\0' };
   // We want the temporary directory to be what the OS returns
   // to us, + the test case name.
   GetTempPath(MAX_PATH, temp_path);
   // THe test case name is exposed to use as a c-style string,
   // But we might be working in UNICODE here on Windows.
   int dwRet = MultiByteToWideChar(CP_ACP, 0, test_info->name(),
-                                  strlen(test_info->name()),
+                                  static_cast<int>(strlen(test_info->name())),
                                   test_name_wide,
                                   MAX_PATH);
   if (!dwRet) {
     assert(false);
   }
   StringCchPrintfW(temp_path_, MAX_PATH, L"%s%s", temp_path, test_name_wide);
   CreateDirectory(temp_path_, NULL);
 }
@@ -242,16 +242,17 @@ TEST_F(ExceptionHandlerTest, InvalidPara
 
   // This HAS to be EXPECT_, because when this test case is executed in the
   // child process, the server registration will fail due to the named pipe
   // being the same.
   EXPECT_TRUE(server.Start());
   EXPECT_EXIT(DoCrashInvalidParameter(), ::testing::ExitedWithCode(0), "");
   ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty());
   ASSERT_TRUE(DoesPathExist(dump_file.c_str()));
+  ASSERT_TRUE(DoesPathExist(full_dump_file.c_str()));
 
   // Verify the dump for infos.
   DumpAnalysis mini(dump_file);
   DumpAnalysis full(full_dump_file);
 
   // The dump should have all of these streams.
   EXPECT_TRUE(mini.HasStream(ThreadListStream));
   EXPECT_TRUE(full.HasStream(ThreadListStream));
@@ -313,16 +314,17 @@ TEST_F(ExceptionHandlerTest, PureVirtual
 
   // This HAS to be EXPECT_, because when this test case is executed in the
   // child process, the server registration will fail due to the named pipe
   // being the same.
   EXPECT_TRUE(server.Start());
   EXPECT_EXIT(DoCrashPureVirtualCall(), ::testing::ExitedWithCode(0), "");
   ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty());
   ASSERT_TRUE(DoesPathExist(dump_file.c_str()));
+  ASSERT_TRUE(DoesPathExist(full_dump_file.c_str()));
 
   // Verify the dump for infos.
   DumpAnalysis mini(dump_file);
   DumpAnalysis full(full_dump_file);
 
   // The dump should have all of these streams.
   EXPECT_TRUE(mini.HasStream(ThreadListStream));
   EXPECT_TRUE(full.HasStream(ThreadListStream));
--- a/toolkit/crashreporter/breakpad-client/windows/unittests/minidump_test.cc
+++ b/toolkit/crashreporter/breakpad-client/windows/unittests/minidump_test.cc
@@ -26,21 +26,20 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <windows.h>
 #include <objbase.h>
 #include <dbghelp.h>
 
+#include "breakpad_googletest_includes.h"
 #include "client/windows/crash_generation/minidump_generator.h"
 #include "client/windows/unittests/dump_analysis.h"  // NOLINT
 
-#include "gtest/gtest.h"
-
 namespace {
 
 // Minidump with stacks, PEB, TEB, and unloaded module list.
 const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>(
     MiniDumpWithProcessThreadData |  // Get PEB and TEB.
     MiniDumpWithUnloadedModules);  // Get unloaded modules when available.
 
 // Minidump with all of the above, plus memory referenced from stack.
@@ -89,17 +88,17 @@ class MinidumpTest: public testing::Test
   bool WriteDump(ULONG flags) {
     using google_breakpad::MinidumpGenerator;
 
     // Fake exception is access violation on write to this.
     EXCEPTION_RECORD ex_record = {
         STATUS_ACCESS_VIOLATION,  // ExceptionCode
         0,  // ExceptionFlags
         NULL,  // ExceptionRecord;
-        reinterpret_cast<void*>(0xCAFEBABE),  // ExceptionAddress;
+        reinterpret_cast<void*>(static_cast<uintptr_t>(0xCAFEBABE)),  // ExceptionAddress;
         2,  // NumberParameters;
         { EXCEPTION_WRITE_FAULT, reinterpret_cast<ULONG_PTR>(this) }
     };
     CONTEXT ctx_record = {};
     EXCEPTION_POINTERS ex_ptrs = {
       &ex_record,
       &ctx_record,
     };
--- a/toolkit/crashreporter/google-breakpad/.gitignore
+++ b/toolkit/crashreporter/google-breakpad/.gitignore
@@ -22,16 +22,17 @@
 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 # Ignore other VCSs.
+.repo/
 .svn/
 
 # Ignore common compiled artifacts.
 *~
 *.dwo
 *.o
 lib*.a
 /breakpad.pc
@@ -42,16 +43,22 @@ lib*.a
 /src/processor/minidump_dump
 /src/processor/minidump_stackwalk
 /src/tools/linux/core2md/core2md
 /src/tools/linux/dump_syms/dump_syms
 /src/tools/linux/md2core/minidump-2-core
 /src/tools/linux/symupload/minidump_upload
 /src/tools/linux/symupload/sym_upload
 /src/tools/mac/dump_syms/dump_syms
+/src/tools/mac/dump_syms/dump_syms_mac
+
+# Ignore unit test artifacts.
+*_unittest
+*.log
+*.trs
 
 # Ignore autotools generated artifacts.
 .deps
 .dirstamp
 autom4te.cache/
 /config.cache
 config.h
 /config.log
@@ -72,12 +79,11 @@ src/Makefile
 *.Makefile
 *.target.mk
 
 # Ignore compiled Python files.
 *.pyc
 
 # Ignore directories gclient syncs.
 src/testing
-src/third_party/glog
 src/third_party/lss
 src/third_party/protobuf
 src/tools/gyp
--- a/toolkit/crashreporter/google-breakpad/DEPS
+++ b/toolkit/crashreporter/google-breakpad/DEPS
@@ -28,48 +28,57 @@
 
 # This is used to mimic the svn:externals mechanism for gclient (both Git and
 # SVN) based checkouts of Breakpad. As such, its use is entirely optional. If
 # using a manually managed SVN checkout as opposed to a gclient managed checkout
 # you can still use the hooks mechanism for generating project files by calling
 # 'gclient runhooks' rather than 'gclient sync'.
 
 deps = {
-  # Logging code.
-  "src/src/third_party/glog":
-    "https://github.com/google/glog.git" +
-      "@v0.3.4",
-
   # Testing libraries and utilities.
   "src/src/testing":
-    "https://github.com/google/googlemock.git" +
-      "@release-1.7.0",
-  "src/src/testing/gtest":
     "https://github.com/google/googletest.git" +
-      "@release-1.7.0",
+      "@release-1.8.0",
 
   # Protobuf.
   "src/src/third_party/protobuf/protobuf":
     "https://github.com/google/protobuf.git" +
       "@cb6dd4ef5f82e41e06179dcd57d3b1d9246ad6ac",
 
   # GYP project generator.
   "src/src/tools/gyp":
     "https://chromium.googlesource.com/external/gyp/" +
-      "@e8ab0833a42691cd2184bd4c45d779e43821d3e0",
+      "@324dd166b7c0b39d513026fa52d6280ac6d56770",
 
   # Linux syscall support.
   "src/src/third_party/lss":
     "https://chromium.googlesource.com/linux-syscall-support/" +
-      "@3f6478ac95edf86cd3da300c2c0d34a438f5dbeb",
+      "@e6527b0cd469e3ff5764785dadcb39bf7d787154",
 }
 
 hooks = [
   {
-    # TODO(chrisha): Fix the GYP files so that they work without
-    # --no-circular-check.
-    "pattern": ".",
-    "action": ["python",
-               "src/src/tools/gyp/gyp_main.py",
-               "--no-circular-check",
-               "src/src/client/windows/breakpad_client.gyp"],
+    # Keep the manifest up to date.
+    "action": ["python", "src/src/tools/python/deps-to-manifest.py",
+               "src/DEPS", "src/default.xml"],
   },
 ]
+
+hooks_os = {
+  'win': [
+    {
+      # TODO(chrisha): Fix the GYP files so that they work without
+      # --no-circular-check.
+      "pattern": ".",
+      "action": ["python",
+                 "src/src/tools/gyp/gyp_main.py",
+                 "--no-circular-check",
+                 "src/src/client/windows/breakpad_client.gyp"],
+    },
+    {
+      # XXX: this and above should all be wired into build/all.gyp ?
+      "action": ["python",
+                 "src/src/tools/gyp/gyp_main.py",
+                 "--no-circular-check",
+                 "src/src/tools/windows/tools_windows.gyp"],
+    },
+  ],
+}
--- a/toolkit/crashreporter/google-breakpad/GIT-INFO
+++ b/toolkit/crashreporter/google-breakpad/GIT-INFO
@@ -1,1 +1,1 @@
-704f41ec901c419f8c321742114b415e6f5ceacc
+69c2c51dd89965d234eec16e3a9353634831916b
--- a/toolkit/crashreporter/google-breakpad/Makefile.am
+++ b/toolkit/crashreporter/google-breakpad/Makefile.am
@@ -38,27 +38,17 @@ AM_CXXFLAGS =
 if ANDROID_HOST
 # This allows using fixed NDK headers when building for Android.
 AM_CXXFLAGS += -I$(top_srcdir)/src/common/android/include
 # This is only necessary for building the unit tests until GTest is upgraded
 # to a future version.
 AM_CXXFLAGS += -I$(top_srcdir)/src/common/android/testing/include
 endif
 
-if GCC
-# These are good warnings to be treated as errors
-AM_CXXFLAGS += \
-	-Werror=missing-braces \
-	-Werror=non-virtual-dtor \
-	-Werror=overloaded-virtual \
-	-Werror=reorder \
-	-Werror=sign-compare \
-	-Werror=unused-variable \
-	-Werror=vla
-endif
+AM_CXXFLAGS += $(WARN_CXXFLAGS)
 
 if LINUX_HOST
 # Build as PIC on Linux, for linux_client_unittest_shlib
 AM_CFLAGS += -fPIC
 AM_CXXFLAGS += -fPIC
 endif
 
 # Specify include paths for ac macros
@@ -115,18 +105,20 @@ pkgconfig_DATA =
 ## Common test logic
 if SYSTEM_TEST_LIBS
 TEST_CFLAGS = $(GTEST_CFLAGS) $(GMOCK_CFLAGS)
 TEST_LIBS = $(GTEST_LIBS) -lgtest_main $(GMOCK_LIBS)
 TEST_DEPS =
 else
 TEST_CFLAGS = \
 	-I$(top_srcdir)/src/testing/include \
-	-I$(top_srcdir)/src/testing/gtest/include \
-	-I$(top_srcdir)/src/testing/gtest \
+	-I$(top_srcdir)/src/testing/googletest/include \
+	-I$(top_srcdir)/src/testing/googletest \
+	-I$(top_srcdir)/src/testing/googlemock/include \
+	-I$(top_srcdir)/src/testing/googlemock \
 	-I$(top_srcdir)/src/testing
 TEST_LIBS = src/testing/libtesting.a
 TEST_DEPS = $(TEST_LIBS)
 endif
 
 ## Libraries
 check_LIBRARIES =
 noinst_LIBRARIES =
@@ -136,19 +128,19 @@ check_PROGRAMS =
 EXTRA_PROGRAMS =
 CLEANFILES =
 
 check_LIBRARIES += src/testing/libtesting.a
 
 if !SYSTEM_TEST_LIBS
 src_testing_libtesting_a_SOURCES = \
 	src/breakpad_googletest_includes.h \
-	src/testing/gtest/src/gtest-all.cc \
-	src/testing/gtest/src/gtest_main.cc \
-	src/testing/src/gmock-all.cc
+	src/testing/googletest/src/gtest-all.cc \
+	src/testing/googletest/src/gtest_main.cc \
+	src/testing/googlemock/src/gmock-all.cc
 src_testing_libtesting_a_CPPFLAGS = \
 	$(AM_CPPFLAGS) $(TEST_CFLAGS)
 endif
 
 if !DISABLE_PROCESSOR
 lib_LIBRARIES += src/libbreakpad.a
 pkgconfig_DATA += breakpad.pc
 noinst_LIBRARIES += src/third_party/libdisasm/libdisasm.a
@@ -409,17 +401,18 @@ endif
 
 if LINUX_HOST
 EXTRA_PROGRAMS += \
 	src/client/linux/linux_client_unittest_shlib
 CLEANFILES += \
 	src/client/linux/linux_client_unittest_shlib
 
 check_PROGRAMS += \
-	src/client/linux/linux_client_unittest
+	src/client/linux/linux_client_unittest \
+	src/common/linux/google_crashdump_uploader_test
 
 if !DISABLE_TOOLS
 check_PROGRAMS += \
 	src/common/dumper_unittest \
 	src/tools/linux/md2core/minidump_2_core_unittest
 if X86_HOST
 check_PROGRAMS += \
 	src/common/mac/macho_reader_unittest
@@ -448,18 +441,22 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPT
 if ANDROID_HOST
 # Since Autotools 1.2, tests are run through a special "test driver" script.
 # Unfortunately, it's not possible anymore to specify an alternative shell to
 # run them on connected devices, so use a slightly modified version of the
 # driver for Android.
 LOG_DRIVER = $(top_srcdir)/android/test-driver
 else
 # The default Autotools test driver script.
+if TESTS_AS_ROOT
+LOG_DRIVER = $(top_srcdir)/autotools/root-test-driver $(top_srcdir)/autotools/test-driver
+else
 LOG_DRIVER = $(top_srcdir)/autotools/test-driver
-endif
+endif !TESTS_AS_ROOT
+endif !ANDROID_HOST
 
 if LINUX_HOST
 src_client_linux_linux_dumper_unittest_helper_SOURCES = \
 	src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
 src_client_linux_linux_dumper_unittest_helper_LDFLAGS=$(PTHREAD_CFLAGS)
 src_client_linux_linux_dumper_unittest_helper_CC=$(PTHREAD_CC)
 if ANDROID_HOST
 # On Android PTHREAD_CFLAGS is empty, and adding src/common/android/include
@@ -571,16 +568,17 @@ src_tools_linux_core2md_core2md_LDADD = 
 	src/client/linux/libbreakpad_client.a
 
 src_tools_linux_dump_syms_dump_syms_SOURCES = \
 	src/common/dwarf_cfi_to_module.cc \
 	src/common/dwarf_cu_to_module.cc \
 	src/common/dwarf_line_to_module.cc \
 	src/common/language.cc \
 	src/common/module.cc \
+	src/common/path_helper.cc \
 	src/common/stabs_reader.cc \
 	src/common/stabs_to_module.cc \
 	src/common/dwarf/bytereader.cc \
 	src/common/dwarf/dwarf2diehandler.cc \
 	src/common/dwarf/dwarf2reader.cc \
 	src/common/dwarf/elf_reader.cc \
 	src/common/linux/crc32.cc \
 	src/common/linux/dump_symbols.cc \
@@ -588,19 +586,24 @@ src_tools_linux_dump_syms_dump_syms_SOUR
 	src/common/linux/elf_symbols_to_module.cc \
 	src/common/linux/elf_symbols_to_module.h \
 	src/common/linux/elfutils.cc \
 	src/common/linux/file_id.cc \
 	src/common/linux/linux_libc_support.cc \
 	src/common/linux/memory_mapped_file.cc \
 	src/common/linux/safe_readlink.cc \
 	src/tools/linux/dump_syms/dump_syms.cc
+src_tools_linux_dump_syms_dump_syms_CXXFLAGS = \
+	$(RUST_DEMANGLE_CFLAGS)
+src_tools_linux_dump_syms_dump_syms_LDADD = \
+	$(RUST_DEMANGLE_LIBS)
 
 src_tools_linux_md2core_minidump_2_core_SOURCES = \
 	src/common/linux/memory_mapped_file.cc \
+	src/common/path_helper.cc \
 	src/tools/linux/md2core/minidump-2-core.cc \
 	src/tools/linux/md2core/minidump_memory_range.h
 
 src_tools_linux_symupload_minidump_upload_SOURCES = \
 	src/common/linux/http_upload.cc \
 	src/tools/linux/symupload/minidump_upload.cc
 src_tools_linux_symupload_minidump_upload_LDADD = -ldl
 
@@ -614,16 +617,17 @@ src_tools_linux_symupload_sym_upload_LDA
 
 src_tools_mac_dump_syms_dump_syms_mac_SOURCES = \
 	src/common/dwarf_cfi_to_module.cc \
 	src/common/dwarf_cu_to_module.cc \
 	src/common/dwarf_line_to_module.cc \
 	src/common/language.cc \
 	src/common/md5.cc \
 	src/common/module.cc \
+	src/common/path_helper.cc \
 	src/common/stabs_reader.cc \
 	src/common/stabs_to_module.cc \
 	src/common/dwarf/bytereader.cc \
 	src/common/dwarf/dwarf2diehandler.cc \
 	src/common/dwarf/dwarf2reader.cc \
 	src/common/dwarf/elf_reader.cc \
 	src/common/mac/arch_utilities.cc \
 	src/common/mac/dump_syms.cc \
@@ -636,30 +640,34 @@ src_tools_mac_dump_syms_dump_syms_mac_SO
 	src/common/mac/macho_reader.h \
 	src/common/mac/macho_utilities.cc \
 	src/common/mac/macho_utilities.h \
 	src/common/mac/macho_walker.cc \
 	src/common/mac/macho_walker.h \
 	src/tools/mac/dump_syms/dump_syms_tool.cc
 src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS= \
 	-I$(top_srcdir)/src/third_party/mac_headers \
+	$(RUST_DEMANGLE_CFLAGS) \
 	-DHAVE_MACH_O_NLIST_H
+src_tools_mac_dump_syms_dump_syms_mac_LDADD= \
+	$(RUST_DEMANGLE_LIBS)
 
 src_common_dumper_unittest_SOURCES = \
 	src/common/byte_cursor_unittest.cc \
 	src/common/dwarf_cfi_to_module.cc \
 	src/common/dwarf_cfi_to_module_unittest.cc \
 	src/common/dwarf_cu_to_module.cc \
 	src/common/dwarf_cu_to_module_unittest.cc \
 	src/common/dwarf_line_to_module.cc \
 	src/common/dwarf_line_to_module_unittest.cc \
 	src/common/language.cc \
 	src/common/memory_range_unittest.cc \
 	src/common/module.cc \
 	src/common/module_unittest.cc \
+	src/common/path_helper.cc \
 	src/common/stabs_reader.cc \
 	src/common/stabs_reader_unittest.cc \
 	src/common/stabs_to_module.cc \
 	src/common/stabs_to_module_unittest.cc \
 	src/common/test_assembler.cc \
 	src/common/dwarf/bytereader.cc \
 	src/common/dwarf/bytereader.h \
 	src/common/dwarf/bytereader-inl.h \
@@ -693,28 +701,31 @@ src_common_dumper_unittest_SOURCES = \
 	src/common/linux/synth_elf.cc \
 	src/common/linux/synth_elf_unittest.cc \
 	src/common/linux/tests/crash_generator.cc \
 	src/common/linux/tests/crash_generator.h \
 	src/common/testdata/func-line-pairing.h \
 	src/common/tests/file_utils.cc
 src_common_dumper_unittest_CPPFLAGS = \
 	$(AM_CPPFLAGS) $(TEST_CFLAGS) \
+	$(RUST_DEMANGLE_CFLAGS) \
 	$(PTHREAD_CFLAGS)
 src_common_dumper_unittest_LDADD = \
 	$(TEST_LIBS) \
+	$(RUST_DEMANGLE_LIBS) \
 	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
 
 src_common_mac_macho_reader_unittest_SOURCES = \
 	src/common/dwarf_cfi_to_module.cc \
 	src/common/dwarf_cu_to_module.cc \
 	src/common/dwarf_line_to_module.cc \
 	src/common/language.cc \
 	src/common/md5.cc \
 	src/common/module.cc \
+	src/common/path_helper.cc \
 	src/common/stabs_reader.cc \
 	src/common/stabs_to_module.cc \
 	src/common/test_assembler.cc \
 	src/common/dwarf/bytereader.cc \
 	src/common/dwarf/cfi_assembler.cc \
 	src/common/dwarf/dwarf2diehandler.cc \
 	src/common/dwarf/dwarf2reader.cc \
 	src/common/dwarf/elf_reader.cc \
@@ -731,16 +742,27 @@ src_common_mac_macho_reader_unittest_CPP
 	-I$(top_srcdir)/src/third_party/mac_headers \
 	-DHAVE_MACH_O_NLIST_H \
 	$(PTHREAD_CFLAGS)
 src_common_mac_macho_reader_unittest_LDADD = \
 	$(TEST_LIBS) \
 	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
 endif
 
+src_common_linux_google_crashdump_uploader_test_SOURCES = \
+	src/common/linux/google_crashdump_uploader.cc \
+	src/common/linux/google_crashdump_uploader_test.cc \
+	src/common/linux/libcurl_wrapper.cc
+src_common_linux_google_crashdump_uploader_test_CPPFLAGS = \
+	$(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_common_linux_google_crashdump_uploader_test_LDADD = \
+	$(TEST_LIBS) \
+	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS) \
+	-ldl
+
 src_tools_linux_md2core_minidump_2_core_unittest_SOURCES = \
 	src/tools/linux/md2core/minidump_memory_range_unittest.cc
 src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS = \
 	$(AM_CPPFLAGS) $(TEST_CFLAGS)
 src_tools_linux_md2core_minidump_2_core_unittest_LDADD = \
 	$(TEST_LIBS) \
 	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
 
@@ -1169,16 +1191,17 @@ src_processor_minidump_dump_LDADD = \
 	src/processor/logging.o \
 	src/processor/minidump.o \
 	src/processor/pathname_stripper.o \
 	src/processor/proc_maps_linux.o
 
 src_processor_microdump_stackwalk_SOURCES = \
 	src/processor/microdump_stackwalk.cc
 src_processor_microdump_stackwalk_LDADD = \
+	src/common/path_helper.o \
 	src/processor/basic_code_modules.o \
 	src/processor/basic_source_line_resolver.o \
 	src/processor/call_stack.o \
 	src/processor/cfi_frame_info.o \
 	src/processor/disassembler_x86.o \
 	src/processor/dump_context.o \
 	src/processor/dump_object.o \
 	src/processor/logging.o \
@@ -1202,16 +1225,17 @@ src_processor_microdump_stackwalk_LDADD 
 	src/processor/stackwalker_sparc.o \
 	src/processor/stackwalker_x86.o \
 	src/processor/tokenize.o \
 	src/third_party/libdisasm/libdisasm.a
 
 src_processor_minidump_stackwalk_SOURCES = \
 	src/processor/minidump_stackwalk.cc
 src_processor_minidump_stackwalk_LDADD = \
+	src/common/path_helper.o \
 	src/processor/basic_code_modules.o \
 	src/processor/basic_source_line_resolver.o \
 	src/processor/call_stack.o \
 	src/processor/cfi_frame_info.o \
 	src/processor/disassembler_x86.o \
 	src/processor/dump_context.o \
 	src/processor/dump_object.o \
 	src/processor/exploitability.o \
@@ -1316,16 +1340,17 @@ EXTRA_DIST = \
 	src/common/windows/guid_string.cc \
 	src/common/windows/guid_string.h \
 	src/common/windows/http_upload.cc \
 	src/common/windows/http_upload.h \
 	src/common/windows/pdb_source_line_writer.cc \
 	src/common/windows/pdb_source_line_writer.h \
 	src/common/windows/string_utils-inl.h \
 	src/common/windows/string_utils.cc \
+	src/processor/microdump_stackwalk_test_vars \
 	src/processor/stackwalk_common.cc \
 	src/processor/stackwalk_common.h \
 	src/processor/stackwalker_selftest_sol.s \
 	src/processor/testdata/ascii_read_av_block_write.dmp \
 	src/processor/testdata/ascii_read_av_clobber_write.dmp \
 	src/processor/testdata/ascii_read_av_conditional.dmp \
 	src/processor/testdata/ascii_read_av.dmp \
 	src/processor/testdata/ascii_read_av_then_jmp.dmp \
@@ -1342,31 +1367,33 @@ EXTRA_DIST = \
 	src/processor/testdata/linux_jmp_to_module_not_exe_region.dmp \
 	src/processor/testdata/linux_null_dereference.dmp \
 	src/processor/testdata/linux_null_read_av.dmp \
 	src/processor/testdata/linux_outside_module.dmp \
 	src/processor/testdata/linux_overflow.dmp \
 	src/processor/testdata/linux_raise_sigabrt.dmp \
 	src/processor/testdata/linux_stack_pointer_in_module.dmp \
 	src/processor/testdata/linux_stack_pointer_in_stack.dmp \
+	src/processor/testdata/linux_stack_pointer_in_stack_alt_name.dmp \
 	src/processor/testdata/linux_stacksmash.dmp \
 	src/processor/testdata/linux_write_to_nonwritable_module.dmp \
 	src/processor/testdata/linux_write_to_nonwritable_region_math.dmp \
 	src/processor/testdata/linux_write_to_outside_module.dmp \
 	src/processor/testdata/linux_write_to_outside_module_via_math.dmp \
 	src/processor/testdata/linux_write_to_under_4k.dmp \
 	src/processor/testdata/microdump-arm64.dmp \
 	src/processor/testdata/microdump-arm.dmp \
 	src/processor/testdata/microdump-mips32.dmp \
 	src/processor/testdata/microdump-mips64.dmp \
 	src/processor/testdata/microdump-multiple.dmp \
 	src/processor/testdata/microdump.stackwalk-arm64.out \
 	src/processor/testdata/microdump.stackwalk-arm.out \
 	src/processor/testdata/microdump.stackwalk.machine_readable-arm64.out \
 	src/processor/testdata/microdump.stackwalk.machine_readable-arm.out \
+	src/processor/testdata/microdump-withcrashreason.dmp \
 	src/processor/testdata/microdump-x86.dmp \
 	src/processor/testdata/minidump2.dmp \
 	src/processor/testdata/minidump2.dump.out \
 	src/processor/testdata/minidump2.stackwalk.machine_readable.out \
 	src/processor/testdata/minidump2.stackwalk.out \
 	src/processor/testdata/module0.out \
 	src/processor/testdata/module1.out \
 	src/processor/testdata/module2.out \
@@ -1386,64 +1413,71 @@ EXTRA_DIST = \
 	src/processor/testdata/symbols/microdump/breakpad_unittests/D6D1FEC9A15DE7F38A236898871A2E770/breakpad_unittests.sym \
 	src/processor/testdata/symbols/microdump/breakpad_unittests/DA7778FB66018A4E9B4110ED06E730D00/breakpad_unittests.sym \
 	src/processor/testdata/symbols/microdump/crash_example/6E72E2F1A5F59AB3D51356FDFE394D490/crash_example.sym \
 	src/processor/testdata/symbols/microdump/crash_example/8F36148CC4647A8116CAF2A25F591F570/crash_example.sym \
 	src/processor/testdata/symbols/null_read_av/7B7D1968FF0D47AE4366E9C3A7E1B6750/null_read_av.sym \
 	src/processor/testdata/symbols/overflow/B0E1FC01EF48E39CAF5C881D2DF0C3840/overflow.sym \
 	src/processor/testdata/symbols/test_app.pdb/5A9832E5287241C1838ED98914E9B7FF1/test_app.sym \
 	src/processor/testdata/test_app.cc \
-	src/testing/gtest/include/gtest/gtest.h \
-	src/testing/gtest/include/gtest/gtest-death-test.h \
-	src/testing/gtest/include/gtest/gtest-message.h \
-	src/testing/gtest/include/gtest/gtest-param-test.h \
-	src/testing/gtest/include/gtest/gtest-printers.h \
-	src/testing/gtest/include/gtest/gtest-spi.h \
-	src/testing/gtest/include/gtest/gtest-test-part.h \
-	src/testing/gtest/include/gtest/gtest-typed-test.h \
-	src/testing/gtest/include/gtest/gtest_pred_impl.h \
-	src/testing/gtest/include/gtest/gtest_prod.h \
-	src/testing/gtest/include/gtest/internal/gtest-death-test-internal.h \
-	src/testing/gtest/include/gtest/internal/gtest-filepath.h \
-	src/testing/gtest/include/gtest/internal/gtest-internal.h \
-	src/testing/gtest/include/gtest/internal/gtest-linked_ptr.h \
-	src/testing/gtest/include/gtest/internal/gtest-param-util-generated.h \
-	src/testing/gtest/include/gtest/internal/gtest-param-util.h \
-	src/testing/gtest/include/gtest/internal/gtest-port.h \
-	src/testing/gtest/include/gtest/internal/gtest-string.h \
-	src/testing/gtest/include/gtest/internal/gtest-tuple.h \
-	src/testing/gtest/include/gtest/internal/gtest-type-util.h \
-	src/testing/gtest/src/gtest.cc \
-	src/testing/gtest/src/gtest-death-test.cc \
-	src/testing/gtest/src/gtest-filepath.cc \
-	src/testing/gtest/src/gtest-internal-inl.h \
-	src/testing/gtest/src/gtest-port.cc \
-	src/testing/gtest/src/gtest-printers.cc \
-	src/testing/gtest/src/gtest-test-part.cc \
-	src/testing/gtest/src/gtest-typed-test.cc \
-	src/testing/include/gmock/gmock.h \
-	src/testing/include/gmock/gmock-actions.h \
-	src/testing/include/gmock/gmock-cardinalities.h \
-	src/testing/include/gmock/gmock-generated-actions.h \
-	src/testing/include/gmock/gmock-generated-function-mockers.h \
-	src/testing/include/gmock/gmock-generated-matchers.h \
-	src/testing/include/gmock/gmock-generated-nice-strict.h \
-	src/testing/include/gmock/gmock-matchers.h \
-	src/testing/include/gmock/gmock-more-actions.h \
-	src/testing/include/gmock/gmock-more-matchers.h \
-	src/testing/include/gmock/gmock-spec-builders.h \
-	src/testing/include/gmock/internal/gmock-generated-internal-utils.h \
-	src/testing/include/gmock/internal/gmock-internal-utils.h \
-	src/testing/include/gmock/internal/gmock-port.h \
-	src/testing/src/gmock.cc \
-	src/testing/src/gmock-cardinalities.cc \
-	src/testing/src/gmock-internal-utils.cc \
-	src/testing/src/gmock-matchers.cc \
-	src/testing/src/gmock-spec-builders.cc \
-	src/testing/src/gmock_main.cc \
+	src/testing/googletest/include/gtest/gtest.h \
+	src/testing/googletest/include/gtest/gtest-death-test.h \
+	src/testing/googletest/include/gtest/gtest-message.h \
+	src/testing/googletest/include/gtest/gtest-param-test.h \
+	src/testing/googletest/include/gtest/gtest-printers.h \
+	src/testing/googletest/include/gtest/gtest-spi.h \
+	src/testing/googletest/include/gtest/gtest-test-part.h \
+	src/testing/googletest/include/gtest/gtest-typed-test.h \
+	src/testing/googletest/include/gtest/gtest_pred_impl.h \
+	src/testing/googletest/include/gtest/gtest_prod.h \
+	src/testing/googletest/include/gtest/internal/custom/gtest-port.h \
+	src/testing/googletest/include/gtest/internal/custom/gtest-printers.h \
+	src/testing/googletest/include/gtest/internal/custom/gtest.h \
+	src/testing/googletest/include/gtest/internal/gtest-death-test-internal.h \
+	src/testing/googletest/include/gtest/internal/gtest-filepath.h \
+	src/testing/googletest/include/gtest/internal/gtest-internal.h \
+	src/testing/googletest/include/gtest/internal/gtest-linked_ptr.h \
+	src/testing/googletest/include/gtest/internal/gtest-param-util-generated.h \
+	src/testing/googletest/include/gtest/internal/gtest-param-util.h \
+	src/testing/googletest/include/gtest/internal/gtest-port-arch.h \
+	src/testing/googletest/include/gtest/internal/gtest-port.h \
+	src/testing/googletest/include/gtest/internal/gtest-string.h \
+	src/testing/googletest/include/gtest/internal/gtest-tuple.h \
+	src/testing/googletest/include/gtest/internal/gtest-type-util.h \
+	src/testing/googletest/src/gtest.cc \
+	src/testing/googletest/src/gtest-death-test.cc \
+	src/testing/googletest/src/gtest-filepath.cc \
+	src/testing/googletest/src/gtest-internal-inl.h \
+	src/testing/googletest/src/gtest-port.cc \
+	src/testing/googletest/src/gtest-printers.cc \
+	src/testing/googletest/src/gtest-test-part.cc \
+	src/testing/googletest/src/gtest-typed-test.cc \
+	src/testing/googlemock/include/gmock/gmock.h \
+	src/testing/googlemock/include/gmock/gmock-actions.h \
+	src/testing/googlemock/include/gmock/gmock-cardinalities.h \
+	src/testing/googlemock/include/gmock/gmock-generated-actions.h \
+	src/testing/googlemock/include/gmock/gmock-generated-function-mockers.h \
+	src/testing/googlemock/include/gmock/gmock-generated-matchers.h \
+	src/testing/googlemock/include/gmock/gmock-generated-nice-strict.h \
+	src/testing/googlemock/include/gmock/gmock-matchers.h \
+	src/testing/googlemock/include/gmock/gmock-more-actions.h \
+	src/testing/googlemock/include/gmock/gmock-more-matchers.h \
+	src/testing/googlemock/include/gmock/gmock-spec-builders.h \
+	src/testing/googlemock/include/gmock/internal/custom/gmock-generated-actions.h \
+	src/testing/googlemock/include/gmock/internal/custom/gmock-matchers.h \
+	src/testing/googlemock/include/gmock/internal/custom/gmock-port.h \
+	src/testing/googlemock/include/gmock/internal/gmock-generated-internal-utils.h \
+	src/testing/googlemock/include/gmock/internal/gmock-internal-utils.h \
+	src/testing/googlemock/include/gmock/internal/gmock-port.h \
+	src/testing/googlemock/src/gmock.cc \
+	src/testing/googlemock/src/gmock-cardinalities.cc \
+	src/testing/googlemock/src/gmock-internal-utils.cc \
+	src/testing/googlemock/src/gmock-matchers.cc \
+	src/testing/googlemock/src/gmock-spec-builders.cc \
+	src/testing/googlemock/src/gmock_main.cc \
 	src/third_party/curl/COPYING \
 	src/third_party/curl/curlbuild.h \
 	src/third_party/curl/curl.h \
 	src/third_party/curl/curlrules.h \
 	src/third_party/curl/curlver.h \
 	src/third_party/curl/easy.h \
 	src/third_party/curl/mprintf.h \
 	src/third_party/curl/multi.h \
--- a/toolkit/crashreporter/google-breakpad/README.md
+++ b/toolkit/crashreporter/google-breakpad/README.md
@@ -3,17 +3,17 @@
 Breakpad is a set of client and server components which implement a
 crash-reporting system.
 
 * [Homepage](https://chromium.googlesource.com/breakpad/breakpad/)
 * [Documentation](https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/)
 * [Bugs](https://bugs.chromium.org/p/google-breakpad/)
 * Discussion/Questions: [google-breakpad-discuss@googlegroups.com](https://groups.google.com/d/forum/google-breakpad-discuss)
 * Developer/Reviews: [google-breakpad-dev@googlegroups.com](https://groups.google.com/d/forum/google-breakpad-dev)
-* Tests: [![Build Status](https://travis-ci.org/google/breakpad.svg?branch=master)](https://travis-ci.org/google/breakpad)
+* Tests: [![Build Status](https://travis-ci.org/google/breakpad.svg?branch=master)](https://travis-ci.org/google/breakpad) [![Build status](https://ci.appveyor.com/api/projects/status/eguv4emv2rhq68u2?svg=true)](https://ci.appveyor.com/project/vapier/breakpad)
 * Coverage [![Coverity Status](https://scan.coverity.com/projects/9215/badge.svg)](https://scan.coverity.com/projects/google-breakpad)
 
 ## Getting started (from master)
 
 1.  First, [download depot_tools](http://dev.chromium.org/developers/how-tos/install-depot-tools)
     and ensure that they’re in your `PATH`.
 
 2.  Create a new directory for checking out the source code (it must be named
--- a/toolkit/crashreporter/google-breakpad/aclocal.m4
+++ b/toolkit/crashreporter/google-breakpad/aclocal.m4
@@ -1290,8 +1290,15 @@ m4_if([$1], [v7],
 
   AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
   AC_MSG_RESULT([$am_cv_prog_tar_$1])])
 
 AC_SUBST([am__tar])
 AC_SUBST([am__untar])
 ]) # _AM_PROG_TAR
 
+m4_include([m4/ax_append_compile_flags.m4])
+m4_include([m4/ax_append_flag.m4])
+m4_include([m4/ax_check_compile_flag.m4])
+m4_include([m4/ax_check_define.m4])
+m4_include([m4/ax_cxx_compile_stdcxx.m4])
+m4_include([m4/ax_pthread.m4])
+m4_include([m4/ax_require_defined.m4])
deleted file mode 100755
--- a/toolkit/crashreporter/google-breakpad/autotools/compile
+++ /dev/null
@@ -1,347 +0,0 @@
-#! /bin/sh
-# Wrapper for compilers which do not understand '-c -o'.
-
-scriptversion=2012-10-14.11; # UTC
-
-# Copyright (C) 1999-2014 Free Software Foundation, Inc.
-# Written by Tom Tromey <tromey@cygnus.com>.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# This file is maintained in Automake, please report
-# bugs to <bug-automake@gnu.org> or send patches to
-# <automake-patches@gnu.org>.
-
-nl='
-'
-
-# We need space, tab and new line, in precisely that order.  Quoting is
-# there to prevent tools from complaining about whitespace usage.
-IFS=" ""	$nl"
-
-file_conv=
-
-# func_file_conv build_file lazy
-# Convert a $build file to $host form and store it in $file
-# Currently only supports Windows hosts. If the determined conversion
-# type is listed in (the comma separated) LAZY, no conversion will
-# take place.
-func_file_conv ()
-{
-  file=$1
-  case $file in
-    / | /[!/]*) # absolute file, and not a UNC file
-      if test -z "$file_conv"; then
-	# lazily determine how to convert abs files
-	case `uname -s` in
-	  MINGW*)
-	    file_conv=mingw
-	    ;;
-	  CYGWIN*)
-	    file_conv=cygwin
-	    ;;
-	  *)
-	    file_conv=wine
-	    ;;
-	esac
-      fi
-      case $file_conv/,$2, in
-	*,$file_conv,*)
-	  ;;
-	mingw/*)
-	  file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
-	  ;;
-	cygwin/*)
-	  file=`cygpath -m "$file" || echo "$file"`
-	  ;;
-	wine/*)
-	  file=`winepath -w "$file" || echo "$file"`
-	  ;;
-      esac
-      ;;
-  esac
-}
-
-# func_cl_dashL linkdir
-# Make cl look for libraries in LINKDIR
-func_cl_dashL ()
-{
-  func_file_conv "$1"
-  if test -z "$lib_path"; then
-    lib_path=$file
-  else
-    lib_path="$lib_path;$file"
-  fi
-  linker_opts="$linker_opts -LIBPATH:$file"
-}
-
-# func_cl_dashl library
-# Do a library search-path lookup for cl
-func_cl_dashl ()
-{
-  lib=$1
-  found=no
-  save_IFS=$IFS
-  IFS=';'
-  for dir in $lib_path $LIB
-  do
-    IFS=$save_IFS
-    if $shared && test -f "$dir/$lib.dll.lib"; then
-      found=yes
-      lib=$dir/$lib.dll.lib
-      break
-    fi
-    if test -f "$dir/$lib.lib"; then
-      found=yes
-      lib=$dir/$lib.lib
-      break
-    fi
-    if test -f "$dir/lib$lib.a"; then
-      found=yes
-      lib=$dir/lib$lib.a
-      break
-    fi
-  done
-  IFS=$save_IFS
-
-  if test "$found" != yes; then
-    lib=$lib.lib
-  fi
-}
-
-# func_cl_wrapper cl arg...
-# Adjust compile command to suit cl
-func_cl_wrapper ()
-{
-  # Assume a capable shell
-  lib_path=
-  shared=:
-  linker_opts=
-  for arg
-  do
-    if test -n "$eat"; then
-      eat=
-    else
-      case $1 in
-	-o)
-	  # configure might choose to run compile as 'compile cc -o foo foo.c'.
-	  eat=1
-	  case $2 in
-	    *.o | *.[oO][bB][jJ])
-	      func_file_conv "$2"
-	      set x "$@" -Fo"$file"
-	      shift
-	      ;;
-	    *)
-	      func_file_conv "$2"
-	      set x "$@" -Fe"$file"
-	      shift
-	      ;;
-	  esac
-	  ;;
-	-I)
-	  eat=1
-	  func_file_conv "$2" mingw
-	  set x "$@" -I"$file"
-	  shift
-	  ;;
-	-I*)
-	  func_file_conv "${1#-I}" mingw
-	  set x "$@" -I"$file"
-	  shift
-	  ;;
-	-l)
-	  eat=1
-	  func_cl_dashl "$2"
-	  set x "$@" "$lib"
-	  shift
-	  ;;
-	-l*)
-	  func_cl_dashl "${1#-l}"
-	  set x "$@" "$lib"
-	  shift
-	  ;;
-	-L)
-	  eat=1
-	  func_cl_dashL "$2"
-	  ;;
-	-L*)
-	  func_cl_dashL "${1#-L}"
-	  ;;
-	-static)
-	  shared=false
-	  ;;
-	-Wl,*)
-	  arg=${1#-Wl,}
-	  save_ifs="$IFS"; IFS=','
-	  for flag in $arg; do
-	    IFS="$save_ifs"
-	    linker_opts="$linker_opts $flag"
-	  done
-	  IFS="$save_ifs"
-	  ;;
-	-Xlinker)
-	  eat=1
-	  linker_opts="$linker_opts $2"
-	  ;;
-	-*)
-	  set x "$@" "$1"
-	  shift
-	  ;;
-	*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
-	  func_file_conv "$1"
-	  set x "$@" -Tp"$file"
-	  shift
-	  ;;
-	*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
-	  func_file_conv "$1" mingw
-	  set x "$@" "$file"
-	  shift
-	  ;;
-	*)
-	  set x "$@" "$1"
-	  shift
-	  ;;
-      esac
-    fi
-    shift
-  done
-  if test -n "$linker_opts"; then
-    linker_opts="-link$linker_opts"
-  fi
-  exec "$@" $linker_opts
-  exit 1
-}
-
-eat=
-
-case $1 in
-  '')
-     echo "$0: No command.  Try '$0 --help' for more information." 1>&2
-     exit 1;
-     ;;
-  -h | --h*)
-    cat <<\EOF
-Usage: compile [--help] [--version] PROGRAM [ARGS]
-
-Wrapper for compilers which do not understand '-c -o'.
-Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
-arguments, and rename the output as expected.
-
-If you are trying to build a whole package this is not the
-right script to run: please start by reading the file 'INSTALL'.
-
-Report bugs to <bug-automake@gnu.org>.
-EOF
-    exit $?
-    ;;
-  -v | --v*)
-    echo "compile $scriptversion"
-    exit $?
-    ;;
-  cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
-    func_cl_wrapper "$@"      # Doesn't return...
-    ;;
-esac
-
-ofile=
-cfile=
-
-for arg
-do
-  if test -n "$eat"; then
-    eat=
-  else
-    case $1 in
-      -o)
-	# configure might choose to run compile as 'compile cc -o foo foo.c'.
-	# So we strip '-o arg' only if arg is an object.
-	eat=1
-	case $2 in
-	  *.o | *.obj)
-	    ofile=$2
-	    ;;
-	  *)
-	    set x "$@" -o "$2"
-	    shift
-	    ;;
-	esac
-	;;
-      *.c)
-	cfile=$1
-	set x "$@" "$1"
-	shift
-	;;
-      *)
-	set x "$@" "$1"
-	shift
-	;;
-    esac
-  fi
-  shift
-done
-
-if test -z "$ofile" || test -z "$cfile"; then
-  # If no '-o' option was seen then we might have been invoked from a
-  # pattern rule where we don't need one.  That is ok -- this is a
-  # normal compilation that the losing compiler can handle.  If no
-  # '.c' file was seen then we are probably linking.  That is also
-  # ok.
-  exec "$@"
-fi
-
-# Name of file we expect compiler to create.
-cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
-
-# Create the lock directory.
-# Note: use '[/\\:.-]' here to ensure that we don't use the same name
-# that we are using for the .o file.  Also, base the name on the expected
-# object file name, since that is what matters with a parallel build.
-lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
-while true; do
-  if mkdir "$lockdir" >/dev/null 2>&1; then
-    break
-  fi
-  sleep 1
-done
-# FIXME: race condition here if user kills between mkdir and trap.
-trap "rmdir '$lockdir'; exit 1" 1 2 15
-
-# Run the compile.
-"$@"
-ret=$?
-
-if test -f "$cofile"; then
-  test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
-elif test -f "${cofile}bj"; then
-  test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
-fi
-
-rmdir "$lockdir"
-exit $ret
-
-# Local Variables:
-# mode: shell-script
-# sh-indentation: 2
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "scriptversion="
-# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-time-zone: "UTC"
-# time-stamp-end: "; # UTC"
-# End:
deleted file mode 100755
--- a/toolkit/crashreporter/google-breakpad/autotools/config.guess
+++ /dev/null
@@ -1,1447 +0,0 @@
-#! /bin/sh
-# Attempt to guess a canonical system name.
-#   Copyright 1992-2016 Free Software Foundation, Inc.
-
-timestamp='2016-01-01'
-
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that
-# program.  This Exception is an additional permission under section 7
-# of the GNU General Public License, version 3 ("GPLv3").
-#
-# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
-#
-# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
-#
-# Please send patches to <config-patches@gnu.org>.
-
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION]
-
-Output the configuration name of the system \`$me' is run on.
-
-Operation modes:
-  -h, --help         print this help, then exit
-  -t, --time-stamp   print date of last modification, then exit
-  -v, --version      print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.guess ($timestamp)
-
-Originally written by Per Bothner.
-Copyright 1992-2016 Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions.  There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
-  case $1 in
-    --time-stamp | --time* | -t )
-       echo "$timestamp" ; exit ;;
-    --version | -v )
-       echo "$version" ; exit ;;
-    --help | --h* | -h )
-       echo "$usage"; exit ;;
-    -- )     # Stop option processing
-       shift; break ;;
-    - )	# Use stdin as input.
-       break ;;
-    -* )
-       echo "$me: invalid option $1$help" >&2
-       exit 1 ;;
-    * )
-       break ;;
-  esac
-done
-
-if test $# != 0; then
-  echo "$me: too many arguments$help" >&2
-  exit 1
-fi
-
-trap 'exit 1' 1 2 15
-
-# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
-# compiler to aid in system detection is discouraged as it requires
-# temporary files to be created and, as you can see below, it is a
-# headache to deal with in a portable fashion.
-
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
-
-# Portable tmp directory creation inspired by the Autoconf team.
-
-set_cc_for_build='
-trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
-trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
-: ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
-dummy=$tmp/dummy ;
-tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case $CC_FOR_BUILD,$HOST_CC,$CC in
- ,,)    echo "int x;" > $dummy.c ;
-	for c in cc gcc c89 c99 ; do
-	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
-	     CC_FOR_BUILD="$c"; break ;
-	  fi ;
-	done ;
-	if test x"$CC_FOR_BUILD" = x ; then
-	  CC_FOR_BUILD=no_compiler_found ;
-	fi
-	;;
- ,,*)   CC_FOR_BUILD=$CC ;;
- ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
-esac ; set_cc_for_build= ;'
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 1994-08-24)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
-	PATH=$PATH:/.attbin ; export PATH
-fi
-
-UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
-UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
-UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-
-case "${UNAME_SYSTEM}" in
-Linux|GNU|GNU/*)
-	# If the system lacks a compiler, then just pick glibc.
-	# We could probably try harder.
-	LIBC=gnu
-
-	eval $set_cc_for_build
-	cat <<-EOF > $dummy.c
-	#include <features.h>
-	#if defined(__UCLIBC__)
-	LIBC=uclibc
-	#elif defined(__dietlibc__)
-	LIBC=dietlibc
-	#else
-	LIBC=gnu
-	#endif
-	EOF
-	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
-	;;
-esac
-
-# Note: order is significant - the case branches are not exclusive.
-
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
-    *:NetBSD:*:*)
-	# NetBSD (nbsd) targets should (where applicable) match one or
-	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
-	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
-	# switched to ELF, *-*-netbsd* would select the old
-	# object file format.  This provides both forward
-	# compatibility and a consistent mechanism for selecting the
-	# object file format.
-	#
-	# Note: NetBSD doesn't particularly care about the vendor
-	# portion of the name.  We always set it to "unknown".
-	sysctl="sysctl -n hw.machine_arch"
-	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
-	    /sbin/$sysctl 2>/dev/null || \
-	    /usr/sbin/$sysctl 2>/dev/null || \
-	    echo unknown)`
-	case "${UNAME_MACHINE_ARCH}" in
-	    armeb) machine=armeb-unknown ;;
-	    arm*) machine=arm-unknown ;;
-	    sh3el) machine=shl-unknown ;;
-	    sh3eb) machine=sh-unknown ;;
-	    sh5el) machine=sh5le-unknown ;;
-	    earmv*)
-		arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
-		endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
-		machine=${arch}${endian}-unknown
-		;;
-	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
-	esac
-	# The Operating System including object format, if it has switched
-	# to ELF recently, or will in the future.
-	case "${UNAME_MACHINE_ARCH}" in
-	    arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
-		eval $set_cc_for_build
-		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
-			| grep -q __ELF__
-		then
-		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
-		    # Return netbsd for either.  FIX?
-		    os=netbsd
-		else
-		    os=netbsdelf
-		fi
-		;;
-	    *)
-		os=netbsd
-		;;
-	esac
-	# Determine ABI tags.
-	case "${UNAME_MACHINE_ARCH}" in
-	    earm*)
-		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
-		abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
-		;;
-	esac
-	# The OS release
-	# Debian GNU/NetBSD machines have a different userland, and
-	# thus, need a distinct triplet. However, they do not need
-	# kernel version information, so it can be replaced with a
-	# suitable tag, in the style of linux-gnu.
-	case "${UNAME_VERSION}" in
-	    Debian*)
-		release='-gnu'
-		;;
-	    *)
-		release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
-		;;
-	esac
-	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
-	# contains redundant information, the shorter form:
-	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
-	echo "${machine}-${os}${release}${abi}"
-	exit ;;
-    *:Bitrig:*:*)
-	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
-	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
-	exit ;;
-    *:OpenBSD:*:*)
-	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
-	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
-	exit ;;
-    *:ekkoBSD:*:*)
-	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
-	exit ;;
-    *:SolidBSD:*:*)
-	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
-	exit ;;
-    macppc:MirBSD:*:*)
-	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
-	exit ;;
-    *:MirBSD:*:*)
-	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
-	exit ;;
-    *:Sortix:*:*)
-	echo ${UNAME_MACHINE}-unknown-sortix
-	exit ;;
-    alpha:OSF1:*:*)
-	case $UNAME_RELEASE in
-	*4.0)
-		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
-		;;
-	*5.*)
-		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
-		;;
-	esac
-	# According to Compaq, /usr/sbin/psrinfo has been available on
-	# OSF/1 and Tru64 systems produced since 1995.  I hope that
-	# covers most systems running today.  This code pipes the CPU
-	# types through head -n 1, so we only detect the type of CPU 0.
-	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
-	case "$ALPHA_CPU_TYPE" in
-	    "EV4 (21064)")
-		UNAME_MACHINE="alpha" ;;
-	    "EV4.5 (21064)")
-		UNAME_MACHINE="alpha" ;;
-	    "LCA4 (21066/21068)")
-		UNAME_MACHINE="alpha" ;;
-	    "EV5 (21164)")
-		UNAME_MACHINE="alphaev5" ;;
-	    "EV5.6 (21164A)")
-		UNAME_MACHINE="alphaev56" ;;
-	    "EV5.6 (21164PC)")
-		UNAME_MACHINE="alphapca56" ;;
-	    "EV5.7 (21164PC)")
-		UNAME_MACHINE="alphapca57" ;;
-	    "EV6 (21264)")
-		UNAME_MACHINE="alphaev6" ;;
-	    "EV6.7 (21264A)")
-		UNAME_MACHINE="alphaev67" ;;
-	    "EV6.8CB (21264C)")
-		UNAME_MACHINE="alphaev68" ;;
-	    "EV6.8AL (21264B)")
-		UNAME_MACHINE="alphaev68" ;;
-	    "EV6.8CX (21264D)")
-		UNAME_MACHINE="alphaev68" ;;
-	    "EV6.9A (21264/EV69A)")
-		UNAME_MACHINE="alphaev69" ;;
-	    "EV7 (21364)")
-		UNAME_MACHINE="alphaev7" ;;
-	    "EV7.9 (21364A)")
-		UNAME_MACHINE="alphaev79" ;;
-	esac
-	# A Pn.n version is a patched version.
-	# A Vn.n version is a released version.
-	# A Tn.n version is a released field test version.
-	# A Xn.n version is an unreleased experimental baselevel.
-	# 1.2 uses "1.2" for uname -r.
-	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
-	exitcode=$?
-	trap '' 0
-	exit $exitcode ;;
-    Alpha\ *:Windows_NT*:*)
-	# How do we know it's Interix rather than the generic POSIX subsystem?
-	# Should we change UNAME_MACHINE based on the output of uname instead
-	# of the specific Alpha model?
-	echo alpha-pc-interix
-	exit ;;
-    21064:Windows_NT:50:3)
-	echo alpha-dec-winnt3.5
-	exit ;;
-    Amiga*:UNIX_System_V:4.0:*)
-	echo m68k-unknown-sysv4
-	exit ;;
-    *:[Aa]miga[Oo][Ss]:*:*)
-	echo ${UNAME_MACHINE}-unknown-amigaos
-	exit ;;
-    *:[Mm]orph[Oo][Ss]:*:*)
-	echo ${UNAME_MACHINE}-unknown-morphos
-	exit ;;
-    *:OS/390:*:*)
-	echo i370-ibm-openedition
-	exit ;;
-    *:z/VM:*:*)
-	echo s390-ibm-zvmoe
-	exit ;;
-    *:OS400:*:*)
-	echo powerpc-ibm-os400
-	exit ;;
-    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
-	echo arm-acorn-riscix${UNAME_RELEASE}
-	exit ;;
-    arm*:riscos:*:*|arm*:RISCOS:*:*)
-	echo arm-unknown-riscos
-	exit ;;
-    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
-	echo hppa1.1-hitachi-hiuxmpp
-	exit ;;
-    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
-	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
-	if test "`(/bin/universe) 2>/dev/null`" = att ; then
-		echo pyramid-pyramid-sysv3
-	else
-		echo pyramid-pyramid-bsd
-	fi
-	exit ;;
-    NILE*:*:*:dcosx)
-	echo pyramid-pyramid-svr4
-	exit ;;
-    DRS?6000:unix:4.0:6*)
-	echo sparc-icl-nx6
-	exit ;;
-    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
-	case `/usr/bin/uname -p` in
-	    sparc) echo sparc-icl-nx7; exit ;;
-	esac ;;
-    s390x:SunOS:*:*)
-	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit ;;
-    sun4H:SunOS:5.*:*)
-	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit ;;
-    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
-	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit ;;
-    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
-	echo i386-pc-auroraux${UNAME_RELEASE}
-	exit ;;
-    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
-	eval $set_cc_for_build
-	SUN_ARCH="i386"
-	# If there is a compiler, see if it is configured for 64-bit objects.
-	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
-	# This test works for both compilers.
-	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
-	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
-		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
-		grep IS_64BIT_ARCH >/dev/null
-	    then
-		SUN_ARCH="x86_64"
-	    fi
-	fi
-	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit ;;
-    sun4*:SunOS:6*:*)
-	# According to config.sub, this is the proper way to canonicalize
-	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
-	# it's likely to be more like Solaris than SunOS4.
-	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit ;;
-    sun4*:SunOS:*:*)
-	case "`/usr/bin/arch -k`" in
-	    Series*|S4*)
-		UNAME_RELEASE=`uname -v`
-		;;
-	esac
-	# Japanese Language versions have a version number like `4.1.3-JL'.
-	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
-	exit ;;
-    sun3*:SunOS:*:*)
-	echo m68k-sun-sunos${UNAME_RELEASE}
-	exit ;;
-    sun*:*:4.2BSD:*)
-	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
-	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
-	case "`/bin/arch`" in
-	    sun3)
-		echo m68k-sun-sunos${UNAME_RELEASE}
-		;;
-	    sun4)
-		echo sparc-sun-sunos${UNAME_RELEASE}
-		;;
-	esac
-	exit ;;
-    aushp:SunOS:*:*)
-	echo sparc-auspex-sunos${UNAME_RELEASE}
-	exit ;;
-    # The situation for MiNT is a little confusing.  The machine name
-    # can be virtually everything (everything which is not
-    # "atarist" or "atariste" at least should have a processor
-    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
-    # to the lowercase version "mint" (or "freemint").  Finally
-    # the system name "TOS" denotes a system which is actually not
-    # MiNT.  But MiNT is downward compatible to TOS, so this should
-    # be no problem.
-    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-	echo m68k-atari-mint${UNAME_RELEASE}
-	exit ;;
-    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
-	echo m68k-atari-mint${UNAME_RELEASE}
-	exit ;;
-    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-	echo m68k-atari-mint${UNAME_RELEASE}
-	exit ;;
-    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-	echo m68k-milan-mint${UNAME_RELEASE}
-	exit ;;
-    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-	echo m68k-hades-mint${UNAME_RELEASE}
-	exit ;;
-    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-	echo m68k-unknown-mint${UNAME_RELEASE}
-	exit ;;
-    m68k:machten:*:*)
-	echo m68k-apple-machten${UNAME_RELEASE}
-	exit ;;
-    powerpc:machten:*:*)
-	echo powerpc-apple-machten${UNAME_RELEASE}
-	exit ;;
-    RISC*:Mach:*:*)
-	echo mips-dec-mach_bsd4.3
-	exit ;;
-    RISC*:ULTRIX:*:*)
-	echo mips-dec-ultrix${UNAME_RELEASE}
-	exit ;;
-    VAX*:ULTRIX*:*:*)
-	echo vax-dec-ultrix${UNAME_RELEASE}
-	exit ;;
-    2020:CLIX:*:* | 2430:CLIX:*:*)
-	echo clipper-intergraph-clix${UNAME_RELEASE}
-	exit ;;
-    mips:*:*:UMIPS | mips:*:*:RISCos)
-	eval $set_cc_for_build
-	sed 's/^	//' << EOF >$dummy.c
-#ifdef __cplusplus
-#include <stdio.h>  /* for printf() prototype */
-	int main (int argc, char *argv[]) {
-#else
-	int main (argc, argv) int argc; char *argv[]; {
-#endif
-	#if defined (host_mips) && defined (MIPSEB)
-	#if defined (SYSTYPE_SYSV)
-	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
-	#endif
-	#if defined (SYSTYPE_SVR4)
-	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
-	#endif
-	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
-	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
-	#endif
-	#endif
-	  exit (-1);
-	}
-EOF
-	$CC_FOR_BUILD -o $dummy $dummy.c &&
-	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
-	  SYSTEM_NAME=`$dummy $dummyarg` &&
-	    { echo "$SYSTEM_NAME"; exit; }
-	echo mips-mips-riscos${UNAME_RELEASE}
-	exit ;;
-    Motorola:PowerMAX_OS:*:*)
-	echo powerpc-motorola-powermax
-	exit ;;
-    Motorola:*:4.3:PL8-*)
-	echo powerpc-harris-powermax
-	exit ;;
-    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
-	echo powerpc-harris-powermax
-	exit ;;
-    Night_Hawk:Power_UNIX:*:*)
-	echo powerpc-harris-powerunix
-	exit ;;
-    m88k:CX/UX:7*:*)
-	echo m88k-harris-cxux7
-	exit ;;
-    m88k:*:4*:R4*)
-	echo m88k-motorola-sysv4
-	exit ;;
-    m88k:*:3*:R3*)
-	echo m88k-motorola-sysv3
-	exit ;;
-    AViiON:dgux:*:*)
-	# DG/UX returns AViiON for all architectures
-	UNAME_PROCESSOR=`/usr/bin/uname -p`
-	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
-	then
-	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
-	       [ ${TARGET_BINARY_INTERFACE}x = x ]
-	    then
-		echo m88k-dg-dgux${UNAME_RELEASE}
-	    else
-		echo m88k-dg-dguxbcs${UNAME_RELEASE}
-	    fi
-	else
-	    echo i586-dg-dgux${UNAME_RELEASE}
-	fi
-	exit ;;
-    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
-	echo m88k-dolphin-sysv3
-	exit ;;
-    M88*:*:R3*:*)
-	# Delta 88k system running SVR3
-	echo m88k-motorola-sysv3
-	exit ;;
-    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
-	echo m88k-tektronix-sysv3
-	exit ;;
-    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
-	echo m68k-tektronix-bsd
-	exit ;;
-    *:IRIX*:*:*)
-	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
-	exit ;;
-    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
-	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
-	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
-    i*86:AIX:*:*)
-	echo i386-ibm-aix
-	exit ;;
-    ia64:AIX:*:*)
-	if [ -x /usr/bin/oslevel ] ; then
-		IBM_REV=`/usr/bin/oslevel`
-	else
-		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
-	fi
-	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
-	exit ;;
-    *:AIX:2:3)
-	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
-		eval $set_cc_for_build
-		sed 's/^		//' << EOF >$dummy.c
-		#include <sys/systemcfg.h>
-
-		main()
-			{
-			if (!__power_pc())
-				exit(1);
-			puts("powerpc-ibm-aix3.2.5");
-			exit(0);
-			}
-EOF
-		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
-		then
-			echo "$SYSTEM_NAME"
-		else
-			echo rs6000-ibm-aix3.2.5
-		fi
-	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
-		echo rs6000-ibm-aix3.2.4
-	else
-		echo rs6000-ibm-aix3.2
-	fi
-	exit ;;
-    *:AIX:*:[4567])
-	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
-	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
-		IBM_ARCH=rs6000
-	else
-		IBM_ARCH=powerpc
-	fi
-	if [ -x /usr/bin/lslpp ] ; then
-		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
-			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
-	else
-		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
-	fi
-	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
-	exit ;;
-    *:AIX:*:*)
-	echo rs6000-ibm-aix
-	exit ;;
-    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
-	echo romp-ibm-bsd4.4
-	exit ;;
-    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
-	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
-	exit ;;                             # report: romp-ibm BSD 4.3
-    *:BOSX:*:*)
-	echo rs6000-bull-bosx
-	exit ;;
-    DPX/2?00:B.O.S.:*:*)
-	echo m68k-bull-sysv3
-	exit ;;
-    9000/[34]??:4.3bsd:1.*:*)
-	echo m68k-hp-bsd
-	exit ;;
-    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
-	echo m68k-hp-bsd4.4
-	exit ;;
-    9000/[34678]??:HP-UX:*:*)
-	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
-	case "${UNAME_MACHINE}" in
-	    9000/31? )            HP_ARCH=m68000 ;;
-	    9000/[34]?? )         HP_ARCH=m68k ;;
-	    9000/[678][0-9][0-9])
-		if [ -x /usr/bin/getconf ]; then
-		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
-		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
-		    case "${sc_cpu_version}" in
-		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
-		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
-		      532)                      # CPU_PA_RISC2_0
-			case "${sc_kernel_bits}" in
-			  32) HP_ARCH="hppa2.0n" ;;
-			  64) HP_ARCH="hppa2.0w" ;;
-			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
-			esac ;;
-		    esac
-		fi
-		if [ "${HP_ARCH}" = "" ]; then
-		    eval $set_cc_for_build
-		    sed 's/^		//' << EOF >$dummy.c
-
-		#define _HPUX_SOURCE
-		#include <stdlib.h>
-		#include <unistd.h>
-
-		int main ()
-		{
-		#if defined(_SC_KERNEL_BITS)
-		    long bits = sysconf(_SC_KERNEL_BITS);
-		#endif
-		    long cpu  = sysconf (_SC_CPU_VERSION);
-
-		    switch (cpu)
-			{
-			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
-			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
-			case CPU_PA_RISC2_0:
-		#if defined(_SC_KERNEL_BITS)
-			    switch (bits)
-				{
-				case 64: puts ("hppa2.0w"); break;
-				case 32: puts ("hppa2.0n"); break;
-				default: puts ("hppa2.0"); break;
-				} break;
-		#else  /* !defined(_SC_KERNEL_BITS) */
-			    puts ("hppa2.0"); break;
-		#endif
-			default: puts ("hppa1.0"); break;
-			}
-		    exit (0);
-		}
-EOF
-		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
-		    test -z "$HP_ARCH" && HP_ARCH=hppa
-		fi ;;
-	esac
-	if [ ${HP_ARCH} = "hppa2.0w" ]
-	then
-	    eval $set_cc_for_build
-
-	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
-	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
-	    # generating 64-bit code.  GNU and HP use different nomenclature:
-	    #
-	    # $ CC_FOR_BUILD=cc ./config.guess
-	    # => hppa2.0w-hp-hpux11.23
-	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
-	    # => hppa64-hp-hpux11.23
-
-	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
-		grep -q __LP64__
-	    then
-		HP_ARCH="hppa2.0w"
-	    else
-		HP_ARCH="hppa64"
-	    fi
-	fi
-	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
-	exit ;;
-    ia64:HP-UX:*:*)
-	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
-	echo ia64-hp-hpux${HPUX_REV}
-	exit ;;
-    3050*:HI-UX:*:*)
-	eval $set_cc_for_build
-	sed 's/^	//' << EOF >$dummy.c
-	#include <unistd.h>
-	int
-	main ()
-	{
-	  long cpu = sysconf (_SC_CPU_VERSION);
-	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
-	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
-	     results, however.  */
-	  if (CPU_IS_PA_RISC (cpu))
-	    {
-	      switch (cpu)
-		{
-		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
-		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
-		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
-		  default: puts ("hppa-hitachi-hiuxwe2"); break;
-		}
-	    }
-	  else if (CPU_IS_HP_MC68K (cpu))
-	    puts ("m68k-hitachi-hiuxwe2");
-	  else puts ("unknown-hitachi-hiuxwe2");
-	  exit (0);
-	}
-EOF
-	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
-		{ echo "$SYSTEM_NAME"; exit; }
-	echo unknown-hitachi-hiuxwe2
-	exit ;;
-    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
-	echo hppa1.1-hp-bsd
-	exit ;;
-    9000/8??:4.3bsd:*:*)
-	echo hppa1.0-hp-bsd
-	exit ;;
-    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
-	echo hppa1.0-hp-mpeix
-	exit ;;
-    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
-	echo hppa1.1-hp-osf
-	exit ;;
-    hp8??:OSF1:*:*)
-	echo hppa1.0-hp-osf
-	exit ;;
-    i*86:OSF1:*:*)
-	if [ -x /usr/sbin/sysversion ] ; then
-	    echo ${UNAME_MACHINE}-unknown-osf1mk
-	else
-	    echo ${UNAME_MACHINE}-unknown-osf1
-	fi
-	exit ;;
-    parisc*:Lites*:*:*)
-	echo hppa1.1-hp-lites
-	exit ;;
-    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
-	echo c1-convex-bsd
-	exit ;;
-    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
-	if getsysinfo -f scalar_acc
-	then echo c32-convex-bsd
-	else echo c2-convex-bsd
-	fi
-	exit ;;
-    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
-	echo c34-convex-bsd
-	exit ;;
-    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
-	echo c38-convex-bsd
-	exit ;;
-    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
-	echo c4-convex-bsd
-	exit ;;
-    CRAY*Y-MP:*:*:*)
-	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
-    CRAY*[A-Z]90:*:*:*)
-	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
-	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-	      -e 's/\.[^.]*$/.X/'
-	exit ;;
-    CRAY*TS:*:*:*)
-	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
-    CRAY*T3E:*:*:*)
-	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
-    CRAY*SV1:*:*:*)
-	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
-    *:UNICOS/mp:*:*)
-	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
-    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
-	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
-	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-	exit ;;
-    5000:UNIX_System_V:4.*:*)
-	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
-	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-	exit ;;
-    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
-	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
-	exit ;;
-    sparc*:BSD/OS:*:*)
-	echo sparc-unknown-bsdi${UNAME_RELEASE}
-	exit ;;
-    *:BSD/OS:*:*)
-	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
-	exit ;;
-    *:FreeBSD:*:*)
-	UNAME_PROCESSOR=`/usr/bin/uname -p`
-	case ${UNAME_PROCESSOR} in
-	    amd64)
-		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
-	    *)
-		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
-	esac
-	exit ;;
-    i*:CYGWIN*:*)
-	echo ${UNAME_MACHINE}-pc-cygwin
-	exit ;;
-    *:MINGW64*:*)
-	echo ${UNAME_MACHINE}-pc-mingw64
-	exit ;;
-    *:MINGW*:*)
-	echo ${UNAME_MACHINE}-pc-mingw32
-	exit ;;
-    *:MSYS*:*)
-	echo ${UNAME_MACHINE}-pc-msys
-	exit ;;
-    i*:windows32*:*)
-	# uname -m includes "-pc" on this system.
-	echo ${UNAME_MACHINE}-mingw32
-	exit ;;
-    i*:PW*:*)
-	echo ${UNAME_MACHINE}-pc-pw32
-	exit ;;
-    *:Interix*:*)
-	case ${UNAME_MACHINE} in
-	    x86)
-		echo i586-pc-interix${UNAME_RELEASE}
-		exit ;;
-	    authenticamd | genuineintel | EM64T)
-		echo x86_64-unknown-interix${UNAME_RELEASE}
-		exit ;;
-	    IA64)
-		echo ia64-unknown-interix${UNAME_RELEASE}
-		exit ;;
-	esac ;;
-    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
-	echo i${UNAME_MACHINE}-pc-mks
-	exit ;;
-    8664:Windows_NT:*)
-	echo x86_64-pc-mks
-	exit ;;
-    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
-	# How do we know it's Interix rather than the generic POSIX subsystem?
-	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
-	# UNAME_MACHINE based on the output of uname instead of i386?
-	echo i586-pc-interix
-	exit ;;
-    i*:UWIN*:*)
-	echo ${UNAME_MACHINE}-pc-uwin
-	exit ;;
-    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
-	echo x86_64-unknown-cygwin
-	exit ;;
-    p*:CYGWIN*:*)
-	echo powerpcle-unknown-cygwin
-	exit ;;
-    prep*:SunOS:5.*:*)
-	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-	exit ;;
-    *:GNU:*:*)
-	# the GNU system
-	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
-	exit ;;
-    *:GNU/*:*:*)
-	# other systems with GNU libc and userland
-	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
-	exit ;;
-    i*86:Minix:*:*)
-	echo ${UNAME_MACHINE}-pc-minix
-	exit ;;
-    aarch64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    aarch64_be:Linux:*:*)
-	UNAME_MACHINE=aarch64_be
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    alpha:Linux:*:*)
-	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
-	  EV5)   UNAME_MACHINE=alphaev5 ;;
-	  EV56)  UNAME_MACHINE=alphaev56 ;;
-	  PCA56) UNAME_MACHINE=alphapca56 ;;
-	  PCA57) UNAME_MACHINE=alphapca56 ;;
-	  EV6)   UNAME_MACHINE=alphaev6 ;;
-	  EV67)  UNAME_MACHINE=alphaev67 ;;
-	  EV68*) UNAME_MACHINE=alphaev68 ;;
-	esac
-	objdump --private-headers /bin/sh | grep -q ld.so.1
-	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    arc:Linux:*:* | arceb:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    arm*:Linux:*:*)
-	eval $set_cc_for_build
-	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
-	    | grep -q __ARM_EABI__
-	then
-	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	else
-	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
-		| grep -q __ARM_PCS_VFP
-	    then
-		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
-	    else
-		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
-	    fi
-	fi
-	exit ;;
-    avr32*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    cris:Linux:*:*)
-	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
-	exit ;;
-    crisv32:Linux:*:*)
-	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
-	exit ;;
-    e2k:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    frv:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    hexagon:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    i*86:Linux:*:*)
-	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
-	exit ;;
-    ia64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    k1om:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    m32r*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    m68*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    mips:Linux:*:* | mips64:Linux:*:*)
-	eval $set_cc_for_build
-	sed 's/^	//' << EOF >$dummy.c
-	#undef CPU
-	#undef ${UNAME_MACHINE}
-	#undef ${UNAME_MACHINE}el
-	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
-	CPU=${UNAME_MACHINE}el
-	#else
-	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
-	CPU=${UNAME_MACHINE}
-	#else
-	CPU=
-	#endif
-	#endif
-EOF
-	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
-	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
-	;;
-    openrisc*:Linux:*:*)
-	echo or1k-unknown-linux-${LIBC}
-	exit ;;
-    or32:Linux:*:* | or1k*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    padre:Linux:*:*)
-	echo sparc-unknown-linux-${LIBC}
-	exit ;;
-    parisc64:Linux:*:* | hppa64:Linux:*:*)
-	echo hppa64-unknown-linux-${LIBC}
-	exit ;;
-    parisc:Linux:*:* | hppa:Linux:*:*)
-	# Look for CPU level
-	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
-	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
-	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
-	  *)    echo hppa-unknown-linux-${LIBC} ;;
-	esac
-	exit ;;
-    ppc64:Linux:*:*)
-	echo powerpc64-unknown-linux-${LIBC}
-	exit ;;
-    ppc:Linux:*:*)
-	echo powerpc-unknown-linux-${LIBC}
-	exit ;;
-    ppc64le:Linux:*:*)
-	echo powerpc64le-unknown-linux-${LIBC}
-	exit ;;
-    ppcle:Linux:*:*)
-	echo powerpcle-unknown-linux-${LIBC}
-	exit ;;
-    s390:Linux:*:* | s390x:Linux:*:*)
-	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
-	exit ;;
-    sh64*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    sh*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    sparc:Linux:*:* | sparc64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    tile*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    vax:Linux:*:*)
-	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
-	exit ;;
-    x86_64:Linux:*:*)
-	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
-	exit ;;
-    xtensa*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
-	exit ;;
-    i*86:DYNIX/ptx:4*:*)
-	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
-	# earlier versions are messed up and put the nodename in both
-	# sysname and nodename.
-	echo i386-sequent-sysv4
-	exit ;;
-    i*86:UNIX_SV:4.2MP:2.*)
-	# Unixware is an offshoot of SVR4, but it has its own version
-	# number series starting with 2...
-	# I am not positive that other SVR4 systems won't match this,
-	# I just have to hope.  -- rms.
-	# Use sysv4.2uw... so that sysv4* matches it.
-	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
-	exit ;;
-    i*86:OS/2:*:*)
-	# If we were able to find `uname', then EMX Unix compatibility
-	# is probably installed.
-	echo ${UNAME_MACHINE}-pc-os2-emx
-	exit ;;
-    i*86:XTS-300:*:STOP)
-	echo ${UNAME_MACHINE}-unknown-stop
-	exit ;;
-    i*86:atheos:*:*)
-	echo ${UNAME_MACHINE}-unknown-atheos
-	exit ;;
-    i*86:syllable:*:*)
-	echo ${UNAME_MACHINE}-pc-syllable
-	exit ;;
-    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
-	echo i386-unknown-lynxos${UNAME_RELEASE}
-	exit ;;
-    i*86:*DOS:*:*)
-	echo ${UNAME_MACHINE}-pc-msdosdjgpp
-	exit ;;
-    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
-	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
-	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
-		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
-	else
-		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
-	fi
-	exit ;;
-    i*86:*:5:[678]*)
-	# UnixWare 7.x, OpenUNIX and OpenServer 6.
-	case `/bin/uname -X | grep "^Machine"` in
-	    *486*)	     UNAME_MACHINE=i486 ;;
-	    *Pentium)	     UNAME_MACHINE=i586 ;;
-	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
-	esac
-	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
-	exit ;;
-    i*86:*:3.2:*)
-	if test -f /usr/options/cb.name; then
-		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
-		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
-	elif /bin/uname -X 2>/dev/null >/dev/null ; then
-		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
-		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
-		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
-			&& UNAME_MACHINE=i586
-		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
-			&& UNAME_MACHINE=i686
-		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
-			&& UNAME_MACHINE=i686
-		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
-	else
-		echo ${UNAME_MACHINE}-pc-sysv32
-	fi
-	exit ;;
-    pc:*:*:*)
-	# Left here for compatibility:
-	# uname -m prints for DJGPP always 'pc', but it prints nothing about
-	# the processor, so we play safe by assuming i586.
-	# Note: whatever this is, it MUST be the same as what config.sub
-	# prints for the "djgpp" host, or else GDB configure will decide that
-	# this is a cross-build.
-	echo i586-pc-msdosdjgpp
-	exit ;;
-    Intel:Mach:3*:*)
-	echo i386-pc-mach3
-	exit ;;
-    paragon:*:*:*)
-	echo i860-intel-osf1
-	exit ;;
-    i860:*:4.*:*) # i860-SVR4
-	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
-	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
-	else # Add other i860-SVR4 vendors below as they are discovered.
-	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
-	fi
-	exit ;;
-    mini*:CTIX:SYS*5:*)
-	# "miniframe"
-	echo m68010-convergent-sysv
-	exit ;;
-    mc68k:UNIX:SYSTEM5:3.51m)
-	echo m68k-convergent-sysv
-	exit ;;
-    M680?0:D-NIX:5.3:*)
-	echo m68k-diab-dnix
-	exit ;;
-    M68*:*:R3V[5678]*:*)
-	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
-    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
-	OS_REL=''
-	test -r /etc/.relid \
-	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
-	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
-	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
-    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
-	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-	  && { echo i486-ncr-sysv4; exit; } ;;
-    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
-	OS_REL='.3'
-	test -r /etc/.relid \
-	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
-	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
-	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
-	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
-	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
-    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
-	echo m68k-unknown-lynxos${UNAME_RELEASE}
-	exit ;;
-    mc68030:UNIX_System_V:4.*:*)
-	echo m68k-atari-sysv4
-	exit ;;
-    TSUNAMI:LynxOS:2.*:*)
-	echo sparc-unknown-lynxos${UNAME_RELEASE}
-	exit ;;
-    rs6000:LynxOS:2.*:*)
-	echo rs6000-unknown-lynxos${UNAME_RELEASE}
-	exit ;;
-    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
-	echo powerpc-unknown-lynxos${UNAME_RELEASE}
-	exit ;;
-    SM[BE]S:UNIX_SV:*:*)
-	echo mips-dde-sysv${UNAME_RELEASE}
-	exit ;;
-    RM*:ReliantUNIX-*:*:*)
-	echo mips-sni-sysv4
-	exit ;;
-    RM*:SINIX-*:*:*)
-	echo mips-sni-sysv4
-	exit ;;
-    *:SINIX-*:*:*)
-	if uname -p 2>/dev/null >/dev/null ; then
-		UNAME_MACHINE=`(uname -p) 2>/dev/null`
-		echo ${UNAME_MACHINE}-sni-sysv4
-	else
-		echo ns32k-sni-sysv
-	fi
-	exit ;;
-    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
-			# says <Richard.M.Bartel@ccMail.Census.GOV>
-	echo i586-unisys-sysv4
-	exit ;;
-    *:UNIX_System_V:4*:FTX*)
-	# From Gerald Hewes <hewes@openmarket.com>.
-	# How about differentiating between stratus architectures? -djm
-	echo hppa1.1-stratus-sysv4
-	exit ;;
-    *:*:*:FTX*)
-	# From seanf@swdc.stratus.com.
-	echo i860-stratus-sysv4
-	exit ;;
-    i*86:VOS:*:*)
-	# From Paul.Green@stratus.com.
-	echo ${UNAME_MACHINE}-stratus-vos
-	exit ;;
-    *:VOS:*:*)
-	# From Paul.Green@stratus.com.
-	echo hppa1.1-stratus-vos
-	exit ;;
-    mc68*:A/UX:*:*)
-	echo m68k-apple-aux${UNAME_RELEASE}
-	exit ;;
-    news*:NEWS-OS:6*:*)
-	echo mips-sony-newsos6
-	exit ;;
-    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
-	if [ -d /usr/nec ]; then
-		echo mips-nec-sysv${UNAME_RELEASE}
-	else
-		echo mips-unknown-sysv${UNAME_RELEASE}
-	fi
-	exit ;;
-    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
-	echo powerpc-be-beos
-	exit ;;
-    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
-	echo powerpc-apple-beos
-	exit ;;
-    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
-	echo i586-pc-beos
-	exit ;;
-    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
-	echo i586-pc-haiku
-	exit ;;
-    x86_64:Haiku:*:*)
-	echo x86_64-unknown-haiku
-	exit ;;
-    SX-4:SUPER-UX:*:*)
-	echo sx4-nec-superux${UNAME_RELEASE}
-	exit ;;
-    SX-5:SUPER-UX:*:*)
-	echo sx5-nec-superux${UNAME_RELEASE}
-	exit ;;
-    SX-6:SUPER-UX:*:*)
-	echo sx6-nec-superux${UNAME_RELEASE}
-	exit ;;
-    SX-7:SUPER-UX:*:*)
-	echo sx7-nec-superux${UNAME_RELEASE}
-	exit ;;
-    SX-8:SUPER-UX:*:*)
-	echo sx8-nec-superux${UNAME_RELEASE}
-	exit ;;
-    SX-8R:SUPER-UX:*:*)
-	echo sx8r-nec-superux${UNAME_RELEASE}
-	exit ;;
-    Power*:Rhapsody:*:*)
-	echo powerpc-apple-rhapsody${UNAME_RELEASE}
-	exit ;;
-    *:Rhapsody:*:*)
-	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
-	exit ;;
-    *:Darwin:*:*)
-	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
-	eval $set_cc_for_build
-	if test "$UNAME_PROCESSOR" = unknown ; then
-	    UNAME_PROCESSOR=powerpc
-	fi
-	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
-	    if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
-		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
-		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
-		    grep IS_64BIT_ARCH >/dev/null
-		then
-		    case $UNAME_PROCESSOR in
-			i386) UNAME_PROCESSOR=x86_64 ;;
-			powerpc) UNAME_PROCESSOR=powerpc64 ;;
-		    esac
-		fi
-	    fi
-	elif test "$UNAME_PROCESSOR" = i386 ; then
-	    # Avoid executing cc on OS X 10.9, as it ships with a stub
-	    # that puts up a graphical alert prompting to install
-	    # developer tools.  Any system running Mac OS X 10.7 or
-	    # later (Darwin 11 and later) is required to have a 64-bit
-	    # processor. This is not true of the ARM version of Darwin
-	    # that Apple uses in portable devices.
-	    UNAME_PROCESSOR=x86_64
-	fi
-	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
-	exit ;;
-    *:procnto*:*:* | *:QNX:[0123456789]*:*)
-	UNAME_PROCESSOR=`uname -p`
-	if test "$UNAME_PROCESSOR" = "x86"; then
-		UNAME_PROCESSOR=i386
-		UNAME_MACHINE=pc
-	fi
-	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
-	exit ;;
-    *:QNX:*:4*)
-	echo i386-pc-qnx
-	exit ;;
-    NEO-?:NONSTOP_KERNEL:*:*)
-	echo neo-tandem-nsk${UNAME_RELEASE}
-	exit ;;
-    NSE-*:NONSTOP_KERNEL:*:*)
-	echo nse-tandem-nsk${UNAME_RELEASE}
-	exit ;;
-    NSR-?:NONSTOP_KERNEL:*:*)
-	echo nsr-tandem-nsk${UNAME_RELEASE}
-	exit ;;
-    *:NonStop-UX:*:*)
-	echo mips-compaq-nonstopux
-	exit ;;
-    BS2000:POSIX*:*:*)
-	echo bs2000-siemens-sysv
-	exit ;;
-    DS/*:UNIX_System_V:*:*)
-	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
-	exit ;;
-    *:Plan9:*:*)
-	# "uname -m" is not consistent, so use $cputype instead. 386
-	# is converted to i386 for consistency with other x86
-	# operating systems.
-	if test "$cputype" = "386"; then
-	    UNAME_MACHINE=i386
-	else
-	    UNAME_MACHINE="$cputype"
-	fi
-	echo ${UNAME_MACHINE}-unknown-plan9
-	exit ;;
-    *:TOPS-10:*:*)
-	echo pdp10-unknown-tops10
-	exit ;;
-    *:TENEX:*:*)
-	echo pdp10-unknown-tenex
-	exit ;;
-    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
-	echo pdp10-dec-tops20
-	exit ;;
-    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
-	echo pdp10-xkl-tops20
-	exit ;;
-    *:TOPS-20:*:*)
-	echo pdp10-unknown-tops20
-	exit ;;
-    *:ITS:*:*)
-	echo pdp10-unknown-its
-	exit ;;
-    SEI:*:*:SEIUX)
-	echo mips-sei-seiux${UNAME_RELEASE}
-	exit ;;
-    *:DragonFly:*:*)
-	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
-	exit ;;
-    *:*VMS:*:*)
-	UNAME_MACHINE=`(uname -p) 2>/dev/null`
-	case "${UNAME_MACHINE}" in
-	    A*) echo alpha-dec-vms ; exit ;;
-	    I*) echo ia64-dec-vms ; exit ;;
-	    V*) echo vax-dec-vms ; exit ;;
-	esac ;;
-    *:XENIX:*:SysV)
-	echo i386-pc-xenix
-	exit ;;
-    i*86:skyos:*:*)
-	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
-	exit ;;
-    i*86:rdos:*:*)
-	echo ${UNAME_MACHINE}-pc-rdos
-	exit ;;
-    i*86:AROS:*:*)
-	echo ${UNAME_MACHINE}-pc-aros
-	exit ;;
-    x86_64:VMkernel:*:*)
-	echo ${UNAME_MACHINE}-unknown-esx
-	exit ;;
-    amd64:Isilon\ OneFS:*:*)
-	echo x86_64-unknown-onefs
-	exit ;;
-esac
-
-cat >&2 <<EOF
-$0: unable to guess system type
-
-This script, last modified $timestamp, has failed to recognize
-the operating system you are using. It is advised that you
-download the most up to date version of the config scripts from
-
-  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
-and
-  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
-
-If the version you run ($0) is already up to date, please
-send the following data and any information you think might be
-pertinent to <config-patches@gnu.org> in order to provide the needed
-information to handle your system.
-
-config.guess timestamp = $timestamp
-
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
-/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
-
-hostinfo               = `(hostinfo) 2>/dev/null`
-/bin/universe          = `(/bin/universe) 2>/dev/null`
-/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
-/bin/arch              = `(/bin/arch) 2>/dev/null`
-/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
-
-UNAME_MACHINE = ${UNAME_MACHINE}
-UNAME_RELEASE = ${UNAME_RELEASE}
-UNAME_SYSTEM  = ${UNAME_SYSTEM}
-UNAME_VERSION = ${UNAME_VERSION}
-EOF
-
-exit 1
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
deleted file mode 100755
--- a/toolkit/crashreporter/google-breakpad/autotools/config.sub
+++ /dev/null
@@ -1,1813 +0,0 @@
-#! /bin/sh
-# Configuration validation subroutine script.
-#   Copyright 1992-2016 Free Software Foundation, Inc.
-
-timestamp='2016-01-01'
-
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that
-# program.  This Exception is an additional permission under section 7
-# of the GNU General Public License, version 3 ("GPLv3").
-
-
-# Please send patches to <config-patches@gnu.org>.
-#
-# Configuration subroutine to validate and canonicalize a configuration type.
-# Supply the specified configuration type as an argument.
-# If it is invalid, we print an error message on stderr and exit with code 1.
-# Otherwise, we print the canonical config type on stdout and succeed.
-
-# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
-
-# This file is supposed to be the same for all GNU packages
-# and recognize all the CPU types, system types and aliases
-# that are meaningful with *any* GNU software.
-# Each package is responsible for reporting which valid configurations
-# it does not support.  The user should be able to distinguish
-# a failure to support a valid configuration from a meaningless
-# configuration.
-
-# The goal of this file is to map all the various variations of a given
-# machine specification into a single specification in the form:
-#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
-# or in some cases, the newer four-part form:
-#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
-# It is wrong to echo any other type of specification.
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
-
-Canonicalize a configuration name.
-
-Operation modes:
-  -h, --help         print this help, then exit
-  -t, --time-stamp   print date of last modification, then exit
-  -v, --version      print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.sub ($timestamp)
-
-Copyright 1992-2016 Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions.  There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
-  case $1 in
-    --time-stamp | --time* | -t )
-       echo "$timestamp" ; exit ;;
-    --version | -v )
-       echo "$version" ; exit ;;
-    --help | --h* | -h )
-       echo "$usage"; exit ;;
-    -- )     # Stop option processing
-       shift; break ;;
-    - )	# Use stdin as input.
-       break ;;
-    -* )
-       echo "$me: invalid option $1$help"
-       exit 1 ;;
-
-    *local*)
-       # First pass through any local machine types.
-       echo $1
-       exit ;;
-
-    * )
-       break ;;
-  esac
-done
-
-case $# in
- 0) echo "$me: missing argument$help" >&2
-    exit 1;;
- 1) ;;
- *) echo "$me: too many arguments$help" >&2
-    exit 1;;
-esac
-
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
-case $maybe_os in
-  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
-  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
-  knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
-  kopensolaris*-gnu* | \
-  storm-chaos* | os2-emx* | rtmk-nova*)
-    os=-$maybe_os
-    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
-    ;;
-  android-linux)
-    os=-linux-android
-    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
-    ;;
-  *)
-    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
-    if [ $basic_machine != $1 ]
-    then os=`echo $1 | sed 's/.*-/-/'`
-    else os=; fi
-    ;;
-esac
-
-### Let's recognize common machines as not being operating systems so
-### that things like config.sub decstation-3100 work.  We also
-### recognize some manufacturers as not being operating systems, so we
-### can provide default operating systems below.
-case $os in
-	-sun*os*)
-		# Prevent following clause from handling this invalid input.
-		;;
-	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
-	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
-	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
-	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-	-apple | -axis | -knuth | -cray | -microblaze*)
-		os=
-		basic_machine=$1
-		;;
-	-bluegene*)
-		os=-cnk
-		;;
-	-sim | -cisco | -oki | -wec | -winbond)
-		os=
-		basic_machine=$1
-		;;
-	-scout)
-		;;
-	-wrs)
-		os=-vxworks
-		basic_machine=$1
-		;;
-	-chorusos*)
-		os=-chorusos
-		basic_machine=$1
-		;;
-	-chorusrdb)
-		os=-chorusrdb
-		basic_machine=$1
-		;;
-	-hiux*)
-		os=-hiuxwe2
-		;;
-	-sco6)
-		os=-sco5v6
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-sco5)
-		os=-sco3.2v5
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-sco4)
-		os=-sco3.2v4
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-sco3.2.[4-9]*)
-		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-sco3.2v[4-9]*)
-		# Don't forget version if it is 3.2v4 or newer.
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-sco5v6*)
-		# Don't forget version if it is 3.2v4 or newer.
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-sco*)
-		os=-sco3.2v2
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-udk*)
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-isc)
-		os=-isc2.2
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-clix*)
-		basic_machine=clipper-intergraph
-		;;
-	-isc*)
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-		;;
-	-lynx*178)
-		os=-lynxos178
-		;;
-	-lynx*5)
-		os=-lynxos5
-		;;
-	-lynx*)
-		os=-lynxos
-		;;
-	-ptx*)
-		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
-		;;
-	-windowsnt*)
-		os=`echo $os | sed -e 's/windowsnt/winnt/'`
-		;;
-	-psos*)
-		os=-psos
-		;;
-	-mint | -mint[0-9]*)
-		basic_machine=m68k-atari
-		os=-mint
-		;;
-esac
-
-# Decode aliases for certain CPU-COMPANY combinations.
-case $basic_machine in
-	# Recognize the basic CPU types without company name.
-	# Some are omitted here because they have special meanings below.
-	1750a | 580 \
-	| a29k \
-	| aarch64 | aarch64_be \
-	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
-	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
-	| am33_2.0 \
-	| arc | arceb \
-	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
-	| avr | avr32 \
-	| ba \
-	| be32 | be64 \
-	| bfin \
-	| c4x | c8051 | clipper \
-	| d10v | d30v | dlx | dsp16xx \
-	| e2k | epiphany \
-	| fido | fr30 | frv | ft32 \
-	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
-	| hexagon \
-	| i370 | i860 | i960 | ia64 \
-	| ip2k | iq2000 \
-	| k1om \
-	| le32 | le64 \
-	| lm32 \
-	| m32c | m32r | m32rle | m68000 | m68k | m88k \
-	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
-	| mips | mipsbe | mipseb | mipsel | mipsle \
-	| mips16 \
-	| mips64 | mips64el \
-	| mips64octeon | mips64octeonel \
-	| mips64orion | mips64orionel \
-	| mips64r5900 | mips64r5900el \
-	| mips64vr | mips64vrel \
-	| mips64vr4100 | mips64vr4100el \
-	| mips64vr4300 | mips64vr4300el \
-	| mips64vr5000 | mips64vr5000el \
-	| mips64vr5900 | mips64vr5900el \
-	| mipsisa32 | mipsisa32el \
-	| mipsisa32r2 | mipsisa32r2el \
-	| mipsisa32r6 | mipsisa32r6el \
-	| mipsisa64 | mipsisa64el \
-	| mipsisa64r2 | mipsisa64r2el \
-	| mipsisa64r6 | mipsisa64r6el \
-	| mipsisa64sb1 | mipsisa64sb1el \
-	| mipsisa64sr71k | mipsisa64sr71kel \
-	| mipsr5900 | mipsr5900el \
-	| mipstx39 | mipstx39el \
-	| mn10200 | mn10300 \
-	| moxie \
-	| mt \
-	| msp430 \
-	| nds32 | nds32le | nds32be \
-	| nios | nios2 | nios2eb | nios2el \
-	| ns16k | ns32k \
-	| open8 | or1k | or1knd | or32 \
-	| pdp10 | pdp11 | pj | pjl \
-	| powerpc | powerpc64 | powerpc64le | powerpcle \
-	| pyramid \
-	| riscv32 | riscv64 \
-	| rl78 | rx \
-	| score \
-	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
-	| sh64 | sh64le \
-	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
-	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
-	| spu \
-	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
-	| ubicom32 \
-	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
-	| visium \
-	| we32k \
-	| x86 | xc16x | xstormy16 | xtensa \
-	| z8k | z80)
-		basic_machine=$basic_machine-unknown
-		;;
-	c54x)
-		basic_machine=tic54x-unknown
-		;;
-	c55x)
-		basic_machine=tic55x-unknown
-		;;
-	c6x)
-		basic_machine=tic6x-unknown
-		;;
-	leon|leon[3-9])
-		basic_machine=sparc-$basic_machine
-		;;
-	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
-		basic_machine=$basic_machine-unknown
-		os=-none
-		;;
-	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
-		;;
-	ms1)
-		basic_machine=mt-unknown
-		;;
-
-	strongarm | thumb | xscale)
-		basic_machine=arm-unknown
-		;;
-	xgate)
-		basic_machine=$basic_machine-unknown
-		os=-none
-		;;
-	xscaleeb)
-		basic_machine=armeb-unknown
-		;;
-
-	xscaleel)
-		basic_machine=armel-unknown
-		;;
-
-	# We use `pc' rather than `unknown'
-	# because (1) that's what they normally are, and
-	# (2) the word "unknown" tends to confuse beginning users.
-	i*86 | x86_64)
-	  basic_machine=$basic_machine-pc
-	  ;;
-	# Object if more than one company name word.
-	*-*-*)
-		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
-		exit 1
-		;;
-	# Recognize the basic CPU types with company name.
-	580-* \
-	| a29k-* \
-	| aarch64-* | aarch64_be-* \
-	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
-	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
-	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
-	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
-	| avr-* | avr32-* \
-	| ba-* \
-	| be32-* | be64-* \
-	| bfin-* | bs2000-* \
-	| c[123]* | c30-* | [cjt]90-* | c4x-* \
-	| c8051-* | clipper-* | craynv-* | cydra-* \
-	| d10v-* | d30v-* | dlx-* \
-	| e2k-* | elxsi-* \
-	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
-	| h8300-* | h8500-* \
-	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
-	| hexagon-* \
-	| i*86-* | i860-* | i960-* | ia64-* \
-	| ip2k-* | iq2000-* \
-	| k1om-* \
-	| le32-* | le64-* \
-	| lm32-* \
-	| m32c-* | m32r-* | m32rle-* \
-	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
-	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
-	| microblaze-* | microblazeel-* \
-	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
-	| mips16-* \
-	| mips64-* | mips64el-* \
-	| mips64octeon-* | mips64octeonel-* \
-	| mips64orion-* | mips64orionel-* \
-	| mips64r5900-* | mips64r5900el-* \
-	| mips64vr-* | mips64vrel-* \
-	| mips64vr4100-* | mips64vr4100el-* \
-	| mips64vr4300-* | mips64vr4300el-* \
-	| mips64vr5000-* | mips64vr5000el-* \
-	| mips64vr5900-* | mips64vr5900el-* \
-	| mipsisa32-* | mipsisa32el-* \
-	| mipsisa32r2-* | mipsisa32r2el-* \
-	| mipsisa32r6-* | mipsisa32r6el-* \
-	| mipsisa64-* | mipsisa64el-* \
-	| mipsisa64r2-* | mipsisa64r2el-* \
-	| mipsisa64r6-* | mipsisa64r6el-* \
-	| mipsisa64sb1-* | mipsisa64sb1el-* \
-	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
-	| mipsr5900-* | mipsr5900el-* \
-	| mipstx39-* | mipstx39el-* \
-	| mmix-* \
-	| mt-* \
-	| msp430-* \
-	| nds32-* | nds32le-* | nds32be-* \
-	| nios-* | nios2-* | nios2eb-* | nios2el-* \
-	| none-* | np1-* | ns16k-* | ns32k-* \
-	| open8-* \
-	| or1k*-* \
-	| orion-* \
-	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
-	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
-	| pyramid-* \
-	| riscv32-* | riscv64-* \
-	| rl78-* | romp-* | rs6000-* | rx-* \
-	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
-	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
-	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
-	| sparclite-* \
-	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
-	| tahoe-* \
-	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
-	| tile*-* \
-	| tron-* \
-	| ubicom32-* \
-	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
-	| vax-* \
-	| visium-* \
-	| we32k-* \
-	| x86-* | x86_64-* | xc16x-* | xps100-* \
-	| xstormy16-* | xtensa*-* \
-	| ymp-* \
-	| z8k-* | z80-*)
-		;;
-	# Recognize the basic CPU types without company name, with glob match.
-	xtensa*)
-		basic_machine=$basic_machine-unknown
-		;;
-	# Recognize the various machine names and aliases which stand
-	# for a CPU type and a company and sometimes even an OS.
-	386bsd)
-		basic_machine=i386-unknown
-		os=-bsd
-		;;
-	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
-		basic_machine=m68000-att
-		;;
-	3b*)
-		basic_machine=we32k-att
-		;;
-	a29khif)
-		basic_machine=a29k-amd
-		os=-udi
-		;;
-	abacus)
-		basic_machine=abacus-unknown
-		;;
-	adobe68k)
-		basic_machine=m68010-adobe
-		os=-scout
-		;;
-	alliant | fx80)
-		basic_machine=fx80-alliant
-		;;
-	altos | altos3068)
-		basic_machine=m68k-altos
-		;;
-	am29k)
-		basic_machine=a29k-none
-		os=-bsd
-		;;
-	amd64)
-		basic_machine=x86_64-pc
-		;;
-	amd64-*)
-		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	amdahl)
-		basic_machine=580-amdahl
-		os=-sysv
-		;;
-	amiga | amiga-*)
-		basic_machine=m68k-unknown
-		;;
-	amigaos | amigados)
-		basic_machine=m68k-unknown
-		os=-amigaos
-		;;
-	amigaunix | amix)
-		basic_machine=m68k-unknown
-		os=-sysv4
-		;;
-	apollo68)
-		basic_machine=m68k-apollo
-		os=-sysv
-		;;
-	apollo68bsd)
-		basic_machine=m68k-apollo
-		os=-bsd
-		;;
-	aros)
-		basic_machine=i386-pc
-		os=-aros
-		;;
-	asmjs)
-		basic_machine=asmjs-unknown
-		;;
-	aux)
-		basic_machine=m68k-apple
-		os=-aux
-		;;
-	balance)
-		basic_machine=ns32k-sequent
-		os=-dynix
-		;;
-	blackfin)
-		basic_machine=bfin-unknown
-		os=-linux
-		;;
-	blackfin-*)
-		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
-		os=-linux
-		;;
-	bluegene*)
-		basic_machine=powerpc-ibm
-		os=-cnk
-		;;
-	c54x-*)
-		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	c55x-*)
-		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	c6x-*)
-		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	c90)
-		basic_machine=c90-cray
-		os=-unicos
-		;;
-	cegcc)
-		basic_machine=arm-unknown
-		os=-cegcc
-		;;
-	convex-c1)
-		basic_machine=c1-convex
-		os=-bsd
-		;;
-	convex-c2)
-		basic_machine=c2-convex
-		os=-bsd
-		;;
-	convex-c32)
-		basic_machine=c32-convex
-		os=-bsd
-		;;
-	convex-c34)
-		basic_machine=c34-convex
-		os=-bsd
-		;;
-	convex-c38)
-		basic_machine=c38-convex
-		os=-bsd
-		;;
-	cray | j90)
-		basic_machine=j90-cray
-		os=-unicos
-		;;
-	craynv)
-		basic_machine=craynv-cray
-		os=-unicosmp
-		;;
-	cr16 | cr16-*)
-		basic_machine=cr16-unknown
-		os=-elf
-		;;
-	crds | unos)
-		basic_machine=m68k-crds
-		;;
-	crisv32 | crisv32-* | etraxfs*)
-		basic_machine=crisv32-axis
-		;;
-	cris | cris-* | etrax*)
-		basic_machine=cris-axis
-		;;
-	crx)
-		basic_machine=crx-unknown
-		os=-elf
-		;;
-	da30 | da30-*)
-		basic_machine=m68k-da30
-		;;
-	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
-		basic_machine=mips-dec
-		;;
-	decsystem10* | dec10*)
-		basic_machine=pdp10-dec
-		os=-tops10
-		;;
-	decsystem20* | dec20*)
-		basic_machine=pdp10-dec
-		os=-tops20
-		;;
-	delta | 3300 | motorola-3300 | motorola-delta \
-	      | 3300-motorola | delta-motorola)
-		basic_machine=m68k-motorola
-		;;
-	delta88)
-		basic_machine=m88k-motorola
-		os=-sysv3
-		;;
-	dicos)
-		basic_machine=i686-pc
-		os=-dicos
-		;;
-	djgpp)
-		basic_machine=i586-pc
-		os=-msdosdjgpp
-		;;
-	dpx20 | dpx20-*)
-		basic_machine=rs6000-bull
-		os=-bosx
-		;;
-	dpx2* | dpx2*-bull)
-		basic_machine=m68k-bull
-		os=-sysv3
-		;;
-	ebmon29k)
-		basic_machine=a29k-amd
-		os=-ebmon
-		;;
-	elxsi)
-		basic_machine=elxsi-elxsi
-		os=-bsd
-		;;
-	encore | umax | mmax)
-		basic_machine=ns32k-encore
-		;;
-	es1800 | OSE68k | ose68k | ose | OSE)
-		basic_machine=m68k-ericsson
-		os=-ose
-		;;
-	fx2800)
-		basic_machine=i860-alliant
-		;;
-	genix)
-		basic_machine=ns32k-ns
-		;;
-	gmicro)
-		basic_machine=tron-gmicro
-		os=-sysv
-		;;
-	go32)
-		basic_machine=i386-pc
-		os=-go32
-		;;
-	h3050r* | hiux*)
-		basic_machine=hppa1.1-hitachi
-		os=-hiuxwe2
-		;;
-	h8300hms)
-		basic_machine=h8300-hitachi
-		os=-hms
-		;;
-	h8300xray)
-		basic_machine=h8300-hitachi
-		os=-xray
-		;;
-	h8500hms)
-		basic_machine=h8500-hitachi
-		os=-hms
-		;;
-	harris)
-		basic_machine=m88k-harris
-		os=-sysv3
-		;;
-	hp300-*)
-		basic_machine=m68k-hp
-		;;
-	hp300bsd)
-		basic_machine=m68k-hp
-		os=-bsd
-		;;
-	hp300hpux)
-		basic_machine=m68k-hp
-		os=-hpux
-		;;
-	hp3k9[0-9][0-9] | hp9[0-9][0-9])
-		basic_machine=hppa1.0-hp
-		;;
-	hp9k2[0-9][0-9] | hp9k31[0-9])
-		basic_machine=m68000-hp
-		;;
-	hp9k3[2-9][0-9])
-		basic_machine=m68k-hp
-		;;
-	hp9k6[0-9][0-9] | hp6[0-9][0-9])
-		basic_machine=hppa1.0-hp
-		;;
-	hp9k7[0-79][0-9] | hp7[0-79][0-9])
-		basic_machine=hppa1.1-hp
-		;;
-	hp9k78[0-9] | hp78[0-9])
-		# FIXME: really hppa2.0-hp
-		basic_machine=hppa1.1-hp
-		;;
-	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
-		# FIXME: really hppa2.0-hp
-		basic_machine=hppa1.1-hp
-		;;
-	hp9k8[0-9][13679] | hp8[0-9][13679])
-		basic_machine=hppa1.1-hp
-		;;
-	hp9k8[0-9][0-9] | hp8[0-9][0-9])
-		basic_machine=hppa1.0-hp
-		;;
-	hppa-next)
-		os=-nextstep3
-		;;
-	hppaosf)
-		basic_machine=hppa1.1-hp
-		os=-osf
-		;;
-	hppro)
-		basic_machine=hppa1.1-hp
-		os=-proelf
-		;;
-	i370-ibm* | ibm*)
-		basic_machine=i370-ibm
-		;;
-	i*86v32)
-		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-		os=-sysv32
-		;;
-	i*86v4*)
-		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-		os=-sysv4
-		;;
-	i*86v)
-		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-		os=-sysv
-		;;
-	i*86sol2)
-		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-		os=-solaris2
-		;;
-	i386mach)
-		basic_machine=i386-mach
-		os=-mach
-		;;
-	i386-vsta | vsta)
-		basic_machine=i386-unknown
-		os=-vsta
-		;;
-	iris | iris4d)
-		basic_machine=mips-sgi
-		case $os in
-		    -irix*)
-			;;
-		    *)
-			os=-irix4
-			;;
-		esac
-		;;
-	isi68 | isi)
-		basic_machine=m68k-isi
-		os=-sysv
-		;;
-	leon-*|leon[3-9]-*)
-		basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
-		;;
-	m68knommu)
-		basic_machine=m68k-unknown
-		os=-linux
-		;;
-	m68knommu-*)
-		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
-		os=-linux
-		;;
-	m88k-omron*)
-		basic_machine=m88k-omron
-		;;
-	magnum | m3230)
-		basic_machine=mips-mips
-		os=-sysv
-		;;
-	merlin)
-		basic_machine=ns32k-utek
-		os=-sysv
-		;;
-	microblaze*)
-		basic_machine=microblaze-xilinx
-		;;
-	mingw64)
-		basic_machine=x86_64-pc
-		os=-mingw64
-		;;
-	mingw32)
-		basic_machine=i686-pc
-		os=-mingw32
-		;;
-	mingw32ce)
-		basic_machine=arm-unknown
-		os=-mingw32ce
-		;;
-	miniframe)
-		basic_machine=m68000-convergent
-		;;
-	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
-		basic_machine=m68k-atari
-		os=-mint
-		;;
-	mips3*-*)
-		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
-		;;
-	mips3*)
-		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
-		;;
-	monitor)
-		basic_machine=m68k-rom68k
-		os=-coff
-		;;
-	morphos)
-		basic_machine=powerpc-unknown
-		os=-morphos
-		;;
-	moxiebox)
-		basic_machine=moxie-unknown
-		os=-moxiebox
-		;;
-	msdos)
-		basic_machine=i386-pc
-		os=-msdos
-		;;
-	ms1-*)
-		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
-		;;
-	msys)
-		basic_machine=i686-pc
-		os=-msys
-		;;
-	mvs)
-		basic_machine=i370-ibm
-		os=-mvs
-		;;
-	nacl)
-		basic_machine=le32-unknown
-		os=-nacl
-		;;
-	ncr3000)
-		basic_machine=i486-ncr
-		os=-sysv4
-		;;
-	netbsd386)
-		basic_machine=i386-unknown
-		os=-netbsd
-		;;
-	netwinder)
-		basic_machine=armv4l-rebel
-		os=-linux
-		;;
-	news | news700 | news800 | news900)
-		basic_machine=m68k-sony
-		os=-newsos
-		;;
-	news1000)
-		basic_machine=m68030-sony
-		os=-newsos
-		;;
-	news-3600 | risc-news)
-		basic_machine=mips-sony
-		os=-newsos
-		;;
-	necv70)
-		basic_machine=v70-nec
-		os=-sysv
-		;;
-	next | m*-next )
-		basic_machine=m68k-next
-		case $os in
-		    -nextstep* )
-			;;
-		    -ns2*)
-		      os=-nextstep2
-			;;
-		    *)
-		      os=-nextstep3
-			;;
-		esac
-		;;
-	nh3000)
-		basic_machine=m68k-harris
-		os=-cxux
-		;;
-	nh[45]000)
-		basic_machine=m88k-harris
-		os=-cxux
-		;;
-	nindy960)
-		basic_machine=i960-intel
-		os=-nindy
-		;;
-	mon960)
-		basic_machine=i960-intel
-		os=-mon960
-		;;
-	nonstopux)
-		basic_machine=mips-compaq
-		os=-nonstopux
-		;;
-	np1)
-		basic_machine=np1-gould
-		;;
-	neo-tandem)
-		basic_machine=neo-tandem
-		;;
-	nse-tandem)
-		basic_machine=nse-tandem
-		;;
-	nsr-tandem)
-		basic_machine=nsr-tandem
-		;;
-	op50n-* | op60c-*)
-		basic_machine=hppa1.1-oki
-		os=-proelf
-		;;
-	openrisc | openrisc-*)
-		basic_machine=or32-unknown
-		;;
-	os400)
-		basic_machine=powerpc-ibm
-		os=-os400
-		;;
-	OSE68000 | ose68000)
-		basic_machine=m68000-ericsson
-		os=-ose
-		;;
-	os68k)
-		basic_machine=m68k-none
-		os=-os68k
-		;;
-	pa-hitachi)
-		basic_machine=hppa1.1-hitachi
-		os=-hiuxwe2
-		;;
-	paragon)
-		basic_machine=i860-intel
-		os=-osf
-		;;
-	parisc)
-		basic_machine=hppa-unknown
-		os=-linux
-		;;
-	parisc-*)
-		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
-		os=-linux
-		;;
-	pbd)
-		basic_machine=sparc-tti
-		;;
-	pbb)
-		basic_machine=m68k-tti
-		;;
-	pc532 | pc532-*)
-		basic_machine=ns32k-pc532
-		;;
-	pc98)
-		basic_machine=i386-pc
-		;;
-	pc98-*)
-		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	pentium | p5 | k5 | k6 | nexgen | viac3)
-		basic_machine=i586-pc
-		;;
-	pentiumpro | p6 | 6x86 | athlon | athlon_*)
-		basic_machine=i686-pc
-		;;
-	pentiumii | pentium2 | pentiumiii | pentium3)
-		basic_machine=i686-pc
-		;;
-	pentium4)
-		basic_machine=i786-pc
-		;;
-	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
-		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	pentiumpro-* | p6-* | 6x86-* | athlon-*)
-		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
-		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	pentium4-*)
-		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	pn)
-		basic_machine=pn-gould
-		;;
-	power)	basic_machine=power-ibm
-		;;
-	ppc | ppcbe)	basic_machine=powerpc-unknown
-		;;
-	ppc-* | ppcbe-*)
-		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	ppcle | powerpclittle | ppc-le | powerpc-little)
-		basic_machine=powerpcle-unknown
-		;;
-	ppcle-* | powerpclittle-*)
-		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	ppc64)	basic_machine=powerpc64-unknown
-		;;
-	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
-		basic_machine=powerpc64le-unknown
-		;;
-	ppc64le-* | powerpc64little-*)
-		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	ps2)
-		basic_machine=i386-ibm
-		;;
-	pw32)
-		basic_machine=i586-unknown
-		os=-pw32
-		;;
-	rdos | rdos64)
-		basic_machine=x86_64-pc
-		os=-rdos
-		;;
-	rdos32)
-		basic_machine=i386-pc
-		os=-rdos
-		;;
-	rom68k)
-		basic_machine=m68k-rom68k
-		os=-coff
-		;;
-	rm[46]00)
-		basic_machine=mips-siemens
-		;;
-	rtpc | rtpc-*)
-		basic_machine=romp-ibm
-		;;
-	s390 | s390-*)
-		basic_machine=s390-ibm
-		;;
-	s390x | s390x-*)
-		basic_machine=s390x-ibm
-		;;
-	sa29200)
-		basic_machine=a29k-amd
-		os=-udi
-		;;
-	sb1)
-		basic_machine=mipsisa64sb1-unknown
-		;;
-	sb1el)
-		basic_machine=mipsisa64sb1el-unknown
-		;;
-	sde)
-		basic_machine=mipsisa32-sde
-		os=-elf
-		;;
-	sei)
-		basic_machine=mips-sei
-		os=-seiux
-		;;
-	sequent)
-		basic_machine=i386-sequent
-		;;
-	sh)
-		basic_machine=sh-hitachi
-		os=-hms
-		;;
-	sh5el)
-		basic_machine=sh5le-unknown
-		;;
-	sh64)
-		basic_machine=sh64-unknown
-		;;
-	sparclite-wrs | simso-wrs)
-		basic_machine=sparclite-wrs
-		os=-vxworks
-		;;
-	sps7)
-		basic_machine=m68k-bull
-		os=-sysv2
-		;;
-	spur)
-		basic_machine=spur-unknown
-		;;
-	st2000)
-		basic_machine=m68k-tandem
-		;;
-	stratus)
-		basic_machine=i860-stratus
-		os=-sysv4
-		;;
-	strongarm-* | thumb-*)
-		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
-	sun2)
-		basic_machine=m68000-sun
-		;;
-	sun2os3)
-		basic_machine=m68000-sun
-		os=-sunos3
-		;;
-	sun2os4)
-		basic_machine=m68000-sun
-		os=-sunos4
-		;;
-	sun3os3)
-		basic_machine=m68k-sun
-		os=-sunos3
-		;;
-	sun3os4)
-		basic_machine=m68k-sun
-		os=-sunos4
-		;;
-	sun4os3)
-		basic_machine=sparc-sun
-		os=-sunos3
-		;;
-	sun4os4)
-		basic_machine=sparc-sun
-		os=-sunos4
-		;;
-	sun4sol2)
-		basic_machine=sparc-sun
-		os=-solaris2
-		;;
-	sun3 | sun3-*)
-		basic_machine=m68k-sun
-		;;
-	sun4)
-		basic_machine=sparc-sun
-		;;
-	sun386 | sun386i | roadrunner)
-		basic_machine=i386-sun
-		;;
-	sv1)
-		basic_machine=sv1-cray
-		os=-unicos
-		;;
-	symmetry)
-		basic_machine=i386-sequent
-		os=-dynix
-		;;
-	t3e)
-		basic_machine=alphaev5-cray
-		os=-unicos
-		;;
-	t90)
-		basic_machine=t90-cray
-		os=-unicos
-		;;
-	tile*)
-		basic_machine=$basic_machine-unknown
-		os=-linux-gnu
-		;;
-	tx39)
-		basic_machine=mipstx39-unknown
-		;;
-	tx39el)
-		basic_machine=mipstx39el-unknown
-		;;
-	toad1)
-		basic_machine=pdp10-xkl
-		os=-tops20
-		;;
-	tower | tower-32)
-		basic_machine=m68k-ncr
-		;;
-	tpf)
-		basic_machine=s390x-ibm
-		os=-tpf
-		;;
-	udi29k)
-		basic_machine=a29k-amd
-		os=-udi
-		;;
-	ultra3)
-		basic_machine=a29k-nyu
-		os=-sym1
-		;;
-	v810 | necv810)
-		basic_machine=v810-nec
-		os=-none
-		;;
-	vaxv)
-		basic_machine=vax-dec
-		os=-sysv
-		;;
-	vms)
-		basic_machine=vax-dec
-		os=-vms
-		;;
-	vpp*|vx|vx-*)
-		basic_machine=f301-fujitsu
-		;;
-	vxworks960)
-		basic_machine=i960-wrs
-		os=-vxworks
-		;;
-	vxworks68)
-		basic_machine=m68k-wrs
-		os=-vxworks
-		;;
-	vxworks29k)
-		basic_machine=a29k-wrs
-		os=-vxworks
-		;;
-	w65*)
-		basic_machine=w65-wdc
-		os=-none
-		;;
-	w89k-*)
-		basic_machine=hppa1.1-winbond
-		os=-proelf
-		;;
-	xbox)
-		basic_machine=i686-pc
-		os=-mingw32
-		;;
-	xps | xps100)
-		basic_machine=xps100-honeywell
-		;;
-	xscale-* | xscalee[bl]-*)
-		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
-		;;
-	ymp)
-		basic_machine=ymp-cray
-		os=-unicos
-		;;
-	z8k-*-coff)
-		basic_machine=z8k-unknown
-		os=-sim
-		;;
-	z80-*-coff)
-		basic_machine=z80-unknown
-		os=-sim
-		;;
-	none)
-		basic_machine=none-none
-		os=-none
-		;;
-
-# Here we handle the default manufacturer of certain CPU types.  It is in
-# some cases the only manufacturer, in others, it is the most popular.
-	w89k)
-		basic_machine=hppa1.1-winbond
-		;;
-	op50n)
-		basic_machine=hppa1.1-oki
-		;;
-	op60c)
-		basic_machine=hppa1.1-oki
-		;;
-	romp)
-		basic_machine=romp-ibm
-		;;
-	mmix)
-		basic_machine=mmix-knuth
-		;;
-	rs6000)
-		basic_machine=rs6000-ibm
-		;;
-	vax)
-		basic_machine=vax-dec
-		;;
-	pdp10)
-		# there are many clones, so DEC is not a safe bet
-		basic_machine=pdp10-unknown
-		;;
-	pdp11)
-		basic_machine=pdp11-dec
-		;;
-	we32k)
-		basic_machine=we32k-att
-		;;
-	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
-		basic_machine=sh-unknown
-		;;
-	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
-		basic_machine=sparc-sun
-		;;
-	cydra)
-		basic_machine=cydra-cydrome
-		;;
-	orion)
-		basic_machine=orion-highlevel
-		;;
-	orion105)
-		basic_machine=clipper-highlevel
-		;;
-	mac | mpw | mac-mpw)
-		basic