Skip to content

Commit

Permalink
implement RegId for x86
Browse files Browse the repository at this point in the history
This is one of action items in issue daniel5151#29.
  • Loading branch information
keiichiw committed Oct 28, 2020
1 parent da716bd commit 7035a35
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 3 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -16,6 +16,7 @@ categories = ["development-tools::debugging", "embedded", "emulators", "network-
cfg-if = "0.1"
log = "0.4"
managed = { version = "0.8", default-features = false }
num-derive = { version = "0.3", default-features = false }
num-traits = { version = "0.2", default-features = false }
paste = "1.0"

Expand Down
2 changes: 1 addition & 1 deletion src/arch/x86/mod.rs
Expand Up @@ -32,7 +32,7 @@ impl<RegIdImpl: RegId> Arch for X86_64_SSE<RegIdImpl> {
/// Check out the [module level docs](../index.html#whats-with-regidimpl) for
/// more info about the `RegIdImpl` type parameter.
#[allow(non_camel_case_types)]
pub enum X86_SSE<RegIdImpl: RegId> {
pub enum X86_SSE<RegIdImpl: RegId = reg::id::X86CoreRegId> {
#[doc(hidden)]
_Marker(core::marker::PhantomData<RegIdImpl>),
}
Expand Down
130 changes: 128 additions & 2 deletions src/arch/x86/reg/id.rs
@@ -1,5 +1,131 @@
// TODO: Add proper `RegId` implementation. See [issue #29](https://github.com/daniel5151/gdbstub/issues/29)
// pub enum X86RegId {}
use crate::arch::RegId;
use num_traits::cast::FromPrimitive;

/// FPU register identifier.
#[derive(Debug, Clone, Copy, FromPrimitive)]
pub enum X87FpuInternalRegId {
/// Floating-point control register
Fctrl,
/// Floating-point status register
Fstat,
/// Tag word
Ftag,
/// FPU instruction pointer segment
Fiseg,
/// FPU intstruction pointer offset
Fioff,
/// FPU operand segment
Foseg,
/// FPU operand offset
Fooff,
/// Floating-point opcode
Fop,
}

/// 32-bit x86 core + SSE register identifier.
///
/// Source: https://github.com/bminor/binutils-gdb/blob/master/gdb/features/i386/32bit-core.xml
/// Additionally: https://github.com/bminor/binutils-gdb/blob/master/gdb/features/i386/32bit-sse.xml
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub enum X86CoreRegId {
/// Accumulator
Eax,
/// Count register
Ecx,
/// Data register
Edx,
/// Base register
Ebx,
/// Stack pointer
Esp,
/// Base pointer
Ebp,
/// Source index
Esi,
/// Destination index
Edi,
/// Instruction pointer
Eip,
/// Status register
Eflags,
/// Segment registers: CS, SS, DS, ES, FS, GS
Segment(u8),
/// FPU registers: ST0 through ST7
St(u8),
/// FPU internal registers
Fpu(X87FpuInternalRegId),
/// SIMD Registers: XMM0 through XMM7
Xmm(u8),
/// SSE Status/Control Register
Mxcsr,
}

impl RegId for X86CoreRegId {
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
use crate::arch::x86::reg::id::X86CoreRegId::*;

let r = match id {
0 => (Eax, 4),
1 => (Ecx, 4),
2 => (Edx, 4),
3 => (Ebx, 4),
4 => (Esp, 4),
5 => (Ebp, 4),
6 => (Esi, 4),
7 => (Edi, 4),
8 => (Eip, 4),
9 => (Eflags, 4),
10..=15 => (Segment(id as u8 - 10), 4),
16..=23 => (St(id as u8 - 16), 10),
24..=31 => {
// Safe because `(id as u8 - 24)` must be within `0..8`.
let fpu_id = FromPrimitive::from_u8(id as u8 - 24).unwrap();
(Fpu(fpu_id), 4)
}
32..=39 => (Xmm(id as u8 - 32), 16),
40 => (Mxcsr, 4),
_ => return None,
};
Some(r)
}
}

// TODO: Add proper `RegId` implementation. See [issue #29](https://github.com/daniel5151/gdbstub/issues/29)
// pub enum X86_64RegId {}

#[cfg(test)]
mod tests {
use crate::arch::traits::RegId;
use crate::arch::traits::Registers;

/// Compare the following two values which are expected to be the same:
/// * length of data written by `Registers::gdb_serialize()` in byte
/// * sum of sizes of all registers obtained by `RegId::from_raw_id()`
fn test<Rs: Registers, RId: RegId>() {
// Obtain the data length written by `gdb_serialize` by passing a custom
// closure.
let mut serialized_data_len = 0;
let counter = |b: Option<u8>| {
if b.is_some() {
serialized_data_len += 1;
}
};
Rs::default().gdb_serialize(counter);

// Accumulate register sizes returned by `from_raw_id`.
let mut i = 0;
let mut sum_reg_sizes = 0;
while let Some((_, size)) = RId::from_raw_id(i) {
sum_reg_sizes += size;
i += 1;
}

assert_eq!(serialized_data_len, sum_reg_sizes);
}

#[test]
fn test_x86() {
test::<crate::arch::x86::reg::X86CoreRegs, crate::arch::x86::reg::id::X86CoreRegId>()
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Expand Up @@ -129,6 +129,8 @@
#[cfg(feature = "alloc")]
extern crate alloc;

#[macro_use]
extern crate num_derive;
#[macro_use]
extern crate log;

Expand Down

0 comments on commit 7035a35

Please sign in to comment.