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