diff --git a/config_help.txt b/config_help.txt index 08c2e7627f..5c57e30d63 100644 --- a/config_help.txt +++ b/config_help.txt @@ -119,6 +119,11 @@ Build options: -testcocoon .......... Instrument with the TestCocoon code coverage tool [no] -gcov ................ Instrument with the GCov code coverage tool [no] + + -trace [backend] ..... Enable instrumentation with tracepoints. + Currently supported backends are 'etw' (Windows) and + 'lttng' (Linux), or 'yes' for auto-detection. [no] + -sanitize {address|thread|memory|undefined} Instrument with the specified compiler sanitizer. diff --git a/mkspecs/features/exclusive_builds.prf b/mkspecs/features/exclusive_builds.prf index f40cc99172..b477cff162 100644 --- a/mkspecs/features/exclusive_builds.prf +++ b/mkspecs/features/exclusive_builds.prf @@ -38,5 +38,5 @@ defineTest(addExclusiveBuilds) { } # Default directories to process -QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR -QMAKE_DIR_REPLACE_SANE += QGLTF_DIR +QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR TRACEGEN_DIR +QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR diff --git a/mkspecs/features/qt_build_config.prf b/mkspecs/features/qt_build_config.prf index 76e1d15319..a2fa1be481 100644 --- a/mkspecs/features/qt_build_config.prf +++ b/mkspecs/features/qt_build_config.prf @@ -25,6 +25,7 @@ OBJECTS_DIR = .obj MOC_DIR = .moc RCC_DIR = .rcc UI_DIR = .uic +TRACEGEN_DIR = .tracegen intel_icl { # ICL 14.0 has a bug that makes it not find #includes in dirs starting with . MOC_DIR = tmp/moc diff --git a/mkspecs/features/qt_tracepoints.prf b/mkspecs/features/qt_tracepoints.prf new file mode 100644 index 0000000000..d1b45a47cb --- /dev/null +++ b/mkspecs/features/qt_tracepoints.prf @@ -0,0 +1,54 @@ +# W A R N I N G +# ------------- +# +# This file is not part of the Qt API. It exists purely as an +# implementation detail. It may change from version to version +# without notice, or even be removed. +# +# We mean it. +# + +qtPrepareTool(QMAKE_TRACEGEN, tracegen) + +isEmpty(TRACEGEN_DIR): TRACEGEN_DIR = . + +PROVIDER_NAME = qt$$lower($$MODULE) +INCLUDEPATH += $$absolute_path($$TRACEGEN_DIR, $$OUT_PWD) +HEADER_PATH = $$OUT_PWD/$$TRACEGEN_DIR/$${PROVIDER_NAME}_tracepoints_p$${first(QMAKE_EXT_H)} + +!force_bootstrap:if(qtConfig(lttng)|qtConfig(etw)) { + SOURCE_PATH = $$OUT_PWD/$$TRACEGEN_DIR/$${PROVIDER_NAME}_tracepoints$${first(QMAKE_EXT_CPP)} + + isEmpty(BUILDS)|build_pass { + impl_file_contents = \ + "$${LITERAL_HASH}define TRACEPOINT_CREATE_PROBES" \ + "$${LITERAL_HASH}define TRACEPOINT_DEFINE" \ + "$${LITERAL_HASH}include \"$${HEADER_PATH}\"" + + write_file($$SOURCE_PATH, impl_file_contents)|error() + } + + GENERATED_SOURCES += $$SOURCE_PATH + + tracegen.input = TRACEPOINT_PROVIDER + tracegen.output = $$HEADER_PATH + tracegen.variable_out = HEADERS + tracegen.depends += $$QMAKE_TRACEGEN_EXE + tracegen.CONFIG = target_predeps + + qtConfig(lttng) { + tracegen.commands = $$QMAKE_TRACEGEN lttng ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} + QMAKE_USE_PRIVATE += lttng-ust + } else { + tracegen.commands = $$QMAKE_TRACEGEN etw ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} + } + + QMAKE_EXTRA_COMPILERS += tracegen + + DEFINES += Q_TRACEPOINT +} else { + isEmpty(BUILDS)|build_pass { + header_file_contents = "$${LITERAL_HASH}include " + write_file($$HEADER_PATH, header_file_contents)|error() + } +} diff --git a/src/corelib/configure.json b/src/corelib/configure.json index 8cd73d6ce4..9f9512942a 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -15,7 +15,8 @@ "posix-ipc": { "type": "boolean", "name": "ipc_posix" }, "pps": { "type": "boolean", "name": "qqnx_pps" }, "slog2": "boolean", - "syslog": "boolean" + "syslog": "boolean", + "trace": { "type": "optionalString", "values": [ "etw", "lttng", "no", "yes" ] } } }, @@ -147,6 +148,18 @@ "-lrt" ] }, + "lttng-ust": { + "label": "lttng-ust", + "test": { + "include": "lttng/ust-events.h", + "main": "lttng_session_destroy(nullptr);" + }, + "sources": [ + { "type": "pkgConfig", "args": "lttng-ust" }, + "-llttng-ust" + ], + "use": "libdl" + }, "pcre2": { "label": "PCRE2", "test": { @@ -858,6 +871,22 @@ "section": "Utilities", "output": [ "publicFeature" ] }, + "lttng": { + "label": "LTTNG", + "autoDetect": false, + "enable": "input.trace == 'lttng' || (input.trace =='yes' && config.linux)", + "disable": "input.trace == 'etw' || input.trace =='no'", + "condition": "config.linux && libs.lttng-ust", + "output": [ "privateFeature" ] + }, + "etw": { + "label": "ETW", + "autoDetect": false, + "enable": "input.trace == 'etw' || (input.trace == 'yes' && config.win32)", + "disable": "input.trace == 'lttng' || input.trace == 'no'", + "condition": "config.win32", + "output": [ "privateFeature" ] + }, "topleveldomain": { "label": "QUrl::topLevelDomain()", "purpose": "Provides support for extracting the top level domain from URLs. @@ -907,6 +936,11 @@ Please apply the patch corresponding to your Standard Library vendor, found in "glib", "iconv", "icu", + { + "message": "Tracing backend", + "type": "firstAvailableFeature", + "args": "etw lttng" + }, { "section": "Logging backends", "entries": [ diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index 4cce7c0df3..2079d2117f 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -6,6 +6,9 @@ MODULE = core # not corelib, as per project file MODULE_CONFIG = moc resources !isEmpty(QT_NAMESPACE): MODULE_DEFINES = QT_NAMESPACE=$$QT_NAMESPACE +TRACEPOINT_PROVIDER = $$PWD/qtcore.tracepoints +CONFIG += qt_tracepoints + CONFIG += $$MODULE_CONFIG DEFINES += $$MODULE_DEFINES DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h index 0df593941d..86ef1a2613 100644 --- a/src/corelib/global/qconfig-bootstrapped.h +++ b/src/corelib/global/qconfig-bootstrapped.h @@ -78,6 +78,7 @@ #define QT_FEATURE_cxx11_random (QT_HAS_INCLUDE() ? 1 : -1) #define QT_NO_DATASTREAM #define QT_FEATURE_datetimeparser -1 +#define QT_FEATURE_etw -1 #define QT_FEATURE_getauxval (QT_HAS_INCLUDE() ? 1 : -1) #define QT_FEATURE_getentropy -1 #define QT_NO_GEOM_VARIANT @@ -92,6 +93,7 @@ #else # define QT_FEATURE_linkat -1 #endif +#define QT_FEATURE_lttng -1 #define QT_NO_QOBJECT #define QT_FEATURE_process -1 #define QT_FEATURE_regularexpression -1 diff --git a/src/corelib/global/qtrace_p.h b/src/corelib/global/qtrace_p.h new file mode 100644 index 0000000000..ab8fc14af5 --- /dev/null +++ b/src/corelib/global/qtrace_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTRACE_P_H +#define QTRACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +/* + * The Qt tracepoints API consists of only three macros: + * + * - Q_TRACE(tracepoint, args...) + * Fires 'tracepoint' if it is enabled. + * + * - Q_UNCONDITIONAL_TRACE(tracepoint, args...) + * Fires 'tracepoint' unconditionally: no check is performed to query + * whether 'tracepoint' is enabled. + * + * - Q_TRACE_ENABLED(tracepoint) + * Returns 'true' if 'tracepoint' is enabled; false otherwise. + * + * When using LTTNG, Q_TRACE, Q_UNCONDITIONAL_TRACE and Q_TRACE_ENABLED map + * ultimately to tracepoint(), do_tracepoint() and tracepoint_enabled(), + * respectively, described on the lttng-ust manpage (man 3 lttng-ust). + * + * On ETW, Q_TRACE() and Q_UNCONDITIONAL_TRACE() are equivalent, ultimately + * amounting to a call to TraceLoggingWrite(), whereas Q_TRACE_ENABLED() + * wraps around TraceLoggingProviderEnabled(). + * + * A tracepoint provider is defined in a separate file, that follows the + * following format: + * + * tracepoint_name(arg_type arg_name, ...) + * + * For instance: + * + * qcoreapplication_ctor(int argc, const char * const argv) + * qcoreapplication_foo(int argc, const char[10] argv) + * qcoreapplication_baz(const char[len] some_string, unsigned int len) + * qcoreapplication_qstring(const QString &foo) + * qcoreapplication_qrect(const QRect &rect) + * + * The provider file is then parsed by src/tools/tracegen, which can be + * switched to output either ETW or LTTNG tracepoint definitions. The provider + * name is deduced to be basename(provider_file). + * + * To use the above (inside qtcore), you need to include + * . After that, the following call becomes + * possible: + * + * Q_TRACE(qcoreapplication_qrect, myRect); + * + * Currently, all C++ primitive non-pointer types are supported for + * arguments. Additionally, char * is supported, and is assumed to + * be a NULL-terminated string. Finally, the following subset of Qt types also + * currently supported: + * + * - QString + * - QByteArray + * - QUrl + * - QRect + * + * Dynamic arrays are supported using the syntax illustrated by + * qcoreapplication_baz above. + */ + +QT_BEGIN_NAMESPACE + +#if defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED) +# define Q_TRACE(x, ...) QtPrivate::trace_ ## x(__VA_ARGS__) +# define Q_UNCONDITIONAL_TRACE(x, ...) QtPrivate::do_trace_ ## x(__VA_ARGS__) +# define Q_TRACE_ENABLED(x) QtPrivate::trace_ ## x ## _enabled() +#else +# define Q_TRACE(x, ...) +# define Q_UNCONDITIONAL_TRACE(x, ...) +# define Q_TRACE_ENABLED(x) false +#endif // defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED) + +QT_END_NAMESPACE + +#endif // QTRACE_P_H diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e93a14c116..4bab0b9f01 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -116,6 +116,12 @@ # include #endif +#ifdef QT_BOOTSTRAPPED +#include +#else +#include +#endif + #include QT_BEGIN_NAMESPACE @@ -790,6 +796,8 @@ QCoreApplication::QCoreApplication(int &argc, char **argv void QCoreApplicationPrivate::init() { + Q_TRACE(qcoreapplicationprivate_init_entry); + #if defined(Q_OS_MACOS) QMacAutoReleasePool pool; #endif @@ -873,6 +881,8 @@ void QCoreApplicationPrivate::init() #ifndef QT_NO_QOBJECT is_app_running = true; // No longer starting up. #endif + + Q_TRACE(qcoreapplicationprivate_init_exit); } /*! diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index 0cc193c325..a4be18a67f 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -54,6 +54,8 @@ #include "qjsonobject.h" #include "qjsonarray.h" +#include + QT_BEGIN_NAMESPACE class QFactoryLoaderPrivate : public QObjectPrivate @@ -142,6 +144,9 @@ void QFactoryLoader::update() if (qt_debug_component()) { qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName; } + + Q_TRACE(qfactoryloader_update, fileName); + library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath()); if (!library->isPlugin()) { if (qt_debug_component()) { diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index ebad7f1751..bca6918b4a 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -64,6 +64,8 @@ #include "qelfparser_p.h" #include "qmachparser_p.h" +#include + QT_BEGIN_NAMESPACE #ifdef QT_NO_DEBUG @@ -535,6 +537,8 @@ bool QLibraryPrivate::load() if (fileName.isEmpty()) return false; + Q_TRACE(qlibraryprivate_load_entry, fileName); + bool ret = load_sys(); if (qt_debug_component()) { if (ret) { @@ -551,6 +555,8 @@ bool QLibraryPrivate::load() installCoverageTool(this); } + Q_TRACE(qlibraryprivate_load_exit, ret); + return ret; } diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp index 3a1c0495fe..5dfbf23c33 100644 --- a/src/corelib/plugin/quuid.cpp +++ b/src/corelib/plugin/quuid.cpp @@ -143,7 +143,6 @@ static QUuid _q_uuidFromHex(const char *src) return QUuid(); } -#ifndef QT_BOOTSTRAPPED static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCryptographicHash::Algorithm algorithm, int version) { QByteArray hashResult; @@ -166,7 +165,6 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto return result; } -#endif /*! \class QUuid @@ -488,12 +486,12 @@ QUuid QUuid::createUuidV3(const QUuid &ns, const QByteArray &baseData) { return createFromName(ns, baseData, QCryptographicHash::Md5, 3); } +#endif QUuid QUuid::createUuidV5(const QUuid &ns, const QByteArray &baseData) { return createFromName(ns, baseData, QCryptographicHash::Sha1, 5); } -#endif /*! Creates a QUuid object from the binary representation of the UUID, as diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h index ee0a9f9dac..014b69831e 100644 --- a/src/corelib/plugin/quuid.h +++ b/src/corelib/plugin/quuid.h @@ -192,18 +192,20 @@ public: static QUuid createUuid(); #ifndef QT_BOOTSTRAPPED static QUuid createUuidV3(const QUuid &ns, const QByteArray &baseData); +#endif static QUuid createUuidV5(const QUuid &ns, const QByteArray &baseData); +#ifndef QT_BOOTSTRAPPED static inline QUuid createUuidV3(const QUuid &ns, const QString &baseData) { return QUuid::createUuidV3(ns, baseData.toUtf8()); } +#endif static inline QUuid createUuidV5(const QUuid &ns, const QString &baseData) { return QUuid::createUuidV5(ns, baseData.toUtf8()); } -#endif QUuid::Variant variant() const Q_DECL_NOTHROW; QUuid::Version version() const Q_DECL_NOTHROW; diff --git a/src/corelib/qtcore.tracepoints b/src/corelib/qtcore.tracepoints new file mode 100644 index 0000000000..e6b666ac74 --- /dev/null +++ b/src/corelib/qtcore.tracepoints @@ -0,0 +1,5 @@ +qcoreapplicationprivate_init_entry() +qcoreapplicationprivate_init_exit() +qfactoryloader_update(const QString &fileName) +qlibraryprivate_load_entry(const QString &fileName) +qlibraryprivate_load_exit(bool success) diff --git a/src/gui/gui.pro b/src/gui/gui.pro index f8cec00b82..759d6f3cbf 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -95,3 +95,6 @@ qtConfig(angle) { qtConfig(egl): CMAKE_EGL_INCDIRS = $$cmakePortablePaths($$QMAKE_INCDIR_EGL) QMAKE_DYNAMIC_LIST_FILE = $$PWD/QtGui.dynlist + +TRACEPOINT_PROVIDER = $$PWD/qtgui.tracepoints +CONFIG += qt_tracepoints diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 3d85f47f34..70b4869442 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -111,6 +111,8 @@ # include #endif // Q_OS_WIN +#include + #include QT_BEGIN_NAMESPACE @@ -1360,6 +1362,8 @@ void QGuiApplicationPrivate::eventDispatcherReady() void QGuiApplicationPrivate::init() { + Q_TRACE(qguiapplicationprivate_init_entry); + #if defined(Q_OS_MACOS) QMacAutoReleasePool pool; #endif @@ -1522,6 +1526,8 @@ void QGuiApplicationPrivate::init() if (!QGuiApplicationPrivate::displayName) QObject::connect(q, &QGuiApplication::applicationNameChanged, q, &QGuiApplication::applicationDisplayNameChanged); + + Q_TRACE(qguiapplicationprivate_init_exit); } extern void qt_cleanupFontDatabase(); @@ -1756,6 +1762,8 @@ bool QGuiApplicationPrivate::processNativeEvent(QWindow *window, const QByteArra void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e) { + Q_TRACE(qguiapplicationprivate_processwsevents_entry, e->type); + switch(e->type) { case QWindowSystemInterfacePrivate::Mouse: QGuiApplicationPrivate::processMouseEvent(static_cast(e)); @@ -1864,6 +1872,8 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv qWarning() << "Unknown user input event type:" << e->type; break; } + + Q_TRACE(qguiapplicationprivate_processwsevents_exit, e->type); } /*! \internal diff --git a/src/gui/qtgui.tracepoints b/src/gui/qtgui.tracepoints new file mode 100644 index 0000000000..aa8a8ede57 --- /dev/null +++ b/src/gui/qtgui.tracepoints @@ -0,0 +1,8 @@ +qfontdatabase_addapplicationfont(const QString &filename) +qfontdatabase_load(const QString &family, int pointSize) +qfontdatabase_loadengine(const QString &family, int pointSize) +qfontdatabaseprivate_addappfont(const QString &fileName) +qguiapplicationprivate_init_entry() +qguiapplicationprivate_init_exit() +qguiapplicationprivate_processwsevents_entry(int type) +qguiapplicationprivate_processwsevents_exit(int type) diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 4be2197c68..404a722e29 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -74,6 +74,7 @@ # define FM_DEBUG if (false) qDebug #endif +#include QT_BEGIN_NAMESPACE @@ -1009,6 +1010,8 @@ QFontEngine *loadEngine(int script, const QFontDef &request, QFontEngine *engine = loadSingleEngine(script, request, family, foundry, style, size); if (engine && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) { + Q_TRACE(qfontdatabase_loadengine, request.family, request.pointSize); + QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); QFontEngineMulti *pfMultiEngine = pfdb->fontEngineMulti(engine, QChar::Script(script)); if (!request.fallBackFamilies.isEmpty()) { @@ -2439,6 +2442,8 @@ int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString & font.data = fontData; font.fileName = fileName; + Q_TRACE(qfontdatabaseprivate_addappfont, fileName); + int i; for (i = 0; i < applicationFonts.count(); ++i) if (applicationFonts.at(i).families.isEmpty()) @@ -2494,6 +2499,9 @@ int QFontDatabase::addApplicationFont(const QString &fileName) QFile f(fileName); if (!f.open(QIODevice::ReadOnly)) return -1; + + Q_TRACE(qfontdatabase_addapplicationfont, fileName); + data = f.readAll(); } QMutexLocker locker(fontDatabaseMutex()); @@ -2792,6 +2800,8 @@ void QFontDatabase::load(const QFontPrivate *d, int script) QFontEngine *fe = nullptr; + Q_TRACE(qfontdatabase_load, req.family, req.pointSize); + req.fallBackFamilies = fallBackFamilies; if (!req.fallBackFamilies.isEmpty()) req.family = req.fallBackFamilies.takeFirst(); diff --git a/src/src.pro b/src/src.pro index a2064b1362..3b93b1a9d8 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs -QT_FOR_CONFIG += gui-private +QT_FOR_CONFIG += core-private gui-private include($$OUT_PWD/corelib/qtcore-config.pri) include($$OUT_PWD/gui/qtgui-config.pri) @@ -30,6 +30,10 @@ src_tools_qlalr.target = sub-qlalr force_bootstrap: src_tools_qlalr.depends = src_tools_bootstrap else: src_tools_qlalr.depends = src_corelib +src_tools_tracegen.subdir = tools/tracegen +src_tools_tracegen.target = sub-tracegen +src_tools_tracegen.depends = src_tools_bootstrap + src_tools_uic.subdir = tools/uic src_tools_uic.target = sub-uic force_bootstrap: src_tools_uic.depends = src_tools_bootstrap @@ -152,8 +156,13 @@ qtConfig(regularexpression):pcre2 { SUBDIRS += src_3rdparty_pcre2 src_corelib.depends += src_3rdparty_pcre2 } -SUBDIRS += src_corelib src_tools_qlalr TOOLS = src_tools_moc src_tools_rcc src_tools_qlalr src_tools_qfloat16_tables +!force_bootstrap:if(qtConfig(lttng)|qtConfig(etw)) { + SUBDIRS += src_tools_tracegen + src_corelib.depends += src_tools_tracegen + TOOLS += src_tools_tracegen +} +SUBDIRS += src_corelib src_tools_qlalr win32:SUBDIRS += src_winmain qtConfig(network) { SUBDIRS += src_network @@ -220,7 +229,8 @@ android: SUBDIRS += src_android src_3rdparty_gradle TR_EXCLUDE = \ src_tools_bootstrap src_tools_moc src_tools_rcc src_tools_uic src_tools_qlalr \ src_tools_bootstrap_dbus src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml \ - src_3rdparty_pcre2 src_3rdparty_harfbuzzng src_3rdparty_freetype + src_3rdparty_pcre2 src_3rdparty_harfbuzzng src_3rdparty_freetype \ + src_tools_tracegen sub-tools.depends = $$TOOLS QMAKE_EXTRA_TARGETS = sub-tools diff --git a/src/tools/tracegen/etw.cpp b/src/tools/tracegen/etw.cpp new file mode 100644 index 0000000000..07f2d114b6 --- /dev/null +++ b/src/tools/tracegen/etw.cpp @@ -0,0 +1,228 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "etw.h" +#include "provider.h" +#include "helpers.h" +#include "qtheaders.h" + +#include +#include +#include +#include +#include + +static inline QString providerVar(const QString &providerName) +{ + return providerName + QLatin1String("_provider"); +} + +static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field) +{ + const QString &name = field.name; + + switch (field.backendType) { + case Tracepoint::Field::QtString: + stream << "TraceLoggingCountedWideString(reinterpret_cast(" + << name << ".utf16()), " << name << ".size(), \"" << name << "\")"; + return; + case Tracepoint::Field::QtByteArray: + stream << "TraceLoggingBinary(" << name << ".constData(), " + << name << ".size(), \"" << name << "\")"; + return; + case Tracepoint::Field::QtUrl: + stream << "TraceLoggingValue(" << name << ".toEncoded().constData(), \"" << name << "\")"; + return; + case Tracepoint::Field::QtRect: + stream << "TraceLoggingValue(" << name << ".x(), \"x\"), " + << "TraceLoggingValue(" << name << ".y(), \"y\"), " + << "TraceLoggingValue(" << name << ".width(), \"width\"), " + << "TraceLoggingValue(" << name << ".height(), \"height\")"; + return; + default: + break; + } + + stream << "TraceLoggingValue(" << name << ", \"" << name << "\")"; +} + +static QString createGuid(const QUuid &uuid) +{ + QString guid; + + QTextStream stream(&guid); + + hex(stream); + + stream << "(" + << "0x" << uuid.data1 << ", " + << "0x" << uuid.data2 << ", " + << "0x" << uuid.data3 << ", " + << "0x" << uuid.data4[0] << ", " + << "0x" << uuid.data4[1] << ", " + << "0x" << uuid.data4[2] << ", " + << "0x" << uuid.data4[3] << ", " + << "0x" << uuid.data4[4] << ", " + << "0x" << uuid.data4[5] << ", " + << "0x" << uuid.data4[6] << ", " + << "0x" << uuid.data4[7] + << ")"; + + return guid; +} + +static void writePrologue(QTextStream &stream, const QString &fileName, const QString &providerName) +{ + QUuid uuid = QUuid::createUuidV5(QUuid(), providerName.toLocal8Bit()); + + const QString provider = providerVar(providerName); + const QString guard = includeGuard(fileName); + const QString guid = createGuid(uuid); + const QString guidString = uuid.toString(); + + stream << "#ifndef " << guard << "\n" + << "#define " << guard << "\n" + << "#include \n" + << "#include \n"; + + /* TraceLogging API macros cannot deal with UTF8 + * source files, so we work around it like this + */ + stream << "#undef _TlgPragmaUtf8Begin\n" + "#undef _TlgPragmaUtf8End\n" + "#define _TlgPragmaUtf8Begin\n" + "#define _TlgPragmaUtf8End\n"; + + stream << qtHeaders(); + + stream << "\n"; + + stream << "#ifdef TRACEPOINT_DEFINE\n" + << "/* " << guidString << " */\n" + << "TRACELOGGING_DEFINE_PROVIDER(" << provider << ", \"" + << providerName <<"\", " << guid << ");\n\n"; + + stream << "static inline void registerProvider()\n" + << "{\n" + << " TraceLoggingRegister(" << provider << ");\n" + << "}\n\n"; + + stream << "static inline void unregisterProvider()\n" + << "{\n" + << " TraceLoggingUnregister(" << provider << ");\n" + << "}\n"; + + stream << "Q_CONSTRUCTOR_FUNCTION(registerProvider)\n" + << "Q_DESTRUCTOR_FUNCTION(unregisterProvider)\n\n"; + + stream << "#else\n" + << "TRACELOGGING_DECLARE_PROVIDER(" << provider << ");\n" + << "#endif // TRACEPOINT_DEFINE\n\n"; +} + +static void writeEpilogue(QTextStream &stream, const QString &fileName) +{ + stream << "\n#endif // " << includeGuard(fileName) << "\n" + << "#include \n"; +} + +static void writeWrapper(QTextStream &stream, const Tracepoint &tracepoint, + const QString &providerName) +{ + const QString argList = formatFunctionSignature(tracepoint.args); + const QString paramList = formatParameterList(tracepoint.args, ETW); + const QString &name = tracepoint.name; + const QString includeGuard = QStringLiteral("TP_%1_%2").arg(providerName).arg(name).toUpper(); + const QString provider = providerVar(providerName); + + stream << "\n"; + + stream << "inline void trace_" << name << "(" << argList << ")\n" + << "{\n" + << " TraceLoggingWrite(" << provider << ", \"" << name << "\""; + + for (const Tracepoint::Field &field : tracepoint.fields) { + stream << ",\n"; + stream << " "; + writeEtwMacro(stream, field); + } + + stream << ");\n" + << "}\n\n"; + + stream << "inline void do_trace_" << name << "(" << argList << ")\n" + << "{\n" + << " trace_" << name << "(" << paramList << ");\n" + << "}\n"; + + stream << "inline bool trace_" << name << "_enabled()\n" + << "{\n" + << " return TraceLoggingProviderEnabled(" << provider << ", 0, 0);\n" + << "}\n"; +} + +static void writeTracepoints(QTextStream &stream, const Provider &provider) +{ + if (provider.tracepoints.isEmpty()) + return; + + const QString includeGuard = QStringLiteral("TP_%1_PROVIDER").arg(provider.name).toUpper(); + + stream << "#if !defined(" << includeGuard << ") && !defined(TRACEPOINT_DEFINE)\n" + << "#define " << includeGuard << "\n" + << "namespace QtPrivate {\n"; + + for (const Tracepoint &t : provider.tracepoints) + writeWrapper(stream, t, provider.name); + + stream << "} // namespace QtPrivate\n" + << "#endif // " << includeGuard << "\n\n"; +} + +void writeEtw(QFile &file, const Provider &provider) +{ + QTextStream stream(&file); + + const QString fileName = QFileInfo(file.fileName()).fileName(); + + writePrologue(stream, fileName, provider.name); + writeTracepoints(stream, provider); + writeEpilogue(stream, fileName); +} + diff --git a/src/tools/tracegen/etw.h b/src/tools/tracegen/etw.h new file mode 100644 index 0000000000..5fc9b57eaa --- /dev/null +++ b/src/tools/tracegen/etw.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ETW_H +#define ETW_H + +struct Provider; +class QFile; + +void writeEtw(QFile &device, const Provider &p); + +#endif // ETW_H diff --git a/src/tools/tracegen/helpers.cpp b/src/tools/tracegen/helpers.cpp new file mode 100644 index 0000000000..f0ac7ed47f --- /dev/null +++ b/src/tools/tracegen/helpers.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "helpers.h" +#include + +QString includeGuard(const QString &filename) +{ + QString guard = filename.toUpper(); + + for (int i = 0; i < guard.size(); ++i) { + if (!guard.at(i).isLetterOrNumber()) + guard[i] = QChar('_'); + } + + return guard; +} + +template +static QString joinArguments(const QVector &args, T joinFunction) +{ + QString ret; + bool first = true; + + for (const Tracepoint::Argument &arg : args) { + if (!first) + ret += QLatin1String(", "); + + ret += joinFunction(arg); + + first = false; + } + + return ret; +} + +QString formatFunctionSignature(const QVector &args) +{ + return joinArguments(args, [](const Tracepoint::Argument &arg) { + return QStringLiteral("%1 %2").arg(arg.type).arg(arg.name); + }); +} + +QString formatParameterList(const QVector &args, ParamType type) +{ + if (type == LTTNG) { + QString ret; + + for (const Tracepoint::Argument &arg : args) + ret += QLatin1String(", ") + arg.name; + + return ret; + } + + return joinArguments(args, [](const Tracepoint::Argument &arg) { return arg.name; }); +} diff --git a/src/tools/tracegen/helpers.h b/src/tools/tracegen/helpers.h new file mode 100644 index 0000000000..77f16a0da6 --- /dev/null +++ b/src/tools/tracegen/helpers.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef HELPERS_H +#define HELPERS_H + +#include "provider.h" + +#include +#include + +enum ParamType { + LTTNG, + ETW +}; + +QString includeGuard(const QString &filename); +QString formatFunctionSignature(const QVector &args); +QString formatParameterList(const QVector &args, ParamType type); + +#endif // HELPERS_H diff --git a/src/tools/tracegen/lttng.cpp b/src/tools/tracegen/lttng.cpp new file mode 100644 index 0000000000..6c0d8cc88b --- /dev/null +++ b/src/tools/tracegen/lttng.cpp @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "lttng.h" +#include "provider.h" +#include "helpers.h" +#include "panic.h" +#include "qtheaders.h" + +#include +#include +#include +#include +#include + +static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field) +{ + const QString ¶mType = 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(" <\n\n"; +} + +static void writeEpilogue(QTextStream &stream, const QString &fileName) +{ + stream << "\n"; + stream << "#endif // " << includeGuard(fileName) << "\n" + << "#include \n" + << "#include \n"; +} + +static void writeWrapper(QTextStream &stream, + const Tracepoint &tracepoint, const QString &providerName) +{ + const QString argList = formatFunctionSignature(tracepoint.args); + const QString paramList = formatParameterList(tracepoint.args, LTTNG); + const QString &name = tracepoint.name; + const QString includeGuard = QStringLiteral("TP_%1_%2").arg(providerName).arg(name).toUpper(); + + /* prevents the redefinion of the inline wrapper functions + * once LTTNG recursively includes this header file + */ + stream << "\n" + << "#ifndef " << includeGuard << "\n" + << "#define " << includeGuard << "\n" + << "namespace QtPrivate {\n"; + + stream << "inline void trace_" << name << "(" << argList << ")\n" + << "{\n" + << " tracepoint(" << providerName << ", " << name << paramList << ");\n" + << "}\n"; + + stream << "inline void do_trace_" << name << "(" << argList << ")\n" + << "{\n" + << " do_tracepoint(" << providerName << ", " << name << paramList << ");\n" + << "}\n"; + + stream << "inline bool trace_" << name << "_enabled()\n" + << "{\n" + << " return tracepoint_enabled(" << providerName << ", " << name << ");\n" + << "}\n"; + + stream << "} // namespace QtPrivate\n" + << "#endif // " << includeGuard << "\n\n"; +} + +static void writeTracepoint(QTextStream &stream, + const Tracepoint &tracepoint, const QString &providerName) +{ + stream << "TRACEPOINT_EVENT(\n" + << " " << providerName << ",\n" + << " " << tracepoint.name << ",\n" + << " TP_ARGS("; + + const char *comma = nullptr; + + for (const Tracepoint::Argument &arg : tracepoint.args) { + stream << comma << arg.type << ", " << arg.name; + comma = ", "; + } + + stream << "),\n" + << " TP_FIELDS("; + + const char *newline = nullptr; + + for (const Tracepoint::Field &f : tracepoint.fields) { + stream << newline; + writeCtfMacro(stream, f); + newline = "\n "; + } + + stream << ")\n)\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); + } +} + +void writeLttng(QFile &file, const Provider &provider) +{ + QTextStream stream(&file); + + const QString fileName = QFileInfo(file.fileName()).fileName(); + + writePrologue(stream, fileName, provider.name); + writeTracepoints(stream, provider); + writeEpilogue(stream, fileName); +} diff --git a/src/tools/tracegen/lttng.h b/src/tools/tracegen/lttng.h new file mode 100644 index 0000000000..0307b375bc --- /dev/null +++ b/src/tools/tracegen/lttng.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LTTNG_H +#define LTTNG_H + +struct Provider; +class QFile; + +void writeLttng(QFile &device, const Provider &p); + +#endif // LTTNG_H diff --git a/src/tools/tracegen/panic.cpp b/src/tools/tracegen/panic.cpp new file mode 100644 index 0000000000..d1e207764e --- /dev/null +++ b/src/tools/tracegen/panic.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "panic.h" + +#include +#include +#include + +void panic(const char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, "tracegen: fatal: "); + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + fputc('\n', stderr); + + exit(EXIT_FAILURE); +} diff --git a/src/tools/tracegen/panic.h b/src/tools/tracegen/panic.h new file mode 100644 index 0000000000..c6b195af00 --- /dev/null +++ b/src/tools/tracegen/panic.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PANIC_H +#define PANIC_H + +void panic(const char *fmt, ...); + +#endif // PANIC_H diff --git a/src/tools/tracegen/provider.cpp b/src/tools/tracegen/provider.cpp new file mode 100644 index 0000000000..00e105377e --- /dev/null +++ b/src/tools/tracegen/provider.cpp @@ -0,0 +1,304 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "provider.h" +#include "panic.h" + +#include +#include +#include +#include +#include + +#ifdef TRACEGEN_DEBUG +#include + +static void dumpTracepoint(const Tracepoint &t) +{ + qDebug() << "=== BEGIN TRACEPOINT ==="; + qDebug() << "name:" << t.name; + qDebug() << "ARGS\n"; + + int j = 0; + + for (auto i = t.args.constBegin(); i != t.args.constEnd(); ++i) { + qDebug() << "ARG[" << j << "] type:" << i->type; + qDebug() << "ARG[" << j << "] name:" << i->name; + qDebug() << "ARG[" << j << "] arrayLen:" << i->arrayLen; + ++j; + } + + qDebug() << "\nFIELDS\n"; + + j = 0; + + for (auto i = t.fields.constBegin(); i != t.fields.constEnd(); ++i) { + qDebug() << "FIELD[" << j << "] backend_type" << static_cast(i->backendType); + qDebug() << "FIELD[" << j << "] param_type" << i->paramType; + qDebug() << "FIELD[" << j << "] name" << i->name; + qDebug() << "FIELD[" << j << "] arrayLen" << i->arrayLen; + qDebug() << "FIELD[" << j << "] seqLen" << i->seqLen; + ++j; + } + + qDebug() << "=== END TRACEPOINT ===\n"; + +} +#endif + +static inline int arrayLength(const QString &rawType) +{ + /* matches the length of an ordinary array type + * Ex: foo[10] yields '10' + */ + static const QRegExp rx(QStringLiteral(".*\\[([0-9]+)\\].*")); + + if (!rx.exactMatch(rawType.trimmed())) + return 0; + + return rx.cap(1).toInt(); +} + +static inline QString sequenceLength(const QString &rawType) +{ + /* matches the identifier pointing to length of a CTF sequence type, which is + * a dynamic sized array. + * Ex: in qcoreapplication_foo(const char[len], some_string, unsigned int, * len) + * it will match the 'len' part of 'const char[len]') + */ + static const QRegExp rx(QStringLiteral(".*\\[([A-Za-z_][A-Za-z_0-9]*)\\].*")); + + if (!rx.exactMatch(rawType.trimmed())) + return QString(); + + return rx.cap(1); +} + +static QString decayArrayToPointer(QString type) +{ + /* decays an array to a pointer, i.e., if 'type' holds int[10], + * this function returns 'int *' + */ + static QRegExp rx(QStringLiteral("\\[(.+)\\]")); + + rx.setMinimal(true); + return type.replace(rx, QStringLiteral("*")); +} + +static QString removeBraces(QString type) +{ + static const QRegExp rx(QStringLiteral("\\[.*\\]")); + + return type.remove(rx); +} + +static Tracepoint::Field::BackendType backendType(QString rawType) +{ + static const struct { + const char *type; + Tracepoint::Field::BackendType 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 }, + { "float", Tracepoint::Field::Float }, + { "double", Tracepoint::Field::Float }, + { "long_double", Tracepoint::Field::Float }, + { "char_ptr", Tracepoint::Field::String }, + { "QString", Tracepoint::Field::QtString }, + { "QByteArray", Tracepoint::Field::QtByteArray }, + { "QUrl", Tracepoint::Field::QtUrl }, + { "QRect", Tracepoint::Field::QtRect } + }; + + auto backendType = [](const QString &rawType) { + + static const size_t tableSize = sizeof (typeTable) / sizeof (typeTable[0]); + + for (size_t i = 0; i < tableSize; ++i) { + if (rawType == QLatin1String(typeTable[i].type)) + return typeTable[i].backendType; + } + + return Tracepoint::Field::Unknown; + }; + + if (arrayLength(rawType) > 0) + return Tracepoint::Field::Array; + + if (!sequenceLength(rawType).isNull()) + return Tracepoint::Field::Sequence; + + static const QRegExp constMatch(QStringLiteral("\\bconst\\b")); + rawType.remove(constMatch); + rawType.remove(QLatin1Char('&')); + + static const QRegExp ptrMatch(QStringLiteral("\\s*\\*\\s*")); + rawType.replace(ptrMatch, QStringLiteral("_ptr")); + rawType = rawType.trimmed(); + rawType.replace(QStringLiteral(" "), QStringLiteral("_")); + + return backendType(rawType.trimmed()); +} + +static Tracepoint parseTracepoint(const QString &name, const QStringList &args, + const QString &fileName, const int lineNumber) +{ + Tracepoint t; + t.name = name; + + if (args.isEmpty()) + return t; + + auto i = args.constBegin(); + auto end = args.constEnd(); + int argc = 0; + + static const QRegExp rx(QStringLiteral("(.*)\\b([A-Za-z_][A-Za-z0-9_]*)$")); + + while (i != end) { + rx.exactMatch(*i); + + const QString type = rx.cap(1).trimmed(); + + if (type.isNull()) { + panic("Missing parameter type for argument %d of %s (%s:%d)", + argc, qPrintable(name), qPrintable(fileName), lineNumber); + } + + const QString name = rx.cap(2).trimmed(); + + if (name.isNull()) { + panic("Missing parameter name for argument %d of %s (%s:%d)", + argc, qPrintable(name), qPrintable(fileName), lineNumber); + } + + int arrayLen = arrayLength(type); + + Tracepoint::Argument a; + a.arrayLen = arrayLen; + a.name = name; + a.type = decayArrayToPointer(type); + + 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); + + t.fields << std::move(f); + + ++i; + } + + return t; +} + +Provider parseProvider(const QString &filename) +{ + QFile f(filename); + + if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) + panic("Cannot open %s: %s", qPrintable(filename), qPrintable(f.errorString())); + + QTextStream s(&f); + + static const QRegExp tracedef(QStringLiteral("([A-Za-z][A-Za-z0-9_]*)\\((.*)\\)")); + + int lineNumber = 0; + + Provider provider; + provider.name = QFileInfo(filename).baseName(); + + for (;;) { + QString line = s.readLine().trimmed(); + + if (line.isNull()) + break; + + if (line.isEmpty() || line.startsWith(QStringLiteral("#"))) { + ++lineNumber; + continue; + } + + if (tracedef.exactMatch(line)) { + const QString name = tracedef.cap(1); + QStringList args = tracedef.cap(2).split(QStringLiteral(","), QString::SkipEmptyParts); + + if (args.at(0).isNull()) + args.clear(); + + provider.tracepoints << parseTracepoint(name, args, filename, lineNumber); + } else { + panic("Syntax error whilre processing %s on line %d", qPrintable(filename), lineNumber); + } + + ++lineNumber; + } + +#ifdef TRACEGEN_DEBUG + for (auto i = provider.tracepoints.constBegin(); i != provider.tracepoints.constEnd(); ++i) + dumpTracepoint(*i); +#endif + + return provider; +} diff --git a/src/tools/tracegen/provider.h b/src/tools/tracegen/provider.h new file mode 100644 index 0000000000..d8cbd2662d --- /dev/null +++ b/src/tools/tracegen/provider.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PROVIDER_H +#define PROVIDER_H + +#include +#include +#include + +struct Tracepoint +{ + struct Argument + { + QString type; + QString name; + int arrayLen; + }; + + struct Field + { + enum BackendType { + Array, + Sequence, + Integer, + Float, + String, + QtString, + QtByteArray, + QtUrl, + QtRect, + Unknown + }; + + BackendType backendType; + QString paramType; + QString name; + int arrayLen; + QString seqLen; + }; + + QString name; + QVector args; + QVector fields; +}; + +struct Provider +{ + QString name; + QVector tracepoints; +}; + +Provider parseProvider(const QString &filename); + +Q_DECLARE_TYPEINFO(Tracepoint::Argument, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(Tracepoint::Field, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(Tracepoint, Q_MOVABLE_TYPE); + +#endif // PROVIDER_H diff --git a/src/tools/tracegen/qtheaders.cpp b/src/tools/tracegen/qtheaders.cpp new file mode 100644 index 0000000000..eec3488a6d --- /dev/null +++ b/src/tools/tracegen/qtheaders.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtheaders.h" + +const char *qtHeaders() +{ + static const char headers[] = "" + "#include \n" + "#include \n" + "#include \n" + "#include \n"; + + return headers; +} diff --git a/src/tools/tracegen/qtheaders.h b/src/tools/tracegen/qtheaders.h new file mode 100644 index 0000000000..b80d374ca8 --- /dev/null +++ b/src/tools/tracegen/qtheaders.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTHEADERS_H +#define QTHEADERS_H + +const char *qtHeaders(); + +#endif // QTHEADERS_H diff --git a/src/tools/tracegen/tracegen.cpp b/src/tools/tracegen/tracegen.cpp new file mode 100644 index 0000000000..978fe406d0 --- /dev/null +++ b/src/tools/tracegen/tracegen.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "provider.h" +#include "lttng.h" +#include "etw.h" +#include "panic.h" + +#include +#include + +enum class Target +{ + LTTNG, + ETW +}; + +static inline void usage(int status) +{ + printf("Usage: tracegen \n"); + exit(status); +} + +static void parseArgs(int argc, char *argv[], Target *target, QString *inFile, QString *outFile) +{ + if (argc == 1) + usage(EXIT_SUCCESS); + if (argc != 4) + usage(EXIT_FAILURE); + + const char *targetString = argv[1]; + + if (qstrcmp(targetString, "lttng") == 0) { + *target = Target::LTTNG; + } else if (qstrcmp(targetString, "etw") == 0) { + *target = Target::ETW; + } else { + fprintf(stderr, "Invalid target: %s\n", targetString); + usage(EXIT_FAILURE); + } + + *inFile = QLatin1String(argv[2]); + *outFile = QLatin1String(argv[3]); +} + +int main(int argc, char *argv[]) +{ + Target target = Target::LTTNG; + QString inFile; + QString outFile; + + parseArgs(argc, argv, &target, &inFile, &outFile); + + Provider p = parseProvider(inFile); + + QFile out(outFile); + + if (!out.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + panic("Cannot open '%s' for writing: %s", + qPrintable(outFile), qPrintable(out.errorString())); + } + + switch (target) { + case Target::LTTNG: + writeLttng(out, p); + break; + case Target::ETW: + writeEtw(out, p); + break; + } + + return 0; +} diff --git a/src/tools/tracegen/tracegen.pro b/src/tools/tracegen/tracegen.pro new file mode 100644 index 0000000000..20f0bb2914 --- /dev/null +++ b/src/tools/tracegen/tracegen.pro @@ -0,0 +1,21 @@ +option(host_build) +CONFIG += force_bootstrap + +SOURCES += \ + etw.cpp \ + helpers.cpp \ + lttng.cpp \ + panic.cpp \ + provider.cpp \ + qtheaders.cpp \ + tracegen.cpp + +HEADERS += \ + etw.h \ + helpers.h \ + lttng.h \ + panic.h \ + provider.h \ + qtheaders.h + +load(qt_tool)