Change iOS implementation to not use exc_server
Instead of using exc_server, the message is parsed directly, and the minidump is created, then the app is killed. Moreover, the only catch exception is exception_raise. This patch remove all rereference to exception_raise_state and exception_raise_state_identity. Review URL: https://breakpad.appspot.com/358001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@934 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
b1f858f26b
commit
7facb6a6fb
1 changed files with 90 additions and 87 deletions
|
@ -28,6 +28,8 @@
|
|||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <map>
|
||||
#include <mach/exc.h>
|
||||
#include <mach/mig.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <TargetConditionals.h>
|
||||
|
@ -99,6 +101,7 @@ struct ExceptionReplyMessage {
|
|||
exception_mask_t s_exception_mask = EXC_MASK_BAD_ACCESS |
|
||||
EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | EXC_MASK_BREAKPOINT;
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
extern "C"
|
||||
{
|
||||
// Forward declarations for functions that need "C" style compilation
|
||||
|
@ -114,53 +117,98 @@ extern "C"
|
|||
exception_data_t code,
|
||||
mach_msg_type_number_t code_count)
|
||||
__attribute__((visibility("default")));
|
||||
|
||||
kern_return_t ForwardException(mach_port_t task,
|
||||
mach_port_t failed_thread,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t code_count);
|
||||
|
||||
kern_return_t exception_raise(mach_port_t target_port,
|
||||
mach_port_t failed_thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t exception_code,
|
||||
mach_msg_type_number_t exception_code_count);
|
||||
|
||||
kern_return_t
|
||||
exception_raise_state(mach_port_t target_port,
|
||||
mach_port_t failed_thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t exception_code,
|
||||
mach_msg_type_number_t code_count,
|
||||
thread_state_flavor_t *target_flavor,
|
||||
thread_state_t in_thread_state,
|
||||
mach_msg_type_number_t in_thread_state_count,
|
||||
thread_state_t out_thread_state,
|
||||
mach_msg_type_number_t *out_thread_state_count);
|
||||
|
||||
kern_return_t
|
||||
exception_raise_state_identity(mach_port_t target_port,
|
||||
mach_port_t failed_thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t exception_code,
|
||||
mach_msg_type_number_t exception_code_count,
|
||||
thread_state_flavor_t *target_flavor,
|
||||
thread_state_t in_thread_state,
|
||||
mach_msg_type_number_t in_thread_state_count,
|
||||
thread_state_t out_thread_state,
|
||||
mach_msg_type_number_t *out_thread_state_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
kern_return_t ForwardException(mach_port_t task,
|
||||
mach_port_t failed_thread,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t code_count);
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
// Implementation is based on the implementation generated by mig.
|
||||
boolean_t breakpad_exc_server(mach_msg_header_t *InHeadP,
|
||||
mach_msg_header_t *OutHeadP) {
|
||||
OutHeadP->msgh_bits =
|
||||
MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(InHeadP->msgh_bits), 0);
|
||||
OutHeadP->msgh_remote_port = InHeadP->msgh_remote_port;
|
||||
/* Minimal size: routine() will update it if different */
|
||||
OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);
|
||||
OutHeadP->msgh_local_port = MACH_PORT_NULL;
|
||||
OutHeadP->msgh_id = InHeadP->msgh_id + 100;
|
||||
|
||||
if (InHeadP->msgh_id != 2401) {
|
||||
((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;
|
||||
((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Request;
|
||||
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
} Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
Request *In0P = (Request *)InHeadP;
|
||||
Reply *OutP = (Reply *)OutHeadP;
|
||||
|
||||
if (In0P->task.name != mach_task_self()) {
|
||||
return FALSE;
|
||||
}
|
||||
OutP->RetCode = ForwardException(In0P->task.name,
|
||||
In0P->thread.name,
|
||||
In0P->exception,
|
||||
In0P->code,
|
||||
In0P->codeCnt);
|
||||
OutP->NDR = NDR_record;
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
boolean_t breakpad_exc_server(mach_msg_header_t *request,
|
||||
mach_msg_header_t *reply) {
|
||||
return exc_server(request, reply);
|
||||
}
|
||||
|
||||
// Callback from exc_server()
|
||||
kern_return_t catch_exception_raise(mach_port_t port, mach_port_t failed_thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t code_count) {
|
||||
if (task != mach_task_self()) {
|
||||
return KERN_FAILURE;
|
||||
}
|
||||
return ForwardException(task, failed_thread, exception, code, code_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
ExceptionHandler::ExceptionHandler(const string &dump_path,
|
||||
FilterCallback filter,
|
||||
MinidumpCallback callback,
|
||||
void *callback_context,
|
||||
bool install_handler,
|
||||
const char *port_name)
|
||||
const char *port_name)
|
||||
: dump_path_(),
|
||||
filter_(filter),
|
||||
callback_(callback),
|
||||
|
@ -380,10 +428,7 @@ kern_return_t ForwardException(mach_port_t task, mach_port_t failed_thread,
|
|||
|
||||
mach_port_t target_port = current.ports[found];
|
||||
exception_behavior_t target_behavior = current.behaviors[found];
|
||||
thread_state_flavor_t target_flavor = current.flavors[found];
|
||||
|
||||
mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
|
||||
breakpad_thread_state_data_t thread_state;
|
||||
kern_return_t result;
|
||||
switch (target_behavior) {
|
||||
case EXCEPTION_DEFAULT:
|
||||
|
@ -391,38 +436,8 @@ kern_return_t ForwardException(mach_port_t task, mach_port_t failed_thread,
|
|||
code, code_count);
|
||||
break;
|
||||
|
||||
case EXCEPTION_STATE:
|
||||
result = thread_get_state(failed_thread, target_flavor, thread_state,
|
||||
&thread_state_count);
|
||||
if (result == KERN_SUCCESS)
|
||||
result = exception_raise_state(target_port, failed_thread, task,
|
||||
exception, code,
|
||||
code_count, &target_flavor,
|
||||
thread_state, thread_state_count,
|
||||
thread_state, &thread_state_count);
|
||||
if (result == KERN_SUCCESS)
|
||||
result = thread_set_state(failed_thread, target_flavor, thread_state,
|
||||
thread_state_count);
|
||||
break;
|
||||
|
||||
case EXCEPTION_STATE_IDENTITY:
|
||||
result = thread_get_state(failed_thread, target_flavor, thread_state,
|
||||
&thread_state_count);
|
||||
if (result == KERN_SUCCESS)
|
||||
result = exception_raise_state_identity(target_port, failed_thread,
|
||||
task, exception, code,
|
||||
code_count, &target_flavor,
|
||||
thread_state,
|
||||
thread_state_count,
|
||||
thread_state,
|
||||
&thread_state_count);
|
||||
if (result == KERN_SUCCESS)
|
||||
result = thread_set_state(failed_thread, target_flavor, thread_state,
|
||||
thread_state_count);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "** Unknown exception behavior\n");
|
||||
fprintf(stderr, "** Unknown exception behavior: %d\n", target_behavior);
|
||||
result = KERN_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
@ -430,18 +445,6 @@ kern_return_t ForwardException(mach_port_t task, mach_port_t failed_thread,
|
|||
return result;
|
||||
}
|
||||
|
||||
// Callback from exc_server()
|
||||
kern_return_t catch_exception_raise(mach_port_t port, mach_port_t failed_thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t code_count) {
|
||||
if (task != mach_task_self()) {
|
||||
return KERN_FAILURE;
|
||||
}
|
||||
return ForwardException(task, failed_thread, exception, code, code_count);
|
||||
}
|
||||
|
||||
// static
|
||||
void *ExceptionHandler::WaitForMessage(void *exception_handler_class) {
|
||||
ExceptionHandler *self =
|
||||
|
@ -561,7 +564,7 @@ void *ExceptionHandler::WaitForMessage(void *exception_handler_class) {
|
|||
// message and call catch_exception_raise() and put the return
|
||||
// code into the reply.
|
||||
ExceptionReplyMessage reply;
|
||||
if (!exc_server(&receive.header, &reply.header))
|
||||
if (!breakpad_exc_server(&receive.header, &reply.header))
|
||||
exit(1);
|
||||
|
||||
// Send a reply and exit
|
||||
|
|
Loading…
Reference in a new issue