xref: /llvm-project/llvm/include/llvm/Object/FaultMapParser.h (revision 4a0ccfa865437fe29ef2ecb18152df7694dddb7f)
10b50fa99SCraig Topper //===-- FaultMapParser.h - Parser for the  "FaultMaps" section --*- C++ -*-===//
20b50fa99SCraig Topper //
30b50fa99SCraig Topper // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b50fa99SCraig Topper // See https://llvm.org/LICENSE.txt for license information.
50b50fa99SCraig Topper // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b50fa99SCraig Topper //
70b50fa99SCraig Topper //===----------------------------------------------------------------------===//
80b50fa99SCraig Topper 
90b50fa99SCraig Topper #ifndef LLVM_OBJECT_FAULTMAPPARSER_H
100b50fa99SCraig Topper #define LLVM_OBJECT_FAULTMAPPARSER_H
110b50fa99SCraig Topper 
120b50fa99SCraig Topper #include "llvm/Support/Endian.h"
130b50fa99SCraig Topper #include <cassert>
140b50fa99SCraig Topper #include <cstdint>
150b50fa99SCraig Topper 
160b50fa99SCraig Topper namespace llvm {
170b50fa99SCraig Topper 
180b50fa99SCraig Topper class raw_ostream;
190b50fa99SCraig Topper 
200b50fa99SCraig Topper /// A parser for the __llvm_faultmaps section generated by the FaultMaps class
210b50fa99SCraig Topper /// declared in llvm/CodeGen/FaultMaps.h.  This parser is version locked with
220b50fa99SCraig Topper /// with the __llvm_faultmaps section generated by the version of LLVM that
230b50fa99SCraig Topper /// includes it.  No guarantees are made with respect to forward or backward
240b50fa99SCraig Topper /// compatibility.
250b50fa99SCraig Topper class FaultMapParser {
260b50fa99SCraig Topper   using FaultMapVersionType = uint8_t;
270b50fa99SCraig Topper   using Reserved0Type = uint8_t;
280b50fa99SCraig Topper   using Reserved1Type = uint16_t;
290b50fa99SCraig Topper   using NumFunctionsType = uint32_t;
300b50fa99SCraig Topper 
310b50fa99SCraig Topper   static const size_t FaultMapVersionOffset = 0;
320b50fa99SCraig Topper   static const size_t Reserved0Offset =
330b50fa99SCraig Topper       FaultMapVersionOffset + sizeof(FaultMapVersionType);
340b50fa99SCraig Topper   static const size_t Reserved1Offset = Reserved0Offset + sizeof(Reserved0Type);
350b50fa99SCraig Topper   static const size_t NumFunctionsOffset =
360b50fa99SCraig Topper       Reserved1Offset + sizeof(Reserved1Type);
370b50fa99SCraig Topper   static const size_t FunctionInfosOffset =
380b50fa99SCraig Topper       NumFunctionsOffset + sizeof(NumFunctionsType);
390b50fa99SCraig Topper 
400b50fa99SCraig Topper   const uint8_t *P;
410b50fa99SCraig Topper   const uint8_t *E;
420b50fa99SCraig Topper 
read(const uint8_t * P,const uint8_t * E)430b50fa99SCraig Topper   template <typename T> static T read(const uint8_t *P, const uint8_t *E) {
440b50fa99SCraig Topper     assert(P + sizeof(T) <= E && "out of bounds read!");
45*4a0ccfa8SKazu Hirata     return support::endian::read<T, llvm::endianness::little>(P);
460b50fa99SCraig Topper   }
470b50fa99SCraig Topper 
480b50fa99SCraig Topper public:
490b50fa99SCraig Topper   enum FaultKind {
500b50fa99SCraig Topper     FaultingLoad = 1,
510b50fa99SCraig Topper     FaultingLoadStore,
520b50fa99SCraig Topper     FaultingStore,
530b50fa99SCraig Topper     FaultKindMax
540b50fa99SCraig Topper   };
550b50fa99SCraig Topper 
560b50fa99SCraig Topper   class FunctionFaultInfoAccessor {
570b50fa99SCraig Topper     using FaultKindType = uint32_t;
580b50fa99SCraig Topper     using FaultingPCOffsetType = uint32_t;
590b50fa99SCraig Topper     using HandlerPCOffsetType = uint32_t;
600b50fa99SCraig Topper 
610b50fa99SCraig Topper     static const size_t FaultKindOffset = 0;
620b50fa99SCraig Topper     static const size_t FaultingPCOffsetOffset =
630b50fa99SCraig Topper         FaultKindOffset + sizeof(FaultKindType);
640b50fa99SCraig Topper     static const size_t HandlerPCOffsetOffset =
650b50fa99SCraig Topper         FaultingPCOffsetOffset + sizeof(FaultingPCOffsetType);
660b50fa99SCraig Topper 
670b50fa99SCraig Topper     const uint8_t *P;
680b50fa99SCraig Topper     const uint8_t *E;
690b50fa99SCraig Topper 
700b50fa99SCraig Topper   public:
710b50fa99SCraig Topper     static const size_t Size =
720b50fa99SCraig Topper         HandlerPCOffsetOffset + sizeof(HandlerPCOffsetType);
730b50fa99SCraig Topper 
FunctionFaultInfoAccessor(const uint8_t * P,const uint8_t * E)740b50fa99SCraig Topper     explicit FunctionFaultInfoAccessor(const uint8_t *P, const uint8_t *E)
750b50fa99SCraig Topper         : P(P), E(E) {}
760b50fa99SCraig Topper 
getFaultKind()770b50fa99SCraig Topper     FaultKindType getFaultKind() const {
780b50fa99SCraig Topper       return read<FaultKindType>(P + FaultKindOffset, E);
790b50fa99SCraig Topper     }
800b50fa99SCraig Topper 
getFaultingPCOffset()810b50fa99SCraig Topper     FaultingPCOffsetType getFaultingPCOffset() const {
820b50fa99SCraig Topper       return read<FaultingPCOffsetType>(P + FaultingPCOffsetOffset, E);
830b50fa99SCraig Topper     }
840b50fa99SCraig Topper 
getHandlerPCOffset()850b50fa99SCraig Topper     HandlerPCOffsetType getHandlerPCOffset() const {
860b50fa99SCraig Topper       return read<HandlerPCOffsetType>(P + HandlerPCOffsetOffset, E);
870b50fa99SCraig Topper     }
880b50fa99SCraig Topper   };
890b50fa99SCraig Topper 
900b50fa99SCraig Topper   class FunctionInfoAccessor {
910b50fa99SCraig Topper     using FunctionAddrType = uint64_t;
920b50fa99SCraig Topper     using NumFaultingPCsType = uint32_t;
930b50fa99SCraig Topper     using ReservedType = uint32_t;
940b50fa99SCraig Topper 
950b50fa99SCraig Topper     static const size_t FunctionAddrOffset = 0;
960b50fa99SCraig Topper     static const size_t NumFaultingPCsOffset =
970b50fa99SCraig Topper         FunctionAddrOffset + sizeof(FunctionAddrType);
980b50fa99SCraig Topper     static const size_t ReservedOffset =
990b50fa99SCraig Topper         NumFaultingPCsOffset + sizeof(NumFaultingPCsType);
1000b50fa99SCraig Topper     static const size_t FunctionFaultInfosOffset =
1010b50fa99SCraig Topper         ReservedOffset + sizeof(ReservedType);
1020b50fa99SCraig Topper     static const size_t FunctionInfoHeaderSize = FunctionFaultInfosOffset;
1030b50fa99SCraig Topper 
1040b50fa99SCraig Topper     const uint8_t *P = nullptr;
1050b50fa99SCraig Topper     const uint8_t *E = nullptr;
1060b50fa99SCraig Topper 
1070b50fa99SCraig Topper   public:
1080b50fa99SCraig Topper     FunctionInfoAccessor() = default;
1090b50fa99SCraig Topper 
FunctionInfoAccessor(const uint8_t * P,const uint8_t * E)1100b50fa99SCraig Topper     explicit FunctionInfoAccessor(const uint8_t *P, const uint8_t *E)
1110b50fa99SCraig Topper         : P(P), E(E) {}
1120b50fa99SCraig Topper 
getFunctionAddr()1130b50fa99SCraig Topper     FunctionAddrType getFunctionAddr() const {
1140b50fa99SCraig Topper       return read<FunctionAddrType>(P + FunctionAddrOffset, E);
1150b50fa99SCraig Topper     }
1160b50fa99SCraig Topper 
getNumFaultingPCs()1170b50fa99SCraig Topper     NumFaultingPCsType getNumFaultingPCs() const {
1180b50fa99SCraig Topper       return read<NumFaultingPCsType>(P + NumFaultingPCsOffset, E);
1190b50fa99SCraig Topper     }
1200b50fa99SCraig Topper 
getFunctionFaultInfoAt(uint32_t Index)1210b50fa99SCraig Topper     FunctionFaultInfoAccessor getFunctionFaultInfoAt(uint32_t Index) const {
1220b50fa99SCraig Topper       assert(Index < getNumFaultingPCs() && "index out of bounds!");
1230b50fa99SCraig Topper       const uint8_t *Begin = P + FunctionFaultInfosOffset +
1240b50fa99SCraig Topper                              FunctionFaultInfoAccessor::Size * Index;
1250b50fa99SCraig Topper       return FunctionFaultInfoAccessor(Begin, E);
1260b50fa99SCraig Topper     }
1270b50fa99SCraig Topper 
getNextFunctionInfo()1280b50fa99SCraig Topper     FunctionInfoAccessor getNextFunctionInfo() const {
1290b50fa99SCraig Topper       size_t MySize = FunctionInfoHeaderSize +
1300b50fa99SCraig Topper                       getNumFaultingPCs() * FunctionFaultInfoAccessor::Size;
1310b50fa99SCraig Topper 
1320b50fa99SCraig Topper       const uint8_t *Begin = P + MySize;
1330b50fa99SCraig Topper       assert(Begin < E && "out of bounds!");
1340b50fa99SCraig Topper       return FunctionInfoAccessor(Begin, E);
1350b50fa99SCraig Topper     }
1360b50fa99SCraig Topper   };
1370b50fa99SCraig Topper 
FaultMapParser(const uint8_t * Begin,const uint8_t * End)1380b50fa99SCraig Topper   explicit FaultMapParser(const uint8_t *Begin, const uint8_t *End)
1390b50fa99SCraig Topper       : P(Begin), E(End) {}
1400b50fa99SCraig Topper 
getFaultMapVersion()1410b50fa99SCraig Topper   FaultMapVersionType getFaultMapVersion() const {
1420b50fa99SCraig Topper     auto Version = read<FaultMapVersionType>(P + FaultMapVersionOffset, E);
1430b50fa99SCraig Topper     assert(Version == 1 && "only version 1 supported!");
1440b50fa99SCraig Topper     return Version;
1450b50fa99SCraig Topper   }
1460b50fa99SCraig Topper 
getNumFunctions()1470b50fa99SCraig Topper   NumFunctionsType getNumFunctions() const {
1480b50fa99SCraig Topper     return read<NumFunctionsType>(P + NumFunctionsOffset, E);
1490b50fa99SCraig Topper   }
1500b50fa99SCraig Topper 
getFirstFunctionInfo()1510b50fa99SCraig Topper   FunctionInfoAccessor getFirstFunctionInfo() const {
1520b50fa99SCraig Topper     const uint8_t *Begin = P + FunctionInfosOffset;
1530b50fa99SCraig Topper     return FunctionInfoAccessor(Begin, E);
1540b50fa99SCraig Topper   }
1550b50fa99SCraig Topper };
1560b50fa99SCraig Topper 
1570b50fa99SCraig Topper raw_ostream &operator<<(raw_ostream &OS,
1580b50fa99SCraig Topper                         const FaultMapParser::FunctionFaultInfoAccessor &);
1590b50fa99SCraig Topper 
1600b50fa99SCraig Topper raw_ostream &operator<<(raw_ostream &OS,
1610b50fa99SCraig Topper                         const FaultMapParser::FunctionInfoAccessor &);
1620b50fa99SCraig Topper 
1630b50fa99SCraig Topper raw_ostream &operator<<(raw_ostream &OS, const FaultMapParser &);
1640b50fa99SCraig Topper 
1650b50fa99SCraig Topper } // namespace llvm
1660b50fa99SCraig Topper 
1670b50fa99SCraig Topper #endif
168