Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test on AArch64 #4

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -6,6 +6,7 @@ edition = "2018"
[features]
default = []

stub_aarch64 = []
stub_arm = []
stub_x86 = []
stub_mips = []
Expand Down
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -96,6 +96,7 @@ See the `try_stepi.gdb` script for more commands.

| | `--single-step` (`vCont;c;C;s;S`) | (no support) (`vCont;c;C`) |
|:------:|:---------------------------------:|:--------------------------:|
|`aarch64`| `vCont;s:p1.1;c:p1.-1` | `vCont;s:p1.1;c:p1.-1` |
| `arm` | `vCont;c:p1.-1` | `vCont;s:p1.1;c:p1.-1` |
| `mips` | `vCont;c:p1.-1` | `vCont;c:p1.-1` |
| `x86` | `vCont;s:p1.1;c:p1.-1` | `vCont;s:p1.1;c:p1.-1` |
Expand All @@ -105,6 +106,7 @@ See the `try_stepi.gdb` script for more commands.
- This matches the spec.
- The x86 example does _not_ work as expected.
- If `--single-step` is not provided, the GDB stub reports `vCont;c;C`, and the GDB client nonetheless respond with `vCont;s:p1.1;c:p1.-1`! This results in a internal `gdbstub` error, and the example terminates.
- The AArch64 example also assumes support for `vCont`.
- The MIPS example is interesting.
- Regardless if `--single-step` was provided, the GDB client will _never_ send a `vCont;s:pX.X` packet!
- While this isn't strictly an "error", it is nonetheless weird that the GDB client doesn't attempt to use the target's "native" single step feature.
Expand Down
2 changes: 1 addition & 1 deletion check_vcont.sh
Expand Up @@ -8,7 +8,7 @@ function run_test {
${gdb} -x try_stepi.gdb -ex quit &>/dev/null
kill ${cargo} &>/dev/null
}
declare -A supported_archs=([arm]= [mips]= [x86]=)
declare -A supported_archs=([aarch64]= [arm]= [mips]= [x86]=)

export RUST_LOG="error,gdbstub::protocol=trace"

Expand Down
108 changes: 108 additions & 0 deletions src/gdb_aarch64.rs
@@ -0,0 +1,108 @@
use gdbstub::arch::{Arch, SingleStepGdbBehavior};
use gdbstub::common::Signal;
use gdbstub::target;
use gdbstub::target::ext::base::singlethread::{SingleThreadBase, SingleThreadResume};
use gdbstub::target::{Target, TargetResult};

use crate::emu::{Emu, ExecMode};

impl Target for Emu<u64> {
type Arch = gdbstub_arch::aarch64::AArch64;
type Error = &'static str;

#[inline(always)]
fn base_ops(&mut self) -> target::ext::base::BaseOps<Self::Arch, Self::Error> {
target::ext::base::BaseOps::SingleThread(self)
}

#[inline(always)]
fn guard_rail_implicit_sw_breakpoints(&self) -> bool {
true
}

#[inline(always)]
fn guard_rail_single_step_gdb_behavior(&self) -> SingleStepGdbBehavior {
if !self.with_guard_rail {
SingleStepGdbBehavior::Optional
} else {
Self::Arch::single_step_gdb_behavior()
}
}
}

impl SingleThreadResume for Emu<u64> {
fn resume(&mut self, signal: Option<Signal>) -> Result<(), Self::Error> {
if signal.is_some() {
return Err("no support for continuing with signal");
}

self.exec_mode = ExecMode::Continue;

Ok(())
}

#[inline(always)]
fn support_single_step(
&mut self,
) -> Option<target::ext::base::singlethread::SingleThreadSingleStepOps<Self>> {
if self.with_single_step {
Some(self)
} else {
None
}
}
}

impl SingleThreadBase for Emu<u64> {
fn read_registers(
&mut self,
regs: &mut gdbstub_arch::aarch64::reg::AArch64CoreRegs,
) -> TargetResult<(), Self> {
log::debug!("read_registers");

for (i, reg) in regs.x.iter_mut().enumerate() {
*reg = i as u64;
}
regs.pc = 0x5555_0000;

Ok(())
}

fn write_registers(
&mut self,
regs: &gdbstub_arch::aarch64::reg::AArch64CoreRegs,
) -> TargetResult<(), Self> {
log::debug!("write_registers: {:#x?}", regs);
Ok(())
}

fn read_addrs(&mut self, start_addr: u64, data: &mut [u8]) -> TargetResult<(), Self> {
log::debug!("read_addrs: {:#x?},{}", start_addr, data.len());
data.fill(0x00); // nop
Ok(())
}

fn write_addrs(&mut self, start_addr: u64, data: &[u8]) -> TargetResult<(), Self> {
log::debug!("write_addrs: {:#x?},{:x?}", start_addr, data);
Ok(())
}

#[inline(always)]
fn support_resume(
&mut self,
) -> Option<target::ext::base::singlethread::SingleThreadResumeOps<'_, Self>> {
Some(self)
}
}

impl target::ext::base::singlethread::SingleThreadSingleStep for Emu<u64> {
fn step(&mut self, signal: Option<Signal>) -> Result<(), Self::Error> {
if signal.is_some() {
return Err("no support for stepping with signal");
}

self.exec_mode = ExecMode::Step;

Ok(())
}
}
26 changes: 20 additions & 6 deletions src/main.rs
Expand Up @@ -10,18 +10,32 @@ use gdbstub::target::Target;

mod emu;

#[cfg(feature = "stub_aarch64")]
mod gdb_aarch64;
#[cfg(feature = "stub_arm")]
mod gdb_arm;
#[cfg(feature = "stub_mips")]
mod gdb_mips;
#[cfg(feature = "stub_x86")]
mod gdb_x86;
#[cfg(all(
not(feature = "stub_arm"),
not(feature = "stub_x86"),
not(feature = "stub_mips")
))]
compile_error!("must compile with either --feature 'stub_arm' or --feature 'stub_x86' or --feature 'stub_mips'");
#[cfg(not(any(
feature = "stub_aarch64",
feature = "stub_arm",
feature = "stub_mips",
feature = "stub_x86",
)))]
#[rustfmt::skip]
compile_error!(concat!(
"must compile with one --feature from [",
"stub_aarch64",
", ",
"stub_arm",
", ",
"stub_mips",
", ",
"stub_x86",
"]"
));

pub type DynResult<T> = Result<T, Box<dyn std::error::Error>>;

Expand Down