aboutsummaryrefslogtreecommitdiff
path: root/src/client/ios/handler
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/handler
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/handler')
-rw-r--r--src/client/ios/handler/ios_exception_minidump_generator.h11
-rw-r--r--src/client/ios/handler/ios_exception_minidump_generator.mm94
2 files changed, 70 insertions, 35 deletions
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