1 //===- DebugChecksumsSubsection.cpp ----------------------*- 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 #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" 11 12 #include "llvm/DebugInfo/CodeView/CodeViewError.h" 13 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" 14 #include "llvm/Support/BinaryStreamReader.h" 15 16 using namespace llvm; 17 using namespace llvm::codeview; 18 19 struct FileChecksumEntryHeader { 20 using ulittle32_t = support::ulittle32_t; 21 22 ulittle32_t FileNameOffset; // Byte offset of filename in global string table. 23 uint8_t ChecksumSize; // Number of bytes of checksum. 24 uint8_t ChecksumKind; // FileChecksumKind 25 // Checksum bytes follow. 26 }; 27 28 Error llvm::VarStreamArrayExtractor<FileChecksumEntry>::extract( 29 BinaryStreamRef Stream, uint32_t &Len, FileChecksumEntry &Item) { 30 BinaryStreamReader Reader(Stream); 31 32 const FileChecksumEntryHeader *Header; 33 if (auto EC = Reader.readObject(Header)) 34 return EC; 35 36 Item.FileNameOffset = Header->FileNameOffset; 37 Item.Kind = static_cast<FileChecksumKind>(Header->ChecksumKind); 38 if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize)) 39 return EC; 40 41 Len = alignTo(Header->ChecksumSize + sizeof(FileChecksumEntryHeader), 4); 42 return Error::success(); 43 } 44 45 Error DebugChecksumsSubsectionRef::initialize(BinaryStreamReader Reader) { 46 if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining())) 47 return EC; 48 49 return Error::success(); 50 } 51 Error DebugChecksumsSubsectionRef::initialize(BinaryStreamRef Section) { 52 BinaryStreamReader Reader(Section); 53 return initialize(Reader); 54 } 55 56 DebugChecksumsSubsection::DebugChecksumsSubsection( 57 DebugStringTableSubsection &Strings) 58 : DebugSubsection(DebugSubsectionKind::FileChecksums), Strings(Strings) {} 59 60 void DebugChecksumsSubsection::addChecksum(StringRef FileName, 61 FileChecksumKind Kind, 62 ArrayRef<uint8_t> Bytes) { 63 FileChecksumEntry Entry; 64 if (!Bytes.empty()) { 65 uint8_t *Copy = Storage.Allocate<uint8_t>(Bytes.size()); 66 ::memcpy(Copy, Bytes.data(), Bytes.size()); 67 Entry.Checksum = makeArrayRef(Copy, Bytes.size()); 68 } 69 70 Entry.FileNameOffset = Strings.insert(FileName); 71 Entry.Kind = Kind; 72 Checksums.push_back(Entry); 73 74 // This maps the offset of this string in the string table to the offset 75 // of this checksum entry in the checksum buffer. 76 OffsetMap[Entry.FileNameOffset] = SerializedSize; 77 assert(SerializedSize % 4 == 0); 78 79 uint32_t Len = alignTo(sizeof(FileChecksumEntryHeader) + Bytes.size(), 4); 80 SerializedSize += Len; 81 } 82 83 uint32_t DebugChecksumsSubsection::calculateSerializedSize() const { 84 return SerializedSize; 85 } 86 87 Error DebugChecksumsSubsection::commit(BinaryStreamWriter &Writer) const { 88 for (const auto &FC : Checksums) { 89 FileChecksumEntryHeader Header; 90 Header.ChecksumKind = uint8_t(FC.Kind); 91 Header.ChecksumSize = FC.Checksum.size(); 92 Header.FileNameOffset = FC.FileNameOffset; 93 if (auto EC = Writer.writeObject(Header)) 94 return EC; 95 if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum))) 96 return EC; 97 if (auto EC = Writer.padToAlignment(4)) 98 return EC; 99 } 100 return Error::success(); 101 } 102 103 uint32_t DebugChecksumsSubsection::mapChecksumOffset(StringRef FileName) const { 104 uint32_t Offset = Strings.getStringId(FileName); 105 auto Iter = OffsetMap.find(Offset); 106 assert(Iter != OffsetMap.end()); 107 return Iter->second; 108 } 109