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