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