minidump-2-core: Use exception context for crashed thread
Use the exception record's context for the crashed thread instead of the thread's own context. For the crashed thread the thread's own context is the state inside the exception handler. Using it would not result in the expected stack trace from the time of the crash. This change aligns the behavior of minidump-2-core with the behavior of minidump_stackwalk. Bug: google-breakpad:885 Change-Id: I5cd3e9d39807308491b64fcd335f5f85b1dcd084 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/4473128 Reviewed-by: Joshua Peraza <jperaza@google.com> Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
68f5a4d11a
commit
de040fa25d
1 changed files with 31 additions and 11 deletions
|
@ -282,7 +282,7 @@ typedef struct prpsinfo { /* Information about process */
|
||||||
// We parse the minidump file and keep the parsed information in this structure
|
// We parse the minidump file and keep the parsed information in this structure
|
||||||
struct CrashedProcess {
|
struct CrashedProcess {
|
||||||
CrashedProcess()
|
CrashedProcess()
|
||||||
: crashing_tid(-1),
|
: exception{-1},
|
||||||
auxv(NULL),
|
auxv(NULL),
|
||||||
auxv_length(0) {
|
auxv_length(0) {
|
||||||
memset(&prps, 0, sizeof(prps));
|
memset(&prps, 0, sizeof(prps));
|
||||||
|
@ -306,7 +306,6 @@ struct CrashedProcess {
|
||||||
};
|
};
|
||||||
std::map<uint64_t, Mapping> mappings;
|
std::map<uint64_t, Mapping> mappings;
|
||||||
|
|
||||||
pid_t crashing_tid;
|
|
||||||
int fatal_signal;
|
int fatal_signal;
|
||||||
|
|
||||||
struct Thread {
|
struct Thread {
|
||||||
|
@ -330,6 +329,7 @@ struct CrashedProcess {
|
||||||
size_t stack_length;
|
size_t stack_length;
|
||||||
};
|
};
|
||||||
std::vector<Thread> threads;
|
std::vector<Thread> threads;
|
||||||
|
Thread exception;
|
||||||
|
|
||||||
const uint8_t* auxv;
|
const uint8_t* auxv;
|
||||||
size_t auxv_length;
|
size_t auxv_length;
|
||||||
|
@ -999,10 +999,25 @@ ParseDSODebugInfo(const Options& options, CrashedProcess* crashinfo,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ParseExceptionStream(const Options& options, CrashedProcess* crashinfo,
|
ParseExceptionStream(const Options& options, CrashedProcess* crashinfo,
|
||||||
const MinidumpMemoryRange& range) {
|
const MinidumpMemoryRange& range,
|
||||||
|
const MinidumpMemoryRange& full_file) {
|
||||||
const MDRawExceptionStream* exp = range.GetData<MDRawExceptionStream>(0);
|
const MDRawExceptionStream* exp = range.GetData<MDRawExceptionStream>(0);
|
||||||
crashinfo->crashing_tid = exp->thread_id;
|
if (!exp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (options.verbose) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"MD_EXCEPTION_STREAM:\n"
|
||||||
|
"Found exception thread %" PRIu32 " \n"
|
||||||
|
"\n\n",
|
||||||
|
exp->thread_id);
|
||||||
|
}
|
||||||
crashinfo->fatal_signal = (int) exp->exception_record.exception_code;
|
crashinfo->fatal_signal = (int) exp->exception_record.exception_code;
|
||||||
|
crashinfo->exception = {};
|
||||||
|
crashinfo->exception.tid = exp->thread_id;
|
||||||
|
// crashinfo->threads[].tid == crashinfo->exception.tid provides the stack.
|
||||||
|
ParseThreadRegisters(&crashinfo->exception,
|
||||||
|
full_file.Subrange(exp->thread_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -1365,7 +1380,7 @@ main(int argc, const char* argv[]) {
|
||||||
break;
|
break;
|
||||||
case MD_EXCEPTION_STREAM:
|
case MD_EXCEPTION_STREAM:
|
||||||
ParseExceptionStream(options, &crashinfo,
|
ParseExceptionStream(options, &crashinfo,
|
||||||
dump.Subrange(dirent->location));
|
dump.Subrange(dirent->location), dump);
|
||||||
break;
|
break;
|
||||||
case MD_MODULE_LIST_STREAM:
|
case MD_MODULE_LIST_STREAM:
|
||||||
ParseModuleStream(options, &crashinfo, dump.Subrange(dirent->location),
|
ParseModuleStream(options, &crashinfo, dump.Subrange(dirent->location),
|
||||||
|
@ -1481,16 +1496,21 @@ main(int argc, const char* argv[]) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < crashinfo.threads.size(); ++i) {
|
for (const auto& current_thread : crashinfo.threads) {
|
||||||
if (crashinfo.threads[i].tid == crashinfo.crashing_tid) {
|
if (current_thread.tid == crashinfo.exception.tid) {
|
||||||
WriteThread(options, crashinfo.threads[i], crashinfo.fatal_signal);
|
// Use the exception record's context for the crashed thread instead of
|
||||||
|
// the thread's own context. For the crashed thread the thread's own
|
||||||
|
// context is the state inside the exception handler. Using it would not
|
||||||
|
// result in the expected stack trace from the time of the crash.
|
||||||
|
// The stack memory has already been provided by current_thread.
|
||||||
|
WriteThread(options, crashinfo.exception, crashinfo.fatal_signal);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < crashinfo.threads.size(); ++i) {
|
for (const auto& current_thread : crashinfo.threads) {
|
||||||
if (crashinfo.threads[i].tid != crashinfo.crashing_tid)
|
if (current_thread.tid != crashinfo.exception.tid)
|
||||||
WriteThread(options, crashinfo.threads[i], 0);
|
WriteThread(options, current_thread, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (note_align) {
|
if (note_align) {
|
||||||
|
|
Loading…
Reference in a new issue