1 //===-- FaultMapParser.h - Parser for the  "FaultMaps" section --*- C++ -*-===//
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 #ifndef LLVM_OBJECT_FAULTMAPPARSER_H
10 #define LLVM_OBJECT_FAULTMAPPARSER_H
11 
12 #include "llvm/Support/Endian.h"
13 #include <cassert>
14 #include <cstdint>
15 
16 namespace llvm {
17 
18 class raw_ostream;
19 
20 /// A parser for the __llvm_faultmaps section generated by the FaultMaps class
21 /// declared in llvm/CodeGen/FaultMaps.h.  This parser is version locked with
22 /// with the __llvm_faultmaps section generated by the version of LLVM that
23 /// includes it.  No guarantees are made with respect to forward or backward
24 /// compatibility.
25 class FaultMapParser {
26   using FaultMapVersionType = uint8_t;
27   using Reserved0Type = uint8_t;
28   using Reserved1Type = uint16_t;
29   using NumFunctionsType = uint32_t;
30 
31   static const size_t FaultMapVersionOffset = 0;
32   static const size_t Reserved0Offset =
33       FaultMapVersionOffset + sizeof(FaultMapVersionType);
34   static const size_t Reserved1Offset = Reserved0Offset + sizeof(Reserved0Type);
35   static const size_t NumFunctionsOffset =
36       Reserved1Offset + sizeof(Reserved1Type);
37   static const size_t FunctionInfosOffset =
38       NumFunctionsOffset + sizeof(NumFunctionsType);
39 
40   const uint8_t *P;
41   const uint8_t *E;
42 
read(const uint8_t * P,const uint8_t * E)43   template <typename T> static T read(const uint8_t *P, const uint8_t *E) {
44     assert(P + sizeof(T) <= E && "out of bounds read!");
45     return support::endian::read<T, llvm::endianness::little>(P);
46   }
47 
48 public:
49   enum FaultKind {
50     FaultingLoad = 1,
51     FaultingLoadStore,
52     FaultingStore,
53     FaultKindMax
54   };
55 
56   class FunctionFaultInfoAccessor {
57     using FaultKindType = uint32_t;
58     using FaultingPCOffsetType = uint32_t;
59     using HandlerPCOffsetType = uint32_t;
60 
61     static const size_t FaultKindOffset = 0;
62     static const size_t FaultingPCOffsetOffset =
63         FaultKindOffset + sizeof(FaultKindType);
64     static const size_t HandlerPCOffsetOffset =
65         FaultingPCOffsetOffset + sizeof(FaultingPCOffsetType);
66 
67     const uint8_t *P;
68     const uint8_t *E;
69 
70   public:
71     static const size_t Size =
72         HandlerPCOffsetOffset + sizeof(HandlerPCOffsetType);
73 
FunctionFaultInfoAccessor(const uint8_t * P,const uint8_t * E)74     explicit FunctionFaultInfoAccessor(const uint8_t *P, const uint8_t *E)
75         : P(P), E(E) {}
76 
getFaultKind()77     FaultKindType getFaultKind() const {
78       return read<FaultKindType>(P + FaultKindOffset, E);
79     }
80 
getFaultingPCOffset()81     FaultingPCOffsetType getFaultingPCOffset() const {
82       return read<FaultingPCOffsetType>(P + FaultingPCOffsetOffset, E);
83     }
84 
getHandlerPCOffset()85     HandlerPCOffsetType getHandlerPCOffset() const {
86       return read<HandlerPCOffsetType>(P + HandlerPCOffsetOffset, E);
87     }
88   };
89 
90   class FunctionInfoAccessor {
91     using FunctionAddrType = uint64_t;
92     using NumFaultingPCsType = uint32_t;
93     using ReservedType = uint32_t;
94 
95     static const size_t FunctionAddrOffset = 0;
96     static const size_t NumFaultingPCsOffset =
97         FunctionAddrOffset + sizeof(FunctionAddrType);
98     static const size_t ReservedOffset =
99         NumFaultingPCsOffset + sizeof(NumFaultingPCsType);
100     static const size_t FunctionFaultInfosOffset =
101         ReservedOffset + sizeof(ReservedType);
102     static const size_t FunctionInfoHeaderSize = FunctionFaultInfosOffset;
103 
104     const uint8_t *P = nullptr;
105     const uint8_t *E = nullptr;
106 
107   public:
108     FunctionInfoAccessor() = default;
109 
FunctionInfoAccessor(const uint8_t * P,const uint8_t * E)110     explicit FunctionInfoAccessor(const uint8_t *P, const uint8_t *E)
111         : P(P), E(E) {}
112 
getFunctionAddr()113     FunctionAddrType getFunctionAddr() const {
114       return read<FunctionAddrType>(P + FunctionAddrOffset, E);
115     }
116 
getNumFaultingPCs()117     NumFaultingPCsType getNumFaultingPCs() const {
118       return read<NumFaultingPCsType>(P + NumFaultingPCsOffset, E);
119     }
120 
getFunctionFaultInfoAt(uint32_t Index)121     FunctionFaultInfoAccessor getFunctionFaultInfoAt(uint32_t Index) const {
122       assert(Index < getNumFaultingPCs() && "index out of bounds!");
123       const uint8_t *Begin = P + FunctionFaultInfosOffset +
124                              FunctionFaultInfoAccessor::Size * Index;
125       return FunctionFaultInfoAccessor(Begin, E);
126     }
127 
getNextFunctionInfo()128     FunctionInfoAccessor getNextFunctionInfo() const {
129       size_t MySize = FunctionInfoHeaderSize +
130                       getNumFaultingPCs() * FunctionFaultInfoAccessor::Size;
131 
132       const uint8_t *Begin = P + MySize;
133       assert(Begin < E && "out of bounds!");
134       return FunctionInfoAccessor(Begin, E);
135     }
136   };
137 
FaultMapParser(const uint8_t * Begin,const uint8_t * End)138   explicit FaultMapParser(const uint8_t *Begin, const uint8_t *End)
139       : P(Begin), E(End) {}
140 
getFaultMapVersion()141   FaultMapVersionType getFaultMapVersion() const {
142     auto Version = read<FaultMapVersionType>(P + FaultMapVersionOffset, E);
143     assert(Version == 1 && "only version 1 supported!");
144     return Version;
145   }
146 
getNumFunctions()147   NumFunctionsType getNumFunctions() const {
148     return read<NumFunctionsType>(P + NumFunctionsOffset, E);
149   }
150 
getFirstFunctionInfo()151   FunctionInfoAccessor getFirstFunctionInfo() const {
152     const uint8_t *Begin = P + FunctionInfosOffset;
153     return FunctionInfoAccessor(Begin, E);
154   }
155 };
156 
157 raw_ostream &operator<<(raw_ostream &OS,
158                         const FaultMapParser::FunctionFaultInfoAccessor &);
159 
160 raw_ostream &operator<<(raw_ostream &OS,
161                         const FaultMapParser::FunctionInfoAccessor &);
162 
163 raw_ostream &operator<<(raw_ostream &OS, const FaultMapParser &);
164 
165 } // namespace llvm
166 
167 #endif
168