mirror of
https://github.com/obhq/obliteration.git
synced 2024-11-27 05:00:24 +00:00
Implements UI to start debug (#1015)
This commit is contained in:
parent
b97cdfff30
commit
2cac7fbd0b
@ -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;
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user