aboutsummaryrefslogtreecommitdiff
path: root/profiling/common/src/SwTrace.cpp
blob: c25baadfec0119219c8481f722e65599b35cb125 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//
// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include <common/include/CommonProfilingUtils.hpp>
#include <common/include/NumericCast.hpp>
#include <common/include/ProfilingException.hpp>
#include <common/include/SwTrace.hpp>

#include <sstream>

namespace arm
{

namespace pipe
{

// Calculate the actual length an SwString will be including the terminating null character
// padding to bring it to the next uint32_t boundary but minus the leading uint32_t encoding
// the size to allow the offset to be correctly updated when decoding a binary packet.
uint32_t CalculateSizeOfPaddedSwString(const std::string& str)
{
    std::vector<uint32_t> swTraceString;
    StringToSwTraceString<SwTraceCharPolicy>(str, swTraceString);
    unsigned int uint32_t_size = sizeof(uint32_t);
    uint32_t size = (numeric_cast<uint32_t>(swTraceString.size()) - 1) * uint32_t_size;
    return size;
}

// Read TimelineMessageDirectoryPacket from given IPacketBuffer and offset
SwTraceMessage ReadSwTraceMessage(const unsigned char* packetBuffer,
                                  unsigned int& offset,
                                  const unsigned int& packetLength)
{
    if (packetBuffer == nullptr)
    {
        throw ProfilingException("SwTrace.cpp: Attempting to read a null buffer");
    }

    unsigned int uint32_t_size = sizeof(uint32_t);

    SwTraceMessage swTraceMessage;

    // Read the decl_id
    uint32_t readDeclId = ReadUint32(packetBuffer, offset);
    swTraceMessage.m_Id = readDeclId;

    // SWTrace "namestring" format
    // length of the string (first 4 bytes) + string + null terminator

    // Check the decl_name
    offset += uint32_t_size;
    uint32_t swTraceDeclNameLength = ReadUint32(packetBuffer, offset);

    if (swTraceDeclNameLength == 0 || swTraceDeclNameLength > packetLength)
    {
        throw arm::pipe::ProfilingException("Error swTraceDeclNameLength is an invalid size", LOCATION());
    }

    offset += uint32_t_size;
    std::vector<unsigned char> swTraceStringBuffer(swTraceDeclNameLength - 1);
    std::memcpy(swTraceStringBuffer.data(),
                packetBuffer + offset, swTraceStringBuffer.size());

    swTraceMessage.m_Name.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // name

    // Check the ui_name
    offset += CalculateSizeOfPaddedSwString(swTraceMessage.m_Name);
    uint32_t swTraceUINameLength = ReadUint32(packetBuffer, offset);

    if (swTraceUINameLength == 0 || swTraceUINameLength > packetLength)
    {
        throw arm::pipe::ProfilingException("Error swTraceUINameLength is an invalid size", LOCATION());
    }

    offset += uint32_t_size;
    swTraceStringBuffer.resize(swTraceUINameLength - 1);
    std::memcpy(swTraceStringBuffer.data(),
                packetBuffer  + offset, swTraceStringBuffer.size());

    swTraceMessage.m_UiName.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // ui_name

    // Check arg_types
    offset += CalculateSizeOfPaddedSwString(swTraceMessage.m_UiName);
    uint32_t swTraceArgTypesLength = ReadUint32(packetBuffer, offset);

    if (swTraceArgTypesLength == 0 || swTraceArgTypesLength > packetLength)
    {
        throw arm::pipe::ProfilingException("Error swTraceArgTypesLength is an invalid size", LOCATION());
    }

    offset += uint32_t_size;
    swTraceStringBuffer.resize(swTraceArgTypesLength - 1);
    std::memcpy(swTraceStringBuffer.data(),
                packetBuffer  + offset, swTraceStringBuffer.size());

    swTraceMessage.m_ArgTypes.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // arg_types

    std::string swTraceString(swTraceStringBuffer.begin(), swTraceStringBuffer.end());

    // Check arg_names
    offset += CalculateSizeOfPaddedSwString(swTraceString);
    uint32_t swTraceArgNamesLength = ReadUint32(packetBuffer, offset);

    if (swTraceArgNamesLength == 0 || swTraceArgNamesLength > packetLength)
    {
        throw arm::pipe::ProfilingException("Error swTraceArgNamesLength is an invalid size", LOCATION());
    }

    offset += uint32_t_size;
    swTraceStringBuffer.resize(swTraceArgNamesLength - 1);
    std::memcpy(swTraceStringBuffer.data(),
                packetBuffer  + offset, swTraceStringBuffer.size());

    swTraceString.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end());
    std::stringstream stringStream(swTraceString);
    std::string argName;
    while (std::getline(stringStream, argName, ','))
    {
        swTraceMessage.m_ArgNames.push_back(argName);
    }

    offset += CalculateSizeOfPaddedSwString(swTraceString);

    return swTraceMessage;
}

} // namespace pipe

} // namespace arm