diff options
Diffstat (limited to 'lldb/source/Plugins/Process')
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, |