summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/minidump/MinidumpParser.cpp')
-rw-r--r--lldb/source/Plugins/Process/minidump/MinidumpParser.cpp120
1 files changed, 12 insertions, 108 deletions
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
index 64af45f657c..eab0c039f54 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -10,8 +10,8 @@
#include "NtStructures.h"
#include "RegisterContextMinidump_x86_32.h"
-#include "lldb/Utility/LLDBAssert.h"
#include "Plugins/Process/Utility/LinuxProcMaps.h"
+#include "lldb/Utility/LLDBAssert.h"
// C includes
// C++ includes
@@ -23,11 +23,6 @@
using namespace lldb_private;
using namespace minidump;
-static llvm::Error stringError(llvm::StringRef Err) {
- return llvm::make_error<llvm::StringError>(Err,
- llvm::inconvertibleErrorCode());
-}
-
const Header *ParseHeader(llvm::ArrayRef<uint8_t> &data) {
const Header *header = nullptr;
Status error = consumeObject(data, header);
@@ -45,117 +40,26 @@ const Header *ParseHeader(llvm::ArrayRef<uint8_t> &data) {
llvm::Expected<MinidumpParser>
MinidumpParser::Create(const lldb::DataBufferSP &data_sp) {
- if (data_sp->GetByteSize() < sizeof(Header))
- return stringError("Buffer too small.");
-
- llvm::ArrayRef<uint8_t> header_data(data_sp->GetBytes(),
- sizeof(Header));
- const Header *header = ParseHeader(header_data);
- if (!header)
- return stringError("invalid minidump: can't parse the header");
-
- // A minidump without at least one stream is clearly ill-formed
- if (header->NumberOfStreams == 0)
- return stringError("invalid minidump: no streams present");
-
- struct FileRange {
- uint32_t offset = 0;
- uint32_t size = 0;
-
- FileRange(uint32_t offset, uint32_t size) : offset(offset), size(size) {}
- uint32_t end() const { return offset + size; }
- };
-
- const uint32_t file_size = data_sp->GetByteSize();
-
- // Build a global minidump file map, checking for:
- // - overlapping streams/data structures
- // - truncation (streams pointing past the end of file)
- std::vector<FileRange> minidump_map;
-
- minidump_map.emplace_back(0, sizeof(Header));
-
- // Add the directory entries to the file map
- FileRange directory_range(header->StreamDirectoryRVA,
- header->NumberOfStreams * sizeof(Directory));
- if (directory_range.end() > file_size)
- return stringError("invalid minidump: truncated streams directory");
- minidump_map.push_back(directory_range);
-
- llvm::DenseMap<StreamType, LocationDescriptor> directory_map;
-
- // Parse stream directory entries
- llvm::ArrayRef<uint8_t> directory_data(
- data_sp->GetBytes() + directory_range.offset, directory_range.size);
- for (uint32_t i = 0; i < header->NumberOfStreams; ++i) {
- const Directory *directory_entry = nullptr;
- Status error = consumeObject(directory_data, directory_entry);
- if (error.Fail())
- return error.ToError();
- if (directory_entry->Type == StreamType::Unused) {
- // Ignore dummy streams (technically ill-formed, but a number of
- // existing minidumps seem to contain such streams)
- if (directory_entry->Location.DataSize == 0)
- continue;
- return stringError("invalid minidump: bad stream type");
- }
- // Update the streams map, checking for duplicate stream types
- if (!directory_map
- .insert({directory_entry->Type, directory_entry->Location})
- .second)
- return stringError("invalid minidump: duplicate stream type");
-
- // Ignore the zero-length streams for layout checks
- if (directory_entry->Location.DataSize != 0) {
- minidump_map.emplace_back(directory_entry->Location.RVA,
- directory_entry->Location.DataSize);
- }
- }
+ auto ExpectedFile = llvm::object::MinidumpFile::create(
+ llvm::MemoryBufferRef(toStringRef(data_sp->GetData()), "minidump"));
+ if (!ExpectedFile)
+ return ExpectedFile.takeError();
- // Sort the file map ranges by start offset
- llvm::sort(minidump_map.begin(), minidump_map.end(),
- [](const FileRange &a, const FileRange &b) {
- return a.offset < b.offset;
- });
-
- // Check for overlapping streams/data structures
- for (size_t i = 1; i < minidump_map.size(); ++i) {
- const auto &prev_range = minidump_map[i - 1];
- if (prev_range.end() > minidump_map[i].offset)
- return stringError("invalid minidump: overlapping streams");
- }
-
- // Check for streams past the end of file
- const auto &last_range = minidump_map.back();
- if (last_range.end() > file_size)
- return stringError("invalid minidump: truncated stream");
-
- return MinidumpParser(std::move(data_sp), std::move(directory_map));
+ return MinidumpParser(data_sp, std::move(*ExpectedFile));
}
-MinidumpParser::MinidumpParser(
- lldb::DataBufferSP data_sp,
- llvm::DenseMap<StreamType, LocationDescriptor> directory_map)
- : m_data_sp(std::move(data_sp)), m_directory_map(std::move(directory_map)) {
-}
+MinidumpParser::MinidumpParser(lldb::DataBufferSP data_sp,
+ std::unique_ptr<llvm::object::MinidumpFile> file)
+ : m_data_sp(std::move(data_sp)), m_file(std::move(file)) {}
llvm::ArrayRef<uint8_t> MinidumpParser::GetData() {
return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes(),
m_data_sp->GetByteSize());
}
-llvm::ArrayRef<uint8_t>
-MinidumpParser::GetStream(StreamType stream_type) {
- auto iter = m_directory_map.find(stream_type);
- if (iter == m_directory_map.end())
- return {};
-
- // check if there is enough data
- if (iter->second.RVA + iter->second.DataSize > m_data_sp->GetByteSize())
- return {};
-
- return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes() + iter->second.RVA,
- iter->second.DataSize);
+llvm::ArrayRef<uint8_t> MinidumpParser::GetStream(StreamType stream_type) {
+ return m_file->getRawStream(stream_type)
+ .getValueOr(llvm::ArrayRef<uint8_t>());
}
llvm::Optional<std::string> MinidumpParser::GetMinidumpString(uint32_t rva) {
OpenPOWER on IntegriCloud