summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/minidump
diff options
context:
space:
mode:
authorPavel Labath <pavel@labath.sk>2019-04-05 07:56:39 +0000
committerPavel Labath <pavel@labath.sk>2019-04-05 07:56:39 +0000
commit98edcd9b9c28adf36b085c1a33e10328552ae1d4 (patch)
tree58a8c07841d07fd033dab15f12451af0cd3abb0a /lldb/source/Plugins/Process/minidump
parent546bccf61c620893c0f94c84adf542b0bbad24bb (diff)
downloadbcm5719-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')
-rw-r--r--lldb/source/Plugins/Process/minidump/CMakeLists.txt1
-rw-r--r--lldb/source/Plugins/Process/minidump/MinidumpParser.cpp120
-rw-r--r--lldb/source/Plugins/Process/minidump/MinidumpParser.h10
-rw-r--r--lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp10
4 files changed, 23 insertions, 118 deletions
diff --git a/lldb/source/Plugins/Process/minidump/CMakeLists.txt b/lldb/source/Plugins/Process/minidump/CMakeLists.txt
index c90f4f0579f..afa3550dfe4 100644
--- a/lldb/source/Plugins/Process/minidump/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/minidump/CMakeLists.txt
@@ -16,5 +16,6 @@ add_lldb_library(lldbPluginProcessMinidump PLUGIN
lldbPluginProcessElfCore
LINK_COMPONENTS
BinaryFormat
+ Object
Support
)
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) {
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.h b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
index 77207726675..07d7d07e599 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.h
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
@@ -21,6 +21,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/Minidump.h"
// C includes
@@ -93,20 +94,17 @@ public:
static llvm::StringRef GetStreamTypeAsString(StreamType stream_type);
- const llvm::DenseMap<StreamType, LocationDescriptor> &
- GetDirectoryMap() const {
- return m_directory_map;
- }
+ llvm::object::MinidumpFile &GetMinidumpFile() { return *m_file; }
private:
MinidumpParser(lldb::DataBufferSP data_sp,
- llvm::DenseMap<StreamType, LocationDescriptor> directory_map);
+ std::unique_ptr<llvm::object::MinidumpFile> file);
MemoryRegionInfo FindMemoryRegion(lldb::addr_t load_addr) const;
private:
lldb::DataBufferSP m_data_sp;
- llvm::DenseMap<StreamType, LocationDescriptor> m_directory_map;
+ std::unique_ptr<llvm::object::MinidumpFile> m_file;
ArchSpec m_arch;
MemoryRegionInfos m_regions;
bool m_parsed_regions = false;
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index 4d16f82c493..d6ab58c0f05 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -718,10 +718,12 @@ public:
if (DumpDirectory()) {
s.Printf("RVA SIZE TYPE StreamType\n");
s.Printf("---------- ---------- ---------- --------------------------\n");
- for (const auto &pair: minidump.GetDirectoryMap())
- s.Printf("0x%8.8x 0x%8.8x 0x%8.8x %s\n", (uint32_t)pair.second.RVA,
- (uint32_t)pair.second.DataSize, (unsigned)pair.first,
- MinidumpParser::GetStreamTypeAsString(pair.first).data());
+ for (const auto &stream_desc : minidump.GetMinidumpFile().streams())
+ s.Printf(
+ "0x%8.8x 0x%8.8x 0x%8.8x %s\n", (uint32_t)stream_desc.Location.RVA,
+ (uint32_t)stream_desc.Location.DataSize,
+ (unsigned)(StreamType)stream_desc.Type,
+ MinidumpParser::GetStreamTypeAsString(stream_desc.Type).data());
s.Printf("\n");
}
auto DumpTextStream = [&](StreamType stream_type,
OpenPOWER on IntegriCloud