Romain Malmain 43c9100f59
QEMU Synchronous Exit + Syx Snapshot update (#1681)
* Fix: typo in variable name.

* Fix: thread-safe static for emulator initialization.

* Initial support for synchronous exit from QEMU.

* New commands for the sync exit feature.
Supports physical and virtual address requests.
Updated for new SyxSnapshot naming.

* update qemu commit and fix some things

* - Removed lazy_static dependency
- Compiles for usermode
- Format

* Fix warnings

* Fixed sync_exit for missing architectures

---------

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
2023-11-23 17:35:32 +01:00

144 lines
3.4 KiB
Rust

use std::sync::OnceLock;
use capstone::arch::BuildsCapstone;
use enum_map::{enum_map, EnumMap};
use num_enum::{IntoPrimitive, TryFromPrimitive};
#[cfg(feature = "python")]
use pyo3::prelude::*;
pub use strum_macros::EnumIter;
pub use syscall_numbers::aarch64::*;
use crate::{sync_backdoor::SyncBackdoorArgs, CallingConvention};
#[derive(IntoPrimitive, TryFromPrimitive, Debug, Clone, Copy, EnumIter)]
#[repr(i32)]
pub enum Regs {
X0 = 0,
X1 = 1,
X2 = 2,
X3 = 3,
X4 = 4,
X5 = 5,
X6 = 6,
X7 = 7,
X8 = 8,
X9 = 9,
X10 = 10,
X11 = 11,
X12 = 12,
X13 = 13,
X14 = 14,
X15 = 15,
X16 = 16,
X17 = 17,
X18 = 18,
X19 = 19,
X20 = 20,
X21 = 21,
X22 = 22,
X23 = 23,
X24 = 24,
X25 = 25,
X26 = 26,
X27 = 27,
X28 = 28,
X29 = 29,
X30 = 30,
Sp = 31,
Pc = 32,
Pstate = 33,
}
static SYNC_BACKDOOR_ARCH_REGS: OnceLock<EnumMap<SyncBackdoorArgs, Regs>> = OnceLock::new();
pub fn get_sync_backdoor_arch_regs() -> &'static EnumMap<SyncBackdoorArgs, Regs> {
SYNC_BACKDOOR_ARCH_REGS.get_or_init(|| {
enum_map! {
SyncBackdoorArgs::Ret => Regs::X0,
SyncBackdoorArgs::Cmd => Regs::X0,
SyncBackdoorArgs::Arg1 => Regs::X1,
SyncBackdoorArgs::Arg2 => Regs::X2,
SyncBackdoorArgs::Arg3 => Regs::X3,
SyncBackdoorArgs::Arg4 => Regs::X4,
SyncBackdoorArgs::Arg5 => Regs::X5,
SyncBackdoorArgs::Arg6 => Regs::X6,
}
})
}
/// alias registers
#[allow(non_upper_case_globals)]
impl Regs {
pub const Fp: Regs = Regs::X29;
pub const Lr: Regs = Regs::X30;
}
#[cfg(feature = "python")]
impl IntoPy<PyObject> for Regs {
fn into_py(self, py: Python) -> PyObject {
let n: i32 = self.into();
n.into_py(py)
}
}
/// Return an ARM64 ArchCapstoneBuilder
pub fn capstone() -> capstone::arch::arm64::ArchCapstoneBuilder {
capstone::Capstone::new()
.arm64()
.mode(capstone::arch::arm64::ArchMode::Arm)
}
pub type GuestReg = u64;
impl crate::ArchExtras for crate::CPU {
fn read_return_address<T>(&self) -> Result<T, String>
where
T: From<GuestReg>,
{
self.read_reg(Regs::Lr)
}
fn write_return_address<T>(&self, val: T) -> Result<(), String>
where
T: Into<GuestReg>,
{
self.write_reg(Regs::Lr, val)
}
fn read_function_argument<T>(&self, conv: CallingConvention, idx: i32) -> Result<T, String>
where
T: From<GuestReg>,
{
if conv != CallingConvention::Cdecl {
return Err(format!("Unsupported calling convention: {conv:#?}"));
}
match idx {
0 => self.read_reg(Regs::X0),
1 => self.read_reg(Regs::X1),
_ => Err(format!("Unsupported argument: {idx:}")),
}
}
fn write_function_argument<T>(
&self,
conv: CallingConvention,
idx: i32,
val: T,
) -> Result<(), String>
where
T: Into<GuestReg>,
{
if conv != CallingConvention::Cdecl {
return Err(format!("Unsupported calling convention: {conv:#?}"));
}
let val: GuestReg = val.into();
match idx {
0 => self.write_reg(Regs::X0, val),
1 => self.write_reg(Regs::X1, val),
_ => Err(format!("Unsupported argument: {idx:}")),
}
}
}