blob: 5abc59b1a81ccdfe1a68c52a858403bdbc696e46 [file] [log] [blame]
Jim Flynnbbfe6032020-07-20 16:57:44 +01001//
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
15namespace arm
16{
17
18namespace pipe
19{
20
21struct SwTraceHeader
22{
23 uint8_t m_StreamVersion;
24 uint8_t m_PointerBytes;
25 uint8_t m_ThreadIdBytes;
26};
27
28struct 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
37struct SwTraceCharPolicy
38{
39 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
46struct SwTraceNameCharPolicy
47{
48 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
55struct SwTraceTypeCharPolicy
56{
57 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
78template <typename SwTracePolicy>
79bool 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
85template <typename SwTracePolicy>
86bool 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
116template <typename SwTracePolicy,
117 typename SwTraceBuffer = std::vector<uint32_t>>
118bool 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
133uint32_t CalculateSizeOfPaddedSwString(const std::string& str);
134
135SwTraceMessage ReadSwTraceMessage(const unsigned char*, unsigned int&, const unsigned int& packetLength);
136
137} // namespace pipe
138
139} // namespace arm