/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- DebugChecksumsSubsection.cpp ---------------------------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" |
10 | | #include "llvm/ADT/ArrayRef.h" |
11 | | #include "llvm/DebugInfo/CodeView/CodeView.h" |
12 | | #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" |
13 | | #include "llvm/Support/BinaryStreamReader.h" |
14 | | #include "llvm/Support/BinaryStreamWriter.h" |
15 | | #include "llvm/Support/Endian.h" |
16 | | #include "llvm/Support/Error.h" |
17 | | #include "llvm/Support/MathExtras.h" |
18 | | #include <cassert> |
19 | | #include <cstdint> |
20 | | #include <cstring> |
21 | | |
22 | | using namespace llvm; |
23 | | using namespace llvm::codeview; |
24 | | |
25 | | struct FileChecksumEntryHeader { |
26 | | using ulittle32_t = support::ulittle32_t; |
27 | | |
28 | | ulittle32_t FileNameOffset; // Byte offset of filename in global string table. |
29 | | uint8_t ChecksumSize; // Number of bytes of checksum. |
30 | | uint8_t ChecksumKind; // FileChecksumKind |
31 | | // Checksum bytes follow. |
32 | | }; |
33 | | |
34 | | Error VarStreamArrayExtractor<FileChecksumEntry>:: |
35 | 1.96k | operator()(BinaryStreamRef Stream, uint32_t &Len, FileChecksumEntry &Item) { |
36 | 1.96k | BinaryStreamReader Reader(Stream); |
37 | 1.96k | |
38 | 1.96k | const FileChecksumEntryHeader *Header; |
39 | 1.96k | if (auto EC = Reader.readObject(Header)) |
40 | 0 | return EC; |
41 | 1.96k | |
42 | 1.96k | Item.FileNameOffset = Header->FileNameOffset; |
43 | 1.96k | Item.Kind = static_cast<FileChecksumKind>(Header->ChecksumKind); |
44 | 1.96k | if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize)) |
45 | 0 | return EC; |
46 | 1.96k | |
47 | 1.96k | Len = alignTo(Header->ChecksumSize + sizeof(FileChecksumEntryHeader), 4); |
48 | 1.96k | return Error::success(); |
49 | 1.96k | } |
50 | | |
51 | 542 | Error DebugChecksumsSubsectionRef::initialize(BinaryStreamReader Reader) { |
52 | 542 | if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining())) |
53 | 0 | return EC; |
54 | 542 | |
55 | 542 | return Error::success(); |
56 | 542 | } |
57 | | |
58 | 532 | Error DebugChecksumsSubsectionRef::initialize(BinaryStreamRef Section) { |
59 | 532 | BinaryStreamReader Reader(Section); |
60 | 532 | return initialize(Reader); |
61 | 532 | } |
62 | | |
63 | | DebugChecksumsSubsection::DebugChecksumsSubsection( |
64 | | DebugStringTableSubsection &Strings) |
65 | 165 | : DebugSubsection(DebugSubsectionKind::FileChecksums), Strings(Strings) {} |
66 | | |
67 | | void DebugChecksumsSubsection::addChecksum(StringRef FileName, |
68 | | FileChecksumKind Kind, |
69 | 196 | ArrayRef<uint8_t> Bytes) { |
70 | 196 | FileChecksumEntry Entry; |
71 | 196 | if (!Bytes.empty()) { |
72 | 179 | uint8_t *Copy = Storage.Allocate<uint8_t>(Bytes.size()); |
73 | 179 | ::memcpy(Copy, Bytes.data(), Bytes.size()); |
74 | 179 | Entry.Checksum = makeArrayRef(Copy, Bytes.size()); |
75 | 179 | } |
76 | 196 | |
77 | 196 | Entry.FileNameOffset = Strings.insert(FileName); |
78 | 196 | Entry.Kind = Kind; |
79 | 196 | Checksums.push_back(Entry); |
80 | 196 | |
81 | 196 | // This maps the offset of this string in the string table to the offset |
82 | 196 | // of this checksum entry in the checksum buffer. |
83 | 196 | OffsetMap[Entry.FileNameOffset] = SerializedSize; |
84 | 196 | assert(SerializedSize % 4 == 0); |
85 | 196 | |
86 | 196 | uint32_t Len = alignTo(sizeof(FileChecksumEntryHeader) + Bytes.size(), 4); |
87 | 196 | SerializedSize += Len; |
88 | 196 | } |
89 | | |
90 | 324 | uint32_t DebugChecksumsSubsection::calculateSerializedSize() const { |
91 | 324 | return SerializedSize; |
92 | 324 | } |
93 | | |
94 | 122 | Error DebugChecksumsSubsection::commit(BinaryStreamWriter &Writer) const { |
95 | 149 | for (const auto &FC : Checksums) { |
96 | 149 | FileChecksumEntryHeader Header; |
97 | 149 | Header.ChecksumKind = uint8_t(FC.Kind); |
98 | 149 | Header.ChecksumSize = FC.Checksum.size(); |
99 | 149 | Header.FileNameOffset = FC.FileNameOffset; |
100 | 149 | if (auto EC = Writer.writeObject(Header)) |
101 | 0 | return EC; |
102 | 149 | if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum))) |
103 | 0 | return EC; |
104 | 149 | if (auto EC = Writer.padToAlignment(4)) |
105 | 0 | return EC; |
106 | 149 | } |
107 | 122 | return Error::success(); |
108 | 122 | } |
109 | | |
110 | 61 | uint32_t DebugChecksumsSubsection::mapChecksumOffset(StringRef FileName) const { |
111 | 61 | uint32_t Offset = Strings.getIdForString(FileName); |
112 | 61 | auto Iter = OffsetMap.find(Offset); |
113 | 61 | assert(Iter != OffsetMap.end()); |
114 | 61 | return Iter->second; |
115 | 61 | } |