1 //
2 // Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include <common/include/CommonProfilingUtils.hpp>
7 #include <common/include/NumericCast.hpp>
8 #include <common/include/ProfilingException.hpp>
9 #include <common/include/SwTrace.hpp>
10
11 #include <sstream>
12
13 namespace arm
14 {
15
16 namespace pipe
17 {
18
19 // Calculate the actual length an SwString will be including the terminating null character
20 // padding to bring it to the next uint32_t boundary but minus the leading uint32_t encoding
21 // the size to allow the offset to be correctly updated when decoding a binary packet.
CalculateSizeOfPaddedSwString(const std::string & str)22 uint32_t CalculateSizeOfPaddedSwString(const std::string& str)
23 {
24 std::vector<uint32_t> swTraceString;
25 StringToSwTraceString<SwTraceCharPolicy>(str, swTraceString);
26 unsigned int uint32_t_size = sizeof(uint32_t);
27 uint32_t size = (numeric_cast<uint32_t>(swTraceString.size()) - 1) * uint32_t_size;
28 return size;
29 }
30
31 // Read TimelineMessageDirectoryPacket from given IPacketBuffer and offset
ReadSwTraceMessage(const unsigned char * packetBuffer,unsigned int & offset,const unsigned int & packetLength)32 SwTraceMessage ReadSwTraceMessage(const unsigned char* packetBuffer,
33 unsigned int& offset,
34 const unsigned int& packetLength)
35 {
36 ARM_PIPE_ASSERT(packetBuffer);
37
38 unsigned int uint32_t_size = sizeof(uint32_t);
39
40 SwTraceMessage swTraceMessage;
41
42 // Read the decl_id
43 uint32_t readDeclId = ReadUint32(packetBuffer, offset);
44 swTraceMessage.m_Id = readDeclId;
45
46 // SWTrace "namestring" format
47 // length of the string (first 4 bytes) + string + null terminator
48
49 // Check the decl_name
50 offset += uint32_t_size;
51 uint32_t swTraceDeclNameLength = ReadUint32(packetBuffer, offset);
52
53 if (swTraceDeclNameLength == 0 || swTraceDeclNameLength > packetLength)
54 {
55 throw arm::pipe::ProfilingException("Error swTraceDeclNameLength is an invalid size", LOCATION());
56 }
57
58 offset += uint32_t_size;
59 std::vector<unsigned char> swTraceStringBuffer(swTraceDeclNameLength - 1);
60 std::memcpy(swTraceStringBuffer.data(),
61 packetBuffer + offset, swTraceStringBuffer.size());
62
63 swTraceMessage.m_Name.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // name
64
65 // Check the ui_name
66 offset += CalculateSizeOfPaddedSwString(swTraceMessage.m_Name);
67 uint32_t swTraceUINameLength = ReadUint32(packetBuffer, offset);
68
69 if (swTraceUINameLength == 0 || swTraceUINameLength > packetLength)
70 {
71 throw arm::pipe::ProfilingException("Error swTraceUINameLength is an invalid size", LOCATION());
72 }
73
74 offset += uint32_t_size;
75 swTraceStringBuffer.resize(swTraceUINameLength - 1);
76 std::memcpy(swTraceStringBuffer.data(),
77 packetBuffer + offset, swTraceStringBuffer.size());
78
79 swTraceMessage.m_UiName.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // ui_name
80
81 // Check arg_types
82 offset += CalculateSizeOfPaddedSwString(swTraceMessage.m_UiName);
83 uint32_t swTraceArgTypesLength = ReadUint32(packetBuffer, offset);
84
85 if (swTraceArgTypesLength == 0 || swTraceArgTypesLength > packetLength)
86 {
87 throw arm::pipe::ProfilingException("Error swTraceArgTypesLength is an invalid size", LOCATION());
88 }
89
90 offset += uint32_t_size;
91 swTraceStringBuffer.resize(swTraceArgTypesLength - 1);
92 std::memcpy(swTraceStringBuffer.data(),
93 packetBuffer + offset, swTraceStringBuffer.size());
94
95 swTraceMessage.m_ArgTypes.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // arg_types
96
97 std::string swTraceString(swTraceStringBuffer.begin(), swTraceStringBuffer.end());
98
99 // Check arg_names
100 offset += CalculateSizeOfPaddedSwString(swTraceString);
101 uint32_t swTraceArgNamesLength = ReadUint32(packetBuffer, offset);
102
103 if (swTraceArgNamesLength == 0 || swTraceArgNamesLength > packetLength)
104 {
105 throw arm::pipe::ProfilingException("Error swTraceArgNamesLength is an invalid size", LOCATION());
106 }
107
108 offset += uint32_t_size;
109 swTraceStringBuffer.resize(swTraceArgNamesLength - 1);
110 std::memcpy(swTraceStringBuffer.data(),
111 packetBuffer + offset, swTraceStringBuffer.size());
112
113 swTraceString.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end());
114 std::stringstream stringStream(swTraceString);
115 std::string argName;
116 while (std::getline(stringStream, argName, ','))
117 {
118 swTraceMessage.m_ArgNames.push_back(argName);
119 }
120
121 offset += CalculateSizeOfPaddedSwString(swTraceString);
122
123 return swTraceMessage;
124 }
125
126 } // namespace pipe
127
128 } // namespace arm
129