toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 // Copyright (c) 2006, Google Inc.
michael@0 2 // All rights reserved.
michael@0 3 //
michael@0 4 // Redistribution and use in source and binary forms, with or without
michael@0 5 // modification, are permitted provided that the following conditions are
michael@0 6 // met:
michael@0 7 //
michael@0 8 // * Redistributions of source code must retain the above copyright
michael@0 9 // notice, this list of conditions and the following disclaimer.
michael@0 10 // * Redistributions in binary form must reproduce the above
michael@0 11 // copyright notice, this list of conditions and the following disclaimer
michael@0 12 // in the documentation and/or other materials provided with the
michael@0 13 // distribution.
michael@0 14 // * Neither the name of Google Inc. nor the names of its
michael@0 15 // contributors may be used to endorse or promote products derived from
michael@0 16 // this software without specific prior written permission.
michael@0 17 //
michael@0 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
michael@0 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
michael@0 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
michael@0 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
michael@0 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
michael@0 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
michael@0 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
michael@0 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
michael@0 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
michael@0 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 29
michael@0 30 #include "google_breakpad/processor/minidump_processor.h"
michael@0 31
michael@0 32 #include <assert.h>
michael@0 33 #include <stdio.h>
michael@0 34
michael@0 35 #include "common/scoped_ptr.h"
michael@0 36 #include "google_breakpad/processor/call_stack.h"
michael@0 37 #include "google_breakpad/processor/minidump.h"
michael@0 38 #include "google_breakpad/processor/process_state.h"
michael@0 39 #include "google_breakpad/processor/exploitability.h"
michael@0 40 #include "google_breakpad/processor/stack_frame_symbolizer.h"
michael@0 41 #include "processor/logging.h"
michael@0 42 #include "processor/stackwalker_x86.h"
michael@0 43
michael@0 44 namespace google_breakpad {
michael@0 45
michael@0 46 MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier,
michael@0 47 SourceLineResolverInterface *resolver)
michael@0 48 : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)),
michael@0 49 own_frame_symbolizer_(true),
michael@0 50 enable_exploitability_(false) {
michael@0 51 }
michael@0 52
michael@0 53 MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier,
michael@0 54 SourceLineResolverInterface *resolver,
michael@0 55 bool enable_exploitability)
michael@0 56 : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)),
michael@0 57 own_frame_symbolizer_(true),
michael@0 58 enable_exploitability_(enable_exploitability) {
michael@0 59 }
michael@0 60
michael@0 61 MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer *frame_symbolizer,
michael@0 62 bool enable_exploitability)
michael@0 63 : frame_symbolizer_(frame_symbolizer),
michael@0 64 own_frame_symbolizer_(false),
michael@0 65 enable_exploitability_(enable_exploitability) {
michael@0 66 assert(frame_symbolizer_);
michael@0 67 }
michael@0 68
michael@0 69 MinidumpProcessor::~MinidumpProcessor() {
michael@0 70 if (own_frame_symbolizer_) delete frame_symbolizer_;
michael@0 71 }
michael@0 72
michael@0 73 ProcessResult MinidumpProcessor::Process(
michael@0 74 Minidump *dump, ProcessState *process_state) {
michael@0 75 assert(dump);
michael@0 76 assert(process_state);
michael@0 77
michael@0 78 process_state->Clear();
michael@0 79
michael@0 80 const MDRawHeader *header = dump->header();
michael@0 81 if (!header) {
michael@0 82 BPLOG(ERROR) << "Minidump " << dump->path() << " has no header";
michael@0 83 return PROCESS_ERROR_NO_MINIDUMP_HEADER;
michael@0 84 }
michael@0 85 process_state->time_date_stamp_ = header->time_date_stamp;
michael@0 86
michael@0 87 bool has_cpu_info = GetCPUInfo(dump, &process_state->system_info_);
michael@0 88 bool has_os_info = GetOSInfo(dump, &process_state->system_info_);
michael@0 89
michael@0 90 uint32_t dump_thread_id = 0;
michael@0 91 bool has_dump_thread = false;
michael@0 92 uint32_t requesting_thread_id = 0;
michael@0 93 bool has_requesting_thread = false;
michael@0 94
michael@0 95 MinidumpBreakpadInfo *breakpad_info = dump->GetBreakpadInfo();
michael@0 96 if (breakpad_info) {
michael@0 97 has_dump_thread = breakpad_info->GetDumpThreadID(&dump_thread_id);
michael@0 98 has_requesting_thread =
michael@0 99 breakpad_info->GetRequestingThreadID(&requesting_thread_id);
michael@0 100 }
michael@0 101
michael@0 102 MinidumpException *exception = dump->GetException();
michael@0 103 if (exception) {
michael@0 104 process_state->crashed_ = true;
michael@0 105 has_requesting_thread = exception->GetThreadID(&requesting_thread_id);
michael@0 106
michael@0 107 process_state->crash_reason_ = GetCrashReason(
michael@0 108 dump, &process_state->crash_address_);
michael@0 109 }
michael@0 110
michael@0 111 // This will just return an empty string if it doesn't exist.
michael@0 112 process_state->assertion_ = GetAssertion(dump);
michael@0 113
michael@0 114 MinidumpModuleList *module_list = dump->GetModuleList();
michael@0 115
michael@0 116 // Put a copy of the module list into ProcessState object. This is not
michael@0 117 // necessarily a MinidumpModuleList, but it adheres to the CodeModules
michael@0 118 // interface, which is all that ProcessState needs to expose.
michael@0 119 if (module_list)
michael@0 120 process_state->modules_ = module_list->Copy();
michael@0 121
michael@0 122 MinidumpThreadList *threads = dump->GetThreadList();
michael@0 123 if (!threads) {
michael@0 124 BPLOG(ERROR) << "Minidump " << dump->path() << " has no thread list";
michael@0 125 return PROCESS_ERROR_NO_THREAD_LIST;
michael@0 126 }
michael@0 127
michael@0 128 BPLOG(INFO) << "Minidump " << dump->path() << " has " <<
michael@0 129 (has_cpu_info ? "" : "no ") << "CPU info, " <<
michael@0 130 (has_os_info ? "" : "no ") << "OS info, " <<
michael@0 131 (breakpad_info != NULL ? "" : "no ") << "Breakpad info, " <<
michael@0 132 (exception != NULL ? "" : "no ") << "exception, " <<
michael@0 133 (module_list != NULL ? "" : "no ") << "module list, " <<
michael@0 134 (threads != NULL ? "" : "no ") << "thread list, " <<
michael@0 135 (has_dump_thread ? "" : "no ") << "dump thread, and " <<
michael@0 136 (has_requesting_thread ? "" : "no ") << "requesting thread";
michael@0 137
michael@0 138 bool interrupted = false;
michael@0 139 bool found_requesting_thread = false;
michael@0 140 unsigned int thread_count = threads->thread_count();
michael@0 141
michael@0 142 // Reset frame_symbolizer_ at the beginning of stackwalk for each minidump.
michael@0 143 frame_symbolizer_->Reset();
michael@0 144
michael@0 145 for (unsigned int thread_index = 0;
michael@0 146 thread_index < thread_count;
michael@0 147 ++thread_index) {
michael@0 148 char thread_string_buffer[64];
michael@0 149 snprintf(thread_string_buffer, sizeof(thread_string_buffer), "%d/%d",
michael@0 150 thread_index, thread_count);
michael@0 151 string thread_string = dump->path() + ":" + thread_string_buffer;
michael@0 152
michael@0 153 MinidumpThread *thread = threads->GetThreadAtIndex(thread_index);
michael@0 154 if (!thread) {
michael@0 155 BPLOG(ERROR) << "Could not get thread for " << thread_string;
michael@0 156 return PROCESS_ERROR_GETTING_THREAD;
michael@0 157 }
michael@0 158
michael@0 159 uint32_t thread_id;
michael@0 160 if (!thread->GetThreadID(&thread_id)) {
michael@0 161 BPLOG(ERROR) << "Could not get thread ID for " << thread_string;
michael@0 162 return PROCESS_ERROR_GETTING_THREAD_ID;
michael@0 163 }
michael@0 164
michael@0 165 thread_string += " id " + HexString(thread_id);
michael@0 166 BPLOG(INFO) << "Looking at thread " << thread_string;
michael@0 167
michael@0 168 // If this thread is the thread that produced the minidump, don't process
michael@0 169 // it. Because of the problems associated with a thread producing a
michael@0 170 // dump of itself (when both its context and its stack are in flux),
michael@0 171 // processing that stack wouldn't provide much useful data.
michael@0 172 if (has_dump_thread && thread_id == dump_thread_id) {
michael@0 173 continue;
michael@0 174 }
michael@0 175
michael@0 176 MinidumpContext *context = thread->GetContext();
michael@0 177
michael@0 178 if (has_requesting_thread && thread_id == requesting_thread_id) {
michael@0 179 if (found_requesting_thread) {
michael@0 180 // There can't be more than one requesting thread.
michael@0 181 BPLOG(ERROR) << "Duplicate requesting thread: " << thread_string;
michael@0 182 return PROCESS_ERROR_DUPLICATE_REQUESTING_THREADS;
michael@0 183 }
michael@0 184
michael@0 185 // Use processed_state->threads_.size() instead of thread_index.
michael@0 186 // thread_index points to the thread index in the minidump, which
michael@0 187 // might be greater than the thread index in the threads vector if
michael@0 188 // any of the minidump's threads are skipped and not placed into the
michael@0 189 // processed threads vector. The thread vector's current size will
michael@0 190 // be the index of the current thread when it's pushed into the
michael@0 191 // vector.
michael@0 192 process_state->requesting_thread_ = process_state->threads_.size();
michael@0 193
michael@0 194 found_requesting_thread = true;
michael@0 195
michael@0 196 if (process_state->crashed_) {
michael@0 197 // Use the exception record's context for the crashed thread, instead
michael@0 198 // of the thread's own context. For the crashed thread, the thread's
michael@0 199 // own context is the state inside the exception handler. Using it
michael@0 200 // would not result in the expected stack trace from the time of the
michael@0 201 // crash. If the exception context is invalid, however, we fall back
michael@0 202 // on the thread context.
michael@0 203 MinidumpContext *ctx = exception->GetContext();
michael@0 204 context = ctx ? ctx : thread->GetContext();
michael@0 205 }
michael@0 206 }
michael@0 207
michael@0 208 MinidumpMemoryRegion *thread_memory = thread->GetMemory();
michael@0 209 if (!thread_memory) {
michael@0 210 BPLOG(ERROR) << "No memory region for " << thread_string;
michael@0 211 }
michael@0 212
michael@0 213 // Use process_state->modules_ instead of module_list, because the
michael@0 214 // |modules| argument will be used to populate the |module| fields in
michael@0 215 // the returned StackFrame objects, which will be placed into the
michael@0 216 // returned ProcessState object. module_list's lifetime is only as
michael@0 217 // long as the Minidump object: it will be deleted when this function
michael@0 218 // returns. process_state->modules_ is owned by the ProcessState object
michael@0 219 // (just like the StackFrame objects), and is much more suitable for this
michael@0 220 // task.
michael@0 221 scoped_ptr<Stackwalker> stackwalker(
michael@0 222 Stackwalker::StackwalkerForCPU(process_state->system_info(),
michael@0 223 context,
michael@0 224 thread_memory,
michael@0 225 process_state->modules_,
michael@0 226 frame_symbolizer_));
michael@0 227
michael@0 228 scoped_ptr<CallStack> stack(new CallStack());
michael@0 229 if (stackwalker.get()) {
michael@0 230 if (!stackwalker->Walk(stack.get(),
michael@0 231 &process_state->modules_without_symbols_)) {
michael@0 232 BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at "
michael@0 233 << thread_string;
michael@0 234 interrupted = true;
michael@0 235 }
michael@0 236 } else {
michael@0 237 // Threads with missing CPU contexts will hit this, but
michael@0 238 // don't abort processing the rest of the dump just for
michael@0 239 // one bad thread.
michael@0 240 BPLOG(ERROR) << "No stackwalker for " << thread_string;
michael@0 241 }
michael@0 242 process_state->threads_.push_back(stack.release());
michael@0 243 process_state->thread_memory_regions_.push_back(thread_memory);
michael@0 244 }
michael@0 245
michael@0 246 if (interrupted) {
michael@0 247 BPLOG(INFO) << "Processing interrupted for " << dump->path();
michael@0 248 return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED;
michael@0 249 }
michael@0 250
michael@0 251 // If a requesting thread was indicated, it must be present.
michael@0 252 if (has_requesting_thread && !found_requesting_thread) {
michael@0 253 // Don't mark as an error, but invalidate the requesting thread
michael@0 254 BPLOG(ERROR) << "Minidump indicated requesting thread " <<
michael@0 255 HexString(requesting_thread_id) << ", not found in " <<
michael@0 256 dump->path();
michael@0 257 process_state->requesting_thread_ = -1;
michael@0 258 }
michael@0 259
michael@0 260 // Exploitability defaults to EXPLOITABILITY_NOT_ANALYZED
michael@0 261 process_state->exploitability_ = EXPLOITABILITY_NOT_ANALYZED;
michael@0 262
michael@0 263 // If an exploitability run was requested we perform the platform specific
michael@0 264 // rating.
michael@0 265 if (enable_exploitability_) {
michael@0 266 scoped_ptr<Exploitability> exploitability(
michael@0 267 Exploitability::ExploitabilityForPlatform(dump, process_state));
michael@0 268 // The engine will be null if the platform is not supported
michael@0 269 if (exploitability != NULL) {
michael@0 270 process_state->exploitability_ = exploitability->CheckExploitability();
michael@0 271 } else {
michael@0 272 process_state->exploitability_ = EXPLOITABILITY_ERR_NOENGINE;
michael@0 273 }
michael@0 274 }
michael@0 275
michael@0 276 BPLOG(INFO) << "Processed " << dump->path();
michael@0 277 return PROCESS_OK;
michael@0 278 }
michael@0 279
michael@0 280 ProcessResult MinidumpProcessor::Process(
michael@0 281 const string &minidump_file, ProcessState *process_state) {
michael@0 282 BPLOG(INFO) << "Processing minidump in file " << minidump_file;
michael@0 283
michael@0 284 Minidump dump(minidump_file);
michael@0 285 if (!dump.Read()) {
michael@0 286 BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read";
michael@0 287 return PROCESS_ERROR_MINIDUMP_NOT_FOUND;
michael@0 288 }
michael@0 289
michael@0 290 return Process(&dump, process_state);
michael@0 291 }
michael@0 292
michael@0 293 // Returns the MDRawSystemInfo from a minidump, or NULL if system info is
michael@0 294 // not available from the minidump. If system_info is non-NULL, it is used
michael@0 295 // to pass back the MinidumpSystemInfo object.
michael@0 296 static const MDRawSystemInfo* GetSystemInfo(Minidump *dump,
michael@0 297 MinidumpSystemInfo **system_info) {
michael@0 298 MinidumpSystemInfo *minidump_system_info = dump->GetSystemInfo();
michael@0 299 if (!minidump_system_info)
michael@0 300 return NULL;
michael@0 301
michael@0 302 if (system_info)
michael@0 303 *system_info = minidump_system_info;
michael@0 304
michael@0 305 return minidump_system_info->system_info();
michael@0 306 }
michael@0 307
michael@0 308 // static
michael@0 309 bool MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) {
michael@0 310 assert(dump);
michael@0 311 assert(info);
michael@0 312
michael@0 313 info->cpu.clear();
michael@0 314 info->cpu_info.clear();
michael@0 315
michael@0 316 MinidumpSystemInfo *system_info;
michael@0 317 const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info);
michael@0 318 if (!raw_system_info)
michael@0 319 return false;
michael@0 320
michael@0 321 switch (raw_system_info->processor_architecture) {
michael@0 322 case MD_CPU_ARCHITECTURE_X86:
michael@0 323 case MD_CPU_ARCHITECTURE_AMD64: {
michael@0 324 if (raw_system_info->processor_architecture ==
michael@0 325 MD_CPU_ARCHITECTURE_X86)
michael@0 326 info->cpu = "x86";
michael@0 327 else
michael@0 328 info->cpu = "amd64";
michael@0 329
michael@0 330 const string *cpu_vendor = system_info->GetCPUVendor();
michael@0 331 if (cpu_vendor) {
michael@0 332 info->cpu_info = *cpu_vendor;
michael@0 333 info->cpu_info.append(" ");
michael@0 334 }
michael@0 335
michael@0 336 char x86_info[36];
michael@0 337 snprintf(x86_info, sizeof(x86_info), "family %u model %u stepping %u",
michael@0 338 raw_system_info->processor_level,
michael@0 339 raw_system_info->processor_revision >> 8,
michael@0 340 raw_system_info->processor_revision & 0xff);
michael@0 341 info->cpu_info.append(x86_info);
michael@0 342 break;
michael@0 343 }
michael@0 344
michael@0 345 case MD_CPU_ARCHITECTURE_PPC: {
michael@0 346 info->cpu = "ppc";
michael@0 347 break;
michael@0 348 }
michael@0 349
michael@0 350 case MD_CPU_ARCHITECTURE_SPARC: {
michael@0 351 info->cpu = "sparc";
michael@0 352 break;
michael@0 353 }
michael@0 354
michael@0 355 case MD_CPU_ARCHITECTURE_ARM: {
michael@0 356 info->cpu = "arm";
michael@0 357 break;
michael@0 358 }
michael@0 359
michael@0 360 default: {
michael@0 361 // Assign the numeric architecture ID into the CPU string.
michael@0 362 char cpu_string[7];
michael@0 363 snprintf(cpu_string, sizeof(cpu_string), "0x%04x",
michael@0 364 raw_system_info->processor_architecture);
michael@0 365 info->cpu = cpu_string;
michael@0 366 break;
michael@0 367 }
michael@0 368 }
michael@0 369
michael@0 370 info->cpu_count = raw_system_info->number_of_processors;
michael@0 371
michael@0 372 return true;
michael@0 373 }
michael@0 374
michael@0 375 // static
michael@0 376 bool MinidumpProcessor::GetOSInfo(Minidump *dump, SystemInfo *info) {
michael@0 377 assert(dump);
michael@0 378 assert(info);
michael@0 379
michael@0 380 info->os.clear();
michael@0 381 info->os_short.clear();
michael@0 382 info->os_version.clear();
michael@0 383
michael@0 384 MinidumpSystemInfo *system_info;
michael@0 385 const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info);
michael@0 386 if (!raw_system_info)
michael@0 387 return false;
michael@0 388
michael@0 389 info->os_short = system_info->GetOS();
michael@0 390
michael@0 391 switch (raw_system_info->platform_id) {
michael@0 392 case MD_OS_WIN32_NT: {
michael@0 393 info->os = "Windows NT";
michael@0 394 break;
michael@0 395 }
michael@0 396
michael@0 397 case MD_OS_WIN32_WINDOWS: {
michael@0 398 info->os = "Windows";
michael@0 399 break;
michael@0 400 }
michael@0 401
michael@0 402 case MD_OS_MAC_OS_X: {
michael@0 403 info->os = "Mac OS X";
michael@0 404 break;
michael@0 405 }
michael@0 406
michael@0 407 case MD_OS_IOS: {
michael@0 408 info->os = "iOS";
michael@0 409 break;
michael@0 410 }
michael@0 411
michael@0 412 case MD_OS_LINUX: {
michael@0 413 info->os = "Linux";
michael@0 414 break;
michael@0 415 }
michael@0 416
michael@0 417 case MD_OS_SOLARIS: {
michael@0 418 info->os = "Solaris";
michael@0 419 break;
michael@0 420 }
michael@0 421
michael@0 422 case MD_OS_ANDROID: {
michael@0 423 info->os = "Android";
michael@0 424 break;
michael@0 425 }
michael@0 426
michael@0 427 default: {
michael@0 428 // Assign the numeric platform ID into the OS string.
michael@0 429 char os_string[11];
michael@0 430 snprintf(os_string, sizeof(os_string), "0x%08x",
michael@0 431 raw_system_info->platform_id);
michael@0 432 info->os = os_string;
michael@0 433 break;
michael@0 434 }
michael@0 435 }
michael@0 436
michael@0 437 char os_version_string[33];
michael@0 438 snprintf(os_version_string, sizeof(os_version_string), "%u.%u.%u",
michael@0 439 raw_system_info->major_version,
michael@0 440 raw_system_info->minor_version,
michael@0 441 raw_system_info->build_number);
michael@0 442 info->os_version = os_version_string;
michael@0 443
michael@0 444 const string *csd_version = system_info->GetCSDVersion();
michael@0 445 if (csd_version) {
michael@0 446 info->os_version.append(" ");
michael@0 447 info->os_version.append(*csd_version);
michael@0 448 }
michael@0 449
michael@0 450 return true;
michael@0 451 }
michael@0 452
michael@0 453 // static
michael@0 454 string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) {
michael@0 455 MinidumpException *exception = dump->GetException();
michael@0 456 if (!exception)
michael@0 457 return "";
michael@0 458
michael@0 459 const MDRawExceptionStream *raw_exception = exception->exception();
michael@0 460 if (!raw_exception)
michael@0 461 return "";
michael@0 462
michael@0 463 if (address)
michael@0 464 *address = raw_exception->exception_record.exception_address;
michael@0 465
michael@0 466 // The reason value is OS-specific and possibly CPU-specific. Set up
michael@0 467 // sensible numeric defaults for the reason string in case we can't
michael@0 468 // map the codes to a string (because there's no system info, or because
michael@0 469 // it's an unrecognized platform, or because it's an unrecognized code.)
michael@0 470 char reason_string[24];
michael@0 471 uint32_t exception_code = raw_exception->exception_record.exception_code;
michael@0 472 uint32_t exception_flags = raw_exception->exception_record.exception_flags;
michael@0 473 snprintf(reason_string, sizeof(reason_string), "0x%08x / 0x%08x",
michael@0 474 exception_code, exception_flags);
michael@0 475 string reason = reason_string;
michael@0 476
michael@0 477 const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, NULL);
michael@0 478 if (!raw_system_info)
michael@0 479 return reason;
michael@0 480
michael@0 481 switch (raw_system_info->platform_id) {
michael@0 482 case MD_OS_MAC_OS_X:
michael@0 483 case MD_OS_IOS: {
michael@0 484 char flags_string[11];
michael@0 485 snprintf(flags_string, sizeof(flags_string), "0x%08x", exception_flags);
michael@0 486 switch (exception_code) {
michael@0 487 case MD_EXCEPTION_MAC_BAD_ACCESS:
michael@0 488 reason = "EXC_BAD_ACCESS / ";
michael@0 489 switch (exception_flags) {
michael@0 490 case MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS:
michael@0 491 reason.append("KERN_INVALID_ADDRESS");
michael@0 492 break;
michael@0 493 case MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE:
michael@0 494 reason.append("KERN_PROTECTION_FAILURE");
michael@0 495 break;
michael@0 496 case MD_EXCEPTION_CODE_MAC_NO_ACCESS:
michael@0 497 reason.append("KERN_NO_ACCESS");
michael@0 498 break;
michael@0 499 case MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE:
michael@0 500 reason.append("KERN_MEMORY_FAILURE");
michael@0 501 break;
michael@0 502 case MD_EXCEPTION_CODE_MAC_MEMORY_ERROR:
michael@0 503 reason.append("KERN_MEMORY_ERROR");
michael@0 504 break;
michael@0 505 default:
michael@0 506 // arm and ppc overlap
michael@0 507 if (raw_system_info->processor_architecture ==
michael@0 508 MD_CPU_ARCHITECTURE_ARM) {
michael@0 509 switch (exception_flags) {
michael@0 510 case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN:
michael@0 511 reason.append("EXC_ARM_DA_ALIGN");
michael@0 512 break;
michael@0 513 case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG:
michael@0 514 reason.append("EXC_ARM_DA_DEBUG");
michael@0 515 break;
michael@0 516 default:
michael@0 517 reason.append(flags_string);
michael@0 518 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 519 break;
michael@0 520 }
michael@0 521 } else if (raw_system_info->processor_architecture ==
michael@0 522 MD_CPU_ARCHITECTURE_PPC) {
michael@0 523 switch (exception_flags) {
michael@0 524 case MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ:
michael@0 525 reason.append("EXC_PPC_VM_PROT_READ");
michael@0 526 break;
michael@0 527 case MD_EXCEPTION_CODE_MAC_PPC_BADSPACE:
michael@0 528 reason.append("EXC_PPC_BADSPACE");
michael@0 529 break;
michael@0 530 case MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED:
michael@0 531 reason.append("EXC_PPC_UNALIGNED");
michael@0 532 break;
michael@0 533 default:
michael@0 534 reason.append(flags_string);
michael@0 535 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 536 break;
michael@0 537 }
michael@0 538 } else {
michael@0 539 reason.append(flags_string);
michael@0 540 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 541 }
michael@0 542 break;
michael@0 543 }
michael@0 544 break;
michael@0 545 case MD_EXCEPTION_MAC_BAD_INSTRUCTION:
michael@0 546 reason = "EXC_BAD_INSTRUCTION / ";
michael@0 547 switch (raw_system_info->processor_architecture) {
michael@0 548 case MD_CPU_ARCHITECTURE_ARM: {
michael@0 549 switch (exception_flags) {
michael@0 550 case MD_EXCEPTION_CODE_MAC_ARM_UNDEFINED:
michael@0 551 reason.append("EXC_ARM_UNDEFINED");
michael@0 552 break;
michael@0 553 default:
michael@0 554 reason.append(flags_string);
michael@0 555 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 556 break;
michael@0 557 }
michael@0 558 break;
michael@0 559 }
michael@0 560 case MD_CPU_ARCHITECTURE_PPC: {
michael@0 561 switch (exception_flags) {
michael@0 562 case MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL:
michael@0 563 reason.append("EXC_PPC_INVALID_SYSCALL");
michael@0 564 break;
michael@0 565 case MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION:
michael@0 566 reason.append("EXC_PPC_UNIPL_INST");
michael@0 567 break;
michael@0 568 case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION:
michael@0 569 reason.append("EXC_PPC_PRIVINST");
michael@0 570 break;
michael@0 571 case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER:
michael@0 572 reason.append("EXC_PPC_PRIVREG");
michael@0 573 break;
michael@0 574 case MD_EXCEPTION_CODE_MAC_PPC_TRACE:
michael@0 575 reason.append("EXC_PPC_TRACE");
michael@0 576 break;
michael@0 577 case MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR:
michael@0 578 reason.append("EXC_PPC_PERFMON");
michael@0 579 break;
michael@0 580 default:
michael@0 581 reason.append(flags_string);
michael@0 582 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 583 break;
michael@0 584 }
michael@0 585 break;
michael@0 586 }
michael@0 587 case MD_CPU_ARCHITECTURE_X86: {
michael@0 588 switch (exception_flags) {
michael@0 589 case MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION:
michael@0 590 reason.append("EXC_I386_INVOP");
michael@0 591 break;
michael@0 592 case MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT:
michael@0 593 reason.append("EXC_INVTSSFLT");
michael@0 594 break;
michael@0 595 case MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT:
michael@0 596 reason.append("EXC_SEGNPFLT");
michael@0 597 break;
michael@0 598 case MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT:
michael@0 599 reason.append("EXC_STKFLT");
michael@0 600 break;
michael@0 601 case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT:
michael@0 602 reason.append("EXC_GPFLT");
michael@0 603 break;
michael@0 604 case MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT:
michael@0 605 reason.append("EXC_ALIGNFLT");
michael@0 606 break;
michael@0 607 default:
michael@0 608 reason.append(flags_string);
michael@0 609 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 610 break;
michael@0 611 }
michael@0 612 break;
michael@0 613 }
michael@0 614 default:
michael@0 615 reason.append(flags_string);
michael@0 616 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 617 break;
michael@0 618 }
michael@0 619 break;
michael@0 620 case MD_EXCEPTION_MAC_ARITHMETIC:
michael@0 621 reason = "EXC_ARITHMETIC / ";
michael@0 622 switch (raw_system_info->processor_architecture) {
michael@0 623 case MD_CPU_ARCHITECTURE_PPC: {
michael@0 624 switch (exception_flags) {
michael@0 625 case MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW:
michael@0 626 reason.append("EXC_PPC_OVERFLOW");
michael@0 627 break;
michael@0 628 case MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE:
michael@0 629 reason.append("EXC_PPC_ZERO_DIVIDE");
michael@0 630 break;
michael@0 631 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT:
michael@0 632 reason.append("EXC_FLT_INEXACT");
michael@0 633 break;
michael@0 634 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE:
michael@0 635 reason.append("EXC_PPC_FLT_ZERO_DIVIDE");
michael@0 636 break;
michael@0 637 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW:
michael@0 638 reason.append("EXC_PPC_FLT_UNDERFLOW");
michael@0 639 break;
michael@0 640 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW:
michael@0 641 reason.append("EXC_PPC_FLT_OVERFLOW");
michael@0 642 break;
michael@0 643 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER:
michael@0 644 reason.append("EXC_PPC_FLT_NOT_A_NUMBER");
michael@0 645 break;
michael@0 646 case MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION:
michael@0 647 reason.append("EXC_PPC_NOEMULATION");
michael@0 648 break;
michael@0 649 case MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST:
michael@0 650 reason.append("EXC_PPC_ALTIVECASSIST");
michael@0 651 default:
michael@0 652 reason.append(flags_string);
michael@0 653 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 654 break;
michael@0 655 }
michael@0 656 break;
michael@0 657 }
michael@0 658 case MD_CPU_ARCHITECTURE_X86: {
michael@0 659 switch (exception_flags) {
michael@0 660 case MD_EXCEPTION_CODE_MAC_X86_DIV:
michael@0 661 reason.append("EXC_I386_DIV");
michael@0 662 break;
michael@0 663 case MD_EXCEPTION_CODE_MAC_X86_INTO:
michael@0 664 reason.append("EXC_I386_INTO");
michael@0 665 break;
michael@0 666 case MD_EXCEPTION_CODE_MAC_X86_NOEXT:
michael@0 667 reason.append("EXC_I386_NOEXT");
michael@0 668 break;
michael@0 669 case MD_EXCEPTION_CODE_MAC_X86_EXTOVR:
michael@0 670 reason.append("EXC_I386_EXTOVR");
michael@0 671 break;
michael@0 672 case MD_EXCEPTION_CODE_MAC_X86_EXTERR:
michael@0 673 reason.append("EXC_I386_EXTERR");
michael@0 674 break;
michael@0 675 case MD_EXCEPTION_CODE_MAC_X86_EMERR:
michael@0 676 reason.append("EXC_I386_EMERR");
michael@0 677 break;
michael@0 678 case MD_EXCEPTION_CODE_MAC_X86_BOUND:
michael@0 679 reason.append("EXC_I386_BOUND");
michael@0 680 break;
michael@0 681 case MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR:
michael@0 682 reason.append("EXC_I386_SSEEXTERR");
michael@0 683 break;
michael@0 684 default:
michael@0 685 reason.append(flags_string);
michael@0 686 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 687 break;
michael@0 688 }
michael@0 689 break;
michael@0 690 }
michael@0 691 default:
michael@0 692 reason.append(flags_string);
michael@0 693 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 694 break;
michael@0 695 }
michael@0 696 break;
michael@0 697 case MD_EXCEPTION_MAC_EMULATION:
michael@0 698 reason = "EXC_EMULATION / ";
michael@0 699 reason.append(flags_string);
michael@0 700 break;
michael@0 701 case MD_EXCEPTION_MAC_SOFTWARE:
michael@0 702 reason = "EXC_SOFTWARE / ";
michael@0 703 switch (exception_flags) {
michael@0 704 case MD_EXCEPTION_CODE_MAC_ABORT:
michael@0 705 reason.append("SIGABRT");
michael@0 706 break;
michael@0 707 case MD_EXCEPTION_CODE_MAC_NS_EXCEPTION:
michael@0 708 reason.append("UNCAUGHT_NS_EXCEPTION");
michael@0 709 break;
michael@0 710 // These are ppc only but shouldn't be a problem as they're
michael@0 711 // unused on x86
michael@0 712 case MD_EXCEPTION_CODE_MAC_PPC_TRAP:
michael@0 713 reason.append("EXC_PPC_TRAP");
michael@0 714 break;
michael@0 715 case MD_EXCEPTION_CODE_MAC_PPC_MIGRATE:
michael@0 716 reason.append("EXC_PPC_MIGRATE");
michael@0 717 break;
michael@0 718 default:
michael@0 719 reason.append(flags_string);
michael@0 720 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 721 break;
michael@0 722 }
michael@0 723 break;
michael@0 724 case MD_EXCEPTION_MAC_BREAKPOINT:
michael@0 725 reason = "EXC_BREAKPOINT / ";
michael@0 726 switch (raw_system_info->processor_architecture) {
michael@0 727 case MD_CPU_ARCHITECTURE_ARM: {
michael@0 728 switch (exception_flags) {
michael@0 729 case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN:
michael@0 730 reason.append("EXC_ARM_DA_ALIGN");
michael@0 731 break;
michael@0 732 case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG:
michael@0 733 reason.append("EXC_ARM_DA_DEBUG");
michael@0 734 break;
michael@0 735 case MD_EXCEPTION_CODE_MAC_ARM_BREAKPOINT:
michael@0 736 reason.append("EXC_ARM_BREAKPOINT");
michael@0 737 break;
michael@0 738 default:
michael@0 739 reason.append(flags_string);
michael@0 740 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 741 break;
michael@0 742 }
michael@0 743 break;
michael@0 744 }
michael@0 745 case MD_CPU_ARCHITECTURE_PPC: {
michael@0 746 switch (exception_flags) {
michael@0 747 case MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT:
michael@0 748 reason.append("EXC_PPC_BREAKPOINT");
michael@0 749 break;
michael@0 750 default:
michael@0 751 reason.append(flags_string);
michael@0 752 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 753 break;
michael@0 754 }
michael@0 755 break;
michael@0 756 }
michael@0 757 case MD_CPU_ARCHITECTURE_X86: {
michael@0 758 switch (exception_flags) {
michael@0 759 case MD_EXCEPTION_CODE_MAC_X86_SGL:
michael@0 760 reason.append("EXC_I386_SGL");
michael@0 761 break;
michael@0 762 case MD_EXCEPTION_CODE_MAC_X86_BPT:
michael@0 763 reason.append("EXC_I386_BPT");
michael@0 764 break;
michael@0 765 default:
michael@0 766 reason.append(flags_string);
michael@0 767 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 768 break;
michael@0 769 }
michael@0 770 break;
michael@0 771 }
michael@0 772 default:
michael@0 773 reason.append(flags_string);
michael@0 774 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 775 break;
michael@0 776 }
michael@0 777 break;
michael@0 778 case MD_EXCEPTION_MAC_SYSCALL:
michael@0 779 reason = "EXC_SYSCALL / ";
michael@0 780 reason.append(flags_string);
michael@0 781 break;
michael@0 782 case MD_EXCEPTION_MAC_MACH_SYSCALL:
michael@0 783 reason = "EXC_MACH_SYSCALL / ";
michael@0 784 reason.append(flags_string);
michael@0 785 break;
michael@0 786 case MD_EXCEPTION_MAC_RPC_ALERT:
michael@0 787 reason = "EXC_RPC_ALERT / ";
michael@0 788 reason.append(flags_string);
michael@0 789 break;
michael@0 790 }
michael@0 791 break;
michael@0 792 }
michael@0 793
michael@0 794 case MD_OS_WIN32_NT:
michael@0 795 case MD_OS_WIN32_WINDOWS: {
michael@0 796 switch (exception_code) {
michael@0 797 case MD_EXCEPTION_CODE_WIN_CONTROL_C:
michael@0 798 reason = "DBG_CONTROL_C";
michael@0 799 break;
michael@0 800 case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION:
michael@0 801 reason = "EXCEPTION_GUARD_PAGE";
michael@0 802 break;
michael@0 803 case MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT:
michael@0 804 reason = "EXCEPTION_DATATYPE_MISALIGNMENT";
michael@0 805 break;
michael@0 806 case MD_EXCEPTION_CODE_WIN_BREAKPOINT:
michael@0 807 reason = "EXCEPTION_BREAKPOINT";
michael@0 808 break;
michael@0 809 case MD_EXCEPTION_CODE_WIN_SINGLE_STEP:
michael@0 810 reason = "EXCEPTION_SINGLE_STEP";
michael@0 811 break;
michael@0 812 case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION:
michael@0 813 // For EXCEPTION_ACCESS_VIOLATION, Windows puts the address that
michael@0 814 // caused the fault in exception_information[1].
michael@0 815 // exception_information[0] is 0 if the violation was caused by
michael@0 816 // an attempt to read data and 1 if it was an attempt to write
michael@0 817 // data.
michael@0 818 // This information is useful in addition to the code address, which
michael@0 819 // will be present in the crash thread's instruction field anyway.
michael@0 820 if (raw_exception->exception_record.number_parameters >= 1) {
michael@0 821 MDAccessViolationTypeWin av_type =
michael@0 822 static_cast<MDAccessViolationTypeWin>
michael@0 823 (raw_exception->exception_record.exception_information[0]);
michael@0 824 switch (av_type) {
michael@0 825 case MD_ACCESS_VIOLATION_WIN_READ:
michael@0 826 reason = "EXCEPTION_ACCESS_VIOLATION_READ";
michael@0 827 break;
michael@0 828 case MD_ACCESS_VIOLATION_WIN_WRITE:
michael@0 829 reason = "EXCEPTION_ACCESS_VIOLATION_WRITE";
michael@0 830 break;
michael@0 831 case MD_ACCESS_VIOLATION_WIN_EXEC:
michael@0 832 reason = "EXCEPTION_ACCESS_VIOLATION_EXEC";
michael@0 833 break;
michael@0 834 default:
michael@0 835 reason = "EXCEPTION_ACCESS_VIOLATION";
michael@0 836 break;
michael@0 837 }
michael@0 838 } else {
michael@0 839 reason = "EXCEPTION_ACCESS_VIOLATION";
michael@0 840 }
michael@0 841 if (address &&
michael@0 842 raw_exception->exception_record.number_parameters >= 2) {
michael@0 843 *address =
michael@0 844 raw_exception->exception_record.exception_information[1];
michael@0 845 }
michael@0 846 break;
michael@0 847 case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR:
michael@0 848 reason = "EXCEPTION_IN_PAGE_ERROR";
michael@0 849 break;
michael@0 850 case MD_EXCEPTION_CODE_WIN_INVALID_HANDLE:
michael@0 851 reason = "EXCEPTION_INVALID_HANDLE";
michael@0 852 break;
michael@0 853 case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION:
michael@0 854 reason = "EXCEPTION_ILLEGAL_INSTRUCTION";
michael@0 855 break;
michael@0 856 case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION:
michael@0 857 reason = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
michael@0 858 break;
michael@0 859 case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION:
michael@0 860 reason = "EXCEPTION_INVALID_DISPOSITION";
michael@0 861 break;
michael@0 862 case MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED:
michael@0 863 reason = "EXCEPTION_BOUNDS_EXCEEDED";
michael@0 864 break;
michael@0 865 case MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND:
michael@0 866 reason = "EXCEPTION_FLT_DENORMAL_OPERAND";
michael@0 867 break;
michael@0 868 case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO:
michael@0 869 reason = "EXCEPTION_FLT_DIVIDE_BY_ZERO";
michael@0 870 break;
michael@0 871 case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT:
michael@0 872 reason = "EXCEPTION_FLT_INEXACT_RESULT";
michael@0 873 break;
michael@0 874 case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION:
michael@0 875 reason = "EXCEPTION_FLT_INVALID_OPERATION";
michael@0 876 break;
michael@0 877 case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW:
michael@0 878 reason = "EXCEPTION_FLT_OVERFLOW";
michael@0 879 break;
michael@0 880 case MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK:
michael@0 881 reason = "EXCEPTION_FLT_STACK_CHECK";
michael@0 882 break;
michael@0 883 case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW:
michael@0 884 reason = "EXCEPTION_FLT_UNDERFLOW";
michael@0 885 break;
michael@0 886 case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO:
michael@0 887 reason = "EXCEPTION_INT_DIVIDE_BY_ZERO";
michael@0 888 break;
michael@0 889 case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW:
michael@0 890 reason = "EXCEPTION_INT_OVERFLOW";
michael@0 891 break;
michael@0 892 case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION:
michael@0 893 reason = "EXCEPTION_PRIV_INSTRUCTION";
michael@0 894 break;
michael@0 895 case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW:
michael@0 896 reason = "EXCEPTION_STACK_OVERFLOW";
michael@0 897 break;
michael@0 898 case MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK:
michael@0 899 reason = "EXCEPTION_POSSIBLE_DEADLOCK";
michael@0 900 break;
michael@0 901 case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN:
michael@0 902 reason = "EXCEPTION_STACK_BUFFER_OVERRUN";
michael@0 903 break;
michael@0 904 case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION:
michael@0 905 reason = "EXCEPTION_HEAP_CORRUPTION";
michael@0 906 break;
michael@0 907 case MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION:
michael@0 908 reason = "Unhandled C++ Exception";
michael@0 909 break;
michael@0 910 default:
michael@0 911 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 912 break;
michael@0 913 }
michael@0 914 break;
michael@0 915 }
michael@0 916
michael@0 917 case MD_OS_ANDROID:
michael@0 918 case MD_OS_LINUX: {
michael@0 919 switch (exception_code) {
michael@0 920 case MD_EXCEPTION_CODE_LIN_SIGHUP:
michael@0 921 reason = "SIGHUP";
michael@0 922 break;
michael@0 923 case MD_EXCEPTION_CODE_LIN_SIGINT:
michael@0 924 reason = "SIGINT";
michael@0 925 break;
michael@0 926 case MD_EXCEPTION_CODE_LIN_SIGQUIT:
michael@0 927 reason = "SIGQUIT";
michael@0 928 break;
michael@0 929 case MD_EXCEPTION_CODE_LIN_SIGILL:
michael@0 930 reason = "SIGILL";
michael@0 931 break;
michael@0 932 case MD_EXCEPTION_CODE_LIN_SIGTRAP:
michael@0 933 reason = "SIGTRAP";
michael@0 934 break;
michael@0 935 case MD_EXCEPTION_CODE_LIN_SIGABRT:
michael@0 936 reason = "SIGABRT";
michael@0 937 break;
michael@0 938 case MD_EXCEPTION_CODE_LIN_SIGBUS:
michael@0 939 reason = "SIGBUS";
michael@0 940 break;
michael@0 941 case MD_EXCEPTION_CODE_LIN_SIGFPE:
michael@0 942 reason = "SIGFPE";
michael@0 943 break;
michael@0 944 case MD_EXCEPTION_CODE_LIN_SIGKILL:
michael@0 945 reason = "SIGKILL";
michael@0 946 break;
michael@0 947 case MD_EXCEPTION_CODE_LIN_SIGUSR1:
michael@0 948 reason = "SIGUSR1";
michael@0 949 break;
michael@0 950 case MD_EXCEPTION_CODE_LIN_SIGSEGV:
michael@0 951 reason = "SIGSEGV";
michael@0 952 break;
michael@0 953 case MD_EXCEPTION_CODE_LIN_SIGUSR2:
michael@0 954 reason = "SIGUSR2";
michael@0 955 break;
michael@0 956 case MD_EXCEPTION_CODE_LIN_SIGPIPE:
michael@0 957 reason = "SIGPIPE";
michael@0 958 break;
michael@0 959 case MD_EXCEPTION_CODE_LIN_SIGALRM:
michael@0 960 reason = "SIGALRM";
michael@0 961 break;
michael@0 962 case MD_EXCEPTION_CODE_LIN_SIGTERM:
michael@0 963 reason = "SIGTERM";
michael@0 964 break;
michael@0 965 case MD_EXCEPTION_CODE_LIN_SIGSTKFLT:
michael@0 966 reason = "SIGSTKFLT";
michael@0 967 break;
michael@0 968 case MD_EXCEPTION_CODE_LIN_SIGCHLD:
michael@0 969 reason = "SIGCHLD";
michael@0 970 break;
michael@0 971 case MD_EXCEPTION_CODE_LIN_SIGCONT:
michael@0 972 reason = "SIGCONT";
michael@0 973 break;
michael@0 974 case MD_EXCEPTION_CODE_LIN_SIGSTOP:
michael@0 975 reason = "SIGSTOP";
michael@0 976 break;
michael@0 977 case MD_EXCEPTION_CODE_LIN_SIGTSTP:
michael@0 978 reason = "SIGTSTP";
michael@0 979 break;
michael@0 980 case MD_EXCEPTION_CODE_LIN_SIGTTIN:
michael@0 981 reason = "SIGTTIN";
michael@0 982 break;
michael@0 983 case MD_EXCEPTION_CODE_LIN_SIGTTOU:
michael@0 984 reason = "SIGTTOU";
michael@0 985 break;
michael@0 986 case MD_EXCEPTION_CODE_LIN_SIGURG:
michael@0 987 reason = "SIGURG";
michael@0 988 break;
michael@0 989 case MD_EXCEPTION_CODE_LIN_SIGXCPU:
michael@0 990 reason = "SIGXCPU";
michael@0 991 break;
michael@0 992 case MD_EXCEPTION_CODE_LIN_SIGXFSZ:
michael@0 993 reason = "SIGXFSZ";
michael@0 994 break;
michael@0 995 case MD_EXCEPTION_CODE_LIN_SIGVTALRM:
michael@0 996 reason = "SIGVTALRM";
michael@0 997 break;
michael@0 998 case MD_EXCEPTION_CODE_LIN_SIGPROF:
michael@0 999 reason = "SIGPROF";
michael@0 1000 break;
michael@0 1001 case MD_EXCEPTION_CODE_LIN_SIGWINCH:
michael@0 1002 reason = "SIGWINCH";
michael@0 1003 break;
michael@0 1004 case MD_EXCEPTION_CODE_LIN_SIGIO:
michael@0 1005 reason = "SIGIO";
michael@0 1006 break;
michael@0 1007 case MD_EXCEPTION_CODE_LIN_SIGPWR:
michael@0 1008 reason = "SIGPWR";
michael@0 1009 break;
michael@0 1010 case MD_EXCEPTION_CODE_LIN_SIGSYS:
michael@0 1011 reason = "SIGSYS";
michael@0 1012 break;
michael@0 1013 case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED:
michael@0 1014 reason = "DUMP_REQUESTED";
michael@0 1015 break;
michael@0 1016 default:
michael@0 1017 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 1018 break;
michael@0 1019 }
michael@0 1020 break;
michael@0 1021 }
michael@0 1022
michael@0 1023 case MD_OS_SOLARIS: {
michael@0 1024 switch (exception_code) {
michael@0 1025 case MD_EXCEPTION_CODE_SOL_SIGHUP:
michael@0 1026 reason = "SIGHUP";
michael@0 1027 break;
michael@0 1028 case MD_EXCEPTION_CODE_SOL_SIGINT:
michael@0 1029 reason = "SIGINT";
michael@0 1030 break;
michael@0 1031 case MD_EXCEPTION_CODE_SOL_SIGQUIT:
michael@0 1032 reason = "SIGQUIT";
michael@0 1033 break;
michael@0 1034 case MD_EXCEPTION_CODE_SOL_SIGILL:
michael@0 1035 reason = "SIGILL";
michael@0 1036 break;
michael@0 1037 case MD_EXCEPTION_CODE_SOL_SIGTRAP:
michael@0 1038 reason = "SIGTRAP";
michael@0 1039 break;
michael@0 1040 case MD_EXCEPTION_CODE_SOL_SIGIOT:
michael@0 1041 reason = "SIGIOT | SIGABRT";
michael@0 1042 break;
michael@0 1043 case MD_EXCEPTION_CODE_SOL_SIGEMT:
michael@0 1044 reason = "SIGEMT";
michael@0 1045 break;
michael@0 1046 case MD_EXCEPTION_CODE_SOL_SIGFPE:
michael@0 1047 reason = "SIGFPE";
michael@0 1048 break;
michael@0 1049 case MD_EXCEPTION_CODE_SOL_SIGKILL:
michael@0 1050 reason = "SIGKILL";
michael@0 1051 break;
michael@0 1052 case MD_EXCEPTION_CODE_SOL_SIGBUS:
michael@0 1053 reason = "SIGBUS";
michael@0 1054 break;
michael@0 1055 case MD_EXCEPTION_CODE_SOL_SIGSEGV:
michael@0 1056 reason = "SIGSEGV";
michael@0 1057 break;
michael@0 1058 case MD_EXCEPTION_CODE_SOL_SIGSYS:
michael@0 1059 reason = "SIGSYS";
michael@0 1060 break;
michael@0 1061 case MD_EXCEPTION_CODE_SOL_SIGPIPE:
michael@0 1062 reason = "SIGPIPE";
michael@0 1063 break;
michael@0 1064 case MD_EXCEPTION_CODE_SOL_SIGALRM:
michael@0 1065 reason = "SIGALRM";
michael@0 1066 break;
michael@0 1067 case MD_EXCEPTION_CODE_SOL_SIGTERM:
michael@0 1068 reason = "SIGTERM";
michael@0 1069 break;
michael@0 1070 case MD_EXCEPTION_CODE_SOL_SIGUSR1:
michael@0 1071 reason = "SIGUSR1";
michael@0 1072 break;
michael@0 1073 case MD_EXCEPTION_CODE_SOL_SIGUSR2:
michael@0 1074 reason = "SIGUSR2";
michael@0 1075 break;
michael@0 1076 case MD_EXCEPTION_CODE_SOL_SIGCLD:
michael@0 1077 reason = "SIGCLD | SIGCHLD";
michael@0 1078 break;
michael@0 1079 case MD_EXCEPTION_CODE_SOL_SIGPWR:
michael@0 1080 reason = "SIGPWR";
michael@0 1081 break;
michael@0 1082 case MD_EXCEPTION_CODE_SOL_SIGWINCH:
michael@0 1083 reason = "SIGWINCH";
michael@0 1084 break;
michael@0 1085 case MD_EXCEPTION_CODE_SOL_SIGURG:
michael@0 1086 reason = "SIGURG";
michael@0 1087 break;
michael@0 1088 case MD_EXCEPTION_CODE_SOL_SIGPOLL:
michael@0 1089 reason = "SIGPOLL | SIGIO";
michael@0 1090 break;
michael@0 1091 case MD_EXCEPTION_CODE_SOL_SIGSTOP:
michael@0 1092 reason = "SIGSTOP";
michael@0 1093 break;
michael@0 1094 case MD_EXCEPTION_CODE_SOL_SIGTSTP:
michael@0 1095 reason = "SIGTSTP";
michael@0 1096 break;
michael@0 1097 case MD_EXCEPTION_CODE_SOL_SIGCONT:
michael@0 1098 reason = "SIGCONT";
michael@0 1099 break;
michael@0 1100 case MD_EXCEPTION_CODE_SOL_SIGTTIN:
michael@0 1101 reason = "SIGTTIN";
michael@0 1102 break;
michael@0 1103 case MD_EXCEPTION_CODE_SOL_SIGTTOU:
michael@0 1104 reason = "SIGTTOU";
michael@0 1105 break;
michael@0 1106 case MD_EXCEPTION_CODE_SOL_SIGVTALRM:
michael@0 1107 reason = "SIGVTALRM";
michael@0 1108 break;
michael@0 1109 case MD_EXCEPTION_CODE_SOL_SIGPROF:
michael@0 1110 reason = "SIGPROF";
michael@0 1111 break;
michael@0 1112 case MD_EXCEPTION_CODE_SOL_SIGXCPU:
michael@0 1113 reason = "SIGXCPU";
michael@0 1114 break;
michael@0 1115 case MD_EXCEPTION_CODE_SOL_SIGXFSZ:
michael@0 1116 reason = "SIGXFSZ";
michael@0 1117 break;
michael@0 1118 case MD_EXCEPTION_CODE_SOL_SIGWAITING:
michael@0 1119 reason = "SIGWAITING";
michael@0 1120 break;
michael@0 1121 case MD_EXCEPTION_CODE_SOL_SIGLWP:
michael@0 1122 reason = "SIGLWP";
michael@0 1123 break;
michael@0 1124 case MD_EXCEPTION_CODE_SOL_SIGFREEZE:
michael@0 1125 reason = "SIGFREEZE";
michael@0 1126 break;
michael@0 1127 case MD_EXCEPTION_CODE_SOL_SIGTHAW:
michael@0 1128 reason = "SIGTHAW";
michael@0 1129 break;
michael@0 1130 case MD_EXCEPTION_CODE_SOL_SIGCANCEL:
michael@0 1131 reason = "SIGCANCEL";
michael@0 1132 break;
michael@0 1133 case MD_EXCEPTION_CODE_SOL_SIGLOST:
michael@0 1134 reason = "SIGLOST";
michael@0 1135 break;
michael@0 1136 case MD_EXCEPTION_CODE_SOL_SIGXRES:
michael@0 1137 reason = "SIGXRES";
michael@0 1138 break;
michael@0 1139 case MD_EXCEPTION_CODE_SOL_SIGJVM1:
michael@0 1140 reason = "SIGJVM1";
michael@0 1141 break;
michael@0 1142 case MD_EXCEPTION_CODE_SOL_SIGJVM2:
michael@0 1143 reason = "SIGJVM2";
michael@0 1144 break;
michael@0 1145 default:
michael@0 1146 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 1147 break;
michael@0 1148 }
michael@0 1149 break;
michael@0 1150 }
michael@0 1151
michael@0 1152 default: {
michael@0 1153 BPLOG(INFO) << "Unknown exception reason " << reason;
michael@0 1154 break;
michael@0 1155 }
michael@0 1156 }
michael@0 1157
michael@0 1158 return reason;
michael@0 1159 }
michael@0 1160
michael@0 1161 // static
michael@0 1162 string MinidumpProcessor::GetAssertion(Minidump *dump) {
michael@0 1163 MinidumpAssertion *assertion = dump->GetAssertion();
michael@0 1164 if (!assertion)
michael@0 1165 return "";
michael@0 1166
michael@0 1167 const MDRawAssertionInfo *raw_assertion = assertion->assertion();
michael@0 1168 if (!raw_assertion)
michael@0 1169 return "";
michael@0 1170
michael@0 1171 string assertion_string;
michael@0 1172 switch (raw_assertion->type) {
michael@0 1173 case MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER:
michael@0 1174 assertion_string = "Invalid parameter passed to library function";
michael@0 1175 break;
michael@0 1176 case MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL:
michael@0 1177 assertion_string = "Pure virtual function called";
michael@0 1178 break;
michael@0 1179 default: {
michael@0 1180 char assertion_type[32];
michael@0 1181 snprintf(assertion_type, sizeof(assertion_type),
michael@0 1182 "0x%08x", raw_assertion->type);
michael@0 1183 assertion_string = "Unknown assertion type ";
michael@0 1184 assertion_string += assertion_type;
michael@0 1185 break;
michael@0 1186 }
michael@0 1187 }
michael@0 1188
michael@0 1189 string expression = assertion->expression();
michael@0 1190 if (!expression.empty()) {
michael@0 1191 assertion_string.append(" " + expression);
michael@0 1192 }
michael@0 1193
michael@0 1194 string function = assertion->function();
michael@0 1195 if (!function.empty()) {
michael@0 1196 assertion_string.append(" in function " + function);
michael@0 1197 }
michael@0 1198
michael@0 1199 string file = assertion->file();
michael@0 1200 if (!file.empty()) {
michael@0 1201 assertion_string.append(", in file " + file);
michael@0 1202 }
michael@0 1203
michael@0 1204 if (raw_assertion->line != 0) {
michael@0 1205 char assertion_line[32];
michael@0 1206 snprintf(assertion_line, sizeof(assertion_line), "%u", raw_assertion->line);
michael@0 1207 assertion_string.append(" at line ");
michael@0 1208 assertion_string.append(assertion_line);
michael@0 1209 }
michael@0 1210
michael@0 1211 return assertion_string;
michael@0 1212 }
michael@0 1213
michael@0 1214 } // namespace google_breakpad

mercurial