Skip to content

Commit

Permalink
Displays waiting for debugger window (#1203)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Dec 26, 2024
1 parent 2dccc89 commit 54326ec
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 67 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions gui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ name = "obliteration"
path = "src/main.rs"

[dependencies]
async-net = "2.0.0"
bitfield-struct = "0.9.2"
ciborium = "0.2.2"
clap = { version = "4.5.21", features = ["derive"] }
Expand Down
43 changes: 0 additions & 43 deletions gui/src/debug/mod.rs

This file was deleted.

File renamed without changes.
71 changes: 52 additions & 19 deletions gui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ use self::data::{DataError, DataMgr};
use self::graphics::{Graphics, GraphicsError, PhysicalDevice};
use self::profile::{DisplayResolution, Profile};
use self::setup::{run_setup, SetupError};
use self::ui::{MainWindow, ProfileModel, ResolutionModel, RuntimeExt, SlintBackend};
use self::ui::{
MainWindow, ProfileModel, ResolutionModel, RuntimeExt, SlintBackend, WaitForDebugger,
};
use async_net::{TcpListener, TcpStream};
use clap::{Parser, ValueEnum};
use debug::DebugServer;
use erdp::ErrorDisplay;
use slint::{ComponentHandle, ModelRc, SharedString, VecModel, WindowHandle};
use futures::{select_biased, FutureExt};
use slint::{ComponentHandle, ModelRc, SharedString, ToSharedString, VecModel, WindowHandle};
use std::cell::Cell;
use std::error::Error;
use std::net::SocketAddrV4;
Expand All @@ -21,8 +24,8 @@ use winit::dpi::PhysicalSize;
use winit::window::Window;

mod data;
mod debug;
mod dialogs;
mod gdb;
mod graphics;
mod hv;
mod panic;
Expand Down Expand Up @@ -112,7 +115,7 @@ async fn run(args: ProgramArgs, exe: PathBuf) -> Result<(), ProgramError> {
rlim::set_rlimit_nofile().map_err(ProgramError::FdLimit)?;

// Initialize graphics engine.
let mut graphics = graphics::new().map_err(ProgramError::InitGraphics)?;
let graphics = graphics::new().map_err(ProgramError::InitGraphics)?;

// Run setup wizard. This will simply return the data manager if the user already has required
// settings.
Expand Down Expand Up @@ -188,15 +191,14 @@ async fn run(args: ProgramArgs, exe: PathBuf) -> Result<(), ProgramError> {
};

// Wait for debugger.
let debugger = if let Some(listen) = debug {
let debug_server =
DebugServer::new(listen).map_err(|e| ProgramError::StartDebugServer(e, listen))?;
let debugger = if let Some(addr) = debug {
let v = wait_for_debugger(addr).await?;

let debugger = debug_server
.accept()
.map_err(ProgramError::CreateDebugClient)?;
if v.is_none() {
return Ok(());
}

Some(debugger)
v
} else {
None
};
Expand Down Expand Up @@ -334,6 +336,31 @@ async fn run_launcher(
Ok(Some((profile, exit)))
}

async fn wait_for_debugger(addr: SocketAddrV4) -> Result<Option<TcpStream>, ProgramError> {
// Start server.
let server = TcpListener::bind(addr)
.await
.map_err(|e| ProgramError::StartDebugServer(addr, e))?;
let addr = server.local_addr().map_err(ProgramError::GetDebugAddr)?;

// Tell the user that we are waiting for a debugger.
let win = WaitForDebugger::new().map_err(ProgramError::CreateDebugWindow)?;

win.set_address(addr.to_shared_string());
win.show().map_err(ProgramError::ShowDebugWindow)?;

// Wait for connection.
let client = select_biased! {
_ = win.wait().fuse() => None,
v = server.accept().fuse() => match v {
Ok(v) => Some(v.0),
Err(e) => return Err(ProgramError::AcceptDebugger(e)),
}
};

Ok(client)
}

/// Program arguments parsed from command line.
#[derive(Parser)]
#[command(about = None)]
Expand Down Expand Up @@ -384,14 +411,20 @@ enum ProgramError {
#[error("couldn't save default profile")]
SaveDefaultProfile(#[source] self::profile::SaveError),

#[error("failed to start debug server on {1}")]
StartDebugServer(
#[source] debug::StartDebugServerError,
std::net::SocketAddrV4,
),
#[error("couldn't start debug server on {0}")]
StartDebugServer(SocketAddrV4, #[source] std::io::Error),

#[error("couldn't get debug server address")]
GetDebugAddr(#[source] std::io::Error),

#[error("couldn't create debug server window")]
CreateDebugWindow(#[source] slint::PlatformError),

#[error("couldn't show debug server window")]
ShowDebugWindow(#[source] slint::PlatformError),

#[error("failed to accept debug connection")]
CreateDebugClient(#[source] std::io::Error),
#[error("couldn't accept a connection from debugger")]
AcceptDebugger(#[source] std::io::Error),

#[error("failed to create main window")]
CreateMainWindow(#[source] slint::PlatformError),
Expand Down
11 changes: 8 additions & 3 deletions gui/src/ui/backend/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ impl WindowAdapter for Window {
let size = properties.layout_constraints();
let min = size.min.map(&map);
let max = size.max.map(&map);
let preferred = map(size.preferred);
let pre = map(size.preferred);

if self.minimum_size.replace(min) != min {
self.winit.set_min_inner_size(min);
Expand All @@ -223,9 +223,14 @@ impl WindowAdapter for Window {
self.winit.set_max_inner_size(max);
}

// Winit on Wayland will panic if either width or height is zero.
// TODO: Not sure why Slint also update the preferred size when window size is changed.
if self.preferred_size.replace(Some(preferred)).is_none() {
let _ = self.winit.request_inner_size(preferred);
if self.preferred_size.replace(Some(pre)).is_none() && pre.width != 0 && pre.height != 0 {
let _ = self.winit.request_inner_size(pre);

if matches!((min, max), (Some(min), Some(max)) if min == max && pre == max) {
self.winit.set_resizable(false);
}
}
}

Expand Down
14 changes: 14 additions & 0 deletions gui/src/vmm/channel/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pub use self::screen::*;
pub use self::vmm::*;

mod screen;
mod vmm;

/// Create a new channel to communicate with the VMM.
pub fn create_channel() -> (VmmStream, ScreenStream) {
// Create streams.
let vmm = VmmStream::new();
let screen = ScreenStream::new();

(vmm, screen)
}
19 changes: 19 additions & 0 deletions gui/src/vmm/channel/screen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use gdbstub::stub::MultiThreadStopReason;

/// Provides method to send and receive events from the screen.
pub struct ScreenStream {}

impl ScreenStream {
pub(super) fn new() -> Self {
Self {}
}

pub fn recv(&self) {}

pub fn breakpoint(&self, stop: Option<MultiThreadStopReason<u64>>) -> BreakpointLock {
BreakpointLock {}
}
}

/// This struct will prevent the other CPU from entering a debugger dispatch loop.
pub struct BreakpointLock {}
8 changes: 8 additions & 0 deletions gui/src/vmm/channel/vmm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// Provides method to send and receive events from the VMM.
pub struct VmmStream {}

impl VmmStream {
pub(super) fn new() -> Self {
Self {}
}
}
2 changes: 1 addition & 1 deletion gui/src/vmm/debug/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
use super::cpu::{CpuManager, GdbError};
use crate::debug::DebugClient;
use crate::gdb::DebugClient;
use crate::hv::Hypervisor;
use gdbstub::stub::state_machine::state::{Idle, Running};
use gdbstub::stub::state_machine::{GdbStubStateMachine, GdbStubStateMachineInner};
Expand Down
5 changes: 4 additions & 1 deletion gui/src/vmm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pub use self::channel::*;

use self::cpu::CpuManager;
use self::hw::{setup_devices, Device};
use self::kernel::{
Kernel, PT_DYNAMIC, PT_GNU_EH_FRAME, PT_GNU_RELRO, PT_GNU_STACK, PT_LOAD, PT_NOTE, PT_PHDR,
};
use self::ram::RamBuilder;
use crate::debug::DebugClient;
use crate::gdb::DebugClient;
use crate::hv::{Hypervisor, Ram};
use crate::profile::Profile;
use cpu::GdbError;
Expand All @@ -28,6 +30,7 @@ use winit::event_loop::EventLoopProxy;
#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")]
mod arch;
mod channel;
mod cpu;
mod debug;
mod hw;
Expand Down
19 changes: 19 additions & 0 deletions gui/ui/debug.slint
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { VerticalBox } from "std-widgets.slint";

export component WaitForDebugger inherits Window {
in property <string> address;

title: "Obliteration";
icon: @image-url("icon.png");
width: 400px;
height: 50px;

VerticalBox {
alignment: center;

Text {
text: "Waiting for debugger at \{address}.";
horizontal-alignment: center;
}
}
}
1 change: 1 addition & 0 deletions gui/ui/main.slint
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Tabs } from "main/tabs.slint";
import { Actions } from "main/actions.slint";
import { VerticalBox } from "std-widgets.slint";

export { WaitForDebugger } from "debug.slint";
export { ErrorWindow } from "error.slint";
export { SetupWizard } from "setup.slint";

Expand Down

0 comments on commit 54326ec

Please sign in to comment.