[Lldb-commits] [lldb] r280356 - Minidump parsing

Dimitar Vlahovski via lldb-commits lldb-commits at lists.llvm.org
Thu Sep 1 04:29:53 PDT 2016


Author: dvlahovski
Date: Thu Sep  1 06:29:53 2016
New Revision: 280356

URL: http://llvm.org/viewvc/llvm-project?rev=280356&view=rev
Log:
Minidump parsing

Summary:
This is a Minidump parsing code.
There are still some more structures/data streams that need to be added.
The aim ot this is to be used in the implementation of
a minidump debugging plugin that works on all platforms/architectures.
Currently we have a windows-only plugin that uses the WinAPI to parse
the dump files.
Also added unittests for the current functionality.

Reviewers: labath, amccarth

Subscribers: tberghammer, danalbert, srhines, lldb-commits, dschuff

Differential Revision: https://reviews.llvm.org/D23545

Added:
    lldb/trunk/source/Plugins/Process/minidump/
    lldb/trunk/source/Plugins/Process/minidump/CMakeLists.txt
    lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp
    lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h
    lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp
    lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h
    lldb/trunk/unittests/Process/minidump/
    lldb/trunk/unittests/Process/minidump/CMakeLists.txt
    lldb/trunk/unittests/Process/minidump/Inputs/
    lldb/trunk/unittests/Process/minidump/Inputs/linux-x86_64.cpp
    lldb/trunk/unittests/Process/minidump/Inputs/linux-x86_64.dmp
    lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp
Modified:
    lldb/trunk/cmake/LLDBDependencies.cmake
    lldb/trunk/source/Plugins/Process/CMakeLists.txt
    lldb/trunk/unittests/Process/CMakeLists.txt

