diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.h b/lldb/source/Plugins/Process/minidump/MinidumpParser.h --- a/lldb/source/Plugins/Process/minidump/MinidumpParser.h +++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.h @@ -82,7 +82,7 @@ // have the same name, it keeps the copy with the lowest load address. std::vector GetFilteredModuleList(); - const MinidumpExceptionStream *GetExceptionStream(); + const llvm::minidump::ExceptionStream *GetExceptionStream(); llvm::Optional FindMemoryRange(lldb::addr_t addr); diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp --- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp +++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp @@ -314,13 +314,15 @@ return filtered_modules; } -const MinidumpExceptionStream *MinidumpParser::GetExceptionStream() { - llvm::ArrayRef data = GetStream(StreamType::Exception); - - if (data.size() == 0) - return nullptr; - - return MinidumpExceptionStream::Parse(data); +const minidump::ExceptionStream *MinidumpParser::GetExceptionStream() { + auto ExpectedStream = GetMinidumpFile().getExceptionStream(); + if (ExpectedStream) + return &*ExpectedStream; + + LLDB_LOG_ERROR(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS), + ExpectedStream.takeError(), + "Failed to read minidump exception stream: {0}"); + return nullptr; } llvm::Optional diff --git a/lldb/source/Plugins/Process/minidump/MinidumpTypes.h b/lldb/source/Plugins/Process/minidump/MinidumpTypes.h --- a/lldb/source/Plugins/Process/minidump/MinidumpTypes.h +++ b/lldb/source/Plugins/Process/minidump/MinidumpTypes.h @@ -118,35 +118,6 @@ LinuxProcStatus() = default; }; -// Exception stuff -struct MinidumpException { - enum : unsigned { - ExceptonInfoMaxParams = 15, - DumpRequested = 0xFFFFFFFF, - }; - - llvm::support::ulittle32_t exception_code; - llvm::support::ulittle32_t exception_flags; - llvm::support::ulittle64_t exception_record; - llvm::support::ulittle64_t exception_address; - llvm::support::ulittle32_t number_parameters; - llvm::support::ulittle32_t unused_alignment; - llvm::support::ulittle64_t exception_information[ExceptonInfoMaxParams]; -}; -static_assert(sizeof(MinidumpException) == 152, - "sizeof MinidumpException is not correct!"); - -struct MinidumpExceptionStream { - llvm::support::ulittle32_t thread_id; - llvm::support::ulittle32_t alignment; - MinidumpException exception_record; - LocationDescriptor thread_context; - - static const MinidumpExceptionStream *Parse(llvm::ArrayRef &data); -}; -static_assert(sizeof(MinidumpExceptionStream) == 168, - "sizeof MinidumpExceptionStream is not correct!"); - } // namespace minidump } // namespace lldb_private #endif // liblldb_MinidumpTypes_h_ diff --git a/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp b/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp --- a/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp +++ b/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp @@ -57,17 +57,6 @@ lldb::pid_t LinuxProcStatus::GetPid() const { return pid; } -// Exception stuff -const MinidumpExceptionStream * -MinidumpExceptionStream::Parse(llvm::ArrayRef &data) { - const MinidumpExceptionStream *exception_stream = nullptr; - Status error = consumeObject(data, exception_stream); - if (error.Fail()) - return nullptr; - - return exception_stream; -} - std::pair, uint64_t> MinidumpMemoryDescriptor64::ParseMemory64List(llvm::ArrayRef &data) { const llvm::support::ulittle64_t *mem_ranges_count; diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h @@ -108,7 +108,7 @@ FileSpec m_core_file; lldb::DataBufferSP m_core_data; llvm::ArrayRef m_thread_list; - const MinidumpExceptionStream *m_active_exception; + const minidump::ExceptionStream *m_active_exception; lldb::CommandObjectSP m_command_sp; bool m_is_wow64; }; diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -241,36 +241,45 @@ if (!m_active_exception) return; - if (m_active_exception->exception_record.exception_code == - MinidumpException::DumpRequested) { + constexpr uint32_t BreakpadDumpRequested = 0xFFFFFFFF; + if (m_active_exception->ExceptionRecord.ExceptionCode == + BreakpadDumpRequested) { + // This "ExceptionCode" value is a sentinel that is sometimes used + // when generating a dump for a process that hasn't crashed. + + // TODO: The definition and use of this "dump requested" constant + // in Breakpad are actually Linux-specific, and for similar use + // cases on Mac/Windows it defines differnt constants, referring + // to them as "simulated" exceptions; consider moving this check + // down to the OS-specific paths and checking each OS for its own + // constant. return; } lldb::StopInfoSP stop_info; lldb::ThreadSP stop_thread; - Process::m_thread_list.SetSelectedThreadByID(m_active_exception->thread_id); + Process::m_thread_list.SetSelectedThreadByID(m_active_exception->ThreadId); stop_thread = Process::m_thread_list.GetSelectedThread(); ArchSpec arch = GetArchitecture(); if (arch.GetTriple().getOS() == llvm::Triple::Linux) { stop_info = StopInfo::CreateStopReasonWithSignal( - *stop_thread, m_active_exception->exception_record.exception_code); + *stop_thread, m_active_exception->ExceptionRecord.ExceptionCode); } else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) { stop_info = StopInfoMachException::CreateStopReasonWithMachException( - *stop_thread, m_active_exception->exception_record.exception_code, 2, - m_active_exception->exception_record.exception_flags, - m_active_exception->exception_record.exception_address, 0); + *stop_thread, m_active_exception->ExceptionRecord.ExceptionCode, 2, + m_active_exception->ExceptionRecord.ExceptionFlags, + m_active_exception->ExceptionRecord.ExceptionAddress, 0); } else { std::string desc; llvm::raw_string_ostream desc_stream(desc); desc_stream << "Exception " << llvm::format_hex( - m_active_exception->exception_record.exception_code, 8) + m_active_exception->ExceptionRecord.ExceptionCode, 8) << " encountered at address " << llvm::format_hex( - m_active_exception->exception_record.exception_address, - 8); + m_active_exception->ExceptionRecord.ExceptionAddress, 8); stop_info = StopInfo::CreateStopReasonWithException( *stop_thread, desc_stream.str().c_str()); } @@ -335,8 +344,8 @@ // If the minidump contains an exception context, use it if (m_active_exception != nullptr && - m_active_exception->thread_id == thread.ThreadId) { - context_location = m_active_exception->thread_context; + m_active_exception->ThreadId == thread.ThreadId) { + context_location = m_active_exception->ThreadContext; } llvm::ArrayRef context; diff --git a/lldb/unittests/Process/minidump/MinidumpParserTest.cpp b/lldb/unittests/Process/minidump/MinidumpParserTest.cpp --- a/lldb/unittests/Process/minidump/MinidumpParserTest.cpp +++ b/lldb/unittests/Process/minidump/MinidumpParserTest.cpp @@ -252,10 +252,10 @@ TEST_F(MinidumpParserTest, GetExceptionStream) { SetUpData("linux-x86_64.dmp"); - const MinidumpExceptionStream *exception_stream = + const llvm::minidump::ExceptionStream *exception_stream = parser->GetExceptionStream(); ASSERT_NE(nullptr, exception_stream); - ASSERT_EQ(11UL, exception_stream->exception_record.exception_code); + ASSERT_EQ(11UL, exception_stream->ExceptionRecord.ExceptionCode); } void check_mem_range_exists(MinidumpParser &parser, const uint64_t range_start,