1 | // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. |
2 | // |
3 | // SPDX-License-Identifier: GPL-3.0-or-later |
4 | |
5 | #include "minidumpruncontrol.h" |
6 | #include "reversedebuggerconstants.h" |
7 | #include "common/util/custompaths.h" |
8 | |
9 | #include <QDebug> |
10 | #include <QFile> |
11 | #include <QMessageBox> |
12 | #include <QDir> |
13 | |
14 | #include <string> |
15 | #include <unistd.h> |
16 | |
17 | using namespace std; |
18 | |
19 | // global variable used extern. |
20 | bool kEmdRunning = false; |
21 | bool g_emd_buffer_syscall = false; |
22 | QString g_emd_params; |
23 | |
24 | namespace ReverseDebugger { |
25 | namespace Internal { |
26 | |
27 | string found_crash(const char *subdir, int *ppid) |
28 | { |
29 | // find crash.txt |
30 | string parent_dir = getenv("HOME" ); |
31 | parent_dir += subdir; // "/.local/share/rdb/"; |
32 | string linkname = parent_dir; |
33 | linkname += "latest-trace" ; |
34 | string filename = parent_dir; |
35 | int pos = filename.size(); |
36 | filename.resize(512, 0); |
37 | int len = readlink(linkname.data(), |
38 | (char *)filename.data() + pos, 512 - pos); |
39 | if (len < 0) { |
40 | return string(); |
41 | } |
42 | filename.resize(len + pos); |
43 | parent_dir = filename; |
44 | filename += "/crash.txt" ; |
45 | |
46 | // parse crash.txt |
47 | QFile file(QString::fromStdString(filename)); |
48 | if (file.size() > 0 && file.open(QFile::ReadOnly)) { |
49 | char buf[256]; |
50 | int size = file.readLine(buf, sizeof(buf)); |
51 | buf[size] = 0; |
52 | char *stop = nullptr; |
53 | int pid = strtol(buf, &stop, 10); |
54 | int sig = strtol(stop + 1, NULL, 10); |
55 | if (sig > 0 && pid > 0) { |
56 | qDebug() << __FUNCTION__ << "found crash sig: " << sig; |
57 | *ppid = pid; |
58 | return parent_dir; |
59 | } |
60 | } |
61 | |
62 | return string(); |
63 | } |
64 | |
65 | MinidumpRunControl::MinidumpRunControl(QObject *parent) |
66 | : QObject(parent), |
67 | process(new QProcess(this)) |
68 | { |
69 | if (kEmdRunning) { |
70 | qDebug() << "emd is running now!" ; |
71 | return; |
72 | } |
73 | |
74 | // process->setWorkingDirectory() |
75 | // process->setProcessEnvironment(); |
76 | |
77 | connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), |
78 | this, SLOT(onStraceExit(int, QProcess::ExitStatus))); |
79 | } |
80 | |
81 | MinidumpRunControl::~MinidumpRunControl() |
82 | { |
83 | } |
84 | |
85 | void MinidumpRunControl::start(const QString ¶ms, const QString &target) |
86 | { |
87 | qDebug() << __FUNCTION__ << ", object:" << this; |
88 | |
89 | if (target.isEmpty() || !QFile::exists(target)) { |
90 | QMessageBox::warning(nullptr, tr("Reverse debug" ), tr("Target: %1 not found, recored failed!" ).arg(target)); |
91 | return; |
92 | } |
93 | |
94 | execFile = CustomPaths::global(CustomPaths::Tools) + QDir::separator() + "emd" ; |
95 | if (!params.isEmpty()) { |
96 | execFile += ' ' + params + ' '; |
97 | } |
98 | execFile += target; // target debuggee |
99 | |
100 | appendMessage(tr("[Start] %1" ).arg(execFile) + QLatin1Char('\n')); |
101 | |
102 | process->start(execFile); |
103 | if (!process->waitForStarted(1000)) { |
104 | qDebug() << "Failed to run emd" ; |
105 | return; |
106 | } |
107 | |
108 | kEmdRunning = true; |
109 | } |
110 | |
111 | StopResult MinidumpRunControl::stop() |
112 | { |
113 | qDebug() << __FUNCTION__ << ", object:" << this; |
114 | |
115 | if (process) { |
116 | QByteArray data = process->readAll(); |
117 | QString outstr = QString::fromLocal8Bit(data.data()); |
118 | appendMessage(outstr + QLatin1Char('\n')); |
119 | } |
120 | |
121 | kEmdRunning = false; |
122 | |
123 | appendMessage(tr("[Stop] %1" ).arg(execFile) + QLatin1Char('\n')); |
124 | |
125 | return StoppedSynchronously; |
126 | } |
127 | |
128 | bool MinidumpRunControl::isRunning() const |
129 | { |
130 | return kEmdRunning; |
131 | } |
132 | |
133 | QString MinidumpRunControl::displayName() const |
134 | { |
135 | return "event debug recored" ; |
136 | } |
137 | |
138 | void MinidumpRunControl::appendMessage(const QString &msg) |
139 | { |
140 | Q_UNUSED(msg) |
141 | } |
142 | |
143 | void MinidumpRunControl::onStraceExit(int, QProcess::ExitStatus) |
144 | { |
145 | stop(); |
146 | |
147 | int pid = 0; |
148 | string parent_dir = found_crash(("/.local/share/emd/" ), &pid); |
149 | if (!parent_dir.empty()) { |
150 | // emd_replay(QString::fromStdString(parent_dir), pid); |
151 | return; |
152 | } |
153 | |
154 | QMessageBox::information(nullptr, tr("reverse debug" ), tr("Recored done, minidump load ready." )); |
155 | } |
156 | |
157 | } // namespace Internal |
158 | } // namespace ReverseDebugger |
159 | |