1 //===- FaultMaps.h - The "FaultMaps" section --------------------*- C++ -*-===// 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 #ifndef LLVM_CODEGEN_FAULTMAPS_H 11 #define LLVM_CODEGEN_FAULTMAPS_H 12 13 #include "llvm/MC/MCSymbol.h" 14 #include "llvm/Support/Endian.h" 15 #include <cassert> 16 #include <cstddef> 17 #include <cstdint> 18 #include <map> 19 #include <vector> 20 21 namespace llvm { 22 23 class AsmPrinter; 24 class MCExpr; 25 class raw_ostream; 26 27 class FaultMaps { 28 public: 29 enum FaultKind { 30 FaultingLoad = 1, 31 FaultingLoadStore, 32 FaultingStore, 33 FaultKindMax 34 }; 35 36 explicit FaultMaps(AsmPrinter &AP); 37 38 static const char *faultTypeToString(FaultKind); 39 40 void recordFaultingOp(FaultKind FaultTy, const MCSymbol *HandlerLabel); 41 void serializeToFaultMapSection(); 42 void reset() { 43 FunctionInfos.clear(); 44 } 45 46 private: 47 static const char *WFMP; 48 49 struct FaultInfo { 50 FaultKind Kind = FaultKindMax; 51 const MCExpr *FaultingOffsetExpr = nullptr; 52 const MCExpr *HandlerOffsetExpr = nullptr; 53 54 FaultInfo() = default; 55 56 explicit FaultInfo(FaultMaps::FaultKind Kind, const MCExpr *FaultingOffset, 57 const MCExpr *HandlerOffset) 58 : Kind(Kind), FaultingOffsetExpr(FaultingOffset), 59 HandlerOffsetExpr(HandlerOffset) {} 60 }; 61 62 using FunctionFaultInfos = std::vector<FaultInfo>; 63 64 // We'd like to keep a stable iteration order for FunctionInfos to help 65 // FileCheck based testing. 66 struct MCSymbolComparator { 67 bool operator()(const MCSymbol *LHS, const MCSymbol *RHS) const { 68 return LHS->getName() < RHS->getName(); 69 } 70 }; 71 72 std::map<const MCSymbol *, FunctionFaultInfos, MCSymbolComparator> 73 FunctionInfos; 74 AsmPrinter &AP; 75 76 void emitFunctionInfo(const MCSymbol *FnLabel, const FunctionFaultInfos &FFI); 77 }; 78 79 /// A parser for the __llvm_faultmaps section generated by the FaultMaps class 80 /// above. This parser is version locked with with the __llvm_faultmaps section 81 /// generated by the version of LLVM that includes it. No guarantees are made 82 /// with respect to forward or backward compatibility. 83 class FaultMapParser { 84 using FaultMapVersionType = uint8_t; 85 using Reserved0Type = uint8_t; 86 using Reserved1Type = uint16_t; 87 using NumFunctionsType = uint32_t; 88 89 static const size_t FaultMapVersionOffset = 0; 90 static const size_t Reserved0Offset = 91 FaultMapVersionOffset + sizeof(FaultMapVersionType); 92 static const size_t Reserved1Offset = Reserved0Offset + sizeof(Reserved0Type); 93 static const size_t NumFunctionsOffset = 94 Reserved1Offset + sizeof(Reserved1Type); 95 static const size_t FunctionInfosOffset = 96 NumFunctionsOffset + sizeof(NumFunctionsType); 97 98 const uint8_t *P; 99 const uint8_t *E; 100 101 template <typename T> static T read(const uint8_t *P, const uint8_t *E) { 102 assert(P + sizeof(T) <= E && "out of bounds read!"); 103 return support::endian::read<T, support::little, 1>(P); 104 } 105 106 public: 107 class FunctionFaultInfoAccessor { 108 using FaultKindType = uint32_t; 109 using FaultingPCOffsetType = uint32_t; 110 using HandlerPCOffsetType = uint32_t; 111 112 static const size_t FaultKindOffset = 0; 113 static const size_t FaultingPCOffsetOffset = 114 FaultKindOffset + sizeof(FaultKindType); 115 static const size_t HandlerPCOffsetOffset = 116 FaultingPCOffsetOffset + sizeof(FaultingPCOffsetType); 117 118 const uint8_t *P; 119 const uint8_t *E; 120 121 public: 122 static const size_t Size = 123 HandlerPCOffsetOffset + sizeof(HandlerPCOffsetType); 124 125 explicit FunctionFaultInfoAccessor(const uint8_t *P, const uint8_t *E) 126 : P(P), E(E) {} 127 128 FaultKindType getFaultKind() const { 129 return read<FaultKindType>(P + FaultKindOffset, E); 130 } 131 132 FaultingPCOffsetType getFaultingPCOffset() const { 133 return read<FaultingPCOffsetType>(P + FaultingPCOffsetOffset, E); 134 } 135 136 HandlerPCOffsetType getHandlerPCOffset() const { 137 return read<HandlerPCOffsetType>(P + HandlerPCOffsetOffset, E); 138 } 139 }; 140 141 class FunctionInfoAccessor { 142 using FunctionAddrType = uint64_t; 143 using NumFaultingPCsType = uint32_t; 144 using ReservedType = uint32_t; 145 146 static const size_t FunctionAddrOffset = 0; 147 static const size_t NumFaultingPCsOffset = 148 FunctionAddrOffset + sizeof(FunctionAddrType); 149 static const size_t ReservedOffset = 150 NumFaultingPCsOffset + sizeof(NumFaultingPCsType); 151 static const size_t FunctionFaultInfosOffset = 152 ReservedOffset + sizeof(ReservedType); 153 static const size_t FunctionInfoHeaderSize = FunctionFaultInfosOffset; 154 155 const uint8_t *P = nullptr; 156 const uint8_t *E = nullptr; 157 158 public: 159 FunctionInfoAccessor() = default; 160 161 explicit FunctionInfoAccessor(const uint8_t *P, const uint8_t *E) 162 : P(P), E(E) {} 163 164 FunctionAddrType getFunctionAddr() const { 165 return read<FunctionAddrType>(P + FunctionAddrOffset, E); 166 } 167 168 NumFaultingPCsType getNumFaultingPCs() const { 169 return read<NumFaultingPCsType>(P + NumFaultingPCsOffset, E); 170 } 171 172 FunctionFaultInfoAccessor getFunctionFaultInfoAt(uint32_t Index) const { 173 assert(Index < getNumFaultingPCs() && "index out of bounds!"); 174 const uint8_t *Begin = P + FunctionFaultInfosOffset + 175 FunctionFaultInfoAccessor::Size * Index; 176 return FunctionFaultInfoAccessor(Begin, E); 177 } 178 179 FunctionInfoAccessor getNextFunctionInfo() const { 180 size_t MySize = FunctionInfoHeaderSize + 181 getNumFaultingPCs() * FunctionFaultInfoAccessor::Size; 182 183 const uint8_t *Begin = P + MySize; 184 assert(Begin < E && "out of bounds!"); 185 return FunctionInfoAccessor(Begin, E); 186 } 187 }; 188 189 explicit FaultMapParser(const uint8_t *Begin, const uint8_t *End) 190 : P(Begin), E(End) {} 191 192 FaultMapVersionType getFaultMapVersion() const { 193 auto Version = read<FaultMapVersionType>(P + FaultMapVersionOffset, E); 194 assert(Version == 1 && "only version 1 supported!"); 195 return Version; 196 } 197 198 NumFunctionsType getNumFunctions() const { 199 return read<NumFunctionsType>(P + NumFunctionsOffset, E); 200 } 201 202 FunctionInfoAccessor getFirstFunctionInfo() const { 203 const uint8_t *Begin = P + FunctionInfosOffset; 204 return FunctionInfoAccessor(Begin, E); 205 } 206 }; 207 208 raw_ostream & 209 operator<<(raw_ostream &OS, const FaultMapParser::FunctionFaultInfoAccessor &); 210 211 raw_ostream &operator<<(raw_ostream &OS, 212 const FaultMapParser::FunctionInfoAccessor &); 213 214 raw_ostream &operator<<(raw_ostream &OS, const FaultMapParser &); 215 216 } // end namespace llvm 217 218 #endif // LLVM_CODEGEN_FAULTMAPS_H 219