Verified Commit d95475a2 authored by jD91mZM2's avatar jD91mZM2

Initial commit

I intend to get this sort of working on Linux before porting it to
Redox OS. Should be simple as I've abstracted away all internals
parents
use nix
/target
**/*.rs.bk
a.out
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atty"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clap"
version = "2.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gdb-protocol"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gdbserver"
version = "0.1.0"
dependencies = [
"gdb-protocol 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "heck"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "structopt"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "structopt-derive"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.15.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-segmentation"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-width"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vec_map"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum gdb-protocol 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8b88b222a91266bb192222d46d0da29addbc423d0a9910aec233dce875eb6e"
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7"
"checksum structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107"
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[package]
name = "gdbserver"
version = "0.1.0"
authors = ["jD91mZM2 <me@krake.one>"]
edition = "2018"
[dependencies]
gdb-protocol = "0.1.0"
# gdb-protocol = { git = "https://gitlab.redox-os.org/redox-os/gdb-protocol" }
# gdb-protocol = { path = "../gdb-protocol/" }
structopt = "0.2.18"
memchr = "2.2.1"
libc = "0.2.62"
MIT License
Copyright (c) 2019 jD91mZM2
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# gdbserver
A GDB Remote Serial Protocol server for Rust, intended to be a simple
GDBserver for at least Linux and Redox running on the x86_64
architecture rewritten in Rust.
Redox OS internals isn't implemented yet but it should be easy once
Linux somewhat works.
Current status:
![Screenshot of debugging with GDB](https://i.imgur.com/LVCdO1S.png)
{ pkgs ? import <nixpkgs> {} }:
let
gdb-init = pkgs.writers.writeBashBin "gdb" ''
${pkgs.gdb}/bin/gdb "$@" \
-ex "set tdesc filename ${./target-desc.xml}" \
-ex "set debug remote 1"
'';
in pkgs.mkShell {
nativeBuildInputs = [ gdb-init ];
}
use gdb_protocol::{packet::{CheckedPacket, Kind}, io::GdbServer};
use structopt::StructOpt;
use std::io::prelude::*;
mod os;
use os::{Os, Registers, Status, Target};
#[derive(Debug, StructOpt)]
struct Opt {
/// The address which to bind the server to
#[structopt(short = "a", long = "addr", default_value = "0.0.0.0:64126")]
addr: String,
/// The program that should be debugged
program: String,
/// The arguments of the program
args: Vec<String>,
}
pub type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
// fn get_hex_int(buf: &[u8]) -> Result<(&[u8], usize)> {
// let nondigit = buf.iter().position(|b| !(b as char).is_digit(16));
// let (digits, trail) = buf.split_at(nondigit);
// let string = std::str::from_utf8(&digits)?;
// Ok((&trail, string.parse()?))
// }
fn encode_status(tracee: &mut Os) -> CheckedPacket {
let mut bytes = Vec::new();
match tracee.status() {
Status::Exited(status) => write!(bytes, "W{:02X}", status).unwrap(),
Status::Signaled(status) => write!(bytes, "X{:02X}", status).unwrap(),
Status::Stopped(status) => write!(bytes, "T{:02X}", status).unwrap(),
}
CheckedPacket::from_data(Kind::Packet, bytes)
}
fn main() -> Result<()> {
let mut opt = Opt::from_args();
let mut stream = GdbServer::listen(opt.addr)?;
opt.args.insert(0, opt.program.clone());
let mut tracee = Os::new(opt.program, opt.args)?;
while let Some(packet) = stream.next_packet()? {
println!(
"-> {:?} {:?}",
packet.kind,
std::str::from_utf8(&packet.data)
);
stream.dispatch(&match packet.data.first() {
// Maybe extended mode isn't that good, as it'll allow GDB to read the whole filesystem
// Some(b'!') => {
// CheckedPacket::from_data(Kind::Packet, b"OK".to_vec())
// },
Some(b'?') => encode_status(&mut tracee),
Some(b'g') => {
let mut out = Vec::new();
match tracee.getregs() {
Ok(regs) => regs.encode(&mut out)?,
Err(errno) => write!(out, "E{:02X}", errno).unwrap()
}
CheckedPacket::from_data(Kind::Packet, out)
},
Some(b'G') => {
let mut out = Vec::new();
let regs = Registers::decode(&packet.data[1..])?;
match tracee.setregs(&regs) {
Ok(()) => write!(out, "OK").unwrap(),
Err(errno) => write!(out, "E{:02X}", errno).unwrap(),
}
CheckedPacket::from_data(Kind::Packet, out)
},
Some(b'm') => {
let data = &packet.data[1..];
let sep = memchr::memchr(b',', &data).ok_or("gdb didn't send a memory length")?;
let (addr, len) = data.split_at(sep);
let addr = usize::from_str_radix(std::str::from_utf8(&addr)?, 16)?;
let len = usize::from_str_radix(std::str::from_utf8(&len[1..])?, 16)?;
let mut out = Vec::new();
let mut bytes = vec![0; len];
match tracee.getmem(addr, &mut bytes) {
Ok(read) => for byte in &bytes[..read] {
write!(out, "{:02X}", byte).unwrap();
},
Err(errno) => write!(out, "E{:02X}", errno).unwrap(),
}
CheckedPacket::from_data(Kind::Packet, out)
},
Some(b'M') => {
let data = &packet.data[1..];
let sep1 = memchr::memchr(b',', &data).ok_or("gdb didn't send a memory length")?;
let (addr, rest) = data.split_at(sep1);
let sep2 = memchr::memchr(b':', &rest).ok_or("gdb didn't send memory content")?;
let (_, content) = rest.split_at(sep2);
let addr = usize::from_str_radix(std::str::from_utf8(&addr)?, 16)?;
// let len = usize::from_str_radix(std::str::from_utf8(&len[1..])?, 16)?;
let mut bytes = Vec::new();
for byte in content[1..].chunks(2) {
bytes.push(u8::from_str_radix(std::str::from_utf8(&byte)?, 16)?);
}
let mut out = Vec::new();
match tracee.setmem(&bytes, addr) {
Ok(()) => write!(out, "OK").unwrap(),
Err(errno) => write!(out, "E{:02X}", errno).unwrap(),
}
CheckedPacket::from_data(Kind::Packet, out)
},
Some(b'v') => {
// if packet.data[1..].starts_with(b"Run") {
// let mut cursor = &packet.data[1..];
// loop {
// let arg_end = memchr::memchr(b';', &cursor);
// println!("Arg: {:?}", std::str::from_utf8(&cursor[..arg_end.unwrap_or_else(|| cursor.len())]));
// match arg_end {
// Some(arg_end) => cursor = &cursor[arg_end+1..],
// None => break,
// }
// }
// CheckedPacket::from_data(Kind::Packet, b"W00".to_vec())
if packet.data[1..].starts_with(b"Cont") {
let data = &packet.data[1 + 4..];
match data.first() {
Some(b'?') => CheckedPacket::from_data(Kind::Packet, b"vCont;s;c;S;C;r".to_vec()),
Some(b';') => match data.get(1) {
Some(b's') => {
tracee.step(None)?;
encode_status(&mut tracee)
},
Some(b'S') => {
let slice = data.get(2..4).ok_or("gdb didn't send a signal")?;
let signal = u8::from_str_radix(std::str::from_utf8(&slice)?, 16)?;
tracee.step(Some(signal))?;
encode_status(&mut tracee)
},
Some(b'c') => {
tracee.cont(None)?;
encode_status(&mut tracee)
},
Some(b'C') => {
let slice = data.get(2..4).ok_or("gdb didn't send a signal")?;
let signal = u8::from_str_radix(std::str::from_utf8(&slice)?, 16)?;
tracee.cont(Some(signal))?;
encode_status(&mut tracee)
},
Some(b'r') => {
let data = &data[2..];
let sep1 = memchr::memchr(b',', data).ok_or("gdb didn't send an end value")?;
let (start, end) = data.split_at(sep1);
let sep2 = memchr::memchr(b':', end).unwrap_or_else(|| end.len());
let start = u64::from_str_radix(std::str::from_utf8(start)?, 16)?;
let end = u64::from_str_radix(std::str::from_utf8(&end[1..sep2])?, 16)?;
tracee.resume(start..end)?;
encode_status(&mut tracee)
},
_ => CheckedPacket::empty()
},
_ => CheckedPacket::empty()
}
} else if packet.data[1..].starts_with(b"Kill") {
break;
} else {
CheckedPacket::empty()
}
},
_ => CheckedPacket::empty(),
})?;
}
Ok(())
}
use crate::Result;
use super::{Registers, Status};
use std::{
ffi::CString,
io,
iter,
mem::{self, MaybeUninit},
ptr,
};
pub struct Os {
pid: libc::pid_t,
last_status: libc::c_int,
}
// Handle error as Rust: Return an io::Error
macro_rules! re {
($result:expr) => {{
let result = $result;
if result == -1 {
return Err(Box::new(io::Error::last_os_error()));
}
result
}}
}
// Handle error as C: Return the errno
macro_rules! ce {
($result:expr) => {{
let result = $result;
if result == -1 {
return Err(*libc::__errno_location() as i32);
}
result
}}
}
impl super::Target for Os {
fn new(program: String, args: Vec<String>) -> Result<Self> {
let program = CString::new(program)?.into_raw();
let args = args.into_iter()
.map(|s| CString::new(s).map(|s| s.into_raw() as *const _))
.chain(iter::once(Ok(ptr::null())))
.collect::<Result<Vec<*const libc::c_char>, _>>()?;
unsafe {
let pid = libc::fork();
if pid == 0 {
// Must not drop any memory, not unwind (panic).
if libc::ptrace(libc::PTRACE_TRACEME) < 0 {
eprintln!("ptrace(PTRACE_TRACEME) failed: {:?}", io::Error::last_os_error());
libc::exit(1);
}
if libc::raise(libc::SIGSTOP) < 0 {
eprintln!("raise(SIGSTOP) failed: {:?}", io::Error::last_os_error());
libc::exit(1);
}
if libc::execvp(program, args.as_ptr()) < 0 {
eprintln!("execv(...) failed: {:?}", io::Error::last_os_error());
libc::exit(1);
}
eprintln!("execv(...) should not be able to succeed");
libc::exit(1);
} else {
// Drop variables only the child needed
CString::from_raw(program);
for arg in args {
if !arg.is_null() {
// We originally get mutable memory, don't worry!
CString::from_raw(arg as *mut _);
}
}
// Wait for tracee to stop
let mut status = 0;
re!(libc::waitpid(pid, &mut status, 0));
// Skip until post-execve
re!(libc::ptrace(libc::PTRACE_CONT, pid, 0, 0));
re!(libc::waitpid(pid, &mut status, 0));
Ok(Os {
pid,
last_status: status,
})
}
}
}
fn status(&mut self) -> Status {
unsafe {
if libc::WIFEXITED(self.last_status) {
Status::Exited(libc::WEXITSTATUS(self.last_status))
} else if libc::WIFSIGNALED(self.last_status) {
Status::Signaled(libc::WTERMSIG(self.last_status))
} else if libc::WIFSTOPPED(self.last_status) {
Status::Stopped(libc::WSTOPSIG(self.last_status))
} else {
unimplemented!("TODO: Implement status {}", self.last_status);
}
}
}
fn getregs(&mut self) -> Result<Registers, i32> {
let int = unsafe {
let mut int: MaybeUninit<libc::user_regs_struct> = MaybeUninit::uninit();
ce!(libc::ptrace(libc::PTRACE_GETREGS, self.pid, 0, int.as_mut_ptr()));
int.assume_init()
};
let float = unsafe {
let mut float: MaybeUninit<libc::user_fpregs_struct> = MaybeUninit::uninit();
ce!(libc::ptrace(libc::PTRACE_GETFPREGS, self.pid, 0, float.as_mut_ptr()));
float.assume_init()
};
let mut registers = Registers::default();
registers.r15 = Some(int.r15);
registers.r14 = Some(int.r14);
registers.r13 = Some(int.r13);
registers.r12 = Some(int.r12);
registers.rbp = Some(int.rbp);
registers.rbx = Some(int.rbx);
registers.r11 = Some(int.r11);
registers.r10 = Some(int.r10);
registers.r9 = Some(int.r9);
registers.r8 = Some(int.r8);
registers.rax = Some(int.rax);
registers.rcx = Some(int.rcx);
registers.rdx = Some(int.rdx);
registers.rsi = Some(int.rsi);
registers.rdi = Some(int.rdi);
registers.rip = Some(int.rip);
registers.cs = Some(int.cs as _);
registers.eflags = Some(int.eflags as _);
registers.rsp = Some(int.rsp);
registers.ss = Some(int.ss as _);
registers.ds = Some(int.ds as _);
registers.es = Some(int.es as _);
registers.fs = Some(int.fs as _);
registers.gs = Some(int.gs as _);
registers.fcw = Some(float.cwd as _);
registers.fop = Some(float.fop as _);
registers.mxcsr = Some(float.mxcsr);
registers.st0 = Some(float.st_space[0] as _);
registers.st1 = Some(float.st_space[1] as _);
registers.st2 = Some(float.st_space[2] as _);
registers.st3 = Some(float.st_space[3] as _);
registers.st4 = Some(float.st_space[4] as _);
registers.st5 = Some(float.st_space[5] as _);
registers.st6 = Some(float.st_space[6] as _);
registers.st7 = Some(float.st_space[7] as _);
registers.xmm0 = Some(float.xmm_space[0] as _);
registers.xmm1 = Some(float.xmm_space[1] as _);
registers.xmm2 = Some(float.xmm_space[2] as _);
registers.xmm3 = Some(float.xmm_space[3] as _);
registers.xmm4 = Some(float.xmm_space[4] as _);
registers.xmm5 = Some(float.xmm_space[5] as _);
registers.xmm6 = Some(float.xmm_space[6] as _);
registers.xmm7 = Some(float.xmm_space[7] as _);
registers.xmm8 = Some(float.xmm_space[8] as _);
registers.xmm9 = Some(float.xmm_space[9] as _);
registers.xmm10 = Some(float.xmm_space[10] as _);
registers.xmm11 = Some(float.xmm_space[11] as _);
registers.xmm12 = Some(float.xmm_space[12] as _);
registers.xmm13 = Some(float.xmm_space[13] as _);
registers.xmm14 = Some(float.xmm_space[14] as _);
registers.xmm15 = Some(float.xmm_space[15] as _);
Ok(registers)
}
fn setregs(&mut self, registers: &Registers) -> Result<(), i32> {
let mut int: libc::user_regs_struct = unsafe { MaybeUninit::zeroed().assume_init() };
let mut float: libc::user_fpregs_struct = unsafe { MaybeUninit::zeroed().assume_init() };
int.r15 = registers.r15.unwrap_or(int.r15);
int.r14 = registers.r14.unwrap_or(int.r14);
int.r13 = registers.r13.unwrap_or(int.r13);
int.r12 = registers.r12.unwrap_or(int.r12);
int.rbp = registers.rbp.unwrap_or(int.rbp);
int.rbx = registers.rbx.unwrap_or(int.rbx);
int.r11 = registers.r11.unwrap_or(int.r11);
int.r10 = registers.r10.unwrap_or(int.r10);
int.r9 = registers.r9.unwrap_or(int.r9);
int.r8 = registers.r8.unwrap_or(int.r8);
int.rax = registers.rax.unwrap_or(int.rax);
int.rcx = registers.rcx.unwrap_or(int.rcx);
int.rdx = registers.rdx.unwrap_or(int.rdx);