Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
etw.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "etw.h"
5#include "provider.h"
6#include "helpers.h"
7#include "qtheaders.h"
8
9#include <qfile.h>
10#include <qfileinfo.h>
11#include <qtextstream.h>
12#include <quuid.h>
13
14using namespace Qt::StringLiterals;
15
16static inline QString providerVar(const QString &providerName)
17{
18 return providerName + "_provider"_L1;
19}
20
22{
23 const QString &name = field.name;
24
25 if (field.arrayLen > 0) {
26 for (int i = 0; i < field.arrayLen; i++) {
27 stream << "TraceLoggingValue(" << name << "[" << i << "], \"" << name << "[" << i << "]\")";
28 if (i + 1 < field.arrayLen)
29 stream << ",\n ";
30 }
31 return;
32 }
33
34 switch (field.backendType) {
36 stream << "TraceLoggingCountedWideString(reinterpret_cast<LPCWSTR>("
37 << name << ".utf16()), static_cast<ULONG>(" << name << ".size()), \""
38 << name << "\")";
39 return;
41 stream << "TraceLoggingBinary(" << name << ".constData(), "
42 << name << ".size(), \"" << name << "\")";
43 return;
45 stream << "TraceLoggingValue(" << name << ".toEncoded().constData(), \"" << name << "\")";
46 return;
49 stream << "TraceLoggingValue(" << name << ".x(), \"x\"), "
50 << "TraceLoggingValue(" << name << ".y(), \"y\"), "
51 << "TraceLoggingValue(" << name << ".width(), \"width\"), "
52 << "TraceLoggingValue(" << name << ".height(), \"height\")";
53 return;
56 stream << "TraceLoggingValue(" << name << ".width(), \"width\"), "
57 << "TraceLoggingValue(" << name << ".height(), \"height\")";
58 return;
60 stream << "TraceLoggingPointer(" << name << ", \"" << name << "\")";
61 return;
63 // Write down the previously stringified data (like we do for QString).
64 // The string is already created in writeWrapper().
65 // Variable name is name##Str.
66 stream << "TraceLoggingCountedWideString(reinterpret_cast<LPCWSTR>(" << name
67 << "Str.utf16()), static_cast<ULONG>(" << name << "Str.size()), \"" << name << "\")";
68 return;
71 stream << "TraceLoggingString(trace_convert_" << typeToTypeName(field.paramType) << "(" << name << ").toUtf8().constData(), \"" << name << "\")";
72 return;
73 default:
74 break;
75 }
76
77 stream << "TraceLoggingValue(" << name << ", \"" << name << "\")";
78}
79
80static QString createGuid(const QUuid &uuid)
81{
82 QString guid;
83
84 QTextStream stream(&guid);
85
87
88 stream << "("
89 << "0x" << uuid.data1 << ", "
90 << "0x" << uuid.data2 << ", "
91 << "0x" << uuid.data3 << ", "
92 << "0x" << uuid.data4[0] << ", "
93 << "0x" << uuid.data4[1] << ", "
94 << "0x" << uuid.data4[2] << ", "
95 << "0x" << uuid.data4[3] << ", "
96 << "0x" << uuid.data4[4] << ", "
97 << "0x" << uuid.data4[5] << ", "
98 << "0x" << uuid.data4[6] << ", "
99 << "0x" << uuid.data4[7]
100 << ")";
101
102 return guid;
103}
104
105static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider)
106{
108 QUuid uuid = QUuid::createUuidV5(QUuid(), provider.name.toLocal8Bit());
109
110 const QString providerV = providerVar(provider.name);
111 const QString guard = includeGuard(fileName);
112 const QString guid = createGuid(uuid);
113 const QString guidString = uuid.toString();
114
115 stream << "#ifndef " << guard << "\n"
116 << "#define " << guard << "\n"
117 << "\n"
118 << "#include <qt_windows.h>\n"
119 << "#include <TraceLoggingProvider.h>\n"
120 << "\n";
121
122 /* TraceLogging API macros cannot deal with UTF8
123 * source files, so we work around it like this
124 */
125 stream << "#undef _TlgPragmaUtf8Begin\n"
126 "#undef _TlgPragmaUtf8End\n"
127 "#define _TlgPragmaUtf8Begin\n"
128 "#define _TlgPragmaUtf8End\n";
129
130 stream << "\n";
131 stream << qtHeaders();
132 stream << "\n";
133
134 if (!provider.prefixText.isEmpty())
135 stream << provider.prefixText.join(u'\n') << "\n\n";
136
137 stream << "#ifdef TRACEPOINT_DEFINE\n"
138 << "/* " << guidString << " */\n"
139 << "TRACELOGGING_DEFINE_PROVIDER(" << providerV << ", \""
140 << provider.name <<"\", " << guid << ");\n\n";
141
142 stream << "static inline void registerProvider()\n"
143 << "{\n"
144 << " TraceLoggingRegister(" << providerV << ");\n"
145 << "}\n\n";
146
147 stream << "static inline void unregisterProvider()\n"
148 << "{\n"
149 << " TraceLoggingUnregister(" << providerV << ");\n"
150 << "}\n";
151
152 stream << "Q_CONSTRUCTOR_FUNCTION(registerProvider)\n"
153 << "Q_DESTRUCTOR_FUNCTION(unregisterProvider)\n\n";
154
155 stream << "#else\n"
156 << "TRACELOGGING_DECLARE_PROVIDER(" << providerV << ");\n"
157 << "#endif // TRACEPOINT_DEFINE\n\n";
158}
159
161{
162 stream << "\n#endif // " << includeGuard(fileName) << "\n"
163 << "#include <private/qtrace_p.h>\n";
164}
165
166static void writeWrapper(QTextStream &stream, const Provider &provider, const Tracepoint &tracepoint,
167 const QString &providerName)
168{
169 const QString argList = formatFunctionSignature(tracepoint.args);
170 const QString paramList = formatParameterList(provider, tracepoint.args, tracepoint.fields, ETW);
171 const QString &name = tracepoint.name;
172 const QString includeGuard = QStringLiteral("TP_%1_%2").arg(providerName).arg(name).toUpper();
173 const QString provar = providerVar(providerName);
174
175 stream << "\n";
176
177 stream << "inline void trace_" << name << "(" << argList << ")\n"
178 << "{\n";
179
180 // Convert all unknown types to QString's using QDebug.
181 // Note the naming convention: it's field.name##Str
182 for (const Tracepoint::Field &field : tracepoint.fields) {
183 if (field.backendType == Tracepoint::Field::Unknown) {
184 stream << " const QString " << field.name << "Str = QDebug::toString(" << field.name
185 << ");\n";
186 }
187 }
188 stream << " TraceLoggingWrite(" << provar << ", \"" << name << "\"";
189
190 for (const Tracepoint::Field &field : tracepoint.fields) {
191 stream << ",\n";
192 stream << " ";
193 writeEtwMacro(stream, field);
194 }
195
196 stream << ");\n"
197 << "}\n\n";
198
199 stream << "inline void do_trace_" << name << "(" << argList << ")\n"
200 << "{\n"
201 << " trace_" << name << "(" << paramList << ");\n"
202 << "}\n";
203
204 stream << "inline bool trace_" << name << "_enabled()\n"
205 << "{\n"
206 << " return TraceLoggingProviderEnabled(" << provar << ", 0, 0);\n"
207 << "}\n";
208}
209
210static void writeEnumConverter(QTextStream &stream, const TraceEnum &enumeration)
211{
212 stream << "inline QString trace_convert_" << typeToTypeName(enumeration.name) << "(" << enumeration.name << " val)\n";
213 stream << "{\n";
214 for (const auto &v : enumeration.values) {
215 if (v.range != 0) {
216 stream << " if (val >= " << v.value << " && val <= " << v.range << ")\n"
217 << " return QStringLiteral(\"" << v.name << " + \") + QString::number((int)val - " << v.value << ");\n";
218 }
219 }
220 stream << "\n QString ret;\n switch (val) {\n";
221
222 QList<int> handledValues;
223 for (const auto &v : enumeration.values) {
224 if (v.range == 0 && !handledValues.contains(v.value)) {
225 stream << " case " << v.value << ": ret = QStringLiteral(\""
226 << aggregateListValues(v.value, enumeration.values) << "\"); break;\n";
227 handledValues.append(v.value);
228 }
229 }
230
231 stream << " }\n return ret;\n}\n";
232}
233
235{
236 stream << "inline QString trace_convert_" << typeToTypeName(flag.name) << "(" << flag.name << " val)\n";
237 stream << "{\n QString ret;\n";
238 for (const auto &v : flag.values) {
239 if (v.value == 0) {
240 stream << " if (val == 0)\n return QStringLiteral(\""
241 << aggregateListValues(v.value, flag.values) << "\");\n";
242 break;
243 }
244 }
245 QList<int> handledValues;
246 for (const auto &v : flag.values) {
247 if (v.value != 0 && !handledValues.contains(v.value)) {
248 stream << " if (val & " << (1 << (v.value - 1))
249 << ") { if (ret.length()) ret += QLatin1Char(\'|\'); ret += QStringLiteral(\"" << v.name << "\"); }\n";
250 handledValues.append(v.value);
251 }
252 }
253 stream << " return ret;\n}\n";
254}
255
256static void writeTracepoints(QTextStream &stream, const Provider &provider)
257{
258 if (provider.tracepoints.isEmpty())
259 return;
260
261 const QString includeGuard = QStringLiteral("TP_%1_PROVIDER").arg(provider.name).toUpper();
262
263 stream << "#if !defined(" << includeGuard << ") && !defined(TRACEPOINT_DEFINE)\n"
264 << "#define " << includeGuard << "\n"
265 << "QT_BEGIN_NAMESPACE\n"
266 << "namespace QtPrivate {\n";
267
268 for (const auto &enumeration : provider.enumerations)
269 writeEnumConverter(stream, enumeration);
270
271 for (const auto &flag : provider.flags)
273
274 for (const Tracepoint &t : provider.tracepoints)
275 writeWrapper(stream, provider, t, provider.name);
276
277 stream << "} // namespace QtPrivate\n"
278 << "QT_END_NAMESPACE\n"
279 << "#endif // " << includeGuard << "\n\n";
280}
281
282void writeEtw(QFile &file, const Provider &provider)
283{
285
287
288 writePrologue(stream, fileName, provider);
289 writeTracepoints(stream, provider);
291}
292
QString fileName() const
\inmodule QtCore
Definition qfile.h:93
QString fileName() const override
Returns the name set by setFileName() or to the QFile constructors.
Definition qfile.cpp:277
bool isEmpty() const noexcept
Definition qlist.h:401
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QByteArray toLocal8Bit() const &
Definition qstring.h:638
\inmodule QtCore
\inmodule QtCore
Definition quuid.h:31
QString toString(StringFormat mode=WithBraces) const
Definition quuid.cpp:650
static QUuid createUuidV5(const QUuid &ns, const QByteArray &baseData)
Definition quuid.cpp:574
uint data1
Definition quuid.h:203
ushort data3
Definition quuid.h:205
uchar data4[8]
Definition quuid.h:206
ushort data2
Definition quuid.h:204
static QString providerVar(const QString &providerName)
Definition etw.cpp:16
static void writeEpilogue(QTextStream &stream, const QString &fileName)
Definition etw.cpp:160
void writeEtw(QFile &file, const Provider &provider)
Definition etw.cpp:282
static void writeEnumConverter(QTextStream &stream, const TraceEnum &enumeration)
Definition etw.cpp:210
static void writeFlagConverter(QTextStream &stream, const TraceFlags &flag)
Definition etw.cpp:234
static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field)
Definition etw.cpp:21
static void writeWrapper(QTextStream &stream, const Provider &provider, const Tracepoint &tracepoint, const QString &providerName)
Definition etw.cpp:166
static QString createGuid(const QUuid &uuid)
Definition etw.cpp:80
static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider)
Definition etw.cpp:105
static void writeTracepoints(QTextStream &stream, const Provider &provider)
Definition etw.cpp:256
void writeCommonPrologue(QTextStream &stream)
Definition helpers.cpp:9
QString typeToTypeName(const QString &name)
Definition helpers.cpp:14
QString includeGuard(const QString &filename)
Definition helpers.cpp:20
QString formatFunctionSignature(const QList< Tracepoint::Argument > &args)
Definition helpers.cpp:50
QString formatParameterList(const Provider &provider, const QList< Tracepoint::Argument > &args, const QList< Tracepoint::Field > &fields, ParamType type)
Definition helpers.cpp:57
@ ETW
Definition helpers.h:15
static QString aggregateListValues(int value, const QList< T > &list)
Definition helpers.h:27
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
#define tracepoint(provider, name,...)
Definition qctf_p.h:214
EGLStreamKHR stream
GLsizei const GLfloat * v
[13]
GLuint name
GLdouble GLdouble t
Definition qopenglext.h:243
#define QStringLiteral(str)
const char * qtHeaders()
Definition qtheaders.cpp:6
QFile file
[0]
QStringList prefixText
Definition provider.h:85
QList< TraceEnum > enumerations
Definition provider.h:86
QList< TraceFlags > flags
Definition provider.h:87
QString name
Definition provider.h:83
QList< Tracepoint > tracepoints
Definition provider.h:84
QString name
Definition provider.h:56
QList< EnumValue > values
Definition provider.h:62
QString name
Definition provider.h:67
QList< FlagValue > values
Definition provider.h:72
QString paramType
Definition provider.h:43