panda/syscall_injection/
conversion.rs1use crate::sys::target_ulong;
2use async_trait::async_trait;
3
4use std::convert::TryInto;
5
6#[cfg(doc)]
7use super::syscall;
8
9#[async_trait]
14pub trait IntoSyscallArg {
15 async fn into_syscall_arg(self) -> target_ulong;
16}
17
18macro_rules! impl_for_ints {
19 ($($int:ty),*) => {
20 $(
21 #[async_trait]
22 impl IntoSyscallArg for $int {
23 async fn into_syscall_arg(self) -> target_ulong {
24 self.try_into().unwrap()
25 }
26 }
27 )*
28 };
29}
30
31impl_for_ints!(u8, u16, u32, u64);
32
33#[async_trait]
43pub trait IntoSyscallArgs {
44 async fn into_syscall_args(self) -> SyscallArgs;
45}
46
47pub struct SyscallArgs {
52 regs: [target_ulong; 6],
53 regs_used: usize,
54}
55
56impl SyscallArgs {
57 pub fn iter_args(&self) -> impl Iterator<Item = target_ulong> + '_ {
58 self.regs.iter().copied().take(self.regs_used)
59 }
60}
61
62#[doc(hidden)]
63pub struct SyscallCount<const N: usize>;
64
65#[doc(hidden)]
66pub trait LessThan7 {}
67
68impl LessThan7 for SyscallCount<0> {}
69impl LessThan7 for SyscallCount<1> {}
70impl LessThan7 for SyscallCount<2> {}
71impl LessThan7 for SyscallCount<3> {}
72impl LessThan7 for SyscallCount<4> {}
73impl LessThan7 for SyscallCount<5> {}
74impl LessThan7 for SyscallCount<6> {}
75
76#[async_trait]
77impl<Arg: IntoSyscallArg + Send, const N: usize> IntoSyscallArgs for [Arg; N]
78where
79 SyscallCount<N>: LessThan7,
80{
81 async fn into_syscall_args(self) -> SyscallArgs {
82 assert!(N <= 6, "Only up to 6 syscall arguments are allowed");
83 let mut regs = [0; 6];
84 for (i, arg) in IntoIterator::into_iter(self).enumerate() {
85 regs[i] = arg.into_syscall_arg().await;
86 }
87
88 SyscallArgs {
89 regs,
90 regs_used: N as _,
91 }
92 }
93}
94
95macro_rules! impl_for_tuples {
96 ($first:ident $(, $nth:ident)*) => {
97 #[async_trait]
98 impl<$first $(, $nth)*> IntoSyscallArgs for ($first, $($nth),*)
99 where $first: IntoSyscallArg + Send + Sync,
100 $($nth: IntoSyscallArg + Send + Sync),*
101 {
102 #[allow(non_snake_case)]
103 async fn into_syscall_args(self) -> SyscallArgs {
104 let ($first, $($nth),*) = self;
105 let arr = [
106 $first.into_syscall_arg().await,
107 $($nth.into_syscall_arg().await),*
108 ];
109 let mut regs = [0; 6];
110 let regs_used = arr.len();
111
112 regs[..regs_used].copy_from_slice(&arr[..]);
113
114 SyscallArgs { regs, regs_used }
115 }
116 }
117
118 impl_for_tuples!($($nth),*);
119 };
120 () => {
121 #[async_trait]
122 impl IntoSyscallArgs for () {
123 async fn into_syscall_args(self) -> SyscallArgs {
124 SyscallArgs { regs: [0; 6], regs_used: 0 }
125 }
126 }
127 }
128}
129
130impl_for_tuples!(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);