aboutsummaryrefslogtreecommitdiff
path: root/profiling/common/include/SwTrace.hpp
blob: 5abc59b1a81ccdfe1a68c52a858403bdbc696e46 (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
132
133
134
135
136
137
138
139
//
// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//

#pragma once

#include "NumericCast.hpp"

#include <algorithm>
#include <cstring>
#include <string>
#include <vector>

namespace arm
{

namespace pipe
{

struct SwTraceHeader
{
    uint8_t m_StreamVersion;
    uint8_t m_PointerBytes;
    uint8_t m_ThreadIdBytes;
};

struct SwTraceMessage
{
    uint32_t m_Id;
    std::string m_Name;
    std::string m_UiName;
    std::vector<char> m_ArgTypes;
    std::vector<std::string> m_ArgNames;
};

struct SwTraceCharPolicy
{
    static bool IsValidChar(unsigned char c)
    {
        // Check that the given character has ASCII 7-bit encoding
        return c < 128;
    }
};

struct SwTraceNameCharPolicy
{
    static bool IsValidChar(unsigned char c)
    {
        // Check that the given character has ASCII 7-bit encoding, alpha-numeric and underscore only
        return c < 128 && (std::isalnum(c) || c == '_');
    }
};

struct SwTraceTypeCharPolicy
{
    static bool IsValidChar(unsigned char c)
    {
        // Check that the given character is among the allowed ones
        switch (c)
        {
        case '@':
        case 't':
        case 'i':
        case 'I':
        case 'l':
        case 'L':
        case 'F':
        case 'p':
        case 's':
            return true; // Valid char
        default:
            return false; // Invalid char
        }
    }
};

template <typename SwTracePolicy>
bool IsValidSwTraceString(const std::string& s)
{
    // Check that all the characters in the given string conform to the given policy
    return std::all_of(s.begin(), s.end(), [](unsigned char c) { return SwTracePolicy::IsValidChar(c); });
}

template <typename SwTracePolicy>
bool StringToSwTraceString(const std::string& s, std::vector<uint32_t>& outputBuffer)
{
    // Converts the given string to an SWTrace "string" (i.e. a string of "chars"), and writes it into
    // the given buffer including the null-terminator. It also pads it to the next uint32_t if necessary

    // Clear the output buffer
    outputBuffer.clear();

    // Check that the given string is a valid SWTrace "string" (i.e. a string of "chars")
    if (!IsValidSwTraceString<SwTracePolicy>(s))
    {
        return false;
    }

    // Prepare the output buffer
    size_t s_size        = s.size() + 1;    // The size of the string (in chars) plus the null-terminator
    size_t uint32_t_size = sizeof(uint32_t);
    // Output buffer size = StringLength (32 bit) + amount of complete 32bit words that fit into the string
    //                      + an additional 32bit word if there are remaining chars to complete the string
    //                      (The rest of the 32bit word is then filled with the NULL terminator)
    size_t outBufferSize = 1 + (s_size / uint32_t_size) + (s_size % uint32_t_size != 0 ? 1 : 0);
    outputBuffer.resize(outBufferSize, '\0');

    // Write the SWTrace string to the output buffer
    outputBuffer[0] = numeric_cast<uint32_t>(s_size);
    std::memcpy(outputBuffer.data() + 1, s.data(), s_size);

    return true;
}

template <typename SwTracePolicy,
          typename SwTraceBuffer = std::vector<uint32_t>>
bool ConvertDirectoryComponent(const std::string& directoryComponent, SwTraceBuffer& swTraceBuffer)
{
    // Convert the directory component using the given policy
    SwTraceBuffer tempSwTraceBuffer;
    bool result = StringToSwTraceString<SwTracePolicy>(directoryComponent, tempSwTraceBuffer);
    if (!result)
    {
        return false;
    }

    swTraceBuffer.insert(swTraceBuffer.end(), tempSwTraceBuffer.begin(), tempSwTraceBuffer.end());

    return true;
}

uint32_t CalculateSizeOfPaddedSwString(const std::string& str);

SwTraceMessage ReadSwTraceMessage(const unsigned char*, unsigned int&, const unsigned int& packetLength);

} // namespace pipe

} // namespace arm