File: hooks.cpp

package info (click to toggle)
gammaray 3.3.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 21,612 kB
  • sloc: cpp: 94,643; ansic: 2,227; sh: 336; python: 164; yacc: 90; lex: 82; xml: 61; makefile: 26
file content (143 lines) | stat: -rw-r--r-- 4,030 bytes parent folder | download | duplicates (2)
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
  hooks.cpp

  This file is part of GammaRay, the Qt application inspection and manipulation tool.

  SPDX-FileCopyrightText: 2012 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
  Author: Volker Krause <volker.krause@kdab.com>

  SPDX-License-Identifier: GPL-2.0-or-later

  Contact KDAB at <info@kdab.com> for commercial licensing options.
*/
// krazy:excludeall=cpp due to low-level stuff in here

#include <config-gammaray.h>

#include "hooks.h"
#include "probecreator.h"

#include <core/probe.h>

#include <QCoreApplication>

#include <private/qhooks_p.h>

#include <stdio.h> //cannot use cstdio on QNX6.6
#include <cassert>

#ifdef Q_OS_MAC
#include <inttypes.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/errno.h>
#elif defined(Q_OS_WIN)
#include <qt_windows.h>
#endif

#define IF_DEBUG(x)

using namespace GammaRay;

static void log_injection(const char *msg)
{
#ifdef Q_OS_WIN
    OutputDebugStringA(msg);
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-security"
    printf(msg); // NOLINT clang-tidy
#pragma GCC diagnostic pop
#endif
}

static void gammaray_pre_routine()
{
#ifdef Q_OS_WIN
    if (qApp) // DllMain will do a better job at this, we are too early here and might not even have our staticMetaObject properly resolved
        return;
#endif
    new ProbeCreator(ProbeCreator::Create | ProbeCreator::FindExistingObjects);
} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
Q_COREAPP_STARTUP_FUNCTION(gammaray_pre_routine)

// previously installed Qt hooks, for daisy-chaining
static void (*gammaray_next_startup_hook)() = nullptr;
static void (*gammaray_next_addObject)(QObject *) = nullptr;
static void (*gammaray_next_removeObject)(QObject *) = nullptr;

extern "C" Q_DECL_EXPORT void gammaray_startup_hook()
{
    Probe::startupHookReceived();
    new ProbeCreator(ProbeCreator::Create);

    if (gammaray_next_startup_hook)
        gammaray_next_startup_hook();
} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)

extern "C" Q_DECL_EXPORT void gammaray_addObject(QObject *obj)
{
    Probe::objectAdded(obj, true);

    if (gammaray_next_addObject)
        gammaray_next_addObject(obj);
}

extern "C" Q_DECL_EXPORT void gammaray_removeObject(QObject *obj)
{
    Probe::objectRemoved(obj);

    if (gammaray_next_removeObject)
        gammaray_next_removeObject(obj);
}

static void installQHooks()
{
    Q_ASSERT(qtHookData[QHooks::HookDataVersion] >= 1);
    Q_ASSERT(qtHookData[QHooks::HookDataSize] >= 6);

    gammaray_next_addObject = reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject]);
    gammaray_next_removeObject = reinterpret_cast<QHooks::RemoveQObjectCallback>(qtHookData[QHooks::RemoveQObject]);
    gammaray_next_startup_hook = reinterpret_cast<QHooks::StartupCallback>(qtHookData[QHooks::Startup]);

    qtHookData[QHooks::AddQObject] = reinterpret_cast<quintptr>(&gammaray_addObject);
    qtHookData[QHooks::RemoveQObject] = reinterpret_cast<quintptr>(&gammaray_removeObject);
    qtHookData[QHooks::Startup] = reinterpret_cast<quintptr>(&gammaray_startup_hook);
}

bool Hooks::hooksInstalled()
{
    return qtHookData[QHooks::AddQObject] == reinterpret_cast<quintptr>(&gammaray_addObject);
}

void Hooks::installHooks()
{
    if (hooksInstalled())
        return;

    installQHooks();
}

extern "C" Q_DECL_EXPORT void gammaray_probe_inject()
{
    if (!qApp) {
        return;
    }
    Hooks::installHooks();
    log_injection("gammaray_probe_inject()\n");
    new ProbeCreator(ProbeCreator::Create | ProbeCreator::FindExistingObjects);
} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)

extern "C" Q_DECL_EXPORT void gammaray_probe_attach()
{
    if (!qApp) {
        return;
    }
    log_injection("gammaray_probe_attach()\n");
    new ProbeCreator(ProbeCreator::Create | ProbeCreator::FindExistingObjects | ProbeCreator::ResendServerAddress);
} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)

extern "C" Q_DECL_EXPORT void gammaray_install_hooks()
{
    Hooks::installHooks();
}