Skip to content

Commit

Permalink
Add support for AArch64
Browse files Browse the repository at this point in the history
Add a stub for the arch (currently only works with a local branch).

Add the result of my observation to the README.

Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
  • Loading branch information
ptosi committed Jul 28, 2022
1 parent 4fc2be6 commit 75b971d
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 1 deletion.
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(())
}
}
5 changes: 5 additions & 0 deletions src/main.rs
Expand Up @@ -10,20 +10,25 @@ 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(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",
Expand Down

0 comments on commit 75b971d

Please sign in to comment.