[Lldb-commits] [lldb] r281348 - MinidumpParsing: pid, modules, exceptions, strings
Dimitar Vlahovski via lldb-commits
lldb-commits at lists.llvm.org
Tue Sep 13 08:54:39 PDT 2016
Author: dvlahovski
Date: Tue Sep 13 10:54:38 2016
New Revision: 281348
URL: http://llvm.org/viewvc/llvm-project?rev=281348&view=rev
Log:
MinidumpParsing: pid, modules, exceptions, strings
Summary:
Added parsing of the MiscInfo data stream.
The main member of it that we care about is the process_id
On Linux generated Minidump (from breakpad) we don't have
the MiscInfo, we have the /proc/$pid/status from where we can get the
pid.
Also parsing the module list - the list of all of the loaded
modules/shared libraries.
Parsing the exception stream.
Parsing MinidumpStrings.
I have unit tests for all of that.
Also added some tests using a Minidump generated from Windows tools (not
from breakpad)
Reviewers: labath, zturner
Subscribers: beanz, lldb-commits
Differential Revision: https://reviews.llvm.org/D24385
Added:
lldb/trunk/unittests/Process/minidump/Inputs/fizzbuzz_no_heap.dmp
Modified:
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/CMakeLists.txt
lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp
Modified: lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp?rev=281348&r1=281347&r2=281348&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp (original)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp Tue Sep 13 10:54:38 2016
@@ -1,5 +1,4 @@
-//===-- MinidumpParser.cpp ---------------------------------------*- C++
-//-*-===//
+//===-- MinidumpParser.cpp ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -56,13 +55,12 @@ MinidumpParser::Create(const lldb::DataB
directory->location;
}
- MinidumpParser parser(data_buf_sp, header, directory_map);
- return llvm::Optional<MinidumpParser>(parser);
+ return MinidumpParser(data_buf_sp, header, std::move(directory_map));
}
MinidumpParser::MinidumpParser(
const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header,
- const llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &directory_map)
+ llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &&directory_map)
: m_data_sp(data_buf_sp), m_header(header), m_directory_map(directory_map) {
}
@@ -70,50 +68,48 @@ lldb::offset_t MinidumpParser::GetByteSi
return m_data_sp->GetByteSize();
}
-llvm::Optional<llvm::ArrayRef<uint8_t>>
+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;
+ return {};
// check if there is enough data
if (iter->second.rva + iter->second.data_size > m_data_sp->GetByteSize())
- return llvm::None;
+ return {};
+
+ return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes() + iter->second.rva,
+ iter->second.data_size);
+}
- 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::string> MinidumpParser::GetMinidumpString(uint32_t rva) {
+ auto arr_ref = m_data_sp->GetData();
+ if (rva > arr_ref.size())
+ return llvm::None;
+ arr_ref = arr_ref.drop_front(rva);
+ return parseMinidumpString(arr_ref);
}
-llvm::Optional<std::vector<const MinidumpThread *>>
-MinidumpParser::GetThreads() {
- llvm::Optional<llvm::ArrayRef<uint8_t>> data =
- GetStream(MinidumpStreamType::ThreadList);
+llvm::ArrayRef<MinidumpThread> MinidumpParser::GetThreads() {
+ llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::ThreadList);
- if (!data)
+ if (data.size() == 0)
return llvm::None;
- return MinidumpThread::ParseThreadList(data.getValue());
+ return MinidumpThread::ParseThreadList(data);
}
const MinidumpSystemInfo *MinidumpParser::GetSystemInfo() {
- llvm::Optional<llvm::ArrayRef<uint8_t>> data =
- GetStream(MinidumpStreamType::SystemInfo);
+ llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::SystemInfo);
- if (!data)
+ if (data.size() == 0)
return nullptr;
- return MinidumpSystemInfo::Parse(data.getValue());
+ return MinidumpSystemInfo::Parse(data);
}
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)
@@ -122,35 +118,110 @@ ArchSpec MinidumpParser::GetArchitecture
// TODO what to do about big endiand flavors of arm ?
// TODO set the arm subarch stuff if the minidump has info about it
+ llvm::Triple triple;
+ triple.setVendor(llvm::Triple::VendorType::UnknownVendor);
+
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);
+ triple.setArch(llvm::Triple::ArchType::x86);
break;
case MinidumpCPUArchitecture::AMD64:
- arch_spec.GetTriple().setArch(llvm::Triple::ArchType::x86_64);
+ triple.setArch(llvm::Triple::ArchType::x86_64);
break;
case MinidumpCPUArchitecture::ARM:
- arch_spec.GetTriple().setArch(llvm::Triple::ArchType::arm);
+ triple.setArch(llvm::Triple::ArchType::arm);
break;
case MinidumpCPUArchitecture::ARM64:
- arch_spec.GetTriple().setArch(llvm::Triple::ArchType::aarch64);
+ triple.setArch(llvm::Triple::ArchType::aarch64);
+ break;
+ default:
+ triple.setArch(llvm::Triple::ArchType::UnknownArch);
break;
default:
break;
}
+ const MinidumpOSPlatform os = static_cast<const MinidumpOSPlatform>(
+ static_cast<const uint32_t>(system_info->platform_id));
+
+ // TODO add all of the OSes that Minidump/breakpad distinguishes?
+ switch (os) {
+ case MinidumpOSPlatform::Win32S:
+ case MinidumpOSPlatform::Win32Windows:
+ case MinidumpOSPlatform::Win32NT:
+ case MinidumpOSPlatform::Win32CE:
+ triple.setOS(llvm::Triple::OSType::Win32);
+ break;
+ case MinidumpOSPlatform::Linux:
+ triple.setOS(llvm::Triple::OSType::Linux);
+ break;
+ case MinidumpOSPlatform::MacOSX:
+ triple.setOS(llvm::Triple::OSType::MacOSX);
+ break;
+ case MinidumpOSPlatform::Android:
+ triple.setOS(llvm::Triple::OSType::Linux);
+ triple.setEnvironment(llvm::Triple::EnvironmentType::Android);
+ break;
+ default:
+ triple.setOS(llvm::Triple::OSType::UnknownOS);
+ break;
+ }
+
+ arch_spec.SetTriple(triple);
+
return arch_spec;
}
const MinidumpMiscInfo *MinidumpParser::GetMiscInfo() {
- llvm::Optional<llvm::ArrayRef<uint8_t>> data =
- GetStream(MinidumpStreamType::MiscInfo);
+ llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::MiscInfo);
+
+ if (data.size() == 0)
+ return nullptr;
+
+ return MinidumpMiscInfo::Parse(data);
+}
+
+llvm::Optional<LinuxProcStatus> MinidumpParser::GetLinuxProcStatus() {
+ llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::LinuxProcStatus);
+
+ if (data.size() == 0)
+ return llvm::None;
+
+ return LinuxProcStatus::Parse(data);
+}
+
+llvm::Optional<lldb::pid_t> MinidumpParser::GetPid() {
+ const MinidumpMiscInfo *misc_info = GetMiscInfo();
+ if (misc_info != nullptr) {
+ return misc_info->GetPid();
+ }
+
+ llvm::Optional<LinuxProcStatus> proc_status = GetLinuxProcStatus();
+ if (proc_status.hasValue()) {
+ return proc_status->GetPid();
+ }
+
+ return llvm::None;
+}
+
+llvm::ArrayRef<MinidumpModule> MinidumpParser::GetModuleList() {
+ llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::ModuleList);
+
+ if (data.size() == 0)
+ return {};
+
+ return MinidumpModule::ParseModuleList(data);
+}
+
+const MinidumpExceptionStream *MinidumpParser::GetExceptionStream() {
+ llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::Exception);
- if (!data)
+ if (data.size() == 0)
return nullptr;
- return MinidumpMiscInfo::Parse(data.getValue());
+ return MinidumpExceptionStream::Parse(data);
}
Modified: lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h?rev=281348&r1=281347&r2=281348&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h (original)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h Tue Sep 13 10:54:38 2016
@@ -22,6 +22,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
// C includes
@@ -40,10 +41,11 @@ public:
lldb::offset_t GetByteSize();
- llvm::Optional<llvm::ArrayRef<uint8_t>>
- GetStream(MinidumpStreamType stream_type);
+ llvm::ArrayRef<uint8_t> GetStream(MinidumpStreamType stream_type);
- llvm::Optional<std::vector<const MinidumpThread *>> GetThreads();
+ llvm::Optional<std::string> GetMinidumpString(uint32_t rva);
+
+ llvm::ArrayRef<MinidumpThread> GetThreads();
const MinidumpSystemInfo *GetSystemInfo();
@@ -51,15 +53,22 @@ public:
const MinidumpMiscInfo *GetMiscInfo();
+ llvm::Optional<LinuxProcStatus> GetLinuxProcStatus();
+
+ llvm::Optional<lldb::pid_t> GetPid();
+
+ llvm::ArrayRef<MinidumpModule> GetModuleList();
+
+ const MinidumpExceptionStream *GetExceptionStream();
+
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);
+ MinidumpParser(
+ const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header,
+ llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &&directory_map);
};
} // namespace minidump
Modified: lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp?rev=281348&r1=281347&r2=281348&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp (original)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp Tue Sep 13 10:54:38 2016
@@ -9,7 +9,6 @@
// Project includes
#include "MinidumpTypes.h"
-#include "MinidumpParser.h"
// Other libraries and framework includes
// C includes
@@ -40,6 +39,35 @@ const MinidumpHeader *MinidumpHeader::Pa
return header;
}
+// Minidump string
+llvm::Optional<std::string>
+lldb_private::minidump::parseMinidumpString(llvm::ArrayRef<uint8_t> &data) {
+ std::string result;
+
+ const uint32_t *source_length;
+ Error error = consumeObject(data, source_length);
+ if (error.Fail() || *source_length > data.size() || *source_length % 2 != 0)
+ return llvm::None;
+
+ auto source_start = reinterpret_cast<const UTF16 *>(data.data());
+ // source_length is the length of the string in bytes
+ // we need the length of the string in UTF-16 characters/code points (16 bits
+ // per char)
+ // that's why it's divided by 2
+ const auto source_end = source_start + (*source_length) / 2;
+ // resize to worst case length
+ result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * (*source_length) / 2);
+ auto result_start = reinterpret_cast<UTF8 *>(&result[0]);
+ const auto result_end = result_start + result.size();
+ ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end,
+ strictConversion);
+ const auto result_size =
+ std::distance(reinterpret_cast<UTF8 *>(&result[0]), result_start);
+ result.resize(result_size); // shrink to actual length
+
+ return result;
+}
+
// MinidumpThread
const MinidumpThread *MinidumpThread::Parse(llvm::ArrayRef<uint8_t> &data) {
const MinidumpThread *thread = nullptr;
@@ -50,24 +78,15 @@ const MinidumpThread *MinidumpThread::Pa
return thread;
}
-llvm::Optional<std::vector<const MinidumpThread *>>
+llvm::ArrayRef<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;
+ if (error.Fail() || *thread_count * sizeof(MinidumpThread) > data.size())
+ return {};
- 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);
+ return llvm::ArrayRef<MinidumpThread>(
+ reinterpret_cast<const MinidumpThread *>(data.data()), *thread_count);
}
// MinidumpSystemInfo
@@ -90,3 +109,70 @@ const MinidumpMiscInfo *MinidumpMiscInfo
return misc_info;
}
+
+llvm::Optional<lldb::pid_t> MinidumpMiscInfo::GetPid() const {
+ uint32_t pid_flag =
+ static_cast<const uint32_t>(MinidumpMiscInfoFlags::ProcessID);
+ if (flags1 & pid_flag)
+ return llvm::Optional<lldb::pid_t>(process_id);
+
+ return llvm::None;
+}
+
+// Linux Proc Status
+// it's stored as an ascii string in the file
+llvm::Optional<LinuxProcStatus>
+LinuxProcStatus::Parse(llvm::ArrayRef<uint8_t> &data) {
+ LinuxProcStatus result;
+ result.proc_status =
+ llvm::StringRef(reinterpret_cast<const char *>(data.data()), data.size());
+ data = data.drop_front(data.size());
+
+ llvm::SmallVector<llvm::StringRef, 0> lines;
+ result.proc_status.split(lines, '\n', 42);
+ // /proc/$pid/status has 41 lines, but why not use 42?
+ for (auto line : lines) {
+ if (line.consume_front("Pid:")) {
+ line = line.trim();
+ if (!line.getAsInteger(10, result.pid))
+ return result;
+ }
+ }
+
+ return llvm::None;
+}
+
+lldb::pid_t LinuxProcStatus::GetPid() const { return pid; }
+
+// Module stuff
+const MinidumpModule *MinidumpModule::Parse(llvm::ArrayRef<uint8_t> &data) {
+ const MinidumpModule *module = nullptr;
+ Error error = consumeObject(data, module);
+ if (error.Fail())
+ return nullptr;
+
+ return module;
+}
+
+llvm::ArrayRef<MinidumpModule>
+MinidumpModule::ParseModuleList(llvm::ArrayRef<uint8_t> &data) {
+
+ const llvm::support::ulittle32_t *modules_count;
+ Error error = consumeObject(data, modules_count);
+ if (error.Fail() || *modules_count * sizeof(MinidumpModule) > data.size())
+ return {};
+
+ return llvm::ArrayRef<MinidumpModule>(
+ reinterpret_cast<const MinidumpModule *>(data.data()), *modules_count);
+}
+
+// Exception stuff
+const MinidumpExceptionStream *
+MinidumpExceptionStream::Parse(llvm::ArrayRef<uint8_t> &data) {
+ const MinidumpExceptionStream *exception_stream = nullptr;
+ Error error = consumeObject(data, exception_stream);
+ if (error.Fail())
+ return nullptr;
+
+ return exception_stream;
+}
Modified: lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h?rev=281348&r1=281347&r2=281348&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h (original)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h Tue Sep 13 10:54:38 2016
@@ -18,6 +18,9 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Endian.h"
// C includes
@@ -148,6 +151,12 @@ enum class MinidumpPCPUInformationARMElf
LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IDIVT)
};
+enum class MinidumpMiscInfoFlags : uint32_t {
+ ProcessID = (1 << 0),
+ ProcessTimes = (1 << 1),
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ ProcessTimes)
+};
+
template <typename T>
Error consumeObject(llvm::ArrayRef<uint8_t> &Buffer, const T *&Object) {
Error error;
@@ -161,6 +170,11 @@ Error consumeObject(llvm::ArrayRef<uint8
return error;
}
+// parse a MinidumpString which is with UTF-16
+// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680395(v=vs.85).aspx
+llvm::Optional<std::string> parseMinidumpString(llvm::ArrayRef<uint8_t> &data);
+
// Reference:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680378(v=vs.85).aspx
struct MinidumpHeader {
@@ -219,7 +233,7 @@ struct MinidumpThread {
static const MinidumpThread *Parse(llvm::ArrayRef<uint8_t> &data);
- static llvm::Optional<std::vector<const MinidumpThread *>>
+ static llvm::ArrayRef<MinidumpThread>
ParseThreadList(llvm::ArrayRef<uint8_t> &data);
};
static_assert(sizeof(MinidumpThread) == 48,
@@ -272,12 +286,12 @@ struct MinidumpSystemInfo {
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;
+ // flags1 represents what info in the struct is valid
llvm::support::ulittle32_t flags1;
llvm::support::ulittle32_t process_id;
llvm::support::ulittle32_t process_create_time;
@@ -285,10 +299,94 @@ struct MinidumpMiscInfo {
llvm::support::ulittle32_t process_kernel_time;
static const MinidumpMiscInfo *Parse(llvm::ArrayRef<uint8_t> &data);
+
+ llvm::Optional<lldb::pid_t> GetPid() const;
};
static_assert(sizeof(MinidumpMiscInfo) == 24,
"sizeof MinidumpMiscInfo is not correct!");
+// The /proc/pid/status is saved as an ascii string in the file
+class LinuxProcStatus {
+public:
+ llvm::StringRef proc_status;
+ lldb::pid_t pid;
+
+ static llvm::Optional<LinuxProcStatus> Parse(llvm::ArrayRef<uint8_t> &data);
+
+ lldb::pid_t GetPid() const;
+
+private:
+ LinuxProcStatus() = default;
+};
+
+// MinidumpModule stuff
+struct MinidumpVSFixedFileInfo {
+ llvm::support::ulittle32_t signature;
+ llvm::support::ulittle32_t struct_version;
+ llvm::support::ulittle32_t file_version_hi;
+ llvm::support::ulittle32_t file_version_lo;
+ llvm::support::ulittle32_t product_version_hi;
+ llvm::support::ulittle32_t product_version_lo;
+ // file_flags_mask - identifies valid bits in fileFlags
+ llvm::support::ulittle32_t file_flags_mask;
+ llvm::support::ulittle32_t file_flags;
+ llvm::support::ulittle32_t file_os;
+ llvm::support::ulittle32_t file_type;
+ llvm::support::ulittle32_t file_subtype;
+ llvm::support::ulittle32_t file_date_hi;
+ llvm::support::ulittle32_t file_date_lo;
+};
+static_assert(sizeof(MinidumpVSFixedFileInfo) == 52,
+ "sizeof MinidumpVSFixedFileInfo is not correct!");
+
+struct MinidumpModule {
+ llvm::support::ulittle64_t base_of_image;
+ llvm::support::ulittle32_t size_of_image;
+ llvm::support::ulittle32_t checksum;
+ llvm::support::ulittle32_t time_date_stamp;
+ llvm::support::ulittle32_t module_name_rva;
+ MinidumpVSFixedFileInfo version_info;
+ MinidumpLocationDescriptor CV_record;
+ MinidumpLocationDescriptor misc_record;
+ llvm::support::ulittle32_t reserved0[2];
+ llvm::support::ulittle32_t reserved1[2];
+
+ static const MinidumpModule *Parse(llvm::ArrayRef<uint8_t> &data);
+
+ static llvm::ArrayRef<MinidumpModule>
+ ParseModuleList(llvm::ArrayRef<uint8_t> &data);
+};
+static_assert(sizeof(MinidumpModule) == 108,
+ "sizeof MinidumpVSFixedFileInfo is not correct!");
+
+// Exception stuff
+struct MinidumpException {
+ enum {
+ MaxParams = 15,
+ };
+
+ 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[MaxParams];
+};
+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;
+ MinidumpLocationDescriptor thread_context;
+
+ static const MinidumpExceptionStream *Parse(llvm::ArrayRef<uint8_t> &data);
+};
+static_assert(sizeof(MinidumpExceptionStream) == 168,
+ "sizeof MinidumpExceptionStream is not correct!");
+
} // namespace minidump
} // namespace lldb_private
#endif // liblldb_MinidumpTypes_h_
Modified: lldb/trunk/unittests/Process/minidump/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Process/minidump/CMakeLists.txt?rev=281348&r1=281347&r2=281348&view=diff
==============================================================================
--- lldb/trunk/unittests/Process/minidump/CMakeLists.txt (original)
+++ lldb/trunk/unittests/Process/minidump/CMakeLists.txt Tue Sep 13 10:54:38 2016
@@ -3,6 +3,7 @@ add_lldb_unittest(LLDBMinidumpTests
)
set(test_inputs
- linux-x86_64.dmp)
+ linux-x86_64.dmp
+ fizzbuzz_no_heap.dmp)
add_unittest_inputs(LLDBMinidumpTests "${test_inputs}")
Added: lldb/trunk/unittests/Process/minidump/Inputs/fizzbuzz_no_heap.dmp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Process/minidump/Inputs/fizzbuzz_no_heap.dmp?rev=281348&view=auto
==============================================================================
Binary files lldb/trunk/unittests/Process/minidump/Inputs/fizzbuzz_no_heap.dmp (added) and lldb/trunk/unittests/Process/minidump/Inputs/fizzbuzz_no_heap.dmp Tue Sep 13 10:54:38 2016 differ
Modified: lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp?rev=281348&r1=281347&r2=281348&view=diff
==============================================================================
--- lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp (original)
+++ lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp Tue Sep 13 10:54:38 2016
@@ -59,33 +59,111 @@ public:
TEST_F(MinidumpParserTest, GetThreads) {
SetUpData("linux-x86_64.dmp");
- llvm::Optional<std::vector<const MinidumpThread *>> thread_list;
+ llvm::ArrayRef<MinidumpThread> thread_list;
thread_list = parser->GetThreads();
- ASSERT_TRUE(thread_list.hasValue());
- ASSERT_EQ(1UL, thread_list->size());
+ ASSERT_EQ(1UL, thread_list.size());
- const MinidumpThread *thread = thread_list.getValue()[0];
- ASSERT_EQ(16001UL, thread->thread_id);
+ const MinidumpThread thread = thread_list[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;
+ llvm::ArrayRef<MinidumpThread> thread_list;
thread_list = parser->GetThreads();
- ASSERT_FALSE(thread_list.hasValue());
+ ASSERT_EQ(0UL, thread_list.size());
}
TEST_F(MinidumpParserTest, GetArchitecture) {
SetUpData("linux-x86_64.dmp");
ASSERT_EQ(llvm::Triple::ArchType::x86_64,
- parser->GetArchitecture().GetTriple().getArch());
+ parser->GetArchitecture().GetMachine());
+ ASSERT_EQ(llvm::Triple::OSType::Linux,
+ parser->GetArchitecture().GetTriple().getOS());
}
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
+}
+
+TEST_F(MinidumpParserTest, GetLinuxProcStatus) {
+ SetUpData("linux-x86_64.dmp");
+ llvm::Optional<LinuxProcStatus> proc_status = parser->GetLinuxProcStatus();
+ ASSERT_TRUE(proc_status.hasValue());
+ lldb::pid_t pid = proc_status->GetPid();
+ ASSERT_EQ(16001UL, pid);
+}
+
+TEST_F(MinidumpParserTest, GetPid) {
+ SetUpData("linux-x86_64.dmp");
+ llvm::Optional<lldb::pid_t> pid = parser->GetPid();
+ ASSERT_TRUE(pid.hasValue());
+ ASSERT_EQ(16001UL, pid.getValue());
+}
+
+TEST_F(MinidumpParserTest, GetModuleList) {
+ SetUpData("linux-x86_64.dmp");
+ llvm::ArrayRef<MinidumpModule> modules = parser->GetModuleList();
+ ASSERT_EQ(8UL, modules.size());
+ std::string module_names[8] = {
+ "/usr/local/google/home/dvlahovski/projects/test_breakpad/a.out",
+ "/lib/x86_64-linux-gnu/libm-2.19.so",
+ "/lib/x86_64-linux-gnu/libc-2.19.so",
+ "/lib/x86_64-linux-gnu/libgcc_s.so.1",
+ "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19",
+ "/lib/x86_64-linux-gnu/libpthread-2.19.so",
+ "/lib/x86_64-linux-gnu/ld-2.19.so",
+ "linux-gate.so",
+ };
+
+ for (int i = 0; i < 8; ++i) {
+ llvm::Optional<std::string> name =
+ parser->GetMinidumpString(modules[i].module_name_rva);
+ ASSERT_TRUE(name.hasValue());
+ ASSERT_EQ(module_names[i], name.getValue());
+ }
+}
+
+TEST_F(MinidumpParserTest, GetExceptionStream) {
+ SetUpData("linux-x86_64.dmp");
+ const MinidumpExceptionStream *exception_stream =
+ parser->GetExceptionStream();
+ ASSERT_NE(nullptr, exception_stream);
+ ASSERT_EQ(11UL, exception_stream->exception_record.exception_code);
+}
+
+// Windows Minidump tests
+// fizzbuzz_no_heap.dmp is copied from the WinMiniDump tests
+TEST_F(MinidumpParserTest, GetArchitectureWindows) {
+ SetUpData("fizzbuzz_no_heap.dmp");
+ ASSERT_EQ(llvm::Triple::ArchType::x86,
+ parser->GetArchitecture().GetMachine());
+ ASSERT_EQ(llvm::Triple::OSType::Win32,
+ parser->GetArchitecture().GetTriple().getOS());
+}
+
+TEST_F(MinidumpParserTest, GetLinuxProcStatusWindows) {
+ SetUpData("fizzbuzz_no_heap.dmp");
+ llvm::Optional<LinuxProcStatus> proc_status = parser->GetLinuxProcStatus();
+ ASSERT_FALSE(proc_status.hasValue());
+}
+
+TEST_F(MinidumpParserTest, GetMiscInfoWindows) {
+ SetUpData("fizzbuzz_no_heap.dmp");
+ const MinidumpMiscInfo *misc_info = parser->GetMiscInfo();
+ ASSERT_NE(nullptr, misc_info);
+ llvm::Optional<lldb::pid_t> pid = misc_info->GetPid();
+ ASSERT_TRUE(pid.hasValue());
+ ASSERT_EQ(4440UL, pid.getValue());
+}
+
+TEST_F(MinidumpParserTest, GetPidWindows) {
+ SetUpData("fizzbuzz_no_heap.dmp");
+ llvm::Optional<lldb::pid_t> pid = parser->GetPid();
+ ASSERT_TRUE(pid.hasValue());
+ ASSERT_EQ(4440UL, pid.getValue());
}
More information about the lldb-commits
mailing list