157 lines
4.9 KiB
Rust
157 lines
4.9 KiB
Rust
use gdbstub::common::Pid;
|
|
use gdbstub::target;
|
|
use gdbstub::target::ext::extended_mode::{Args, AttachKind, ShouldTerminate};
|
|
use gdbstub::target::TargetResult;
|
|
|
|
use crate::emu::Emu;
|
|
|
|
/*=====================================
|
|
= Extended Mode =
|
|
=====================================*/
|
|
|
|
// This is a stub implementation of GDB's Extended Mode extensions.
|
|
//
|
|
// Truth be told, this particular emulator is _not_ very well suited to running
|
|
// in extended mode, as it doesn't technically spawn/attach to any process.
|
|
// Nonetheless, it's useful to have a stubbed implementation in-tree which can
|
|
// be used for basic usability / regression testing.
|
|
//
|
|
// If you happen to implement a "proper" extended mode gdbstub, feel free to
|
|
// file an issue / open a PR that links to your project!
|
|
|
|
impl target::ext::extended_mode::ExtendedMode for Emu {
|
|
fn kill(&mut self, pid: Option<Pid>) -> TargetResult<ShouldTerminate, Self> {
|
|
eprintln!("GDB sent a kill request for pid {:?}", pid);
|
|
Ok(ShouldTerminate::No)
|
|
}
|
|
|
|
fn restart(&mut self) -> Result<(), Self::Error> {
|
|
eprintln!("GDB sent a restart request");
|
|
Ok(())
|
|
}
|
|
|
|
fn attach(&mut self, pid: Pid) -> TargetResult<(), Self> {
|
|
eprintln!("GDB tried to attach to a process with PID {}", pid);
|
|
Err(().into()) // non-specific failure
|
|
}
|
|
|
|
fn run(&mut self, filename: Option<&[u8]>, args: Args) -> TargetResult<Pid, Self> {
|
|
// simplified example: assume UTF-8 filenames / args
|
|
//
|
|
// To be 100% pedantically correct, consider converting to an `OsStr` in the
|
|
// least lossy way possible (e.g: using the `from_bytes` extension from
|
|
// `std::os::unix::ffi::OsStrExt`).
|
|
|
|
let filename = match filename {
|
|
None => None,
|
|
Some(raw) => Some(core::str::from_utf8(raw).map_err(drop)?),
|
|
};
|
|
let args = args
|
|
.map(|raw| core::str::from_utf8(raw).map_err(drop))
|
|
.collect::<Result<Vec<_>, _>>()?;
|
|
|
|
eprintln!(
|
|
"GDB tried to run a new process with filename {:?}, and args {:?}",
|
|
filename, args
|
|
);
|
|
|
|
self.reset();
|
|
|
|
// when running in single-threaded mode, this PID can be anything
|
|
Ok(Pid::new(1337).unwrap())
|
|
}
|
|
|
|
fn query_if_attached(&mut self, pid: Pid) -> TargetResult<AttachKind, Self> {
|
|
eprintln!(
|
|
"GDB queried if it was attached to a process with PID {}",
|
|
pid
|
|
);
|
|
Ok(AttachKind::Attach)
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn configure_aslr(&mut self) -> Option<target::ext::extended_mode::ConfigureAslrOps<Self>> {
|
|
Some(self)
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn configure_env(&mut self) -> Option<target::ext::extended_mode::ConfigureEnvOps<Self>> {
|
|
Some(self)
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn configure_startup_shell(
|
|
&mut self,
|
|
) -> Option<target::ext::extended_mode::ConfigureStartupShellOps<Self>> {
|
|
Some(self)
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn configure_working_dir(
|
|
&mut self,
|
|
) -> Option<target::ext::extended_mode::ConfigureWorkingDirOps<Self>> {
|
|
Some(self)
|
|
}
|
|
}
|
|
|
|
impl target::ext::extended_mode::ConfigureAslr for Emu {
|
|
fn cfg_aslr(&mut self, enabled: bool) -> TargetResult<(), Self> {
|
|
eprintln!("GDB {} ASLR", if enabled { "enabled" } else { "disabled" });
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl target::ext::extended_mode::ConfigureEnv for Emu {
|
|
fn set_env(&mut self, key: &[u8], val: Option<&[u8]>) -> TargetResult<(), Self> {
|
|
// simplified example: assume UTF-8 key/val env vars
|
|
let key = core::str::from_utf8(key).map_err(drop)?;
|
|
let val = match val {
|
|
None => None,
|
|
Some(raw) => Some(core::str::from_utf8(raw).map_err(drop)?),
|
|
};
|
|
|
|
eprintln!("GDB tried to set a new env var: {:?}={:?}", key, val);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn remove_env(&mut self, key: &[u8]) -> TargetResult<(), Self> {
|
|
let key = core::str::from_utf8(key).map_err(drop)?;
|
|
eprintln!("GDB tried to set remove a env var: {:?}", key);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn reset_env(&mut self) -> TargetResult<(), Self> {
|
|
eprintln!("GDB tried to reset env vars");
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl target::ext::extended_mode::ConfigureStartupShell for Emu {
|
|
fn cfg_startup_with_shell(&mut self, enabled: bool) -> TargetResult<(), Self> {
|
|
eprintln!(
|
|
"GDB {} startup with shell",
|
|
if enabled { "enabled" } else { "disabled" }
|
|
);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl target::ext::extended_mode::ConfigureWorkingDir for Emu {
|
|
fn cfg_working_dir(&mut self, dir: Option<&[u8]>) -> TargetResult<(), Self> {
|
|
let dir = match dir {
|
|
None => None,
|
|
Some(raw) => Some(core::str::from_utf8(raw).map_err(drop)?),
|
|
};
|
|
|
|
match dir {
|
|
None => eprintln!("GDB reset the working directory"),
|
|
Some(dir) => eprintln!("GDB set the working directory to {:?}", dir),
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|