11
11
12
12
#include " llvm/ADT/DenseMap.h"
13
13
#include " llvm/ADT/StringExtras.h"
14
+ #include " llvm/ADT/fallible_iterator.h"
14
15
#include " llvm/ADT/iterator.h"
15
16
#include " llvm/BinaryFormat/Minidump.h"
16
17
#include " llvm/Object/Binary.h"
@@ -103,6 +104,13 @@ class MinidumpFile : public Binary {
103
104
minidump::StreamType::MemoryList);
104
105
}
105
106
107
+ // / Returns the header to the memory 64 list stream. An error is returned if
108
+ // / the file does not contain this stream.
109
+ Expected<minidump::Memory64ListHeader> getMemoryList64Header () const {
110
+ return getStream<minidump::Memory64ListHeader>(
111
+ minidump::StreamType::Memory64List);
112
+ }
113
+
106
114
class MemoryInfoIterator
107
115
: public iterator_facade_base<MemoryInfoIterator,
108
116
std::forward_iterator_tag,
@@ -132,6 +140,90 @@ class MinidumpFile : public Binary {
132
140
size_t Stride;
133
141
};
134
142
143
+ // / Class the provides an iterator over the memory64 memory ranges. Only the
144
+ // / the first descriptor is validated as readable beforehand.
145
+ class Memory64Iterator {
146
+ public:
147
+ static Memory64Iterator
148
+ begin (ArrayRef<uint8_t > Storage,
149
+ ArrayRef<minidump::MemoryDescriptor_64> Descriptors) {
150
+ return Memory64Iterator (Storage, Descriptors);
151
+ }
152
+
153
+ static Memory64Iterator end () { return Memory64Iterator (); }
154
+
155
+ bool operator ==(const Memory64Iterator &R) const {
156
+ return IsEnd == R.IsEnd ;
157
+ }
158
+
159
+ bool operator !=(const Memory64Iterator &R) const { return !(*this == R); }
160
+
161
+ const std::pair<minidump::MemoryDescriptor_64, ArrayRef<uint8_t >> &
162
+ operator *() {
163
+ return Current;
164
+ }
165
+
166
+ const std::pair<minidump::MemoryDescriptor_64, ArrayRef<uint8_t >> *
167
+ operator ->() {
168
+ return &Current;
169
+ }
170
+
171
+ Error inc () {
172
+ if (Descriptors.empty ()) {
173
+ IsEnd = true ;
174
+ return Error::success ();
175
+ }
176
+
177
+ // Drop front gives us an array ref, so we need to call .front() as well.
178
+ const minidump::MemoryDescriptor_64 &Descriptor = Descriptors.front ();
179
+ if (Descriptor.DataSize > Storage.size ()) {
180
+ IsEnd = true ;
181
+ return make_error<GenericBinaryError>(
182
+ " Memory64 Descriptor exceeds end of file." ,
183
+ object_error::unexpected_eof);
184
+ }
185
+
186
+ ArrayRef<uint8_t > Content = Storage.take_front (Descriptor.DataSize );
187
+ Current = std::make_pair (Descriptor, Content);
188
+
189
+ Storage = Storage.drop_front (Descriptor.DataSize );
190
+ Descriptors = Descriptors.drop_front ();
191
+
192
+ return Error::success ();
193
+ }
194
+
195
+ private:
196
+ // This constructor expects that the first descriptor is readable.
197
+ Memory64Iterator (ArrayRef<uint8_t > Storage,
198
+ ArrayRef<minidump::MemoryDescriptor_64> Descriptors)
199
+ : Storage(Storage), Descriptors(Descriptors), IsEnd(false ) {
200
+ assert (!Descriptors.empty () &&
201
+ Storage.size () >= Descriptors.front ().DataSize );
202
+ minidump::MemoryDescriptor_64 Descriptor = Descriptors.front ();
203
+ ArrayRef<uint8_t > Content = Storage.take_front (Descriptor.DataSize );
204
+ Current = std::make_pair (Descriptor, Content);
205
+ this ->Descriptors = Descriptors.drop_front ();
206
+ this ->Storage = Storage.drop_front (Descriptor.DataSize );
207
+ }
208
+
209
+ Memory64Iterator ()
210
+ : Storage(ArrayRef<uint8_t >()),
211
+ Descriptors (ArrayRef<minidump::MemoryDescriptor_64>()), IsEnd(true ) {}
212
+
213
+ std::pair<minidump::MemoryDescriptor_64, ArrayRef<uint8_t >> Current;
214
+ ArrayRef<uint8_t > Storage;
215
+ ArrayRef<minidump::MemoryDescriptor_64> Descriptors;
216
+ bool IsEnd;
217
+ };
218
+
219
+ using FallibleMemory64Iterator = llvm::fallible_iterator<Memory64Iterator>;
220
+
221
+ // / Returns an iterator that pairs each descriptor with it's respective
222
+ // / content from the Memory64List stream. An error is returned if the file
223
+ // / does not contain a Memory64List stream, or if the descriptor data is
224
+ // / unreadable.
225
+ iterator_range<FallibleMemory64Iterator> getMemory64List (Error &Err) const ;
226
+
135
227
// / Returns the list of descriptors embedded in the MemoryInfoList stream. The
136
228
// / descriptors provide properties (e.g. permissions) of interesting regions
137
229
// / of memory at the time the minidump was taken. An error is returned if the
@@ -152,15 +244,15 @@ class MinidumpFile : public Binary {
152
244
}
153
245
154
246
// / Return a slice of the given data array, with bounds checking.
155
- static Expected<ArrayRef<uint8_t >> getDataSlice (ArrayRef< uint8_t > Data,
156
- size_t Offset, size_t Size );
247
+ static Expected<ArrayRef<uint8_t >>
248
+ getDataSlice (ArrayRef< uint8_t > Data, uint64_t Offset, uint64_t Size );
157
249
158
250
// / Return the slice of the given data array as an array of objects of the
159
251
// / given type. The function checks that the input array is large enough to
160
252
// / contain the correct number of objects of the given type.
161
253
template <typename T>
162
254
static Expected<ArrayRef<T>> getDataSliceAs (ArrayRef<uint8_t > Data,
163
- size_t Offset, size_t Count);
255
+ uint64_t Offset, uint64_t Count);
164
256
165
257
MinidumpFile (MemoryBufferRef Source, const minidump::Header &Header,
166
258
ArrayRef<minidump::Directory> Streams,
@@ -199,15 +291,16 @@ Expected<const T &> MinidumpFile::getStream(minidump::StreamType Type) const {
199
291
200
292
template <typename T>
201
293
Expected<ArrayRef<T>> MinidumpFile::getDataSliceAs (ArrayRef<uint8_t > Data,
202
- size_t Offset,
203
- size_t Count) {
294
+ uint64_t Offset,
295
+ uint64_t Count) {
204
296
// Check for overflow.
205
- if (Count > std::numeric_limits<size_t >::max () / sizeof (T))
297
+ if (Count > std::numeric_limits<uint64_t >::max () / sizeof (T))
206
298
return createEOFError ();
207
299
Expected<ArrayRef<uint8_t >> Slice =
208
300
getDataSlice (Data, Offset, sizeof (T) * Count);
209
301
if (!Slice)
210
302
return Slice.takeError ();
303
+
211
304
return ArrayRef<T>(reinterpret_cast <const T *>(Slice->data ()), Count);
212
305
}
213
306
0 commit comments