FaultMaps.h 6.5 KB

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