mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-07-07 11:30:46 +00:00
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:
parent
c52715f32f
commit
61e88c7ad7
|
@ -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));
|
||||||
|
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,11 +509,15 @@ void *ExceptionHandler::WaitForMessage(void *exception_handler_class) {
|
||||||
gBreakpadAllocator->Unprotect();
|
gBreakpadAllocator->Unprotect();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Generate the minidump with the exception data.
|
int subcode = 0;
|
||||||
self->WriteMinidumpWithException(receive.exception, receive.code[0],
|
if (receive.exception == EXC_BAD_ACCESS && receive.code_count > 1)
|
||||||
receive.thread.name);
|
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 USE_PROTECTED_ALLOCATIONS
|
||||||
if(gBreakpadAllocator)
|
if(gBreakpadAllocator)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,7 +596,10 @@ MinidumpGenerator::WriteExceptionStream(MDRawDirectory *exception_stream) {
|
||||||
if (!WriteContext(state, &exception_ptr->thread_context))
|
if (!WriteContext(state, &exception_ptr->thread_context))
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
Loading…
Reference in a new issue