Implement GDB/LLDB compatible server #3

Merged
SonicSwordcane merged 33 commits from debugger into main 2025-01-19 00:13:43 +00:00
5 changed files with 40 additions and 8 deletions
Showing only changes of commit 6fd8d8f5cf - Show all commits

View File

@ -86,6 +86,12 @@ impl Application {
impl ApplicationHandler<UserEvent> for Application { impl ApplicationHandler<UserEvent> for Application {
fn resumed(&mut self, event_loop: &ActiveEventLoop) { fn resumed(&mut self, event_loop: &ActiveEventLoop) {
if let Some(port) = self.init_debug_port {
let mut server =
GdbServerWindow::new(SimId::Player1, self.client.clone(), self.proxy.clone());
server.launch(port);
self.open(event_loop, Box::new(server));
}
let app = GameWindow::new( let app = GameWindow::new(
self.client.clone(), self.client.clone(),
self.proxy.clone(), self.proxy.clone(),
@ -93,11 +99,6 @@ impl ApplicationHandler<UserEvent> for Application {
SimId::Player1, SimId::Player1,
); );
self.open(event_loop, Box::new(app)); self.open(event_loop, Box::new(app));
if let Some(port) = self.init_debug_port {
let mut server = GdbServerWindow::new(SimId::Player1, self.client.clone());
server.start(port);
self.open(event_loop, Box::new(server));
}
} }
fn window_event( fn window_event(
@ -193,7 +194,8 @@ impl ApplicationHandler<UserEvent> for Application {
self.open(event_loop, Box::new(about)); self.open(event_loop, Box::new(about));
} }
UserEvent::OpenDebugger(sim_id) => { UserEvent::OpenDebugger(sim_id) => {
let debugger = GdbServerWindow::new(sim_id, self.client.clone()); let debugger =
GdbServerWindow::new(sim_id, self.client.clone(), self.proxy.clone());
self.open(event_loop, Box::new(debugger)); self.open(event_loop, Box::new(debugger));
} }
UserEvent::OpenInput => { UserEvent::OpenInput => {
@ -209,6 +211,9 @@ impl ApplicationHandler<UserEvent> for Application {
); );
self.open(event_loop, Box::new(p2)); self.open(event_loop, Box::new(p2));
} }
UserEvent::Quit => {
event_loop.exit();
}
} }
} }
@ -390,6 +395,7 @@ pub enum UserEvent {
OpenDebugger(SimId), OpenDebugger(SimId),
OpenInput, OpenInput,
OpenPlayer2, OpenPlayer2,
Quit,
} }
pub enum Action { pub enum Action {

View File

@ -92,6 +92,7 @@ pub struct EmulatorBuilder {
state: Arc<Atomic<EmulatorState>>, state: Arc<Atomic<EmulatorState>>,
audio_on: Arc<[AtomicBool; 2]>, audio_on: Arc<[AtomicBool; 2]>,
linked: Arc<AtomicBool>, linked: Arc<AtomicBool>,
start_paused: bool,
} }
impl EmulatorBuilder { impl EmulatorBuilder {
@ -107,6 +108,7 @@ impl EmulatorBuilder {
state: Arc::new(Atomic::new(EmulatorState::Paused)), state: Arc::new(Atomic::new(EmulatorState::Paused)),
audio_on: Arc::new([AtomicBool::new(true), AtomicBool::new(true)]), audio_on: Arc::new([AtomicBool::new(true), AtomicBool::new(true)]),
linked: Arc::new(AtomicBool::new(false)), linked: Arc::new(AtomicBool::new(false)),
start_paused: false,
}; };
let client = EmulatorClient { let client = EmulatorClient {
queue, queue,
@ -125,6 +127,13 @@ impl EmulatorBuilder {
} }
} }
pub fn start_paused(self, paused: bool) -> Self {
Self {
start_paused: paused,
..self
}
}
pub fn build(self) -> Result<Emulator> { pub fn build(self) -> Result<Emulator> {
let mut emulator = Emulator::new( let mut emulator = Emulator::new(
self.commands, self.commands,
@ -136,6 +145,9 @@ impl EmulatorBuilder {
if let Some(path) = self.rom { if let Some(path) = self.rom {
emulator.load_cart(SimId::Player1, &path)?; emulator.load_cart(SimId::Player1, &path)?;
} }
if self.start_paused {
emulator.pause_sims()?;
}
Ok(emulator) Ok(emulator)
} }
} }

View File

@ -41,6 +41,7 @@ impl GdbServer {
} }
pub fn start(&mut self, port: u16) { pub fn start(&mut self, port: u16) {
*self.status.lock().unwrap() = GdbServerStatus::Connecting;
let sim_id = self.sim_id; let sim_id = self.sim_id;
let client = self.client.clone(); let client = self.client.clone();
let status = self.status.clone(); let status = self.status.clone();

View File

@ -87,6 +87,9 @@ fn main() -> Result<()> {
if let Some(path) = args.rom { if let Some(path) = args.rom {
builder = builder.with_rom(&path); builder = builder.with_rom(&path);
} }
if args.debug_port.is_some() {
builder = builder.start_paused(true);
}
ThreadBuilder::default() ThreadBuilder::default()
.name("Emulator".to_owned()) .name("Emulator".to_owned())

View File

@ -1,6 +1,8 @@
use egui::{Button, CentralPanel, TextEdit, ViewportBuilder, ViewportId}; use egui::{Button, CentralPanel, TextEdit, ViewportBuilder, ViewportId};
use winit::event_loop::EventLoopProxy;
use crate::{ use crate::{
app::UserEvent,
emulator::{EmulatorClient, SimId}, emulator::{EmulatorClient, SimId},
gdbserver::{GdbServer, GdbServerStatus}, gdbserver::{GdbServer, GdbServerStatus},
}; };
@ -10,21 +12,26 @@ use super::AppWindow;
pub struct GdbServerWindow { pub struct GdbServerWindow {
sim_id: SimId, sim_id: SimId,
port_str: String, port_str: String,
launched: bool,
server: GdbServer, server: GdbServer,
proxy: EventLoopProxy<UserEvent>,
} }
impl GdbServerWindow { impl GdbServerWindow {
pub fn new(sim_id: SimId, client: EmulatorClient) -> Self { pub fn new(sim_id: SimId, client: EmulatorClient, proxy: EventLoopProxy<UserEvent>) -> Self {
Self { Self {
sim_id, sim_id,
port_str: (8080 + sim_id.to_index()).to_string(), port_str: (8080 + sim_id.to_index()).to_string(),
launched: false,
server: GdbServer::new(sim_id, client), server: GdbServer::new(sim_id, client),
proxy,
} }
} }
pub fn start(&mut self, port: u16) { pub fn launch(&mut self, port: u16) {
self.server.stop(); self.server.stop();
self.port_str = port.to_string(); self.port_str = port.to_string();
self.launched = true;
self.server.start(port); self.server.start(port);
} }
} }
@ -57,6 +64,9 @@ impl AppWindow for GdbServerWindow {
}); });
if !status.running() { if !status.running() {
if self.launched {
self.proxy.send_event(UserEvent::Quit).unwrap();
}
let start_button = Button::new("Start"); let start_button = Button::new("Start");
if ui.add_enabled(port_num.is_some(), start_button).clicked() { if ui.add_enabled(port_num.is_some(), start_button).clicked() {
let port = port_num.unwrap(); let port = port_num.unwrap();