1 | /* |
2 | * TargetValue.h -- Access to target values using OMPD callbacks |
3 | */ |
4 | |
5 | //===----------------------------------------------------------------------===// |
6 | // |
7 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
8 | // See https://llvm.org/LICENSE.txt for license information. |
9 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "omp-tools.h" |
14 | #include "ompd-private.h" |
15 | #include <stdlib.h> |
16 | |
17 | #ifndef SRC_TARGET_VALUE_H_ |
18 | #define SRC_TARGET_VALUE_H_ |
19 | |
20 | #ifdef __cplusplus |
21 | |
22 | #include <cassert> |
23 | #include <map> |
24 | #include <string> |
25 | |
26 | class TType; |
27 | class TValue; |
28 | class TBaseValue; |
29 | |
30 | class TTypeFactory { |
31 | protected: |
32 | std::map<ompd_address_space_context_t *, std::map<const char *, TType>> |
33 | ttypes; |
34 | |
35 | public: |
36 | TTypeFactory() : ttypes() {} |
37 | TType &getType(ompd_address_space_context_t *context, const char *typName, |
38 | ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED); |
39 | }; |
40 | |
41 | static thread_local TTypeFactory tf = TTypeFactory(); |
42 | |
43 | class TType { |
44 | protected: |
45 | ompd_size_t typeSize; |
46 | std::map<const char *, ompd_size_t> fieldOffsets; |
47 | std::map<const char *, ompd_size_t> fieldSizes; |
48 | std::map<const char *, uint64_t> bitfieldMasks; |
49 | ompd_addr_t descSegment; |
50 | const char *typeName; |
51 | ompd_address_space_context_t *context; |
52 | bool isvoid; |
53 | TType(ompd_address_space_context_t *context, const char *typeName, |
54 | ompd_addr_t _segment = OMPD_SEGMENT_UNSPECIFIED); |
55 | |
56 | public: |
57 | TType(bool, ompd_addr_t _segment = OMPD_SEGMENT_UNSPECIFIED) |
58 | : descSegment(_segment), isvoid(true) {} |
59 | bool isVoid() const { return isvoid; } |
60 | ompd_rc_t getElementOffset(const char *fieldName, ompd_size_t *offset); |
61 | ompd_rc_t getElementSize(const char *fieldName, ompd_size_t *size); |
62 | ompd_rc_t getBitfieldMask(const char *fieldName, uint64_t *bitfieldmask); |
63 | ompd_rc_t getSize(ompd_size_t *size); |
64 | friend TValue; |
65 | friend TTypeFactory; |
66 | }; |
67 | |
68 | static TType nullType(true); |
69 | |
70 | /** |
71 | * class TError |
72 | * As TValue is designed to concatenate operations, we use TError |
73 | * to catch errors that might happen on each operation and provide |
74 | * the according error code and which operation raised the error. |
75 | */ |
76 | |
77 | class TError { |
78 | protected: |
79 | ompd_rc_t errorCode; |
80 | TError() : errorCode(ompd_rc_ok) {} |
81 | TError(const ompd_rc_t &error) : errorCode(error) {} |
82 | |
83 | public: |
84 | std::string toString() { |
85 | return std::string("TError messages not implemented yet" ); |
86 | } |
87 | friend TValue; |
88 | friend TBaseValue; |
89 | }; |
90 | |
91 | /** |
92 | * class TValue |
93 | * This class encapsules the access to target values by using OMPD |
94 | * callback functions. The member functions are designed to concatenate |
95 | * the operations that are needed to access values from structures |
96 | * e.g., _a[6]->_b._c would read like : |
97 | * TValue(ctx, |
98 | * "_a").cast("A",2).getArrayElement(6).access("_b").cast("B").access("_c") |
99 | */ |
100 | |
101 | class TValue { |
102 | protected: |
103 | TError errorState; |
104 | TType *type; |
105 | int pointerLevel; |
106 | ompd_address_space_context_t *context; |
107 | ompd_thread_context_t *tcontext; |
108 | ompd_address_t symbolAddr; |
109 | ompd_size_t fieldSize; |
110 | |
111 | public: |
112 | static const ompd_callbacks_t *callbacks; |
113 | static ompd_device_type_sizes_t type_sizes; |
114 | |
115 | TValue() : errorState(ompd_rc_error) {} |
116 | /** |
117 | * Create a target value object from symbol name |
118 | */ |
119 | TValue(ompd_address_space_context_t *_context, const char *_valueName, |
120 | ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED) |
121 | : TValue(_context, NULL, _valueName, segment) {} |
122 | |
123 | TValue(ompd_address_space_context_t *context, ompd_thread_context_t *tcontext, |
124 | const char *valueName, ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED); |
125 | /** |
126 | * Create a target value object from target value address |
127 | */ |
128 | TValue(ompd_address_space_context_t *_context, ompd_address_t _addr) |
129 | : TValue(_context, NULL, _addr) {} |
130 | TValue(ompd_address_space_context_t *context, ompd_thread_context_t *tcontext, |
131 | ompd_address_t addr); |
132 | /** |
133 | * Cast the target value object to some type of typeName |
134 | * |
135 | * This call modifies the object and returns a reference to the modified |
136 | * object |
137 | */ |
138 | TValue &cast(const char *typeName); |
139 | |
140 | /** |
141 | * Cast the target value object to some pointer of type typename |
142 | * pointerlevel gives the number of * |
143 | * e.g., char** would be: cast("char",2) |
144 | * |
145 | * This call modifies the object and returns a reference to the modified |
146 | * object |
147 | */ |
148 | TValue &cast(const char *typeName, int pointerLevel, |
149 | ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED); |
150 | |
151 | /** |
152 | * Get the target address of the target value |
153 | */ |
154 | ompd_rc_t getAddress(ompd_address_t *addr) const; |
155 | /** |
156 | * Get the raw memory copy of the target value |
157 | */ |
158 | ompd_rc_t getRawValue(void *buf, int count); |
159 | /** |
160 | * Fetch a string copy from the target. "this" represents the pointer |
161 | * that holds the value of a null terminated character string. "buf" |
162 | * points to the destination string to be allocated and copied to. |
163 | * Returns 'ompd_rc_error' to signify a truncated string or a target |
164 | * read error. |
165 | */ |
166 | ompd_rc_t getString(const char **buf); |
167 | /** |
168 | * Get a new target value object for the dereferenced target value |
169 | * reduces the pointer level, uses the target value as new target address, |
170 | * keeps the target type |
171 | */ |
172 | TValue dereference() const; |
173 | /** |
174 | * Cast to a base type |
175 | * Only values of base type may be read from target |
176 | */ |
177 | TBaseValue castBase(ompd_target_prim_types_t baseType) const; |
178 | /** |
179 | * Cast to a base type |
180 | * Get the size by fieldsize from runtime |
181 | */ |
182 | TBaseValue castBase() const; |
183 | /** |
184 | * Cast to a base type |
185 | * Get the size by name from the rtl |
186 | */ |
187 | TBaseValue castBase(const char *varName); |
188 | /** |
189 | * Resolve field access for structs/unions |
190 | * this supports both "->" and "." operator. |
191 | */ |
192 | TValue access(const char *fieldName) const; |
193 | /** |
194 | * Tests for a field bit in a bitfield |
195 | */ |
196 | ompd_rc_t check(const char *bitfieldName, ompd_word_t *isSet) const; |
197 | /** |
198 | * Get an array element |
199 | */ |
200 | TValue getArrayElement(int elemNumber) const; |
201 | /** |
202 | * Get an element of a pointer array |
203 | */ |
204 | TValue getPtrArrayElement(int elemNumber) const; |
205 | /** |
206 | * Did we raise some error yet? |
207 | */ |
208 | bool gotError() const { return errorState.errorCode != ompd_rc_ok; } |
209 | /** |
210 | * Get the error code |
211 | */ |
212 | ompd_rc_t getError() const { return errorState.errorCode; } |
213 | /** |
214 | * Did we raise some error yet? |
215 | */ |
216 | std::string getErrorMessage() { return errorState.toString(); } |
217 | }; |
218 | |
219 | class TBaseValue : public TValue { |
220 | protected: |
221 | ompd_size_t baseTypeSize = 0; |
222 | TBaseValue(const TValue &, ompd_target_prim_types_t baseType); |
223 | TBaseValue(const TValue &, ompd_size_t baseTypeSize); |
224 | |
225 | public: |
226 | ompd_rc_t getValue(void *buf, int count); |
227 | template <typename T> ompd_rc_t getValue(T &buf); |
228 | |
229 | friend TValue; |
230 | }; |
231 | |
232 | template <typename T> ompd_rc_t TBaseValue::getValue(T &buf) { |
233 | assert(sizeof(T) >= baseTypeSize); |
234 | ompd_rc_t ret = getValue(&buf, 1); |
235 | if (sizeof(T) > baseTypeSize) { |
236 | switch (baseTypeSize) { |
237 | case 1: |
238 | buf = (T) * ((int8_t *)&buf); |
239 | break; |
240 | case 2: |
241 | buf = (T) * ((int16_t *)&buf); |
242 | break; |
243 | case 4: |
244 | buf = (T) * ((int32_t *)&buf); |
245 | break; |
246 | case 8: |
247 | buf = (T) * ((int64_t *)&buf); |
248 | break; |
249 | } |
250 | } |
251 | return ret; |
252 | } |
253 | |
254 | #define EXTERN_C extern "C" |
255 | #else |
256 | #define EXTERN_C |
257 | #endif |
258 | |
259 | #endif /*SRC_TARGET_VALUE_H_*/ |
260 | |