1 //
2 // Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #pragma once
7
8 #include "NumericCast.hpp"
9
10 #include <algorithm>
11 #include <cstring>
12 #include <string>
13 #include <vector>
14
15 namespace arm
16 {
17
18 namespace pipe
19 {
20
21 struct SwTraceHeader
22 {
23 uint8_t m_StreamVersion;
24 uint8_t m_PointerBytes;
25 uint8_t m_ThreadIdBytes;
26 };
27
28 struct SwTraceMessage
29 {
30 uint32_t m_Id;
31 std::string m_Name;
32 std::string m_UiName;
33 std::vector<char> m_ArgTypes;
34 std::vector<std::string> m_ArgNames;
35 };
36
37 struct SwTraceCharPolicy
38 {
IsValidChararm::pipe::SwTraceCharPolicy39 static bool IsValidChar(unsigned char c)
40 {
41 // Check that the given character has ASCII 7-bit encoding
42 return c < 128;
43 }
44 };
45
46 struct SwTraceNameCharPolicy
47 {
IsValidChararm::pipe::SwTraceNameCharPolicy48 static bool IsValidChar(unsigned char c)
49 {
50 // Check that the given character has ASCII 7-bit encoding, alpha-numeric and underscore only
51 return c < 128 && (std::isalnum(c) || c == '_');
52 }
53 };
54
55 struct SwTraceTypeCharPolicy
56 {
IsValidChararm::pipe::SwTraceTypeCharPolicy57 static bool IsValidChar(unsigned char c)
58 {
59 // Check that the given character is among the allowed ones
60 switch (c)
61 {
62 case '@':
63 case 't':
64 case 'i':
65 case 'I':
66 case 'l':
67 case 'L':
68 case 'F':
69 case 'p':
70 case 's':
71 return true; // Valid char
72 default:
73 return false; // Invalid char
74 }
75 }
76 };
77
78 template <typename SwTracePolicy>
IsValidSwTraceString(const std::string & s)79 bool IsValidSwTraceString(const std::string& s)
80 {
81 // Check that all the characters in the given string conform to the given policy
82 return std::all_of(s.begin(), s.end(), [](unsigned char c) { return SwTracePolicy::IsValidChar(c); });
83 }
84
85 template <typename SwTracePolicy>
StringToSwTraceString(const std::string & s,std::vector<uint32_t> & outputBuffer)86 bool StringToSwTraceString(const std::string& s, std::vector<uint32_t>& outputBuffer)
87 {
88 // Converts the given string to an SWTrace "string" (i.e. a string of "chars"), and writes it into
89 // the given buffer including the null-terminator. It also pads it to the next uint32_t if necessary
90
91 // Clear the output buffer
92 outputBuffer.clear();
93
94 // Check that the given string is a valid SWTrace "string" (i.e. a string of "chars")
95 if (!IsValidSwTraceString<SwTracePolicy>(s))
96 {
97 return false;
98 }
99
100 // Prepare the output buffer
101 size_t s_size = s.size() + 1; // The size of the string (in chars) plus the null-terminator
102 size_t uint32_t_size = sizeof(uint32_t);
103 // Output buffer size = StringLength (32 bit) + amount of complete 32bit words that fit into the string
104 // + an additional 32bit word if there are remaining chars to complete the string
105 // (The rest of the 32bit word is then filled with the NULL terminator)
106 size_t outBufferSize = 1 + (s_size / uint32_t_size) + (s_size % uint32_t_size != 0 ? 1 : 0);
107 outputBuffer.resize(outBufferSize, '\0');
108
109 // Write the SWTrace string to the output buffer
110 outputBuffer[0] = numeric_cast<uint32_t>(s_size);
111 std::memcpy(outputBuffer.data() + 1, s.data(), s_size);
112
113 return true;
114 }
115
116 template <typename SwTracePolicy,
117 typename SwTraceBuffer = std::vector<uint32_t>>
ConvertDirectoryComponent(const std::string & directoryComponent,SwTraceBuffer & swTraceBuffer)118 bool ConvertDirectoryComponent(const std::string& directoryComponent, SwTraceBuffer& swTraceBuffer)
119 {
120 // Convert the directory component using the given policy
121 SwTraceBuffer tempSwTraceBuffer;
122 bool result = StringToSwTraceString<SwTracePolicy>(directoryComponent, tempSwTraceBuffer);
123 if (!result)
124 {
125 return false;
126 }
127
128 swTraceBuffer.insert(swTraceBuffer.end(), tempSwTraceBuffer.begin(), tempSwTraceBuffer.end());
129
130 return true;
131 }
132
133 uint32_t CalculateSizeOfPaddedSwString(const std::string& str);
134
135 SwTraceMessage ReadSwTraceMessage(const unsigned char*, unsigned int&, const unsigned int& packetLength);
136
137 } // namespace pipe
138
139 } // namespace arm
140