mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2024-11-24 05:55:39 +01: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,
|
||||
int exception_code,
|
||||
int exception_subcode,
|
||||
ucontext_t *task_context,
|
||||
mach_port_t thread_name,
|
||||
bool exit_after_write,
|
||||
bool report_current_thread) {
|
||||
@ -366,6 +367,7 @@ bool ExceptionHandler::WriteMinidumpWithException(int exception_type,
|
||||
MinidumpGenerator md(mach_task_self(),
|
||||
report_current_thread ? MACH_PORT_NULL :
|
||||
mach_thread_self());
|
||||
md.SetTaskContext(task_context);
|
||||
if (exception_type && exception_code) {
|
||||
// If this is a real exception, give the filter (if any) a chance to
|
||||
// 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
|
||||
self->last_minidump_write_result_ =
|
||||
self->WriteMinidumpWithException(exception_type, exception_code,
|
||||
0, thread,
|
||||
0, NULL, thread,
|
||||
false, false);
|
||||
|
||||
#if USE_PROTECTED_ALLOCATIONS
|
||||
@ -544,8 +546,8 @@ void *ExceptionHandler::WaitForMessage(void *exception_handler_class) {
|
||||
|
||||
// Generate the minidump with the exception data.
|
||||
self->WriteMinidumpWithException(receive.exception, receive.code[0],
|
||||
subcode, receive.thread.name, true,
|
||||
false);
|
||||
subcode, NULL, receive.thread.name,
|
||||
true, false);
|
||||
|
||||
#if USE_PROTECTED_ALLOCATIONS
|
||||
// This may have become protected again within
|
||||
@ -590,6 +592,7 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
|
||||
EXC_SOFTWARE,
|
||||
MD_EXCEPTION_CODE_MAC_ABORT,
|
||||
0,
|
||||
static_cast<ucontext_t*>(uc),
|
||||
mach_thread_self(),
|
||||
true,
|
||||
true);
|
||||
|
@ -182,10 +182,13 @@ class ExceptionHandler {
|
||||
// success, false otherwise.
|
||||
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,
|
||||
int exception_code,
|
||||
int exception_subcode,
|
||||
ucontext_t *task_context,
|
||||
mach_port_t thread_name,
|
||||
bool exit_after_write,
|
||||
bool report_current_thread);
|
||||
|
@ -77,6 +77,7 @@ MinidumpGenerator::MinidumpGenerator()
|
||||
crashing_task_(mach_task_self()),
|
||||
handler_thread_(mach_thread_self()),
|
||||
cpu_type_(DynamicImages::GetNativeCPUType()),
|
||||
task_context_(NULL),
|
||||
dynamic_images_(NULL),
|
||||
memory_blocks_(&allocator_) {
|
||||
GatherSystemInformation();
|
||||
@ -94,6 +95,7 @@ MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task,
|
||||
crashing_task_(crashing_task),
|
||||
handler_thread_(handler_thread),
|
||||
cpu_type_(DynamicImages::GetNativeCPUType()),
|
||||
task_context_(NULL),
|
||||
dynamic_images_(NULL),
|
||||
memory_blocks_(&allocator_) {
|
||||
if (crashing_task != mach_task_self()) {
|
||||
@ -168,6 +170,10 @@ void MinidumpGenerator::GatherSystemInformation() {
|
||||
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 *unique_name) {
|
||||
CFUUIDRef uuid = CFUUIDCreate(NULL);
|
||||
@ -770,6 +776,19 @@ bool MinidumpGenerator::WriteContextX86_64(
|
||||
bool MinidumpGenerator::GetThreadState(thread_act_t target_thread,
|
||||
thread_state_t state,
|
||||
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;
|
||||
switch (cpu_type_) {
|
||||
#ifdef HAS_ARM_SUPPORT
|
||||
@ -878,10 +897,7 @@ bool MinidumpGenerator::WriteMemoryListStream(
|
||||
mach_msg_type_number_t stateCount
|
||||
= static_cast<mach_msg_type_number_t>(sizeof(state));
|
||||
|
||||
if (thread_get_state(exception_thread_,
|
||||
BREAKPAD_MACHINE_THREAD_STATE,
|
||||
state,
|
||||
&stateCount) == KERN_SUCCESS) {
|
||||
if (GetThreadState(exception_thread_, state, &stateCount)) {
|
||||
u_int64_t ip = CurrentPCForStack(state);
|
||||
// Bound it to the upper and lower bounds of the region
|
||||
// it's contained within. If it's not in a known memory region,
|
||||
|
@ -102,6 +102,11 @@ class MinidumpGenerator {
|
||||
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
|
||||
// the MinidumpGenerator class.
|
||||
static void GatherSystemInformation();
|
||||
@ -198,7 +203,10 @@ class MinidumpGenerator {
|
||||
static int os_major_version_;
|
||||
static int os_minor_version_;
|
||||
static int os_build_number_;
|
||||
|
||||
|
||||
// Context of the task to dump.
|
||||
ucontext_t *task_context_;
|
||||
|
||||
// Information about dynamically loaded code
|
||||
DynamicImages *dynamic_images_;
|
||||
|
||||
|
@ -54,14 +54,6 @@
|
||||
# define LC_UUID 0x1b /* the uuid */
|
||||
#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.
|
||||
// Their presence isn't guaranteed.
|
||||
struct breakpad_uuid_command {
|
||||
|
Loading…
Reference in New Issue
Block a user