Index: lldb/trunk/cmake/LLDBDependencies.cmake =================================================================== --- lldb/trunk/cmake/LLDBDependencies.cmake +++ lldb/trunk/cmake/LLDBDependencies.cmake @@ -81,6 +81,7 @@ lldbPluginInstrumentationRuntimeThreadSanitizer lldbPluginSystemRuntimeMacOSX lldbPluginProcessElfCore + lldbPluginProcessMinidump lldbPluginJITLoaderGDB lldbPluginExpressionParserClang lldbPluginExpressionParserGo Index: lldb/trunk/source/Plugins/Process/CMakeLists.txt =================================================================== --- lldb/trunk/source/Plugins/Process/CMakeLists.txt +++ lldb/trunk/source/Plugins/Process/CMakeLists.txt @@ -17,3 +17,4 @@ add_subdirectory(Utility) add_subdirectory(mach-core) add_subdirectory(elf-core) +add_subdirectory(minidump) Index: lldb/trunk/source/Plugins/Process/minidump/CMakeLists.txt =================================================================== --- lldb/trunk/source/Plugins/Process/minidump/CMakeLists.txt +++ lldb/trunk/source/Plugins/Process/minidump/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories(../Utility) + +add_lldb_library(lldbPluginProcessMinidump + MinidumpTypes.cpp + MinidumpParser.cpp + ) Index: lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h =================================================================== --- lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h +++ lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h @@ -0,0 +1,73 @@ +//===-- MinidumpParser.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_MinidumpParser_h_ +#define liblldb_MinidumpParser_h_ + +// Project includes +#include "MinidumpTypes.h" + +// Other libraries and framework includes +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/DataBuffer.h" +#include "lldb/Core/Error.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" + +// C includes + +// C++ includes +#include +#include + + +namespace lldb_private +{ + +namespace minidump +{ + +class MinidumpParser +{ +public: + static llvm::Optional + Create(const lldb::DataBufferSP &data_buf_sp); + + lldb::offset_t + GetByteSize(); + + llvm::Optional> + GetStream(MinidumpStreamType stream_type); + + llvm::Optional> + GetThreads(); + + const MinidumpSystemInfo * + GetSystemInfo(); + + ArchSpec + GetArchitecture(); + + const MinidumpMiscInfo * + GetMiscInfo(); + +private: + lldb::DataBufferSP m_data_sp; + const MinidumpHeader *m_header; + llvm::DenseMap m_directory_map; + + MinidumpParser(const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header, + const llvm::DenseMap &directory_map); +}; + +} // namespace minidump +} // namespace lldb_private +#endif // liblldb_MinidumpParser_h_ Index: lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp +++ lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp @@ -0,0 +1,160 @@ +//===-- MinidumpParser.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Project includes +#include "MinidumpParser.h" + +// Other libraries and framework includes +// C includes +// C++ includes + +using namespace lldb_private; +using namespace minidump; + +llvm::Optional +MinidumpParser::Create(const lldb::DataBufferSP &data_buf_sp) +{ + if (data_buf_sp->GetByteSize() < sizeof(MinidumpHeader)) + { + return llvm::None; + } + + llvm::ArrayRef header_data(data_buf_sp->GetBytes(), sizeof(MinidumpHeader)); + const MinidumpHeader *header = MinidumpHeader::Parse(header_data); + + if (header == nullptr) + { + return llvm::None; + } + + lldb::offset_t directory_list_offset = header->stream_directory_rva; + // check if there is enough data for the parsing of the directory list + if ((directory_list_offset + sizeof(MinidumpDirectory) * header->streams_count) > data_buf_sp->GetByteSize()) + { + return llvm::None; + } + + const MinidumpDirectory *directory = nullptr; + Error error; + llvm::ArrayRef directory_data(data_buf_sp->GetBytes() + directory_list_offset, + sizeof(MinidumpDirectory) * header->streams_count); + llvm::DenseMap directory_map; + + for (uint32_t i = 0; i < header->streams_count; ++i) + { + error = consumeObject(directory_data, directory); + if (error.Fail()) + { + return llvm::None; + } + directory_map[static_cast(directory->stream_type)] = directory->location; + } + + MinidumpParser parser(data_buf_sp, header, directory_map); + return llvm::Optional(parser); +} + +MinidumpParser::MinidumpParser(const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header, + const llvm::DenseMap &directory_map) + : m_data_sp(data_buf_sp), m_header(header), m_directory_map(directory_map) +{ +} + +lldb::offset_t +MinidumpParser::GetByteSize() +{ + return m_data_sp->GetByteSize(); +} + +llvm::Optional> +MinidumpParser::GetStream(MinidumpStreamType stream_type) +{ + auto iter = m_directory_map.find(static_cast(stream_type)); + if (iter == m_directory_map.end()) + return llvm::None; + + // check if there is enough data + if (iter->second.rva + iter->second.data_size > m_data_sp->GetByteSize()) + return llvm::None; + + llvm::ArrayRef arr_ref(m_data_sp->GetBytes() + iter->second.rva, iter->second.data_size); + return llvm::Optional>(arr_ref); +} + +llvm::Optional> +MinidumpParser::GetThreads() +{ + llvm::Optional> data = GetStream(MinidumpStreamType::ThreadList); + + if (!data) + return llvm::None; + + return MinidumpThread::ParseThreadList(data.getValue()); +} + +const MinidumpSystemInfo * +MinidumpParser::GetSystemInfo() +{ + llvm::Optional> data = GetStream(MinidumpStreamType::SystemInfo); + + if (!data) + return nullptr; + + return MinidumpSystemInfo::Parse(data.getValue()); +} + +ArchSpec +MinidumpParser::GetArchitecture() +{ + ArchSpec arch_spec; + arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS); + arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor); + arch_spec.GetTriple().setArch(llvm::Triple::ArchType::UnknownArch); + + // TODO should we add the OS type here, or somewhere else ? + + const MinidumpSystemInfo *system_info = GetSystemInfo(); + + if (!system_info) + return arch_spec; + + // TODO what to do about big endiand flavors of arm ? + // TODO set the arm subarch stuff if the minidump has info about it + + const MinidumpCPUArchitecture arch = + static_cast(static_cast(system_info->processor_arch)); + switch (arch) + { + case MinidumpCPUArchitecture::X86: + arch_spec.GetTriple().setArch(llvm::Triple::ArchType::x86); + break; + case MinidumpCPUArchitecture::AMD64: + arch_spec.GetTriple().setArch(llvm::Triple::ArchType::x86_64); + break; + case MinidumpCPUArchitecture::ARM: + arch_spec.GetTriple().setArch(llvm::Triple::ArchType::arm); + break; + case MinidumpCPUArchitecture::ARM64: + arch_spec.GetTriple().setArch(llvm::Triple::ArchType::aarch64); + break; + } + + return arch_spec; +} + +const MinidumpMiscInfo * +MinidumpParser::GetMiscInfo() +{ + llvm::Optional> data = GetStream(MinidumpStreamType::MiscInfo); + + if (!data) + return nullptr; + + return MinidumpMiscInfo::Parse(data.getValue()); +} Index: lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h =================================================================== --- lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h +++ lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h @@ -0,0 +1,298 @@ +//===-- MinidumpTypes.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_MinidumpTypes_h_ +#define liblldb_MinidumpTypes_h_ + +// Project includes + +// Other libraries and framework includes +#include "lldb/Core/Error.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitmaskEnum.h" +#include "llvm/ADT/Optional.h" +#include "llvm/Support/Endian.h" + +// C includes +// C++ includes + +// Reference: +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms679293(v=vs.85).aspx +// https://chromium.googlesource.com/breakpad/breakpad/ + +namespace lldb_private +{ + +namespace minidump +{ + +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); + +enum class MinidumpHeaderConstants : uint32_t +{ + Signature = 0x504d444d, // 'PMDM' + Version = 0x0000a793, // 42899 + LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Signature) + +}; + +// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680394.aspx +enum class MinidumpStreamType : uint32_t +{ + Unused = 0, + Reserved0 = 1, + Reserved1 = 2, + ThreadList = 3, + ModuleList = 4, + MemoryList = 5, + Exception = 6, + SystemInfo = 7, + ThreadExList = 8, + Memory64List = 9, + CommentA = 10, + CommentW = 11, + HandleData = 12, + FunctionTable = 13, + UnloadedModuleList = 14, + MiscInfo = 15, + MemoryInfoList = 16, + ThreadInfoList = 17, + HandleOperationList = 18, + Token = 19, + JavascriptData = 20, + SystemMemoryInfo = 21, + ProcessVMCounters = 22, + LastReserved = 0x0000ffff, + + /* Breakpad extension types. 0x4767 = "Gg" */ + BreakpadInfo = 0x47670001, + AssertionInfo = 0x47670002, + /* These are additional minidump stream values which are specific to + * the linux breakpad implementation. */ + LinuxCPUInfo = 0x47670003, /* /proc/cpuinfo */ + LinuxProcStatus = 0x47670004, /* /proc/$x/status */ + LinuxLSBRelease = 0x47670005, /* /etc/lsb-release */ + LinuxCMDLine = 0x47670006, /* /proc/$x/cmdline */ + LinuxEnviron = 0x47670007, /* /proc/$x/environ */ + LinuxAuxv = 0x47670008, /* /proc/$x/auxv */ + LinuxMaps = 0x47670009, /* /proc/$x/maps */ + LinuxDSODebug = 0x4767000A +}; + +// for MinidumpSystemInfo.processor_arch +enum class MinidumpCPUArchitecture : uint16_t +{ + X86 = 0, /* PROCESSOR_ARCHITECTURE_INTEL */ + MIPS = 1, /* PROCESSOR_ARCHITECTURE_MIPS */ + Alpha = 2, /* PROCESSOR_ARCHITECTURE_ALPHA */ + PPC = 3, /* PROCESSOR_ARCHITECTURE_PPC */ + SHX = 4, /* PROCESSOR_ARCHITECTURE_SHX (Super-H) */ + ARM = 5, /* PROCESSOR_ARCHITECTURE_ARM */ + IA64 = 6, /* PROCESSOR_ARCHITECTURE_IA64 */ + Alpha64 = 7, /* PROCESSOR_ARCHITECTURE_ALPHA64 */ + MSIL = 8, /* PROCESSOR_ARCHITECTURE_MSIL + * (Microsoft Intermediate Language) */ + AMD64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */ + X86Win64 = 10, /* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */ + SPARC = 0x8001, /* Breakpad-defined value for SPARC */ + PPC64 = 0x8002, /* Breakpad-defined value for PPC64 */ + ARM64 = 0x8003, /* Breakpad-defined value for ARM64 */ + MIPS64 = 0x8004, /* Breakpad-defined value for MIPS64 */ + Unknown = 0xffff /* PROCESSOR_ARCHITECTURE_UNKNOWN */ +}; + +// for MinidumpSystemInfo.platform_id +enum class MinidumpOSPlatform : uint32_t +{ + Win32S = 0, /* VER_PLATFORM_WIN32s (Windows 3.1) */ + Win32Windows = 1, /* VER_PLATFORM_WIN32_WINDOWS (Windows 95-98-Me) */ + Win32NT = 2, /* VER_PLATFORM_WIN32_NT (Windows NT, 2000+) */ + Win32CE = 3, /* VER_PLATFORM_WIN32_CE, VER_PLATFORM_WIN32_HH + * (Windows CE, Windows Mobile, "Handheld") */ + + /* The following values are Breakpad-defined. */ + Unix = 0x8000, /* Generic Unix-ish */ + MacOSX = 0x8101, /* Mac OS X/Darwin */ + IOS = 0x8102, /* iOS */ + Linux = 0x8201, /* Linux */ + Solaris = 0x8202, /* Solaris */ + Android = 0x8203, /* Android */ + PS3 = 0x8204, /* PS3 */ + NaCl = 0x8205 /* Native Client (NaCl) */ +}; + +// For MinidumpCPUInfo.arm_cpu_info.elf_hwcaps. +// This matches the Linux kernel definitions from +enum class MinidumpPCPUInformationARMElfHwCaps : uint32_t +{ + SWP = (1 << 0), + Half = (1 << 1), + Thumb = (1 << 2), + _26BIT = (1 << 3), + FastMult = (1 << 4), + FPA = (1 << 5), + VFP = (1 << 6), + EDSP = (1 << 7), + Java = (1 << 8), + IWMMXT = (1 << 9), + Crunch = (1 << 10), + ThumbEE = (1 << 11), + Neon = (1 << 12), + VFPv3 = (1 << 13), + VFPv3D16 = (1 << 14), + TLS = (1 << 15), + VFPv4 = (1 << 16), + IDIVA = (1 << 17), + IDIVT = (1 << 18), + LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IDIVT) +}; + +template +Error +consumeObject(llvm::ArrayRef &Buffer, const T *&Object) +{ + Error error; + if (Buffer.size() < sizeof(T)) + { + error.SetErrorString("Insufficient buffer!"); + return error; + } + + Object = reinterpret_cast(Buffer.data()); + Buffer = Buffer.drop_front(sizeof(T)); + return error; +} + +// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680378(v=vs.85).aspx +struct MinidumpHeader +{ + llvm::support::ulittle32_t signature; + llvm::support::ulittle32_t version; // The high 16 bits of version field are implementation specific + llvm::support::ulittle32_t streams_count; + llvm::support::ulittle32_t stream_directory_rva; // offset of the stream directory + llvm::support::ulittle32_t checksum; + llvm::support::ulittle32_t time_date_stamp; // time_t format + llvm::support::ulittle64_t flags; + + static const MinidumpHeader * + Parse(llvm::ArrayRef &data); +}; +static_assert(sizeof(MinidumpHeader) == 32, "sizeof MinidumpHeader is not correct!"); + +// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680383.aspx +struct MinidumpLocationDescriptor +{ + llvm::support::ulittle32_t data_size; + llvm::support::ulittle32_t rva; +}; +static_assert(sizeof(MinidumpLocationDescriptor) == 8, "sizeof MinidumpLocationDescriptor is not correct!"); + +// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680384(v=vs.85).aspx +struct MinidumpMemoryDescriptor +{ + llvm::support::ulittle64_t start_of_memory_range; + MinidumpLocationDescriptor memory; +}; +static_assert(sizeof(MinidumpMemoryDescriptor) == 16, "sizeof MinidumpMemoryDescriptor is not correct!"); + +// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680365.aspx +struct MinidumpDirectory +{ + llvm::support::ulittle32_t stream_type; + MinidumpLocationDescriptor location; +}; +static_assert(sizeof(MinidumpDirectory) == 12, "sizeof MinidumpDirectory is not correct!"); + +// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680517(v=vs.85).aspx +struct MinidumpThread +{ + llvm::support::ulittle32_t thread_id; + llvm::support::ulittle32_t suspend_count; + llvm::support::ulittle32_t priority_class; + llvm::support::ulittle32_t priority; + llvm::support::ulittle64_t teb; + MinidumpMemoryDescriptor stack; + MinidumpLocationDescriptor thread_context; + + static const MinidumpThread * + Parse(llvm::ArrayRef &data); + + static llvm::Optional> + ParseThreadList(llvm::ArrayRef &data); +}; +static_assert(sizeof(MinidumpThread) == 48, "sizeof MinidumpThread is not correct!"); + +// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx +union MinidumpCPUInfo { + struct + { + llvm::support::ulittle32_t vendor_id[3]; /* cpuid 0: ebx, edx, ecx */ + llvm::support::ulittle32_t version_information; /* cpuid 1: eax */ + llvm::support::ulittle32_t feature_information; /* cpuid 1: edx */ + llvm::support::ulittle32_t amd_extended_cpu_features; /* cpuid 0x80000001, ebx */ + } x86_cpu_info; + struct + { + llvm::support::ulittle32_t cpuid; + llvm::support::ulittle32_t elf_hwcaps; /* linux specific, 0 otherwise */ + } arm_cpu_info; + struct + { + llvm::support::ulittle64_t processor_features[2]; + } other_cpu_info; +}; +static_assert(sizeof(MinidumpCPUInfo) == 24, "sizeof MinidumpCPUInfo is not correct!"); + +// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx +struct MinidumpSystemInfo +{ + llvm::support::ulittle16_t processor_arch; + llvm::support::ulittle16_t processor_level; + llvm::support::ulittle16_t processor_revision; + + uint8_t number_of_processors; + uint8_t product_type; + + llvm::support::ulittle32_t major_version; + llvm::support::ulittle32_t minor_version; + llvm::support::ulittle32_t build_number; + llvm::support::ulittle32_t platform_id; + llvm::support::ulittle32_t csd_version_rva; + + llvm::support::ulittle16_t suit_mask; + llvm::support::ulittle16_t reserved2; + + MinidumpCPUInfo cpu; + + static const MinidumpSystemInfo * + Parse(llvm::ArrayRef &data); +}; +static_assert(sizeof(MinidumpSystemInfo) == 56, "sizeof MinidumpSystemInfo is not correct!"); + +// TODO check flags to see what's valid +// TODO misc2, misc3 ? +// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680389(v=vs.85).aspx +struct MinidumpMiscInfo +{ + llvm::support::ulittle32_t size; + llvm::support::ulittle32_t flags1; + llvm::support::ulittle32_t process_id; + llvm::support::ulittle32_t process_create_time; + llvm::support::ulittle32_t process_user_time; + llvm::support::ulittle32_t process_kernel_time; + + static const MinidumpMiscInfo * + Parse(llvm::ArrayRef &data); +}; +static_assert(sizeof(MinidumpMiscInfo) == 24, "sizeof MinidumpMiscInfo is not correct!"); + +} // namespace minidump +} // namespace lldb_private +#endif // liblldb_MinidumpTypes_h_ Index: lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp +++ lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp @@ -0,0 +1,98 @@ +//===-- MinidumpTypes.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Project includes +#include "MinidumpTypes.h" +#include "MinidumpParser.h" + +// Other libraries and framework includes +// C includes +// C++ includes + +using namespace lldb_private; +using namespace minidump; + +const MinidumpHeader * +MinidumpHeader::Parse(llvm::ArrayRef &data) +{ + const MinidumpHeader *header = nullptr; + Error error = consumeObject(data, header); + + const MinidumpHeaderConstants signature = + static_cast(static_cast(header->signature)); + const MinidumpHeaderConstants version = + static_cast(static_cast(header->version) & 0x0000ffff); + // the high 16 bits of the version field are implementation specific + + if (error.Fail() || signature != MinidumpHeaderConstants::Signature || version != MinidumpHeaderConstants::Version) + return nullptr; + + // TODO check for max number of streams ? + // TODO more sanity checks ? + + return header; +} + +// MinidumpThread +const MinidumpThread * +MinidumpThread::Parse(llvm::ArrayRef &data) +{ + const MinidumpThread *thread = nullptr; + Error error = consumeObject(data, thread); + if (error.Fail()) + return nullptr; + + return thread; +} + +llvm::Optional> +MinidumpThread::ParseThreadList(llvm::ArrayRef &data) +{ + std::vector thread_list; + + const llvm::support::ulittle32_t *thread_count; + Error error = consumeObject(data, thread_count); + if (error.Fail()) + return llvm::None; + + const MinidumpThread *thread; + for (uint32_t i = 0; i < *thread_count; ++i) + { + thread = MinidumpThread::Parse(data); + if (thread == nullptr) + return llvm::None; + thread_list.push_back(thread); + } + + return llvm::Optional>(thread_list); +} + +// MinidumpSystemInfo +const MinidumpSystemInfo * +MinidumpSystemInfo::Parse(llvm::ArrayRef &data) +{ + const MinidumpSystemInfo *system_info; + Error error = consumeObject(data, system_info); + if (error.Fail()) + return nullptr; + + return system_info; +} + +// MinidumpMiscInfo +const MinidumpMiscInfo * +MinidumpMiscInfo::Parse(llvm::ArrayRef &data) +{ + const MinidumpMiscInfo *misc_info; + Error error = consumeObject(data, misc_info); + if (error.Fail()) + return nullptr; + + return misc_info; +} Index: lldb/trunk/unittests/Process/CMakeLists.txt =================================================================== --- lldb/trunk/unittests/Process/CMakeLists.txt +++ lldb/trunk/unittests/Process/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(gdb-remote) +add_subdirectory(minidump) Index: lldb/trunk/unittests/Process/minidump/CMakeLists.txt =================================================================== --- lldb/trunk/unittests/Process/minidump/CMakeLists.txt +++ lldb/trunk/unittests/Process/minidump/CMakeLists.txt @@ -0,0 +1,8 @@ +add_lldb_unittest(LLDBMinidumpTests + MinidumpParserTest.cpp + ) + +set(test_inputs + linux-x86_64.dmp) + +add_unittest_inputs(LLDBMinidumpTests "${test_inputs}") Index: lldb/trunk/unittests/Process/minidump/Inputs/linux-x86_64.cpp =================================================================== --- lldb/trunk/unittests/Process/minidump/Inputs/linux-x86_64.cpp +++ lldb/trunk/unittests/Process/minidump/Inputs/linux-x86_64.cpp @@ -0,0 +1,25 @@ +// Example source from breakpad's linux tutorial +// https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/linux_starter_guide.md + +#include +#include +#include + +#include "client/linux/handler/exception_handler.h" + + +static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, +void* context, bool succeeded) { + printf("Dump path: %s\n", descriptor.path()); + return succeeded; +} + +void crash() { volatile int* a = (int*)(NULL); *a = 1; } + +int main(int argc, char* argv[]) { + google_breakpad::MinidumpDescriptor descriptor("/tmp"); + google_breakpad::ExceptionHandler eh(descriptor, NULL, dumpCallback, NULL, true, -1); + printf("pid: %d\n", getpid()); + crash(); + return 0; +} Index: lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp =================================================================== --- lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp +++ lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp @@ -0,0 +1,97 @@ +//===-- MinidumpTypesTest.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Project includes +#include "Plugins/Process/minidump/MinidumpParser.h" +#include "Plugins/Process/minidump/MinidumpTypes.h" + +// Other libraries and framework includes +#include "gtest/gtest.h" + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Host/FileSpec.h" + +#include "llvm/ADT/Optional.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +// C includes + +// C++ includes +#include + +extern const char *TestMainArgv0; + +using namespace lldb_private; +using namespace minidump; + +class MinidumpParserTest : public testing::Test +{ +public: + void + SetUp() override + { + llvm::StringRef dmp_folder = llvm::sys::path::parent_path(TestMainArgv0); + inputs_folder = dmp_folder; + llvm::sys::path::append(inputs_folder, "Inputs"); + } + + void + SetUpData(const char *minidump_filename, size_t load_size = SIZE_MAX) + { + llvm::SmallString<128> filename = inputs_folder; + llvm::sys::path::append(filename, minidump_filename); + FileSpec minidump_file(filename.c_str(), false); + lldb::DataBufferSP data_sp(minidump_file.MemoryMapFileContents(0, load_size)); + llvm::Optional optional_parser = MinidumpParser::Create(data_sp); + ASSERT_TRUE(optional_parser.hasValue()); + parser.reset(new MinidumpParser(optional_parser.getValue())); + ASSERT_GT(parser->GetByteSize(), 0UL); + } + + llvm::SmallString<128> inputs_folder; + std::unique_ptr parser; +}; + +TEST_F(MinidumpParserTest, GetThreads) +{ + SetUpData("linux-x86_64.dmp"); + llvm::Optional> thread_list; + + thread_list = parser->GetThreads(); + ASSERT_TRUE(thread_list.hasValue()); + ASSERT_EQ(1UL, thread_list->size()); + + const MinidumpThread *thread = thread_list.getValue()[0]; + ASSERT_EQ(16001UL, thread->thread_id); +} + +TEST_F(MinidumpParserTest, GetThreadsTruncatedFile) +{ + SetUpData("linux-x86_64.dmp", 200); + llvm::Optional> thread_list; + + thread_list = parser->GetThreads(); + ASSERT_FALSE(thread_list.hasValue()); +} + +TEST_F(MinidumpParserTest, GetArchitecture) +{ + SetUpData("linux-x86_64.dmp"); + ASSERT_EQ(llvm::Triple::ArchType::x86_64, parser->GetArchitecture().GetTriple().getArch()); +} + +TEST_F(MinidumpParserTest, GetMiscInfo) +{ + SetUpData("linux-x86_64.dmp"); + const MinidumpMiscInfo *misc_info = parser->GetMiscInfo(); + ASSERT_EQ(nullptr, misc_info); + // linux breakpad generated minidump files don't have misc info stream +}