1 //===- ModuleSubstreamVisitor.h ---------------------------------*- C++ -*-===// 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 #ifndef LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H 11 #define LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H 12 13 #include "llvm/ADT/ArrayRef.h" 14 #include "llvm/DebugInfo/CodeView/CodeView.h" 15 #include "llvm/DebugInfo/CodeView/CodeViewError.h" 16 #include "llvm/DebugInfo/CodeView/Line.h" 17 #include "llvm/DebugInfo/CodeView/ModuleSubstream.h" 18 #include "llvm/Support/BinaryStreamArray.h" 19 #include "llvm/Support/BinaryStreamReader.h" 20 #include "llvm/Support/BinaryStreamRef.h" 21 #include "llvm/Support/Endian.h" 22 #include "llvm/Support/Error.h" 23 #include <cstdint> 24 25 namespace llvm { 26 27 namespace codeview { 28 29 struct LineColumnEntry { 30 support::ulittle32_t NameIndex; 31 FixedStreamArray<LineNumberEntry> LineNumbers; 32 FixedStreamArray<ColumnNumberEntry> Columns; 33 }; 34 35 struct FileChecksumEntry { 36 uint32_t FileNameOffset; // Byte offset of filename in global stringtable. 37 FileChecksumKind Kind; // The type of checksum. 38 ArrayRef<uint8_t> Checksum; // The bytes of the checksum. 39 }; 40 41 typedef VarStreamArray<LineColumnEntry> LineInfoArray; 42 typedef VarStreamArray<FileChecksumEntry> FileChecksumArray; 43 44 class IModuleSubstreamVisitor { 45 public: 46 virtual ~IModuleSubstreamVisitor() = default; 47 48 virtual Error visitUnknown(ModuleSubstreamKind Kind, 49 BinaryStreamRef Data) = 0; 50 virtual Error visitSymbols(BinaryStreamRef Data); 51 virtual Error visitLines(BinaryStreamRef Data, 52 const LineSubstreamHeader *Header, 53 const LineInfoArray &Lines); 54 virtual Error visitStringTable(BinaryStreamRef Data); 55 virtual Error visitFileChecksums(BinaryStreamRef Data, 56 const FileChecksumArray &Checksums); 57 virtual Error visitFrameData(BinaryStreamRef Data); 58 virtual Error visitInlineeLines(BinaryStreamRef Data); 59 virtual Error visitCrossScopeImports(BinaryStreamRef Data); 60 virtual Error visitCrossScopeExports(BinaryStreamRef Data); 61 virtual Error visitILLines(BinaryStreamRef Data); 62 virtual Error visitFuncMDTokenMap(BinaryStreamRef Data); 63 virtual Error visitTypeMDTokenMap(BinaryStreamRef Data); 64 virtual Error visitMergedAssemblyInput(BinaryStreamRef Data); 65 virtual Error visitCoffSymbolRVA(BinaryStreamRef Data); 66 }; 67 68 Error visitModuleSubstream(const ModuleSubstream &R, 69 IModuleSubstreamVisitor &V); 70 } // end namespace codeview 71 72 template <> class VarStreamArrayExtractor<codeview::LineColumnEntry> { 73 public: 74 VarStreamArrayExtractor(const codeview::LineSubstreamHeader *Header) 75 : Header(Header) {} 76 77 Error operator()(BinaryStreamRef Stream, uint32_t &Len, 78 codeview::LineColumnEntry &Item) const { 79 using namespace codeview; 80 const LineFileBlockHeader *BlockHeader; 81 BinaryStreamReader Reader(Stream); 82 if (auto EC = Reader.readObject(BlockHeader)) 83 return EC; 84 bool HasColumn = Header->Flags & LineFlags::HaveColumns; 85 uint32_t LineInfoSize = 86 BlockHeader->NumLines * 87 (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0)); 88 if (BlockHeader->BlockSize < sizeof(LineFileBlockHeader)) 89 return make_error<CodeViewError>(cv_error_code::corrupt_record, 90 "Invalid line block record size"); 91 uint32_t Size = BlockHeader->BlockSize - sizeof(LineFileBlockHeader); 92 if (LineInfoSize > Size) 93 return make_error<CodeViewError>(cv_error_code::corrupt_record, 94 "Invalid line block record size"); 95 // The value recorded in BlockHeader->BlockSize includes the size of 96 // LineFileBlockHeader. 97 Len = BlockHeader->BlockSize; 98 Item.NameIndex = BlockHeader->NameIndex; 99 if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines)) 100 return EC; 101 if (HasColumn) { 102 if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines)) 103 return EC; 104 } 105 return Error::success(); 106 } 107 108 private: 109 const codeview::LineSubstreamHeader *Header; 110 }; 111 112 template <> class VarStreamArrayExtractor<codeview::FileChecksumEntry> { 113 public: 114 Error operator()(BinaryStreamRef Stream, uint32_t &Len, 115 codeview::FileChecksumEntry &Item) const { 116 using namespace codeview; 117 const FileChecksum *Header; 118 BinaryStreamReader Reader(Stream); 119 if (auto EC = Reader.readObject(Header)) 120 return EC; 121 Item.FileNameOffset = Header->FileNameOffset; 122 Item.Kind = static_cast<FileChecksumKind>(Header->ChecksumKind); 123 if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize)) 124 return EC; 125 Len = sizeof(FileChecksum) + Header->ChecksumSize; 126 return Error::success(); 127 } 128 }; 129 130 } // end namespace llvm 131 132 #endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H 133