Implements UI to start debug (#1015)
Some checks are pending
Development Build / Build (push) Waiting to run
Development Build / Update PRs (push) Waiting to run

This commit is contained in:
Putta Khunchalee 2024-10-05 01:48:26 +07:00 committed by GitHub
parent b97cdfff30
commit 2cac7fbd0b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 109 additions and 16 deletions

View File

@ -3,14 +3,19 @@
#include <QGridLayout> #include <QGridLayout>
#include <QGroupBox> #include <QGroupBox>
#include <QLabel> #include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QPushButton>
#include <QSlider> #include <QSlider>
CpuSettings::CpuSettings(QWidget *parent) : CpuSettings::CpuSettings(QWidget *parent) :
QWidget(parent) QWidget(parent),
m_debugAddr(nullptr)
{ {
auto layout = new QGridLayout(); auto layout = new QGridLayout();
layout->addWidget(buildCount(), 0, 0); layout->addWidget(buildCount(), 0, 0);
layout->addWidget(buildDebug(), 0, 1);
layout->setRowStretch(1, 1); layout->setRowStretch(1, 1);
setLayout(layout); setLayout(layout);
@ -53,3 +58,50 @@ QWidget *CpuSettings::buildCount()
return group; return group;
} }
QWidget *CpuSettings::buildDebug()
{
auto group = new QGroupBox("Debug");
auto layout = new QGridLayout();
// Address label.
auto label = new QLabel("Listen address:");
layout->addWidget(label, 0, 0);
// Address editor.
m_debugAddr = new QLineEdit("127.0.0.1:1234");
label->setBuddy(m_debugAddr);
layout->addWidget(m_debugAddr, 0, 1);
// Start.
auto start = new QPushButton("Start");
connect(start, &QAbstractButton::clicked, [this] {
auto addr = m_debugAddr->text();
if (addr.isEmpty()) {
QMessageBox::critical(this, "Error", "Listen address cannot be empty.");
return;
}
emit debugClicked(addr);
});
layout->addWidget(start, 0, 2);
// Description.
auto desc = new QLabel(
"Specify a TCP address to listen for a debugger. The kernel will wait for a debugger to "
"connect before start.");
desc->setWordWrap(true);
layout->addWidget(desc, 1, 0, 1, -1);
group->setLayout(layout);
return group;
}

View File

@ -2,10 +2,18 @@
#include <QWidget> #include <QWidget>
class QLineEdit;
class CpuSettings final : public QWidget { class CpuSettings final : public QWidget {
Q_OBJECT
public: public:
CpuSettings(QWidget *parent = nullptr); CpuSettings(QWidget *parent = nullptr);
~CpuSettings() override; ~CpuSettings() override;
signals:
void debugClicked(const QString &addr);
private: private:
QWidget *buildCount(); QWidget *buildCount();
QWidget *buildDebug();
QLineEdit *m_debugAddr;
}; };

View File

@ -94,6 +94,10 @@ QWidget *LaunchSettings::buildSettings(GameListModel *games, QList<VkPhysicalDev
// CPU settings. // CPU settings.
m_cpu = new CpuSettings(); m_cpu = new CpuSettings();
connect(m_cpu, &CpuSettings::debugClicked, [this](const QString &addr) {
emit startClicked(addr);
});
tab->addTab(m_cpu, loadIcon(":/resources/cpu-64-bit.svg", iconSize), "CPU"); tab->addTab(m_cpu, loadIcon(":/resources/cpu-64-bit.svg", iconSize), "CPU");
// Game list. // Game list.
@ -153,7 +157,7 @@ QLayout *LaunchSettings::buildActions(ProfileList *profiles)
start->setIcon(loadIcon(":/resources/play.svg", start->iconSize())); start->setIcon(loadIcon(":/resources/play.svg", start->iconSize()));
connect(start, &QAbstractButton::clicked, [this]() { emit startClicked(); }); connect(start, &QAbstractButton::clicked, [this]() { emit startClicked({}); });
actions->addButton(start, QDialogButtonBox::AcceptRole); actions->addButton(start, QDialogButtonBox::AcceptRole);

View File

@ -39,7 +39,7 @@ public:
#endif #endif
signals: signals:
void saveClicked(Profile *p); void saveClicked(Profile *p);
void startClicked(); void startClicked(const QString &debugAddr);
private: private:
#ifdef __APPLE__ #ifdef __APPLE__
QWidget *buildSettings(GameListModel *games); QWidget *buildSettings(GameListModel *games);

View File

@ -341,7 +341,7 @@ void MainWindow::saveProfile(Profile *p)
} }
} }
void MainWindow::startKernel() void MainWindow::startKernel(const QString &debugAddr)
{ {
// Get full path to kernel binary. // Get full path to kernel binary.
std::string kernel; std::string kernel;
@ -387,6 +387,7 @@ void MainWindow::startKernel()
m_main->setCurrentIndex(1); m_main->setCurrentIndex(1);
// Run. // Run.
auto debug = debugAddr.toStdString();
VmmScreen screen; VmmScreen screen;
Rust<RustError> error; Rust<RustError> error;
Rust<Vmm> vmm; Rust<Vmm> vmm;
@ -411,7 +412,7 @@ void MainWindow::startKernel()
kernel.c_str(), kernel.c_str(),
&screen, &screen,
m_launch->currentProfile(), m_launch->currentProfile(),
nullptr, debug.empty() ? nullptr : debug.c_str(),
MainWindow::vmmHandler, MainWindow::vmmHandler,
this, this,
&error); &error);
@ -459,7 +460,7 @@ void MainWindow::waitingDebugger(const QString &addr)
{ {
QMessageBox::information( QMessageBox::information(
this, this,
"Action required", "Debug",
QString("The kernel are waiting for a debugger at %1.").arg(addr)); QString("The kernel are waiting for a debugger at %1.").arg(addr));
} }

