From 61e88c7ad7eb072977b4d4d26bcf8929b75af2d4 Mon Sep 17 00:00:00 2001 From: "ted.mielczarek" Date: Fri, 12 Jun 2009 20:36:53 +0000 Subject: [PATCH] issue 323 - OS X exception handler / minidump generator should set exception address correctly for EXC_BAD_ACCESS . r=nealsid at http://breakpad.appspot.com/15002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@350 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/client/mac/Framework/Breakpad.mm | 8 +++++++- src/client/mac/crash_generation/Inspector.h | 2 ++ src/client/mac/crash_generation/Inspector.mm | 3 +++ src/client/mac/handler/exception_handler.cc | 19 +++++++++++++------ src/client/mac/handler/exception_handler.h | 3 ++- .../mac/handler/exception_handler_test.cc | 2 +- src/client/mac/handler/minidump_generator.cc | 7 ++++++- src/client/mac/handler/minidump_generator.h | 5 ++++- 8 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/client/mac/Framework/Breakpad.mm b/src/client/mac/Framework/Breakpad.mm index 929cfaa8..551f9785 100644 --- a/src/client/mac/Framework/Breakpad.mm +++ b/src/client/mac/Framework/Breakpad.mm @@ -177,10 +177,12 @@ class Breakpad { static bool ExceptionHandlerDirectCallback(void *context, int exception_type, int exception_code, + int exception_subcode, mach_port_t crashing_thread); bool HandleException(int exception_type, int exception_code, + int exception_subcode, mach_port_t crashing_thread); // Since ExceptionHandler (w/o namespace) is defined as typedef in OSX's @@ -245,6 +247,7 @@ static BOOL IsDebuggerActive() { bool Breakpad::ExceptionHandlerDirectCallback(void *context, int exception_type, int exception_code, + int exception_subcode, mach_port_t crashing_thread) { Breakpad *breakpad = (Breakpad *)context; @@ -255,6 +258,7 @@ bool Breakpad::ExceptionHandlerDirectCallback(void *context, return breakpad->HandleException( exception_type, exception_code, + exception_subcode, crashing_thread); } @@ -629,12 +633,13 @@ void Breakpad::RemoveKeyValue(NSString *key) { //============================================================================= void Breakpad::GenerateAndSendReport() { - HandleException(0, 0, mach_thread_self()); + HandleException(0, 0, 0, mach_thread_self()); } //============================================================================= bool Breakpad::HandleException(int exception_type, int exception_code, + int exception_subcode, mach_port_t crashing_thread) { DEBUGLOG(stderr, "Breakpad: an exception occurred\n"); @@ -670,6 +675,7 @@ bool Breakpad::HandleException(int exception_type, InspectorInfo info; info.exception_type = exception_type; info.exception_code = exception_code; + info.exception_subcode = exception_subcode; info.parameter_count = config_params_->GetCount(); message.SetData(&info, sizeof(info)); diff --git a/src/client/mac/crash_generation/Inspector.h b/src/client/mac/crash_generation/Inspector.h index 9ee5c48c..dda53703 100644 --- a/src/client/mac/crash_generation/Inspector.h +++ b/src/client/mac/crash_generation/Inspector.h @@ -56,6 +56,7 @@ enum { struct InspectorInfo { int exception_type; int exception_code; + int exception_subcode; unsigned int parameter_count; // key-value pairs }; @@ -177,6 +178,7 @@ class Inspector { int exception_type_; int exception_code_; + int exception_subcode_; mach_port_t remote_task_; mach_port_t crashing_thread_; mach_port_t handler_thread_; diff --git a/src/client/mac/crash_generation/Inspector.mm b/src/client/mac/crash_generation/Inspector.mm index 649d4b15..5c5c2218 100644 --- a/src/client/mac/crash_generation/Inspector.mm +++ b/src/client/mac/crash_generation/Inspector.mm @@ -297,6 +297,7 @@ kern_return_t Inspector::ReadMessages() { InspectorInfo &info = (InspectorInfo &)*message.GetData(); exception_type_ = info.exception_type; exception_code_ = info.exception_code; + exception_subcode_ = info.exception_subcode; #if VERBOSE printf("message ID = %d\n", message.GetMessageID()); @@ -310,6 +311,7 @@ kern_return_t Inspector::ReadMessages() { #if VERBOSE printf("exception_type = %d\n", exception_type_); printf("exception_code = %d\n", exception_code_); + printf("exception_subcode = %d\n", exception_subcode_); printf("remote_task = %d\n", remote_task_); printf("crashing_thread = %d\n", crashing_thread_); printf("handler_thread = %d\n", handler_thread_); @@ -435,6 +437,7 @@ bool Inspector::InspectTask() { if (exception_type_ && exception_code_) { generator.SetExceptionInformation(exception_type_, exception_code_, + exception_subcode_, crashing_thread_); } diff --git a/src/client/mac/handler/exception_handler.cc b/src/client/mac/handler/exception_handler.cc index fd6ea836..8c4a0d50 100644 --- a/src/client/mac/handler/exception_handler.cc +++ b/src/client/mac/handler/exception_handler.cc @@ -296,6 +296,7 @@ bool ExceptionHandler::WriteMinidump(const string &dump_path, bool ExceptionHandler::WriteMinidumpWithException(int exception_type, int exception_code, + int exception_subcode, mach_port_t thread_name) { bool result = false; @@ -303,6 +304,7 @@ bool ExceptionHandler::WriteMinidumpWithException(int exception_type, if (directCallback_(callback_context_, exception_type, exception_code, + exception_subcode, thread_name) ) { if (exception_type && exception_code) _exit(exception_type); @@ -320,7 +322,8 @@ bool ExceptionHandler::WriteMinidumpWithException(int exception_type, if (filter_ && !filter_(callback_context_)) return false; - md.SetExceptionInformation(exception_type, exception_code, thread_name); + md.SetExceptionInformation(exception_type, exception_code, + exception_subcode, thread_name); } result = md.Write(next_minidump_path_c_); @@ -476,7 +479,7 @@ void *ExceptionHandler::WaitForMessage(void *exception_handler_class) { // Write out the dump and save the result for later retrieval self->last_minidump_write_result_ = - self->WriteMinidumpWithException(0, 0, 0); + self->WriteMinidumpWithException(0, 0, 0, 0); self->UninstallHandler(false); @@ -506,11 +509,15 @@ void *ExceptionHandler::WaitForMessage(void *exception_handler_class) { gBreakpadAllocator->Unprotect(); #endif - // Generate the minidump with the exception data. - self->WriteMinidumpWithException(receive.exception, receive.code[0], - receive.thread.name); + int subcode = 0; + if (receive.exception == EXC_BAD_ACCESS && receive.code_count > 1) + subcode = receive.code[1]; - self->UninstallHandler(true); + // Generate the minidump with the exception data. + self->WriteMinidumpWithException(receive.exception, receive.code[0], + subcode, receive.thread.name); + + self->UninstallHandler(true); #if USE_PROTECTED_ALLOCATIONS if(gBreakpadAllocator) diff --git a/src/client/mac/handler/exception_handler.h b/src/client/mac/handler/exception_handler.h index 2a8ee1e4..896eecda 100644 --- a/src/client/mac/handler/exception_handler.h +++ b/src/client/mac/handler/exception_handler.h @@ -77,6 +77,7 @@ class ExceptionHandler { typedef bool (*DirectCallback)( void *context, int exception_type, int exception_code, + int exception_subcode, mach_port_t thread_name); // Creates a new ExceptionHandler instance to handle writing minidumps. @@ -135,7 +136,7 @@ class ExceptionHandler { // All minidump writing goes through this one routine bool WriteMinidumpWithException(int exception_type, int exception_code, - mach_port_t thread_name); + int exception_subcode, mach_port_t thread_name); // When installed, this static function will be call from a newly created // pthread with |this| as the argument diff --git a/src/client/mac/handler/exception_handler_test.cc b/src/client/mac/handler/exception_handler_test.cc index e9d200f9..0a1ecbe7 100644 --- a/src/client/mac/handler/exception_handler_test.cc +++ b/src/client/mac/handler/exception_handler_test.cc @@ -51,7 +51,7 @@ static void *SleepyFunction(void *) { } static void Crasher() { - int *a = NULL; + int *a = (int*)0x42; fprintf(stdout, "Going to crash...\n"); fprintf(stdout, "A = %d", *a); diff --git a/src/client/mac/handler/minidump_generator.cc b/src/client/mac/handler/minidump_generator.cc index 13db2474..9424c565 100644 --- a/src/client/mac/handler/minidump_generator.cc +++ b/src/client/mac/handler/minidump_generator.cc @@ -54,6 +54,7 @@ namespace google_breakpad { MinidumpGenerator::MinidumpGenerator() : exception_type_(0), exception_code_(0), + exception_subcode_(0), exception_thread_(0), crashing_task_(mach_task_self()), handler_thread_(mach_thread_self()), @@ -67,6 +68,7 @@ MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task, mach_port_t handler_thread) : exception_type_(0), exception_code_(0), + exception_subcode_(0), exception_thread_(0), crashing_task_(crashing_task), handler_thread_(handler_thread) { @@ -594,7 +596,10 @@ MinidumpGenerator::WriteExceptionStream(MDRawDirectory *exception_stream) { if (!WriteContext(state, &exception_ptr->thread_context)) return false; - exception_ptr->exception_record.exception_address = CurrentPCForStack(state); + if (exception_type_ == EXC_BAD_ACCESS) + exception_ptr->exception_record.exception_address = exception_subcode_; + else + exception_ptr->exception_record.exception_address = CurrentPCForStack(state); return true; } diff --git a/src/client/mac/handler/minidump_generator.h b/src/client/mac/handler/minidump_generator.h index 6a06ed66..8b4f327e 100644 --- a/src/client/mac/handler/minidump_generator.h +++ b/src/client/mac/handler/minidump_generator.h @@ -102,9 +102,11 @@ class MinidumpGenerator { bool Write(const char *path); // Specify some exception information, if applicable - void SetExceptionInformation(int type, int code, mach_port_t thread_name) { + void SetExceptionInformation(int type, int code, int subcode, + mach_port_t thread_name) { exception_type_ = type; exception_code_ = code; + exception_subcode_ = subcode; exception_thread_ = thread_name; } @@ -150,6 +152,7 @@ class MinidumpGenerator { // Exception information int exception_type_; int exception_code_; + int exception_subcode_; mach_port_t exception_thread_; mach_port_t crashing_task_; mach_port_t handler_thread_;