//===- Minidump.cpp - Minidump object file implementation -----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/Object/Minidump.h" #include "llvm/Object/Error.h" using namespace llvm; using namespace llvm::object; using namespace llvm::minidump; Optional> MinidumpFile::getRawStream(minidump::StreamType Type) const { auto It = StreamMap.find(Type); if (It != StreamMap.end()) return getRawStream(Streams[It->second]); return None; } Expected> MinidumpFile::getDataSlice(ArrayRef Data, size_t Offset, size_t Size) { // Check for overflow. if (Offset + Size < Offset || Offset + Size < Size || Offset + Size > Data.size()) return createEOFError(); return Data.slice(Offset, Size); } Expected> MinidumpFile::create(MemoryBufferRef Source) { ArrayRef Data = arrayRefFromStringRef(Source.getBuffer()); auto ExpectedHeader = getDataSliceAs(Data, 0, 1); if (!ExpectedHeader) return ExpectedHeader.takeError(); const minidump::Header &Hdr = (*ExpectedHeader)[0]; if (Hdr.Signature != Header::MagicSignature) return createError("Invalid signature"); if ((Hdr.Version & 0xffff) != Header::MagicVersion) return createError("Invalid version"); auto ExpectedStreams = getDataSliceAs(Data, Hdr.StreamDirectoryRVA, Hdr.NumberOfStreams); if (!ExpectedStreams) return ExpectedStreams.takeError(); DenseMap StreamMap; for (const auto &Stream : llvm::enumerate(*ExpectedStreams)) { StreamType Type = Stream.value().Type; const LocationDescriptor &Loc = Stream.value().Location; auto ExpectedStream = getDataSlice(Data, Loc.RVA, Loc.DataSize); if (!ExpectedStream) return ExpectedStream.takeError(); if (Type == StreamType::Unused && Loc.DataSize == 0) { // Ignore dummy streams. This is technically ill-formed, but a number of // existing minidumps seem to contain such streams. continue; } if (Type == DenseMapInfo::getEmptyKey() || Type == DenseMapInfo::getTombstoneKey()) return createError("Cannot handle one of the minidump streams"); // Update the directory map, checking for duplicate stream types. if (!StreamMap.try_emplace(Type, Stream.index()).second) return createError("Duplicate stream type"); } return std::unique_ptr( new MinidumpFile(Source, Hdr, *ExpectedStreams, std::move(StreamMap))); }