Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
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
13
// This is a bootstrapped tool, so we can't rely on QCryptographicHash for the
14
// faster SHA1 implementations from OpenSSL.
15
#
include
"../../3rdparty/sha1/sha1.cpp"
16
17
using
namespace
Qt::StringLiterals;
18
19
static
inline
QString
providerVar
(
const
QString &providerName)
20
{
21
return
providerName +
"_provider"_L1
;
22
}
23
24
static
void
writeEtwMacro
(QTextStream &stream,
const
Tracepoint::Field &field)
25
{
26
const
QString &name = field.name;
27
28
if
(field.arrayLen > 0) {
29
for
(
int
i = 0; i < field.arrayLen; i++) {
30
stream <<
"TraceLoggingValue("
<< name <<
"["
<< i <<
"], \""
<< name <<
"["
<< i <<
"]\")"
;
31
if
(i + 1 < field.arrayLen)
32
stream <<
",\n "
;
33
}
34
return
;
35
}
36
37
switch
(field.backendType) {
38
case
Tracepoint::Field::QtString:
39
stream <<
"TraceLoggingCountedWideString(reinterpret_cast<LPCWSTR>("
40
<< name <<
".utf16()), static_cast<ULONG>("
<< name <<
".size()), \""
41
<< name <<
"\")"
;
42
return
;
43
case
Tracepoint::Field::QtByteArray:
44
stream <<
"TraceLoggingBinary("
<< name <<
".constData(), "
45
<< name <<
".size(), \""
<< name <<
"\")"
;
46
return
;
47
case
Tracepoint::Field::QtUrl:
48
stream <<
"TraceLoggingValue("
<< name <<
".toEncoded().constData(), \""
<< name <<
"\")"
;
49
return
;
50
case
Tracepoint::Field::QtRect:
51
case
Tracepoint::Field::QtRectF:
52
stream <<
"TraceLoggingValue("
<< name <<
".x(), \"x\"), "
53
<<
"TraceLoggingValue("
<< name <<
".y(), \"y\"), "
54
<<
"TraceLoggingValue("
<< name <<
".width(), \"width\"), "
55
<<
"TraceLoggingValue("
<< name <<
".height(), \"height\")"
;
56
return
;
57
case
Tracepoint::Field::QtSize:
58
case
Tracepoint::Field::QtSizeF:
59
stream <<
"TraceLoggingValue("
<< name <<
".width(), \"width\"), "
60
<<
"TraceLoggingValue("
<< name <<
".height(), \"height\")"
;
61
return
;
62
case
Tracepoint::Field::Pointer:
63
stream <<
"TraceLoggingPointer("
<< name <<
", \""
<< name <<
"\")"
;
64
return
;
65
case
Tracepoint::Field::Unknown:
66
// Write down the previously stringified data (like we do for QString).
67
// The string is already created in writeWrapper().
68
// Variable name is name##Str.
69
stream <<
"TraceLoggingCountedWideString(reinterpret_cast<LPCWSTR>("
<< name
70
<<
"Str.utf16()), static_cast<ULONG>("
<< name <<
"Str.size()), \""
<< name <<
"\")"
;
71
return
;
72
case
Tracepoint::Field::EnumeratedType:
73
case
Tracepoint::Field::FlagType:
74
stream <<
"TraceLoggingString(trace_convert_"
<< typeToTypeName(field.paramType) <<
"("
<< name <<
").toUtf8().constData(), \""
<< name <<
"\")"
;
75
return
;
76
default
:
77
break
;
78
}
79
80
stream <<
"TraceLoggingValue("
<< name <<
", \""
<< name <<
"\")"
;
81
}
82
83
static
QString
createGuid
(QByteArrayView name)
84
{
85
quint8 uuid[20] = {};
// SHA1 produces 160 bits of data
86
87
Sha1State state;
88
sha1InitState(&state);
89
#
if
QT_VERSION
<
QT_VERSION_CHECK
(
7
,
0
,
0
)
90
// namespace {00000000-0000-0000-0000-000000000000} for compatibility
91
sha1Update(&state, uuid, 16);
92
#
endif
93
sha1Update(&state,
reinterpret_cast
<
const
uchar *>(name.data()), name.size());
94
sha1FinalizeState(&state);
95
96
sha1ToHash(&state, uuid);
97
98
// set UUID OSF DCE version 5 (SHA1)
99
uuid[6] = (uuid[6] & 0xF) | 0x50;
// version 5
100
uuid[8] = (uuid[8] & 0x3F) | 0x80;
// OSF DCE variant
101
102
QString guid;
103
104
QTextStream
stream(&guid);
105
106
Qt::hex(stream);
107
Qt::showbase(stream);
108
109
stream <<
"("
110
<< qFromBigEndian<quint32>(uuid + 0) <<
", "
111
<< qFromBigEndian<quint16>(uuid + 4) <<
", "
112
<< qFromBigEndian<quint16>(uuid + 6) <<
", "
113
<< uuid[8] <<
", "
114
<< uuid[9] <<
", "
115
<< uuid[10] <<
", "
116
<< uuid[11] <<
", "
117
<< uuid[12] <<
", "
118
<< uuid[13] <<
", "
119
<< uuid[14] <<
", "
120
<< uuid[15]
121
<<
")"
;
122
123
return
guid;
124
}
125
126
static
void
writePrologue
(QTextStream &stream,
const
QString &fileName,
const
Provider &provider)
127
{
128
writeCommonPrologue(stream);
129
130
const
QString providerV = providerVar(provider.name);
131
const
QString guard = includeGuard(fileName);
132
const
QString guid = createGuid(provider.name.toLocal8Bit());
133
134
stream <<
"#ifndef "
<< guard <<
"\n"
135
<<
"#define "
<< guard <<
"\n"
136
<<
"\n"
137
<<
"#include <qt_windows.h>\n"
138
<<
"#include <TraceLoggingProvider.h>\n"
139
<<
"\n"
;
140
141
/* TraceLogging API macros cannot deal with UTF8
142
* source files, so we work around it like this
143
*/
144
stream <<
"#undef _TlgPragmaUtf8Begin\n"
145
"#undef _TlgPragmaUtf8End\n"
146
"#define _TlgPragmaUtf8Begin\n"
147
"#define _TlgPragmaUtf8End\n"
;
148
149
stream <<
"\n"
;
150
stream << qtHeaders();
151
stream <<
"\n"
;
152
153
if
(!provider.prefixText.isEmpty())
154
stream << provider.prefixText.join(u'\n') <<
"\n\n"
;
155
156
stream <<
"#ifdef TRACEPOINT_DEFINE\n"
157
<<
"TRACELOGGING_DEFINE_PROVIDER("
<< providerV <<
", \""
158
<< provider.name <<
"\", "
<< guid <<
");\n\n"
;
159
160
stream <<
"static inline void registerProvider()\n"
161
<<
"{\n"
162
<<
" TraceLoggingRegister("
<< providerV <<
");\n"
163
<<
"}\n\n"
;
164
165
stream <<
"static inline void unregisterProvider()\n"
166
<<
"{\n"
167
<<
" TraceLoggingUnregister("
<< providerV <<
");\n"
168
<<
"}\n"
;
169
170
stream <<
"Q_CONSTRUCTOR_FUNCTION(registerProvider)\n"
171
<<
"Q_DESTRUCTOR_FUNCTION(unregisterProvider)\n\n"
;
172
173
stream <<
"#else\n"
174
<<
"TRACELOGGING_DECLARE_PROVIDER("
<< providerV <<
");\n"
175
<<
"#endif // TRACEPOINT_DEFINE\n\n"
;
176
}
177
178
static
void
writeEpilogue
(QTextStream &stream,
const
QString &fileName)
179
{
180
stream <<
"\n#endif // "
<< includeGuard(fileName) <<
"\n"
181
<<
"#include <private/qtrace_p.h>\n"
;
182
}
183
184
static
void
writeWrapper
(QTextStream &stream,
const
Provider &provider,
const
Tracepoint &tracepoint,
185
const
QString &providerName)
186
{
187
const
QString argList = formatFunctionSignature(tracepoint.args);
188
const
QString paramList = formatParameterList(provider, tracepoint.args, tracepoint.fields, ETW);
189
const
QString &name = tracepoint.name;
190
const
QString includeGuard =
QStringLiteral
(
"TP_%1_%2"
).arg(providerName).arg(name).toUpper();
191
const
QString provar = providerVar(providerName);
192
193
stream <<
"\n"
;
194
195
stream <<
"inline void trace_"
<< name <<
"("
<< argList <<
")\n"
196
<<
"{\n"
;
197
198
// Convert all unknown types to QString's using QDebug.
199
// Note the naming convention: it's field.name##Str
200
for
(
const
Tracepoint::Field &field : tracepoint.fields) {
201
if
(field.backendType == Tracepoint::Field::Unknown) {
202
stream <<
" const QString "
<< field.name <<
"Str = QDebug::toString("
<< field.name
203
<<
");\n"
;
204
}
205
}
206
stream <<
" TraceLoggingWrite("
<< provar <<
", \""
<< name <<
"\""
;
207
208
for
(
const
Tracepoint::Field &field : tracepoint.fields) {
209
stream <<
",\n"
;
210
stream <<
" "
;
211
writeEtwMacro(stream, field);
212
}
213
214
stream <<
");\n"
215
<<
"}\n\n"
;
216
217
stream <<
"inline void do_trace_"
<< name <<
"("
<< argList <<
")\n"
218
<<
"{\n"
219
<<
" trace_"
<< name <<
"("
<< paramList <<
");\n"
220
<<
"}\n"
;
221
222
stream <<
"inline bool trace_"
<< name <<
"_enabled()\n"
223
<<
"{\n"
224
<<
" return TraceLoggingProviderEnabled("
<< provar <<
", 0, 0);\n"
225
<<
"}\n"
;
226
}
227
228
static
void
writeEnumConverter
(QTextStream &stream,
const
TraceEnum &enumeration)
229
{
230
stream <<
"inline QString trace_convert_"
<< typeToTypeName(enumeration.name) <<
"("
<< enumeration.name <<
" val)\n"
;
231
stream <<
"{\n"
;
232
for
(
const
auto
&v : enumeration.values) {
233
if
(v.range != 0) {
234
stream <<
" if (val >= "
<< v.value <<
" && val <= "
<< v.range <<
")\n"
235
<<
" return QStringLiteral(\""
<< v.name <<
" + \") + QString::number((int)val - "
<< v.value <<
");\n"
;
236
}
237
}
238
stream <<
"\n QString ret;\n switch (val) {\n"
;
239
240
QList<
int
> handledValues;
241
for
(
const
auto
&v : enumeration.values) {
242
if
(v.range == 0 && !handledValues.contains(v.value)) {
243
stream <<
" case "
<< v.value <<
": ret = QStringLiteral(\""
244
<< aggregateListValues(v.value, enumeration.values) <<
"\"); break;\n"
;
245
handledValues.append(v.value);
246
}
247
}
248
249
stream <<
" }\n return ret;\n}\n"
;
250
}
251
252
static
void
writeFlagConverter
(QTextStream &stream,
const
TraceFlags &flag)
253
{
254
stream <<
"inline QString trace_convert_"
<< typeToTypeName(flag.name) <<
"("
<< flag.name <<
" val)\n"
;
255
stream <<
"{\n QString ret;\n"
;
256
for
(
const
auto
&v : flag.values) {
257
if
(v.value == 0) {
258
stream <<
" if (val == 0)\n return QStringLiteral(\""
259
<< aggregateListValues(v.value, flag.values) <<
"\");\n"
;
260
break
;
261
}
262
}
263
QList<
int
> handledValues;
264
for
(
const
auto
&v : flag.values) {
265
if
(v.value != 0 && !handledValues.contains(v.value)) {
266
stream <<
" if (val & "
<< (1 << (v.value - 1))
267
<<
") { if (ret.length()) ret += QLatin1Char(\'|\'); ret += QStringLiteral(\""
<< v.name <<
"\"); }\n"
;
268
handledValues.append(v.value);
269
}
270
}
271
stream <<
" return ret;\n}\n"
;
272
}
273
274
static
void
writeTracepoints
(QTextStream &stream,
const
Provider &provider)
275
{
276
if
(provider.tracepoints.isEmpty())
277
return
;
278
279
const
QString includeGuard =
QStringLiteral
(
"TP_%1_PROVIDER"
).arg(provider.name).toUpper();
280
281
stream <<
"#if !defined("
<< includeGuard <<
") && !defined(TRACEPOINT_DEFINE)\n"
282
<<
"#define "
<< includeGuard <<
"\n"
283
<<
"QT_BEGIN_NAMESPACE\n"
284
<<
"namespace QtPrivate {\n"
;
285
286
for
(
const
auto
&enumeration : provider.enumerations)
287
writeEnumConverter(stream, enumeration);
288
289
for
(
const
auto
&flag : provider.flags)
290
writeFlagConverter(stream, flag);
291
292
for
(
const
Tracepoint &t : provider.tracepoints)
293
writeWrapper(stream, provider, t, provider.name);
294
295
stream <<
"} // namespace QtPrivate\n"
296
<<
"QT_END_NAMESPACE\n"
297
<<
"#endif // "
<< includeGuard <<
"\n\n"
;
298
}
299
300
void
writeEtw
(QFile &file,
const
Provider
&provider)
301
{
302
QTextStream
stream(&file);
303
304
const
QString fileName = QFileInfo(file.fileName()).fileName();
305
306
writePrologue
(stream, fileName, provider);
307
writeTracepoints
(stream, provider);
308
writeEpilogue
(stream, fileName);
309
}
QT_FORWARD_DECLARE_CLASS
QT_FORWARD_DECLARE_CLASS(QTextStream)
providerVar
static QString providerVar(const QString &providerName)
Definition
etw.cpp:19
writeEpilogue
static void writeEpilogue(QTextStream &stream, const QString &fileName)
Definition
etw.cpp:178
writeEtw
void writeEtw(QFile &file, const Provider &provider)
Definition
etw.cpp:300
writeEnumConverter
static void writeEnumConverter(QTextStream &stream, const TraceEnum &enumeration)
Definition
etw.cpp:228
writeFlagConverter
static void writeFlagConverter(QTextStream &stream, const TraceFlags &flag)
Definition
etw.cpp:252
writeEtwMacro
static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field)
Definition
etw.cpp:24
writeWrapper
static void writeWrapper(QTextStream &stream, const Provider &provider, const Tracepoint &tracepoint, const QString &providerName)
Definition
etw.cpp:184
createGuid
static QString createGuid(QByteArrayView name)
Definition
etw.cpp:83
writePrologue
static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider)
Definition
etw.cpp:126
writeTracepoints
static void writeTracepoints(QTextStream &stream, const Provider &provider)
Definition
etw.cpp:274
QStringLiteral
#define QStringLiteral(str)
Definition
qstring.h:1865
Provider
Definition
provider.h:82
qtbase
src
tools
tracegen
etw.cpp
Generated on
for Qt by
1.18.0