1//===-- llvm-pdbdump-fuzzer.cpp - Fuzz the llvm-pdbdump tool --------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9/// 10/// \file 11/// \brief This file implements a function that runs llvm-pdbdump 12/// on a single input. This function is then linked into the Fuzzer library. 13/// 14//===----------------------------------------------------------------------===// 15#include "llvm/ADT/STLExtras.h" 16#include "llvm/DebugInfo/CodeView/ByteStream.h" 17#include "llvm/DebugInfo/CodeView/SymbolDumper.h" 18#include "llvm/DebugInfo/CodeView/TypeDumper.h" 19#include "llvm/DebugInfo/PDB/Raw/DbiStream.h" 20#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h" 21#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" 22#include "llvm/DebugInfo/PDB/Raw/ModStream.h" 23#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" 24#include "llvm/DebugInfo/PDB/Raw/RawSession.h" 25#include "llvm/Support/MemoryBuffer.h" 26#include "llvm/Support/ScopedPrinter.h" 27 28using namespace llvm; 29 30namespace { 31// We need a class which behaves like an immutable ByteStream, but whose data 32// is backed by an llvm::MemoryBuffer. It also needs to own the underlying 33// MemoryBuffer, so this simple adapter is a good way to achieve that. 34class InputByteStream : public codeview::ByteStream<false> { 35public: 36 explicit InputByteStream(std::unique_ptr<MemoryBuffer> Buffer) 37 : ByteStream(ArrayRef<uint8_t>(Buffer->getBuffer().bytes_begin(), 38 Buffer->getBuffer().bytes_end())), 39 MemBuffer(std::move(Buffer)) {} 40 41 std::unique_ptr<MemoryBuffer> MemBuffer; 42}; 43} 44 45extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { 46 std::unique_ptr<MemoryBuffer> Buff = MemoryBuffer::getMemBuffer( 47 StringRef((const char *)data, size), "", false); 48 49 ScopedPrinter P(nulls()); 50 codeview::CVTypeDumper TD(&P, false); 51 52 auto InputStream = llvm::make_unique<InputByteStream>(std::move(Buff)); 53 std::unique_ptr<pdb::PDBFile> File(new pdb::PDBFile(std::move(InputStream))); 54 if (auto E = File->parseFileHeaders()) { 55 consumeError(std::move(E)); 56 return 0; 57 } 58 if (auto E = File->parseStreamData()) { 59 consumeError(std::move(E)); 60 return 0; 61 } 62 63 auto DbiS = File->getPDBDbiStream(); 64 if (auto E = DbiS.takeError()) { 65 consumeError(std::move(E)); 66 return 0; 67 } 68 auto TpiS = File->getPDBTpiStream(); 69 if (auto E = TpiS.takeError()) { 70 consumeError(std::move(E)); 71 return 0; 72 } 73 auto IpiS = File->getPDBIpiStream(); 74 if (auto E = IpiS.takeError()) { 75 consumeError(std::move(E)); 76 return 0; 77 } 78 auto InfoS = File->getPDBInfoStream(); 79 if (auto E = InfoS.takeError()) { 80 consumeError(std::move(E)); 81 return 0; 82 } 83 pdb::DbiStream &DS = DbiS.get(); 84 85 for (auto &Modi : DS.modules()) { 86 auto ModStreamData = pdb::MappedBlockStream::createIndexedStream( 87 Modi.Info.getModuleStreamIndex(), *File); 88 if (!ModStreamData) { 89 consumeError(ModStreamData.takeError()); 90 return 0; 91 } 92 pdb::ModStream ModS(Modi.Info, std::move(*ModStreamData)); 93 if (auto E = ModS.reload()) { 94 consumeError(std::move(E)); 95 return 0; 96 } 97 codeview::CVSymbolDumper SD(P, TD, nullptr, false); 98 bool HadError = false; 99 for (auto &S : ModS.symbols(&HadError)) { 100 SD.dump(S); 101 } 102 } 103 return 0; 104} 105