Skip to content

Commit a33bb59

Browse files
committed
Add minidump exception iterator
1 parent 70f94e1 commit a33bb59

File tree

2 files changed

+73
-30
lines changed

2 files changed

+73
-30
lines changed

llvm/include/llvm/Object/Minidump.h

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,6 @@ class MinidumpFile : public Binary {
9595
return getStreamFromDirectory<minidump::ExceptionStream>(Directory);
9696
}
9797

98-
/// Returns the contents of the Exception streams. An error is returned if
99-
/// any of the streams are smaller than the size of the ExceptionStream
100-
/// structure. The internal consistency of the stream is not checked in any
101-
/// way.
102-
Expected<std::vector<const minidump::ExceptionStream *>>
103-
getExceptionStreams() const;
104-
10598
/// Returns the list of descriptors embedded in the MemoryList stream. The
10699
/// descriptors provide the content of interesting regions of memory at the
107100
/// time the minidump was taken. An error is returned if the file does not
@@ -226,8 +219,71 @@ class MinidumpFile : public Binary {
226219
bool IsEnd;
227220
};
228221

222+
class ExceptionStreamsIterator {
223+
public:
224+
225+
static ExceptionStreamsIterator begin(ArrayRef<minidump::Directory> Streams, const MinidumpFile *File) {
226+
return ExceptionStreamsIterator(Streams, File);
227+
}
228+
229+
static ExceptionStreamsIterator end() {
230+
return ExceptionStreamsIterator();
231+
}
232+
233+
bool operator==(const ExceptionStreamsIterator &R) const {
234+
return Streams.empty() && R.Streams.empty();
235+
}
236+
237+
bool operator!=(const ExceptionStreamsIterator &R) const { return !(*this == R); }
238+
239+
const Expected<const minidump::ExceptionStream &>
240+
operator*() {
241+
return ReadCurrent();
242+
}
243+
244+
const Expected<const minidump::ExceptionStream &>
245+
operator->() {
246+
return ReadCurrent();
247+
}
248+
249+
ExceptionStreamsIterator &
250+
operator++ () {
251+
if (!Streams.empty())
252+
Streams = Streams.drop_front();
253+
254+
255+
return *this;
256+
}
257+
258+
private:
259+
ExceptionStreamsIterator(ArrayRef<minidump::Directory> Streams, const MinidumpFile *File)
260+
: Streams(Streams), File(File) {}
261+
262+
ExceptionStreamsIterator() : Streams(ArrayRef<minidump::Directory>()), File(nullptr) {}
263+
264+
ArrayRef<minidump::Directory> Streams;
265+
const MinidumpFile *File;
266+
267+
Expected<const minidump::ExceptionStream&> ReadCurrent() {
268+
assert(!Streams.empty());
269+
Expected<const minidump::ExceptionStream &> ExceptionStream =
270+
File->getExceptionStream(Streams.front());
271+
if (!ExceptionStream)
272+
return ExceptionStream.takeError();
273+
274+
return ExceptionStream;
275+
}
276+
};
277+
229278
using FallibleMemory64Iterator = llvm::fallible_iterator<Memory64Iterator>;
230279

280+
/// Returns an iterator that reads each exception stream independently. The
281+
/// contents of the exception strema are not validated before being read, an
282+
/// error will be returned if the stream is not large enough to contain an
283+
/// exception stream, or if the stream points beyond the end of the file.
284+
iterator_range<ExceptionStreamsIterator>
285+
getExceptionStreams() const;
286+
231287
/// Returns an iterator that pairs each descriptor with it's respective
232288
/// content from the Memory64List stream. An error is returned if the file
233289
/// does not contain a Memory64List stream, or if the descriptor data is
@@ -266,9 +322,10 @@ class MinidumpFile : public Binary {
266322

267323
MinidumpFile(MemoryBufferRef Source, const minidump::Header &Header,
268324
ArrayRef<minidump::Directory> Streams,
269-
DenseMap<minidump::StreamType, std::size_t> StreamMap)
325+
DenseMap<minidump::StreamType, std::size_t> StreamMap,
326+
std::vector<minidump::Directory> ExceptionStreams)
270327
: Binary(ID_Minidump, Source), Header(Header), Streams(Streams),
271-
StreamMap(std::move(StreamMap)) {}
328+
StreamMap(std::move(StreamMap)), ExceptionStreams(std::move(ExceptionStreams)) {}
272329

