Add Windows ARM64 support to Chromium crashpad

Bug: chromium:893460
Change-Id: Ifbeb6f937a6b96c77b02dcf8afe492c5bc617435
Reviewed-on: https://chromium-review.googlesource.com/c/1347773
Reviewed-by: Mark Mentovai <mark@chromium.org>
Commit-Queue: Mark Mentovai <mark@chromium.org>
This commit is contained in:
Tom Tan 2018-12-12 12:58:24 -08:00 committed by Commit Bot
parent 9b6dde9101
commit 761c6fe8be
20 changed files with 229 additions and 69 deletions

View File

@ -36,6 +36,7 @@
#include "util/misc/random_string.h"
#include "util/win/address_types.h"
#include "util/win/command_line.h"
#include "util/win/context_wrappers.h"
#include "util/win/critical_section_with_debug_info.h"
#include "util/win/get_function.h"
#include "util/win/handle.h"
@ -187,11 +188,7 @@ void HandleAbortSignal(int signum) {
EXCEPTION_RECORD record = {};
record.ExceptionCode = STATUS_FATAL_APP_EXIT;
record.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
#if defined(ARCH_CPU_64_BITS)
record.ExceptionAddress = reinterpret_cast<void*>(context.Rip);
#else
record.ExceptionAddress = reinterpret_cast<void*>(context.Eip);
#endif // ARCH_CPU_64_BITS
record.ExceptionAddress = ProgramCounterFromCONTEXT(&context);
EXCEPTION_POINTERS exception_pointers;
exception_pointers.ContextRecord = &context;
@ -773,11 +770,7 @@ void CrashpadClient::DumpWithoutCrash(const CONTEXT& context) {
constexpr uint32_t kSimulatedExceptionCode = 0x517a7ed;
EXCEPTION_RECORD record = {};
record.ExceptionCode = kSimulatedExceptionCode;
#if defined(ARCH_CPU_64_BITS)
record.ExceptionAddress = reinterpret_cast<void*>(context.Rip);
#else
record.ExceptionAddress = reinterpret_cast<void*>(context.Eip);
#endif // ARCH_CPU_64_BITS
record.ExceptionAddress = ProgramCounterFromCONTEXT(&context);
exception_pointers.ExceptionRecord = &record;

View File

@ -126,7 +126,13 @@ void CommonInitializeX86Context(const T& context, CPUContextX86* out) {
} // namespace
#if defined(ARCH_CPU_64_BITS)
#if defined(ARCH_CPU_X86)
void InitializeX86Context(const CONTEXT& context, CPUContextX86* out) {
CommonInitializeX86Context(context, out);
}
#elif defined(ARCH_CPU_X86_64)
void InitializeX86Context(const WOW64_CONTEXT& context, CPUContextX86* out) {
CommonInitializeX86Context(context, out);
@ -192,12 +198,36 @@ void InitializeX64Context(const CONTEXT& context, CPUContextX86_64* out) {
}
}
#else // ARCH_CPU_64_BITS
#elif defined(ARCH_CPU_ARM64)
void InitializeX86Context(const CONTEXT& context, CPUContextX86* out) {
CommonInitializeX86Context(context, out);
void InitializeARM64Context(const CONTEXT& context, CPUContextARM64* out) {
memset(out, 0, sizeof(*out));
LOG_IF(ERROR, !HasContextPart(context, CONTEXT_ARM64)) << "non-arm64 context";
if (HasContextPart(context, CONTEXT_CONTROL)) {
out->spsr = context.Cpsr;
out->pc = context.Pc;
out->regs[30] = context.Lr;
out->sp = context.Sp;
out->regs[29] = context.Fp;
}
if (HasContextPart(context, CONTEXT_INTEGER)) {
memcpy(&out->regs[0], &context.X0, 18 * sizeof(context.X0));
// Don't copy x18 which is reserved as platform register.
memcpy(&out->regs[19], &context.X19, 10 * sizeof(context.X0));
}
if (HasContextPart(context, CONTEXT_FLOATING_POINT)) {
static_assert(sizeof(out->fpsimd) == sizeof(context.V),
"types must be equivalent");
memcpy(&out->fpsimd, &context.V, sizeof(out->fpsimd));
}
}
#endif // ARCH_CPU_64_BITS
#else
#error Unsupported Windows Arch
#endif // ARCH_CPU_X86
} // namespace crashpad

View File

@ -23,8 +23,17 @@ namespace crashpad {
struct CPUContextX86;
struct CPUContextX86_64;
struct CPUContextARM64;
#if defined(ARCH_CPU_64_BITS) || DOXYGEN
#if defined(ARCH_CPU_X86) || DOXYGEN
//! \brief Initializes a CPUContextX86 structure from a native context structure
//! on Windows.
void InitializeX86Context(const CONTEXT& context, CPUContextX86* out);
#endif // ARCH_CPU_X86
#if defined(ARCH_CPU_X86_64) || DOXYGEN
//! \brief Initializes a CPUContextX86 structure from a native context structure
//! on Windows.
@ -34,13 +43,15 @@ void InitializeX86Context(const WOW64_CONTEXT& context, CPUContextX86* out);
//! structure on Windows.
void InitializeX64Context(const CONTEXT& context, CPUContextX86_64* out);
#else // ARCH_CPU_64_BITS
#endif // ARCH_CPU_X86_64
//! \brief Initializes a CPUContextX86 structure from a native context structure
//! on Windows.
void InitializeX86Context(const CONTEXT& context, CPUContextX86* out);
#if defined(ARCH_CPU_ARM64) || DOXYGEN
#endif // ARCH_CPU_64_BITS
//! \brief Initializes a CPUContextARM64 structure from a native context
//! structure on Windows.
void InitializeARM64Context(const CONTEXT& context, CPUContextARM64* out);
#endif // ARCH_CPU_ARM64
} // namespace crashpad

View File

@ -16,10 +16,10 @@
#include <windows.h>
#include "base/logging.h"
#include "build/build_config.h"
#include "client/crashpad_client.h"
#include "util/misc/capture_context.h"
#include "util/win/address_types.h"
#include "util/win/context_wrappers.h"
int wmain(int argc, wchar_t* argv[]) {
CHECK_EQ(argc, 2);
@ -32,11 +32,9 @@ int wmain(int argc, wchar_t* argv[]) {
CONTEXT context;
crashpad::CaptureContext(&context);
#if defined(ARCH_CPU_64_BITS)
crashpad::WinVMAddress break_address = context.Rip;
#else
crashpad::WinVMAddress break_address = context.Eip;
#endif
crashpad::WinVMAddress break_address =
reinterpret_cast<crashpad::WinVMAddress>(
crashpad::ProgramCounterFromCONTEXT(&context));
// This does not used CheckedWriteFile() because at high optimization
// settings, a lot of logging code can be inlined, causing there to be a large

View File

@ -20,6 +20,7 @@
#include "client/simulate_crash.h"
#include "util/misc/capture_context.h"
#include "util/win/address_types.h"
#include "util/win/context_wrappers.h"
int wmain(int argc, wchar_t* argv[]) {
CHECK_EQ(argc, 2);
@ -32,11 +33,9 @@ int wmain(int argc, wchar_t* argv[]) {
CONTEXT context;
crashpad::CaptureContext(&context);
#if defined(ARCH_CPU_64_BITS)
crashpad::WinVMAddress break_address = context.Rip;
#else
crashpad::WinVMAddress break_address = context.Eip;
#endif
crashpad::WinVMAddress break_address =
reinterpret_cast<crashpad::WinVMAddress>(
crashpad::ProgramCounterFromCONTEXT(&context));
// This does not used CheckedWriteFile() because at high optimization
// settings, a lot of logging code can be inlined, causing there to be a large

View File

@ -28,22 +28,13 @@ namespace internal {
namespace {
#if defined(ARCH_CPU_X86_FAMILY)
#if defined(ARCH_CPU_32_BITS)
using Context32 = CONTEXT;
#elif defined(ARCH_CPU_64_BITS)
using Context32 = WOW64_CONTEXT;
#endif
#if defined(ARCH_CPU_64_BITS)
void NativeContextToCPUContext64(const CONTEXT& context_record,
CPUContext* context,
CPUContextUnion* context_union) {
context->architecture = kCPUArchitectureX86_64;
context->x86_64 = &context_union->x86_64;
InitializeX64Context(context_record, context->x86_64);
}
#endif
void NativeContextToCPUContext32(const Context32& context_record,
CPUContext* context,
CPUContextUnion* context_union) {
@ -51,6 +42,25 @@ void NativeContextToCPUContext32(const Context32& context_record,
context->x86 = &context_union->x86;
InitializeX86Context(context_record, context->x86);
}
#endif // ARCH_CPU_X86_FAMILY
#if defined(ARCH_CPU_64_BITS)
void NativeContextToCPUContext64(const CONTEXT& context_record,
CPUContext* context,
CPUContextUnion* context_union) {
#if defined(ARCH_CPU_X86_64)
context->architecture = kCPUArchitectureX86_64;
context->x86_64 = &context_union->x86_64;
InitializeX64Context(context_record, context->x86_64);
#elif defined(ARCH_CPU_ARM64)
context->architecture = kCPUArchitectureARM64;
context->arm64 = &context_union->arm64;
InitializeARM64Context(context_record, context->arm64);
#else
#error Unsupported Windows 64-bit Arch
#endif
}
#endif
} // namespace
@ -106,6 +116,8 @@ bool ExceptionSnapshotWin::Initialize(
}
}
#endif
#if !defined(ARCH_CPU_ARM64)
if (!is_64_bit) {
if (!InitializeFromExceptionPointers<EXCEPTION_RECORD32,
process_types::EXCEPTION_POINTERS32>(
@ -116,6 +128,7 @@ bool ExceptionSnapshotWin::Initialize(
return false;
}
}
#endif
CaptureMemoryDelegateWin capture_memory_delegate(
process_reader, *thread, &extra_memory_, nullptr);

View File

@ -38,12 +38,14 @@ namespace internal {
class MemorySnapshotWin;
#if defined(ARCH_CPU_X86_FAMILY)
union CPUContextUnion {
#if defined(ARCH_CPU_X86_FAMILY)
CPUContextX86 x86;
CPUContextX86_64 x86_64;
};
#elif defined(ARCH_CPU_ARM64)
CPUContextARM64 arm64;
#endif
};
class ExceptionSnapshotWin final : public ExceptionSnapshot {
public:
@ -91,9 +93,7 @@ class ExceptionSnapshotWin final : public ExceptionSnapshot {
CPUContext* context,
CPUContextUnion* context_union));
#if defined(ARCH_CPU_X86_FAMILY)
CPUContextUnion context_union_;
#endif
CPUContext context_;
std::vector<uint64_t> codes_;
std::vector<std::unique_ptr<internal::MemorySnapshotWin>> extra_memory_;

View File

@ -22,6 +22,7 @@
#include "util/misc/from_pointer_cast.h"
#include "util/synchronization/semaphore.h"
#include "util/thread/thread.h"
#include "util/win/context_wrappers.h"
#include "util/win/scoped_process_suspend.h"
namespace crashpad {
@ -106,12 +107,7 @@ TEST(ProcessReaderWin, SelfOneThread) {
ASSERT_GE(threads.size(), 1u);
EXPECT_EQ(threads[0].id, GetCurrentThreadId());
#if defined(ARCH_CPU_64_BITS)
EXPECT_NE(threads[0].context.native.Rip, 0u);
#else
EXPECT_NE(threads[0].context.native.Eip, 0u);
#endif
EXPECT_NE(ProgramCounterFromCONTEXT(&threads[0].context.native), nullptr);
EXPECT_EQ(threads[0].suspend_count, 0u);
}

View File

@ -23,6 +23,7 @@
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "util/misc/from_pointer_cast.h"
#include "util/misc/time.h"
#include "util/win/nt_internals.h"
@ -276,7 +277,7 @@ void ProcessSnapshotWin::InitializeUnloadedModules() {
// and 32-reading-32, so at the moment, we simply do not retrieve unloaded
// modules for 64-reading-32. See https://crashpad.chromium.org/bug/89.
#if defined(ARCH_CPU_X86_64)
#if defined(ARCH_CPU_X86_64) || defined(ARCH_CPU_ARM64)
if (!process_reader_.Is64Bit()) {
LOG(ERROR)
<< "reading unloaded modules across bitness not currently supported";

View File

@ -26,6 +26,7 @@
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "util/win/module_version.h"
namespace crashpad {
@ -125,13 +126,20 @@ void SystemSnapshotWin::Initialize(ProcessReaderWin* process_reader) {
CPUArchitecture SystemSnapshotWin::GetCPUArchitecture() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
#if defined(ARCH_CPU_X86_FAMILY)
return process_reader_->Is64Bit() ? kCPUArchitectureX86_64
: kCPUArchitectureX86;
#elif defined(ARCH_CPU_ARM64)
return kCPUArchitectureARM64;
#else
#error Unsupported Windows Arch
#endif
}
uint32_t SystemSnapshotWin::CPURevision() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
#if defined(ARCH_CPU_X86_FAMILY)
uint32_t raw = CPUX86Signature();
uint8_t stepping = raw & 0xf;
uint8_t model = (raw & 0xf0) >> 4;
@ -149,6 +157,13 @@ uint32_t SystemSnapshotWin::CPURevision() const {
uint16_t adjusted_family = family + extended_family;
uint8_t adjusted_model = model + (extended_model << 4);
return (adjusted_family << 16) | (adjusted_model << 8) | stepping;
#elif defined(ARCH_CPU_ARM64)
// TODO(jperaza): do this. https://crashpad.chromium.org/bug/30
// This is the same as SystemSnapshotLinux::CPURevision.
return 0;
#else
#error Unsupported Windows Arch
#endif
}
uint8_t SystemSnapshotWin::CPUCount() const {
@ -166,6 +181,7 @@ uint8_t SystemSnapshotWin::CPUCount() const {
std::string SystemSnapshotWin::CPUVendor() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
#if defined(ARCH_CPU_X86_FAMILY)
int cpu_info[4];
__cpuid(cpu_info, 0);
char vendor[12];
@ -173,6 +189,13 @@ std::string SystemSnapshotWin::CPUVendor() const {
*reinterpret_cast<int*>(vendor + 4) = cpu_info[3];
*reinterpret_cast<int*>(vendor + 8) = cpu_info[2];
return std::string(vendor, sizeof(vendor));
#elif defined(ARCH_CPU_ARM64)
// TODO(jperaza): do this. https://crashpad.chromium.org/bug/30
// This is the same as SystemSnapshotLinux::CPURevision.
return std::string();
#else
#error Unsupported Windows Arch
#endif
}
void SystemSnapshotWin::CPUFrequency(uint64_t* current_hz,
@ -212,36 +235,52 @@ void SystemSnapshotWin::CPUFrequency(uint64_t* current_hz,
uint32_t SystemSnapshotWin::CPUX86Signature() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
#if defined(ARCH_CPU_X86_FAMILY)
int cpu_info[4];
// We will never run on any processors that don't support at least function 1.
__cpuid(cpu_info, 1);
return cpu_info[0];
#else
NOTREACHED();
return 0;
#endif
}
uint64_t SystemSnapshotWin::CPUX86Features() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
#if defined(ARCH_CPU_X86_FAMILY)
int cpu_info[4];
// We will never run on any processors that don't support at least function 1.
__cpuid(cpu_info, 1);
return (static_cast<uint64_t>(cpu_info[2]) << 32) |
static_cast<uint64_t>(cpu_info[3]);
#else
NOTREACHED();
return 0;
#endif
}
uint64_t SystemSnapshotWin::CPUX86ExtendedFeatures() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
#if defined(ARCH_CPU_X86_FAMILY)
int cpu_info[4];
// We will never run on any processors that don't support at least extended
// function 1.
__cpuid(cpu_info, 0x80000001);
return (static_cast<uint64_t>(cpu_info[2]) << 32) |
static_cast<uint64_t>(cpu_info[3]);
#else
NOTREACHED();
return 0;
#endif
}
uint32_t SystemSnapshotWin::CPUX86Leaf7Features() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
#if defined(ARCH_CPU_X86_FAMILY)
int cpu_info[4];
// Make sure leaf 7 can be called.
@ -251,11 +290,16 @@ uint32_t SystemSnapshotWin::CPUX86Leaf7Features() const {
__cpuidex(cpu_info, 7, 0);
return cpu_info[1];
#else
NOTREACHED();
return 0;
#endif
}
bool SystemSnapshotWin::CPUX86SupportsDAZ() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
#if defined(ARCH_CPU_X86_FAMILY)
// The correct way to check for denormals-as-zeros (DAZ) support is to examine
// mxcsr mask, which can be done with fxsave. See Intel Software Developer's
// Manual, Volume 1: Basic Architecture (253665-051), 11.6.3 "Checking for the
@ -277,6 +321,10 @@ bool SystemSnapshotWin::CPUX86SupportsDAZ() const {
// Test the DAZ bit.
return (mxcsr_mask & (1 << 6)) != 0;
#else
NOTREACHED();
return 0;
#endif
}
SystemSnapshot::OperatingSystem SystemSnapshotWin::GetOperatingSystem() const {

View File

@ -60,6 +60,10 @@ TEST_F(SystemSnapshotWinTest, GetCPUArchitecture) {
EXPECT_EQ(cpu_architecture, kCPUArchitectureX86);
#elif defined(ARCH_CPU_X86_64)
EXPECT_EQ(cpu_architecture, kCPUArchitectureX86_64);
#elif defined(ARCH_CPU_ARM64)
EXPECT_EQ(cpu_architecture, kCPUArchitectureARM64);
#else
#error Unsupported Windows Arch
#endif
}

View File

@ -63,7 +63,11 @@ bool ThreadSnapshotWin::Initialize(
teb_.Initialize(process_reader, 0, 0);
}
#if defined(ARCH_CPU_X86_64)
#if defined(ARCH_CPU_X86)
context_.architecture = kCPUArchitectureX86;
context_.x86 = &context_union_.x86;
InitializeX86Context(process_reader_thread.context.native, context_.x86);
#elif defined(ARCH_CPU_X86_64)
if (process_reader->Is64Bit()) {
context_.architecture = kCPUArchitectureX86_64;
context_.x86_64 = &context_union_.x86_64;
@ -73,11 +77,13 @@ bool ThreadSnapshotWin::Initialize(
context_.x86 = &context_union_.x86;
InitializeX86Context(process_reader_thread.context.wow64, context_.x86);
}
#elif defined(ARCH_CPU_ARM64)
context_.architecture = kCPUArchitectureARM64;
context_.arm64 = &context_union_.arm64;
InitializeARM64Context(process_reader_thread.context.native, context_.arm64);
#else
context_.architecture = kCPUArchitectureX86;
context_.x86 = &context_union_.x86;
InitializeX86Context(process_reader_thread.context.native, context_.x86);
#endif // ARCH_CPU_X86_64
#error Unsupported Windows Arch
#endif // ARCH_CPU_X86
CaptureMemoryDelegateWin capture_memory_delegate(
process_reader,

View File

@ -71,12 +71,16 @@ class ThreadSnapshotWin final : public ThreadSnapshot {
std::vector<const MemorySnapshot*> ExtraMemory() const override;
private:
#if defined(ARCH_CPU_X86_FAMILY)
union {
#if defined(ARCH_CPU_X86_FAMILY)
CPUContextX86 x86;
CPUContextX86_64 x86_64;
} context_union_;
#elif defined(ARCH_CPU_ARM64)
CPUContextARM64 arm64;
#else
#error Unsupported Windows Arch
#endif
} context_union_;
CPUContext context_;
MemorySnapshotWin stack_;
MemorySnapshotWin teb_;

View File

@ -91,6 +91,12 @@ if (zlib_source == "external") {
"/wd4324", # structure was padded due to alignment specifier
"/wd4702", # unreachable code
]
if (current_cpu == "arm64" && !crashpad_is_clang) {
# Select code path for clang in zlib to avoid using MSVC x86/x64
# intrinsics for Windows ARM64.
# TODO: https://crashpad.chromium.org/bug/267
defines += [ "__clang__" ]
}
} else {
defines += [
"HAVE_HIDDEN",

View File

@ -341,6 +341,7 @@ static_library("util") {
"win/checked_win_address_range.h",
"win/command_line.cc",
"win/command_line.h",
"win/context_wrappers.h",
"win/critical_section_with_debug_info.cc",
"win/critical_section_with_debug_info.h",
"win/exception_handler_server.cc",
@ -390,10 +391,15 @@ static_library("util") {
# TODO(thakis): Use the .asm file in cross builds somehow,
# https://crbug.com/762167.
if (host_os == "win") {
sources += [
"misc/capture_context_win.asm",
"win/safe_terminate_process.asm",
]
if (current_cpu != "arm64") {
sources += [
"misc/capture_context_win.asm",
"win/safe_terminate_process.asm",
]
} else {
# TODO: Add assembly code of CaptureContext for Windows ARM64.
sources += [ "misc/capture_context_broken.cc" ]
}
} else {
sources += [
"misc/capture_context_broken.cc",

View File

@ -13,6 +13,7 @@
// limitations under the License.
#include "util/misc/capture_context_test_util.h"
#include "util/win/context_wrappers.h"
#include "base/macros.h"
#include "gtest/gtest.h"
@ -95,11 +96,7 @@ void SanityCheckContext(const NativeCPUContext& context) {
}
uintptr_t ProgramCounterFromContext(const NativeCPUContext& context) {
#if defined(ARCH_CPU_X86)
return context.Eip;
#elif defined(ARCH_CPU_X86_64)
return context.Rip;
#endif
return reinterpret_cast<uintptr_t>(ProgramCounterFromCONTEXT(&context));
}
uintptr_t StackPointerFromContext(const NativeCPUContext& context) {
@ -107,6 +104,8 @@ uintptr_t StackPointerFromContext(const NativeCPUContext& context) {
return context.Esp;
#elif defined(ARCH_CPU_X86_64)
return context.Rsp;
#elif defined(ARCH_CPU_ARM64)
return context.Sp;
#endif
}

View File

@ -65,6 +65,8 @@ std::string UserAgent() {
user_agent.append("x86");
#elif defined(ARCH_CPU_X86_64)
user_agent.append("x64");
#elif defined(ARCH_CPU_ARM64)
user_agent.append("arm64");
#else
#error Port
#endif

View File

@ -246,6 +246,7 @@
'win/checked_win_address_range.h',
'win/command_line.cc',
'win/command_line.h',
'win/context_wrappers.h',
'win/critical_section_with_debug_info.cc',
'win/critical_section_with_debug_info.h',
'win/exception_handler_server.cc',

View File

@ -0,0 +1,40 @@
// Copyright 2018 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_UTIL_WIN_CONTEXT_WRAPPERS_H_
#define CRASHPAD_UTIL_WIN_CONTEXT_WRAPPERS_H_
#include <windows.h>
#include "build/build_config.h"
namespace crashpad {
//! \brief Retrieve program counter from `CONTEXT` structure for different
//! architectures supported by Windows.
inline void* ProgramCounterFromCONTEXT(const CONTEXT* context) {
#if defined(ARCH_CPU_X86)
return reinterpret_cast<void*>(context->Eip);
#elif defined(ARCH_CPU_X86_64)
return reinterpret_cast<void*>(context->Rip);
#elif defined(ARCH_CPU_ARM64)
return reinterpret_cast<void*>(context->Pc);
#else
#error Unsupported Windows Arch
#endif // ARCH_CPU_X86
}
} // namespace crashpad
#endif // CRASHPAD_UTIL_WIN_CONTEXT_WRAPPERS_H_

View File

@ -91,6 +91,8 @@ class ScopedExecutablePatch {
DISALLOW_COPY_AND_ASSIGN(ScopedExecutablePatch);
};
// SafeTerminateProcess is calling convention specific only for x86.
#if defined(ARCH_CPU_X86_FAMILY)
TEST(SafeTerminateProcess, PatchBadly) {
// This is a test of SafeTerminateProcess(), but it doesnt actually terminate
// anything. Instead, it works with a process handle for the current process
@ -161,6 +163,7 @@ TEST(SafeTerminateProcess, PatchBadly) {
EXPECT_FALSE(SafeTerminateProcess(process, 0));
EXPECT_EQ(GetLastError(), static_cast<DWORD>(ERROR_ACCESS_DENIED));
}
#endif // ARCH_CPU_X86_FAMILY
TEST(SafeTerminateProcess, TerminateChild) {
base::FilePath child_executable =