mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-07-23 04:58:26 +00:00
Getting context information from the kernel when catching a SIGABRT on iOS.
Until now, the context information was the current one when receiving a SIGABRT. This is mainly wrong because the signal handler start in a new context. This instead use the context passed to the signal handler. Review URL: https://breakpad.appspot.com/435002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1015 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
e050c46a53
commit
5f57e963d0
|
@ -329,6 +329,7 @@ bool ExceptionHandler::WriteMinidumpForChild(mach_port_t child,
|
||||||
bool ExceptionHandler::WriteMinidumpWithException(int exception_type,
|
bool ExceptionHandler::WriteMinidumpWithException(int exception_type,
|
||||||
int exception_code,
|
int exception_code,
|
||||||
int exception_subcode,
|
int exception_subcode,
|
||||||
|
ucontext_t *task_context,
|
||||||
mach_port_t thread_name,
|
mach_port_t thread_name,
|
||||||
bool exit_after_write,
|
bool exit_after_write,
|
||||||
bool report_current_thread) {
|
bool report_current_thread) {
|
||||||
|
@ -366,6 +367,7 @@ bool ExceptionHandler::WriteMinidumpWithException(int exception_type,
|
||||||
MinidumpGenerator md(mach_task_self(),
|
MinidumpGenerator md(mach_task_self(),
|
||||||
report_current_thread ? MACH_PORT_NULL :
|
report_current_thread ? MACH_PORT_NULL :
|
||||||
mach_thread_self());
|
mach_thread_self());
|
||||||
|
md.SetTaskContext(task_context);
|
||||||
if (exception_type && exception_code) {
|
if (exception_type && exception_code) {
|
||||||
// If this is a real exception, give the filter (if any) a chance to
|
// If this is a real exception, give the filter (if any) a chance to
|
||||||
// decide if this should be sent.
|
// decide if this should be sent.
|
||||||
|
@ -509,7 +511,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(exception_type, exception_code,
|
self->WriteMinidumpWithException(exception_type, exception_code,
|
||||||
0, thread,
|
0, NULL, thread,
|
||||||
false, false);
|
false, false);
|
||||||
|
|
||||||
#if USE_PROTECTED_ALLOCATIONS
|
#if USE_PROTECTED_ALLOCATIONS
|
||||||
|
@ -544,8 +546,8 @@ void *ExceptionHandler::WaitForMessage(void *exception_handler_class) {
|
||||||
|
|
||||||
// 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],
|
||||||
subcode, receive.thread.name, true,
|
subcode, NULL, receive.thread.name,
|
||||||
false);
|
true, false);
|
||||||
|
|
||||||
#if USE_PROTECTED_ALLOCATIONS
|
#if USE_PROTECTED_ALLOCATIONS
|
||||||
// This may have become protected again within
|
// This may have become protected again within
|
||||||
|
@ -590,6 +592,7 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
|
||||||
EXC_SOFTWARE,
|
EXC_SOFTWARE,
|
||||||
MD_EXCEPTION_CODE_MAC_ABORT,
|
MD_EXCEPTION_CODE_MAC_ABORT,
|
||||||
0,
|
0,
|
||||||
|
static_cast<ucontext_t*>(uc),
|
||||||
mach_thread_self(),
|
mach_thread_self(),
|
||||||
true,
|
true,
|
||||||
true);
|
true);
|
||||||
|
|
|
@ -182,10 +182,13 @@ class ExceptionHandler {
|
||||||
// success, false otherwise.
|
// success, false otherwise.
|
||||||
bool SendMessageToHandlerThread(HandlerThreadMessage message_id);
|
bool SendMessageToHandlerThread(HandlerThreadMessage message_id);
|
||||||
|
|
||||||
// All minidump writing goes through this one routine
|
// All minidump writing goes through this one routine.
|
||||||
|
// |task_context| can be NULL. If not, it will be used to retrieve the
|
||||||
|
// context of the current thread, instead of using |thread_get_state|.
|
||||||
bool WriteMinidumpWithException(int exception_type,
|
bool WriteMinidumpWithException(int exception_type,
|
||||||
int exception_code,
|
int exception_code,
|
||||||
int exception_subcode,
|
int exception_subcode,
|
||||||
|
ucontext_t *task_context,
|
||||||
mach_port_t thread_name,
|
mach_port_t thread_name,
|
||||||
bool exit_after_write,
|
bool exit_after_write,
|
||||||
bool report_current_thread);
|
bool report_current_thread);
|
||||||
|
|
|
@ -77,6 +77,7 @@ MinidumpGenerator::MinidumpGenerator()
|
||||||
crashing_task_(mach_task_self()),
|
crashing_task_(mach_task_self()),
|
||||||
handler_thread_(mach_thread_self()),
|
handler_thread_(mach_thread_self()),
|
||||||
cpu_type_(DynamicImages::GetNativeCPUType()),
|
cpu_type_(DynamicImages::GetNativeCPUType()),
|
||||||
|
task_context_(NULL),
|
||||||
dynamic_images_(NULL),
|
dynamic_images_(NULL),
|
||||||
memory_blocks_(&allocator_) {
|
memory_blocks_(&allocator_) {
|
||||||
GatherSystemInformation();
|
GatherSystemInformation();
|
||||||
|
@ -94,6 +95,7 @@ MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task,
|
||||||
crashing_task_(crashing_task),
|
crashing_task_(crashing_task),
|
||||||
handler_thread_(handler_thread),
|
handler_thread_(handler_thread),
|
||||||
cpu_type_(DynamicImages::GetNativeCPUType()),
|
cpu_type_(DynamicImages::GetNativeCPUType()),
|
||||||
|
task_context_(NULL),
|
||||||
dynamic_images_(NULL),
|
dynamic_images_(NULL),
|
||||||
memory_blocks_(&allocator_) {
|
memory_blocks_(&allocator_) {
|
||||||
if (crashing_task != mach_task_self()) {
|
if (crashing_task != mach_task_self()) {
|
||||||
|
@ -168,6 +170,10 @@ void MinidumpGenerator::GatherSystemInformation() {
|
||||||
os_build_number_ = IntegerValueAtIndex(product_str, 2);
|
os_build_number_ = IntegerValueAtIndex(product_str, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MinidumpGenerator::SetTaskContext(ucontext_t *task_context) {
|
||||||
|
task_context_ = task_context;
|
||||||
|
}
|
||||||
|
|
||||||
string MinidumpGenerator::UniqueNameInDirectory(const string &dir,
|
string MinidumpGenerator::UniqueNameInDirectory(const string &dir,
|
||||||
string *unique_name) {
|
string *unique_name) {
|
||||||
CFUUIDRef uuid = CFUUIDCreate(NULL);
|
CFUUIDRef uuid = CFUUIDCreate(NULL);
|
||||||
|
@ -770,6 +776,19 @@ bool MinidumpGenerator::WriteContextX86_64(
|
||||||
bool MinidumpGenerator::GetThreadState(thread_act_t target_thread,
|
bool MinidumpGenerator::GetThreadState(thread_act_t target_thread,
|
||||||
thread_state_t state,
|
thread_state_t state,
|
||||||
mach_msg_type_number_t *count) {
|
mach_msg_type_number_t *count) {
|
||||||
|
if (task_context_ && target_thread == mach_thread_self()) {
|
||||||
|
switch (cpu_type_) {
|
||||||
|
#ifdef HAS_ARM_SUPPORT
|
||||||
|
case CPU_TYPE_ARM: {
|
||||||
|
size_t final_size =
|
||||||
|
std::min(static_cast<size_t>(*count), sizeof(arm_thread_state_t));
|
||||||
|
memcpy(state, &task_context_->uc_mcontext->__ss, final_size);
|
||||||
|
*count = final_size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
thread_state_flavor_t flavor;
|
thread_state_flavor_t flavor;
|
||||||
switch (cpu_type_) {
|
switch (cpu_type_) {
|
||||||
#ifdef HAS_ARM_SUPPORT
|
#ifdef HAS_ARM_SUPPORT
|
||||||
|
@ -878,10 +897,7 @@ bool MinidumpGenerator::WriteMemoryListStream(
|
||||||
mach_msg_type_number_t stateCount
|
mach_msg_type_number_t stateCount
|
||||||
= static_cast<mach_msg_type_number_t>(sizeof(state));
|
= static_cast<mach_msg_type_number_t>(sizeof(state));
|
||||||
|
|
||||||
if (thread_get_state(exception_thread_,
|
if (GetThreadState(exception_thread_, state, &stateCount)) {
|
||||||
BREAKPAD_MACHINE_THREAD_STATE,
|
|
||||||
state,
|
|
||||||
&stateCount) == KERN_SUCCESS) {
|
|
||||||
u_int64_t ip = CurrentPCForStack(state);
|
u_int64_t ip = CurrentPCForStack(state);
|
||||||
// Bound it to the upper and lower bounds of the region
|
// Bound it to the upper and lower bounds of the region
|
||||||
// it's contained within. If it's not in a known memory region,
|
// it's contained within. If it's not in a known memory region,
|
||||||
|
|
|
@ -102,6 +102,11 @@ class MinidumpGenerator {
|
||||||
exception_thread_ = thread_name;
|
exception_thread_ = thread_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Specify the task context. If |task_context| is not NULL, it will be used
|
||||||
|
// to retrieve the context of the current thread, instead of using
|
||||||
|
// |thread_get_state|.
|
||||||
|
void SetTaskContext(ucontext_t *task_context);
|
||||||
|
|
||||||
// Gather system information. This should be call at least once before using
|
// Gather system information. This should be call at least once before using
|
||||||
// the MinidumpGenerator class.
|
// the MinidumpGenerator class.
|
||||||
static void GatherSystemInformation();
|
static void GatherSystemInformation();
|
||||||
|
@ -199,6 +204,9 @@ class MinidumpGenerator {
|
||||||
static int os_minor_version_;
|
static int os_minor_version_;
|
||||||
static int os_build_number_;
|
static int os_build_number_;
|
||||||
|
|
||||||
|
// Context of the task to dump.
|
||||||
|
ucontext_t *task_context_;
|
||||||
|
|
||||||
// Information about dynamically loaded code
|
// Information about dynamically loaded code
|
||||||
DynamicImages *dynamic_images_;
|
DynamicImages *dynamic_images_;
|
||||||
|
|
||||||
|
|
|
@ -54,14 +54,6 @@
|
||||||
# define LC_UUID 0x1b /* the uuid */
|
# define LC_UUID 0x1b /* the uuid */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if TARGET_CPU_X86
|
|
||||||
# define BREAKPAD_MACHINE_THREAD_STATE i386_THREAD_STATE
|
|
||||||
#elif TARGET_CPU_X86_64
|
|
||||||
# define BREAKPAD_MACHINE_THREAD_STATE x86_THREAD_STATE64
|
|
||||||
#else
|
|
||||||
# define BREAKPAD_MACHINE_THREAD_STATE MACHINE_THREAD_STATE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The uuid_command struct/swap routines were added during the 10.4 series.
|
// The uuid_command struct/swap routines were added during the 10.4 series.
|
||||||
// Their presence isn't guaranteed.
|
// Their presence isn't guaranteed.
|
||||||
struct breakpad_uuid_command {
|
struct breakpad_uuid_command {
|
||||||
|
|
Loading…
Reference in a new issue