|  | /* | 
|  | * TargetValue.h -- Access to target values using OMPD callbacks | 
|  | */ | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "omp-tools.h" | 
|  | #include "ompd-private.h" | 
|  | #include <stdlib.h> | 
|  |  | 
|  | #ifndef SRC_TARGET_VALUE_H_ | 
|  | #define SRC_TARGET_VALUE_H_ | 
|  |  | 
|  | #ifdef __cplusplus | 
|  |  | 
|  | #include <cassert> | 
|  | #include <map> | 
|  | #include <string> | 
|  |  | 
|  | class TType; | 
|  | class TValue; | 
|  | class TBaseValue; | 
|  |  | 
|  | class TTypeFactory { | 
|  | protected: | 
|  | std::map<ompd_address_space_context_t *, std::map<const char *, TType>> | 
|  | ttypes; | 
|  |  | 
|  | public: | 
|  | TTypeFactory() : ttypes() {} | 
|  | TType &getType(ompd_address_space_context_t *context, const char *typName, | 
|  | ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED); | 
|  | }; | 
|  |  | 
|  | static thread_local TTypeFactory tf = TTypeFactory(); | 
|  |  | 
|  | class TType { | 
|  | protected: | 
|  | ompd_size_t typeSize; | 
|  | std::map<const char *, ompd_size_t> fieldOffsets; | 
|  | std::map<const char *, ompd_size_t> fieldSizes; | 
|  | std::map<const char *, uint64_t> bitfieldMasks; | 
|  | ompd_addr_t descSegment; | 
|  | const char *typeName; | 
|  | ompd_address_space_context_t *context; | 
|  | bool isvoid; | 
|  | TType(ompd_address_space_context_t *context, const char *typeName, | 
|  | ompd_addr_t _segment = OMPD_SEGMENT_UNSPECIFIED); | 
|  |  | 
|  | public: | 
|  | TType(bool, ompd_addr_t _segment = OMPD_SEGMENT_UNSPECIFIED) | 
|  | : descSegment(_segment), isvoid(true) {} | 
|  | bool isVoid() const { return isvoid; } | 
|  | ompd_rc_t getElementOffset(const char *fieldName, ompd_size_t *offset); | 
|  | ompd_rc_t getElementSize(const char *fieldName, ompd_size_t *size); | 
|  | ompd_rc_t getBitfieldMask(const char *fieldName, uint64_t *bitfieldmask); | 
|  | ompd_rc_t getSize(ompd_size_t *size); | 
|  | friend TValue; | 
|  | friend TTypeFactory; | 
|  | }; | 
|  |  | 
|  | static TType nullType(true); | 
|  |  | 
|  | /** | 
|  | * class TError | 
|  | * As TValue is designed to concatenate operations, we use TError | 
|  | * to catch errors that might happen on each operation and provide | 
|  | * the according error code and which operation raised the error. | 
|  | */ | 
|  |  | 
|  | class TError { | 
|  | protected: | 
|  | ompd_rc_t errorCode; | 
|  | TError() : errorCode(ompd_rc_ok) {} | 
|  | TError(const ompd_rc_t &error) : errorCode(error) {} | 
|  |  | 
|  | public: | 
|  | std::string toString() { | 
|  | return std::string("TError messages not implemented yet"); | 
|  | } | 
|  | friend TValue; | 
|  | friend TBaseValue; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * class TValue | 
|  | * This class encapsules the access to target values by using OMPD | 
|  | * callback functions. The member functions are designed to concatenate | 
|  | * the operations that are needed to access values from structures | 
|  | * e.g., _a[6]->_b._c would read like : | 
|  | * TValue(ctx, | 
|  | * "_a").cast("A",2).getArrayElement(6).access("_b").cast("B").access("_c") | 
|  | */ | 
|  |  | 
|  | class TValue { | 
|  | protected: | 
|  | TError errorState; | 
|  | TType *type; | 
|  | int pointerLevel; | 
|  | ompd_address_space_context_t *context; | 
|  | ompd_thread_context_t *tcontext; | 
|  | ompd_address_t symbolAddr; | 
|  | ompd_size_t fieldSize; | 
|  |  | 
|  | public: | 
|  | static const ompd_callbacks_t *callbacks; | 
|  | static ompd_device_type_sizes_t type_sizes; | 
|  |  | 
|  | TValue() : errorState(ompd_rc_error) {} | 
|  | /** | 
|  | * Create a target value object from symbol name | 
|  | */ | 
|  | TValue(ompd_address_space_context_t *_context, const char *_valueName, | 
|  | ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED) | 
|  | : TValue(_context, NULL, _valueName, segment) {} | 
|  |  | 
|  | TValue(ompd_address_space_context_t *context, ompd_thread_context_t *tcontext, | 
|  | const char *valueName, ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED); | 
|  | /** | 
|  | * Create a target value object from target value address | 
|  | */ | 
|  | TValue(ompd_address_space_context_t *_context, ompd_address_t _addr) | 
|  | : TValue(_context, NULL, _addr) {} | 
|  | TValue(ompd_address_space_context_t *context, ompd_thread_context_t *tcontext, | 
|  | ompd_address_t addr); | 
|  | /** | 
|  | * Cast the target value object to some type of typeName | 
|  | * | 
|  | * This call modifies the object and returns a reference to the modified | 
|  | * object | 
|  | */ | 
|  | TValue &cast(const char *typeName); | 
|  |  | 
|  | /** | 
|  | * Cast the target value object to some pointer of type typename | 
|  | * pointerlevel gives the number of * | 
|  | * e.g., char** would be: cast("char",2) | 
|  | * | 
|  | * This call modifies the object and returns a reference to the modified | 
|  | * object | 
|  | */ | 
|  | TValue &cast(const char *typeName, int pointerLevel, | 
|  | ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED); | 
|  |  | 
|  | /** | 
|  | * Get the target address of the target value | 
|  | */ | 
|  | ompd_rc_t getAddress(ompd_address_t *addr) const; | 
|  | /** | 
|  | * Get the raw memory copy of the target value | 
|  | */ | 
|  | ompd_rc_t getRawValue(void *buf, int count); | 
|  | /** | 
|  | * Fetch a string copy from the target. "this" represents the pointer | 
|  | * that holds the value of a null terminated character string. "buf" | 
|  | * points to the destination string to be allocated and copied to. | 
|  | * Returns 'ompd_rc_error' to signify a truncated string or a target | 
|  | * read error. | 
|  | */ | 
|  | ompd_rc_t getString(const char **buf); | 
|  | /** | 
|  | * Get a new target value object for the dereferenced target value | 
|  | * reduces the pointer level, uses the target value as new target address, | 
|  | * keeps the target type | 
|  | */ | 
|  | TValue dereference() const; | 
|  | /** | 
|  | * Cast to a base type | 
|  | * Only values of base type may be read from target | 
|  | */ | 
|  | TBaseValue castBase(ompd_target_prim_types_t baseType) const; | 
|  | /** | 
|  | * Cast to a base type | 
|  | * Get the size by fieldsize from runtime | 
|  | */ | 
|  | TBaseValue castBase() const; | 
|  | /** | 
|  | * Cast to a base type | 
|  | * Get the size by name from the rtl | 
|  | */ | 
|  | TBaseValue castBase(const char *varName); | 
|  | /** | 
|  | * Resolve field access for structs/unions | 
|  | * this supports both "->" and "." operator. | 
|  | */ | 
|  | TValue access(const char *fieldName) const; | 
|  | /** | 
|  | * Tests for a field bit in a bitfield | 
|  | */ | 
|  | ompd_rc_t check(const char *bitfieldName, ompd_word_t *isSet) const; | 
|  | /** | 
|  | * Get an array element | 
|  | */ | 
|  | TValue getArrayElement(int elemNumber) const; | 
|  | /** | 
|  | * Get an element of a pointer array | 
|  | */ | 
|  | TValue getPtrArrayElement(int elemNumber) const; | 
|  | /** | 
|  | * Did we raise some error yet? | 
|  | */ | 
|  | bool gotError() const { return errorState.errorCode != ompd_rc_ok; } | 
|  | /** | 
|  | * Get the error code | 
|  | */ | 
|  | ompd_rc_t getError() const { return errorState.errorCode; } | 
|  | /** | 
|  | * Did we raise some error yet? | 
|  | */ | 
|  | std::string getErrorMessage() { return errorState.toString(); } | 
|  | }; | 
|  |  | 
|  | class TBaseValue : public TValue { | 
|  | protected: | 
|  | ompd_size_t baseTypeSize = 0; | 
|  | TBaseValue(const TValue &, ompd_target_prim_types_t baseType); | 
|  | TBaseValue(const TValue &, ompd_size_t baseTypeSize); | 
|  |  | 
|  | public: | 
|  | ompd_rc_t getValue(void *buf, int count); | 
|  | template <typename T> ompd_rc_t getValue(T &buf); | 
|  |  | 
|  | friend TValue; | 
|  | }; | 
|  |  | 
|  | template <typename T> ompd_rc_t TBaseValue::getValue(T &buf) { | 
|  | assert(sizeof(T) >= baseTypeSize); | 
|  | ompd_rc_t ret = getValue(&buf, 1); | 
|  | if (sizeof(T) > baseTypeSize) { | 
|  | switch (baseTypeSize) { | 
|  | case 1: | 
|  | buf = (T) * ((int8_t *)&buf); | 
|  | break; | 
|  | case 2: | 
|  | buf = (T) * ((int16_t *)&buf); | 
|  | break; | 
|  | case 4: | 
|  | buf = (T) * ((int32_t *)&buf); | 
|  | break; | 
|  | case 8: | 
|  | buf = (T) * ((int64_t *)&buf); | 
|  | break; | 
|  | } | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | #define EXTERN_C extern "C" | 
|  | #else | 
|  | #define EXTERN_C | 
|  | #endif | 
|  |  | 
|  | #endif /*SRC_TARGET_VALUE_H_*/ |