ptracer.cpp 2.63 KB
Newer Older
1
/*
2
    SPDX-FileCopyrightText: 2019 Christoph Roick <chrisito@gmx.de>
3

4
    SPDX-License-Identifier: GPL-2.0-or-later
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
*/
#include "ptracer.h"

#ifdef Q_OS_LINUX

#include "drkonqi_debug.h"

#include <QFile>
#include <QStandardPaths>

#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/un.h>

#include <unistd.h>
20
#include <errno.h>
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

void setPtracer(qint64 debuggerpid, qint64 debuggeepid)
{

    int sfd = socket(PF_UNIX, SOCK_STREAM, 0);
    if (sfd < 0) {
        qCWarning(DRKONQI_LOG) << "socket to set ptracer not accessible";
        return;
    }

    static struct sockaddr_un server;
    static socklen_t sl = sizeof(server);
    server.sun_family = AF_UNIX;
    const QString socketPath =
        QStringLiteral("%1/kcrash_%2").arg(QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation))
                                      .arg(debuggeepid);

    if (socketPath.size() >= static_cast<int>(sizeof(server.sun_path))) {
        qCWarning(DRKONQI_LOG) << "socket path is too long";
        close(sfd);
        return;
    }
    strcpy(server.sun_path, QFile::encodeName(socketPath).constData());

    if (::connect(sfd, (struct sockaddr *)&server, sl) == 0) {
        static const int msize = 21; // most digits in a 64bit int (+sign +'\0')
        char msg[msize];
        sprintf(msg, "%lld", debuggerpid);

        int r, bytes = 0;
        while (bytes < msize) {
            r = write(sfd, msg + bytes, msize - bytes);
            if (r > 0)
                bytes += r;
            else if (r == -1 && errno != EINTR)
                break;
        }
        if (bytes == msize) {
            struct pollfd fd;
            fd.fd = sfd;
            fd.events = POLLIN;
            while ((r = poll(&fd, 1, 1000)) == -1 && errno == EINTR) {}
            if (r > 0 && (fd.revents & POLLIN)) {
                char rmsg[msize];
                bytes = 0;
                while (bytes < msize) {
                    r = read(sfd, rmsg + bytes, msize - bytes);
                    if (r > 0)
                        bytes += r;
                    else if (r == -1 && errno != EINTR)
                        break;
                }
                if (bytes == msize && memcmp(msg, rmsg, msize) == 0)
                    qCInfo(DRKONQI_LOG) << "ptracer set to" << debuggerpid << "by debugged process";
                else
                    qCWarning(DRKONQI_LOG) << "debugged process did not acknowledge setting ptracer to" << debuggerpid;
                close(sfd);
                return;
            }
        }
    }

    qCWarning(DRKONQI_LOG) << "unable to set ptracer to" << debuggerpid;
    close(sfd);
}

#else

void setPtracer(qint64, qint64)
{
}

#endif