aboutsummaryrefslogtreecommitdiff
path: root/src/client/ios
diff options
context:
space:
mode:
authormark@chromium.org <mark@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2013-11-21 17:44:57 +0000
committermark@chromium.org <mark@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2013-11-21 17:44:57 +0000
commit77022ac0df3e079fb0abea05033b0239d12a4e72 (patch)
tree6f7207ff153e8306c441fa0cdb18b728ef971fe5 /src/client/ios
parentProvide BreakpadGetCrashReportCount() and -[BreakpadController (diff)
downloadbreakpad-77022ac0df3e079fb0abea05033b0239d12a4e72.tar.xz
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
Diffstat (limited to 'src/client/ios')
-rw-r--r--src/client/ios/Breakpad.xcodeproj/project.pbxproj16
-rw-r--r--src/client/ios/handler/ios_exception_minidump_generator.h11
-rw-r--r--src/client/ios/handler/ios_exception_minidump_generator.mm94
3 files changed, 82 insertions, 39 deletions
diff --git a/src/client/ios/Breakpad.xcodeproj/project.pbxproj b/src/client/ios/Breakpad.xcodeproj/project.pbxproj
index 8ac22381..10888c8f 100644
--- a/src/client/ios/Breakpad.xcodeproj/project.pbxproj
+++ b/src/client/ios/Breakpad.xcodeproj/project.pbxproj
@@ -7,6 +7,8 @@
objects = {
/* 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 */; };
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 */; };
@@ -58,6 +60,8 @@
/* End PBXBuildFile 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>"; };
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>"; };
@@ -238,10 +242,12 @@
16C7CBB0147D4A4300776EAD /* dynamic_images.h */,
16C7CBB1147D4A4300776EAD /* exception_handler.cc */,
16C7CBB2147D4A4300776EAD /* exception_handler.h */,
+ 14569322182CE2C10029C465 /* mach_vm_compat.h */,
16C7CBB4147D4A4300776EAD /* minidump_generator.cc */,
16C7CBB5147D4A4300776EAD /* minidump_generator.h */,
16C7CBBC147D4A4300776EAD /* protected_memory_allocator.cc */,
16C7CBBD147D4A4300776EAD /* protected_memory_allocator.h */,
+ 14569320182CE29F0029C465 /* ucontext_compat.h */,
);
path = handler;
sourceTree = "<group>";
@@ -312,6 +318,7 @@
16C7CCCB147D4A4300776EAD /* BreakpadDefines.h in Headers */,
16C7CCCC147D4A4300776EAD /* Breakpad.h in Headers */,
16C7CDE8147D4A4300776EAD /* ConfigFile.h in Headers */,
+ 14569321182CE29F0029C465 /* ucontext_compat.h in Headers */,
16C7CDF6147D4A4300776EAD /* breakpad_nlist_64.h in Headers */,
16C7CDF8147D4A4300776EAD /* dynamic_images.h in Headers */,
16C7CDFA147D4A4300776EAD /* exception_handler.h in Headers */,
@@ -333,6 +340,7 @@
16BFA67014E195E9009704F8 /* ios_exception_minidump_generator.h in Headers */,
16C92FAD150DF8330053D7BA /* BreakpadController.h in Headers */,
1EEEB6101720821900F7E689 /* simple_string_dictionary.h in Headers */,
+ 14569323182CE2C10029C465 /* mach_vm_compat.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -431,7 +439,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
COPY_PHASE_STRIP = NO;
DSTROOT = /tmp/Breakpad.dst;
FRAMEWORK_SEARCH_PATHS = (
@@ -463,7 +471,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
DSTROOT = /tmp/Breakpad.dst;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -491,7 +499,7 @@
1DEB922308733DC00010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -517,7 +525,7 @@
1DEB922408733DC00010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
diff --git a/src/client/ios/handler/ios_exception_minidump_generator.h b/src/client/ios/handler/ios_exception_minidump_generator.h
index fd2f0149..21133e63 100644
--- a/src/client/ios/handler/ios_exception_minidump_generator.h
+++ b/src/client/ios/handler/ios_exception_minidump_generator.h
@@ -51,13 +51,20 @@ class IosExceptionMinidumpGenerator : public MinidumpGenerator {
private:
// Get the crashing program counter from the exception.
- uint32_t GetPCFromException();
+ uintptr_t GetPCFromException();
// Get the crashing link register from the exception.
- uint32_t GetLRFromException();
+ uintptr_t GetLRFromException();
// Write a virtual thread context for the crashing site.
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_;
};
diff --git a/src/client/ios/handler/ios_exception_minidump_generator.mm b/src/client/ios/handler/ios_exception_minidump_generator.mm
index 50bc3093..491c4916 100644
--- a/src/client/ios/handler/ios_exception_minidump_generator.mm
+++ b/src/client/ios/handler/ios_exception_minidump_generator.mm
@@ -31,25 +31,32 @@
#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 "client/minidump_file_writer-inl.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 {
-const uint32_t kExpectedFinalFp = 4;
-const uint32_t kExpectedFinalSp = 0;
+const uintptr_t kExpectedFinalFp = sizeof(uintptr_t);
+const uintptr_t kExpectedFinalSp = 0;
const int kExceptionType = EXC_SOFTWARE;
const int kExceptionCode = MD_EXCEPTION_CODE_MAC_NS_EXCEPTION;
-#ifdef HAS_ARM_SUPPORT
-// Append the given 4 bytes value to the sp position of the stack represented
+// Append the given value to the sp position of the stack represented
// by memory.
-void AppendToMemory(uint8_t *memory, uint32_t sp, uint32_t data) {
- assert(sizeof(data) == 4);
+void AppendToMemory(uint8_t *memory, uintptr_t sp, uintptr_t data) {
memcpy(memory + sp, &data, sizeof(data));
}
-#endif
} // namespace
@@ -72,6 +79,18 @@ IosExceptionMinidumpGenerator::~IosExceptionMinidumpGenerator() {
bool IosExceptionMinidumpGenerator::WriteCrashingContext(
MDLocationDescriptor *register_location) {
#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_);
if (!context.Allocate())
return false;
@@ -79,28 +98,42 @@ bool IosExceptionMinidumpGenerator::WriteCrashingContext(
MDRawContextARM *context_ptr = context.get();
memset(context_ptr, 0, sizeof(MDRawContextARM));
context_ptr->context_flags = MD_CONTEXT_ARM_FULL;
- context_ptr->iregs[7] = kExpectedFinalFp; // FP
- context_ptr->iregs[13] = kExpectedFinalSp; // SP
- context_ptr->iregs[14] = GetLRFromException(); // LR
- context_ptr->iregs[15] = GetPCFromException(); // PC
+ context_ptr->iregs[MD_CONTEXT_ARM_REG_IOS_FP] = kExpectedFinalFp; // FP
+ context_ptr->iregs[MD_CONTEXT_ARM_REG_SP] = kExpectedFinalSp; // SP
+ context_ptr->iregs[MD_CONTEXT_ARM_REG_LR] = GetLRFromException(); // LR
+ context_ptr->iregs[MD_CONTEXT_ARM_REG_PC] = GetPCFromException(); // PC
return true;
-#else
- assert(false);
- return false;
+}
#endif
+
+#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
-uint32_t IosExceptionMinidumpGenerator::GetPCFromException() {
+uintptr_t IosExceptionMinidumpGenerator::GetPCFromException() {
return [[return_addresses_ objectAtIndex:0] unsignedIntegerValue];
}
-uint32_t IosExceptionMinidumpGenerator::GetLRFromException() {
+uintptr_t IosExceptionMinidumpGenerator::GetLRFromException() {
return [[return_addresses_ objectAtIndex:1] unsignedIntegerValue];
}
bool IosExceptionMinidumpGenerator::WriteExceptionStream(
MDRawDirectory *exception_stream) {
-#ifdef HAS_ARM_SUPPORT
TypedMDRVA<MDRawExceptionStream> exception(&writer_);
if (!exception.Allocate())
@@ -121,37 +154,35 @@ bool IosExceptionMinidumpGenerator::WriteExceptionStream(
exception_ptr->exception_record.exception_address = GetPCFromException();
return true;
-#else
- return MinidumpGenerator::WriteExceptionStream(exception_stream);
-#endif
}
bool IosExceptionMinidumpGenerator::WriteThreadStream(mach_port_t thread_id,
MDRawThread *thread) {
-#ifdef HAS_ARM_SUPPORT
if (pthread_mach_thread_np(pthread_self()) != thread_id)
return MinidumpGenerator::WriteThreadStream(thread_id, thread);
size_t frame_count = [return_addresses_ count];
UntypedMDRVA memory(&writer_);
- size_t size = 8 * (frame_count - 1) + 4;
- if (!memory.Allocate(size))
+ size_t pointer_size = sizeof(uintptr_t);
+ 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;
- scoped_array<uint8_t> stack_memory(new uint8_t[size]);
- uint32_t sp = size - 4;
- uint32_t fp = 0;
- uint32_t lr = 0;
+ scoped_array<uint8_t> stack_memory(new uint8_t[stack_size]);
+ uintptr_t sp = stack_size - pointer_size;
+ uintptr_t fp = 0;
+ uintptr_t lr = 0;
for (int current_frame = frame_count - 1;
current_frame > 0;
--current_frame) {
AppendToMemory(stack_memory.get(), sp, lr);
- sp -= 4;
+ sp -= pointer_size;
AppendToMemory(stack_memory.get(), sp, fp);
fp = sp;
- sp -= 4;
+ sp -= pointer_size;
lr = [[return_addresses_ objectAtIndex:current_frame] unsignedIntegerValue];
}
- if (!memory.Copy(stack_memory.get(), size))
+ if (!memory.Copy(stack_memory.get(), stack_size))
return false;
assert(sp == kExpectedFinalSp);
assert(fp == kExpectedFinalFp);
@@ -165,9 +196,6 @@ bool IosExceptionMinidumpGenerator::WriteThreadStream(mach_port_t thread_id,
thread->thread_id = thread_id;
return true;
-#else
- return MinidumpGenerator::WriteThreadStream(thread_id, thread);
-#endif
}
} // namespace google_breakpad