diff options
author | Pavel Labath <pavel@labath.sk> | 2019-04-05 07:56:39 +0000 |
---|---|---|
committer | Pavel Labath <pavel@labath.sk> | 2019-04-05 07:56:39 +0000 |
commit | 98edcd9b9c28adf36b085c1a33e10328552ae1d4 (patch) | |
tree | 58a8c07841d07fd033dab15f12451af0cd3abb0a /lldb/source/Plugins/Process/minidump/MinidumpParser.cpp | |
parent | 546bccf61c620893c0f94c84adf542b0bbad24bb (diff) | |
download | bcm5719-llvm-98edcd9b9c28adf36b085c1a33e10328552ae1d4.tar.gz bcm5719-llvm-98edcd9b9c28adf36b085c1a33e10328552ae1d4.zip |
MinidumpParser: use minidump parser in llvm/Object
This patch removes the lower layers of the minidump parsing code from
the MinidumpParser class, and replaces it with the minidump parser in
llvm.
Not all functionality is already avaiable in the llvm class, but it is
enough for us to be able to stop enumerating streams manually, and rely
on the minidump directory parsing code from the llvm class.
This also removes some checked-in binaries which were used to test error
handling in the parser, as the error handling is now done (and tested)
in llvm. Instead I just add one test that ensures we correctly propagate
the errors reported by the llvm parser. The input for this test can be
written in yaml instead of a checked-in binary.
llvm-svn: 357748
Diffstat (limited to 'lldb/source/Plugins/Process/minidump/MinidumpParser.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/minidump/MinidumpParser.cpp | 120 |
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) { |