1 /* 2 * Copyright (C) 2018-2021 Intel Corporation 3 * 4 * SPDX-License-Identifier: MIT 5 * 6 */ 7 8 #pragma once 9 10 #include "shared/source/helpers/aligned_memory.h" 11 #include "shared/source/helpers/constants.h" 12 #include "shared/source/os_interface/print.h" 13 14 #include <algorithm> 15 #include <cctype> 16 #include <cstdint> 17 #include <functional> 18 #include <string> 19 #include <unordered_map> 20 21 extern int memcpy_s(void *dst, size_t destSize, const void *src, size_t count); 22 23 namespace NEO { 24 25 using StringMap = std::unordered_map<uint32_t, std::string>; 26 27 enum class PRINTF_DATA_TYPE : int { 28 INVALID, 29 BYTE, 30 SHORT, 31 INT, 32 FLOAT, 33 STRING, 34 LONG, 35 POINTER, 36 DOUBLE, 37 VECTOR_BYTE, 38 VECTOR_SHORT, 39 VECTOR_INT, 40 VECTOR_LONG, 41 VECTOR_FLOAT, 42 VECTOR_DOUBLE 43 }; 44 45 class PrintFormatter { 46 public: 47 PrintFormatter(const uint8_t *printfOutputBuffer, uint32_t printfOutputBufferMaxSize, 48 bool using32BitPointers, const StringMap *stringLiteralMap = nullptr); 49 void printKernelOutput(const std::function<void(char *)> &print = [](char *str) { printToSTDOUT(str); }); 50 51 constexpr static size_t maxSinglePrintStringLength = 16 * MemoryConstants::kiloByte; 52 53 protected: 54 const char *queryPrintfString(uint32_t index) const; 55 void printString(const char *formatString, const std::function<void(char *)> &print); 56 size_t printToken(char *output, size_t size, const char *formatString); 57 size_t printStringToken(char *output, size_t size, const char *formatString); 58 size_t printPointerToken(char *output, size_t size, const char *formatString); 59 60 char escapeChar(char escape); 61 bool isConversionSpecifier(char c); 62 void stripVectorFormat(const char *format, char *stripped); 63 void stripVectorTypeConversion(char *format); 64 65 template <class T> read(T * value)66 bool read(T *value) { 67 if (currentOffset + sizeof(T) <= printfOutputBufferSize) { 68 auto srcPtr = reinterpret_cast<const T *>(printfOutputBuffer + currentOffset); 69 70 if (isAligned(srcPtr)) { 71 *value = *srcPtr; 72 } else { 73 memcpy_s(value, printfOutputBufferSize - currentOffset, srcPtr, sizeof(T)); 74 } 75 currentOffset += sizeof(T); 76 return true; 77 } else { 78 return false; 79 } 80 } 81 82 template <class T> typedPrintToken(char * output,size_t size,const char * formatString)83 size_t typedPrintToken(char *output, size_t size, const char *formatString) { 84 T value = {0}; 85 read(&value); 86 return simple_sprintf(output, size, formatString, value); 87 } 88 89 template <class T> typedPrintVectorToken(char * output,size_t size,const char * formatString)90 size_t typedPrintVectorToken(char *output, size_t size, const char *formatString) { 91 T value = {0}; 92 int valueCount = 0; 93 read(&valueCount); 94 95 size_t charactersPrinted = 0; 96 char strippedFormat[1024]; 97 98 stripVectorFormat(formatString, strippedFormat); 99 stripVectorTypeConversion(strippedFormat); 100 101 for (int i = 0; i < valueCount; i++) { 102 read(&value); 103 charactersPrinted += simple_sprintf(output + charactersPrinted, size - charactersPrinted, strippedFormat, value); 104 if (i < valueCount - 1) { 105 charactersPrinted += simple_sprintf(output + charactersPrinted, size - charactersPrinted, "%c", ','); 106 } 107 } 108 109 if (sizeof(T) < 4) { 110 currentOffset += (4 - sizeof(T)) * valueCount; 111 } 112 113 return charactersPrinted; 114 } 115 116 std::unique_ptr<char[]> output; 117 118 const uint8_t *printfOutputBuffer = nullptr; // buffer extracted from the kernel, contains values to be printed 119 uint32_t printfOutputBufferSize = 0; // size of the data contained in the buffer 120 121 bool using32BitPointers = false; 122 const bool usesStringMap; 123 const StringMap *stringLiteralMap; 124 125 uint32_t currentOffset = 0; // current position in currently parsed buffer 126 }; 127 }; // namespace NEO 128