View File

@ -38,7 +38,7 @@ private slots:
void reportIssue(); void reportIssue();
void aboutObliteration(); void aboutObliteration();
void saveProfile(Profile *p); void saveProfile(Profile *p);
void startKernel(); void startKernel(const QString &debugAddr);
void updateScreen(); void updateScreen();
private: private:
void waitingDebugger(const QString &addr); void waitingDebugger(const QString &addr);

View File

@ -20,7 +20,8 @@ use std::ptr::null_mut;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use std::sync::Arc; use std::sync::Arc;
use std::thread::JoinHandle; use std::thread::{sleep, JoinHandle};
use std::time::Duration;
use thiserror::Error; use thiserror::Error;
#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")] #[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
@ -50,19 +51,32 @@ pub unsafe extern "C" fn vmm_run(
// Setup debug server. // Setup debug server.
let debug = match debug.is_null() { let debug = match debug.is_null() {
true => None, true => None,
false => match CStr::from_ptr(debug).to_str() { false => {
Ok(addr) => match TcpListener::bind(addr) { // Get address to listen.
Ok(v) => Some(v), let addr = match CStr::from_ptr(debug).to_str() {
Err(e) => { Ok(v) => v,
*err = RustError::with_source("couldn't listen for a debugger", e);
return null_mut();
}
},
Err(_) => { Err(_) => {
*err = RustError::new("address to listen for a debugger is not UTF-8"); *err = RustError::new("address to listen for a debugger is not UTF-8");
return null_mut(); return null_mut();
} }
}, };
// Setup server.
let sock = match TcpListener::bind(addr) {
Ok(v) => v,
Err(e) => {
*err = RustError::with_source("couldn't listen for a debugger", e);
return null_mut();
}
};
if let Err(e) = sock.set_nonblocking(true) {
*err = RustError::with_source("couldn't enable non-blocking on a debug server", e);
return null_mut();
}
Some(sock)
}
}; };
// Check if path UTF-8. // Check if path UTF-8.
@ -539,7 +553,21 @@ fn main_cpu<H: Hypervisor>(
} }
// Wait for a debugger. // Wait for a debugger.
debug.accept().unwrap().0; loop {
if args.shutdown.load(Ordering::Relaxed) {
return;
}
// Try accept a connection.
let e = match debug.accept() {
Ok(_) => break,
Err(e) => e,
};
assert_eq!(e.kind(), std::io::ErrorKind::WouldBlock);
sleep(Duration::from_secs(1));
}
} }
run_cpu(cpu, args); run_cpu(cpu, args);