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
This commit is contained in:
ted.mielczarek 2009-06-12 20:36:53 +00:00
parent c52715f32f
commit 61e88c7ad7
8 changed files with 38 additions and 11 deletions

View file

@ -177,10 +177,12 @@ class Breakpad {
static bool ExceptionHandlerDirectCallback(void *context, static bool ExceptionHandlerDirectCallback(void *context,
int exception_type, int exception_type,
int exception_code, int exception_code,
int exception_subcode,
mach_port_t crashing_thread); mach_port_t crashing_thread);
bool HandleException(int exception_type, bool HandleException(int exception_type,
int exception_code, int exception_code,
int exception_subcode,
mach_port_t crashing_thread); mach_port_t crashing_thread);
// Since ExceptionHandler (w/o namespace) is defined as typedef in OSX's // Since ExceptionHandler (w/o namespace) is defined as typedef in OSX's
@ -245,6 +247,7 @@ static BOOL IsDebuggerActive() {
bool Breakpad::ExceptionHandlerDirectCallback(void *context, bool Breakpad::ExceptionHandlerDirectCallback(void *context,
int exception_type, int exception_type,
int exception_code, int exception_code,
int exception_subcode,
mach_port_t crashing_thread) { mach_port_t crashing_thread) {
Breakpad *breakpad = (Breakpad *)context; Breakpad *breakpad = (Breakpad *)context;
@ -255,6 +258,7 @@ bool Breakpad::ExceptionHandlerDirectCallback(void *context,
return breakpad->HandleException( exception_type, return breakpad->HandleException( exception_type,
exception_code, exception_code,
exception_subcode,
crashing_thread); crashing_thread);
} }
@ -629,12 +633,13 @@ void Breakpad::RemoveKeyValue(NSString *key) {
//============================================================================= //=============================================================================
void Breakpad::GenerateAndSendReport() { void Breakpad::GenerateAndSendReport() {
HandleException(0, 0, mach_thread_self()); HandleException(0, 0, 0, mach_thread_self());
} }
//============================================================================= //=============================================================================
bool Breakpad::HandleException(int exception_type, bool Breakpad::HandleException(int exception_type,
int exception_code, int exception_code,
int exception_subcode,
mach_port_t crashing_thread) { mach_port_t crashing_thread) {
DEBUGLOG(stderr, "Breakpad: an exception occurred\n"); DEBUGLOG(stderr, "Breakpad: an exception occurred\n");
@ -670,6 +675,7 @@ bool Breakpad::HandleException(int exception_type,
InspectorInfo info; InspectorInfo info;
info.exception_type = exception_type; info.exception_type = exception_type;
info.exception_code = exception_code; info.exception_code = exception_code;
info.exception_subcode = exception_subcode;
info.parameter_count = config_params_->GetCount(); info.parameter_count = config_params_->GetCount();
message.SetData(&info, sizeof(info)); message.SetData(&info, sizeof(info));

View file

@ -56,6 +56,7 @@ enum {
struct InspectorInfo { struct InspectorInfo {
int exception_type; int exception_type;
int exception_code; int exception_code;
int exception_subcode;
unsigned int parameter_count; // key-value pairs unsigned int parameter_count; // key-value pairs
}; };
@ -177,6 +178,7 @@ class Inspector {
int exception_type_; int exception_type_;
int exception_code_; int exception_code_;
int exception_subcode_;
mach_port_t remote_task_; mach_port_t remote_task_;
mach_port_t crashing_thread_; mach_port_t crashing_thread_;
mach_port_t handler_thread_; mach_port_t handler_thread_;

View file

@ -297,6 +297,7 @@ kern_return_t Inspector::ReadMessages() {
InspectorInfo &info = (InspectorInfo &)*message.GetData(); InspectorInfo &info = (InspectorInfo &)*message.GetData();
exception_type_ = info.exception_type; exception_type_ = info.exception_type;
exception_code_ = info.exception_code; exception_code_ = info.exception_code;
exception_subcode_ = info.exception_subcode;
#if VERBOSE #if VERBOSE
printf("message ID = %d\n", message.GetMessageID()); printf("message ID = %d\n", message.GetMessageID());
@ -310,6 +311,7 @@ kern_return_t Inspector::ReadMessages() {
#if VERBOSE #if VERBOSE
printf("exception_type = %d\n", exception_type_); printf("exception_type = %d\n", exception_type_);
printf("exception_code = %d\n", exception_code_); printf("exception_code = %d\n", exception_code_);
printf("exception_subcode = %d\n", exception_subcode_);
printf("remote_task = %d\n", remote_task_); printf("remote_task = %d\n", remote_task_);
printf("crashing_thread = %d\n", crashing_thread_); printf("crashing_thread = %d\n", crashing_thread_);
printf("handler_thread = %d\n", handler_thread_); printf("handler_thread = %d\n", handler_thread_);
@ -435,6 +437,7 @@ bool Inspector::InspectTask() {
if (exception_type_ && exception_code_) { if (exception_type_ && exception_code_) {
generator.SetExceptionInformation(exception_type_, generator.SetExceptionInformation(exception_type_,
exception_code_, exception_code_,
exception_subcode_,
crashing_thread_); crashing_thread_);
} }

View file

@ -296,6 +296,7 @@ bool ExceptionHandler::WriteMinidump(const string &dump_path,
bool ExceptionHandler::WriteMinidumpWithException(int exception_type, bool ExceptionHandler::WriteMinidumpWithException(int exception_type,
int exception_code, int exception_code,
int exception_subcode,
mach_port_t thread_name) { mach_port_t thread_name) {
bool result = false; bool result = false;
@ -303,6 +304,7 @@ bool ExceptionHandler::WriteMinidumpWithException(int exception_type,
if (directCallback_(callback_context_, if (directCallback_(callback_context_,
exception_type, exception_type,
exception_code, exception_code,
exception_subcode,
thread_name) ) { thread_name) ) {
if (exception_type && exception_code) if (exception_type && exception_code)
_exit(exception_type); _exit(exception_type);
@ -320,7 +322,8 @@ bool ExceptionHandler::WriteMinidumpWithException(int exception_type,
if (filter_ && !filter_(callback_context_)) if (filter_ && !filter_(callback_context_))
return false; 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_); 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 // Write out the dump and save the result for later retrieval
self->last_minidump_write_result_ = self->last_minidump_write_result_ =
self->WriteMinidumpWithException(0, 0, 0); self->WriteMinidumpWithException(0, 0, 0, 0);
self->UninstallHandler(false); self->UninstallHandler(false);
@ -506,9 +509,13 @@ void *ExceptionHandler::WaitForMessage(void *exception_handler_class) {
gBreakpadAllocator->Unprotect(); gBreakpadAllocator->Unprotect();
#endif #endif
int subcode = 0;
if (receive.exception == EXC_BAD_ACCESS && receive.code_count > 1)
subcode = receive.code[1];
// Generate the minidump with the exception data. // Generate the minidump with the exception data.
self->WriteMinidumpWithException(receive.exception, receive.code[0], self->WriteMinidumpWithException(receive.exception, receive.code[0],
receive.thread.name); subcode, receive.thread.name);
self->UninstallHandler(true); self->UninstallHandler(true);

View file

@ -77,6 +77,7 @@ class ExceptionHandler {
typedef bool (*DirectCallback)( void *context, typedef bool (*DirectCallback)( void *context,
int exception_type, int exception_type,
int exception_code, int exception_code,
int exception_subcode,
mach_port_t thread_name); mach_port_t thread_name);
// Creates a new ExceptionHandler instance to handle writing minidumps. // Creates a new ExceptionHandler instance to handle writing minidumps.
@ -135,7 +136,7 @@ class ExceptionHandler {
// All minidump writing goes through this one routine // All minidump writing goes through this one routine
bool WriteMinidumpWithException(int exception_type, int exception_code, 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 // When installed, this static function will be call from a newly created
// pthread with |this| as the argument // pthread with |this| as the argument

View file

@ -51,7 +51,7 @@ static void *SleepyFunction(void *) {
} }
static void Crasher() { static void Crasher() {
int *a = NULL; int *a = (int*)0x42;
fprintf(stdout, "Going to crash...\n"); fprintf(stdout, "Going to crash...\n");
fprintf(stdout, "A = %d", *a); fprintf(stdout, "A = %d", *a);

View file

@ -54,6 +54,7 @@ namespace google_breakpad {
MinidumpGenerator::MinidumpGenerator() MinidumpGenerator::MinidumpGenerator()
: exception_type_(0), : exception_type_(0),
exception_code_(0), exception_code_(0),
exception_subcode_(0),
exception_thread_(0), exception_thread_(0),
crashing_task_(mach_task_self()), crashing_task_(mach_task_self()),
handler_thread_(mach_thread_self()), handler_thread_(mach_thread_self()),
@ -67,6 +68,7 @@ MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task,
mach_port_t handler_thread) mach_port_t handler_thread)
: exception_type_(0), : exception_type_(0),
exception_code_(0), exception_code_(0),
exception_subcode_(0),
exception_thread_(0), exception_thread_(0),
crashing_task_(crashing_task), crashing_task_(crashing_task),
handler_thread_(handler_thread) { handler_thread_(handler_thread) {
@ -594,6 +596,9 @@ MinidumpGenerator::WriteExceptionStream(MDRawDirectory *exception_stream) {
if (!WriteContext(state, &exception_ptr->thread_context)) if (!WriteContext(state, &exception_ptr->thread_context))
return false; return false;
if (exception_type_ == EXC_BAD_ACCESS)
exception_ptr->exception_record.exception_address = exception_subcode_;
else
exception_ptr->exception_record.exception_address = CurrentPCForStack(state); exception_ptr->exception_record.exception_address = CurrentPCForStack(state);
return true; return true;

View file

@ -102,9 +102,11 @@ class MinidumpGenerator {
bool Write(const char *path); bool Write(const char *path);
// Specify some exception information, if applicable // 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_type_ = type;
exception_code_ = code; exception_code_ = code;
exception_subcode_ = subcode;
exception_thread_ = thread_name; exception_thread_ = thread_name;
} }
@ -150,6 +152,7 @@ class MinidumpGenerator {
// Exception information // Exception information
int exception_type_; int exception_type_;
int exception_code_; int exception_code_;
int exception_subcode_;
mach_port_t exception_thread_; mach_port_t exception_thread_;
mach_port_t crashing_task_; mach_port_t crashing_task_;
mach_port_t handler_thread_; mach_port_t handler_thread_;