diff options
Diffstat (limited to 'src/processor/minidump_processor.cc')
-rw-r--r-- | src/processor/minidump_processor.cc | 430 |
1 files changed, 387 insertions, 43 deletions
diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc index 4ea4cb70..fb330e26 100644 --- a/src/processor/minidump_processor.cc +++ b/src/processor/minidump_processor.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. +// Copyright 2006 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. -// * Neither the name of Google Inc. nor the names of its +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -31,7 +30,11 @@ #include <assert.h> +#include <algorithm> +#include <limits> +#include <map> #include <string> +#include <utility> #include "common/scoped_ptr.h" #include "common/stdio_wrapper.h" @@ -41,22 +44,23 @@ #include "google_breakpad/processor/process_state.h" #include "google_breakpad/processor/exploitability.h" #include "google_breakpad/processor/stack_frame_symbolizer.h" +#include "processor/disassembler_objdump.h" #include "processor/logging.h" #include "processor/stackwalker_x86.h" #include "processor/symbolic_constants_win.h" namespace google_breakpad { -MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier, - SourceLineResolverInterface *resolver) +MinidumpProcessor::MinidumpProcessor(SymbolSupplier* supplier, + SourceLineResolverInterface* resolver) : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)), own_frame_symbolizer_(true), enable_exploitability_(false), enable_objdump_(false) { } -MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier, - SourceLineResolverInterface *resolver, +MinidumpProcessor::MinidumpProcessor(SymbolSupplier* supplier, + SourceLineResolverInterface* resolver, bool enable_exploitability) : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)), own_frame_symbolizer_(true), @@ -64,7 +68,7 @@ MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier, enable_objdump_(false) { } -MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer *frame_symbolizer, +MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer* frame_symbolizer, bool enable_exploitability) : frame_symbolizer_(frame_symbolizer), own_frame_symbolizer_(false), @@ -78,13 +82,13 @@ MinidumpProcessor::~MinidumpProcessor() { } ProcessResult MinidumpProcessor::Process( - Minidump *dump, ProcessState *process_state) { + Minidump* dump, ProcessState* process_state) { assert(dump); assert(process_state); process_state->Clear(); - const MDRawHeader *header = dump->header(); + const MDRawHeader* header = dump->header(); if (!header) { BPLOG(ERROR) << "Minidump " << dump->path() << " has no header"; return PROCESS_ERROR_NO_MINIDUMP_HEADER; @@ -102,20 +106,20 @@ ProcessResult MinidumpProcessor::Process( uint32_t requesting_thread_id = 0; bool has_requesting_thread = false; - MinidumpBreakpadInfo *breakpad_info = dump->GetBreakpadInfo(); + MinidumpBreakpadInfo* breakpad_info = dump->GetBreakpadInfo(); if (breakpad_info) { has_dump_thread = breakpad_info->GetDumpThreadID(&dump_thread_id); has_requesting_thread = breakpad_info->GetRequestingThreadID(&requesting_thread_id); } - MinidumpException *exception = dump->GetException(); + MinidumpException* exception = dump->GetException(); if (exception) { process_state->crashed_ = true; has_requesting_thread = exception->GetThreadID(&requesting_thread_id); process_state->crash_reason_ = GetCrashReason( - dump, &process_state->crash_address_); + dump, &process_state->crash_address_, enable_objdump_); process_state->exception_record_.set_code( exception->exception()->exception_record.exception_code, @@ -128,8 +132,10 @@ ProcessResult MinidumpProcessor::Process( process_state->exception_record_.set_nested_exception_record_address( exception->exception()->exception_record.exception_record); process_state->exception_record_.set_address(process_state->crash_address_); - for (uint32_t i = 0; - i < exception->exception()->exception_record.number_parameters; i++) { + const uint32_t num_parameters = + std::min(exception->exception()->exception_record.number_parameters, + MD_EXCEPTION_MAXIMUM_PARAMETERS); + for (uint32_t i = 0; i < num_parameters; ++i) { process_state->exception_record_.add_parameter( exception->exception()->exception_record.exception_information[i], // TODO(ivanpe): Populate description. @@ -140,7 +146,7 @@ ProcessResult MinidumpProcessor::Process( // This will just return an empty string if it doesn't exist. process_state->assertion_ = GetAssertion(dump); - MinidumpModuleList *module_list = dump->GetModuleList(); + MinidumpModuleList* module_list = dump->GetModuleList(); // Put a copy of the module list into ProcessState object. This is not // necessarily a MinidumpModuleList, but it adheres to the CodeModules @@ -160,19 +166,19 @@ ProcessResult MinidumpProcessor::Process( } } - MinidumpUnloadedModuleList *unloaded_module_list = + MinidumpUnloadedModuleList* unloaded_module_list = dump->GetUnloadedModuleList(); if (unloaded_module_list) { process_state->unloaded_modules_ = unloaded_module_list->Copy(); } - MinidumpMemoryList *memory_list = dump->GetMemoryList(); + MinidumpMemoryList* memory_list = dump->GetMemoryList(); if (memory_list) { BPLOG(INFO) << "Found " << memory_list->region_count() << " memory regions."; } - MinidumpThreadList *threads = dump->GetThreadList(); + MinidumpThreadList* threads = dump->GetThreadList(); if (!threads) { BPLOG(ERROR) << "Minidump " << dump->path() << " has no thread list"; return PROCESS_ERROR_NO_THREAD_LIST; @@ -196,6 +202,28 @@ ProcessResult MinidumpProcessor::Process( // Reset frame_symbolizer_ at the beginning of stackwalk for each minidump. frame_symbolizer_->Reset(); + + MinidumpThreadNameList* thread_names = dump->GetThreadNameList(); + std::map<uint32_t, string> thread_id_to_name; + if (thread_names) { + const unsigned int thread_name_count = thread_names->thread_name_count(); + for (unsigned int thread_name_index = 0; + thread_name_index < thread_name_count; + ++thread_name_index) { + MinidumpThreadName* thread_name = thread_names->GetThreadNameAtIndex(thread_name_index); + if (!thread_name) { + BPLOG(ERROR) << "Could not get thread name for thread at index " << thread_name_index; + return PROCESS_ERROR_GETTING_THREAD_NAME; + } + uint32_t thread_id; + if (!thread_name->GetThreadID(&thread_id)) { + BPLOG(ERROR) << "Could not get thread ID for thread at index " << thread_name_index; + return PROCESS_ERROR_GETTING_THREAD_NAME; + } + thread_id_to_name.insert(std::make_pair(thread_id, thread_name->GetThreadName())); + } + } + for (unsigned int thread_index = 0; thread_index < thread_count; ++thread_index) { @@ -204,7 +232,7 @@ ProcessResult MinidumpProcessor::Process( thread_index, thread_count); string thread_string = dump->path() + ":" + thread_string_buffer; - MinidumpThread *thread = threads->GetThreadAtIndex(thread_index); + MinidumpThread* thread = threads->GetThreadAtIndex(thread_index); if (!thread) { BPLOG(ERROR) << "Could not get thread for " << thread_string; return PROCESS_ERROR_GETTING_THREAD; @@ -217,6 +245,14 @@ ProcessResult MinidumpProcessor::Process( } thread_string += " id " + HexString(thread_id); + auto thread_name_iter = thread_id_to_name.find(thread_id); + string thread_name; + if (thread_name_iter != thread_id_to_name.end()) { + thread_name = thread_name_iter->second; + } + if (!thread_name.empty()) { + thread_string += " name [" + thread_name + "]"; + } BPLOG(INFO) << "Looking at thread " << thread_string; // If this thread is the thread that produced the minidump, don't process @@ -227,7 +263,7 @@ ProcessResult MinidumpProcessor::Process( continue; } - MinidumpContext *context = thread->GetContext(); + MinidumpContext* context = thread->GetContext(); if (has_requesting_thread && thread_id == requesting_thread_id) { if (found_requesting_thread) { @@ -254,7 +290,7 @@ ProcessResult MinidumpProcessor::Process( // would not result in the expected stack trace from the time of the // crash. If the exception context is invalid, however, we fall back // on the thread context. - MinidumpContext *ctx = exception->GetContext(); + MinidumpContext* ctx = exception->GetContext(); context = ctx ? ctx : thread->GetContext(); } } @@ -262,7 +298,7 @@ ProcessResult MinidumpProcessor::Process( // If the memory region for the stack cannot be read using the RVA stored // in the memory descriptor inside MINIDUMP_THREAD, try to locate and use // a memory region (containing the stack) from the minidump memory list. - MinidumpMemoryRegion *thread_memory = thread->GetMemory(); + MinidumpMemoryRegion* thread_memory = thread->GetMemory(); if (!thread_memory && memory_list) { uint64_t start_stack_memory_range = thread->GetStartOfStackMemoryRange(); if (start_stack_memory_range) { @@ -308,6 +344,7 @@ ProcessResult MinidumpProcessor::Process( stack->set_tid(thread_id); process_state->threads_.push_back(stack.release()); process_state->thread_memory_regions_.push_back(thread_memory); + process_state->thread_names_.push_back(thread_name); } if (interrupted) { @@ -347,7 +384,7 @@ ProcessResult MinidumpProcessor::Process( } ProcessResult MinidumpProcessor::Process( - const string &minidump_file, ProcessState *process_state) { + const string& minidump_file, ProcessState* process_state) { BPLOG(INFO) << "Processing minidump in file " << minidump_file; Minidump dump(minidump_file); @@ -362,9 +399,9 @@ ProcessResult MinidumpProcessor::Process( // Returns the MDRawSystemInfo from a minidump, or NULL if system info is // not available from the minidump. If system_info is non-NULL, it is used // to pass back the MinidumpSystemInfo object. -static const MDRawSystemInfo* GetSystemInfo(Minidump *dump, - MinidumpSystemInfo **system_info) { - MinidumpSystemInfo *minidump_system_info = dump->GetSystemInfo(); +static const MDRawSystemInfo* GetSystemInfo(Minidump* dump, + MinidumpSystemInfo** system_info) { + MinidumpSystemInfo* minidump_system_info = dump->GetSystemInfo(); if (!minidump_system_info) return NULL; @@ -517,15 +554,15 @@ static void GetARMCpuInfo(const MDRawSystemInfo* raw_info, } // static -bool MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) { +bool MinidumpProcessor::GetCPUInfo(Minidump* dump, SystemInfo* info) { assert(dump); assert(info); info->cpu.clear(); info->cpu_info.clear(); - MinidumpSystemInfo *system_info; - const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info); + MinidumpSystemInfo* system_info; + const MDRawSystemInfo* raw_system_info = GetSystemInfo(dump, &system_info); if (!raw_system_info) return false; @@ -538,7 +575,7 @@ bool MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) { else info->cpu = "amd64"; - const string *cpu_vendor = system_info->GetCPUVendor(); + const string* cpu_vendor = system_info->GetCPUVendor(); if (cpu_vendor) { info->cpu_info = *cpu_vendor; info->cpu_info.append(" "); @@ -605,7 +642,7 @@ bool MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) { } // static -bool MinidumpProcessor::GetOSInfo(Minidump *dump, SystemInfo *info) { +bool MinidumpProcessor::GetOSInfo(Minidump* dump, SystemInfo* info) { assert(dump); assert(info); @@ -613,8 +650,8 @@ bool MinidumpProcessor::GetOSInfo(Minidump *dump, SystemInfo *info) { info->os_short.clear(); info->os_version.clear(); - MinidumpSystemInfo *system_info; - const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info); + MinidumpSystemInfo* system_info; + const MDRawSystemInfo* raw_system_info = GetSystemInfo(dump, &system_info); if (!raw_system_info) return false; @@ -688,7 +725,7 @@ bool MinidumpProcessor::GetOSInfo(Minidump *dump, SystemInfo *info) { raw_system_info->build_number); info->os_version = os_version_string; - const string *csd_version = system_info->GetCSDVersion(); + const string* csd_version = system_info->GetCSDVersion(); if (csd_version) { info->os_version.append(" "); info->os_version.append(*csd_version); @@ -723,13 +760,87 @@ bool MinidumpProcessor::GetProcessCreateTime(Minidump* dump, return true; } +static bool IsCanonicalAddress(uint64_t address) { + uint64_t sign_bit = (address >> 63) & 1; + for (int shift = 48; shift < 63; ++shift) { + if (sign_bit != ((address >> shift) & 1)) { + return false; + } + } + return true; +} + +static void CalculateFaultAddressFromInstruction(Minidump* dump, + uint64_t* address) { + MinidumpException* exception = dump->GetException(); + if (exception == NULL) { + BPLOG(INFO) << "Failed to get exception."; + return; + } + + MinidumpContext* context = exception->GetContext(); + if (context == NULL) { + BPLOG(INFO) << "Failed to get exception context."; + return; + } + + uint64_t instruction_ptr = 0; + if (!context->GetInstructionPointer(&instruction_ptr)) { + BPLOG(INFO) << "Failed to get instruction pointer."; + return; + } + + // Get memory region containing instruction pointer. + MinidumpMemoryList* memory_list = dump->GetMemoryList(); + MinidumpMemoryRegion* memory_region = + memory_list ? + memory_list->GetMemoryRegionForAddress(instruction_ptr) : NULL; + if (!memory_region) { + BPLOG(INFO) << "No memory region around instruction pointer."; + return; + } + + DisassemblerObjdump disassembler(context->GetContextCPU(), memory_region, + instruction_ptr); + fprintf(stderr, "%s %s %s\n", disassembler.operation().c_str(), + disassembler.src().c_str(), disassembler.dest().c_str()); + if (!disassembler.IsValid()) { + BPLOG(INFO) << "Disassembling fault instruction failed."; + return; + } + + // It's possible that we reach here when the faulting address is already + // correct, so we only update it if we find that at least one of the src/dest + // addresses is non-canonical. If both are non-canonical, we arbitrarily set + // it to the larger of the two, as this is more likely to be a known poison + // value. + + bool valid_read, valid_write; + uint64_t read_address, write_address; + + valid_read = disassembler.CalculateSrcAddress(*context, read_address); + valid_read &= !IsCanonicalAddress(read_address); + + valid_write = disassembler.CalculateDestAddress(*context, write_address); + valid_write &= !IsCanonicalAddress(write_address); + + if (valid_read && valid_write) { + *address = read_address > write_address ? read_address : write_address; + } else if (valid_read) { + *address = read_address; + } else if (valid_write) { + *address = write_address; + } +} + // static -string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) { - MinidumpException *exception = dump->GetException(); +string MinidumpProcessor::GetCrashReason(Minidump* dump, uint64_t* address, + bool enable_objdump) { + MinidumpException* exception = dump->GetException(); if (!exception) return ""; - const MDRawExceptionStream *raw_exception = exception->exception(); + const MDRawExceptionStream* raw_exception = exception->exception(); if (!raw_exception) return ""; @@ -749,7 +860,7 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) { flags_string); string reason = reason_string; - const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, NULL); + const MDRawSystemInfo* raw_system_info = GetSystemInfo(dump, NULL); if (!raw_system_info) return reason; @@ -1132,9 +1243,20 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) { reason = "EXC_RPC_ALERT / "; reason.append(flags_string); break; + case MD_EXCEPTION_MAC_RESOURCE: + reason = "EXC_RESOURCE / "; + reason.append(flags_string); + break; + case MD_EXCEPTION_MAC_GUARD: + reason = "EXC_GUARD / "; + reason.append(flags_string); + break; case MD_EXCEPTION_MAC_SIMULATED: reason = "Simulated Exception"; break; + case MD_NS_EXCEPTION_SIMULATED: + reason = "Uncaught NSException"; + break; } break; } @@ -1291,7 +1413,220 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) { reason = "EXCEPTION_POSSIBLE_DEADLOCK"; break; case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN: - reason = "EXCEPTION_STACK_BUFFER_OVERRUN"; + if (raw_exception->exception_record.number_parameters >= 1) { + MDFastFailSubcodeTypeWin subcode = + static_cast<MDFastFailSubcodeTypeWin>( + raw_exception->exception_record.exception_information[0]); + switch (subcode) { + // Note - we skip the '0'/GS case as it exists for legacy reasons. + case MD_FAST_FAIL_VTGUARD_CHECK_FAILURE: + reason = "FAST_FAIL_VTGUARD_CHECK_FAILURE"; + break; + case MD_FAST_FAIL_STACK_COOKIE_CHECK_FAILURE: + reason = "FAST_FAIL_STACK_COOKIE_CHECK_FAILURE"; + break; + case MD_FAST_FAIL_CORRUPT_LIST_ENTRY: + reason = "FAST_FAIL_CORRUPT_LIST_ENTRY"; + break; + case MD_FAST_FAIL_INCORRECT_STACK: + reason = "FAST_FAIL_INCORRECT_STACK"; + break; + case MD_FAST_FAIL_INVALID_ARG: + reason = "FAST_FAIL_INVALID_ARG"; + break; + case MD_FAST_FAIL_GS_COOKIE_INIT: + reason = "FAST_FAIL_GS_COOKIE_INIT"; + break; + case MD_FAST_FAIL_FATAL_APP_EXIT: + reason = "FAST_FAIL_FATAL_APP_EXIT"; + break; + case MD_FAST_FAIL_RANGE_CHECK_FAILURE: + reason = "FAST_FAIL_RANGE_CHECK_FAILURE"; + break; + case MD_FAST_FAIL_UNSAFE_REGISTRY_ACCESS: + reason = "FAST_FAIL_UNSAFE_REGISTRY_ACCESS"; + break; + case MD_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE: + reason = "FAST_FAIL_GUARD_ICALL_CHECK_FAILURE"; + break; + case MD_FAST_FAIL_GUARD_WRITE_CHECK_FAILURE: + reason = "FAST_FAIL_GUARD_WRITE_CHECK_FAILURE"; + break; + case MD_FAST_FAIL_INVALID_FIBER_SWITCH: + reason = "FAST_FAIL_INVALID_FIBER_SWITCH"; + break; + case MD_FAST_FAIL_INVALID_SET_OF_CONTEXT: + reason = "FAST_FAIL_INVALID_SET_OF_CONTEXT"; + break; + case MD_FAST_FAIL_INVALID_REFERENCE_COUNT: + reason = "FAST_FAIL_INVALID_REFERENCE_COUNT"; + break; + case MD_FAST_FAIL_INVALID_JUMP_BUFFER: + reason = "FAST_FAIL_INVALID_JUMP_BUFFER"; + break; + case MD_FAST_FAIL_MRDATA_MODIFIED: + reason = "FAST_FAIL_MRDATA_MODIFIED"; + break; + case MD_FAST_FAIL_CERTIFICATION_FAILURE: + reason = "FAST_FAIL_CERTIFICATION_FAILURE"; + break; + case MD_FAST_FAIL_INVALID_EXCEPTION_CHAIN: + reason = "FAST_FAIL_INVALID_EXCEPTION_CHAIN"; + break; + case MD_FAST_FAIL_CRYPTO_LIBRARY: + reason = "FAST_FAIL_CRYPTO_LIBRARY"; + break; + case MD_FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT: + reason = "FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT"; + break; + case MD_FAST_FAIL_INVALID_IMAGE_BASE: + reason = "FAST_FAIL_INVALID_IMAGE_BASE"; + break; + case MD_FAST_FAIL_DLOAD_PROTECTION_FAILURE: + reason = "FAST_FAIL_DLOAD_PROTECTION_FAILURE"; + break; + case MD_FAST_FAIL_UNSAFE_EXTENSION_CALL: + reason = "FAST_FAIL_UNSAFE_EXTENSION_CALL"; + break; + case MD_FAST_FAIL_DEPRECATED_SERVICE_INVOKED: + reason = "FAST_FAIL_DEPRECATED_SERVICE_INVOKED"; + break; + case MD_FAST_FAIL_INVALID_BUFFER_ACCESS: + reason = "FAST_FAIL_INVALID_BUFFER_ACCESS"; + break; + case MD_FAST_FAIL_INVALID_BALANCED_TREE: + reason = "FAST_FAIL_INVALID_BALANCED_TREE"; + break; + case MD_FAST_FAIL_INVALID_NEXT_THREAD: + reason = "FAST_FAIL_INVALID_NEXT_THREAD"; + break; + case MD_FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED: + reason = "FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED"; + break; + case MD_FAST_FAIL_APCS_DISABLED: + reason = "FAST_FAIL_APCS_DISABLED"; + break; + case MD_FAST_FAIL_INVALID_IDLE_STATE: + reason = "FAST_FAIL_INVALID_IDLE_STATE"; + break; + case MD_FAST_FAIL_MRDATA_PROTECTION_FAILURE: + reason = "FAST_FAIL_MRDATA_PROTECTION_FAILURE"; + break; + case MD_FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION: + reason = "FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION"; + break; + case MD_FAST_FAIL_INVALID_LOCK_STATE: + reason = "FAST_FAIL_INVALID_LOCK_STATE"; + break; + case MD_FAST_FAIL_GUARD_JUMPTABLE: + reason = "FAST_FAIL_GUARD_JUMPTABLE"; + break; + case MD_FAST_FAIL_INVALID_LONGJUMP_TARGET: + reason = "FAST_FAIL_INVALID_LONGJUMP_TARGET"; + break; + case MD_FAST_FAIL_INVALID_DISPATCH_CONTEXT: + reason = "FAST_FAIL_INVALID_DISPATCH_CONTEXT"; + break; + case MD_FAST_FAIL_INVALID_THREAD: + reason = "FAST_FAIL_INVALID_THREAD"; + break; + case MD_FAST_FAIL_INVALID_SYSCALL_NUMBER: + reason = "FAST_FAIL_INVALID_SYSCALL_NUMBER"; + break; + case MD_FAST_FAIL_INVALID_FILE_OPERATION: + reason = "FAST_FAIL_INVALID_FILE_OPERATION"; + break; + case MD_FAST_FAIL_LPAC_ACCESS_DENIED: + reason = "FAST_FAIL_LPAC_ACCESS_DENIED"; + break; + case MD_FAST_FAIL_GUARD_SS_FAILURE: + reason = "FAST_FAIL_GUARD_SS_FAILURE"; + break; + case MD_FAST_FAIL_LOADER_CONTINUITY_FAILURE: + reason = "FAST_FAIL_LOADER_CONTINUITY_FAILURE"; + break; + case MD_FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE: + reason = "FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE"; + break; + case MD_FAST_FAIL_INVALID_CONTROL_STACK: + reason = "FAST_FAIL_INVALID_CONTROL_STACK"; + break; + case MD_FAST_FAIL_SET_CONTEXT_DENIED: + reason = "FAST_FAIL_SET_CONTEXT_DENIED"; + break; + case MD_FAST_FAIL_INVALID_IAT: + reason = "FAST_FAIL_INVALID_IAT"; + break; + case MD_FAST_FAIL_HEAP_METADATA_CORRUPTION: + reason = "FAST_FAIL_HEAP_METADATA_CORRUPTION"; + break; + case MD_FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION: + reason = "FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION"; + break; + case MD_FAST_FAIL_LOW_LABEL_ACCESS_DENIED: + reason = "FAST_FAIL_LOW_LABEL_ACCESS_DENIED"; + break; + case MD_FAST_FAIL_ENCLAVE_CALL_FAILURE: + reason = "FAST_FAIL_ENCLAVE_CALL_FAILURE"; + break; + case MD_FAST_FAIL_UNHANDLED_LSS_EXCEPTON: + reason = "FAST_FAIL_UNHANDLED_LSS_EXCEPTON"; + break; + case MD_FAST_FAIL_ADMINLESS_ACCESS_DENIED: + reason = "FAST_FAIL_ADMINLESS_ACCESS_DENIED"; + break; + case MD_FAST_FAIL_UNEXPECTED_CALL: + reason = "FAST_FAIL_UNEXPECTED_CALL"; + break; + case MD_FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS: + reason = "FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS"; + break; + case MD_FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR: + reason = "FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR"; + break; + case MD_FAST_FAIL_FLAGS_CORRUPTION: + reason = "FAST_FAIL_FLAGS_CORRUPTION"; + break; + case MD_FAST_FAIL_VEH_CORRUPTION: + reason = "FAST_FAIL_VEH_CORRUPTION"; + break; + case MD_FAST_FAIL_ETW_CORRUPTION: + reason = "FAST_FAIL_ETW_CORRUPTION"; + break; + case MD_FAST_FAIL_RIO_ABORT: + reason = "FAST_FAIL_RIO_ABORT"; + break; + case MD_FAST_FAIL_INVALID_PFN: + reason = "FAST_FAIL_INVALID_PFN"; + break; + case MD_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE_XFG: + reason = "FAST_FAIL_GUARD_ICALL_CHECK_FAILURE_XFG"; + break; + case MD_FAST_FAIL_CAST_GUARD: + reason = "FAST_FAIL_CAST_GUARD"; + break; + case MD_FAST_FAIL_HOST_VISIBILITY_CHANGE: + reason = "FAST_FAIL_HOST_VISIBILITY_CHANGE"; + break; + case MD_FAST_FAIL_KERNEL_CET_SHADOW_STACK_ASSIST: + reason = "FAST_FAIL_KERNEL_CET_SHADOW_STACK_ASSIST"; + break; + case MD_FAST_FAIL_PATCH_CALLBACK_FAILED: + reason = "FAST_FAIL_PATCH_CALLBACK_FAILED"; + break; + case MD_FAST_FAIL_NTDLL_PATCH_FAILED: + reason = "FAST_FAIL_NTDLL_PATCH_FAILED"; + break; + case MD_FAST_FAIL_INVALID_FLS_DATA: + reason = "FAST_FAIL_INVALID_FLS_DATA"; + break; + default: + reason = "EXCEPTION_STACK_BUFFER_OVERRUN"; + break; + } + } else { + reason = "EXCEPTION_STACK_BUFFER_OVERRUN"; + } break; case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION: reason = "EXCEPTION_HEAP_CORRUPTION"; @@ -1734,18 +2069,27 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) { *address = GetAddressForArchitecture( static_cast<MDCPUArchitecture>(raw_system_info->processor_architecture), *address); + + // For invalid accesses to non-canonical addresses, amd64 cpus don't provide + // the fault address, so recover it from the disassembly and register state + // if possible. + if (enable_objdump + && raw_system_info->processor_architecture == MD_CPU_ARCHITECTURE_AMD64 + && std::numeric_limits<uint64_t>::max() == *address) { + CalculateFaultAddressFromInstruction(dump, address); + } } return reason; } // static -string MinidumpProcessor::GetAssertion(Minidump *dump) { - MinidumpAssertion *assertion = dump->GetAssertion(); +string MinidumpProcessor::GetAssertion(Minidump* dump) { + MinidumpAssertion* assertion = dump->GetAssertion(); if (!assertion) return ""; - const MDRawAssertionInfo *raw_assertion = assertion->assertion(); + const MDRawAssertionInfo* raw_assertion = assertion->assertion(); if (!raw_assertion) return ""; |