10
10
#include " NtStructures.h"
11
11
#include " RegisterContextMinidump_x86_32.h"
12
12
13
- #include " lldb/Utility/LLDBAssert.h"
14
13
#include " Plugins/Process/Utility/LinuxProcMaps.h"
14
+ #include " lldb/Utility/LLDBAssert.h"
15
15
16
16
// C includes
17
17
// C++ includes
23
23
using namespace lldb_private ;
24
24
using namespace minidump ;
25
25
26
- static llvm::Error stringError (llvm::StringRef Err) {
27
- return llvm::make_error<llvm::StringError>(Err,
28
- llvm::inconvertibleErrorCode ());
29
- }
30
-
31
26
const Header *ParseHeader (llvm::ArrayRef<uint8_t > &data) {
32
27
const Header *header = nullptr ;
33
28
Status error = consumeObject (data, header);
@@ -45,117 +40,26 @@ const Header *ParseHeader(llvm::ArrayRef<uint8_t> &data) {
45
40
46
41
llvm::Expected<MinidumpParser>
47
42
MinidumpParser::Create (const lldb::DataBufferSP &data_sp) {
48
- if (data_sp->GetByteSize () < sizeof (Header))
49
- return stringError (" Buffer too small." );
50
-
51
- llvm::ArrayRef<uint8_t > header_data (data_sp->GetBytes (),
52
- sizeof (Header));
53
- const Header *header = ParseHeader (header_data);
54
- if (!header)
55
- return stringError (" invalid minidump: can't parse the header" );
56
-
57
- // A minidump without at least one stream is clearly ill-formed
58
- if (header->NumberOfStreams == 0 )
59
- return stringError (" invalid minidump: no streams present" );
60
-
61
- struct FileRange {
62
- uint32_t offset = 0 ;
63
- uint32_t size = 0 ;
64
-
65
- FileRange (uint32_t offset, uint32_t size) : offset(offset), size(size) {}
66
- uint32_t end () const { return offset + size; }
67
- };
68
-
69
- const uint32_t file_size = data_sp->GetByteSize ();
70
-
71
- // Build a global minidump file map, checking for:
72
- // - overlapping streams/data structures
73
- // - truncation (streams pointing past the end of file)
74
- std::vector<FileRange> minidump_map;
75
-
76
- minidump_map.emplace_back (0 , sizeof (Header));
77
-
78
- // Add the directory entries to the file map
79
- FileRange directory_range (header->StreamDirectoryRVA ,
80
- header->NumberOfStreams * sizeof (Directory));
81
- if (directory_range.end () > file_size)
82
- return stringError (" invalid minidump: truncated streams directory" );
83
- minidump_map.push_back (directory_range);
84
-
85
- llvm::DenseMap<StreamType, LocationDescriptor> directory_map;
86
-
87
- // Parse stream directory entries
88
- llvm::ArrayRef<uint8_t > directory_data (
89
- data_sp->GetBytes () + directory_range.offset , directory_range.size );
90
- for (uint32_t i = 0 ; i < header->NumberOfStreams ; ++i) {
91
- const Directory *directory_entry = nullptr ;
92
- Status error = consumeObject (directory_data, directory_entry);
93
- if (error.Fail ())
94
- return error.ToError ();
95
- if (directory_entry->Type == StreamType::Unused) {
96
- // Ignore dummy streams (technically ill-formed, but a number of
97
- // existing minidumps seem to contain such streams)
98
- if (directory_entry->Location .DataSize == 0 )
99
- continue ;
100
- return stringError (" invalid minidump: bad stream type" );
101
- }
102
- // Update the streams map, checking for duplicate stream types
103
- if (!directory_map
104
- .insert ({directory_entry->Type , directory_entry->Location })
105
- .second )
106
- return stringError (" invalid minidump: duplicate stream type" );
107
-
108
- // Ignore the zero-length streams for layout checks
109
- if (directory_entry->Location .DataSize != 0 ) {
110
- minidump_map.emplace_back (directory_entry->Location .RVA ,
111
- directory_entry->Location .DataSize );
112
- }
113
- }
43
+ auto ExpectedFile = llvm::object::MinidumpFile::create (
44
+ llvm::MemoryBufferRef (toStringRef (data_sp->GetData ()), " minidump" ));
45
+ if (!ExpectedFile)
46
+ return ExpectedFile.takeError ();
114
47
115
- // Sort the file map ranges by start offset
116
- llvm::sort (minidump_map.begin (), minidump_map.end (),
117
- [](const FileRange &a, const FileRange &b) {
118
- return a.offset < b.offset ;
119
- });
120
-
121
- // Check for overlapping streams/data structures
122
- for (size_t i = 1 ; i < minidump_map.size (); ++i) {
123
- const auto &prev_range = minidump_map[i - 1 ];
124
- if (prev_range.end () > minidump_map[i].offset )
125
- return stringError (" invalid minidump: overlapping streams" );
126
- }
127
-
128
- // Check for streams past the end of file
129
- const auto &last_range = minidump_map.back ();
130
- if (last_range.end () > file_size)
131
- return stringError (" invalid minidump: truncated stream" );
132
-
133
- return MinidumpParser (std::move (data_sp), std::move (directory_map));
48
+ return MinidumpParser (data_sp, std::move (*ExpectedFile));
134
49
}
135
50
136
- MinidumpParser::MinidumpParser (
137
- lldb::DataBufferSP data_sp,
138
- llvm::DenseMap<StreamType, LocationDescriptor> directory_map)
139
- : m_data_sp(std::move(data_sp)), m_directory_map(std::move(directory_map)) {
140
- }
51
+ MinidumpParser::MinidumpParser (lldb::DataBufferSP data_sp,
52
+ std::unique_ptr<llvm::object::MinidumpFile> file)
53
+ : m_data_sp(std::move(data_sp)), m_file(std::move(file)) {}
141
54
142
55
llvm::ArrayRef<uint8_t > MinidumpParser::GetData () {
143
56
return llvm::ArrayRef<uint8_t >(m_data_sp->GetBytes (),
144
57
m_data_sp->GetByteSize ());
145
58
}
146
59
147
- llvm::ArrayRef<uint8_t >
148
- MinidumpParser::GetStream (StreamType stream_type) {
149
- auto iter = m_directory_map.find (stream_type);
150
- if (iter == m_directory_map.end ())
151
- return {};
152
-
153
- // check if there is enough data
154
- if (iter->second .RVA + iter->second .DataSize > m_data_sp->GetByteSize ())
155
- return {};
156
-
157
- return llvm::ArrayRef<uint8_t >(m_data_sp->GetBytes () + iter->second .RVA ,
158
- iter->second .DataSize );
60
+ llvm::ArrayRef<uint8_t > MinidumpParser::GetStream (StreamType stream_type) {
61
+ return m_file->getRawStream (stream_type)
62
+ .getValueOr (llvm::ArrayRef<uint8_t >());
159
63
}
160
64
161
65
llvm::Optional<std::string> MinidumpParser::GetMinidumpString (uint32_t rva) {
0 commit comments