aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorqsr@chromium.org <qsr@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2012-08-20 13:42:09 +0000
committerqsr@chromium.org <qsr@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2012-08-20 13:42:09 +0000
commit5f57e963d04bf7552d0939725c43c4806a05808f (patch)
tree1902c2b3f19746eadba7aa8d5197362bc7aeee1d
parentFixing a Windows compiler warning in src/client/windows/crash_generation/mini... (diff)
downloadbreakpad-5f57e963d04bf7552d0939725c43c4806a05808f.tar.xz
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
-rw-r--r--src/client/mac/handler/exception_handler.cc9
-rw-r--r--src/client/mac/handler/exception_handler.h5
-rw-r--r--src/client/mac/handler/minidump_generator.cc24
-rw-r--r--src/client/mac/handler/minidump_generator.h10
-rw-r--r--src/common/mac/macho_utilities.h8
5 files changed, 39 insertions, 17 deletions
diff --git a/src/client/mac/handler/exception_handler.cc b/src/client/mac/handler/exception_handler.cc
index 40430194..9b401330 100644
--- a/src/client/mac/handler/exception_handler.cc
+++ b/src/client/mac/handler/exception_handler.cc
@@ -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);
diff --git a/src/client/mac/handler/exception_handler.h b/src/client/mac/handler/exception_handler.h
index ec091341..7babcf66 100644
--- a/src/client/mac/handler/exception_handler.h
+++ b/src/client/mac/handler/exception_handler.h
@@ -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);
diff --git a/src/client/mac/handler/minidump_generator.cc b/src/client/mac/handler/minidump_generator.cc
index b1d429cf..d6326e38 100644
--- a/src/client/mac/handler/minidump_generator.cc
+++ b/src/client/mac/handler/minidump_generator.cc
@@ -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,
diff --git a/src/client/mac/handler/minidump_generator.h b/src/client/mac/handler/minidump_generator.h
index 8394ce6f..ef947841 100644
--- a/src/client/mac/handler/minidump_generator.h
+++ b/src/client/mac/handler/minidump_generator.h
@@ -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_;
diff --git a/src/common/mac/macho_utilities.h b/src/common/mac/macho_utilities.h
index a07945fd..a200c0f7 100644
--- a/src/common/mac/macho_utilities.h
+++ b/src/common/mac/macho_utilities.h
@@ -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 {