summaryrefslogtreecommitdiffstats
path: root/src/corelib/tracing/qctf.cpp
blob: 1dafa582d915c4f8fbacaba476e50a8bc7e78339 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#define BUILD_LIBRARY

#include <qthread.h>
#include <qpluginloader.h>
#include <qfileinfo.h>
#include <qdir.h>

#include "qctf_p.h"

QT_BEGIN_NAMESPACE

static bool s_initialized = false;
static bool s_triedLoading = false;
static bool s_prevent_recursion = false;
static QCtfLib* s_plugin = nullptr;

#if defined(Q_OS_ANDROID)
static QString findPlugin(const QString &plugin)
{
    QString pluginPath = QString::fromUtf8(qgetenv("QT_PLUGIN_PATH"));
    QDir dir(pluginPath);
    const QStringList files = dir.entryList(QDir::Files);
    for (const QString &file : files) {
        if (file.contains(plugin))
            return QFileInfo(pluginPath + QLatin1Char('/') + file).absoluteFilePath();
    }
    return {};
}
#endif

static bool loadPlugin(bool &retry)
{
    retry = false;
#ifdef Q_OS_WIN
#ifdef QT_DEBUG
    QPluginLoader loader(QStringLiteral("tracing/QCtfTracePlugind.dll"));
#else
    QPluginLoader loader(QStringLiteral("tracing/QCtfTracePlugin.dll"));
#endif
#elif defined(Q_OS_ANDROID)

    QString plugin = findPlugin(QStringLiteral("QCtfTracePlugin"));
    if (plugin.isEmpty()) {
        retry = true;
        return false;
    }
    QPluginLoader loader(plugin);
#else
    QPluginLoader loader(QStringLiteral("tracing/libQCtfTracePlugin.so"));
#endif

    if (!loader.isLoaded()) {
        if (!loader.load())
            return false;
    }
    s_plugin = qobject_cast<QCtfLib *>(loader.instance());
    if (!s_plugin)
        return false;
    QObject *obj = loader.instance();
    if (obj) {
        QObject::connect(obj, &QObject::destroyed, []() {
            s_plugin = nullptr;
        });
    }
    return true;
}

static bool initialize()
{
    if (s_prevent_recursion)
        return false;
    if (s_initialized || s_triedLoading)
        return s_initialized;
    s_prevent_recursion = true;
    bool retry = false;
    if (!loadPlugin(retry)) {
        if (!retry) {
            s_triedLoading = true;
            s_initialized = false;
        }
    } else {
        bool enabled = s_plugin->sessionEnabled();
        if (!enabled) {
            s_triedLoading = true;
            s_initialized = false;
        } else {
            s_initialized = true;
        }
    }
    s_prevent_recursion = false;
    return s_initialized;
}

bool _tracepoint_enabled(const QCtfTracePointEvent &point)
{
    if (!initialize())
        return false;
    return s_plugin ? s_plugin->tracepointEnabled(point) : false;
}

void _do_tracepoint(const QCtfTracePointEvent &point, const QByteArray &arr)
{
    if (!initialize())
        return;
    if (s_plugin)
        s_plugin->doTracepoint(point, arr);
}

QCtfTracePointPrivate *_initialize_tracepoint(const QCtfTracePointEvent &point)
{
    if (!initialize())
        return nullptr;
    return s_plugin ? s_plugin->initializeTracepoint(point) : nullptr;
}

QT_END_NAMESPACE