diff options
Diffstat (limited to 'llvm/lib/Object')
-rw-r--r-- | llvm/lib/Object/Binary.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Object/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Object/Minidump.cpp | 77 | ||||
-rw-r--r-- | llvm/lib/Object/ObjectFile.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Object/SymbolicFile.cpp | 1 |
5 files changed, 83 insertions, 0 deletions
diff --git a/llvm/lib/Object/Binary.cpp b/llvm/lib/Object/Binary.cpp index 87b2c1278c0..e1063a64b14 100644 --- a/llvm/lib/Object/Binary.cpp +++ b/llvm/lib/Object/Binary.cpp @@ -16,6 +16,7 @@ #include "llvm/Object/Archive.h" #include "llvm/Object/Error.h" #include "llvm/Object/MachOUniversal.h" +#include "llvm/Object/Minidump.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/WindowsResource.h" #include "llvm/Support/Error.h" @@ -81,6 +82,8 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer, case file_magic::coff_cl_gl_object: // Unrecognized object file format. return errorCodeToError(object_error::invalid_file_type); + case file_magic::minidump: + return MinidumpFile::create(Buffer); } llvm_unreachable("Unexpected Binary File Type"); } diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt index fd5e7707c54..a0ac0046c0b 100644 --- a/llvm/lib/Object/CMakeLists.txt +++ b/llvm/lib/Object/CMakeLists.txt @@ -13,6 +13,7 @@ add_llvm_library(LLVMObject IRSymtab.cpp MachOObjectFile.cpp MachOUniversal.cpp + Minidump.cpp ModuleSymbolTable.cpp Object.cpp ObjectFile.cpp diff --git a/llvm/lib/Object/Minidump.cpp b/llvm/lib/Object/Minidump.cpp new file mode 100644 index 00000000000..d0d49b4e8d3 --- /dev/null +++ b/llvm/lib/Object/Minidump.cpp @@ -0,0 +1,77 @@ +//===- 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<ArrayRef<uint8_t>> +MinidumpFile::getRawStream(minidump::StreamType Type) const { + auto It = StreamMap.find(Type); + if (It != StreamMap.end()) + return getRawStream(Streams[It->second]); + return None; +} + +Expected<ArrayRef<uint8_t>> +MinidumpFile::getDataSlice(ArrayRef<uint8_t> 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<std::unique_ptr<MinidumpFile>> +MinidumpFile::create(MemoryBufferRef Source) { + ArrayRef<uint8_t> Data = arrayRefFromStringRef(Source.getBuffer()); + auto ExpectedHeader = getDataSliceAs<minidump::Header>(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<Directory>(Data, Hdr.StreamDirectoryRVA, + Hdr.NumberOfStreams); + if (!ExpectedStreams) + return ExpectedStreams.takeError(); + + DenseMap<StreamType, std::size_t> 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<StreamType>::getEmptyKey() || + Type == DenseMapInfo<StreamType>::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<MinidumpFile>( + new MinidumpFile(Source, Hdr, *ExpectedStreams, std::move(StreamMap))); +} diff --git a/llvm/lib/Object/ObjectFile.cpp b/llvm/lib/Object/ObjectFile.cpp index 441ef54bd84..cf095db8e8c 100644 --- a/llvm/lib/Object/ObjectFile.cpp +++ b/llvm/lib/Object/ObjectFile.cpp @@ -127,6 +127,7 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type) { case file_magic::macho_universal_binary: case file_magic::windows_resource: case file_magic::pdb: + case file_magic::minidump: return errorCodeToError(object_error::invalid_file_type); case file_magic::elf: case file_magic::elf_relocatable: diff --git a/llvm/lib/Object/SymbolicFile.cpp b/llvm/lib/Object/SymbolicFile.cpp index 8ee82567710..675f2091518 100644 --- a/llvm/lib/Object/SymbolicFile.cpp +++ b/llvm/lib/Object/SymbolicFile.cpp @@ -52,6 +52,7 @@ SymbolicFile::createSymbolicFile(MemoryBufferRef Object, file_magic Type, case file_magic::macho_universal_binary: case file_magic::windows_resource: case file_magic::pdb: + case file_magic::minidump: return errorCodeToError(object_error::invalid_file_type); case file_magic::elf: case file_magic::elf_executable: |