aboutsummaryrefslogtreecommitdiff
path: root/profiling/common/src/SwTrace.cpp
blob: 5860d8cf06655615626519c33151fcf05f474840 (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
//
// 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)
{
    ARM_PIPE_ASSERT(packetBuffer);

    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