Skip to content

Commit

Permalink
fixes & improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
michelhe committed Oct 4, 2022
1 parent 5f9f972 commit 1dfdec3
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 29 deletions.
3 changes: 2 additions & 1 deletion arm7tdmi/src/gdb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ pub extern crate gdbstub_arch;
/// Wait for tcp connection on port
pub fn wait_for_connection(port: u16) -> io::Result<TcpStream> {
let bind_addr = format!("0.0.0.0:{port}");
info!("waiting for connection on {:?}", bind_addr);

let sock = TcpListener::bind(bind_addr)?;

info!("waiting for connection");
// Blocks until a GDB client connects via TCP.
// i.e: Running `target remote localhost:<port>` from the GDB prompt.
let (stream, addr) = sock.accept()?;
Expand Down
2 changes: 1 addition & 1 deletion arm7tdmi/src/gdb/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl<I: MemoryGdbInterface> SingleThreadBase for Arm7tdmiCore<I> {
&mut self,
regs: &mut gdbstub_arch::arm::reg::ArmCoreRegs,
) -> TargetResult<(), Self> {
regs.pc = self.pc;
regs.pc = self.get_next_pc();
regs.lr = self.get_reg(REG_LR);
regs.sp = self.get_reg(REG_SP);
regs.r[..].copy_from_slice(&self.gpr[..13]);
Expand Down
13 changes: 12 additions & 1 deletion core/src/gdb_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub(crate) enum DebuggerRequest {
Interrupt,
Resume,
SingleStep,
Reset,
Disconnected(DisconnectReason),
}

Expand All @@ -40,7 +41,7 @@ pub(crate) struct DebuggerRequestHandler {
request_complete_signal: Arc<(Mutex<bool>, Condvar)>,
stop_signal: Arc<(Mutex<Option<SingleThreadStopReason<u32>>>, Condvar)>,
thread: JoinHandle<()>,
stopped: bool,
pub(crate) stopped: bool,
}

impl DebuggerRequestHandler {
Expand Down Expand Up @@ -123,6 +124,12 @@ impl DebuggerRequestHandler {
self.stopped = false;
self.complete_request(None)
}
Reset => {
debug!("Sending reset interrupt to gba");
self.stopped = true;
gba.cpu.reset();
self.complete_request(Some(SingleThreadStopReason::Signal(Signal::SIGTRAP)))
}
SingleStep => {
debug!("Debugger requested single step");
self.stopped = true;
Expand Down Expand Up @@ -153,6 +160,10 @@ impl DebuggerRequestHandler {
let mut finished = lock.lock().unwrap();
*finished = true;
cvar.notify_one();
// wait for the ack
while *finished {
finished = cvar.wait(finished).unwrap();
}
}

fn complete_request(
Expand Down
7 changes: 2 additions & 5 deletions core/src/gdb_support/gdb_thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ use std::sync::{Arc, Condvar, Mutex};
use arm7tdmi::{
gdb::wait_for_connection,
gdbstub::{
common::Signal,
conn::ConnectionExt,
stub::{GdbStub, SingleThreadStopReason},
stub::GdbStub,
},
};

Expand Down Expand Up @@ -41,14 +40,12 @@ pub(crate) fn start_gdb_server_thread(
target.disconnect(disconnect_reason);
});

let mut debugger = DebuggerRequestHandler {
let debugger = DebuggerRequestHandler {
rx,
request_complete_signal,
stop_signal,
thread,
stopped: true,
};
debugger.notify_stop_reason(SingleThreadStopReason::Signal(Signal::SIGINT));

Ok(debugger)
}
60 changes: 45 additions & 15 deletions core/src/gdb_support/target.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::sync::{Arc, Condvar, Mutex};
use std::sync::{Arc, Condvar, Mutex, WaitTimeoutResult};
use std::time::Duration;

/// Implementing the Target trait for gdbstub
Expand All @@ -12,6 +12,7 @@ use gdbstub::target::ext::base::singlethread::{
use gdbstub::target::ext::base::singlethread::{SingleThreadResumeOps, SingleThreadSingleStepOps};
use gdbstub::target::ext::base::BaseOps;
use gdbstub::target::ext::breakpoints::BreakpointsOps;
use gdbstub::target::ext::monitor_cmd::{outputln, ConsoleOutput};
use gdbstub::target::{self, Target, TargetError, TargetResult};
use gdbstub_arch::arm::reg::ArmCoreRegs;

Expand Down Expand Up @@ -42,16 +43,15 @@ impl DebuggerTarget {
pub fn debugger_request(&mut self, req: DebuggerRequest) {
let (lock, cvar) = &*self.request_complete_signal;
let mut finished = lock.lock().unwrap();
*finished = false;

// now send the request
self.tx.send(req).unwrap();

// wait for the notification
while !*finished {
finished = cvar.wait(finished).unwrap();
}
// ack the other side we got the signal
*finished = false;
cvar.notify_one();
}

pub fn wait_for_stop_reason_timeout(
Expand All @@ -60,24 +60,22 @@ impl DebuggerTarget {
) -> Option<SingleThreadStopReason<u32>> {
let (lock, cvar) = &*self.stop_signal;
let mut stop_reason = lock.lock().unwrap();
if let Some(stop_reason) = stop_reason.take() {
return Some(stop_reason);
}
let (mut stop_reason, timeout_result) = cvar.wait_timeout(stop_reason, timeout).unwrap();
if timeout_result.timed_out() {
None
} else {
Some(stop_reason.take().expect("None is not expected here"))
let mut timeout_result: WaitTimeoutResult;
while stop_reason.is_none() {
(stop_reason, timeout_result) = cvar.wait_timeout(stop_reason, timeout).unwrap();
if timeout_result.timed_out() {
return None;
}
}
Some(stop_reason.take().expect("None is not expected here"))
}

pub fn wait_for_stop_reason_blocking(&mut self) -> SingleThreadStopReason<u32> {
let (lock, cvar) = &*self.stop_signal;
let mut stop_reason = lock.lock().unwrap();
if let Some(stop_reason) = stop_reason.take() {
return stop_reason;
while stop_reason.is_none() {
stop_reason = cvar.wait(stop_reason).unwrap();
}
let mut stop_reason = cvar.wait(stop_reason).unwrap();
stop_reason.take().expect("None is not expected here")
}

Expand Down Expand Up @@ -106,6 +104,10 @@ impl Target for DebuggerTarget {
fn support_memory_map(&mut self) -> Option<target::ext::memory_map::MemoryMapOps<Self>> {
Some(self)
}

fn support_monitor_cmd(&mut self) -> Option<target::ext::monitor_cmd::MonitorCmdOps<'_, Self>> {
Some(self)
}
}

impl SingleThreadBase for DebuggerTarget {
Expand Down Expand Up @@ -208,3 +210,31 @@ impl target::ext::breakpoints::SwBreakpoint for DebuggerTarget {
Ok(true)
}
}

impl target::ext::monitor_cmd::MonitorCmd for DebuggerTarget {
fn handle_monitor_cmd(
&mut self,
cmd: &[u8],
mut out: ConsoleOutput<'_>,
) -> Result<(), Self::Error> {
let cmd = match std::str::from_utf8(cmd) {
Ok(cmd) => cmd,
Err(_) => {
outputln!(out, "command must be valid UTF-8");
return Ok(());
}
};

match cmd {
"reset" => {
self.debugger_request(DebuggerRequest::Reset);
outputln!(out, "sent reset signal");
}
unk => {
outputln!(out, "unknown command: {}", unk);
}
}

Ok(())
}
}
15 changes: 10 additions & 5 deletions platform/rustboyadvance-sdl2/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use rustboyadvance_core::prelude::*;
use rustboyadvance_utils::FpsCounter;

const LOG_DIR: &str = ".logs";
const DEFAULT_GDB_SERVER_PORT: u16 = 1337;

fn ask_download_bios() {
const OPEN_SOURCE_BIOS_URL: &'static str =
Expand Down Expand Up @@ -113,7 +112,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}

if opts.gdbserver {
gba.start_gdbserver(DEFAULT_GDB_SERVER_PORT);
gba.start_gdbserver(opts.gdbserver_port);
}

let mut vsync = true;
Expand Down Expand Up @@ -144,7 +143,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.unwrap();
info!("ending debugger...")
}
Scancode::F2 => gba.start_gdbserver(DEFAULT_GDB_SERVER_PORT),
Scancode::F2 => gba.start_gdbserver(opts.gdbserver_port),
Scancode::F5 => {
info!("Saving state ...");
let save = gba.save_state()?;
Expand All @@ -159,10 +158,16 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
if opts.savestate_path().is_file() {
let save = read_bin_file(&opts.savestate_path())?;
info!("Restoring state from {:?}...", opts.savestate_path());
let (audio_interface, _sdl_audio_device_new) = audio::create_audio_player(&sdl_context)?;
let (audio_interface, _sdl_audio_device_new) =
audio::create_audio_player(&sdl_context)?;
_sdl_audio_device = _sdl_audio_device_new;
let rom = opts.read_rom()?.into_boxed_slice();
gba = Box::new(GameBoyAdvance::from_saved_state(&save, bios_bin.clone(), rom, audio_interface)?);
gba = Box::new(GameBoyAdvance::from_saved_state(
&save,
bios_bin.clone(),
rom,
audio_interface,
)?);
info!("Restored!");
} else {
info!("Savestate not created, please create one by pressing F5");
Expand Down
5 changes: 4 additions & 1 deletion platform/rustboyadvance-sdl2/src/options.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{path::PathBuf, io};
use std::{io, path::PathBuf};

use rustboyadvance_core::{
cartridge::{BackupType, GamepakBuilder},
Expand Down Expand Up @@ -33,6 +33,9 @@ pub struct Options {
#[structopt(short = "d", long)]
pub gdbserver: bool,

#[structopt(long = "port", default_value = "1337")]
pub gdbserver_port: u16,

/// Force emulation of RTC, use for games that have RTC but the emulator fails to detect
#[structopt(long)]
pub rtc: bool,
Expand Down

0 comments on commit 1dfdec3

Please sign in to comment.