1 //===- DebugChecksumsSubsection.cpp ---------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
24 using namespace llvm::codeview
;
26 struct FileChecksumEntryHeader
{
27 using ulittle32_t
= support::ulittle32_t
;
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.
35 Error VarStreamArrayExtractor
<FileChecksumEntry
>::
36 operator()(BinaryStreamRef Stream
, uint32_t &Len
, FileChecksumEntry
&Item
) {
37 BinaryStreamReader
Reader(Stream
);
39 const FileChecksumEntryHeader
*Header
;
40 if (auto EC
= Reader
.readObject(Header
))
43 Item
.FileNameOffset
= Header
->FileNameOffset
;
44 Item
.Kind
= static_cast<FileChecksumKind
>(Header
->ChecksumKind
);
45 if (auto EC
= Reader
.readBytes(Item
.Checksum
, Header
->ChecksumSize
))
48 Len
= alignTo(Header
->ChecksumSize
+ sizeof(FileChecksumEntryHeader
), 4);
49 return Error::success();
52 Error
DebugChecksumsSubsectionRef::initialize(BinaryStreamReader Reader
) {
53 if (auto EC
= Reader
.readArray(Checksums
, Reader
.bytesRemaining()))
56 return Error::success();
59 Error
DebugChecksumsSubsectionRef::initialize(BinaryStreamRef Section
) {
60 BinaryStreamReader
Reader(Section
);
61 return initialize(Reader
);
64 DebugChecksumsSubsection::DebugChecksumsSubsection(
65 DebugStringTableSubsection
&Strings
)
66 : DebugSubsection(DebugSubsectionKind::FileChecksums
), Strings(Strings
) {}
68 void DebugChecksumsSubsection::addChecksum(StringRef FileName
,
69 FileChecksumKind Kind
,
70 ArrayRef
<uint8_t> Bytes
) {
71 FileChecksumEntry Entry
;
73 uint8_t *Copy
= Storage
.Allocate
<uint8_t>(Bytes
.size());
74 ::memcpy(Copy
, Bytes
.data(), Bytes
.size());
75 Entry
.Checksum
= makeArrayRef(Copy
, Bytes
.size());
78 Entry
.FileNameOffset
= Strings
.insert(FileName
);
80 Checksums
.push_back(Entry
);
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 OffsetMap
[Entry
.FileNameOffset
] = SerializedSize
;
85 assert(SerializedSize
% 4 == 0);
87 uint32_t Len
= alignTo(sizeof(FileChecksumEntryHeader
) + Bytes
.size(), 4);
88 SerializedSize
+= Len
;
91 uint32_t DebugChecksumsSubsection::calculateSerializedSize() const {
92 return SerializedSize
;
95 Error
DebugChecksumsSubsection::commit(BinaryStreamWriter
&Writer
) const {
96 for (const auto &FC
: Checksums
) {
97 FileChecksumEntryHeader Header
;
98 Header
.ChecksumKind
= uint8_t(FC
.Kind
);
99 Header
.ChecksumSize
= FC
.Checksum
.size();
100 Header
.FileNameOffset
= FC
.FileNameOffset
;
101 if (auto EC
= Writer
.writeObject(Header
))
103 if (auto EC
= Writer
.writeArray(makeArrayRef(FC
.Checksum
)))
105 if (auto EC
= Writer
.padToAlignment(4))
108 return Error::success();
111 uint32_t DebugChecksumsSubsection::mapChecksumOffset(StringRef FileName
) const {
112 uint32_t Offset
= Strings
.getIdForString(FileName
);
113 auto Iter
= OffsetMap
.find(Offset
);
114 assert(Iter
!= OffsetMap
.end());