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