1 //===- CodeViewYAMLTypeHashing.cpp - CodeView YAMLIO type hashing ---------===//
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 // This file defines classes for handling the YAML representation of CodeView
11 // Debug Info.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/ObjectYAML/CodeViewYAMLTypeHashing.h"
16 
17 #include "llvm/BinaryFormat/COFF.h"
18 #include "llvm/Support/BinaryByteStream.h"
19 #include "llvm/Support/BinaryStreamReader.h"
20 #include "llvm/Support/BinaryStreamWriter.h"
21 
22 using namespace llvm;
23 using namespace llvm::codeview;
24 using namespace llvm::CodeViewYAML;
25 using namespace llvm::yaml;
26 
27 namespace llvm {
28 namespace yaml {
29 
30 void MappingTraits<DebugHSection>::mapping(IO &io, DebugHSection &DebugH) {
31   io.mapRequired("Version", DebugH.Version);
32   io.mapRequired("HashAlgorithm", DebugH.HashAlgorithm);
33   io.mapOptional("HashValues", DebugH.Hashes);
34 }
35 
36 void ScalarTraits<GlobalHash>::output(const GlobalHash &GH, void *Ctx,
37                                       raw_ostream &OS) {
38   ScalarTraits<BinaryRef>::output(GH.Hash, Ctx, OS);
39 }
40 
41 StringRef ScalarTraits<GlobalHash>::input(StringRef Scalar, void *Ctx,
42                                           GlobalHash &GH) {
43   return ScalarTraits<BinaryRef>::input(Scalar, Ctx, GH.Hash);
44 }
45 
46 } // end namespace yaml
47 } // end namespace llvm
48 
49 DebugHSection llvm::CodeViewYAML::fromDebugH(ArrayRef<uint8_t> DebugH) {
50   assert(DebugH.size() >= 8);
51   assert((DebugH.size() - 8) % 8 == 0);
52 
53   BinaryStreamReader Reader(DebugH, llvm::support::little);
54   DebugHSection DHS;
55   cantFail(Reader.readInteger(DHS.Magic));
56   cantFail(Reader.readInteger(DHS.Version));
57   cantFail(Reader.readInteger(DHS.HashAlgorithm));
58   assert(DHS.Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$H section!");
59   assert(DHS.Version == 1 && "Invalid .debug$H version!");
60   assert(DHS.HashAlgorithm == 1 && "Invalid .debug$H algorithm!");
61 
62   while (Reader.bytesRemaining() != 0) {
63     ArrayRef<uint8_t> S;
64     cantFail(Reader.readBytes(S, 8));
65     DHS.Hashes.emplace_back(S);
66   }
67   assert(Reader.bytesRemaining() == 0);
68   return DHS;
69 }
70 
71 ArrayRef<uint8_t> llvm::CodeViewYAML::toDebugH(const DebugHSection &DebugH,
72                                                BumpPtrAllocator &Alloc) {
73   uint32_t Size = 8 + 8 * DebugH.Hashes.size();
74   uint8_t *Data = Alloc.Allocate<uint8_t>(Size);
75   MutableArrayRef<uint8_t> Buffer(Data, Size);
76   BinaryStreamWriter Writer(Buffer, llvm::support::little);
77   assert(DebugH.Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$H section!");
78   assert(DebugH.Version == 1 && "Invalid .debug$H version!");
79   assert(DebugH.HashAlgorithm == 1 && "Invalid .debug$H algorithm!");
80 
81   cantFail(Writer.writeInteger(DebugH.Magic));
82   cantFail(Writer.writeInteger(DebugH.Version));
83   cantFail(Writer.writeInteger(DebugH.HashAlgorithm));
84   SmallString<8> Hash;
85   for (const auto &H : DebugH.Hashes) {
86     Hash.clear();
87     raw_svector_ostream OS(Hash);
88     H.Hash.writeAsBinary(OS);
89     assert((Hash.size() == 8) && "Invalid hash size!");
90     cantFail(Writer.writeFixedString(Hash));
91   }
92   assert(Writer.bytesRemaining() == 0);
93   return Buffer;
94 }
95