1 //===- DebugChecksumsSubsection.cpp ---------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
23 using namespace llvm::codeview
;
25 struct FileChecksumEntryHeader
{
26 using ulittle32_t
= support::ulittle32_t
;
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.
34 Error VarStreamArrayExtractor
<FileChecksumEntry
>::
35 operator()(BinaryStreamRef Stream
, uint32_t &Len
, FileChecksumEntry
&Item
) {
36 BinaryStreamReader
Reader(Stream
);
38 const FileChecksumEntryHeader
*Header
;
39 if (auto EC
= Reader
.readObject(Header
))
42 Item
.FileNameOffset
= Header
->FileNameOffset
;
43 Item
.Kind
= static_cast<FileChecksumKind
>(Header
->ChecksumKind
);
44 if (auto EC
= Reader
.readBytes(Item
.Checksum
, Header
->ChecksumSize
))
47 Len
= alignTo(Header
->ChecksumSize
+ sizeof(FileChecksumEntryHeader
), 4);
48 return Error::success();
51 Error
DebugChecksumsSubsectionRef::initialize(BinaryStreamReader Reader
) {
52 if (auto EC
= Reader
.readArray(Checksums
, Reader
.bytesRemaining()))
55 return Error::success();
58 Error
DebugChecksumsSubsectionRef::initialize(BinaryStreamRef Section
) {
59 BinaryStreamReader
Reader(Section
);
60 return initialize(Reader
);
63 DebugChecksumsSubsection::DebugChecksumsSubsection(
64 DebugStringTableSubsection
&Strings
)
65 : DebugSubsection(DebugSubsectionKind::FileChecksums
), Strings(Strings
) {}
67 void DebugChecksumsSubsection::addChecksum(StringRef FileName
,
68 FileChecksumKind Kind
,
69 ArrayRef
<uint8_t> Bytes
) {
70 FileChecksumEntry Entry
;
72 uint8_t *Copy
= Storage
.Allocate
<uint8_t>(Bytes
.size());
73 ::memcpy(Copy
, Bytes
.data(), Bytes
.size());
74 Entry
.Checksum
= makeArrayRef(Copy
, Bytes
.size());
77 Entry
.FileNameOffset
= Strings
.insert(FileName
);
79 Checksums
.push_back(Entry
);
81 // This maps the offset of this string in the string table to the offset
82 // of this checksum entry in the checksum buffer.
83 OffsetMap
[Entry
.FileNameOffset
] = SerializedSize
;
84 assert(SerializedSize
% 4 == 0);
86 uint32_t Len
= alignTo(sizeof(FileChecksumEntryHeader
) + Bytes
.size(), 4);
87 SerializedSize
+= Len
;
90 uint32_t DebugChecksumsSubsection::calculateSerializedSize() const {
91 return SerializedSize
;
94 Error
DebugChecksumsSubsection::commit(BinaryStreamWriter
&Writer
) const {
95 for (const auto &FC
: Checksums
) {
96 FileChecksumEntryHeader Header
;
97 Header
.ChecksumKind
= uint8_t(FC
.Kind
);
98 Header
.ChecksumSize
= FC
.Checksum
.size();
99 Header
.FileNameOffset
= FC
.FileNameOffset
;
100 if (auto EC
= Writer
.writeObject(Header
))
102 if (auto EC
= Writer
.writeArray(makeArrayRef(FC
.Checksum
)))
104 if (auto EC
= Writer
.padToAlignment(4))
107 return Error::success();
110 uint32_t DebugChecksumsSubsection::mapChecksumOffset(StringRef FileName
) const {
111 uint32_t Offset
= Strings
.getIdForString(FileName
);
112 auto Iter
= OffsetMap
.find(Offset
);
113 assert(Iter
!= OffsetMap
.end());