Generate minidumps for 64-bit ARM apps on iOS.
Adds an ARM64-specific definition of MDRawContext and support for writing out a minidump when running on ARM64. Additionally, extends the iOS minidump generator for NSExceptions to work on ARM64 as well as ARM. Patch by Colin Blundell <blundell@chromium.org> BUG=542 Review URL: https://breakpad.appspot.com/664002/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1235 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
8e28cb3898
commit
77022ac0df
12 changed files with 419 additions and 63 deletions
|
@ -7,6 +7,8 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
14569321182CE29F0029C465 /* ucontext_compat.h in Headers */ = {isa = PBXBuildFile; fileRef = 14569320182CE29F0029C465 /* ucontext_compat.h */; };
|
||||||
|
14569323182CE2C10029C465 /* mach_vm_compat.h in Headers */ = {isa = PBXBuildFile; fileRef = 14569322182CE2C10029C465 /* mach_vm_compat.h */; };
|
||||||
16BFA67014E195E9009704F8 /* ios_exception_minidump_generator.h in Headers */ = {isa = PBXBuildFile; fileRef = 16BFA66E14E195E9009704F8 /* ios_exception_minidump_generator.h */; };
|
16BFA67014E195E9009704F8 /* ios_exception_minidump_generator.h in Headers */ = {isa = PBXBuildFile; fileRef = 16BFA66E14E195E9009704F8 /* ios_exception_minidump_generator.h */; };
|
||||||
16BFA67214E1965A009704F8 /* ios_exception_minidump_generator.mm in Sources */ = {isa = PBXBuildFile; fileRef = 16BFA67114E1965A009704F8 /* ios_exception_minidump_generator.mm */; };
|
16BFA67214E1965A009704F8 /* ios_exception_minidump_generator.mm in Sources */ = {isa = PBXBuildFile; fileRef = 16BFA67114E1965A009704F8 /* ios_exception_minidump_generator.mm */; };
|
||||||
16C7CCCB147D4A4300776EAD /* BreakpadDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C7C968147D4A4200776EAD /* BreakpadDefines.h */; };
|
16C7CCCB147D4A4300776EAD /* BreakpadDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C7C968147D4A4200776EAD /* BreakpadDefines.h */; };
|
||||||
|
@ -58,6 +60,8 @@
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
14569320182CE29F0029C465 /* ucontext_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ucontext_compat.h; sourceTree = "<group>"; };
|
||||||
|
14569322182CE2C10029C465 /* mach_vm_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_vm_compat.h; sourceTree = "<group>"; };
|
||||||
16BFA66E14E195E9009704F8 /* ios_exception_minidump_generator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ios_exception_minidump_generator.h; sourceTree = "<group>"; };
|
16BFA66E14E195E9009704F8 /* ios_exception_minidump_generator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ios_exception_minidump_generator.h; sourceTree = "<group>"; };
|
||||||
16BFA67114E1965A009704F8 /* ios_exception_minidump_generator.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ios_exception_minidump_generator.mm; sourceTree = "<group>"; };
|
16BFA67114E1965A009704F8 /* ios_exception_minidump_generator.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ios_exception_minidump_generator.mm; sourceTree = "<group>"; };
|
||||||
16C7C968147D4A4200776EAD /* BreakpadDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BreakpadDefines.h; sourceTree = "<group>"; };
|
16C7C968147D4A4200776EAD /* BreakpadDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BreakpadDefines.h; sourceTree = "<group>"; };
|
||||||
|
@ -238,10 +242,12 @@
|
||||||
16C7CBB0147D4A4300776EAD /* dynamic_images.h */,
|
16C7CBB0147D4A4300776EAD /* dynamic_images.h */,
|
||||||
16C7CBB1147D4A4300776EAD /* exception_handler.cc */,
|
16C7CBB1147D4A4300776EAD /* exception_handler.cc */,
|
||||||
16C7CBB2147D4A4300776EAD /* exception_handler.h */,
|
16C7CBB2147D4A4300776EAD /* exception_handler.h */,
|
||||||
|
14569322182CE2C10029C465 /* mach_vm_compat.h */,
|
||||||
16C7CBB4147D4A4300776EAD /* minidump_generator.cc */,
|
16C7CBB4147D4A4300776EAD /* minidump_generator.cc */,
|
||||||
16C7CBB5147D4A4300776EAD /* minidump_generator.h */,
|
16C7CBB5147D4A4300776EAD /* minidump_generator.h */,
|
||||||
16C7CBBC147D4A4300776EAD /* protected_memory_allocator.cc */,
|
16C7CBBC147D4A4300776EAD /* protected_memory_allocator.cc */,
|
||||||
16C7CBBD147D4A4300776EAD /* protected_memory_allocator.h */,
|
16C7CBBD147D4A4300776EAD /* protected_memory_allocator.h */,
|
||||||
|
14569320182CE29F0029C465 /* ucontext_compat.h */,
|
||||||
);
|
);
|
||||||
path = handler;
|
path = handler;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -312,6 +318,7 @@
|
||||||
16C7CCCB147D4A4300776EAD /* BreakpadDefines.h in Headers */,
|
16C7CCCB147D4A4300776EAD /* BreakpadDefines.h in Headers */,
|
||||||
16C7CCCC147D4A4300776EAD /* Breakpad.h in Headers */,
|
16C7CCCC147D4A4300776EAD /* Breakpad.h in Headers */,
|
||||||
16C7CDE8147D4A4300776EAD /* ConfigFile.h in Headers */,
|
16C7CDE8147D4A4300776EAD /* ConfigFile.h in Headers */,
|
||||||
|
14569321182CE29F0029C465 /* ucontext_compat.h in Headers */,
|
||||||
16C7CDF6147D4A4300776EAD /* breakpad_nlist_64.h in Headers */,
|
16C7CDF6147D4A4300776EAD /* breakpad_nlist_64.h in Headers */,
|
||||||
16C7CDF8147D4A4300776EAD /* dynamic_images.h in Headers */,
|
16C7CDF8147D4A4300776EAD /* dynamic_images.h in Headers */,
|
||||||
16C7CDFA147D4A4300776EAD /* exception_handler.h in Headers */,
|
16C7CDFA147D4A4300776EAD /* exception_handler.h in Headers */,
|
||||||
|
@ -333,6 +340,7 @@
|
||||||
16BFA67014E195E9009704F8 /* ios_exception_minidump_generator.h in Headers */,
|
16BFA67014E195E9009704F8 /* ios_exception_minidump_generator.h in Headers */,
|
||||||
16C92FAD150DF8330053D7BA /* BreakpadController.h in Headers */,
|
16C92FAD150DF8330053D7BA /* BreakpadController.h in Headers */,
|
||||||
1EEEB6101720821900F7E689 /* simple_string_dictionary.h in Headers */,
|
1EEEB6101720821900F7E689 /* simple_string_dictionary.h in Headers */,
|
||||||
|
14569323182CE2C10029C465 /* mach_vm_compat.h in Headers */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -431,7 +439,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
DSTROOT = /tmp/Breakpad.dst;
|
DSTROOT = /tmp/Breakpad.dst;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
@ -463,7 +471,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
|
||||||
DSTROOT = /tmp/Breakpad.dst;
|
DSTROOT = /tmp/Breakpad.dst;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
|
@ -491,7 +499,7 @@
|
||||||
1DEB922308733DC00010E9CD /* Debug */ = {
|
1DEB922308733DC00010E9CD /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
|
||||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = c99;
|
GCC_C_LANGUAGE_STANDARD = c99;
|
||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
@ -517,7 +525,7 @@
|
||||||
1DEB922408733DC00010E9CD /* Release */ = {
|
1DEB922408733DC00010E9CD /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
|
||||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = c99;
|
GCC_C_LANGUAGE_STANDARD = c99;
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
|
|
@ -51,13 +51,20 @@ class IosExceptionMinidumpGenerator : public MinidumpGenerator {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Get the crashing program counter from the exception.
|
// Get the crashing program counter from the exception.
|
||||||
uint32_t GetPCFromException();
|
uintptr_t GetPCFromException();
|
||||||
|
|
||||||
// Get the crashing link register from the exception.
|
// Get the crashing link register from the exception.
|
||||||
uint32_t GetLRFromException();
|
uintptr_t GetLRFromException();
|
||||||
|
|
||||||
// Write a virtual thread context for the crashing site.
|
// Write a virtual thread context for the crashing site.
|
||||||
bool WriteCrashingContext(MDLocationDescriptor *register_location);
|
bool WriteCrashingContext(MDLocationDescriptor *register_location);
|
||||||
|
// Per-CPU implementations of the above method.
|
||||||
|
#ifdef HAS_ARM_SUPPORT
|
||||||
|
bool WriteCrashingContextARM(MDLocationDescriptor *register_location);
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_ARM64_SUPPORT
|
||||||
|
bool WriteCrashingContextARM64(MDLocationDescriptor *register_location);
|
||||||
|
#endif
|
||||||
|
|
||||||
NSArray *return_addresses_;
|
NSArray *return_addresses_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,25 +31,32 @@
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "google_breakpad/common/minidump_cpu_arm.h"
|
||||||
|
#include "google_breakpad/common/minidump_cpu_arm64.h"
|
||||||
#include "google_breakpad/common/minidump_exception_mac.h"
|
#include "google_breakpad/common/minidump_exception_mac.h"
|
||||||
#include "client/minidump_file_writer-inl.h"
|
#include "client/minidump_file_writer-inl.h"
|
||||||
#include "common/scoped_ptr.h"
|
#include "common/scoped_ptr.h"
|
||||||
|
|
||||||
|
#if !defined(HAS_ARM_SUPPORT) && !defined(HAS_ARM64_SUPPORT)
|
||||||
|
#error "This file should only be compiled for ARM processors"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAS_ARM_SUPPORT) && defined(HAS_ARM64_SUPPORT)
|
||||||
|
#error "This file should be compiled for only one architecture at a time"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const uint32_t kExpectedFinalFp = 4;
|
const uintptr_t kExpectedFinalFp = sizeof(uintptr_t);
|
||||||
const uint32_t kExpectedFinalSp = 0;
|
const uintptr_t kExpectedFinalSp = 0;
|
||||||
const int kExceptionType = EXC_SOFTWARE;
|
const int kExceptionType = EXC_SOFTWARE;
|
||||||
const int kExceptionCode = MD_EXCEPTION_CODE_MAC_NS_EXCEPTION;
|
const int kExceptionCode = MD_EXCEPTION_CODE_MAC_NS_EXCEPTION;
|
||||||
|
|
||||||
#ifdef HAS_ARM_SUPPORT
|
// Append the given value to the sp position of the stack represented
|
||||||
// Append the given 4 bytes value to the sp position of the stack represented
|
|
||||||
// by memory.
|
// by memory.
|
||||||
void AppendToMemory(uint8_t *memory, uint32_t sp, uint32_t data) {
|
void AppendToMemory(uint8_t *memory, uintptr_t sp, uintptr_t data) {
|
||||||
assert(sizeof(data) == 4);
|
|
||||||
memcpy(memory + sp, &data, sizeof(data));
|
memcpy(memory + sp, &data, sizeof(data));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -72,6 +79,18 @@ IosExceptionMinidumpGenerator::~IosExceptionMinidumpGenerator() {
|
||||||
bool IosExceptionMinidumpGenerator::WriteCrashingContext(
|
bool IosExceptionMinidumpGenerator::WriteCrashingContext(
|
||||||
MDLocationDescriptor *register_location) {
|
MDLocationDescriptor *register_location) {
|
||||||
#ifdef HAS_ARM_SUPPORT
|
#ifdef HAS_ARM_SUPPORT
|
||||||
|
return WriteCrashingContextARM(register_location);
|
||||||
|
#elif defined(HAS_ARM64_SUPPORT)
|
||||||
|
return WriteCrashingContextARM64(register_location);
|
||||||
|
#else
|
||||||
|
#error "This file should only be compiled on ARM processors"
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_ARM_SUPPORT
|
||||||
|
bool IosExceptionMinidumpGenerator::WriteCrashingContextARM(
|
||||||
|
MDLocationDescriptor *register_location) {
|
||||||
TypedMDRVA<MDRawContextARM> context(&writer_);
|
TypedMDRVA<MDRawContextARM> context(&writer_);
|
||||||
if (!context.Allocate())
|
if (!context.Allocate())
|
||||||
return false;
|
return false;
|
||||||
|
@ -79,28 +98,42 @@ bool IosExceptionMinidumpGenerator::WriteCrashingContext(
|
||||||
MDRawContextARM *context_ptr = context.get();
|
MDRawContextARM *context_ptr = context.get();
|
||||||
memset(context_ptr, 0, sizeof(MDRawContextARM));
|
memset(context_ptr, 0, sizeof(MDRawContextARM));
|
||||||
context_ptr->context_flags = MD_CONTEXT_ARM_FULL;
|
context_ptr->context_flags = MD_CONTEXT_ARM_FULL;
|
||||||
context_ptr->iregs[7] = kExpectedFinalFp; // FP
|
context_ptr->iregs[MD_CONTEXT_ARM_REG_IOS_FP] = kExpectedFinalFp; // FP
|
||||||
context_ptr->iregs[13] = kExpectedFinalSp; // SP
|
context_ptr->iregs[MD_CONTEXT_ARM_REG_SP] = kExpectedFinalSp; // SP
|
||||||
context_ptr->iregs[14] = GetLRFromException(); // LR
|
context_ptr->iregs[MD_CONTEXT_ARM_REG_LR] = GetLRFromException(); // LR
|
||||||
context_ptr->iregs[15] = GetPCFromException(); // PC
|
context_ptr->iregs[MD_CONTEXT_ARM_REG_PC] = GetPCFromException(); // PC
|
||||||
return true;
|
return true;
|
||||||
#else
|
|
||||||
assert(false);
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32_t IosExceptionMinidumpGenerator::GetPCFromException() {
|
#ifdef HAS_ARM64_SUPPORT
|
||||||
|
bool IosExceptionMinidumpGenerator::WriteCrashingContextARM64(
|
||||||
|
MDLocationDescriptor *register_location) {
|
||||||
|
TypedMDRVA<MDRawContextARM64> context(&writer_);
|
||||||
|
if (!context.Allocate())
|
||||||
|
return false;
|
||||||
|
*register_location = context.location();
|
||||||
|
MDRawContextARM64 *context_ptr = context.get();
|
||||||
|
memset(context_ptr, 0, sizeof(*context_ptr));
|
||||||
|
context_ptr->context_flags = MD_CONTEXT_ARM64_FULL;
|
||||||
|
context_ptr->iregs[MD_CONTEXT_ARM64_REG_FP] = kExpectedFinalFp; // FP
|
||||||
|
context_ptr->iregs[MD_CONTEXT_ARM64_REG_SP] = kExpectedFinalSp; // SP
|
||||||
|
context_ptr->iregs[MD_CONTEXT_ARM64_REG_LR] = GetLRFromException(); // LR
|
||||||
|
context_ptr->iregs[MD_CONTEXT_ARM64_REG_PC] = GetPCFromException(); // PC
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uintptr_t IosExceptionMinidumpGenerator::GetPCFromException() {
|
||||||
return [[return_addresses_ objectAtIndex:0] unsignedIntegerValue];
|
return [[return_addresses_ objectAtIndex:0] unsignedIntegerValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t IosExceptionMinidumpGenerator::GetLRFromException() {
|
uintptr_t IosExceptionMinidumpGenerator::GetLRFromException() {
|
||||||
return [[return_addresses_ objectAtIndex:1] unsignedIntegerValue];
|
return [[return_addresses_ objectAtIndex:1] unsignedIntegerValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IosExceptionMinidumpGenerator::WriteExceptionStream(
|
bool IosExceptionMinidumpGenerator::WriteExceptionStream(
|
||||||
MDRawDirectory *exception_stream) {
|
MDRawDirectory *exception_stream) {
|
||||||
#ifdef HAS_ARM_SUPPORT
|
|
||||||
TypedMDRVA<MDRawExceptionStream> exception(&writer_);
|
TypedMDRVA<MDRawExceptionStream> exception(&writer_);
|
||||||
|
|
||||||
if (!exception.Allocate())
|
if (!exception.Allocate())
|
||||||
|
@ -121,37 +154,35 @@ bool IosExceptionMinidumpGenerator::WriteExceptionStream(
|
||||||
|
|
||||||
exception_ptr->exception_record.exception_address = GetPCFromException();
|
exception_ptr->exception_record.exception_address = GetPCFromException();
|
||||||
return true;
|
return true;
|
||||||
#else
|
|
||||||
return MinidumpGenerator::WriteExceptionStream(exception_stream);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IosExceptionMinidumpGenerator::WriteThreadStream(mach_port_t thread_id,
|
bool IosExceptionMinidumpGenerator::WriteThreadStream(mach_port_t thread_id,
|
||||||
MDRawThread *thread) {
|
MDRawThread *thread) {
|
||||||
#ifdef HAS_ARM_SUPPORT
|
|
||||||
if (pthread_mach_thread_np(pthread_self()) != thread_id)
|
if (pthread_mach_thread_np(pthread_self()) != thread_id)
|
||||||
return MinidumpGenerator::WriteThreadStream(thread_id, thread);
|
return MinidumpGenerator::WriteThreadStream(thread_id, thread);
|
||||||
|
|
||||||
size_t frame_count = [return_addresses_ count];
|
size_t frame_count = [return_addresses_ count];
|
||||||
UntypedMDRVA memory(&writer_);
|
UntypedMDRVA memory(&writer_);
|
||||||
size_t size = 8 * (frame_count - 1) + 4;
|
size_t pointer_size = sizeof(uintptr_t);
|
||||||
if (!memory.Allocate(size))
|
size_t frame_record_size = 2 * pointer_size;
|
||||||
|
size_t stack_size = frame_record_size * (frame_count - 1) + pointer_size;
|
||||||
|
if (!memory.Allocate(stack_size))
|
||||||
return false;
|
return false;
|
||||||
scoped_array<uint8_t> stack_memory(new uint8_t[size]);
|
scoped_array<uint8_t> stack_memory(new uint8_t[stack_size]);
|
||||||
uint32_t sp = size - 4;
|
uintptr_t sp = stack_size - pointer_size;
|
||||||
uint32_t fp = 0;
|
uintptr_t fp = 0;
|
||||||
uint32_t lr = 0;
|
uintptr_t lr = 0;
|
||||||
for (int current_frame = frame_count - 1;
|
for (int current_frame = frame_count - 1;
|
||||||
current_frame > 0;
|
current_frame > 0;
|
||||||
--current_frame) {
|
--current_frame) {
|
||||||
AppendToMemory(stack_memory.get(), sp, lr);
|
AppendToMemory(stack_memory.get(), sp, lr);
|
||||||
sp -= 4;
|
sp -= pointer_size;
|
||||||
AppendToMemory(stack_memory.get(), sp, fp);
|
AppendToMemory(stack_memory.get(), sp, fp);
|
||||||
fp = sp;
|
fp = sp;
|
||||||
sp -= 4;
|
sp -= pointer_size;
|
||||||
lr = [[return_addresses_ objectAtIndex:current_frame] unsignedIntegerValue];
|
lr = [[return_addresses_ objectAtIndex:current_frame] unsignedIntegerValue];
|
||||||
}
|
}
|
||||||
if (!memory.Copy(stack_memory.get(), size))
|
if (!memory.Copy(stack_memory.get(), stack_size))
|
||||||
return false;
|
return false;
|
||||||
assert(sp == kExpectedFinalSp);
|
assert(sp == kExpectedFinalSp);
|
||||||
assert(fp == kExpectedFinalFp);
|
assert(fp == kExpectedFinalFp);
|
||||||
|
@ -165,9 +196,6 @@ bool IosExceptionMinidumpGenerator::WriteThreadStream(mach_port_t thread_id,
|
||||||
|
|
||||||
thread->thread_id = thread_id;
|
thread->thread_id = thread_id;
|
||||||
return true;
|
return true;
|
||||||
#else
|
|
||||||
return MinidumpGenerator::WriteThreadStream(thread_id, thread);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
|
|
@ -285,6 +285,8 @@ class DynamicImages {
|
||||||
return CPU_TYPE_POWERPC64;
|
return CPU_TYPE_POWERPC64;
|
||||||
#elif defined(__arm__)
|
#elif defined(__arm__)
|
||||||
return CPU_TYPE_ARM;
|
return CPU_TYPE_ARM;
|
||||||
|
#elif defined(__arm64__)
|
||||||
|
return CPU_TYPE_ARM64;
|
||||||
#else
|
#else
|
||||||
#error "GetNativeCPUType not implemented for this architecture"
|
#error "GetNativeCPUType not implemented for this architecture"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -326,7 +326,7 @@ bool ExceptionHandler::WriteMinidumpForChild(mach_port_t child,
|
||||||
EXC_I386_BPT,
|
EXC_I386_BPT,
|
||||||
#elif defined(__ppc__) || defined(__ppc64__)
|
#elif defined(__ppc__) || defined(__ppc64__)
|
||||||
EXC_PPC_BREAKPOINT,
|
EXC_PPC_BREAKPOINT,
|
||||||
#elif defined(__arm__)
|
#elif defined(__arm__) || defined(__arm64__)
|
||||||
EXC_ARM_BREAKPOINT,
|
EXC_ARM_BREAKPOINT,
|
||||||
#else
|
#else
|
||||||
#error architecture not supported
|
#error architecture not supported
|
||||||
|
@ -342,10 +342,11 @@ bool ExceptionHandler::WriteMinidumpForChild(mach_port_t child,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExceptionHandler::WriteMinidumpWithException(int exception_type,
|
bool ExceptionHandler::WriteMinidumpWithException(
|
||||||
|
int exception_type,
|
||||||
int exception_code,
|
int exception_code,
|
||||||
int exception_subcode,
|
int exception_subcode,
|
||||||
ucontext_t* task_context,
|
breakpad_ucontext_t* task_context,
|
||||||
mach_port_t thread_name,
|
mach_port_t thread_name,
|
||||||
bool exit_after_write,
|
bool exit_after_write,
|
||||||
bool report_current_thread) {
|
bool report_current_thread) {
|
||||||
|
@ -453,12 +454,13 @@ kern_return_t ForwardException(mach_port_t task, mach_port_t failed_thread,
|
||||||
exception_behavior_t target_behavior = current.behaviors[found];
|
exception_behavior_t target_behavior = current.behaviors[found];
|
||||||
|
|
||||||
kern_return_t result;
|
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
|
||||||
switch (target_behavior) {
|
switch (target_behavior) {
|
||||||
case EXCEPTION_DEFAULT:
|
case EXCEPTION_DEFAULT:
|
||||||
result = exception_raise(target_port, failed_thread, task, exception,
|
result = exception_raise(target_port, failed_thread, task, exception,
|
||||||
code, code_count);
|
code, code_count);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "** Unknown exception behavior: %d\n", target_behavior);
|
fprintf(stderr, "** Unknown exception behavior: %d\n", target_behavior);
|
||||||
result = KERN_FAILURE;
|
result = KERN_FAILURE;
|
||||||
|
@ -520,7 +522,7 @@ void* ExceptionHandler::WaitForMessage(void* exception_handler_class) {
|
||||||
exception_code = EXC_I386_BPT;
|
exception_code = EXC_I386_BPT;
|
||||||
#elif defined(__ppc__) || defined(__ppc64__)
|
#elif defined(__ppc__) || defined(__ppc64__)
|
||||||
exception_code = EXC_PPC_BREAKPOINT;
|
exception_code = EXC_PPC_BREAKPOINT;
|
||||||
#elif defined(__arm__)
|
#elif defined(__arm__) || defined(__arm64__)
|
||||||
exception_code = EXC_ARM_BREAKPOINT;
|
exception_code = EXC_ARM_BREAKPOINT;
|
||||||
#else
|
#else
|
||||||
#error architecture not supported
|
#error architecture not supported
|
||||||
|
@ -611,7 +613,7 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
|
||||||
EXC_SOFTWARE,
|
EXC_SOFTWARE,
|
||||||
MD_EXCEPTION_CODE_MAC_ABORT,
|
MD_EXCEPTION_CODE_MAC_ABORT,
|
||||||
0,
|
0,
|
||||||
static_cast<ucontext_t*>(uc),
|
static_cast<breakpad_ucontext_t*>(uc),
|
||||||
mach_thread_self(),
|
mach_thread_self(),
|
||||||
true,
|
true,
|
||||||
true);
|
true);
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "client/mac/handler/ucontext_compat.h"
|
||||||
#include "common/scoped_ptr.h"
|
#include "common/scoped_ptr.h"
|
||||||
|
|
||||||
#if !TARGET_OS_IPHONE
|
#if !TARGET_OS_IPHONE
|
||||||
|
@ -188,7 +189,7 @@ class ExceptionHandler {
|
||||||
bool WriteMinidumpWithException(int exception_type,
|
bool WriteMinidumpWithException(int exception_type,
|
||||||
int exception_code,
|
int exception_code,
|
||||||
int exception_subcode,
|
int exception_subcode,
|
||||||
ucontext_t *task_context,
|
breakpad_ucontext_t *task_context,
|
||||||
mach_port_t thread_name,
|
mach_port_t thread_name,
|
||||||
bool exit_after_write,
|
bool exit_after_write,
|
||||||
bool report_current_thread);
|
bool report_current_thread);
|
||||||
|
|
|
@ -32,14 +32,18 @@
|
||||||
|
|
||||||
#include <TargetConditionals.h>
|
#include <TargetConditionals.h>
|
||||||
|
|
||||||
// On iOS 5, mach/mach_vm.h is not supported anymore. As the architecture is 32
|
// On iOS 5 and higher, mach/mach_vm.h is not supported. Use the corresponding
|
||||||
// bits, we can use the simple vm_ functions instead of the mach_vm_ ones.
|
// vm_map functions instead.
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
#include <mach/vm_map.h>
|
#include <mach/vm_map.h>
|
||||||
#define mach_vm_address_t vm_address_t
|
#define mach_vm_address_t vm_address_t
|
||||||
#define mach_vm_deallocate vm_deallocate
|
#define mach_vm_deallocate vm_deallocate
|
||||||
#define mach_vm_read vm_read
|
#define mach_vm_read vm_read
|
||||||
|
#if defined(__LP64__)
|
||||||
|
#define mach_vm_region_recurse vm_region_recurse_64
|
||||||
|
#else
|
||||||
#define mach_vm_region_recurse vm_region_recurse
|
#define mach_vm_region_recurse vm_region_recurse
|
||||||
|
#endif
|
||||||
#define mach_vm_size_t vm_size_t
|
#define mach_vm_size_t vm_size_t
|
||||||
#else
|
#else
|
||||||
#include <mach/mach_vm.h>
|
#include <mach/mach_vm.h>
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
|
|
||||||
#include "client/mac/handler/minidump_generator.h"
|
#include "client/mac/handler/minidump_generator.h"
|
||||||
|
|
||||||
#ifdef HAS_ARM_SUPPORT
|
#if defined(HAS_ARM_SUPPORT) || defined(HAS_ARM64_SUPPORT)
|
||||||
#include <mach/arm/thread_status.h>
|
#include <mach/arm/thread_status.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAS_PPC_SUPPORT
|
#ifdef HAS_PPC_SUPPORT
|
||||||
|
@ -171,7 +171,7 @@ void MinidumpGenerator::GatherSystemInformation() {
|
||||||
os_build_number_ = IntegerValueAtIndex(product_str, 2);
|
os_build_number_ = IntegerValueAtIndex(product_str, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinidumpGenerator::SetTaskContext(ucontext_t *task_context) {
|
void MinidumpGenerator::SetTaskContext(breakpad_ucontext_t *task_context) {
|
||||||
task_context_ = task_context;
|
task_context_ = task_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,6 +369,10 @@ bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state,
|
||||||
case CPU_TYPE_ARM:
|
case CPU_TYPE_ARM:
|
||||||
return WriteStackARM(state, stack_location);
|
return WriteStackARM(state, stack_location);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAS_ARM64_SUPPORT
|
||||||
|
case CPU_TYPE_ARM64:
|
||||||
|
return WriteStackARM64(state, stack_location);
|
||||||
|
#endif
|
||||||
#ifdef HAS_PPC_SUPPORT
|
#ifdef HAS_PPC_SUPPORT
|
||||||
case CPU_TYPE_POWERPC:
|
case CPU_TYPE_POWERPC:
|
||||||
return WriteStackPPC(state, stack_location);
|
return WriteStackPPC(state, stack_location);
|
||||||
|
@ -393,6 +397,10 @@ bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
|
||||||
case CPU_TYPE_ARM:
|
case CPU_TYPE_ARM:
|
||||||
return WriteContextARM(state, register_location);
|
return WriteContextARM(state, register_location);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAS_ARM64_SUPPORT
|
||||||
|
case CPU_TYPE_ARM64:
|
||||||
|
return WriteContextARM64(state, register_location);
|
||||||
|
#endif
|
||||||
#ifdef HAS_PPC_SUPPORT
|
#ifdef HAS_PPC_SUPPORT
|
||||||
case CPU_TYPE_POWERPC:
|
case CPU_TYPE_POWERPC:
|
||||||
return WriteContextPPC(state, register_location);
|
return WriteContextPPC(state, register_location);
|
||||||
|
@ -417,6 +425,10 @@ uint64_t MinidumpGenerator::CurrentPCForStack(
|
||||||
case CPU_TYPE_ARM:
|
case CPU_TYPE_ARM:
|
||||||
return CurrentPCForStackARM(state);
|
return CurrentPCForStackARM(state);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAS_ARM64_SUPPORT
|
||||||
|
case CPU_TYPE_ARM64:
|
||||||
|
return CurrentPCForStackARM64(state);
|
||||||
|
#endif
|
||||||
#ifdef HAS_PPC_SUPPORT
|
#ifdef HAS_PPC_SUPPORT
|
||||||
case CPU_TYPE_POWERPC:
|
case CPU_TYPE_POWERPC:
|
||||||
return CurrentPCForStackPPC(state);
|
return CurrentPCForStackPPC(state);
|
||||||
|
@ -486,7 +498,82 @@ bool MinidumpGenerator::WriteContextARM(breakpad_thread_state_data_t state,
|
||||||
AddGPR(10);
|
AddGPR(10);
|
||||||
AddGPR(11);
|
AddGPR(11);
|
||||||
AddGPR(12);
|
AddGPR(12);
|
||||||
#undef AddReg
|
#undef AddGPR
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_ARM64_SUPPORT
|
||||||
|
bool MinidumpGenerator::WriteStackARM64(breakpad_thread_state_data_t state,
|
||||||
|
MDMemoryDescriptor *stack_location) {
|
||||||
|
arm_thread_state64_t *machine_state =
|
||||||
|
reinterpret_cast<arm_thread_state64_t *>(state);
|
||||||
|
mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, sp);
|
||||||
|
return WriteStackFromStartAddress(start_addr, stack_location);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
MinidumpGenerator::CurrentPCForStackARM64(breakpad_thread_state_data_t state) {
|
||||||
|
arm_thread_state64_t *machine_state =
|
||||||
|
reinterpret_cast<arm_thread_state64_t *>(state);
|
||||||
|
|
||||||
|
return REGISTER_FROM_THREADSTATE(machine_state, pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MinidumpGenerator::WriteContextARM64(breakpad_thread_state_data_t state,
|
||||||
|
MDLocationDescriptor *register_location)
|
||||||
|
{
|
||||||
|
TypedMDRVA<MDRawContextARM64> context(&writer_);
|
||||||
|
arm_thread_state64_t *machine_state =
|
||||||
|
reinterpret_cast<arm_thread_state64_t *>(state);
|
||||||
|
|
||||||
|
if (!context.Allocate())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*register_location = context.location();
|
||||||
|
MDRawContextARM64 *context_ptr = context.get();
|
||||||
|
context_ptr->context_flags = MD_CONTEXT_ARM64_FULL;
|
||||||
|
|
||||||
|
#define AddGPR(a) context_ptr->iregs[a] = \
|
||||||
|
REGISTER_FROM_THREADSTATE(machine_state, x[a])
|
||||||
|
|
||||||
|
context_ptr->iregs[29] = REGISTER_FROM_THREADSTATE(machine_state, fp);
|
||||||
|
context_ptr->iregs[30] = REGISTER_FROM_THREADSTATE(machine_state, lr);
|
||||||
|
context_ptr->iregs[31] = REGISTER_FROM_THREADSTATE(machine_state, sp);
|
||||||
|
context_ptr->iregs[32] = REGISTER_FROM_THREADSTATE(machine_state, pc);
|
||||||
|
context_ptr->cpsr = REGISTER_FROM_THREADSTATE(machine_state, cpsr);
|
||||||
|
|
||||||
|
AddGPR(0);
|
||||||
|
AddGPR(1);
|
||||||
|
AddGPR(2);
|
||||||
|
AddGPR(3);
|
||||||
|
AddGPR(4);
|
||||||
|
AddGPR(5);
|
||||||
|
AddGPR(6);
|
||||||
|
AddGPR(7);
|
||||||
|
AddGPR(8);
|
||||||
|
AddGPR(9);
|
||||||
|
AddGPR(10);
|
||||||
|
AddGPR(11);
|
||||||
|
AddGPR(12);
|
||||||
|
AddGPR(13);
|
||||||
|
AddGPR(14);
|
||||||
|
AddGPR(15);
|
||||||
|
AddGPR(16);
|
||||||
|
AddGPR(17);
|
||||||
|
AddGPR(18);
|
||||||
|
AddGPR(19);
|
||||||
|
AddGPR(20);
|
||||||
|
AddGPR(21);
|
||||||
|
AddGPR(22);
|
||||||
|
AddGPR(23);
|
||||||
|
AddGPR(24);
|
||||||
|
AddGPR(25);
|
||||||
|
AddGPR(26);
|
||||||
|
AddGPR(27);
|
||||||
|
AddGPR(28);
|
||||||
#undef AddGPR
|
#undef AddGPR
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -780,10 +867,18 @@ bool MinidumpGenerator::GetThreadState(thread_act_t target_thread,
|
||||||
if (task_context_ && target_thread == mach_thread_self()) {
|
if (task_context_ && target_thread == mach_thread_self()) {
|
||||||
switch (cpu_type_) {
|
switch (cpu_type_) {
|
||||||
#ifdef HAS_ARM_SUPPORT
|
#ifdef HAS_ARM_SUPPORT
|
||||||
case CPU_TYPE_ARM: {
|
case CPU_TYPE_ARM:
|
||||||
size_t final_size =
|
size_t final_size =
|
||||||
std::min(static_cast<size_t>(*count), sizeof(arm_thread_state_t));
|
std::min(static_cast<size_t>(*count), sizeof(arm_thread_state_t));
|
||||||
memcpy(state, &task_context_->uc_mcontext->__ss, final_size);
|
memcpy(state, &task_context_->breakpad_uc_mcontext->__ss, final_size);
|
||||||
|
*count = final_size;
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_ARM64_SUPPORT
|
||||||
|
case CPU_TYPE_ARM64: {
|
||||||
|
size_t final_size =
|
||||||
|
std::min(static_cast<size_t>(*count), sizeof(arm_thread_state64_t));
|
||||||
|
memcpy(state, &task_context_->breakpad_uc_mcontext->__ss, final_size);
|
||||||
*count = final_size;
|
*count = final_size;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -795,7 +890,7 @@ bool MinidumpGenerator::GetThreadState(thread_act_t target_thread,
|
||||||
sizeof(i386_thread_state_t) : sizeof(x86_thread_state64_t);
|
sizeof(i386_thread_state_t) : sizeof(x86_thread_state64_t);
|
||||||
size_t final_size =
|
size_t final_size =
|
||||||
std::min(static_cast<size_t>(*count), state_size);
|
std::min(static_cast<size_t>(*count), state_size);
|
||||||
memcpy(state, &task_context_->uc_mcontext->__ss, final_size);
|
memcpy(state, &task_context_->breakpad_uc_mcontext->__ss, final_size);
|
||||||
*count = final_size;
|
*count = final_size;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -810,6 +905,11 @@ bool MinidumpGenerator::GetThreadState(thread_act_t target_thread,
|
||||||
flavor = ARM_THREAD_STATE;
|
flavor = ARM_THREAD_STATE;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAS_ARM64_SUPPORT
|
||||||
|
case CPU_TYPE_ARM64:
|
||||||
|
flavor = ARM_THREAD_STATE64;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
#ifdef HAS_PPC_SUPPORT
|
#ifdef HAS_PPC_SUPPORT
|
||||||
case CPU_TYPE_POWERPC:
|
case CPU_TYPE_POWERPC:
|
||||||
flavor = PPC_THREAD_STATE;
|
flavor = PPC_THREAD_STATE;
|
||||||
|
@ -1060,6 +1160,11 @@ bool MinidumpGenerator::WriteSystemInfoStream(
|
||||||
info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_ARM;
|
info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_ARM;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAS_ARM64_SUPPORT
|
||||||
|
case CPU_TYPE_ARM64:
|
||||||
|
info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_ARM64;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
#ifdef HAS_PPC_SUPPORT
|
#ifdef HAS_PPC_SUPPORT
|
||||||
case CPU_TYPE_POWERPC:
|
case CPU_TYPE_POWERPC:
|
||||||
case CPU_TYPE_POWERPC64:
|
case CPU_TYPE_POWERPC64:
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "client/mac/handler/ucontext_compat.h"
|
||||||
#include "client/minidump_file_writer.h"
|
#include "client/minidump_file_writer.h"
|
||||||
#include "common/memory.h"
|
#include "common/memory.h"
|
||||||
#include "common/mac/macho_utilities.h"
|
#include "common/mac/macho_utilities.h"
|
||||||
|
@ -50,6 +51,8 @@
|
||||||
#endif
|
#endif
|
||||||
#if defined(__arm__)
|
#if defined(__arm__)
|
||||||
#define HAS_ARM_SUPPORT
|
#define HAS_ARM_SUPPORT
|
||||||
|
#elif defined(__arm64__)
|
||||||
|
#define HAS_ARM64_SUPPORT
|
||||||
#elif defined(__i386__) || defined(__x86_64__)
|
#elif defined(__i386__) || defined(__x86_64__)
|
||||||
#define HAS_X86_SUPPORT
|
#define HAS_X86_SUPPORT
|
||||||
#endif
|
#endif
|
||||||
|
@ -105,7 +108,7 @@ class MinidumpGenerator {
|
||||||
// Specify the task context. If |task_context| is not NULL, it will be used
|
// Specify the task context. If |task_context| is not NULL, it will be used
|
||||||
// to retrieve the context of the current thread, instead of using
|
// to retrieve the context of the current thread, instead of using
|
||||||
// |thread_get_state|.
|
// |thread_get_state|.
|
||||||
void SetTaskContext(ucontext_t *task_context);
|
void SetTaskContext(breakpad_ucontext_t *task_context);
|
||||||
|
|
||||||
// Gather system information. This should be call at least once before using
|
// Gather system information. This should be call at least once before using
|
||||||
// the MinidumpGenerator class.
|
// the MinidumpGenerator class.
|
||||||
|
@ -153,6 +156,13 @@ class MinidumpGenerator {
|
||||||
MDLocationDescriptor *register_location);
|
MDLocationDescriptor *register_location);
|
||||||
uint64_t CurrentPCForStackARM(breakpad_thread_state_data_t state);
|
uint64_t CurrentPCForStackARM(breakpad_thread_state_data_t state);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAS_ARM64_SUPPORT
|
||||||
|
bool WriteStackARM64(breakpad_thread_state_data_t state,
|
||||||
|
MDMemoryDescriptor *stack_location);
|
||||||
|
bool WriteContextARM64(breakpad_thread_state_data_t state,
|
||||||
|
MDLocationDescriptor *register_location);
|
||||||
|
uint64_t CurrentPCForStackARM64(breakpad_thread_state_data_t state);
|
||||||
|
#endif
|
||||||
#ifdef HAS_PPC_SUPPORT
|
#ifdef HAS_PPC_SUPPORT
|
||||||
bool WriteStackPPC(breakpad_thread_state_data_t state,
|
bool WriteStackPPC(breakpad_thread_state_data_t state,
|
||||||
MDMemoryDescriptor *stack_location);
|
MDMemoryDescriptor *stack_location);
|
||||||
|
@ -205,7 +215,7 @@ class MinidumpGenerator {
|
||||||
static int os_build_number_;
|
static int os_build_number_;
|
||||||
|
|
||||||
// Context of the task to dump.
|
// Context of the task to dump.
|
||||||
ucontext_t *task_context_;
|
breakpad_ucontext_t *task_context_;
|
||||||
|
|
||||||
// Information about dynamically loaded code
|
// Information about dynamically loaded code
|
||||||
DynamicImages *dynamic_images_;
|
DynamicImages *dynamic_images_;
|
||||||
|
|
47
src/client/mac/handler/ucontext_compat.h
Normal file
47
src/client/mac/handler/ucontext_compat.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright 2013 Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef CLIENT_MAC_HANDLER_UCONTEXT_COMPAT_H_
|
||||||
|
#define CLIENT_MAC_HANDLER_UCONTEXT_COMPAT_H_
|
||||||
|
|
||||||
|
#include <sys/ucontext.h>
|
||||||
|
|
||||||
|
// The purpose of this file is to work around the fact that ucontext_t's
|
||||||
|
// uc_mcontext member is an mcontext_t rather than an mcontext64_t on ARM64.
|
||||||
|
#if defined(__arm64__)
|
||||||
|
// <sys/ucontext.h> doesn't include the below file.
|
||||||
|
#include <sys/_types/_ucontext64.h>
|
||||||
|
typedef ucontext64_t breakpad_ucontext_t;
|
||||||
|
#define breakpad_uc_mcontext uc_mcontext64
|
||||||
|
#else
|
||||||
|
typedef ucontext_t breakpad_ucontext_t;
|
||||||
|
#define breakpad_uc_mcontext uc_mcontext
|
||||||
|
#endif // defined(__arm64__)
|
||||||
|
|
||||||
|
#endif // CLIENT_MAC_HANDLER_UCONTEXT_COMPAT_H_
|
140
src/google_breakpad/common/minidump_cpu_arm64.h
Normal file
140
src/google_breakpad/common/minidump_cpu_arm64.h
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/* Copyright 2013 Google Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
|
* in the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Google Inc. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* 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. */
|
||||||
|
|
||||||
|
/* minidump_format.h: A cross-platform reimplementation of minidump-related
|
||||||
|
* portions of DbgHelp.h from the Windows Platform SDK.
|
||||||
|
*
|
||||||
|
* (This is C99 source, please don't corrupt it with C++.)
|
||||||
|
*
|
||||||
|
* This file contains the necessary definitions to read minidump files
|
||||||
|
* produced on ARM. These files may be read on any platform provided
|
||||||
|
* that the alignments of these structures on the processing system are
|
||||||
|
* identical to the alignments of these structures on the producing system.
|
||||||
|
* For this reason, precise-sized types are used. The structures defined
|
||||||
|
* by this file have been laid out to minimize alignment problems by
|
||||||
|
* ensuring that all members are aligned on their natural boundaries.
|
||||||
|
* In some cases, tail-padding may be significant when different ABIs specify
|
||||||
|
* different tail-padding behaviors. To avoid problems when reading or
|
||||||
|
* writing affected structures, MD_*_SIZE macros are provided where needed,
|
||||||
|
* containing the useful size of the structures without padding.
|
||||||
|
*
|
||||||
|
* Structures that are defined by Microsoft to contain a zero-length array
|
||||||
|
* are instead defined here to contain an array with one element, as
|
||||||
|
* zero-length arrays are forbidden by standard C and C++. In these cases,
|
||||||
|
* *_minsize constants are provided to be used in place of sizeof. For a
|
||||||
|
* cleaner interface to these sizes when using C++, see minidump_size.h.
|
||||||
|
*
|
||||||
|
* These structures are also sufficient to populate minidump files.
|
||||||
|
*
|
||||||
|
* Because precise data type sizes are crucial for this implementation to
|
||||||
|
* function properly and portably, a set of primitive types with known sizes
|
||||||
|
* are used as the basis of each structure defined by this file.
|
||||||
|
*
|
||||||
|
* Author: Colin Blundell
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ARM64 support
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM64_H__
|
||||||
|
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM64_H__
|
||||||
|
|
||||||
|
#define MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT 32
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t fpsr; /* FPU status register */
|
||||||
|
uint32_t fpcr; /* FPU control register */
|
||||||
|
|
||||||
|
/* 32 128-bit floating point registers, d0 .. d31. */
|
||||||
|
uint128_struct regs[MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT];
|
||||||
|
} MDFloatingSaveAreaARM64;
|
||||||
|
|
||||||
|
#define MD_CONTEXT_ARM64_GPR_COUNT 33
|
||||||
|
|
||||||
|
/* Use the same 32-bit alignment when accessing this structure from 64-bit code
|
||||||
|
* as is used natively in 32-bit code. */
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* The next field determines the layout of the structure, and which parts
|
||||||
|
* of it are populated
|
||||||
|
*/
|
||||||
|
uint64_t context_flags;
|
||||||
|
|
||||||
|
/* 33 64-bit integer registers, x0 .. x31 + the PC
|
||||||
|
* Note the following fixed uses:
|
||||||
|
* x29 is the frame pointer
|
||||||
|
* x30 is the link register
|
||||||
|
* x31 is the stack pointer
|
||||||
|
* The PC is effectively x32.
|
||||||
|
*/
|
||||||
|
uint64_t iregs[MD_CONTEXT_ARM64_GPR_COUNT];
|
||||||
|
|
||||||
|
/* CPSR (flags, basically): 32 bits:
|
||||||
|
bit 31 - N (negative)
|
||||||
|
bit 30 - Z (zero)
|
||||||
|
bit 29 - C (carry)
|
||||||
|
bit 28 - V (overflow)
|
||||||
|
bit 27 - Q (saturation flag, sticky)
|
||||||
|
All other fields -- ignore */
|
||||||
|
uint32_t cpsr;
|
||||||
|
|
||||||
|
/* The next field is included with MD_CONTEXT64_ARM_FLOATING_POINT */
|
||||||
|
MDFloatingSaveAreaARM64 float_save;
|
||||||
|
|
||||||
|
} MDRawContextARM64;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
/* Indices into iregs for registers with a dedicated or conventional
|
||||||
|
* purpose.
|
||||||
|
*/
|
||||||
|
enum MDARM64RegisterNumbers {
|
||||||
|
MD_CONTEXT_ARM64_REG_FP = 29,
|
||||||
|
MD_CONTEXT_ARM64_REG_LR = 30,
|
||||||
|
MD_CONTEXT_ARM64_REG_SP = 31,
|
||||||
|
MD_CONTEXT_ARM64_REG_PC = 32
|
||||||
|
};
|
||||||
|
|
||||||
|
/* For (MDRawContextARM64).context_flags. These values indicate the type of
|
||||||
|
* context stored in the structure. MD_CONTEXT_ARM64 is Breakpad-defined.
|
||||||
|
* This value was chosen to avoid likely conflicts with MD_CONTEXT_*
|
||||||
|
* for other CPUs. */
|
||||||
|
#define MD_CONTEXT_ARM64 0x80000000
|
||||||
|
#define MD_CONTEXT_ARM64_INTEGER (MD_CONTEXT_ARM64 | 0x00000002)
|
||||||
|
#define MD_CONTEXT_ARM64_FLOATING_POINT (MD_CONTEXT_ARM64 | 0x00000004)
|
||||||
|
|
||||||
|
#define MD_CONTEXT_ARM64_FULL (MD_CONTEXT_ARM64_INTEGER | \
|
||||||
|
MD_CONTEXT_ARM64_FLOATING_POINT)
|
||||||
|
|
||||||
|
#define MD_CONTEXT_ARM64_ALL (MD_CONTEXT_ARM64_INTEGER | \
|
||||||
|
MD_CONTEXT_ARM64_FLOATING_POINT)
|
||||||
|
|
||||||
|
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM64_H__ */
|
|
@ -114,6 +114,7 @@ typedef struct {
|
||||||
|
|
||||||
#include "minidump_cpu_amd64.h"
|
#include "minidump_cpu_amd64.h"
|
||||||
#include "minidump_cpu_arm.h"
|
#include "minidump_cpu_arm.h"
|
||||||
|
#include "minidump_cpu_arm64.h"
|
||||||
#include "minidump_cpu_mips.h"
|
#include "minidump_cpu_mips.h"
|
||||||
#include "minidump_cpu_ppc.h"
|
#include "minidump_cpu_ppc.h"
|
||||||
#include "minidump_cpu_ppc64.h"
|
#include "minidump_cpu_ppc64.h"
|
||||||
|
@ -636,6 +637,7 @@ typedef enum {
|
||||||
/* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */
|
/* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */
|
||||||
MD_CPU_ARCHITECTURE_SPARC = 0x8001, /* Breakpad-defined value for SPARC */
|
MD_CPU_ARCHITECTURE_SPARC = 0x8001, /* Breakpad-defined value for SPARC */
|
||||||
MD_CPU_ARCHITECTURE_PPC64 = 0x8002, /* Breakpad-defined value for PPC64 */
|
MD_CPU_ARCHITECTURE_PPC64 = 0x8002, /* Breakpad-defined value for PPC64 */
|
||||||
|
MD_CPU_ARCHITECTURE_ARM64 = 0x8003, /* Breakpad-defined value for ARM64 */
|
||||||
MD_CPU_ARCHITECTURE_UNKNOWN = 0xffff /* PROCESSOR_ARCHITECTURE_UNKNOWN */
|
MD_CPU_ARCHITECTURE_UNKNOWN = 0xffff /* PROCESSOR_ARCHITECTURE_UNKNOWN */
|
||||||
} MDCPUArchitecture;
|
} MDCPUArchitecture;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue