1 // Copyright 2006 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h> // Must come first
31 #endif
32
33 #include "google_breakpad/processor/minidump_processor.h"
34
35 #include <assert.h>
36
37 #include <algorithm>
38 #include <limits>
39 #include <map>
40 #include <string>
41 #include <utility>
42
43 #include "common/scoped_ptr.h"
44 #include "common/stdio_wrapper.h"
45 #include "common/using_std_string.h"
46 #include "google_breakpad/processor/call_stack.h"
47 #include "google_breakpad/processor/minidump.h"
48 #include "google_breakpad/processor/process_state.h"
49 #include "google_breakpad/processor/exploitability.h"
50 #include "google_breakpad/processor/stack_frame_symbolizer.h"
51 #include "processor/logging.h"
52 #include "processor/stackwalker_x86.h"
53 #include "processor/symbolic_constants_win.h"
54
55 #ifdef __linux__
56 #include "processor/disassembler_objdump.h"
57 #endif
58
59 namespace google_breakpad {
60
MinidumpProcessor(SymbolSupplier * supplier,SourceLineResolverInterface * resolver)61 MinidumpProcessor::MinidumpProcessor(SymbolSupplier* supplier,
62 SourceLineResolverInterface* resolver)
63 : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)),
64 own_frame_symbolizer_(true),
65 enable_exploitability_(false),
66 enable_objdump_(false),
67 enable_objdump_for_exploitability_(false) {
68 }
69
MinidumpProcessor(SymbolSupplier * supplier,SourceLineResolverInterface * resolver,bool enable_exploitability)70 MinidumpProcessor::MinidumpProcessor(SymbolSupplier* supplier,
71 SourceLineResolverInterface* resolver,
72 bool enable_exploitability)
73 : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)),
74 own_frame_symbolizer_(true),
75 enable_exploitability_(enable_exploitability),
76 enable_objdump_(false),
77 enable_objdump_for_exploitability_(false) {
78 }
79
MinidumpProcessor(StackFrameSymbolizer * frame_symbolizer,bool enable_exploitability)80 MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer* frame_symbolizer,
81 bool enable_exploitability)
82 : frame_symbolizer_(frame_symbolizer),
83 own_frame_symbolizer_(false),
84 enable_exploitability_(enable_exploitability),
85 enable_objdump_(false),
86 enable_objdump_for_exploitability_(false) {
87 assert(frame_symbolizer_);
88 }
89
~MinidumpProcessor()90 MinidumpProcessor::~MinidumpProcessor() {
91 if (own_frame_symbolizer_) delete frame_symbolizer_;
92 }
93
Process(Minidump * dump,ProcessState * process_state)94 ProcessResult MinidumpProcessor::Process(
95 Minidump* dump, ProcessState* process_state) {
96 assert(dump);
97 assert(process_state);
98
99 process_state->Clear();
100
101 const MDRawHeader* header = dump->header();
102 if (!header) {
103 BPLOG(ERROR) << "Minidump " << dump->path() << " has no header";
104 return PROCESS_ERROR_NO_MINIDUMP_HEADER;
105 }
106 process_state->time_date_stamp_ = header->time_date_stamp;
107
108 bool has_process_create_time =
109 GetProcessCreateTime(dump, &process_state->process_create_time_);
110
111 bool has_cpu_info = GetCPUInfo(dump, &process_state->system_info_);
112 bool has_os_info = GetOSInfo(dump, &process_state->system_info_);
113
114 uint32_t dump_thread_id = 0;
115 bool has_dump_thread = false;
116 uint32_t requesting_thread_id = 0;
117 bool has_requesting_thread = false;
118
119 MinidumpBreakpadInfo* breakpad_info = dump->GetBreakpadInfo();
120 if (breakpad_info) {
121 has_dump_thread = breakpad_info->GetDumpThreadID(&dump_thread_id);
122 has_requesting_thread =
123 breakpad_info->GetRequestingThreadID(&requesting_thread_id);
124 }
125
126 MinidumpException* exception = dump->GetException();
127 if (exception) {
128 process_state->crashed_ = true;
129 has_requesting_thread = exception->GetThreadID(&requesting_thread_id);
130
131 process_state->crash_reason_ = GetCrashReason(
132 dump, &process_state->crash_address_, enable_objdump_);
133
134 process_state->exception_record_.set_code(
135 exception->exception()->exception_record.exception_code,
136 // TODO(ivanpe): Populate description.
137 /* description = */ "");
138 process_state->exception_record_.set_flags(
139 exception->exception()->exception_record.exception_flags,
140 // TODO(ivanpe): Populate description.
141 /* description = */ "");
142 process_state->exception_record_.set_nested_exception_record_address(
143 exception->exception()->exception_record.exception_record);
144 process_state->exception_record_.set_address(process_state->crash_address_);
145 const uint32_t num_parameters =
146 std::min(exception->exception()->exception_record.number_parameters,
147 MD_EXCEPTION_MAXIMUM_PARAMETERS);
148 for (uint32_t i = 0; i < num_parameters; ++i) {
149 process_state->exception_record_.add_parameter(
150 exception->exception()->exception_record.exception_information[i],
151 // TODO(ivanpe): Populate description.
152 /* description = */ "");
153 }
154 }
155
156 // This will just return an empty string if it doesn't exist.
157 process_state->assertion_ = GetAssertion(dump);
158
159 MinidumpModuleList* module_list = dump->GetModuleList();
160
161 // Put a copy of the module list into ProcessState object. This is not
162 // necessarily a MinidumpModuleList, but it adheres to the CodeModules
163 // interface, which is all that ProcessState needs to expose.
164 if (module_list) {
165 process_state->modules_ = module_list->Copy();
166 process_state->shrunk_range_modules_ =
167 process_state->modules_->GetShrunkRangeModules();
168 for (unsigned int i = 0;
169 i < process_state->shrunk_range_modules_.size();
170 i++) {
171 linked_ptr<const CodeModule> module =
172 process_state->shrunk_range_modules_[i];
173 BPLOG(INFO) << "The range for module " << module->code_file()
174 << " was shrunk down by " << HexString(
175 module->shrink_down_delta()) << " bytes. ";
176 }
177 }
178
179 MinidumpUnloadedModuleList* unloaded_module_list =
180 dump->GetUnloadedModuleList();
181 if (unloaded_module_list) {
182 process_state->unloaded_modules_ = unloaded_module_list->Copy();
183 }
184
185 MinidumpMemoryList* memory_list = dump->GetMemoryList();
186 if (memory_list) {
187 BPLOG(INFO) << "Found " << memory_list->region_count()
188 << " memory regions.";
189 }
190
191 MinidumpThreadList* threads = dump->GetThreadList();
192 if (!threads) {
193 BPLOG(ERROR) << "Minidump " << dump->path() << " has no thread list";
194 return PROCESS_ERROR_NO_THREAD_LIST;
195 }
196
197 BPLOG(INFO) << "Minidump " << dump->path() << " has " <<
198 (has_cpu_info ? "" : "no ") << "CPU info, " <<
199 (has_os_info ? "" : "no ") << "OS info, " <<
200 (breakpad_info != NULL ? "" : "no ") << "Breakpad info, " <<
201 (exception != NULL ? "" : "no ") << "exception, " <<
202 (module_list != NULL ? "" : "no ") << "module list, " <<
203 (threads != NULL ? "" : "no ") << "thread list, " <<
204 (has_dump_thread ? "" : "no ") << "dump thread, " <<
205 (has_requesting_thread ? "" : "no ") << "requesting thread, and " <<
206 (has_process_create_time ? "" : "no ") << "process create time";
207
208 bool interrupted = false;
209 bool found_requesting_thread = false;
210 unsigned int thread_count = threads->thread_count();
211
212 // Reset frame_symbolizer_ at the beginning of stackwalk for each minidump.
213 frame_symbolizer_->Reset();
214
215
216 MinidumpThreadNameList* thread_names = dump->GetThreadNameList();
217 std::map<uint32_t, string> thread_id_to_name;
218 if (thread_names) {
219 const unsigned int thread_name_count = thread_names->thread_name_count();
220 for (unsigned int thread_name_index = 0;
221 thread_name_index < thread_name_count;
222 ++thread_name_index) {
223 MinidumpThreadName* thread_name = thread_names->GetThreadNameAtIndex(thread_name_index);
224 if (!thread_name) {
225 BPLOG(ERROR) << "Could not get thread name for thread at index " << thread_name_index;
226 return PROCESS_ERROR_GETTING_THREAD_NAME;
227 }
228 uint32_t thread_id;
229 if (!thread_name->GetThreadID(&thread_id)) {
230 BPLOG(ERROR) << "Could not get thread ID for thread at index " << thread_name_index;
231 return PROCESS_ERROR_GETTING_THREAD_NAME;
232 }
233 thread_id_to_name.insert(std::make_pair(thread_id, thread_name->GetThreadName()));
234 }
235 }
236
237 for (unsigned int thread_index = 0;
238 thread_index < thread_count;
239 ++thread_index) {
240 char thread_string_buffer[64];
241 snprintf(thread_string_buffer, sizeof(thread_string_buffer), "%d/%d",
242 thread_index, thread_count);
243 string thread_string = dump->path() + ":" + thread_string_buffer;
244
245 MinidumpThread* thread = threads->GetThreadAtIndex(thread_index);
246 if (!thread) {
247 BPLOG(ERROR) << "Could not get thread for " << thread_string;
248 return PROCESS_ERROR_GETTING_THREAD;
249 }
250
251 uint32_t thread_id;
252 if (!thread->GetThreadID(&thread_id)) {
253 BPLOG(ERROR) << "Could not get thread ID for " << thread_string;
254 return PROCESS_ERROR_GETTING_THREAD_ID;
255 }
256
257 thread_string += " id " + HexString(thread_id);
258 auto thread_name_iter = thread_id_to_name.find(thread_id);
259 string thread_name;
260 if (thread_name_iter != thread_id_to_name.end()) {
261 thread_name = thread_name_iter->second;
262 }
263 if (!thread_name.empty()) {
264 thread_string += " name [" + thread_name + "]";
265 }
266 BPLOG(INFO) << "Looking at thread " << thread_string;
267
268 // If this thread is the thread that produced the minidump, don't process
269 // it. Because of the problems associated with a thread producing a
270 // dump of itself (when both its context and its stack are in flux),
271 // processing that stack wouldn't provide much useful data.
272 if (has_dump_thread && thread_id == dump_thread_id) {
273 continue;
274 }
275
276 MinidumpContext* context = thread->GetContext();
277
278 if (has_requesting_thread && thread_id == requesting_thread_id) {
279 if (found_requesting_thread) {
280 // There can't be more than one requesting thread.
281 BPLOG(ERROR) << "Duplicate requesting thread: " << thread_string;
282 return PROCESS_ERROR_DUPLICATE_REQUESTING_THREADS;
283 }
284
285 // Use processed_state->threads_.size() instead of thread_index.
286 // thread_index points to the thread index in the minidump, which
287 // might be greater than the thread index in the threads vector if
288 // any of the minidump's threads are skipped and not placed into the
289 // processed threads vector. The thread vector's current size will
290 // be the index of the current thread when it's pushed into the
291 // vector.
292 process_state->requesting_thread_ = process_state->threads_.size();
293
294 found_requesting_thread = true;
295
296 if (process_state->crashed_) {
297 // Use the exception record's context for the crashed thread, instead
298 // of the thread's own context. For the crashed thread, the thread's
299 // own context is the state inside the exception handler. Using it
300 // would not result in the expected stack trace from the time of the
301 // crash. If the exception context is invalid, however, we fall back
302 // on the thread context.
303 MinidumpContext* ctx = exception->GetContext();
304 context = ctx ? ctx : thread->GetContext();
305 }
306 }
307
308 // If the memory region for the stack cannot be read using the RVA stored
309 // in the memory descriptor inside MINIDUMP_THREAD, try to locate and use
310 // a memory region (containing the stack) from the minidump memory list.
311 MinidumpMemoryRegion* thread_memory = thread->GetMemory();
312 if (!thread_memory && memory_list) {
313 uint64_t start_stack_memory_range = thread->GetStartOfStackMemoryRange();
314 if (start_stack_memory_range) {
315 thread_memory = memory_list->GetMemoryRegionForAddress(
316 start_stack_memory_range);
317 }
318 }
319 if (!thread_memory) {
320 BPLOG(ERROR) << "No memory region for " << thread_string;
321 }
322
323 // Use process_state->modules_ instead of module_list, because the
324 // |modules| argument will be used to populate the |module| fields in
325 // the returned StackFrame objects, which will be placed into the
326 // returned ProcessState object. module_list's lifetime is only as
327 // long as the Minidump object: it will be deleted when this function
328 // returns. process_state->modules_ is owned by the ProcessState object
329 // (just like the StackFrame objects), and is much more suitable for this
330 // task.
331 scoped_ptr<Stackwalker> stackwalker(
332 Stackwalker::StackwalkerForCPU(process_state->system_info(),
333 context,
334 thread_memory,
335 process_state->modules_,
336 process_state->unloaded_modules_,
337 frame_symbolizer_));
338
339 scoped_ptr<CallStack> stack(new CallStack());
340 if (stackwalker.get()) {
341 if (!stackwalker->Walk(stack.get(),
342 &process_state->modules_without_symbols_,
343 &process_state->modules_with_corrupt_symbols_)) {
344 BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at "
345 << thread_string;
346 interrupted = true;
347 }
348 } else {
349 // Threads with missing CPU contexts will hit this, but
350 // don't abort processing the rest of the dump just for
351 // one bad thread.
352 BPLOG(ERROR) << "No stackwalker for " << thread_string;
353 }
354 stack->set_tid(thread_id);
355 process_state->threads_.push_back(stack.release());
356 process_state->thread_memory_regions_.push_back(thread_memory);
357 process_state->thread_names_.push_back(thread_name);
358 }
359
360 if (interrupted) {
361 BPLOG(INFO) << "Processing interrupted for " << dump->path();
362 return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED;
363 }
364
365 // If a requesting thread was indicated, it must be present.
366 if (has_requesting_thread && !found_requesting_thread) {
367 // Don't mark as an error, but invalidate the requesting thread
368 BPLOG(ERROR) << "Minidump indicated requesting thread " <<
369 HexString(requesting_thread_id) << ", not found in " <<
370 dump->path();
371 process_state->requesting_thread_ = -1;
372 }
373
374 // Exploitability defaults to EXPLOITABILITY_NOT_ANALYZED
375 process_state->exploitability_ = EXPLOITABILITY_NOT_ANALYZED;
376
377 // If an exploitability run was requested we perform the platform specific
378 // rating.
379 if (enable_exploitability_) {
380 scoped_ptr<Exploitability> exploitability(
381 Exploitability::ExploitabilityForPlatform(
382 dump, process_state, enable_objdump_for_exploitability_));
383 // The engine will be null if the platform is not supported
384 if (exploitability != NULL) {
385 process_state->exploitability_ = exploitability->CheckExploitability();
386 } else {
387 process_state->exploitability_ = EXPLOITABILITY_ERR_NOENGINE;
388 }
389 }
390
391 BPLOG(INFO) << "Processed " << dump->path();
392 return PROCESS_OK;
393 }
394
Process(const string & minidump_file,ProcessState * process_state)395 ProcessResult MinidumpProcessor::Process(
396 const string& minidump_file, ProcessState* process_state) {
397 BPLOG(INFO) << "Processing minidump in file " << minidump_file;
398
399 Minidump dump(minidump_file);
400 if (!dump.Read()) {
401 BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read";
402 return PROCESS_ERROR_MINIDUMP_NOT_FOUND;
403 }
404
405 return Process(&dump, process_state);
406 }
407
408 // Returns the MDRawSystemInfo from a minidump, or NULL if system info is
409 // not available from the minidump. If system_info is non-NULL, it is used
410 // to pass back the MinidumpSystemInfo object.
GetSystemInfo(Minidump * dump,MinidumpSystemInfo ** system_info)411 static const MDRawSystemInfo* GetSystemInfo(Minidump* dump,
412 MinidumpSystemInfo** system_info) {
413 MinidumpSystemInfo* minidump_system_info = dump->GetSystemInfo();
414 if (!minidump_system_info)
415 return NULL;
416
417 if (system_info)
418 *system_info = minidump_system_info;
419
420 return minidump_system_info->system_info();
421 }
422
GetAddressForArchitecture(const MDCPUArchitecture architecture,size_t raw_address)423 static uint64_t GetAddressForArchitecture(const MDCPUArchitecture architecture,
424 size_t raw_address)
425 {
426 switch (architecture) {
427 case MD_CPU_ARCHITECTURE_X86:
428 case MD_CPU_ARCHITECTURE_MIPS:
429 case MD_CPU_ARCHITECTURE_PPC:
430 case MD_CPU_ARCHITECTURE_SHX:
431 case MD_CPU_ARCHITECTURE_ARM:
432 case MD_CPU_ARCHITECTURE_X86_WIN64:
433 // 32-bit architectures, mask the upper bits.
434 return raw_address & 0xffffffffULL;
435
436 default:
437 // All other architectures either have 64-bit pointers or it's impossible
438 // to tell from the minidump (e.g. MSIL or SPARC) so use 64-bits anyway.
439 return raw_address;
440 }
441 }
442
443 // Extract CPU info string from ARM-specific MDRawSystemInfo structure.
444 // raw_info: pointer to source MDRawSystemInfo.
445 // cpu_info: address of target string, cpu info text will be appended to it.
GetARMCpuInfo(const MDRawSystemInfo * raw_info,string * cpu_info)446 static void GetARMCpuInfo(const MDRawSystemInfo* raw_info,
447 string* cpu_info) {
448 assert(raw_info != NULL && cpu_info != NULL);
449
450 // Write ARM architecture version.
451 char cpu_string[32];
452 snprintf(cpu_string, sizeof(cpu_string), "ARMv%d",
453 raw_info->processor_level);
454 cpu_info->append(cpu_string);
455
456 // There is no good list of implementer id values, but the following
457 // pages provide some help:
458 // http://comments.gmane.org/gmane.linux.linaro.devel/6903
459 // http://forum.xda-developers.com/archive/index.php/t-480226.html
460 const struct {
461 uint32_t id;
462 const char* name;
463 } vendors[] = {
464 { 0x41, "ARM" },
465 { 0x51, "Qualcomm" },
466 { 0x56, "Marvell" },
467 { 0x69, "Intel/Marvell" },
468 };
469 const struct {
470 uint32_t id;
471 const char* name;
472 } parts[] = {
473 { 0x4100c050, "Cortex-A5" },
474 { 0x4100c080, "Cortex-A8" },
475 { 0x4100c090, "Cortex-A9" },
476 { 0x4100c0f0, "Cortex-A15" },
477 { 0x4100c140, "Cortex-R4" },
478 { 0x4100c150, "Cortex-R5" },
479 { 0x4100b360, "ARM1136" },
480 { 0x4100b560, "ARM1156" },
481 { 0x4100b760, "ARM1176" },
482 { 0x4100b020, "ARM11-MPCore" },
483 { 0x41009260, "ARM926" },
484 { 0x41009460, "ARM946" },
485 { 0x41009660, "ARM966" },
486 { 0x510006f0, "Krait" },
487 { 0x510000f0, "Scorpion" },
488 };
489
490 const struct {
491 uint32_t hwcap;
492 const char* name;
493 } features[] = {
494 { MD_CPU_ARM_ELF_HWCAP_SWP, "swp" },
495 { MD_CPU_ARM_ELF_HWCAP_HALF, "half" },
496 { MD_CPU_ARM_ELF_HWCAP_THUMB, "thumb" },
497 { MD_CPU_ARM_ELF_HWCAP_26BIT, "26bit" },
498 { MD_CPU_ARM_ELF_HWCAP_FAST_MULT, "fastmult" },
499 { MD_CPU_ARM_ELF_HWCAP_FPA, "fpa" },
500 { MD_CPU_ARM_ELF_HWCAP_VFP, "vfpv2" },
501 { MD_CPU_ARM_ELF_HWCAP_EDSP, "edsp" },
502 { MD_CPU_ARM_ELF_HWCAP_JAVA, "java" },
503 { MD_CPU_ARM_ELF_HWCAP_IWMMXT, "iwmmxt" },
504 { MD_CPU_ARM_ELF_HWCAP_CRUNCH, "crunch" },
505 { MD_CPU_ARM_ELF_HWCAP_THUMBEE, "thumbee" },
506 { MD_CPU_ARM_ELF_HWCAP_NEON, "neon" },
507 { MD_CPU_ARM_ELF_HWCAP_VFPv3, "vfpv3" },
508 { MD_CPU_ARM_ELF_HWCAP_VFPv3D16, "vfpv3d16" },
509 { MD_CPU_ARM_ELF_HWCAP_TLS, "tls" },
510 { MD_CPU_ARM_ELF_HWCAP_VFPv4, "vfpv4" },
511 { MD_CPU_ARM_ELF_HWCAP_IDIVA, "idiva" },
512 { MD_CPU_ARM_ELF_HWCAP_IDIVT, "idivt" },
513 };
514
515 uint32_t cpuid = raw_info->cpu.arm_cpu_info.cpuid;
516 if (cpuid != 0) {
517 // Extract vendor name from CPUID
518 const char* vendor = NULL;
519 uint32_t vendor_id = (cpuid >> 24) & 0xff;
520 for (size_t i = 0; i < sizeof(vendors)/sizeof(vendors[0]); ++i) {
521 if (vendors[i].id == vendor_id) {
522 vendor = vendors[i].name;
523 break;
524 }
525 }
526 cpu_info->append(" ");
527 if (vendor) {
528 cpu_info->append(vendor);
529 } else {
530 snprintf(cpu_string, sizeof(cpu_string), "vendor(0x%x)", vendor_id);
531 cpu_info->append(cpu_string);
532 }
533
534 // Extract part name from CPUID
535 uint32_t part_id = (cpuid & 0xff00fff0);
536 const char* part = NULL;
537 for (size_t i = 0; i < sizeof(parts)/sizeof(parts[0]); ++i) {
538 if (parts[i].id == part_id) {
539 part = parts[i].name;
540 break;
541 }
542 }
543 cpu_info->append(" ");
544 if (part != NULL) {
545 cpu_info->append(part);
546 } else {
547 snprintf(cpu_string, sizeof(cpu_string), "part(0x%x)", part_id);
548 cpu_info->append(cpu_string);
549 }
550 }
551 uint32_t elf_hwcaps = raw_info->cpu.arm_cpu_info.elf_hwcaps;
552 if (elf_hwcaps != 0) {
553 cpu_info->append(" features: ");
554 const char* comma = "";
555 for (size_t i = 0; i < sizeof(features)/sizeof(features[0]); ++i) {
556 if (elf_hwcaps & features[i].hwcap) {
557 cpu_info->append(comma);
558 cpu_info->append(features[i].name);
559 comma = ",";
560 }
561 }
562 }
563 }
564
565 // static
GetCPUInfo(Minidump * dump,SystemInfo * info)566 bool MinidumpProcessor::GetCPUInfo(Minidump* dump, SystemInfo* info) {
567 assert(dump);
568 assert(info);
569
570 info->cpu.clear();
571 info->cpu_info.clear();
572
573 MinidumpSystemInfo* system_info;
574 const MDRawSystemInfo* raw_system_info = GetSystemInfo(dump, &system_info);
575 if (!raw_system_info)
576 return false;
577
578 switch (raw_system_info->processor_architecture) {
579 case MD_CPU_ARCHITECTURE_X86:
580 case MD_CPU_ARCHITECTURE_AMD64: {
581 if (raw_system_info->processor_architecture ==
582 MD_CPU_ARCHITECTURE_X86)
583 info->cpu = "x86";
584 else
585 info->cpu = "amd64";
586
587 const string* cpu_vendor = system_info->GetCPUVendor();
588 if (cpu_vendor) {
589 info->cpu_info = *cpu_vendor;
590 info->cpu_info.append(" ");
591 }
592
593 char x86_info[36];
594 snprintf(x86_info, sizeof(x86_info), "family %u model %u stepping %u",
595 raw_system_info->processor_level,
596 raw_system_info->processor_revision >> 8,
597 raw_system_info->processor_revision & 0xff);
598 info->cpu_info.append(x86_info);
599 break;
600 }
601
602 case MD_CPU_ARCHITECTURE_PPC: {
603 info->cpu = "ppc";
604 break;
605 }
606
607 case MD_CPU_ARCHITECTURE_PPC64: {
608 info->cpu = "ppc64";
609 break;
610 }
611
612 case MD_CPU_ARCHITECTURE_SPARC: {
613 info->cpu = "sparc";
614 break;
615 }
616
617 case MD_CPU_ARCHITECTURE_ARM: {
618 info->cpu = "arm";
619 GetARMCpuInfo(raw_system_info, &info->cpu_info);
620 break;
621 }
622
623 case MD_CPU_ARCHITECTURE_ARM64:
624 case MD_CPU_ARCHITECTURE_ARM64_OLD: {
625 info->cpu = "arm64";
626 break;
627 }
628
629 case MD_CPU_ARCHITECTURE_MIPS: {
630 info->cpu = "mips";
631 break;
632 }
633 case MD_CPU_ARCHITECTURE_MIPS64: {
634 info->cpu = "mips64";
635 break;
636 }
637
638 case MD_CPU_ARCHITECTURE_RISCV: {
639 info->cpu = "riscv";
640 break;
641 }
642
643 case MD_CPU_ARCHITECTURE_RISCV64: {
644 info->cpu = "riscv64";
645 break;
646 }
647
648 default: {
649 // Assign the numeric architecture ID into the CPU string.
650 char cpu_string[7];
651 snprintf(cpu_string, sizeof(cpu_string), "0x%04x",
652 raw_system_info->processor_architecture);
653 info->cpu = cpu_string;
654 break;
655 }
656 }
657
658 info->cpu_count = raw_system_info->number_of_processors;
659
660 return true;
661 }
662
663 // static
GetOSInfo(Minidump * dump,SystemInfo * info)664 bool MinidumpProcessor::GetOSInfo(Minidump* dump, SystemInfo* info) {
665 assert(dump);
666 assert(info);
667
668 info->os.clear();
669 info->os_short.clear();
670 info->os_version.clear();
671
672 MinidumpSystemInfo* system_info;
673 const MDRawSystemInfo* raw_system_info = GetSystemInfo(dump, &system_info);
674 if (!raw_system_info)
675 return false;
676
677 info->os_short = system_info->GetOS();
678
679 switch (raw_system_info->platform_id) {
680 case MD_OS_WIN32_NT: {
681 info->os = "Windows NT";
682 break;
683 }
684
685 case MD_OS_WIN32_WINDOWS: {
686 info->os = "Windows";
687 break;
688 }
689
690 case MD_OS_MAC_OS_X: {
691 info->os = "Mac OS X";
692 break;
693 }
694
695 case MD_OS_IOS: {
696 info->os = "iOS";
697 break;
698 }
699
700 case MD_OS_LINUX: {
701 info->os = "Linux";
702 break;
703 }
704
705 case MD_OS_SOLARIS: {
706 info->os = "Solaris";
707 break;
708 }
709
710 case MD_OS_ANDROID: {
711 info->os = "Android";
712 break;
713 }
714
715 case MD_OS_PS3: {
716 info->os = "PS3";
717 break;
718 }
719
720 case MD_OS_NACL: {
721 info->os = "NaCl";
722 break;
723 }
724
725 case MD_OS_FUCHSIA: {
726 info->os = "Fuchsia";
727 break;
728 }
729
730 default: {
731 // Assign the numeric platform ID into the OS string.
732 char os_string[11];
733 snprintf(os_string, sizeof(os_string), "0x%08x",
734 raw_system_info->platform_id);
735 info->os = os_string;
736 break;
737 }
738 }
739
740 char os_version_string[33];
741 snprintf(os_version_string, sizeof(os_version_string), "%u.%u.%u",
742 raw_system_info->major_version,
743 raw_system_info->minor_version,
744 raw_system_info->build_number);
745 info->os_version = os_version_string;
746
747 const string* csd_version = system_info->GetCSDVersion();
748 if (csd_version) {
749 info->os_version.append(" ");
750 info->os_version.append(*csd_version);
751 }
752
753 return true;
754 }
755
756 // static
GetProcessCreateTime(Minidump * dump,uint32_t * process_create_time)757 bool MinidumpProcessor::GetProcessCreateTime(Minidump* dump,
758 uint32_t* process_create_time) {
759 assert(dump);
760 assert(process_create_time);
761
762 *process_create_time = 0;
763
764 MinidumpMiscInfo* minidump_misc_info = dump->GetMiscInfo();
765 if (!minidump_misc_info) {
766 return false;
767 }
768
769 const MDRawMiscInfo* md_raw_misc_info = minidump_misc_info->misc_info();
770 if (!md_raw_misc_info) {
771 return false;
772 }
773
774 if (!(md_raw_misc_info->flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES)) {
775 return false;
776 }
777
778 *process_create_time = md_raw_misc_info->process_create_time;
779 return true;
780 }
781
782 #ifdef __linux__
783
IsCanonicalAddress(uint64_t address)784 static bool IsCanonicalAddress(uint64_t address) {
785 uint64_t sign_bit = (address >> 63) & 1;
786 for (int shift = 48; shift < 63; ++shift) {
787 if (sign_bit != ((address >> shift) & 1)) {
788 return false;
789 }
790 }
791 return true;
792 }
793
CalculateFaultAddressFromInstruction(Minidump * dump,uint64_t * address)794 static void CalculateFaultAddressFromInstruction(Minidump* dump,
795 uint64_t* address) {
796 MinidumpException* exception = dump->GetException();
797 if (exception == NULL) {
798 BPLOG(INFO) << "Failed to get exception.";
799 return;
800 }
801
802 MinidumpContext* context = exception->GetContext();
803 if (context == NULL) {
804 BPLOG(INFO) << "Failed to get exception context.";
805 return;
806 }
807
808 uint64_t instruction_ptr = 0;
809 if (!context->GetInstructionPointer(&instruction_ptr)) {
810 BPLOG(INFO) << "Failed to get instruction pointer.";
811 return;
812 }
813
814 // Get memory region containing instruction pointer.
815 MinidumpMemoryList* memory_list = dump->GetMemoryList();
816 MinidumpMemoryRegion* memory_region =
817 memory_list ?
818 memory_list->GetMemoryRegionForAddress(instruction_ptr) : NULL;
819 if (!memory_region) {
820 BPLOG(INFO) << "No memory region around instruction pointer.";
821 return;
822 }
823
824 DisassemblerObjdump disassembler(context->GetContextCPU(), memory_region,
825 instruction_ptr);
826 fprintf(stderr, "%s %s %s\n", disassembler.operation().c_str(),
827 disassembler.src().c_str(), disassembler.dest().c_str());
828 if (!disassembler.IsValid()) {
829 BPLOG(INFO) << "Disassembling fault instruction failed.";
830 return;
831 }
832
833 // It's possible that we reach here when the faulting address is already
834 // correct, so we only update it if we find that at least one of the src/dest
835 // addresses is non-canonical. If both are non-canonical, we arbitrarily set
836 // it to the larger of the two, as this is more likely to be a known poison
837 // value.
838
839 bool valid_read, valid_write;
840 uint64_t read_address, write_address;
841
842 valid_read = disassembler.CalculateSrcAddress(*context, read_address);
843 valid_read &= !IsCanonicalAddress(read_address);
844
845 valid_write = disassembler.CalculateDestAddress(*context, write_address);
846 valid_write &= !IsCanonicalAddress(write_address);
847
848 if (valid_read && valid_write) {
849 *address = read_address > write_address ? read_address : write_address;
850 } else if (valid_read) {
851 *address = read_address;
852 } else if (valid_write) {
853 *address = write_address;
854 }
855 }
856 #endif // __linux__
857
858 // static
GetCrashReason(Minidump * dump,uint64_t * address,bool enable_objdump)859 string MinidumpProcessor::GetCrashReason(Minidump* dump, uint64_t* address,
860 bool enable_objdump) {
861 MinidumpException* exception = dump->GetException();
862 if (!exception)
863 return "";
864
865 const MDRawExceptionStream* raw_exception = exception->exception();
866 if (!raw_exception)
867 return "";
868
869 if (address)
870 *address = raw_exception->exception_record.exception_address;
871
872 // The reason value is OS-specific and possibly CPU-specific. Set up
873 // sensible numeric defaults for the reason string in case we can't
874 // map the codes to a string (because there's no system info, or because
875 // it's an unrecognized platform, or because it's an unrecognized code.)
876 char reason_string[24];
877 char flags_string[11];
878 uint32_t exception_code = raw_exception->exception_record.exception_code;
879 uint32_t exception_flags = raw_exception->exception_record.exception_flags;
880 snprintf(flags_string, sizeof(flags_string), "0x%08x", exception_flags);
881 snprintf(reason_string, sizeof(reason_string), "0x%08x / %s", exception_code,
882 flags_string);
883 string reason = reason_string;
884
885 const MDRawSystemInfo* raw_system_info = GetSystemInfo(dump, NULL);
886 if (!raw_system_info)
887 return reason;
888
889 switch (raw_system_info->platform_id) {
890 case MD_OS_FUCHSIA: {
891 switch (exception_code) {
892 case MD_EXCEPTION_CODE_FUCHSIA_GENERAL:
893 reason = "GENERAL / ";
894 reason.append(flags_string);
895 break;
896 case MD_EXCEPTION_CODE_FUCHSIA_FATAL_PAGE_FAULT:
897 reason = "FATAL_PAGE_FAULT / ";
898 reason.append(flags_string);
899 break;
900 case MD_EXCEPTION_CODE_FUCHSIA_UNDEFINED_INSTRUCTION:
901 reason = "UNDEFINED_INSTRUCTION / ";
902 reason.append(flags_string);
903 break;
904 case MD_EXCEPTION_CODE_FUCHSIA_SW_BREAKPOINT:
905 reason = "SW_BREAKPOINT / ";
906 reason.append(flags_string);
907 break;
908 case MD_EXCEPTION_CODE_FUCHSIA_HW_BREAKPOINT:
909 reason = "HW_BREAKPOINT / ";
910 reason.append(flags_string);
911 break;
912 case MD_EXCEPTION_CODE_FUCHSIA_UNALIGNED_ACCESS:
913 reason = "UNALIGNED_ACCESS / ";
914 reason.append(flags_string);
915 break;
916 case MD_EXCEPTION_CODE_FUCHSIA_THREAD_STARTING:
917 reason = "THREAD_STARTING / ";
918 reason.append(flags_string);
919 break;
920 case MD_EXCEPTION_CODE_FUCHSIA_THREAD_EXITING:
921 reason = "THREAD_EXITING / ";
922 reason.append(flags_string);
923 break;
924 case MD_EXCEPTION_CODE_FUCHSIA_POLICY_ERROR:
925 reason = "POLICY_ERROR / ";
926 reason.append(flags_string);
927 break;
928 case MD_EXCEPTION_CODE_FUCHSIA_PROCESS_STARTING:
929 reason = "PROCESS_STARTING / ";
930 reason.append(flags_string);
931 break;
932 default:
933 BPLOG(INFO) << "Unknown exception reason " << reason;
934 }
935 break;
936 }
937
938 case MD_OS_MAC_OS_X:
939 case MD_OS_IOS: {
940 switch (exception_code) {
941 case MD_EXCEPTION_MAC_BAD_ACCESS:
942 reason = "EXC_BAD_ACCESS / ";
943 switch (exception_flags) {
944 case MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS:
945 reason.append("KERN_INVALID_ADDRESS");
946 break;
947 case MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE:
948 reason.append("KERN_PROTECTION_FAILURE");
949 break;
950 case MD_EXCEPTION_CODE_MAC_NO_ACCESS:
951 reason.append("KERN_NO_ACCESS");
952 break;
953 case MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE:
954 reason.append("KERN_MEMORY_FAILURE");
955 break;
956 case MD_EXCEPTION_CODE_MAC_MEMORY_ERROR:
957 reason.append("KERN_MEMORY_ERROR");
958 break;
959 case MD_EXCEPTION_CODE_MAC_CODESIGN_ERROR:
960 reason.append("KERN_CODESIGN_ERROR");
961 break;
962 default:
963 // arm and ppc overlap
964 if (raw_system_info->processor_architecture ==
965 MD_CPU_ARCHITECTURE_ARM ||
966 raw_system_info->processor_architecture ==
967 MD_CPU_ARCHITECTURE_ARM64_OLD) {
968 switch (exception_flags) {
969 case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN:
970 reason.append("EXC_ARM_DA_ALIGN");
971 break;
972 case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG:
973 reason.append("EXC_ARM_DA_DEBUG");
974 break;
975 default:
976 reason.append(flags_string);
977 BPLOG(INFO) << "Unknown exception reason " << reason;
978 break;
979 }
980 } else if (raw_system_info->processor_architecture ==
981 MD_CPU_ARCHITECTURE_PPC) {
982 switch (exception_flags) {
983 case MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ:
984 reason.append("EXC_PPC_VM_PROT_READ");
985 break;
986 case MD_EXCEPTION_CODE_MAC_PPC_BADSPACE:
987 reason.append("EXC_PPC_BADSPACE");
988 break;
989 case MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED:
990 reason.append("EXC_PPC_UNALIGNED");
991 break;
992 default:
993 reason.append(flags_string);
994 BPLOG(INFO) << "Unknown exception reason " << reason;
995 break;
996 }
997 } else if (raw_system_info->processor_architecture ==
998 MD_CPU_ARCHITECTURE_X86 ||
999 raw_system_info->processor_architecture ==
1000 MD_CPU_ARCHITECTURE_AMD64) {
1001 switch (exception_flags) {
1002 case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT:
1003 reason.append("EXC_I386_GPFLT");
1004 break;
1005 default:
1006 reason.append(flags_string);
1007 BPLOG(INFO) << "Unknown exception reason " << reason;
1008 break;
1009 }
1010 } else {
1011 reason.append(flags_string);
1012 BPLOG(INFO) << "Unknown exception reason " << reason;
1013 }
1014 break;
1015 }
1016 break;
1017 case MD_EXCEPTION_MAC_BAD_INSTRUCTION:
1018 reason = "EXC_BAD_INSTRUCTION / ";
1019 switch (raw_system_info->processor_architecture) {
1020 case MD_CPU_ARCHITECTURE_ARM:
1021 case MD_CPU_ARCHITECTURE_ARM64_OLD: {
1022 switch (exception_flags) {
1023 case MD_EXCEPTION_CODE_MAC_ARM_UNDEFINED:
1024 reason.append("EXC_ARM_UNDEFINED");
1025 break;
1026 default:
1027 reason.append(flags_string);
1028 BPLOG(INFO) << "Unknown exception reason " << reason;
1029 break;
1030 }
1031 break;
1032 }
1033 case MD_CPU_ARCHITECTURE_PPC: {
1034 switch (exception_flags) {
1035 case MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL:
1036 reason.append("EXC_PPC_INVALID_SYSCALL");
1037 break;
1038 case MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION:
1039 reason.append("EXC_PPC_UNIPL_INST");
1040 break;
1041 case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION:
1042 reason.append("EXC_PPC_PRIVINST");
1043 break;
1044 case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER:
1045 reason.append("EXC_PPC_PRIVREG");
1046 break;
1047 case MD_EXCEPTION_CODE_MAC_PPC_TRACE:
1048 reason.append("EXC_PPC_TRACE");
1049 break;
1050 case MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR:
1051 reason.append("EXC_PPC_PERFMON");
1052 break;
1053 default:
1054 reason.append(flags_string);
1055 BPLOG(INFO) << "Unknown exception reason " << reason;
1056 break;
1057 }
1058 break;
1059 }
1060 case MD_CPU_ARCHITECTURE_AMD64:
1061 case MD_CPU_ARCHITECTURE_X86: {
1062 switch (exception_flags) {
1063 case MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION:
1064 reason.append("EXC_I386_INVOP");
1065 break;
1066 case MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT:
1067 reason.append("EXC_I386_INVTSSFLT");
1068 break;
1069 case MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT:
1070 reason.append("EXC_I386_SEGNPFLT");
1071 break;
1072 case MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT:
1073 reason.append("EXC_I386_STKFLT");
1074 break;
1075 case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT:
1076 reason.append("EXC_I386_GPFLT");
1077 break;
1078 case MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT:
1079 reason.append("EXC_I386_ALIGNFLT");
1080 break;
1081 default:
1082 reason.append(flags_string);
1083 BPLOG(INFO) << "Unknown exception reason " << reason;
1084 break;
1085 }
1086 break;
1087 }
1088 default:
1089 reason.append(flags_string);
1090 BPLOG(INFO) << "Unknown exception reason " << reason;
1091 break;
1092 }
1093 break;
1094 case MD_EXCEPTION_MAC_ARITHMETIC:
1095 reason = "EXC_ARITHMETIC / ";
1096 switch (raw_system_info->processor_architecture) {
1097 case MD_CPU_ARCHITECTURE_PPC: {
1098 switch (exception_flags) {
1099 case MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW:
1100 reason.append("EXC_PPC_OVERFLOW");
1101 break;
1102 case MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE:
1103 reason.append("EXC_PPC_ZERO_DIVIDE");
1104 break;
1105 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT:
1106 reason.append("EXC_FLT_INEXACT");
1107 break;
1108 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE:
1109 reason.append("EXC_PPC_FLT_ZERO_DIVIDE");
1110 break;
1111 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW:
1112 reason.append("EXC_PPC_FLT_UNDERFLOW");
1113 break;
1114 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW:
1115 reason.append("EXC_PPC_FLT_OVERFLOW");
1116 break;
1117 case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER:
1118 reason.append("EXC_PPC_FLT_NOT_A_NUMBER");
1119 break;
1120 case MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION:
1121 reason.append("EXC_PPC_NOEMULATION");
1122 break;
1123 case MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST:
1124 reason.append("EXC_PPC_ALTIVECASSIST");
1125 break;
1126 default:
1127 reason.append(flags_string);
1128 BPLOG(INFO) << "Unknown exception reason " << reason;
1129 break;
1130 }
1131 break;
1132 }
1133 case MD_CPU_ARCHITECTURE_AMD64:
1134 case MD_CPU_ARCHITECTURE_X86: {
1135 switch (exception_flags) {
1136 case MD_EXCEPTION_CODE_MAC_X86_DIV:
1137 reason.append("EXC_I386_DIV");
1138 break;
1139 case MD_EXCEPTION_CODE_MAC_X86_INTO:
1140 reason.append("EXC_I386_INTO");
1141 break;
1142 case MD_EXCEPTION_CODE_MAC_X86_NOEXT:
1143 reason.append("EXC_I386_NOEXT");
1144 break;
1145 case MD_EXCEPTION_CODE_MAC_X86_EXTOVR:
1146 reason.append("EXC_I386_EXTOVR");
1147 break;
1148 case MD_EXCEPTION_CODE_MAC_X86_EXTERR:
1149 reason.append("EXC_I386_EXTERR");
1150 break;
1151 case MD_EXCEPTION_CODE_MAC_X86_EMERR:
1152 reason.append("EXC_I386_EMERR");
1153 break;
1154 case MD_EXCEPTION_CODE_MAC_X86_BOUND:
1155 reason.append("EXC_I386_BOUND");
1156 break;
1157 case MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR:
1158 reason.append("EXC_I386_SSEEXTERR");
1159 break;
1160 default:
1161 reason.append(flags_string);
1162 BPLOG(INFO) << "Unknown exception reason " << reason;
1163 break;
1164 }
1165 break;
1166 }
1167 default:
1168 reason.append(flags_string);
1169 BPLOG(INFO) << "Unknown exception reason " << reason;
1170 break;
1171 }
1172 break;
1173 case MD_EXCEPTION_MAC_EMULATION:
1174 reason = "EXC_EMULATION / ";
1175 reason.append(flags_string);
1176 break;
1177 case MD_EXCEPTION_MAC_SOFTWARE:
1178 reason = "EXC_SOFTWARE / ";
1179 switch (exception_flags) {
1180 case MD_EXCEPTION_CODE_MAC_ABORT:
1181 reason.append("SIGABRT");
1182 break;
1183 case MD_EXCEPTION_CODE_MAC_NS_EXCEPTION:
1184 reason.append("UNCAUGHT_NS_EXCEPTION");
1185 break;
1186 // These are ppc only but shouldn't be a problem as they're
1187 // unused on x86
1188 case MD_EXCEPTION_CODE_MAC_PPC_TRAP:
1189 reason.append("EXC_PPC_TRAP");
1190 break;
1191 case MD_EXCEPTION_CODE_MAC_PPC_MIGRATE:
1192 reason.append("EXC_PPC_MIGRATE");
1193 break;
1194 default:
1195 reason.append(flags_string);
1196 BPLOG(INFO) << "Unknown exception reason " << reason;
1197 break;
1198 }
1199 break;
1200 case MD_EXCEPTION_MAC_BREAKPOINT:
1201 reason = "EXC_BREAKPOINT / ";
1202 switch (raw_system_info->processor_architecture) {
1203 case MD_CPU_ARCHITECTURE_ARM:
1204 case MD_CPU_ARCHITECTURE_ARM64_OLD: {
1205 switch (exception_flags) {
1206 case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN:
1207 reason.append("EXC_ARM_DA_ALIGN");
1208 break;
1209 case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG:
1210 reason.append("EXC_ARM_DA_DEBUG");
1211 break;
1212 case MD_EXCEPTION_CODE_MAC_ARM_BREAKPOINT:
1213 reason.append("EXC_ARM_BREAKPOINT");
1214 break;
1215 default:
1216 reason.append(flags_string);
1217 BPLOG(INFO) << "Unknown exception reason " << reason;
1218 break;
1219 }
1220 break;
1221 }
1222 case MD_CPU_ARCHITECTURE_PPC: {
1223 switch (exception_flags) {
1224 case MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT:
1225 reason.append("EXC_PPC_BREAKPOINT");
1226 break;
1227 default:
1228 reason.append(flags_string);
1229 BPLOG(INFO) << "Unknown exception reason " << reason;
1230 break;
1231 }
1232 break;
1233 }
1234 case MD_CPU_ARCHITECTURE_AMD64:
1235 case MD_CPU_ARCHITECTURE_X86: {
1236 switch (exception_flags) {
1237 case MD_EXCEPTION_CODE_MAC_X86_SGL:
1238 reason.append("EXC_I386_SGL");
1239 break;
1240 case MD_EXCEPTION_CODE_MAC_X86_BPT:
1241 reason.append("EXC_I386_BPT");
1242 break;
1243 default:
1244 reason.append(flags_string);
1245 BPLOG(INFO) << "Unknown exception reason " << reason;
1246 break;
1247 }
1248 break;
1249 }
1250 default:
1251 reason.append(flags_string);
1252 BPLOG(INFO) << "Unknown exception reason " << reason;
1253 break;
1254 }
1255 break;
1256 case MD_EXCEPTION_MAC_SYSCALL:
1257 reason = "EXC_SYSCALL / ";
1258 reason.append(flags_string);
1259 break;
1260 case MD_EXCEPTION_MAC_MACH_SYSCALL:
1261 reason = "EXC_MACH_SYSCALL / ";
1262 reason.append(flags_string);
1263 break;
1264 case MD_EXCEPTION_MAC_RPC_ALERT:
1265 reason = "EXC_RPC_ALERT / ";
1266 reason.append(flags_string);
1267 break;
1268 case MD_EXCEPTION_MAC_RESOURCE:
1269 reason = "EXC_RESOURCE / ";
1270 reason.append(flags_string);
1271 break;
1272 case MD_EXCEPTION_MAC_GUARD:
1273 reason = "EXC_GUARD / ";
1274 reason.append(flags_string);
1275 break;
1276 case MD_EXCEPTION_MAC_SIMULATED:
1277 reason = "Simulated Exception";
1278 break;
1279 case MD_NS_EXCEPTION_SIMULATED:
1280 reason = "Uncaught NSException";
1281 break;
1282 }
1283 break;
1284 }
1285
1286 case MD_OS_WIN32_NT:
1287 case MD_OS_WIN32_WINDOWS: {
1288 switch (exception_code) {
1289 case MD_EXCEPTION_CODE_WIN_CONTROL_C:
1290 reason = "DBG_CONTROL_C";
1291 break;
1292 case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION:
1293 reason = "EXCEPTION_GUARD_PAGE";
1294 break;
1295 case MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT:
1296 reason = "EXCEPTION_DATATYPE_MISALIGNMENT";
1297 break;
1298 case MD_EXCEPTION_CODE_WIN_BREAKPOINT:
1299 reason = "EXCEPTION_BREAKPOINT";
1300 break;
1301 case MD_EXCEPTION_CODE_WIN_SINGLE_STEP:
1302 reason = "EXCEPTION_SINGLE_STEP";
1303 break;
1304 case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION:
1305 // For EXCEPTION_ACCESS_VIOLATION, Windows puts the address that
1306 // caused the fault in exception_information[1].
1307 // exception_information[0] is 0 if the violation was caused by
1308 // an attempt to read data, 1 if it was an attempt to write data,
1309 // and 8 if this was a data execution violation.
1310 // This information is useful in addition to the code address, which
1311 // will be present in the crash thread's instruction field anyway.
1312 if (raw_exception->exception_record.number_parameters >= 1) {
1313 MDAccessViolationTypeWin av_type =
1314 static_cast<MDAccessViolationTypeWin>
1315 (raw_exception->exception_record.exception_information[0]);
1316 switch (av_type) {
1317 case MD_ACCESS_VIOLATION_WIN_READ:
1318 reason = "EXCEPTION_ACCESS_VIOLATION_READ";
1319 break;
1320 case MD_ACCESS_VIOLATION_WIN_WRITE:
1321 reason = "EXCEPTION_ACCESS_VIOLATION_WRITE";
1322 break;
1323 case MD_ACCESS_VIOLATION_WIN_EXEC:
1324 reason = "EXCEPTION_ACCESS_VIOLATION_EXEC";
1325 break;
1326 default:
1327 reason = "EXCEPTION_ACCESS_VIOLATION";
1328 break;
1329 }
1330 } else {
1331 reason = "EXCEPTION_ACCESS_VIOLATION";
1332 }
1333 if (address &&
1334 raw_exception->exception_record.number_parameters >= 2) {
1335 *address =
1336 raw_exception->exception_record.exception_information[1];
1337 }
1338 break;
1339 case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR:
1340 // For EXCEPTION_IN_PAGE_ERROR, Windows puts the address that
1341 // caused the fault in exception_information[1].
1342 // exception_information[0] is 0 if the violation was caused by
1343 // an attempt to read data, 1 if it was an attempt to write data,
1344 // and 8 if this was a data execution violation.
1345 // exception_information[2] contains the underlying NTSTATUS code,
1346 // which is the explanation for why this error occured.
1347 // This information is useful in addition to the code address, which
1348 // will be present in the crash thread's instruction field anyway.
1349 if (raw_exception->exception_record.number_parameters >= 1) {
1350 MDInPageErrorTypeWin av_type =
1351 static_cast<MDInPageErrorTypeWin>
1352 (raw_exception->exception_record.exception_information[0]);
1353 switch (av_type) {
1354 case MD_IN_PAGE_ERROR_WIN_READ:
1355 reason = "EXCEPTION_IN_PAGE_ERROR_READ";
1356 break;
1357 case MD_IN_PAGE_ERROR_WIN_WRITE:
1358 reason = "EXCEPTION_IN_PAGE_ERROR_WRITE";
1359 break;
1360 case MD_IN_PAGE_ERROR_WIN_EXEC:
1361 reason = "EXCEPTION_IN_PAGE_ERROR_EXEC";
1362 break;
1363 default:
1364 reason = "EXCEPTION_IN_PAGE_ERROR";
1365 break;
1366 }
1367 } else {
1368 reason = "EXCEPTION_IN_PAGE_ERROR";
1369 }
1370 if (address &&
1371 raw_exception->exception_record.number_parameters >= 2) {
1372 *address =
1373 raw_exception->exception_record.exception_information[1];
1374 }
1375 if (raw_exception->exception_record.number_parameters >= 3) {
1376 uint32_t ntstatus =
1377 static_cast<uint32_t>
1378 (raw_exception->exception_record.exception_information[2]);
1379 reason.append(" / ");
1380 reason.append(NTStatusToString(ntstatus));
1381 }
1382 break;
1383 case MD_EXCEPTION_CODE_WIN_INVALID_HANDLE:
1384 reason = "EXCEPTION_INVALID_HANDLE";
1385 break;
1386 case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION:
1387 reason = "EXCEPTION_ILLEGAL_INSTRUCTION";
1388 break;
1389 case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION:
1390 reason = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
1391 break;
1392 case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION:
1393 reason = "EXCEPTION_INVALID_DISPOSITION";
1394 break;
1395 case MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED:
1396 reason = "EXCEPTION_BOUNDS_EXCEEDED";
1397 break;
1398 case MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND:
1399 reason = "EXCEPTION_FLT_DENORMAL_OPERAND";
1400 break;
1401 case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO:
1402 reason = "EXCEPTION_FLT_DIVIDE_BY_ZERO";
1403 break;
1404 case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT:
1405 reason = "EXCEPTION_FLT_INEXACT_RESULT";
1406 break;
1407 case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION:
1408 reason = "EXCEPTION_FLT_INVALID_OPERATION";
1409 break;
1410 case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW:
1411 reason = "EXCEPTION_FLT_OVERFLOW";
1412 break;
1413 case MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK:
1414 reason = "EXCEPTION_FLT_STACK_CHECK";
1415 break;
1416 case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW:
1417 reason = "EXCEPTION_FLT_UNDERFLOW";
1418 break;
1419 case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO:
1420 reason = "EXCEPTION_INT_DIVIDE_BY_ZERO";
1421 break;
1422 case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW:
1423 reason = "EXCEPTION_INT_OVERFLOW";
1424 break;
1425 case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION:
1426 reason = "EXCEPTION_PRIV_INSTRUCTION";
1427 break;
1428 case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW:
1429 reason = "EXCEPTION_STACK_OVERFLOW";
1430 break;
1431 case MD_EXCEPTION_CODE_WIN_BAD_FUNCTION_TABLE:
1432 reason = "EXCEPTION_BAD_FUNCTION_TABLE";
1433 break;
1434 case MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK:
1435 reason = "EXCEPTION_POSSIBLE_DEADLOCK";
1436 break;
1437 case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN:
1438 if (raw_exception->exception_record.number_parameters >= 1) {
1439 MDFastFailSubcodeTypeWin subcode =
1440 static_cast<MDFastFailSubcodeTypeWin>(
1441 raw_exception->exception_record.exception_information[0]);
1442 switch (subcode) {
1443 // Note - we skip the '0'/GS case as it exists for legacy reasons.
1444 case MD_FAST_FAIL_VTGUARD_CHECK_FAILURE:
1445 reason = "FAST_FAIL_VTGUARD_CHECK_FAILURE";
1446 break;
1447 case MD_FAST_FAIL_STACK_COOKIE_CHECK_FAILURE:
1448 reason = "FAST_FAIL_STACK_COOKIE_CHECK_FAILURE";
1449 break;
1450 case MD_FAST_FAIL_CORRUPT_LIST_ENTRY:
1451 reason = "FAST_FAIL_CORRUPT_LIST_ENTRY";
1452 break;
1453 case MD_FAST_FAIL_INCORRECT_STACK:
1454 reason = "FAST_FAIL_INCORRECT_STACK";
1455 break;
1456 case MD_FAST_FAIL_INVALID_ARG:
1457 reason = "FAST_FAIL_INVALID_ARG";
1458 break;
1459 case MD_FAST_FAIL_GS_COOKIE_INIT:
1460 reason = "FAST_FAIL_GS_COOKIE_INIT";
1461 break;
1462 case MD_FAST_FAIL_FATAL_APP_EXIT:
1463 reason = "FAST_FAIL_FATAL_APP_EXIT";
1464 break;
1465 case MD_FAST_FAIL_RANGE_CHECK_FAILURE:
1466 reason = "FAST_FAIL_RANGE_CHECK_FAILURE";
1467 break;
1468 case MD_FAST_FAIL_UNSAFE_REGISTRY_ACCESS:
1469 reason = "FAST_FAIL_UNSAFE_REGISTRY_ACCESS";
1470 break;
1471 case MD_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE:
1472 reason = "FAST_FAIL_GUARD_ICALL_CHECK_FAILURE";
1473 break;
1474 case MD_FAST_FAIL_GUARD_WRITE_CHECK_FAILURE:
1475 reason = "FAST_FAIL_GUARD_WRITE_CHECK_FAILURE";
1476 break;
1477 case MD_FAST_FAIL_INVALID_FIBER_SWITCH:
1478 reason = "FAST_FAIL_INVALID_FIBER_SWITCH";
1479 break;
1480 case MD_FAST_FAIL_INVALID_SET_OF_CONTEXT:
1481 reason = "FAST_FAIL_INVALID_SET_OF_CONTEXT";
1482 break;
1483 case MD_FAST_FAIL_INVALID_REFERENCE_COUNT:
1484 reason = "FAST_FAIL_INVALID_REFERENCE_COUNT";
1485 break;
1486 case MD_FAST_FAIL_INVALID_JUMP_BUFFER:
1487 reason = "FAST_FAIL_INVALID_JUMP_BUFFER";
1488 break;
1489 case MD_FAST_FAIL_MRDATA_MODIFIED:
1490 reason = "FAST_FAIL_MRDATA_MODIFIED";
1491 break;
1492 case MD_FAST_FAIL_CERTIFICATION_FAILURE:
1493 reason = "FAST_FAIL_CERTIFICATION_FAILURE";
1494 break;
1495 case MD_FAST_FAIL_INVALID_EXCEPTION_CHAIN:
1496 reason = "FAST_FAIL_INVALID_EXCEPTION_CHAIN";
1497 break;
1498 case MD_FAST_FAIL_CRYPTO_LIBRARY:
1499 reason = "FAST_FAIL_CRYPTO_LIBRARY";
1500 break;
1501 case MD_FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT:
1502 reason = "FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT";
1503 break;
1504 case MD_FAST_FAIL_INVALID_IMAGE_BASE:
1505 reason = "FAST_FAIL_INVALID_IMAGE_BASE";
1506 break;
1507 case MD_FAST_FAIL_DLOAD_PROTECTION_FAILURE:
1508 reason = "FAST_FAIL_DLOAD_PROTECTION_FAILURE";
1509 break;
1510 case MD_FAST_FAIL_UNSAFE_EXTENSION_CALL:
1511 reason = "FAST_FAIL_UNSAFE_EXTENSION_CALL";
1512 break;
1513 case MD_FAST_FAIL_DEPRECATED_SERVICE_INVOKED:
1514 reason = "FAST_FAIL_DEPRECATED_SERVICE_INVOKED";
1515 break;
1516 case MD_FAST_FAIL_INVALID_BUFFER_ACCESS:
1517 reason = "FAST_FAIL_INVALID_BUFFER_ACCESS";
1518 break;
1519 case MD_FAST_FAIL_INVALID_BALANCED_TREE:
1520 reason = "FAST_FAIL_INVALID_BALANCED_TREE";
1521 break;
1522 case MD_FAST_FAIL_INVALID_NEXT_THREAD:
1523 reason = "FAST_FAIL_INVALID_NEXT_THREAD";
1524 break;
1525 case MD_FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED:
1526 reason = "FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED";
1527 break;
1528 case MD_FAST_FAIL_APCS_DISABLED:
1529 reason = "FAST_FAIL_APCS_DISABLED";
1530 break;
1531 case MD_FAST_FAIL_INVALID_IDLE_STATE:
1532 reason = "FAST_FAIL_INVALID_IDLE_STATE";
1533 break;
1534 case MD_FAST_FAIL_MRDATA_PROTECTION_FAILURE:
1535 reason = "FAST_FAIL_MRDATA_PROTECTION_FAILURE";
1536 break;
1537 case MD_FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION:
1538 reason = "FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION";
1539 break;
1540 case MD_FAST_FAIL_INVALID_LOCK_STATE:
1541 reason = "FAST_FAIL_INVALID_LOCK_STATE";
1542 break;
1543 case MD_FAST_FAIL_GUARD_JUMPTABLE:
1544 reason = "FAST_FAIL_GUARD_JUMPTABLE";
1545 break;
1546 case MD_FAST_FAIL_INVALID_LONGJUMP_TARGET:
1547 reason = "FAST_FAIL_INVALID_LONGJUMP_TARGET";
1548 break;
1549 case MD_FAST_FAIL_INVALID_DISPATCH_CONTEXT:
1550 reason = "FAST_FAIL_INVALID_DISPATCH_CONTEXT";
1551 break;
1552 case MD_FAST_FAIL_INVALID_THREAD:
1553 reason = "FAST_FAIL_INVALID_THREAD";
1554 break;
1555 case MD_FAST_FAIL_INVALID_SYSCALL_NUMBER:
1556 reason = "FAST_FAIL_INVALID_SYSCALL_NUMBER";
1557 break;
1558 case MD_FAST_FAIL_INVALID_FILE_OPERATION:
1559 reason = "FAST_FAIL_INVALID_FILE_OPERATION";
1560 break;
1561 case MD_FAST_FAIL_LPAC_ACCESS_DENIED:
1562 reason = "FAST_FAIL_LPAC_ACCESS_DENIED";
1563 break;
1564 case MD_FAST_FAIL_GUARD_SS_FAILURE:
1565 reason = "FAST_FAIL_GUARD_SS_FAILURE";
1566 break;
1567 case MD_FAST_FAIL_LOADER_CONTINUITY_FAILURE:
1568 reason = "FAST_FAIL_LOADER_CONTINUITY_FAILURE";
1569 break;
1570 case MD_FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE:
1571 reason = "FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE";
1572 break;
1573 case MD_FAST_FAIL_INVALID_CONTROL_STACK:
1574 reason = "FAST_FAIL_INVALID_CONTROL_STACK";
1575 break;
1576 case MD_FAST_FAIL_SET_CONTEXT_DENIED:
1577 reason = "FAST_FAIL_SET_CONTEXT_DENIED";
1578 break;
1579 case MD_FAST_FAIL_INVALID_IAT:
1580 reason = "FAST_FAIL_INVALID_IAT";
1581 break;
1582 case MD_FAST_FAIL_HEAP_METADATA_CORRUPTION:
1583 reason = "FAST_FAIL_HEAP_METADATA_CORRUPTION";
1584 break;
1585 case MD_FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION:
1586 reason = "FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION";
1587 break;
1588 case MD_FAST_FAIL_LOW_LABEL_ACCESS_DENIED:
1589 reason = "FAST_FAIL_LOW_LABEL_ACCESS_DENIED";
1590 break;
1591 case MD_FAST_FAIL_ENCLAVE_CALL_FAILURE:
1592 reason = "FAST_FAIL_ENCLAVE_CALL_FAILURE";
1593 break;
1594 case MD_FAST_FAIL_UNHANDLED_LSS_EXCEPTON:
1595 reason = "FAST_FAIL_UNHANDLED_LSS_EXCEPTON";
1596 break;
1597 case MD_FAST_FAIL_ADMINLESS_ACCESS_DENIED:
1598 reason = "FAST_FAIL_ADMINLESS_ACCESS_DENIED";
1599 break;
1600 case MD_FAST_FAIL_UNEXPECTED_CALL:
1601 reason = "FAST_FAIL_UNEXPECTED_CALL";
1602 break;
1603 case MD_FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS:
1604 reason = "FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS";
1605 break;
1606 case MD_FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR:
1607 reason = "FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR";
1608 break;
1609 case MD_FAST_FAIL_FLAGS_CORRUPTION:
1610 reason = "FAST_FAIL_FLAGS_CORRUPTION";
1611 break;
1612 case MD_FAST_FAIL_VEH_CORRUPTION:
1613 reason = "FAST_FAIL_VEH_CORRUPTION";
1614 break;
1615 case MD_FAST_FAIL_ETW_CORRUPTION:
1616 reason = "FAST_FAIL_ETW_CORRUPTION";
1617 break;
1618 case MD_FAST_FAIL_RIO_ABORT:
1619 reason = "FAST_FAIL_RIO_ABORT";
1620 break;
1621 case MD_FAST_FAIL_INVALID_PFN:
1622 reason = "FAST_FAIL_INVALID_PFN";
1623 break;
1624 case MD_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE_XFG:
1625 reason = "FAST_FAIL_GUARD_ICALL_CHECK_FAILURE_XFG";
1626 break;
1627 case MD_FAST_FAIL_CAST_GUARD:
1628 reason = "FAST_FAIL_CAST_GUARD";
1629 break;
1630 case MD_FAST_FAIL_HOST_VISIBILITY_CHANGE:
1631 reason = "FAST_FAIL_HOST_VISIBILITY_CHANGE";
1632 break;
1633 case MD_FAST_FAIL_KERNEL_CET_SHADOW_STACK_ASSIST:
1634 reason = "FAST_FAIL_KERNEL_CET_SHADOW_STACK_ASSIST";
1635 break;
1636 case MD_FAST_FAIL_PATCH_CALLBACK_FAILED:
1637 reason = "FAST_FAIL_PATCH_CALLBACK_FAILED";
1638 break;
1639 case MD_FAST_FAIL_NTDLL_PATCH_FAILED:
1640 reason = "FAST_FAIL_NTDLL_PATCH_FAILED";
1641 break;
1642 case MD_FAST_FAIL_INVALID_FLS_DATA:
1643 reason = "FAST_FAIL_INVALID_FLS_DATA";
1644 break;
1645 default:
1646 reason = "EXCEPTION_STACK_BUFFER_OVERRUN";
1647 break;
1648 }
1649 } else {
1650 reason = "EXCEPTION_STACK_BUFFER_OVERRUN";
1651 }
1652 break;
1653 case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION:
1654 reason = "EXCEPTION_HEAP_CORRUPTION";
1655 break;
1656 case MD_EXCEPTION_OUT_OF_MEMORY:
1657 reason = "Out of Memory";
1658 break;
1659 case MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION:
1660 reason = "Unhandled C++ Exception";
1661 break;
1662 case MD_EXCEPTION_CODE_WIN_SIMULATED:
1663 reason = "Simulated Exception";
1664 break;
1665 default:
1666 BPLOG(INFO) << "Unknown exception reason " << reason;
1667 break;
1668 }
1669 break;
1670 }
1671
1672 case MD_OS_ANDROID:
1673 case MD_OS_LINUX: {
1674 switch (exception_code) {
1675 case MD_EXCEPTION_CODE_LIN_SIGHUP:
1676 reason = "SIGHUP";
1677 break;
1678 case MD_EXCEPTION_CODE_LIN_SIGINT:
1679 reason = "SIGINT";
1680 break;
1681 case MD_EXCEPTION_CODE_LIN_SIGQUIT:
1682 reason = "SIGQUIT";
1683 break;
1684 case MD_EXCEPTION_CODE_LIN_SIGILL:
1685 reason = "SIGILL / ";
1686 switch (exception_flags) {
1687 case MD_EXCEPTION_FLAG_LIN_ILL_ILLOPC:
1688 reason.append("ILL_ILLOPC");
1689 break;
1690 case MD_EXCEPTION_FLAG_LIN_ILL_ILLOPN:
1691 reason.append("ILL_ILLOPN");
1692 break;
1693 case MD_EXCEPTION_FLAG_LIN_ILL_ILLADR:
1694 reason.append("ILL_ILLADR");
1695 break;
1696 case MD_EXCEPTION_FLAG_LIN_ILL_ILLTRP:
1697 reason.append("ILL_ILLTRP");
1698 break;
1699 case MD_EXCEPTION_FLAG_LIN_ILL_PRVOPC:
1700 reason.append("ILL_PRVOPC");
1701 break;
1702 case MD_EXCEPTION_FLAG_LIN_ILL_PRVREG:
1703 reason.append("ILL_PRVREG");
1704 break;
1705 case MD_EXCEPTION_FLAG_LIN_ILL_COPROC:
1706 reason.append("ILL_COPROC");
1707 break;
1708 case MD_EXCEPTION_FLAG_LIN_ILL_BADSTK:
1709 reason.append("ILL_BADSTK");
1710 break;
1711 default:
1712 reason.append(flags_string);
1713 BPLOG(INFO) << "Unknown exception reason " << reason;
1714 break;
1715 }
1716 break;
1717 case MD_EXCEPTION_CODE_LIN_SIGTRAP:
1718 reason = "SIGTRAP";
1719 break;
1720 case MD_EXCEPTION_CODE_LIN_SIGABRT:
1721 reason = "SIGABRT";
1722 break;
1723 case MD_EXCEPTION_CODE_LIN_SIGBUS:
1724 reason = "SIGBUS / ";
1725 switch (exception_flags) {
1726 case MD_EXCEPTION_FLAG_LIN_BUS_ADRALN:
1727 reason.append("BUS_ADRALN");
1728 break;
1729 case MD_EXCEPTION_FLAG_LIN_BUS_ADRERR:
1730 reason.append("BUS_ADRERR");
1731 break;
1732 case MD_EXCEPTION_FLAG_LIN_BUS_OBJERR:
1733 reason.append("BUS_OBJERR");
1734 break;
1735 case MD_EXCEPTION_FLAG_LIN_BUS_MCEERR_AR:
1736 reason.append("BUS_MCEERR_AR");
1737 break;
1738 case MD_EXCEPTION_FLAG_LIN_BUS_MCEERR_AO:
1739 reason.append("BUS_MCEERR_AO");
1740 break;
1741 default:
1742 reason.append(flags_string);
1743 BPLOG(INFO) << "Unknown exception reason " << reason;
1744 break;
1745 }
1746 break;
1747 case MD_EXCEPTION_CODE_LIN_SIGFPE:
1748 reason = "SIGFPE / ";
1749 switch (exception_flags) {
1750 case MD_EXCEPTION_FLAG_LIN_FPE_INTDIV:
1751 reason.append("FPE_INTDIV");
1752 break;
1753 case MD_EXCEPTION_FLAG_LIN_FPE_INTOVF:
1754 reason.append("FPE_INTOVF");
1755 break;
1756 case MD_EXCEPTION_FLAG_LIN_FPE_FLTDIV:
1757 reason.append("FPE_FLTDIV");
1758 break;
1759 case MD_EXCEPTION_FLAG_LIN_FPE_FLTOVF:
1760 reason.append("FPE_FLTOVF");
1761 break;
1762 case MD_EXCEPTION_FLAG_LIN_FPE_FLTUND:
1763 reason.append("FPE_FLTUND");
1764 break;
1765 case MD_EXCEPTION_FLAG_LIN_FPE_FLTRES:
1766 reason.append("FPE_FLTRES");
1767 break;
1768 case MD_EXCEPTION_FLAG_LIN_FPE_FLTINV:
1769 reason.append("FPE_FLTINV");
1770 break;
1771 case MD_EXCEPTION_FLAG_LIN_FPE_FLTSUB:
1772 reason.append("FPE_FLTSUB");
1773 break;
1774 default:
1775 reason.append(flags_string);
1776 BPLOG(INFO) << "Unknown exception reason " << reason;
1777 break;
1778 }
1779 break;
1780 case MD_EXCEPTION_CODE_LIN_SIGKILL:
1781 reason = "SIGKILL";
1782 break;
1783 case MD_EXCEPTION_CODE_LIN_SIGUSR1:
1784 reason = "SIGUSR1";
1785 break;
1786 case MD_EXCEPTION_CODE_LIN_SIGSEGV:
1787 reason = "SIGSEGV /";
1788 switch (exception_flags) {
1789 case MD_EXCEPTION_FLAG_LIN_SEGV_MAPERR:
1790 reason.append("SEGV_MAPERR");
1791 break;
1792 case MD_EXCEPTION_FLAG_LIN_SEGV_ACCERR:
1793 reason.append("SEGV_ACCERR");
1794 break;
1795 case MD_EXCEPTION_FLAG_LIN_SEGV_BNDERR:
1796 reason.append("SEGV_BNDERR");
1797 break;
1798 case MD_EXCEPTION_FLAG_LIN_SEGV_PKUERR:
1799 reason.append("SEGV_PKUERR");
1800 break;
1801 case MD_EXCEPTION_FLAG_LIN_SEGV_ACCADI:
1802 reason.append("SEGV_ACCADI");
1803 break;
1804 case MD_EXCEPTION_FLAG_LIN_SEGV_ADIDERR:
1805 reason.append("SEGV_ADIDERR");
1806 break;
1807 case MD_EXCEPTION_FLAG_LIN_SEGV_ADIPERR:
1808 reason.append("SEGV_ADIPERR");
1809 break;
1810 case MD_EXCEPTION_FLAG_LIN_SEGV_MTEAERR:
1811 reason.append("SEGV_MTEAERR");
1812 break;
1813 case MD_EXCEPTION_FLAG_LIN_SEGV_MTESERR:
1814 reason.append("SEGV_MTESERR");
1815 break;
1816 default:
1817 reason.append(flags_string);
1818 BPLOG(INFO) << "Unknown exception reason " << reason;
1819 break;
1820 }
1821 break;
1822 case MD_EXCEPTION_CODE_LIN_SIGUSR2:
1823 reason = "SIGUSR2";
1824 break;
1825 case MD_EXCEPTION_CODE_LIN_SIGPIPE:
1826 reason = "SIGPIPE";
1827 break;
1828 case MD_EXCEPTION_CODE_LIN_SIGALRM:
1829 reason = "SIGALRM";
1830 break;
1831 case MD_EXCEPTION_CODE_LIN_SIGTERM:
1832 reason = "SIGTERM";
1833 break;
1834 case MD_EXCEPTION_CODE_LIN_SIGSTKFLT:
1835 reason = "SIGSTKFLT";
1836 break;
1837 case MD_EXCEPTION_CODE_LIN_SIGCHLD:
1838 reason = "SIGCHLD";
1839 break;
1840 case MD_EXCEPTION_CODE_LIN_SIGCONT:
1841 reason = "SIGCONT";
1842 break;
1843 case MD_EXCEPTION_CODE_LIN_SIGSTOP:
1844 reason = "SIGSTOP";
1845 break;
1846 case MD_EXCEPTION_CODE_LIN_SIGTSTP:
1847 reason = "SIGTSTP";
1848 break;
1849 case MD_EXCEPTION_CODE_LIN_SIGTTIN:
1850 reason = "SIGTTIN";
1851 break;
1852 case MD_EXCEPTION_CODE_LIN_SIGTTOU:
1853 reason = "SIGTTOU";
1854 break;
1855 case MD_EXCEPTION_CODE_LIN_SIGURG:
1856 reason = "SIGURG";
1857 break;
1858 case MD_EXCEPTION_CODE_LIN_SIGXCPU:
1859 reason = "SIGXCPU";
1860 break;
1861 case MD_EXCEPTION_CODE_LIN_SIGXFSZ:
1862 reason = "SIGXFSZ";
1863 break;
1864 case MD_EXCEPTION_CODE_LIN_SIGVTALRM:
1865 reason = "SIGVTALRM";
1866 break;
1867 case MD_EXCEPTION_CODE_LIN_SIGPROF:
1868 reason = "SIGPROF";
1869 break;
1870 case MD_EXCEPTION_CODE_LIN_SIGWINCH:
1871 reason = "SIGWINCH";
1872 break;
1873 case MD_EXCEPTION_CODE_LIN_SIGIO:
1874 reason = "SIGIO";
1875 break;
1876 case MD_EXCEPTION_CODE_LIN_SIGPWR:
1877 reason = "SIGPWR";
1878 break;
1879 case MD_EXCEPTION_CODE_LIN_SIGSYS:
1880 reason = "SIGSYS";
1881 break;
1882 case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED:
1883 reason = "DUMP_REQUESTED";
1884 break;
1885 default:
1886 BPLOG(INFO) << "Unknown exception reason " << reason;
1887 break;
1888 }
1889 break;
1890 }
1891
1892 case MD_OS_SOLARIS: {
1893 switch (exception_code) {
1894 case MD_EXCEPTION_CODE_SOL_SIGHUP:
1895 reason = "SIGHUP";
1896 break;
1897 case MD_EXCEPTION_CODE_SOL_SIGINT:
1898 reason = "SIGINT";
1899 break;
1900 case MD_EXCEPTION_CODE_SOL_SIGQUIT:
1901 reason = "SIGQUIT";
1902 break;
1903 case MD_EXCEPTION_CODE_SOL_SIGILL:
1904 reason = "SIGILL";
1905 break;
1906 case MD_EXCEPTION_CODE_SOL_SIGTRAP:
1907 reason = "SIGTRAP";
1908 break;
1909 case MD_EXCEPTION_CODE_SOL_SIGIOT:
1910 reason = "SIGIOT | SIGABRT";
1911 break;
1912 case MD_EXCEPTION_CODE_SOL_SIGEMT:
1913 reason = "SIGEMT";
1914 break;
1915 case MD_EXCEPTION_CODE_SOL_SIGFPE:
1916 reason = "SIGFPE";
1917 break;
1918 case MD_EXCEPTION_CODE_SOL_SIGKILL:
1919 reason = "SIGKILL";
1920 break;
1921 case MD_EXCEPTION_CODE_SOL_SIGBUS:
1922 reason = "SIGBUS";
1923 break;
1924 case MD_EXCEPTION_CODE_SOL_SIGSEGV:
1925 reason = "SIGSEGV";
1926 break;
1927 case MD_EXCEPTION_CODE_SOL_SIGSYS:
1928 reason = "SIGSYS";
1929 break;
1930 case MD_EXCEPTION_CODE_SOL_SIGPIPE:
1931 reason = "SIGPIPE";
1932 break;
1933 case MD_EXCEPTION_CODE_SOL_SIGALRM:
1934 reason = "SIGALRM";
1935 break;
1936 case MD_EXCEPTION_CODE_SOL_SIGTERM:
1937 reason = "SIGTERM";
1938 break;
1939 case MD_EXCEPTION_CODE_SOL_SIGUSR1:
1940 reason = "SIGUSR1";
1941 break;
1942 case MD_EXCEPTION_CODE_SOL_SIGUSR2:
1943 reason = "SIGUSR2";
1944 break;
1945 case MD_EXCEPTION_CODE_SOL_SIGCLD:
1946 reason = "SIGCLD | SIGCHLD";
1947 break;
1948 case MD_EXCEPTION_CODE_SOL_SIGPWR:
1949 reason = "SIGPWR";
1950 break;
1951 case MD_EXCEPTION_CODE_SOL_SIGWINCH:
1952 reason = "SIGWINCH";
1953 break;
1954 case MD_EXCEPTION_CODE_SOL_SIGURG:
1955 reason = "SIGURG";
1956 break;
1957 case MD_EXCEPTION_CODE_SOL_SIGPOLL:
1958 reason = "SIGPOLL | SIGIO";
1959 break;
1960 case MD_EXCEPTION_CODE_SOL_SIGSTOP:
1961 reason = "SIGSTOP";
1962 break;
1963 case MD_EXCEPTION_CODE_SOL_SIGTSTP:
1964 reason = "SIGTSTP";
1965 break;
1966 case MD_EXCEPTION_CODE_SOL_SIGCONT:
1967 reason = "SIGCONT";
1968 break;
1969 case MD_EXCEPTION_CODE_SOL_SIGTTIN:
1970 reason = "SIGTTIN";
1971 break;
1972 case MD_EXCEPTION_CODE_SOL_SIGTTOU:
1973 reason = "SIGTTOU";
1974 break;
1975 case MD_EXCEPTION_CODE_SOL_SIGVTALRM:
1976 reason = "SIGVTALRM";
1977 break;
1978 case MD_EXCEPTION_CODE_SOL_SIGPROF:
1979 reason = "SIGPROF";
1980 break;
1981 case MD_EXCEPTION_CODE_SOL_SIGXCPU:
1982 reason = "SIGXCPU";
1983 break;
1984 case MD_EXCEPTION_CODE_SOL_SIGXFSZ:
1985 reason = "SIGXFSZ";
1986 break;
1987 case MD_EXCEPTION_CODE_SOL_SIGWAITING:
1988 reason = "SIGWAITING";
1989 break;
1990 case MD_EXCEPTION_CODE_SOL_SIGLWP:
1991 reason = "SIGLWP";
1992 break;
1993 case MD_EXCEPTION_CODE_SOL_SIGFREEZE:
1994 reason = "SIGFREEZE";
1995 break;
1996 case MD_EXCEPTION_CODE_SOL_SIGTHAW:
1997 reason = "SIGTHAW";
1998 break;
1999 case MD_EXCEPTION_CODE_SOL_SIGCANCEL:
2000 reason = "SIGCANCEL";
2001 break;
2002 case MD_EXCEPTION_CODE_SOL_SIGLOST:
2003 reason = "SIGLOST";
2004 break;
2005 case MD_EXCEPTION_CODE_SOL_SIGXRES:
2006 reason = "SIGXRES";
2007 break;
2008 case MD_EXCEPTION_CODE_SOL_SIGJVM1:
2009 reason = "SIGJVM1";
2010 break;
2011 case MD_EXCEPTION_CODE_SOL_SIGJVM2:
2012 reason = "SIGJVM2";
2013 break;
2014 default:
2015 BPLOG(INFO) << "Unknown exception reason " << reason;
2016 break;
2017 }
2018 break;
2019 }
2020
2021 case MD_OS_PS3: {
2022 switch (exception_code) {
2023 case MD_EXCEPTION_CODE_PS3_UNKNOWN:
2024 reason = "UNKNOWN";
2025 break;
2026 case MD_EXCEPTION_CODE_PS3_TRAP_EXCEP:
2027 reason = "TRAP_EXCEP";
2028 break;
2029 case MD_EXCEPTION_CODE_PS3_PRIV_INSTR:
2030 reason = "PRIV_INSTR";
2031 break;
2032 case MD_EXCEPTION_CODE_PS3_ILLEGAL_INSTR:
2033 reason = "ILLEGAL_INSTR";
2034 break;
2035 case MD_EXCEPTION_CODE_PS3_INSTR_STORAGE:
2036 reason = "INSTR_STORAGE";
2037 break;
2038 case MD_EXCEPTION_CODE_PS3_INSTR_SEGMENT:
2039 reason = "INSTR_SEGMENT";
2040 break;
2041 case MD_EXCEPTION_CODE_PS3_DATA_STORAGE:
2042 reason = "DATA_STORAGE";
2043 break;
2044 case MD_EXCEPTION_CODE_PS3_DATA_SEGMENT:
2045 reason = "DATA_SEGMENT";
2046 break;
2047 case MD_EXCEPTION_CODE_PS3_FLOAT_POINT:
2048 reason = "FLOAT_POINT";
2049 break;
2050 case MD_EXCEPTION_CODE_PS3_DABR_MATCH:
2051 reason = "DABR_MATCH";
2052 break;
2053 case MD_EXCEPTION_CODE_PS3_ALIGN_EXCEP:
2054 reason = "ALIGN_EXCEP";
2055 break;
2056 case MD_EXCEPTION_CODE_PS3_MEMORY_ACCESS:
2057 reason = "MEMORY_ACCESS";
2058 break;
2059 case MD_EXCEPTION_CODE_PS3_COPRO_ALIGN:
2060 reason = "COPRO_ALIGN";
2061 break;
2062 case MD_EXCEPTION_CODE_PS3_COPRO_INVALID_COM:
2063 reason = "COPRO_INVALID_COM";
2064 break;
2065 case MD_EXCEPTION_CODE_PS3_COPRO_ERR:
2066 reason = "COPRO_ERR";
2067 break;
2068 case MD_EXCEPTION_CODE_PS3_COPRO_FIR:
2069 reason = "COPRO_FIR";
2070 break;
2071 case MD_EXCEPTION_CODE_PS3_COPRO_DATA_SEGMENT:
2072 reason = "COPRO_DATA_SEGMENT";
2073 break;
2074 case MD_EXCEPTION_CODE_PS3_COPRO_DATA_STORAGE:
2075 reason = "COPRO_DATA_STORAGE";
2076 break;
2077 case MD_EXCEPTION_CODE_PS3_COPRO_STOP_INSTR:
2078 reason = "COPRO_STOP_INSTR";
2079 break;
2080 case MD_EXCEPTION_CODE_PS3_COPRO_HALT_INSTR:
2081 reason = "COPRO_HALT_INSTR";
2082 break;
2083 case MD_EXCEPTION_CODE_PS3_COPRO_HALTINST_UNKNOWN:
2084 reason = "COPRO_HALTINSTR_UNKNOWN";
2085 break;
2086 case MD_EXCEPTION_CODE_PS3_COPRO_MEMORY_ACCESS:
2087 reason = "COPRO_MEMORY_ACCESS";
2088 break;
2089 case MD_EXCEPTION_CODE_PS3_GRAPHIC:
2090 reason = "GRAPHIC";
2091 break;
2092 default:
2093 BPLOG(INFO) << "Unknown exception reason "<< reason;
2094 break;
2095 }
2096 break;
2097 }
2098
2099 default: {
2100 BPLOG(INFO) << "Unknown exception reason " << reason;
2101 break;
2102 }
2103 }
2104
2105 if (address) {
2106 *address = GetAddressForArchitecture(
2107 static_cast<MDCPUArchitecture>(raw_system_info->processor_architecture),
2108 *address);
2109
2110 #ifdef __linux__
2111 // For invalid accesses to non-canonical addresses, amd64 cpus don't provide
2112 // the fault address, so recover it from the disassembly and register state
2113 // if possible.
2114 if (enable_objdump
2115 && raw_system_info->processor_architecture == MD_CPU_ARCHITECTURE_AMD64
2116 && std::numeric_limits<uint64_t>::max() == *address) {
2117 CalculateFaultAddressFromInstruction(dump, address);
2118 }
2119 #endif // __linux__
2120 }
2121
2122 return reason;
2123 }
2124
2125 // static
GetAssertion(Minidump * dump)2126 string MinidumpProcessor::GetAssertion(Minidump* dump) {
2127 MinidumpAssertion* assertion = dump->GetAssertion();
2128 if (!assertion)
2129 return "";
2130
2131 const MDRawAssertionInfo* raw_assertion = assertion->assertion();
2132 if (!raw_assertion)
2133 return "";
2134
2135 string assertion_string;
2136 switch (raw_assertion->type) {
2137 case MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER:
2138 assertion_string = "Invalid parameter passed to library function";
2139 break;
2140 case MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL:
2141 assertion_string = "Pure virtual function called";
2142 break;
2143 default: {
2144 char assertion_type[32];
2145 snprintf(assertion_type, sizeof(assertion_type),
2146 "0x%08x", raw_assertion->type);
2147 assertion_string = "Unknown assertion type ";
2148 assertion_string += assertion_type;
2149 break;
2150 }
2151 }
2152
2153 string expression = assertion->expression();
2154 if (!expression.empty()) {
2155 assertion_string.append(" " + expression);
2156 }
2157
2158 string function = assertion->function();
2159 if (!function.empty()) {
2160 assertion_string.append(" in function " + function);
2161 }
2162
2163 string file = assertion->file();
2164 if (!file.empty()) {
2165 assertion_string.append(", in file " + file);
2166 }
2167
2168 if (raw_assertion->line != 0) {
2169 char assertion_line[32];
2170 snprintf(assertion_line, sizeof(assertion_line), "%u", raw_assertion->line);
2171 assertion_string.append(" at line ");
2172 assertion_string.append(assertion_line);
2173 }
2174
2175 return assertion_string;
2176 }
2177
2178 } // namespace google_breakpad
2179