1 //===- FaultMaps.h - The "FaultMaps" section --------------------*- C++ -*-===//
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 #ifndef LLVM_CODEGEN_FAULTMAPS_H
10 #define LLVM_CODEGEN_FAULTMAPS_H
12 #include "llvm/MC/MCSymbol.h"
13 #include "llvm/Support/Endian.h"
35 explicit FaultMaps(AsmPrinter
&AP
);
37 static const char *faultTypeToString(FaultKind
);
39 void recordFaultingOp(FaultKind FaultTy
, const MCSymbol
*HandlerLabel
);
40 void serializeToFaultMapSection();
42 FunctionInfos
.clear();
46 static const char *WFMP
;
49 FaultKind Kind
= FaultKindMax
;
50 const MCExpr
*FaultingOffsetExpr
= nullptr;
51 const MCExpr
*HandlerOffsetExpr
= nullptr;
53 FaultInfo() = default;
55 explicit FaultInfo(FaultMaps::FaultKind Kind
, const MCExpr
*FaultingOffset
,
56 const MCExpr
*HandlerOffset
)
57 : Kind(Kind
), FaultingOffsetExpr(FaultingOffset
),
58 HandlerOffsetExpr(HandlerOffset
) {}
61 using FunctionFaultInfos
= std::vector
<FaultInfo
>;
63 // We'd like to keep a stable iteration order for FunctionInfos to help
64 // FileCheck based testing.
65 struct MCSymbolComparator
{
66 bool operator()(const MCSymbol
*LHS
, const MCSymbol
*RHS
) const {
67 return LHS
->getName() < RHS
->getName();
71 std::map
<const MCSymbol
*, FunctionFaultInfos
, MCSymbolComparator
>
75 void emitFunctionInfo(const MCSymbol
*FnLabel
, const FunctionFaultInfos
&FFI
);
78 /// A parser for the __llvm_faultmaps section generated by the FaultMaps class
79 /// above. This parser is version locked with with the __llvm_faultmaps section
80 /// generated by the version of LLVM that includes it. No guarantees are made
81 /// with respect to forward or backward compatibility.
82 class FaultMapParser
{
83 using FaultMapVersionType
= uint8_t;
84 using Reserved0Type
= uint8_t;
85 using Reserved1Type
= uint16_t;
86 using NumFunctionsType
= uint32_t;
88 static const size_t FaultMapVersionOffset
= 0;
89 static const size_t Reserved0Offset
=
90 FaultMapVersionOffset
+ sizeof(FaultMapVersionType
);
91 static const size_t Reserved1Offset
= Reserved0Offset
+ sizeof(Reserved0Type
);
92 static const size_t NumFunctionsOffset
=
93 Reserved1Offset
+ sizeof(Reserved1Type
);
94 static const size_t FunctionInfosOffset
=
95 NumFunctionsOffset
+ sizeof(NumFunctionsType
);
100 template <typename T
> static T
read(const uint8_t *P
, const uint8_t *E
) {
101 assert(P
+ sizeof(T
) <= E
&& "out of bounds read!");
102 return support::endian::read
<T
, support::little
, 1>(P
);
106 class FunctionFaultInfoAccessor
{
107 using FaultKindType
= uint32_t;
108 using FaultingPCOffsetType
= uint32_t;
109 using HandlerPCOffsetType
= uint32_t;
111 static const size_t FaultKindOffset
= 0;
112 static const size_t FaultingPCOffsetOffset
=
113 FaultKindOffset
+ sizeof(FaultKindType
);
114 static const size_t HandlerPCOffsetOffset
=
115 FaultingPCOffsetOffset
+ sizeof(FaultingPCOffsetType
);
121 static const size_t Size
=
122 HandlerPCOffsetOffset
+ sizeof(HandlerPCOffsetType
);
124 explicit FunctionFaultInfoAccessor(const uint8_t *P
, const uint8_t *E
)
127 FaultKindType
getFaultKind() const {
128 return read
<FaultKindType
>(P
+ FaultKindOffset
, E
);
131 FaultingPCOffsetType
getFaultingPCOffset() const {
132 return read
<FaultingPCOffsetType
>(P
+ FaultingPCOffsetOffset
, E
);
135 HandlerPCOffsetType
getHandlerPCOffset() const {
136 return read
<HandlerPCOffsetType
>(P
+ HandlerPCOffsetOffset
, E
);
140 class FunctionInfoAccessor
{
141 using FunctionAddrType
= uint64_t;
142 using NumFaultingPCsType
= uint32_t;
143 using ReservedType
= uint32_t;
145 static const size_t FunctionAddrOffset
= 0;
146 static const size_t NumFaultingPCsOffset
=
147 FunctionAddrOffset
+ sizeof(FunctionAddrType
);
148 static const size_t ReservedOffset
=
149 NumFaultingPCsOffset
+ sizeof(NumFaultingPCsType
);
150 static const size_t FunctionFaultInfosOffset
=
151 ReservedOffset
+ sizeof(ReservedType
);
152 static const size_t FunctionInfoHeaderSize
= FunctionFaultInfosOffset
;
154 const uint8_t *P
= nullptr;
155 const uint8_t *E
= nullptr;
158 FunctionInfoAccessor() = default;
160 explicit FunctionInfoAccessor(const uint8_t *P
, const uint8_t *E
)
163 FunctionAddrType
getFunctionAddr() const {
164 return read
<FunctionAddrType
>(P
+ FunctionAddrOffset
, E
);
167 NumFaultingPCsType
getNumFaultingPCs() const {
168 return read
<NumFaultingPCsType
>(P
+ NumFaultingPCsOffset
, E
);
171 FunctionFaultInfoAccessor
getFunctionFaultInfoAt(uint32_t Index
) const {
172 assert(Index
< getNumFaultingPCs() && "index out of bounds!");
173 const uint8_t *Begin
= P
+ FunctionFaultInfosOffset
+
174 FunctionFaultInfoAccessor::Size
* Index
;
175 return FunctionFaultInfoAccessor(Begin
, E
);
178 FunctionInfoAccessor
getNextFunctionInfo() const {
179 size_t MySize
= FunctionInfoHeaderSize
+
180 getNumFaultingPCs() * FunctionFaultInfoAccessor::Size
;
182 const uint8_t *Begin
= P
+ MySize
;
183 assert(Begin
< E
&& "out of bounds!");
184 return FunctionInfoAccessor(Begin
, E
);
188 explicit FaultMapParser(const uint8_t *Begin
, const uint8_t *End
)
189 : P(Begin
), E(End
) {}
191 FaultMapVersionType
getFaultMapVersion() const {
192 auto Version
= read
<FaultMapVersionType
>(P
+ FaultMapVersionOffset
, E
);
193 assert(Version
== 1 && "only version 1 supported!");
197 NumFunctionsType
getNumFunctions() const {
198 return read
<NumFunctionsType
>(P
+ NumFunctionsOffset
, E
);
201 FunctionInfoAccessor
getFirstFunctionInfo() const {
202 const uint8_t *Begin
= P
+ FunctionInfosOffset
;
203 return FunctionInfoAccessor(Begin
, E
);
208 operator<<(raw_ostream
&OS
, const FaultMapParser::FunctionFaultInfoAccessor
&);
210 raw_ostream
&operator<<(raw_ostream
&OS
,
211 const FaultMapParser::FunctionInfoAccessor
&);
213 raw_ostream
&operator<<(raw_ostream
&OS
, const FaultMapParser
&);
215 } // end namespace llvm
217 #endif // LLVM_CODEGEN_FAULTMAPS_H