diff options
author | mark@chromium.org <mark@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2013-11-21 17:44:57 +0000 |
---|---|---|
committer | mark@chromium.org <mark@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2013-11-21 17:44:57 +0000 |
commit | 77022ac0df3e079fb0abea05033b0239d12a4e72 (patch) | |
tree | 6f7207ff153e8306c441fa0cdb18b728ef971fe5 /src/client/ios/handler | |
parent | Provide BreakpadGetCrashReportCount() and -[BreakpadController (diff) | |
download | breakpad-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.h | 11 | ||||
-rw-r--r-- | src/client/ios/handler/ios_exception_minidump_generator.mm | 94 |
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 |