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