Line data Source code
1 : //===- TpiHashing.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/PDB/Raw/TpiHashing.h"
11 :
12 : #include "llvm/DebugInfo/PDB/Raw/Hash.h"
13 : #include "llvm/DebugInfo/PDB/Raw/RawError.h"
14 :
15 : using namespace llvm;
16 : using namespace llvm::codeview;
17 : using namespace llvm::pdb;
18 :
19 : // Corresponds to `fUDTAnon`.
20 242 : template <typename T> static bool isAnonymous(T &Rec) {
21 242 : StringRef Name = Rec.getName();
22 1452 : return Name == "<unnamed-tag>" || Name == "__unnamed" ||
23 1452 : Name.endswith("::<unnamed-tag>") || Name.endswith("::__unnamed");
24 : }
25 :
26 : // Computes a hash for a given TPI record.
27 : template <typename T>
28 242 : static uint32_t getTpiHash(T &Rec, ArrayRef<uint8_t> FullRecord) {
29 242 : auto Opts = static_cast<uint16_t>(Rec.getOptions());
30 :
31 : bool ForwardRef =
32 242 : Opts & static_cast<uint16_t>(ClassOptions::ForwardReference);
33 242 : bool Scoped = Opts & static_cast<uint16_t>(ClassOptions::Scoped);
34 242 : bool UniqueName = Opts & static_cast<uint16_t>(ClassOptions::HasUniqueName);
35 242 : bool IsAnon = UniqueName && isAnonymous(Rec);
36 :
37 242 : if (!ForwardRef && !Scoped && !IsAnon)
38 165 : return hashStringV1(Rec.getName());
39 77 : if (!ForwardRef && UniqueName && !IsAnon)
40 0 : return hashStringV1(Rec.getUniqueName());
41 77 : return hashBufferV8(FullRecord);
42 : }
43 :
44 0 : template <typename T> static uint32_t getSourceLineHash(T &Rec) {
45 : char Buf[4];
46 0 : support::endian::write32le(Buf, Rec.getUDT().getIndex());
47 0 : return hashStringV1(StringRef(Buf, 4));
48 : }
49 :
50 0 : void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR,
51 : UdtSourceLineRecord &Rec) {
52 0 : CVR.Hash = getSourceLineHash(Rec);
53 0 : }
54 :
55 0 : void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR,
56 : UdtModSourceLineRecord &Rec) {
57 0 : CVR.Hash = getSourceLineHash(Rec);
58 0 : }
59 :
60 28 : void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, ClassRecord &Rec) {
61 56 : CVR.Hash = getTpiHash(Rec, CVR.data());
62 28 : }
63 :
64 16 : void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, EnumRecord &Rec) {
65 32 : CVR.Hash = getTpiHash(Rec, CVR.data());
66 16 : }
67 :
68 0 : void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, UnionRecord &Rec) {
69 0 : CVR.Hash = getTpiHash(Rec, CVR.data());
70 0 : }
71 :
72 0 : Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UdtSourceLineRecord &Rec) {
73 0 : return verifySourceLine(Rec.getUDT());
74 : }
75 :
76 28 : Error TpiHashVerifier::visitKnownRecord(CVType &CVR,
77 : UdtModSourceLineRecord &Rec) {
78 28 : return verifySourceLine(Rec.getUDT());
79 : }
80 :
81 126 : Error TpiHashVerifier::visitKnownRecord(CVType &CVR, ClassRecord &Rec) {
82 252 : if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
83 0 : return errorInvalidHash();
84 378 : return Error::success();
85 : }
86 72 : Error TpiHashVerifier::visitKnownRecord(CVType &CVR, EnumRecord &Rec) {
87 144 : if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
88 0 : return errorInvalidHash();
89 216 : return Error::success();
90 : }
91 0 : Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UnionRecord &Rec) {
92 0 : if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
93 0 : return errorInvalidHash();
94 0 : return Error::success();
95 : }
96 :
97 28 : Error TpiHashVerifier::verifySourceLine(codeview::TypeIndex TI) {
98 : char Buf[4];
99 56 : support::endian::write32le(Buf, TI.getIndex());
100 28 : uint32_t Hash = hashStringV1(StringRef(Buf, 4));
101 56 : if (Hash % NumHashBuckets != HashValues[Index])
102 0 : return errorInvalidHash();
103 84 : return Error::success();
104 : }
105 :
106 735 : Error TpiHashVerifier::visitTypeBegin(CVType &Rec) {
107 735 : ++Index;
108 1470 : RawRecord = Rec;
109 2205 : return Error::success();
110 : }
|