summaryrefslogtreecommitdiffstats
path: root/src/tools/tracegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/tracegen')
-rw-r--r--src/tools/tracegen/CMakeLists.txt10
-rw-r--r--src/tools/tracegen/ctf.cpp376
-rw-r--r--src/tools/tracegen/ctf.h12
-rw-r--r--src/tools/tracegen/etw.cpp86
-rw-r--r--src/tools/tracegen/etw.h2
-rw-r--r--src/tools/tracegen/helpers.cpp65
-rw-r--r--src/tools/tracegen/helpers.h22
-rw-r--r--src/tools/tracegen/lttng.cpp162
-rw-r--r--src/tools/tracegen/lttng.h2
-rw-r--r--src/tools/tracegen/panic.cpp15
-rw-r--r--src/tools/tracegen/panic.h3
-rw-r--r--src/tools/tracegen/provider.cpp270
-rw-r--r--src/tools/tracegen/provider.h47
-rw-r--r--src/tools/tracegen/qtheaders.cpp2
-rw-r--r--src/tools/tracegen/qtheaders.h2
-rw-r--r--src/tools/tracegen/tracegen.cpp13
16 files changed, 957 insertions, 132 deletions
diff --git a/src/tools/tracegen/CMakeLists.txt b/src/tools/tracegen/CMakeLists.txt
index cbc4942e1e..f5f6b2e184 100644
--- a/src/tools/tracegen/CMakeLists.txt
+++ b/src/tools/tracegen/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from tracegen.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tracegen Tool:
@@ -8,17 +9,16 @@ qt_get_tool_target_name(target_name tracegen)
qt_internal_add_tool(${target_name}
CORE_LIBRARY Bootstrap
INSTALL_DIR "${INSTALL_LIBEXECDIR}"
- TOOLS_TARGET Core # special case
+ TOOLS_TARGET Core
SOURCES
etw.cpp etw.h
helpers.cpp helpers.h
+ ctf.cpp ctf.h
lttng.cpp lttng.h
panic.cpp panic.h
provider.cpp provider.h
qtheaders.cpp qtheaders.h
tracegen.cpp
+ NO_UNITY_BUILD
)
qt_internal_return_unless_building_tools()
-
-#### Keys ignored in scope 1:.:.:tracegen.pro:<TRUE>:
-# _OPTION = "host_build"
diff --git a/src/tools/tracegen/ctf.cpp b/src/tools/tracegen/ctf.cpp
new file mode 100644
index 0000000000..95ffcf89cc
--- /dev/null
+++ b/src/tools/tracegen/ctf.cpp
@@ -0,0 +1,376 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "ctf.h"
+#include "provider.h"
+#include "helpers.h"
+#include "panic.h"
+#include "qtheaders.h"
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+#include <qdebug.h>
+
+
+static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider)
+{
+ writeCommonPrologue(stream);
+ const QString guard = includeGuard(fileName);
+
+ // include prefix text or qt headers only once
+ stream << "#if !defined(" << guard << ")\n";
+ stream << qtHeaders();
+ stream << "\n";
+ if (!provider.prefixText.isEmpty())
+ stream << provider.prefixText.join(u'\n') << "\n\n";
+ stream << "#endif\n\n";
+
+ /* the first guard is the usual one, the second is required
+ * by LTTNG to force the re-evaluation of TRACEPOINT_* macros
+ */
+ stream << "#if !defined(" << guard << ") || defined(TRACEPOINT_HEADER_MULTI_READ)\n";
+
+ stream << "#define " << guard << "\n\n"
+ << "#undef TRACEPOINT_INCLUDE\n"
+ << "#define TRACEPOINT_INCLUDE \"" << fileName << "\"\n\n";
+
+ stream << "#include <private/qctf_p.h>\n\n";
+
+ const QString namespaceGuard = guard + QStringLiteral("_USE_NAMESPACE");
+ stream << "#if !defined(" << namespaceGuard << ")\n"
+ << "#define " << namespaceGuard << "\n"
+ << "QT_USE_NAMESPACE\n"
+ << "#endif // " << namespaceGuard << "\n\n";
+
+ stream << "TRACEPOINT_PROVIDER(" << provider.name << ");\n\n";
+}
+
+static void writeEpilogue(QTextStream &stream, const QString &fileName)
+{
+ stream << "\n";
+ stream << "#endif // " << includeGuard(fileName) << "\n"
+ << "#include <private/qtrace_p.h>\n";
+}
+
+static void writeWrapper(QTextStream &stream,
+ const Tracepoint &tracepoint, const Provider &provider)
+{
+ const QString argList = formatFunctionSignature(tracepoint.args);
+ const QString paramList = formatParameterList(provider, tracepoint.args, tracepoint.fields, CTF);
+ const QString &name = tracepoint.name;
+ const QString includeGuard = QStringLiteral("TP_%1_%2").arg(provider.name).arg(name).toUpper();
+
+ /* prevents the redefinion of the inline wrapper functions
+ */
+ stream << "\n"
+ << "#ifndef " << includeGuard << "\n"
+ << "#define " << includeGuard << "\n"
+ << "QT_BEGIN_NAMESPACE\n"
+ << "namespace QtPrivate {\n";
+
+ stream << "inline void trace_" << name << "(" << argList << ")\n"
+ << "{\n"
+ << " tracepoint(" << provider.name << ", " << name << paramList << ");\n"
+ << "}\n";
+
+ stream << "inline void do_trace_" << name << "(" << argList << ")\n"
+ << "{\n"
+ << " do_tracepoint(" << provider.name << ", " << name << paramList << ");\n"
+ << "}\n";
+
+ stream << "inline bool trace_" << name << "_enabled()\n"
+ << "{\n"
+ << " return tracepoint_enabled(" << provider.name << ", " << name << ");\n"
+ << "}\n";
+
+ stream << "} // namespace QtPrivate\n"
+ << "QT_END_NAMESPACE\n"
+ << "#endif // " << includeGuard << "\n\n";
+}
+
+
+static void writeMetadataGenerators(QTextStream &stream)
+{
+ stream << R"CPP(
+template <typename T>
+inline QString integerToMetadata(const QString &name)
+{
+ QString ret;
+ if (!std::is_signed<T>().value)
+ ret += QLatin1Char('u');
+ if (sizeof(T) == 8)
+ ret += QStringLiteral("int64_t ");
+ else if (sizeof(T) == 4)
+ ret += QStringLiteral("int32_t ");
+ else if (sizeof(T) == 2)
+ ret += QStringLiteral("int16_t ");
+ else if (sizeof(T) == 1)
+ ret += QStringLiteral("int8_t ");
+ ret += name + QLatin1Char(';');
+ return ret;
+}
+
+template <typename T>
+inline QString integerArrayToMetadata(const QString &size, const QString &name)
+{
+ QString ret;
+ if (!std::is_signed<T>().value)
+ ret += QLatin1Char('u');
+ if (sizeof(T) == 8)
+ ret += QStringLiteral("int64_t ");
+ else if (sizeof(T) == 4)
+ ret += QStringLiteral("int32_t ");
+ else if (sizeof(T) == 2)
+ ret += QStringLiteral("int16_t ");
+ else if (sizeof(T) == 1)
+ ret += QStringLiteral("int8_t ");
+ ret += name + QLatin1Char('[') + size + QStringLiteral("];");
+ return ret;
+}
+
+template <typename T>
+inline QString floatToMetadata(const QString &name)
+{
+ QString ret;
+ if (sizeof(T) == 8)
+ ret += QStringLiteral("double ");
+ else if (sizeof(T) == 4)
+ ret += QStringLiteral("float ");
+ ret += name + QLatin1Char(';');
+ return ret;
+}
+
+template <typename T>
+inline QString floatArrayToMetadata(const QString &size, const QString &name)
+{
+ QString ret;
+ if (sizeof(T) == 8)
+ ret += QStringLiteral("double ");
+ else if (sizeof(T) == 4)
+ ret += QStringLiteral("float ");
+ ret += name + QLatin1Char('[') + size + QLatin1Char(']');
+ return ret + QLatin1Char(';');
+}
+
+inline QString pointerToMetadata(const QString &name)
+{
+ QString ret;
+ if (QT_POINTER_SIZE == 8)
+ ret += QStringLiteral("intptr64_t ");
+ else if (QT_POINTER_SIZE == 4)
+ ret += QStringLiteral("intptr32_t ");
+ ret += name + QLatin1Char(';');
+ return ret;
+}
+
+)CPP";
+}
+
+static void writeTracepoint(QTextStream &stream,
+ const Tracepoint &tracepoint, const QString &providerName)
+{
+ stream << "TRACEPOINT_EVENT(\n"
+ << " " << providerName << ",\n"
+ << " " << tracepoint.name << ",\n";
+
+ const auto checkUnknownArgs = [](const Tracepoint &tracepoint) {
+ for (auto &field : tracepoint.fields) {
+ if (field.backendType == Tracepoint::Field::Unknown)
+ return true;
+ }
+ return false;
+ };
+
+ const auto formatType = [](const QString &type) {
+ QString ret = type;
+ if (type.endsWith(QLatin1Char('*')) || type.endsWith(QLatin1Char('&')))
+ ret = type.left(type.length() - 1).simplified();
+ if (ret.startsWith(QStringLiteral("const")))
+ ret = ret.right(ret.length() - 6).simplified();
+ return typeToTypeName(ret);
+ };
+ QString eventSize;
+ bool variableSize = false;
+ const bool emptyMetadata = checkUnknownArgs(tracepoint) || tracepoint.args.size() == 0;
+ if (!emptyMetadata) {
+ for (int i = 0; i < tracepoint.args.size(); i++) {
+ auto &arg = tracepoint.args[i];
+ auto &field = tracepoint.fields[i];
+ if (i > 0) {
+ stream << " + QStringLiteral(\"\\n\\\n \") + ";
+ eventSize += QStringLiteral(" + ");
+ }
+ const bool array = field.arrayLen > 0;
+ switch (field.backendType) {
+ case Tracepoint::Field::Boolean: {
+ stream << "QStringLiteral(\"Boolean " << arg.name << ";\")";
+ eventSize += QStringLiteral("sizeof(bool)");
+ } break;
+ case Tracepoint::Field::Integer: {
+ if (array) {
+ stream << "integerArrayToMetadata<" << formatType(arg.type)
+ << ">(QStringLiteral(\"" << field.arrayLen << "\"), QStringLiteral(\""
+ << arg.name << "\"))";
+ } else {
+ stream << "integerToMetadata<" << formatType(arg.type) << ">(QStringLiteral(\""
+ << arg.name << "\"))";
+ }
+ eventSize += QStringLiteral("sizeof(") + formatType(arg.type) + QStringLiteral(")");
+ if (array)
+ eventSize += QStringLiteral(" * ") + QString::number(field.arrayLen);
+ } break;
+ case Tracepoint::Field::Pointer:
+ case Tracepoint::Field::IntegerHex: {
+ stream << "pointerToMetadata(QStringLiteral(\"" << formatType(arg.type) << "_"
+ << arg.name << "\"))";
+ eventSize += QStringLiteral("QT_POINTER_SIZE");
+ } break;
+ case Tracepoint::Field::Float: {
+ if (array) {
+ stream << "floatArrayToMetadata<" << formatType(arg.type)
+ << ">(QStringLiteral(\"" << field.arrayLen << "\"), QStringLiteral(\""
+ << arg.name << "\"))";
+ } else {
+ stream << "floatToMetadata<" << formatType(arg.type) << ">(QStringLiteral(\""
+ << arg.name << "\"))";
+ }
+ eventSize += QStringLiteral("sizeof(") + formatType(arg.type) + QStringLiteral(")");
+ if (array)
+ eventSize += QStringLiteral(" * ") + QString::number(field.arrayLen);
+ } break;
+ case Tracepoint::Field::QtUrl:
+ case Tracepoint::Field::QtString:
+ case Tracepoint::Field::String: {
+ stream << "QStringLiteral(\"string " << arg.name << ";\")";
+ eventSize += QStringLiteral("1");
+ variableSize = true;
+ } break;
+ case Tracepoint::Field::QtRect: {
+ stream << "QStringLiteral(\"int32_t QRect_" << arg.name << "_x;\\n\\\n \")";
+ stream << " + QStringLiteral(\"int32_t QRect_" << arg.name << "_y;\\n\\\n \")";
+ stream << " + QStringLiteral(\"int32_t QRect_" << arg.name << "_width;\\n\\\n \")";
+ stream << " + QStringLiteral(\"int32_t QRect_" << arg.name << "_height;\\n\\\n \")";
+ eventSize += QStringLiteral("16");
+ } break;
+ case Tracepoint::Field::QtSize: {
+ stream << "QStringLiteral(\"int32_t QSize_" << arg.name << "_width;\\n\\\n \")";
+ stream << " + QStringLiteral(\"int32_t QSize_" << arg.name << "_height;\\n\\\n \")";
+ eventSize += QStringLiteral("8");
+ } break;
+ case Tracepoint::Field::QtRectF: {
+ stream << "QStringLiteral(\"float QRectF_" << arg.name << "_x;\\n\\\n \")";
+ stream << " + QStringLiteral(\"float QRectF_" << arg.name << "_y;\\n\\\n \")";
+ stream << " + QStringLiteral(\"float QRectF_" << arg.name << "_width;\\n\\\n \")";
+ stream << " + QStringLiteral(\"float QRectF_" << arg.name << "_height;\\n\\\n \")";
+ eventSize += QStringLiteral("16");
+ } break;
+ case Tracepoint::Field::QtSizeF: {
+ stream << "QStringLiteral(\"float QSizeF_" << arg.name << "_width;\\n\\\n \")";
+ stream << " + QStringLiteral(\"float QSizeF_" << arg.name << "_height;\\n\\\n \")";
+ eventSize += QStringLiteral("8");
+ } break;
+ case Tracepoint::Field::Unknown:
+ break;
+ case Tracepoint::Field::EnumeratedType: {
+ stream << "QStringLiteral(\"" << typeToTypeName(arg.type) << " " << arg.name << ";\")";
+ eventSize += QString::number(field.enumValueSize / 8);
+ variableSize = true;
+ } break;
+ case Tracepoint::Field::FlagType: {
+ stream << "QStringLiteral(\"uint8_t " << arg.name << "_length;\\n\\\n ";
+ stream << typeToTypeName(arg.type) << " " << arg.name << "[" << arg.name << "_length];\")";
+ eventSize += QStringLiteral("2");
+ variableSize = true;
+ } break;
+ case Tracepoint::Field::QtByteArray:
+ case Tracepoint::Field::Sequence:
+ panic("Unhandled type '%s %s", qPrintable(arg.type), qPrintable(arg.name));
+ break;
+ }
+ }
+ }
+
+ if (emptyMetadata)
+ stream << "{},\n";
+ else
+ stream << ",\n";
+ if (eventSize.length())
+ stream << eventSize << ", \n";
+ else
+ stream << "0, \n";
+ stream << (variableSize ? "true" : "false") << "\n";
+ stream << ")\n\n";
+}
+
+static void writeTracepoints(QTextStream &stream, const Provider &provider)
+{
+ for (const Tracepoint &t : provider.tracepoints) {
+ writeTracepoint(stream, t, provider.name);
+ writeWrapper(stream, t, provider);
+ }
+}
+
+static void writeEnums(QTextStream &stream, const Provider &provider)
+{
+ for (const auto &e : provider.enumerations) {
+ QString name = e.name;
+ name.replace(QStringLiteral("::"), QStringLiteral("_"));
+ stream << "TRACEPOINT_METADATA(" << provider.name << ", " << name << ", \n";
+ stream << "QStringLiteral(\"typealias enum : integer { size = " << e.valueSize << "; } {\\n\\\n";
+
+ const auto values = e.values;
+ QList<int> handledValues;
+
+ for (const auto &v : values) {
+ if (handledValues.contains(v.value))
+ continue;
+ if (v.range) {
+ stream << v.name << " = " << v.value << " ... " << v.range << ", \\n\\\n";
+ } else {
+ const QString names = aggregateListValues(v.value, values);
+ stream << names << " = " << v.value << ", \\n\\\n";
+ handledValues.append(v.value);
+ }
+ }
+ stream << "} := " << name << ";\\n\\n\"));\n\n";
+ }
+ stream << "\n";
+}
+
+static void writeFlags(QTextStream &stream, const Provider &provider)
+{
+ for (const auto &e : provider.flags) {
+ QString name = e.name;
+ name.replace(QStringLiteral("::"), QStringLiteral("_"));
+ stream << "TRACEPOINT_METADATA(" << provider.name << ", " << name << ", \n";
+ stream << "QStringLiteral(\"typealias enum : integer { size = 8; } {\\n\\\n";
+
+ const auto values = e.values;
+ QList<int> handledValues;
+
+ for (const auto &v : values) {
+ if (handledValues.contains(v.value))
+ continue;
+ const QString names = aggregateListValues(v.value, values);
+ stream << names << " = " << v.value << ", \\n\\\n";
+ handledValues.append(v.value);
+ }
+ stream << "} := " << name << ";\\n\\n\"));\n\n";
+ }
+ stream << "\n";
+}
+
+void writeCtf(QFile &file, const Provider &provider)
+{
+ QTextStream stream(&file);
+
+ const QString fileName = QFileInfo(file.fileName()).fileName();
+
+ writePrologue(stream, fileName, provider);
+ writeMetadataGenerators(stream);
+ writeEnums(stream, provider);
+ writeFlags(stream, provider);
+ writeTracepoints(stream, provider);
+ writeEpilogue(stream, fileName);
+}
diff --git a/src/tools/tracegen/ctf.h b/src/tools/tracegen/ctf.h
new file mode 100644
index 0000000000..113e30919f
--- /dev/null
+++ b/src/tools/tracegen/ctf.h
@@ -0,0 +1,12 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef CTF_H
+#define CTF_H
+
+struct Provider;
+class QFile;
+
+void writeCtf(QFile &device, const Provider &p);
+
+#endif // CTF_H
diff --git a/src/tools/tracegen/etw.cpp b/src/tools/tracegen/etw.cpp
index cdda3bf232..f54a7896ea 100644
--- a/src/tools/tracegen/etw.cpp
+++ b/src/tools/tracegen/etw.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "etw.h"
#include "provider.h"
@@ -22,6 +22,15 @@ static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field)
{
const QString &name = field.name;
+ if (field.arrayLen > 0) {
+ for (int i = 0; i < field.arrayLen; i++) {
+ stream << "TraceLoggingValue(" << name << "[" << i << "], \"" << name << "[" << i << "]\")";
+ if (i + 1 < field.arrayLen)
+ stream << ",\n ";
+ }
+ return;
+ }
+
switch (field.backendType) {
case Tracepoint::Field::QtString:
stream << "TraceLoggingCountedWideString(reinterpret_cast<LPCWSTR>("
@@ -36,11 +45,17 @@ static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field)
stream << "TraceLoggingValue(" << name << ".toEncoded().constData(), \"" << name << "\")";
return;
case Tracepoint::Field::QtRect:
+ case Tracepoint::Field::QtRectF:
stream << "TraceLoggingValue(" << name << ".x(), \"x\"), "
<< "TraceLoggingValue(" << name << ".y(), \"y\"), "
<< "TraceLoggingValue(" << name << ".width(), \"width\"), "
<< "TraceLoggingValue(" << name << ".height(), \"height\")";
return;
+ case Tracepoint::Field::QtSize:
+ case Tracepoint::Field::QtSizeF:
+ stream << "TraceLoggingValue(" << name << ".width(), \"width\"), "
+ << "TraceLoggingValue(" << name << ".height(), \"height\")";
+ return;
case Tracepoint::Field::Pointer:
stream << "TraceLoggingPointer(" << name << ", \"" << name << "\")";
return;
@@ -51,6 +66,10 @@ static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field)
stream << "TraceLoggingCountedWideString(reinterpret_cast<LPCWSTR>(" << name
<< "Str.utf16()), static_cast<ULONG>(" << name << "Str.size()), \"" << name << "\")";
return;
+ case Tracepoint::Field::EnumeratedType:
+ case Tracepoint::Field::FlagType:
+ stream << "TraceLoggingString(trace_convert_" << typeToTypeName(field.paramType) << "(" << name << ").toUtf8().constData(), \"" << name << "\")";
+ return;
default:
break;
}
@@ -85,6 +104,7 @@ static QString createGuid(const QUuid &uuid)
static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider)
{
+ writeCommonPrologue(stream);
QUuid uuid = QUuid::createUuidV5(QUuid(), provider.name.toLocal8Bit());
const QString providerV = providerVar(provider.name);
@@ -143,14 +163,14 @@ static void writeEpilogue(QTextStream &stream, const QString &fileName)
<< "#include <private/qtrace_p.h>\n";
}
-static void writeWrapper(QTextStream &stream, const Tracepoint &tracepoint,
+static void writeWrapper(QTextStream &stream, const Provider &provider, const Tracepoint &tracepoint,
const QString &providerName)
{
const QString argList = formatFunctionSignature(tracepoint.args);
- const QString paramList = formatParameterList(tracepoint.args, ETW);
+ const QString paramList = formatParameterList(provider, tracepoint.args, tracepoint.fields, ETW);
const QString &name = tracepoint.name;
const QString includeGuard = QStringLiteral("TP_%1_%2").arg(providerName).arg(name).toUpper();
- const QString provider = providerVar(providerName);
+ const QString provar = providerVar(providerName);
stream << "\n";
@@ -165,7 +185,7 @@ static void writeWrapper(QTextStream &stream, const Tracepoint &tracepoint,
<< ");\n";
}
}
- stream << " TraceLoggingWrite(" << provider << ", \"" << name << "\"";
+ stream << " TraceLoggingWrite(" << provar << ", \"" << name << "\"";
for (const Tracepoint::Field &field : tracepoint.fields) {
stream << ",\n";
@@ -183,10 +203,56 @@ static void writeWrapper(QTextStream &stream, const Tracepoint &tracepoint,
stream << "inline bool trace_" << name << "_enabled()\n"
<< "{\n"
- << " return TraceLoggingProviderEnabled(" << provider << ", 0, 0);\n"
+ << " return TraceLoggingProviderEnabled(" << provar << ", 0, 0);\n"
<< "}\n";
}
+static void writeEnumConverter(QTextStream &stream, const TraceEnum &enumeration)
+{
+ stream << "inline QString trace_convert_" << typeToTypeName(enumeration.name) << "(" << enumeration.name << " val)\n";
+ stream << "{\n";
+ for (const auto &v : enumeration.values) {
+ if (v.range != 0) {
+ stream << " if (val >= " << v.value << " && val <= " << v.range << ")\n"
+ << " return QStringLiteral(\"" << v.name << " + \") + QString::number((int)val - " << v.value << ");\n";
+ }
+ }
+ stream << "\n QString ret;\n switch (val) {\n";
+
+ QList<int> handledValues;
+ for (const auto &v : enumeration.values) {
+ if (v.range == 0 && !handledValues.contains(v.value)) {
+ stream << " case " << v.value << ": ret = QStringLiteral(\""
+ << aggregateListValues(v.value, enumeration.values) << "\"); break;\n";
+ handledValues.append(v.value);
+ }
+ }
+
+ stream << " }\n return ret;\n}\n";
+}
+
+static void writeFlagConverter(QTextStream &stream, const TraceFlags &flag)
+{
+ stream << "inline QString trace_convert_" << typeToTypeName(flag.name) << "(" << flag.name << " val)\n";
+ stream << "{\n QString ret;\n";
+ for (const auto &v : flag.values) {
+ if (v.value == 0) {
+ stream << " if (val == 0)\n return QStringLiteral(\""
+ << aggregateListValues(v.value, flag.values) << "\");\n";
+ break;
+ }
+ }
+ QList<int> handledValues;
+ for (const auto &v : flag.values) {
+ if (v.value != 0 && !handledValues.contains(v.value)) {
+ stream << " if (val & " << (1 << (v.value - 1))
+ << ") { if (ret.length()) ret += QLatin1Char(\'|\'); ret += QStringLiteral(\"" << v.name << "\"); }\n";
+ handledValues.append(v.value);
+ }
+ }
+ stream << " return ret;\n}\n";
+}
+
static void writeTracepoints(QTextStream &stream, const Provider &provider)
{
if (provider.tracepoints.isEmpty())
@@ -199,8 +265,14 @@ static void writeTracepoints(QTextStream &stream, const Provider &provider)
<< "QT_BEGIN_NAMESPACE\n"
<< "namespace QtPrivate {\n";
+ for (const auto &enumeration : provider.enumerations)
+ writeEnumConverter(stream, enumeration);
+
+ for (const auto &flag : provider.flags)
+ writeFlagConverter(stream, flag);
+
for (const Tracepoint &t : provider.tracepoints)
- writeWrapper(stream, t, provider.name);
+ writeWrapper(stream, provider, t, provider.name);
stream << "} // namespace QtPrivate\n"
<< "QT_END_NAMESPACE\n"
diff --git a/src/tools/tracegen/etw.h b/src/tools/tracegen/etw.h
index ad68fe08de..88508e2034 100644
--- a/src/tools/tracegen/etw.h
+++ b/src/tools/tracegen/etw.h
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef ETW_H
#define ETW_H
diff --git a/src/tools/tracegen/helpers.cpp b/src/tools/tracegen/helpers.cpp
index de523e74a6..0ea5848493 100644
--- a/src/tools/tracegen/helpers.cpp
+++ b/src/tools/tracegen/helpers.cpp
@@ -1,11 +1,26 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "helpers.h"
#include <qdebug.h>
using namespace Qt::StringLiterals;
+void writeCommonPrologue(QTextStream &stream)
+{
+ stream << R"CPP(
+#ifndef Q_TRACEPOINT
+#error "Q_TRACEPOINT not set for the module, Q_TRACE not enabled."
+#endif
+)CPP";
+}
+
+QString typeToTypeName(const QString &name)
+{
+ QString ret = name;
+ return ret.replace(QStringLiteral("::"), QStringLiteral("_"));
+}
+
QString includeGuard(const QString &filename)
{
QString guard = filename.toUpper();
@@ -43,14 +58,56 @@ QString formatFunctionSignature(const QList<Tracepoint::Argument> &args)
});
}
-QString formatParameterList(const QList<Tracepoint::Argument> &args, ParamType type)
+QString formatParameterList(const Provider &provider, const QList<Tracepoint::Argument> &args, const QList<Tracepoint::Field> &fields, ParamType type)
{
if (type == LTTNG) {
QString ret;
- for (const Tracepoint::Argument &arg : args)
- ret += ", "_L1 + arg.name;
+ for (int i = 0; i < args.size(); i++) {
+ const Tracepoint::Argument &arg = args[i];
+ const Tracepoint::Field &field = fields[i];
+ if (field.backendType == Tracepoint::Field::FlagType)
+ ret += ", trace_convert_"_L1 + typeToTypeName(arg.type) + "("_L1 + arg.name + ")"_L1;
+ else
+ ret += ", "_L1 + arg.name;
+ }
+ return ret;
+ }
+
+ auto findEnumeration = [](const QList<TraceEnum> &enums, const QString &name) {
+ for (const auto &e : enums) {
+ if (e.name == name)
+ return e;
+ }
+ return TraceEnum();
+ };
+
+ if (type == CTF) {
+ QString ret;
+ for (int i = 0; i < args.size(); i++) {
+ const Tracepoint::Argument &arg = args[i];
+ const Tracepoint::Field &field = fields[i];
+ if (arg.arrayLen > 1) {
+ ret += ", trace::toByteArrayFromArray("_L1 + arg.name + ", "_L1 + QString::number(arg.arrayLen) + ") "_L1;
+ } else if (field.backendType == Tracepoint::Field::EnumeratedType) {
+ const TraceEnum &e = findEnumeration(provider.enumerations, arg.type);
+ QString integerType;
+ if (e.valueSize == 8)
+ integerType = QStringLiteral("quint8");
+ else if (e.valueSize == 16)
+ integerType = QStringLiteral("quint16");
+ else
+ integerType = QStringLiteral("quint32");
+ ret += ", trace::toByteArrayFromEnum<"_L1 + integerType + ">("_L1 + arg.name + ")"_L1;
+ } else if (field.backendType == Tracepoint::Field::FlagType) {
+ ret += ", trace::toByteArrayFromFlags("_L1 + arg.name + ")"_L1;
+ } else if (field.backendType == Tracepoint::Field::String) {
+ ret += ", trace::toByteArrayFromCString("_L1 + arg.name + ")"_L1;
+ } else {
+ ret += ", "_L1 + arg.name;
+ }
+ }
return ret;
}
diff --git a/src/tools/tracegen/helpers.h b/src/tools/tracegen/helpers.h
index 4c30eaff0d..ea6db016a6 100644
--- a/src/tools/tracegen/helpers.h
+++ b/src/tools/tracegen/helpers.h
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef HELPERS_H
#define HELPERS_H
@@ -8,14 +8,30 @@
#include <qlist.h>
#include <qstring.h>
+#include <qtextstream.h>
enum ParamType {
LTTNG,
- ETW
+ ETW,
+ CTF
};
+QString typeToTypeName(const QString &type);
QString includeGuard(const QString &filename);
QString formatFunctionSignature(const QList<Tracepoint::Argument> &args);
-QString formatParameterList(const QList<Tracepoint::Argument> &args, ParamType type);
+QString formatParameterList(const Provider &provider, const QList<Tracepoint::Argument> &args, const QList<Tracepoint::Field> &fields, ParamType type);
+
+void writeCommonPrologue(QTextStream &stream);
+
+template <typename T>
+static QString aggregateListValues(int value, const QList<T> &list)
+{
+ QStringList values;
+ for (const T &l : list) {
+ if (l.value == value)
+ values << l.name;
+ }
+ return values.join(QLatin1Char('_'));
+}
#endif // HELPERS_H
diff --git a/src/tools/tracegen/lttng.cpp b/src/tools/tracegen/lttng.cpp
index 46168e3c5a..9711570874 100644
--- a/src/tools/tracegen/lttng.cpp
+++ b/src/tools/tracegen/lttng.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "lttng.h"
#include "provider.h"
@@ -12,23 +12,37 @@
#include <qtextstream.h>
#include <qdebug.h>
-static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field)
+static void writeCtfMacro(QTextStream &stream, const Provider &provider, const Tracepoint::Field &field)
{
const QString &paramType = field.paramType;
const QString &name = field.name;
const QString &seqLen = field.seqLen;
const int arrayLen = field.arrayLen;
- switch (field.backendType) {
- case Tracepoint::Field::Array:
- stream << "ctf_array(" <<paramType << ", "
- << name << ", " << name << ", " << arrayLen << ")";
+ if (arrayLen > 0) {
+ if (paramType == QStringLiteral("double") || paramType == QStringLiteral("float")) {
+ const char *newline = nullptr;
+ for (int i = 0; i < arrayLen; i++) {
+ stream << newline;
+ stream << "ctf_float(" <<paramType << ", " << name << "_" << QString::number(i) << ", "
+ << name << "[" << QString::number(i) << "]" << ")";
+ newline = "\n ";
+ }
+
+ } else {
+ stream << "ctf_array(" <<paramType << ", "
+ << name << ", " << name << ", " << arrayLen << ")";
+ }
return;
+ }
+
+ switch (field.backendType) {
case Tracepoint::Field::Sequence:
stream << "ctf_sequence(" << paramType
<< ", " << name << ", " << name
<< ", unsigned int, " << seqLen << ")";
return;
+ case Tracepoint::Field::Boolean:
case Tracepoint::Field::Integer:
stream << "ctf_integer(" << paramType << ", " << name << ", " << name << ")";
return;
@@ -43,33 +57,51 @@ static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field)
stream << "ctf_string(" << name << ", " << name << ")";
return;
case Tracepoint::Field::QtString:
- stream << "ctf_sequence(const ushort, " << name << ", "
- << name << ".utf16(), unsigned int, " << name << ".size())";
+ stream << "ctf_string(" << name << ", " << name << ".toUtf8().constData())";
return;
case Tracepoint::Field::QtByteArray:
stream << "ctf_sequence(const char, " << name << ", "
<< name << ".constData(), unsigned int, " << name << ".size())";
return;
case Tracepoint::Field::QtUrl:
- stream << "ctf_sequence(const char, " << name << ", "
- << name << ".toEncoded().constData(), unsigned int, "
- << name << ".toEncoded().size())";
+ stream << "ctf_string(" << name << ", " << name << ".toString().toUtf8().constData())";
return;
case Tracepoint::Field::QtRect:
- stream << "ctf_integer(int, x, " << name << ".x()) "
- << "ctf_integer(int, y, " << name << ".y()) "
- << "ctf_integer(int, width, " << name << ".width()) "
- << "ctf_integer(int, height, " << name << ".height()) ";
+ stream << "ctf_integer(int, QRect_" << name << "_x, " << name << ".x()) "
+ << "ctf_integer(int, QRect_" << name << "_y, " << name << ".y()) "
+ << "ctf_integer(int, QRect_" << name << "_width, " << name << ".width()) "
+ << "ctf_integer(int, QRect_" << name << "_height, " << name << ".height()) ";
+ return;
+ case Tracepoint::Field::QtSizeF:
+ stream << "ctf_float(double, QSizeF_" << name << "_width, " << name << ".width()) "
+ << "ctf_float(double, QSizeF_" << name << "_height, " << name << ".height()) ";
+ return;
+ case Tracepoint::Field::QtRectF:
+ stream << "ctf_float(double, QRectF_" << name << "_x, " << name << ".x()) "
+ << "ctf_float(double, QRectF_" << name << "_y, " << name << ".y()) "
+ << "ctf_float(double, QRectF_" << name << "_width, " << name << ".width()) "
+ << "ctf_float(double, QRectF_" << name << "_height, " << name << ".height()) ";
+ return;
+ case Tracepoint::Field::QtSize:
+ stream << "ctf_integer(int, QSize_" << name << "_width, " << name << ".width()) "
+ << "ctf_integer(int, QSize_" << name << "_height, " << name << ".height()) ";
+ return;
+ case Tracepoint::Field::EnumeratedType:
+ stream << "ctf_enum(" << provider.name << ", " << typeToTypeName(paramType) << ", int, " << name << ", " << name << ") ";
+ return;
+ case Tracepoint::Field::FlagType:
+ stream << "ctf_sequence(const char , " << name << ", "
+ << name << ".constData(), unsigned int, " << name << ".size())";
return;
case Tracepoint::Field::Unknown:
- justified_worry("Cannot deduce CTF type for '%s %s'", qPrintable(paramType),
- qPrintable(name));
+ panic("Cannot deduce CTF type for '%s %s", qPrintable(paramType), qPrintable(name));
break;
}
}
static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider)
{
+ writeCommonPrologue(stream);
const QString guard = includeGuard(fileName);
stream << "#undef TRACEPOINT_PROVIDER\n";
@@ -111,12 +143,12 @@ static void writeEpilogue(QTextStream &stream, const QString &fileName)
}
static void writeWrapper(QTextStream &stream,
- const Tracepoint &tracepoint, const QString &providerName)
+ const Tracepoint &tracepoint, const Provider &provider)
{
const QString argList = formatFunctionSignature(tracepoint.args);
- const QString paramList = formatParameterList(tracepoint.args, LTTNG);
+ const QString paramList = formatParameterList(provider, tracepoint.args, tracepoint.fields, LTTNG);
const QString &name = tracepoint.name;
- const QString includeGuard = QStringLiteral("TP_%1_%2").arg(providerName).arg(name).toUpper();
+ const QString includeGuard = QStringLiteral("TP_%1_%2").arg(provider.name).arg(name).toUpper();
/* prevents the redefinion of the inline wrapper functions
* once LTTNG recursively includes this header file
@@ -129,17 +161,17 @@ static void writeWrapper(QTextStream &stream,
stream << "inline void trace_" << name << "(" << argList << ")\n"
<< "{\n"
- << " tracepoint(" << providerName << ", " << name << paramList << ");\n"
+ << " tracepoint(" << provider.name << ", " << name << paramList << ");\n"
<< "}\n";
stream << "inline void do_trace_" << name << "(" << argList << ")\n"
<< "{\n"
- << " do_tracepoint(" << providerName << ", " << name << paramList << ");\n"
+ << " do_tracepoint(" << provider.name << ", " << name << paramList << ");\n"
<< "}\n";
stream << "inline bool trace_" << name << "_enabled()\n"
<< "{\n"
- << " return tracepoint_enabled(" << providerName << ", " << name << ");\n"
+ << " return tracepoint_enabled(" << provider.name << ", " << name << ");\n"
<< "}\n";
stream << "} // namespace QtPrivate\n"
@@ -147,7 +179,7 @@ static void writeWrapper(QTextStream &stream,
<< "#endif // " << includeGuard << "\n\n";
}
-static void writeTracepoint(QTextStream &stream,
+static void writeTracepoint(QTextStream &stream, const Provider &provider,
const Tracepoint &tracepoint, const QString &providerName)
{
stream << "TRACEPOINT_EVENT(\n"
@@ -157,8 +189,13 @@ static void writeTracepoint(QTextStream &stream,
const char *comma = nullptr;
- for (const Tracepoint::Argument &arg : tracepoint.args) {
- stream << comma << arg.type << ", " << arg.name;
+ for (int i = 0; i < tracepoint.args.size(); i++) {
+ const auto &arg = tracepoint.args[i];
+ const auto &field = tracepoint.fields[i];
+ if (field.backendType == Tracepoint::Field::FlagType)
+ stream << comma << "QByteArray, " << arg.name;
+ else
+ stream << comma << arg.type << ", " << arg.name;
comma = ", ";
}
@@ -169,18 +206,82 @@ static void writeTracepoint(QTextStream &stream,
for (const Tracepoint::Field &f : tracepoint.fields) {
stream << newline;
- writeCtfMacro(stream, f);
+ writeCtfMacro(stream, provider, f);
newline = "\n ";
}
stream << ")\n)\n\n";
}
+static void writeEnums(QTextStream &stream, const Provider &provider)
+{
+ for (const auto &e : provider.enumerations) {
+ stream << "TRACEPOINT_ENUM(\n"
+ << " " << provider.name << ",\n"
+ << " " << typeToTypeName(e.name) << ",\n"
+ << " TP_ENUM_VALUES(\n";
+ QList<int> handledValues;
+ for (const auto &v : e.values) {
+ if (v.range > 0) {
+ stream << " ctf_enum_range(\"" << v.name << "\", " << v.value << ", " << v.range << ")\n";
+ } else if (!handledValues.contains(v.value)) {
+ stream << " ctf_enum_value(\"" << aggregateListValues(v.value, e.values) << "\", " << v.value << ")\n";
+ handledValues.append(v.value);
+ }
+ }
+ stream << " )\n)\n\n";
+ }
+}
+
+static void writeFlags(QTextStream &stream, const Provider &provider)
+{
+ for (const auto &f : provider.flags) {
+ stream << "TRACEPOINT_ENUM(\n"
+ << " " << provider.name << ",\n"
+ << " " << typeToTypeName(f.name) << ",\n"
+ << " TP_ENUM_VALUES(\n";
+ QList<int> handledValues;
+ for (const auto &v : f.values) {
+ if (!handledValues.contains(v.value)) {
+ stream << " ctf_enum_value(\"" << aggregateListValues(v.value, f.values) << "\", " << v.value << ")\n";
+ handledValues.append(v.value);
+ }
+ }
+ stream << " )\n)\n\n";
+ }
+
+ // converters
+ const QString includeGuard = QStringLiteral("TP_%1_CONVERTERS").arg(provider.name).toUpper();
+ stream << "\n"
+ << "#ifndef " << includeGuard << "\n"
+ << "#define " << includeGuard << "\n";
+ stream << "QT_BEGIN_NAMESPACE\n";
+ stream << "namespace QtPrivate {\n";
+ for (const auto &f : provider.flags) {
+ stream << "inline QByteArray trace_convert_" << typeToTypeName(f.name) << "(" << f.name << " val)\n";
+ stream << "{\n";
+ stream << " QByteArray ret;\n";
+ stream << " if (val == 0) { ret.append((char)0); return ret; }\n";
+
+ for (const auto &v : f.values) {
+ if (!v.value)
+ continue;
+ stream << " if (val & " << (1 << (v.value - 1)) << ") { ret.append((char)" << v.value << "); };\n";
+ }
+ stream << " return ret;\n";
+ stream << "}\n";
+
+ }
+ stream << "} // namespace QtPrivate\n"
+ << "QT_END_NAMESPACE\n\n"
+ << "#endif // " << includeGuard << "\n\n";
+}
+
static void writeTracepoints(QTextStream &stream, const Provider &provider)
{
for (const Tracepoint &t : provider.tracepoints) {
- writeTracepoint(stream, t, provider.name);
- writeWrapper(stream, t, provider.name);
+ writeTracepoint(stream, provider, t, provider.name);
+ writeWrapper(stream, t, provider);
}
}
@@ -191,6 +292,9 @@ void writeLttng(QFile &file, const Provider &provider)
const QString fileName = QFileInfo(file.fileName()).fileName();
writePrologue(stream, fileName, provider);
+ writeEnums(stream, provider);
+ writeFlags(stream, provider);
writeTracepoints(stream, provider);
writeEpilogue(stream, fileName);
}
+
diff --git a/src/tools/tracegen/lttng.h b/src/tools/tracegen/lttng.h
index d8fbd1291e..c36c70a1d4 100644
--- a/src/tools/tracegen/lttng.h
+++ b/src/tools/tracegen/lttng.h
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef LTTNG_H
#define LTTNG_H
diff --git a/src/tools/tracegen/panic.cpp b/src/tools/tracegen/panic.cpp
index aca816aa7a..fa4e6b3ee3 100644
--- a/src/tools/tracegen/panic.cpp
+++ b/src/tools/tracegen/panic.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "panic.h"
@@ -21,16 +21,3 @@ void panic(const char *fmt, ...)
exit(EXIT_FAILURE);
}
-
-void justified_worry(const char *fmt, ...)
-{
- va_list ap;
-
- fprintf(stderr, "tracegen: warning: ");
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- fputc('\n', stderr);
-}
diff --git a/src/tools/tracegen/panic.h b/src/tools/tracegen/panic.h
index d44d2b4e12..ee635a8aeb 100644
--- a/src/tools/tracegen/panic.h
+++ b/src/tools/tracegen/panic.h
@@ -1,10 +1,9 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef PANIC_H
#define PANIC_H
void panic(const char *fmt, ...);
-void justified_worry(const char *fmt, ...);
#endif // PANIC_H
diff --git a/src/tools/tracegen/provider.cpp b/src/tools/tracegen/provider.cpp
index 11322e951c..bdd669c9cd 100644
--- a/src/tools/tracegen/provider.cpp
+++ b/src/tools/tracegen/provider.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "provider.h"
#include "panic.h"
@@ -9,6 +9,7 @@
#include <qtextstream.h>
#include <qregularexpression.h>
#include <qstring.h>
+#include <qtpreprocessorsupport.h>
using namespace Qt::StringLiterals;
@@ -95,46 +96,53 @@ static QString removeBraces(QString type)
return type.remove(rx);
}
-static Tracepoint::Field::BackendType backendType(QString rawType)
+#define TYPEDATA_ENTRY(type, backendType) \
+{ QT_STRINGIFY(type), backendType }
+
+static Tracepoint::Field::Type backendType(QString rawType)
{
- static const struct {
+ static const struct TypeData {
const char *type;
- Tracepoint::Field::BackendType backendType;
+ Tracepoint::Field::Type backendType;
} typeTable[] = {
- { "bool", Tracepoint::Field::Integer },
- { "short_int", Tracepoint::Field::Integer },
- { "signed_short", Tracepoint::Field::Integer },
- { "signed_short_int", Tracepoint::Field::Integer },
- { "unsigned_short", Tracepoint::Field::Integer },
- { "unsigned_short_int", Tracepoint::Field::Integer },
- { "int", Tracepoint::Field::Integer },
- { "signed", Tracepoint::Field::Integer },
- { "signed_int", Tracepoint::Field::Integer },
- { "unsigned", Tracepoint::Field::Integer },
- { "unsigned_int", Tracepoint::Field::Integer },
- { "long", Tracepoint::Field::Integer },
- { "long_int", Tracepoint::Field::Integer },
- { "signed_long", Tracepoint::Field::Integer },
- { "signed_long_int", Tracepoint::Field::Integer },
- { "unsigned_long", Tracepoint::Field::Integer },
- { "unsigned_long_int", Tracepoint::Field::Integer },
- { "long_long", Tracepoint::Field::Integer },
- { "long_long_int", Tracepoint::Field::Integer },
- { "signed_long_long", Tracepoint::Field::Integer },
- { "signed_long_long_int", Tracepoint::Field::Integer },
- { "unsigned_long_long", Tracepoint::Field::Integer },
- { "char", Tracepoint::Field::Integer },
- { "intptr_t", Tracepoint::Field::IntegerHex },
- { "uintptr_t", Tracepoint::Field::IntegerHex },
- { "std::intptr_t", Tracepoint::Field::IntegerHex },
- { "std::uintptr_t", Tracepoint::Field::IntegerHex },
- { "float", Tracepoint::Field::Float },
- { "double", Tracepoint::Field::Float },
- { "long_double", Tracepoint::Field::Float },
- { "QString", Tracepoint::Field::QtString },
- { "QByteArray", Tracepoint::Field::QtByteArray },
- { "QUrl", Tracepoint::Field::QtUrl },
- { "QRect", Tracepoint::Field::QtRect }
+ TYPEDATA_ENTRY(short_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_short, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_short_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned_short, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned_short_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(long_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_long, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_long_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned_long, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned_long_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(long_long, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(long_long_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_long_long, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed_long_long_int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned_long_long, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(bool, Tracepoint::Field::Boolean),
+ TYPEDATA_ENTRY(int, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(signed, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(unsigned, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(long, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(qint64, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(char, Tracepoint::Field::Integer),
+ TYPEDATA_ENTRY(intptr_t, Tracepoint::Field::IntegerHex),
+ TYPEDATA_ENTRY(uintptr_t, Tracepoint::Field::IntegerHex),
+ TYPEDATA_ENTRY(std::intptr_t, Tracepoint::Field::IntegerHex),
+ TYPEDATA_ENTRY(std::uintptr_t, Tracepoint::Field::IntegerHex),
+ TYPEDATA_ENTRY(float, Tracepoint::Field::Float),
+ TYPEDATA_ENTRY(double, Tracepoint::Field::Float),
+ TYPEDATA_ENTRY(long double, Tracepoint::Field::Float),
+ TYPEDATA_ENTRY(QString, Tracepoint::Field::QtString),
+ TYPEDATA_ENTRY(QByteArray, Tracepoint::Field::QtByteArray),
+ TYPEDATA_ENTRY(QUrl, Tracepoint::Field::QtUrl),
+ TYPEDATA_ENTRY(QRect, Tracepoint::Field::QtRect),
+ TYPEDATA_ENTRY(QSize, Tracepoint::Field::QtSize),
+ TYPEDATA_ENTRY(QRectF, Tracepoint::Field::QtRectF),
+ TYPEDATA_ENTRY(QSizeF, Tracepoint::Field::QtSizeF)
};
auto backendType = [](const QString &rawType) {
@@ -142,14 +150,16 @@ static Tracepoint::Field::BackendType backendType(QString rawType)
for (size_t i = 0; i < tableSize; ++i) {
if (rawType == QLatin1StringView(typeTable[i].type))
- return typeTable[i].backendType;
+ return typeTable[i];
}
- return Tracepoint::Field::Unknown;
+ TypeData unknown = { nullptr, Tracepoint::Field::Unknown };
+ return unknown;
};
- if (arrayLength(rawType) > 0)
- return Tracepoint::Field::Array;
+ int arrayLen = arrayLength(rawType);
+ if (arrayLen > 0)
+ rawType = removeBraces(rawType);
if (!sequenceLength(rawType).isNull())
return Tracepoint::Field::Sequence;
@@ -169,15 +179,32 @@ static Tracepoint::Field::BackendType backendType(QString rawType)
if (rawType.endsWith("_ptr"_L1))
return Tracepoint::Field::Pointer;
- return backendType(rawType);
+ TypeData d = backendType(rawType);
+ return d.backendType;
}
-static Tracepoint parseTracepoint(const QString &name, const QStringList &args,
+static Tracepoint parseTracepoint(const Provider &provider, const QString &name, const QStringList &args,
const QString &fileName, const int lineNumber)
{
Tracepoint t;
t.name = name;
+ auto findEnumeration = [](const QList<TraceEnum> &enums, const QString &name) {
+ for (const auto &e : enums) {
+ if (e.name == name)
+ return e;
+ }
+ return TraceEnum();
+ };
+ auto findFlags = [](const QList<TraceFlags> &flags, const QString &name) {
+ for (const auto &f : flags) {
+ if (f.name == name)
+ return f;
+ }
+ return TraceFlags();
+ };
+
+
if (args.isEmpty())
return t;
@@ -213,14 +240,23 @@ static Tracepoint parseTracepoint(const QString &name, const QStringList &args,
t.args << std::move(a);
- Tracepoint::Field f;
- f.backendType = backendType(type);
- f.paramType = removeBraces(type);
- f.name = name;
- f.arrayLen = arrayLen;
- f.seqLen = sequenceLength(type);
+ Tracepoint::Field field;
+ const TraceEnum &e = findEnumeration(provider.enumerations, type);
+ const TraceFlags &f = findFlags(provider.flags, type);
+ if (!e.name.isEmpty()) {
+ field.backendType = Tracepoint::Field::EnumeratedType;
+ field.enumValueSize = e.valueSize;
+ } else if (!f.name.isEmpty()) {
+ field.backendType = Tracepoint::Field::FlagType;
+ } else {
+ field.backendType = backendType(type);
+ }
+ field.paramType = removeBraces(type);
+ field.name = name;
+ field.arrayLen = arrayLen;
+ field.seqLen = sequenceLength(type);
- t.fields << std::move(f);
+ t.fields << std::move(field);
++i;
}
@@ -228,6 +264,31 @@ static Tracepoint parseTracepoint(const QString &name, const QStringList &args,
return t;
}
+static int minumumValueSize(int min, int max)
+{
+ if (min < 0) {
+ if (min >= std::numeric_limits<char>::min() && max <= std::numeric_limits<char>::max())
+ return 8;
+ if (min >= std::numeric_limits<short>::min() && max <= std::numeric_limits<short>::max())
+ return 16;
+ return 32;
+ }
+ if (max <= std::numeric_limits<unsigned char>::max())
+ return 8;
+ if (max <= std::numeric_limits<unsigned short>::max())
+ return 16;
+ return 32;
+}
+
+static bool isPow2OrZero(quint32 value)
+{
+ return (value & (value - 1)) == 0;
+}
+
+static quint32 pow2Log2(quint32 v) {
+ return 32 - qCountLeadingZeroBits(v);
+}
+
Provider parseProvider(const QString &filename)
{
QFile f(filename);
@@ -238,11 +299,21 @@ Provider parseProvider(const QString &filename)
QTextStream s(&f);
static const QRegularExpression tracedef(QStringLiteral("^([A-Za-z][A-Za-z0-9_]*)\\((.*)\\)$"));
+ static const QRegularExpression enumenddef(QStringLiteral("^} ?([A-Za-z][A-Za-z0-9_:]*);"));
+ static const QRegularExpression enumdef(QStringLiteral("^([A-Za-z][A-Za-z0-9_]*)( *= *([xabcdef0-9]*))?"));
+ static const QRegularExpression rangedef(QStringLiteral("^RANGE\\(([A-Za-z][A-Za-z0-9_]*) ?, ?([0-9]*) ?... ?([0-9]*) ?\\)"));
Provider provider;
provider.name = QFileInfo(filename).baseName();
bool parsingPrefixText = false;
+ bool parsingEnum = false;
+ bool parsingFlags = false;
+ TraceEnum currentEnum;
+ TraceFlags currentFlags;
+ int currentEnumValue = 0;
+ int minEnumValue = std::numeric_limits<int>::max();
+ int maxEnumValue = std::numeric_limits<int>::min();
for (int lineNumber = 1; !s.atEnd(); ++lineNumber) {
QString line = s.readLine().trimmed();
@@ -255,18 +326,113 @@ Provider parseProvider(const QString &filename)
} else if (parsingPrefixText) {
provider.prefixText.append(line);
continue;
+ } else if (line == "ENUM {"_L1) {
+ parsingEnum = true;
+ continue;
+ } else if (line == "FLAGS {"_L1) {
+ parsingFlags = true;
+ continue;
+ } else if (line.startsWith("}"_L1) && (parsingEnum || parsingFlags)) {
+ auto match = enumenddef.match(line);
+ if (match.hasMatch()) {
+ if (parsingEnum) {
+ currentEnum.name = match.captured(1);
+ currentEnum.valueSize = minumumValueSize(minEnumValue, maxEnumValue);
+ provider.enumerations.push_back(currentEnum);
+ currentEnum = TraceEnum();
+ parsingEnum = false;
+ } else {
+ currentFlags.name = match.captured(1);
+ provider.flags.push_back(currentFlags);
+ currentFlags = TraceFlags();
+ parsingFlags = false;
+ }
+
+ minEnumValue = std::numeric_limits<int>::max();
+ maxEnumValue = std::numeric_limits<int>::min();
+ } else {
+ panic("Syntax error while processing '%s' line %d:\n"
+ " '%s' end of enum/flags does not match",
+ qPrintable(filename), lineNumber,
+ qPrintable(line));
+ }
+
+ continue;
}
if (line.isEmpty() || line.startsWith(u'#'))
continue;
+ if (parsingEnum || parsingFlags) {
+ auto m = enumdef.match(line);
+ if (parsingEnum && line.startsWith(QStringLiteral("RANGE"))) {
+ auto m = rangedef.match(line);
+ if (m.hasMatch()) {
+ TraceEnum::EnumValue value;
+ value.name = m.captured(1);
+ value.value = m.captured(2).toInt();
+ value.range = m.captured(3).toInt();
+ currentEnumValue = value.range + 1;
+ currentEnum.values.push_back(value);
+ maxEnumValue = qMax(maxEnumValue, value.range);
+ minEnumValue = qMin(minEnumValue, value.value);
+ }
+ } else if (m.hasMatch()) {
+ if (m.hasCaptured(3)) {
+ if (parsingEnum) {
+ TraceEnum::EnumValue value;
+ value.name = m.captured(1);
+ value.value = m.captured(3).toInt();
+ value.range = 0;
+ currentEnumValue = value.value + 1;
+ currentEnum.values.push_back(value);
+ maxEnumValue = qMax(maxEnumValue, value.value);
+ minEnumValue = qMin(minEnumValue, value.value);
+ } else {
+ TraceFlags::FlagValue value;
+ value.name = m.captured(1);
+ if (m.captured(3).startsWith(QStringLiteral("0x")))
+ value.value = m.captured(3).toInt(nullptr, 16);
+ else
+ value.value = m.captured(3).toInt();
+ if (!isPow2OrZero(value.value)) {
+ printf("Warning: '%s' line %d:\n"
+ " '%s' flag value is not power of two.\n",
+ qPrintable(filename), lineNumber,
+ qPrintable(line));
+ } else {
+ value.value = pow2Log2(value.value);
+ currentFlags.values.push_back(value);
+ }
+ }
+ } else {
+ maxEnumValue = qMax(maxEnumValue, currentEnumValue);
+ minEnumValue = qMin(minEnumValue, currentEnumValue);
+ if (parsingEnum) {
+ currentEnum.values.push_back({m.captured(0), currentEnumValue++, 0});
+ } else {
+ panic("Syntax error while processing '%s' line %d:\n"
+ " '%s' flags value not set",
+ qPrintable(filename), lineNumber,
+ qPrintable(line));
+ }
+ }
+ } else {
+ panic("Syntax error while processing '%s' line %d:\n"
+ " '%s' enum/flags does not match",
+ qPrintable(filename), lineNumber,
+ qPrintable(line));
+ }
+ continue;
+ }
+
auto match = tracedef.match(line);
if (match.hasMatch()) {
const QString name = match.captured(1);
const QString argsString = match.captured(2);
const QStringList args = argsString.split(u',', Qt::SkipEmptyParts);
- provider.tracepoints << parseTracepoint(name, args, filename, lineNumber);
+ provider.tracepoints << parseTracepoint(provider, name, args, filename, lineNumber);
} else {
panic("Syntax error while processing '%s' line %d:\n"
" '%s' does not look like a tracepoint definition",
diff --git a/src/tools/tracegen/provider.h b/src/tools/tracegen/provider.h
index 28bbb75959..e5e99b868e 100644
--- a/src/tools/tracegen/provider.h
+++ b/src/tools/tracegen/provider.h
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef PROVIDER_H
#define PROVIDER_H
@@ -20,9 +20,9 @@ struct Tracepoint
struct Field
{
- enum BackendType {
- Array,
+ enum Type {
Sequence,
+ Boolean,
Integer,
IntegerHex,
Float,
@@ -32,13 +32,18 @@ struct Tracepoint
QtByteArray,
QtUrl,
QtRect,
+ QtSize,
+ QtRectF,
+ QtSizeF,
+ EnumeratedType,
+ FlagType,
Unknown
};
-
- BackendType backendType;
+ Type backendType;
QString paramType;
QString name;
int arrayLen;
+ int enumValueSize;
QString seqLen;
};
@@ -47,17 +52,41 @@ struct Tracepoint
QList<Field> fields;
};
+struct TraceEnum {
+ QString name;
+ struct EnumValue {
+ QString name;
+ int value;
+ int range;
+ };
+ QList<EnumValue> values;
+ int valueSize;
+};
+
+struct TraceFlags {
+ QString name;
+ struct FlagValue {
+ QString name;
+ int value;
+ };
+ QList<FlagValue> values;
+};
+
+Q_DECLARE_TYPEINFO(TraceEnum, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(TraceFlags, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracepoint::Argument, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracepoint::Field, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracepoint, Q_RELOCATABLE_TYPE);
+
struct Provider
{
QString name;
QList<Tracepoint> tracepoints;
QStringList prefixText;
+ QList<TraceEnum> enumerations;
+ QList<TraceFlags> flags;
};
Provider parseProvider(const QString &filename);
-Q_DECLARE_TYPEINFO(Tracepoint::Argument, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(Tracepoint::Field, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(Tracepoint, Q_RELOCATABLE_TYPE);
-
#endif // PROVIDER_H
diff --git a/src/tools/tracegen/qtheaders.cpp b/src/tools/tracegen/qtheaders.cpp
index a65ece5c5b..237c22b237 100644
--- a/src/tools/tracegen/qtheaders.cpp
+++ b/src/tools/tracegen/qtheaders.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "qtheaders.h"
diff --git a/src/tools/tracegen/qtheaders.h b/src/tools/tracegen/qtheaders.h
index 6be4d15f4a..86405c9479 100644
--- a/src/tools/tracegen/qtheaders.h
+++ b/src/tools/tracegen/qtheaders.h
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef QTHEADERS_H
#define QTHEADERS_H
diff --git a/src/tools/tracegen/tracegen.cpp b/src/tools/tracegen/tracegen.cpp
index 6a5f3286a9..776d81675d 100644
--- a/src/tools/tracegen/tracegen.cpp
+++ b/src/tools/tracegen/tracegen.cpp
@@ -1,7 +1,8 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "provider.h"
+#include "ctf.h"
#include "lttng.h"
#include "etw.h"
#include "panic.h"
@@ -12,12 +13,13 @@
enum class Target
{
LTTNG,
- ETW
+ ETW,
+ CTF,
};
static inline void usage(int status)
{
- printf("Usage: tracegen <lttng|etw> <input file> <output file>\n");
+ printf("Usage: tracegen <lttng|etw|ctf> <input file> <output file>\n");
exit(status);
}
@@ -34,6 +36,8 @@ static void parseArgs(int argc, char *argv[], Target *target, QString *inFile, Q
*target = Target::LTTNG;
} else if (qstrcmp(targetString, "etw") == 0) {
*target = Target::ETW;
+ } else if (qstrcmp(targetString, "ctf") == 0) {
+ *target = Target::CTF;
} else {
fprintf(stderr, "Invalid target: %s\n", targetString);
usage(EXIT_FAILURE);
@@ -61,6 +65,9 @@ int main(int argc, char *argv[])
}
switch (target) {
+ case Target::CTF:
+ writeCtf(out, p);
+ break;
case Target::LTTNG:
writeLttng(out, p);
break;