1 //===- FaultMaps.h - The "FaultMaps" section --------------------*- C++ -*-===//
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 #ifndef LLVM_CODEGEN_FAULTMAPS_H
11 #define LLVM_CODEGEN_FAULTMAPS_H
13 #include "llvm/MC/MCSymbol.h"
14 #include "llvm/Support/Endian.h"
36 explicit FaultMaps(AsmPrinter &AP);
38 static const char *faultTypeToString(FaultKind);
40 void recordFaultingOp(FaultKind FaultTy, const MCSymbol *HandlerLabel);
41 void serializeToFaultMapSection();
44 static const char *WFMP;
47 FaultKind Kind = FaultKindMax;
48 const MCExpr *FaultingOffsetExpr = nullptr;
49 const MCExpr *HandlerOffsetExpr = nullptr;
51 FaultInfo() = default;
53 explicit FaultInfo(FaultMaps::FaultKind Kind, const MCExpr *FaultingOffset,
54 const MCExpr *HandlerOffset)
55 : Kind(Kind), FaultingOffsetExpr(FaultingOffset),
56 HandlerOffsetExpr(HandlerOffset) {}
59 using FunctionFaultInfos = std::vector<FaultInfo>;
61 // We'd like to keep a stable iteration order for FunctionInfos to help
62 // FileCheck based testing.
63 struct MCSymbolComparator {
64 bool operator()(const MCSymbol *LHS, const MCSymbol *RHS) const {
65 return LHS->getName() < RHS->getName();
69 std::map<const MCSymbol *, FunctionFaultInfos, MCSymbolComparator>
73 void emitFunctionInfo(const MCSymbol *FnLabel, const FunctionFaultInfos &FFI);
76 /// A parser for the __llvm_faultmaps section generated by the FaultMaps class
77 /// above. This parser is version locked with with the __llvm_faultmaps section
78 /// generated by the version of LLVM that includes it. No guarantees are made
79 /// with respect to forward or backward compatibility.
80 class FaultMapParser {
81 using FaultMapVersionType = uint8_t;
82 using Reserved0Type = uint8_t;
83 using Reserved1Type = uint16_t;
84 using NumFunctionsType = uint32_t;
86 static const size_t FaultMapVersionOffset = 0;
87 static const size_t Reserved0Offset =
88 FaultMapVersionOffset + sizeof(FaultMapVersionType);
89 static const size_t Reserved1Offset = Reserved0Offset + sizeof(Reserved0Type);
90 static const size_t NumFunctionsOffset =
91 Reserved1Offset + sizeof(Reserved1Type);
92 static const size_t FunctionInfosOffset =
93 NumFunctionsOffset + sizeof(NumFunctionsType);
98 template <typename T> static T read(const uint8_t *P, const uint8_t *E) {
99 assert(P + sizeof(T) <= E && "out of bounds read!");
100 return support::endian::read<T, support::little, 1>(P);
104 class FunctionFaultInfoAccessor {
105 using FaultKindType = uint32_t;
106 using FaultingPCOffsetType = uint32_t;
107 using HandlerPCOffsetType = uint32_t;
109 static const size_t FaultKindOffset = 0;
110 static const size_t FaultingPCOffsetOffset =
111 FaultKindOffset + sizeof(FaultKindType);
112 static const size_t HandlerPCOffsetOffset =
113 FaultingPCOffsetOffset + sizeof(FaultingPCOffsetType);
119 static const size_t Size =
120 HandlerPCOffsetOffset + sizeof(HandlerPCOffsetType);
122 explicit FunctionFaultInfoAccessor(const uint8_t *P, const uint8_t *E)
125 FaultKindType getFaultKind() const {
126 return read<FaultKindType>(P + FaultKindOffset, E);
129 FaultingPCOffsetType getFaultingPCOffset() const {
130 return read<FaultingPCOffsetType>(P + FaultingPCOffsetOffset, E);
133 HandlerPCOffsetType getHandlerPCOffset() const {
134 return read<HandlerPCOffsetType>(P + HandlerPCOffsetOffset, E);
138 class FunctionInfoAccessor {
139 using FunctionAddrType = uint64_t;
140 using NumFaultingPCsType = uint32_t;
141 using ReservedType = uint32_t;
143 static const size_t FunctionAddrOffset = 0;
144 static const size_t NumFaultingPCsOffset =
145 FunctionAddrOffset + sizeof(FunctionAddrType);
146 static const size_t ReservedOffset =
147 NumFaultingPCsOffset + sizeof(NumFaultingPCsType);
148 static const size_t FunctionFaultInfosOffset =
149 ReservedOffset + sizeof(ReservedType);
150 static const size_t FunctionInfoHeaderSize = FunctionFaultInfosOffset;
152 const uint8_t *P = nullptr;
153 const uint8_t *E = nullptr;
156 FunctionInfoAccessor() = default;
158 explicit FunctionInfoAccessor(const uint8_t *P, const uint8_t *E)
161 FunctionAddrType getFunctionAddr() const {
162 return read<FunctionAddrType>(P + FunctionAddrOffset, E);
165 NumFaultingPCsType getNumFaultingPCs() const {
166 return read<NumFaultingPCsType>(P + NumFaultingPCsOffset, E);
169 FunctionFaultInfoAccessor getFunctionFaultInfoAt(uint32_t Index) const {
170 assert(Index < getNumFaultingPCs() && "index out of bounds!");
171 const uint8_t *Begin = P + FunctionFaultInfosOffset +
172 FunctionFaultInfoAccessor::Size * Index;
173 return FunctionFaultInfoAccessor(Begin, E);
176 FunctionInfoAccessor getNextFunctionInfo() const {
177 size_t MySize = FunctionInfoHeaderSize +
178 getNumFaultingPCs() * FunctionFaultInfoAccessor::Size;
180 const uint8_t *Begin = P + MySize;
181 assert(Begin < E && "out of bounds!");
182 return FunctionInfoAccessor(Begin, E);
186 explicit FaultMapParser(const uint8_t *Begin, const uint8_t *End)
187 : P(Begin), E(End) {}
189 FaultMapVersionType getFaultMapVersion() const {
190 auto Version = read<FaultMapVersionType>(P + FaultMapVersionOffset, E);
191 assert(Version == 1 && "only version 1 supported!");
195 NumFunctionsType getNumFunctions() const {
196 return read<NumFunctionsType>(P + NumFunctionsOffset, E);
199 FunctionInfoAccessor getFirstFunctionInfo() const {
200 const uint8_t *Begin = P + FunctionInfosOffset;
201 return FunctionInfoAccessor(Begin, E);
206 operator<<(raw_ostream &OS, const FaultMapParser::FunctionFaultInfoAccessor &);
208 raw_ostream &operator<<(raw_ostream &OS,
209 const FaultMapParser::FunctionInfoAccessor &);
211 raw_ostream &operator<<(raw_ostream &OS, const FaultMapParser &);
213 } // end namespace llvm
215 #endif // LLVM_CODEGEN_FAULTMAPS_H