1 //===-- FaultMapParser.h - Parser for the "FaultMaps" section --*- C++ -*-===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_OBJECT_FAULTMAPPARSER_H 10 #define LLVM_OBJECT_FAULTMAPPARSER_H 11 12 #include "llvm/Support/Compiler.h" 13 #include "llvm/Support/Endian.h" 14 #include <cassert> 15 #include <cstdint> 16 17 namespace llvm { 18 19 class raw_ostream; 20 21 /// A parser for the __llvm_faultmaps section generated by the FaultMaps class 22 /// declared in llvm/CodeGen/FaultMaps.h. This parser is version locked with 23 /// with the __llvm_faultmaps section generated by the version of LLVM that 24 /// includes it. No guarantees are made with respect to forward or backward 25 /// compatibility. 26 class FaultMapParser { 27 using FaultMapVersionType = uint8_t; 28 using Reserved0Type = uint8_t; 29 using Reserved1Type = uint16_t; 30 using NumFunctionsType = uint32_t; 31 32 static const size_t FaultMapVersionOffset = 0; 33 static const size_t Reserved0Offset = 34 FaultMapVersionOffset + sizeof(FaultMapVersionType); 35 static const size_t Reserved1Offset = Reserved0Offset + sizeof(Reserved0Type); 36 static const size_t NumFunctionsOffset = 37 Reserved1Offset + sizeof(Reserved1Type); 38 static const size_t FunctionInfosOffset = 39 NumFunctionsOffset + sizeof(NumFunctionsType); 40 41 const uint8_t *P; 42 const uint8_t *E; 43 read(const uint8_t * P,const uint8_t * E)44 template <typename T> static T read(const uint8_t *P, const uint8_t *E) { 45 assert(P + sizeof(T) <= E && "out of bounds read!"); 46 return support::endian::read<T, llvm::endianness::little>(P); 47 } 48 49 public: 50 enum FaultKind { 51 FaultingLoad = 1, 52 FaultingLoadStore, 53 FaultingStore, 54 FaultKindMax 55 }; 56 57 class FunctionFaultInfoAccessor { 58 using FaultKindType = uint32_t; 59 using FaultingPCOffsetType = uint32_t; 60 using HandlerPCOffsetType = uint32_t; 61 62 static const size_t FaultKindOffset = 0; 63 static const size_t FaultingPCOffsetOffset = 64 FaultKindOffset + sizeof(FaultKindType); 65 static const size_t HandlerPCOffsetOffset = 66 FaultingPCOffsetOffset + sizeof(FaultingPCOffsetType); 67 68 const uint8_t *P; 69 const uint8_t *E; 70 71 public: 72 static const size_t Size = 73 HandlerPCOffsetOffset + sizeof(HandlerPCOffsetType); 74 FunctionFaultInfoAccessor(const uint8_t * P,const uint8_t * E)75 explicit FunctionFaultInfoAccessor(const uint8_t *P, const uint8_t *E) 76 : P(P), E(E) {} 77 getFaultKind()78 FaultKindType getFaultKind() const { 79 return read<FaultKindType>(P + FaultKindOffset, E); 80 } 81 getFaultingPCOffset()82 FaultingPCOffsetType getFaultingPCOffset() const { 83 return read<FaultingPCOffsetType>(P + FaultingPCOffsetOffset, E); 84 } 85 getHandlerPCOffset()86 HandlerPCOffsetType getHandlerPCOffset() const { 87 return read<HandlerPCOffsetType>(P + HandlerPCOffsetOffset, E); 88 } 89 }; 90 91 class FunctionInfoAccessor { 92 using FunctionAddrType = uint64_t; 93 using NumFaultingPCsType = uint32_t; 94 using ReservedType = uint32_t; 95 96 static const size_t FunctionAddrOffset = 0; 97 static const size_t NumFaultingPCsOffset = 98 FunctionAddrOffset + sizeof(FunctionAddrType); 99 static const size_t ReservedOffset = 100 NumFaultingPCsOffset + sizeof(NumFaultingPCsType); 101 static const size_t FunctionFaultInfosOffset = 102 ReservedOffset + sizeof(ReservedType); 103 static const size_t FunctionInfoHeaderSize = FunctionFaultInfosOffset; 104 105 const uint8_t *P = nullptr; 106 const uint8_t *E = nullptr; 107 108 public: 109 FunctionInfoAccessor() = default; 110 FunctionInfoAccessor(const uint8_t * P,const uint8_t * E)111 explicit FunctionInfoAccessor(const uint8_t *P, const uint8_t *E) 112 : P(P), E(E) {} 113 getFunctionAddr()114 FunctionAddrType getFunctionAddr() const { 115 return read<FunctionAddrType>(P + FunctionAddrOffset, E); 116 } 117 getNumFaultingPCs()118 NumFaultingPCsType getNumFaultingPCs() const { 119 return read<NumFaultingPCsType>(P + NumFaultingPCsOffset, E); 120 } 121 getFunctionFaultInfoAt(uint32_t Index)122 FunctionFaultInfoAccessor getFunctionFaultInfoAt(uint32_t Index) const { 123 assert(Index < getNumFaultingPCs() && "index out of bounds!"); 124 const uint8_t *Begin = P + FunctionFaultInfosOffset + 125 FunctionFaultInfoAccessor::Size * Index; 126 return FunctionFaultInfoAccessor(Begin, E); 127 } 128 getNextFunctionInfo()129 FunctionInfoAccessor getNextFunctionInfo() const { 130 size_t MySize = FunctionInfoHeaderSize + 131 getNumFaultingPCs() * FunctionFaultInfoAccessor::Size; 132 133 const uint8_t *Begin = P + MySize; 134 assert(Begin < E && "out of bounds!"); 135 return FunctionInfoAccessor(Begin, E); 136 } 137 }; 138 FaultMapParser(const uint8_t * Begin,const uint8_t * End)139 explicit FaultMapParser(const uint8_t *Begin, const uint8_t *End) 140 : P(Begin), E(End) {} 141 getFaultMapVersion()142 FaultMapVersionType getFaultMapVersion() const { 143 auto Version = read<FaultMapVersionType>(P + FaultMapVersionOffset, E); 144 assert(Version == 1 && "only version 1 supported!"); 145 return Version; 146 } 147 getNumFunctions()148 NumFunctionsType getNumFunctions() const { 149 return read<NumFunctionsType>(P + NumFunctionsOffset, E); 150 } 151 getFirstFunctionInfo()152 FunctionInfoAccessor getFirstFunctionInfo() const { 153 const uint8_t *Begin = P + FunctionInfosOffset; 154 return FunctionInfoAccessor(Begin, E); 155 } 156 }; 157 158 LLVM_ABI raw_ostream & 159 operator<<(raw_ostream &OS, const FaultMapParser::FunctionFaultInfoAccessor &); 160 161 LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, 162 const FaultMapParser::FunctionInfoAccessor &); 163 164 LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const FaultMapParser &); 165 166 } // namespace llvm 167 168 #endif 169