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