Modified: lldb/trunk/cmake/LLDBDependencies.cmake
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/cmake/LLDBDependencies.cmake?rev=280356&r1=280355&r2=280356&view=diff
==============================================================================
--- lldb/trunk/cmake/LLDBDependencies.cmake (original)
+++ lldb/trunk/cmake/LLDBDependencies.cmake Thu Sep  1 06:29:53 2016
@@ -81,6 +81,7 @@ set( LLDB_USED_LIBS
   lldbPluginInstrumentationRuntimeThreadSanitizer
   lldbPluginSystemRuntimeMacOSX
   lldbPluginProcessElfCore
+  lldbPluginProcessMinidump
   lldbPluginJITLoaderGDB
   lldbPluginExpressionParserClang
   lldbPluginExpressionParserGo

Modified: lldb/trunk/source/Plugins/Process/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/CMakeLists.txt?rev=280356&r1=280355&r2=280356&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Process/CMakeLists.txt Thu Sep  1 06:29:53 2016
@@ -17,3 +17,4 @@ add_subdirectory(gdb-remote)
 add_subdirectory(Utility)
 add_subdirectory(mach-core)
 add_subdirectory(elf-core)
+add_subdirectory(minidump)

Added: lldb/trunk/source/Plugins/Process/minidump/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/CMakeLists.txt?rev=280356&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/CMakeLists.txt (added)
+++ lldb/trunk/source/Plugins/Process/minidump/CMakeLists.txt Thu Sep  1 06:29:53 2016
@@ -0,0 +1,6 @@
+include_directories(../Utility)
+
+add_lldb_library(lldbPluginProcessMinidump
+  MinidumpTypes.cpp
+  MinidumpParser.cpp
+  )

Added: lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp?rev=280356&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp (added)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp Thu Sep  1 06:29:53 2016
@@ -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>
+MinidumpParser::Create(const lldb::DataBufferSP &data_buf_sp)
+{
+    if (data_buf_sp->GetByteSize() < sizeof(MinidumpHeader))
+    {
+        return llvm::None;
+    }
+
+    llvm::ArrayRef<uint8_t> 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<uint8_t> directory_data(data_buf_sp->GetBytes() + directory_list_offset,
+                                           sizeof(MinidumpDirectory) * header->streams_count);
+    llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> 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<const uint32_t>(directory->stream_type)] = directory->location;
+    }
+
+    MinidumpParser parser(data_buf_sp, header, directory_map);
+    return llvm::Optional<MinidumpParser>(parser);
+}
+
+MinidumpParser::MinidumpParser(const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header,
+                               const llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &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<llvm::ArrayRef<uint8_t>>
+MinidumpParser::GetStream(MinidumpStreamType stream_type)
+{
+    auto iter = m_directory_map.find(static_cast<uint32_t>(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<uint8_t> arr_ref(m_data_sp->GetBytes() + iter->second.rva, iter->second.data_size);
+    return llvm::Optional<llvm::ArrayRef<uint8_t>>(arr_ref);
+}
+
+llvm::Optional<std::vector<const MinidumpThread *>>
+MinidumpParser::GetThreads()
+{
+    llvm::Optional<llvm::ArrayRef<uint8_t>> data = GetStream(MinidumpStreamType::ThreadList);
+
+    if (!data)
+        return llvm::None;
+
+    return MinidumpThread::ParseThreadList(data.getValue());
+}
+
+const MinidumpSystemInfo *
+MinidumpParser::GetSystemInfo()
+{
+    llvm::Optional<llvm::ArrayRef<uint8_t>> 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<const MinidumpCPUArchitecture>(static_cast<const uint32_t>(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<llvm::ArrayRef<uint8_t>> data = GetStream(MinidumpStreamType::MiscInfo);
+
+    if (!data)
+        return nullptr;
+
+    return MinidumpMiscInfo::Parse(data.getValue());
+}

Added: lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h?rev=280356&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h (added)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h Thu Sep  1 06:29:53 2016
@@ -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 <cstring>
+#include <unordered_map>
+
+
+namespace lldb_private
+{
+
+namespace minidump
+{
+
+class MinidumpParser
+{
+public:
+    static llvm::Optional<MinidumpParser>
+    Create(const lldb::DataBufferSP &data_buf_sp);
+
+    lldb::offset_t
+    GetByteSize();
+
+    llvm::Optional<llvm::ArrayRef<uint8_t>>
+    GetStream(MinidumpStreamType stream_type);
+
+    llvm::Optional<std::vector<const MinidumpThread *>>
+    GetThreads();
+
+    const MinidumpSystemInfo *
+    GetSystemInfo();
+
+    ArchSpec
+    GetArchitecture();
+
+    const MinidumpMiscInfo *
+    GetMiscInfo();
+
+private:
+    lldb::DataBufferSP m_data_sp;
+    const MinidumpHeader *m_header;
+    llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> m_directory_map;
+
+    MinidumpParser(const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header,
+                   const llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &directory_map);
+};
+
+} // namespace minidump
+} // namespace lldb_private
+#endif // liblldb_MinidumpParser_h_

Added: lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp?rev=280356&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp (added)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp Thu Sep  1 06:29:53 2016
@@ -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<uint8_t> &data)
+{
+    const MinidumpHeader *header = nullptr;
+    Error error = consumeObject(data, header);
+
+    const MinidumpHeaderConstants signature =
+        static_cast<const MinidumpHeaderConstants>(static_cast<const uint32_t>(header->signature));
+    const MinidumpHeaderConstants version =
+        static_cast<const MinidumpHeaderConstants>(static_cast<const uint32_t>(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<uint8_t> &data)
+{
+    const MinidumpThread *thread = nullptr;
+    Error error = consumeObject(data, thread);
+    if (error.Fail())
+        return nullptr;
+
+    return thread;
+}
+
+llvm::Optional<std::vector<const MinidumpThread *>>
+MinidumpThread::ParseThreadList(llvm::ArrayRef<uint8_t> &data)
+{
+    std::vector<const MinidumpThread *> 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<std::vector<const MinidumpThread *>>(thread_list);
+}
+
+// MinidumpSystemInfo
+const MinidumpSystemInfo *
+MinidumpSystemInfo::Parse(llvm::ArrayRef<uint8_t> &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<uint8_t> &data)
+{
+    const MinidumpMiscInfo *misc_info;
+    Error error = consumeObject(data, misc_info);
+    if (error.Fail())
+        return nullptr;
+
+    return misc_info;
+}

Added: lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h?rev=280356&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h (added)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h Thu Sep  1 06:29:53 2016
@@ -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 <asm/hwcaps.h>
+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 <typename T>
+Error
+consumeObject(llvm::ArrayRef<uint8_t> &Buffer, const T *&Object)
+{
+    Error error;
+    if (Buffer.size() < sizeof(T))
+    {
+        error.SetErrorString("Insufficient buffer!");
+        return error;
+    }
+
+    Object = reinterpret_cast<const T *>(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<uint8_t> &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<uint8_t> &data);
+
+    static llvm::Optional<std::vector<const MinidumpThread *>>
+    ParseThreadList(llvm::ArrayRef<uint8_t> &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<uint8_t> &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<uint8_t> &data);
+};
+static_assert(sizeof(MinidumpMiscInfo) == 24, "sizeof MinidumpMiscInfo is not correct!");
+
+} // namespace minidump
+} // namespace lldb_private
+#endif // liblldb_MinidumpTypes_h_

Modified: lldb/trunk/unittests/Process/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Process/CMakeLists.txt?rev=280356&r1=280355&r2=280356&view=diff
==============================================================================
--- lldb/trunk/unittests/Process/CMakeLists.txt (original)
+++ lldb/trunk/unittests/Process/CMakeLists.txt Thu Sep  1 06:29:53 2016
@@ -1 +1,2 @@
 add_subdirectory(gdb-remote)
+add_subdirectory(minidump)

Added: lldb/trunk/unittests/Process/minidump/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Process/minidump/CMakeLists.txt?rev=280356&view=auto
==============================================================================
--- lldb/trunk/unittests/Process/minidump/CMakeLists.txt (added)
+++ lldb/trunk/unittests/Process/minidump/CMakeLists.txt Thu Sep  1 06:29:53 2016
@@ -0,0 +1,8 @@
+add_lldb_unittest(LLDBMinidumpTests
+  MinidumpParserTest.cpp
+  )
+
+set(test_inputs
+   linux-x86_64.dmp)
+
+add_unittest_inputs(LLDBMinidumpTests "${test_inputs}")

Added: lldb/trunk/unittests/Process/minidump/Inputs/linux-x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Process/minidump/Inputs/linux-x86_64.cpp?rev=280356&view=auto
==============================================================================
--- lldb/trunk/unittests/Process/minidump/Inputs/linux-x86_64.cpp (added)
+++ lldb/trunk/unittests/Process/minidump/Inputs/linux-x86_64.cpp Thu Sep  1 06:29:53 2016
@@ -0,0 +1,25 @@
+// Example source from breakpad's linux tutorial
+// https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/linux_starter_guide.md
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#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;
+}

Added: lldb/trunk/unittests/Process/minidump/Inputs/linux-x86_64.dmp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Process/minidump/Inputs/linux-x86_64.dmp?rev=280356&view=auto
==============================================================================
Binary files lldb/trunk/unittests/Process/minidump/Inputs/linux-x86_64.dmp (added) and lldb/trunk/unittests/Process/minidump/Inputs/linux-x86_64.dmp Thu Sep  1 06:29:53 2016 differ

Added: lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp?rev=280356&view=auto
==============================================================================
--- lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp (added)
+++ lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp Thu Sep  1 06:29:53 2016
@@ -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 <memory>
+
+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<MinidumpParser> 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<MinidumpParser> parser;
+};
+
+TEST_F(MinidumpParserTest, GetThreads)
+{
+    SetUpData("linux-x86_64.dmp");
+    llvm::Optional<std::vector<const MinidumpThread *>> 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<std::vector<const MinidumpThread *>> 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
+}




More information about the lldb-commits mailing list