273330
ArrayRef<uint8_t> getData() const {
274331
return arrayRefFromStringRef(Data.getBuffer());
@@ -293,6 +350,7 @@ class MinidumpFile : public Binary {
293350
const minidump::Header &Header;
294351
ArrayRef<minidump::Directory> Streams;
295352
DenseMap<minidump::StreamType, std::size_t> StreamMap;
353+
std::vector<minidump::Directory> ExceptionStreams;
296354
};
297355

298356
template <typename T>

llvm/lib/Object/Minidump.cpp

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -53,25 +53,10 @@ Expected<std::string> MinidumpFile::getString(size_t Offset) const {
5353
return Result;
5454
}
5555

56-
Expected<std::vector<const minidump::ExceptionStream *>>
56+
iterator_range<llvm::object::MinidumpFile::ExceptionStreamsIterator>
5757
MinidumpFile::getExceptionStreams() const {
58-
59-
std::vector<const minidump::ExceptionStream *> exceptionStreamList;
60-
for (const auto &directory : Streams) {
61-
if (directory.Type == StreamType::Exception) {
62-
llvm::Expected<minidump::ExceptionStream *> ExpectedStream =
63-
getStreamFromDirectory<minidump::ExceptionStream *>(directory);
64-
if (!ExpectedStream)
65-
return ExpectedStream.takeError();
66-
67-
exceptionStreamList.push_back(ExpectedStream.get());
68-
}
69-
}
70-
71-
if (exceptionStreamList.empty())
72-
return createError("No exception streams found");
73-
74-
return exceptionStreamList;
58+
return make_range(ExceptionStreamsIterator::begin(ExceptionStreams, this),
59+
ExceptionStreamsIterator::end());
7560
}
7661

7762
Expected<iterator_range<MinidumpFile::MemoryInfoIterator>>
@@ -149,7 +134,7 @@ MinidumpFile::create(MemoryBufferRef Source) {
149134
return ExpectedStreams.takeError();
150135

151136
DenseMap<StreamType, std::size_t> StreamMap;
152-
std::vector<std::size_t> ExceptionStreams;
137+
std::vector<Directory> ExceptionStreams;
153138
for (const auto &StreamDescriptor : llvm::enumerate(*ExpectedStreams)) {
154139
StreamType Type = StreamDescriptor.value().Type;
155140
const LocationDescriptor &Loc = StreamDescriptor.value().Location;
@@ -171,7 +156,7 @@ MinidumpFile::create(MemoryBufferRef Source) {
171156
// streams that point back to their thread So we will omit them here, and
172157
// will find them when needed in the MinidumpFile.
173158
if (Type == StreamType::Exception) {
174-
continue;
159+
ExceptionStreams.push_back(StreamDescriptor.value());
175160
}
176161

177162
if (Type == DenseMapInfo<StreamType>::getEmptyKey() ||
@@ -184,7 +169,7 @@ MinidumpFile::create(MemoryBufferRef Source) {
184169
}
185170

186171
return std::unique_ptr<MinidumpFile>(
187-
new MinidumpFile(Source, Hdr, *ExpectedStreams, std::move(StreamMap)));
172+
new MinidumpFile(Source, Hdr, *ExpectedStreams, std::move(StreamMap), ExceptionStreams));
188173
}
189174

190175
iterator_range<MinidumpFile::FallibleMemory64Iterator>

0 commit comments

Comments
 (0)