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