• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Syscall wrappers for 32-bit x86.
2 //!
3 //! This module is similar to the `nr_last` module, except specialized for
4 //! 32-bit x86.
5 //!
6 //! The syscall convention passes all arguments in registers. The closest we
7 //! can easily get to that from Rust is to use the fastcall convention which
8 //! passes the first two arguments in `ecx` and `edx`, which are the second
9 //! and third Linux syscall arguments. To line them up, this function passes
10 //! the second and third syscall argument as the first and second argument to
11 //! the outline assembly, followed by the first syscall argument, and then the
12 //! rest of the syscall arguments. The assembly code still has to do some work,
13 //! but at least we can get up to two arguments into the right place for it.
14 
15 #![allow(dead_code, unused_imports)]
16 
17 use crate::backend::reg::{ArgReg, RetReg, SyscallNumber, A0, A1, A2, A3, A4, A5, R0};
18 use crate::backend::vdso_wrappers::SyscallType;
19 
20 // First we declare the actual assembly routines with `*_nr_last_fastcall`
21 // names and reordered arguments. If the signatures or calling conventions are
22 // ever changed, the symbol names should also be updated accordingly, to avoid
23 // collisions with other versions of this crate.
24 //
25 // We don't define `_readonly` versions of these because we have no way to tell
26 // Rust that calls to our outline assembly are readonly.
27 extern "fastcall" {
rustix_syscall0_nr_last_fastcall(nr: SyscallNumber<'_>) -> RetReg<R0>28     fn rustix_syscall0_nr_last_fastcall(nr: SyscallNumber<'_>) -> RetReg<R0>;
rustix_syscall1_nr_last_fastcall(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> RetReg<R0>29     fn rustix_syscall1_nr_last_fastcall(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> RetReg<R0>;
rustix_syscall1_noreturn_nr_last_fastcall(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> !30     fn rustix_syscall1_noreturn_nr_last_fastcall(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> !;
rustix_syscall2_nr_last_fastcall( a1: ArgReg<'_, A1>, a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>, ) -> RetReg<R0>31     fn rustix_syscall2_nr_last_fastcall(
32         a1: ArgReg<'_, A1>,
33         a0: ArgReg<'_, A0>,
34         nr: SyscallNumber<'_>,
35     ) -> RetReg<R0>;
rustix_syscall3_nr_last_fastcall( a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>, ) -> RetReg<R0>36     fn rustix_syscall3_nr_last_fastcall(
37         a1: ArgReg<'_, A1>,
38         a2: ArgReg<'_, A2>,
39         a0: ArgReg<'_, A0>,
40         nr: SyscallNumber<'_>,
41     ) -> RetReg<R0>;
rustix_syscall4_nr_last_fastcall( a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a0: ArgReg<'_, A0>, a3: ArgReg<'_, A3>, nr: SyscallNumber<'_>, ) -> RetReg<R0>42     fn rustix_syscall4_nr_last_fastcall(
43         a1: ArgReg<'_, A1>,
44         a2: ArgReg<'_, A2>,
45         a0: ArgReg<'_, A0>,
46         a3: ArgReg<'_, A3>,
47         nr: SyscallNumber<'_>,
48     ) -> RetReg<R0>;
rustix_syscall5_nr_last_fastcall( a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a0: ArgReg<'_, A0>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, nr: SyscallNumber<'_>, ) -> RetReg<R0>49     fn rustix_syscall5_nr_last_fastcall(
50         a1: ArgReg<'_, A1>,
51         a2: ArgReg<'_, A2>,
52         a0: ArgReg<'_, A0>,
53         a3: ArgReg<'_, A3>,
54         a4: ArgReg<'_, A4>,
55         nr: SyscallNumber<'_>,
56     ) -> RetReg<R0>;
rustix_syscall6_nr_last_fastcall( a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a0: ArgReg<'_, A0>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, a5: ArgReg<'_, A5>, nr: SyscallNumber<'_>, ) -> RetReg<R0>57     fn rustix_syscall6_nr_last_fastcall(
58         a1: ArgReg<'_, A1>,
59         a2: ArgReg<'_, A2>,
60         a0: ArgReg<'_, A0>,
61         a3: ArgReg<'_, A3>,
62         a4: ArgReg<'_, A4>,
63         a5: ArgReg<'_, A5>,
64         nr: SyscallNumber<'_>,
65     ) -> RetReg<R0>;
66 }
67 
68 // Then we define inline wrapper functions that do the reordering.
69 
70 #[inline]
syscall0(nr: SyscallNumber<'_>) -> RetReg<R0>71 pub(in crate::backend) unsafe fn syscall0(nr: SyscallNumber<'_>) -> RetReg<R0> {
72     rustix_syscall0_nr_last_fastcall(nr)
73 }
74 #[inline]
syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0>75 pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
76     rustix_syscall1_nr_last_fastcall(a0, nr)
77 }
78 #[inline]
syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> !79 pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
80     rustix_syscall1_noreturn_nr_last_fastcall(a0, nr)
81 }
82 #[inline]
syscall2( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, ) -> RetReg<R0>83 pub(in crate::backend) unsafe fn syscall2(
84     nr: SyscallNumber<'_>,
85     a0: ArgReg<'_, A0>,
86     a1: ArgReg<'_, A1>,
87 ) -> RetReg<R0> {
88     rustix_syscall2_nr_last_fastcall(a1, a0, nr)
89 }
90 #[inline]
syscall3( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, ) -> RetReg<R0>91 pub(in crate::backend) unsafe fn syscall3(
92     nr: SyscallNumber<'_>,
93     a0: ArgReg<'_, A0>,
94     a1: ArgReg<'_, A1>,
95     a2: ArgReg<'_, A2>,
96 ) -> RetReg<R0> {
97     rustix_syscall3_nr_last_fastcall(a1, a2, a0, nr)
98 }
99 #[inline]
syscall4( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, ) -> RetReg<R0>100 pub(in crate::backend) unsafe fn syscall4(
101     nr: SyscallNumber<'_>,
102     a0: ArgReg<'_, A0>,
103     a1: ArgReg<'_, A1>,
104     a2: ArgReg<'_, A2>,
105     a3: ArgReg<'_, A3>,
106 ) -> RetReg<R0> {
107     rustix_syscall4_nr_last_fastcall(a1, a2, a0, a3, nr)
108 }
109 #[inline]
syscall5( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, ) -> RetReg<R0>110 pub(in crate::backend) unsafe fn syscall5(
111     nr: SyscallNumber<'_>,
112     a0: ArgReg<'_, A0>,
113     a1: ArgReg<'_, A1>,
114     a2: ArgReg<'_, A2>,
115     a3: ArgReg<'_, A3>,
116     a4: ArgReg<'_, A4>,
117 ) -> RetReg<R0> {
118     rustix_syscall5_nr_last_fastcall(a1, a2, a0, a3, a4, nr)
119 }
120 #[inline]
syscall6( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, a5: ArgReg<'_, A5>, ) -> RetReg<R0>121 pub(in crate::backend) unsafe fn syscall6(
122     nr: SyscallNumber<'_>,
123     a0: ArgReg<'_, A0>,
124     a1: ArgReg<'_, A1>,
125     a2: ArgReg<'_, A2>,
126     a3: ArgReg<'_, A3>,
127     a4: ArgReg<'_, A4>,
128     a5: ArgReg<'_, A5>,
129 ) -> RetReg<R0> {
130     rustix_syscall6_nr_last_fastcall(a1, a2, a0, a3, a4, a5, nr)
131 }
132 
133 // Then we define the `_readonly` versions of the wrappers. We don't have
134 // separate `_readonly` implementations, so these can just be aliases to
135 // their non-`_readonly` counterparts.
136 pub(in crate::backend) use {
137     syscall0 as syscall0_readonly, syscall1 as syscall1_readonly, syscall2 as syscall2_readonly,
138     syscall3 as syscall3_readonly, syscall4 as syscall4_readonly, syscall5 as syscall5_readonly,
139     syscall6 as syscall6_readonly,
140 };
141 
142 // x86 prefers to route all syscalls through the vDSO, though this isn't
143 // always possible, so it also has a special form for doing the dispatch.
144 //
145 // First we declare the actual assembly routines with `*_nr_last_fastcall`
146 // names and reordered arguments. If the signatures or calling conventions are
147 // ever changed, the symbol names should also be updated accordingly, to avoid
148 // collisions with other versions of this crate.
149 extern "fastcall" {
rustix_indirect_syscall0_nr_last_fastcall( nr: SyscallNumber<'_>, callee: SyscallType, ) -> RetReg<R0>150     fn rustix_indirect_syscall0_nr_last_fastcall(
151         nr: SyscallNumber<'_>,
152         callee: SyscallType,
153     ) -> RetReg<R0>;
rustix_indirect_syscall1_nr_last_fastcall( a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>, callee: SyscallType, ) -> RetReg<R0>154     fn rustix_indirect_syscall1_nr_last_fastcall(
155         a0: ArgReg<'_, A0>,
156         nr: SyscallNumber<'_>,
157         callee: SyscallType,
158     ) -> RetReg<R0>;
rustix_indirect_syscall1_noreturn_nr_last_fastcall( a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>, callee: SyscallType, ) -> !159     fn rustix_indirect_syscall1_noreturn_nr_last_fastcall(
160         a0: ArgReg<'_, A0>,
161         nr: SyscallNumber<'_>,
162         callee: SyscallType,
163     ) -> !;
rustix_indirect_syscall2_nr_last_fastcall( a1: ArgReg<'_, A1>, a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>, callee: SyscallType, ) -> RetReg<R0>164     fn rustix_indirect_syscall2_nr_last_fastcall(
165         a1: ArgReg<'_, A1>,
166         a0: ArgReg<'_, A0>,
167         nr: SyscallNumber<'_>,
168         callee: SyscallType,
169     ) -> RetReg<R0>;
rustix_indirect_syscall3_nr_last_fastcall( a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>, callee: SyscallType, ) -> RetReg<R0>170     fn rustix_indirect_syscall3_nr_last_fastcall(
171         a1: ArgReg<'_, A1>,
172         a2: ArgReg<'_, A2>,
173         a0: ArgReg<'_, A0>,
174         nr: SyscallNumber<'_>,
175         callee: SyscallType,
176     ) -> RetReg<R0>;
rustix_indirect_syscall4_nr_last_fastcall( a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a0: ArgReg<'_, A0>, a3: ArgReg<'_, A3>, nr: SyscallNumber<'_>, callee: SyscallType, ) -> RetReg<R0>177     fn rustix_indirect_syscall4_nr_last_fastcall(
178         a1: ArgReg<'_, A1>,
179         a2: ArgReg<'_, A2>,
180         a0: ArgReg<'_, A0>,
181         a3: ArgReg<'_, A3>,
182         nr: SyscallNumber<'_>,
183         callee: SyscallType,
184     ) -> RetReg<R0>;
rustix_indirect_syscall5_nr_last_fastcall( a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a0: ArgReg<'_, A0>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, nr: SyscallNumber<'_>, callee: SyscallType, ) -> RetReg<R0>185     fn rustix_indirect_syscall5_nr_last_fastcall(
186         a1: ArgReg<'_, A1>,
187         a2: ArgReg<'_, A2>,
188         a0: ArgReg<'_, A0>,
189         a3: ArgReg<'_, A3>,
190         a4: ArgReg<'_, A4>,
191         nr: SyscallNumber<'_>,
192         callee: SyscallType,
193     ) -> RetReg<R0>;
rustix_indirect_syscall6_nr_last_fastcall( a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a0: ArgReg<'_, A0>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, a5: ArgReg<'_, A5>, nr: SyscallNumber<'_>, callee: SyscallType, ) -> RetReg<R0>194     fn rustix_indirect_syscall6_nr_last_fastcall(
195         a1: ArgReg<'_, A1>,
196         a2: ArgReg<'_, A2>,
197         a0: ArgReg<'_, A0>,
198         a3: ArgReg<'_, A3>,
199         a4: ArgReg<'_, A4>,
200         a5: ArgReg<'_, A5>,
201         nr: SyscallNumber<'_>,
202         callee: SyscallType,
203     ) -> RetReg<R0>;
204 }
205 
206 // Then we define inline wrapper functions that do the reordering.
207 
208 #[inline]
indirect_syscall0( callee: SyscallType, nr: SyscallNumber<'_>, ) -> RetReg<R0>209 pub(in crate::backend) unsafe fn indirect_syscall0(
210     callee: SyscallType,
211     nr: SyscallNumber<'_>,
212 ) -> RetReg<R0> {
213     rustix_indirect_syscall0_nr_last_fastcall(nr, callee)
214 }
215 #[inline]
indirect_syscall1( callee: SyscallType, nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, ) -> RetReg<R0>216 pub(in crate::backend) unsafe fn indirect_syscall1(
217     callee: SyscallType,
218     nr: SyscallNumber<'_>,
219     a0: ArgReg<'_, A0>,
220 ) -> RetReg<R0> {
221     rustix_indirect_syscall1_nr_last_fastcall(a0, nr, callee)
222 }
223 #[inline]
indirect_syscall1_noreturn( callee: SyscallType, nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, ) -> !224 pub(in crate::backend) unsafe fn indirect_syscall1_noreturn(
225     callee: SyscallType,
226     nr: SyscallNumber<'_>,
227     a0: ArgReg<'_, A0>,
228 ) -> ! {
229     rustix_indirect_syscall1_noreturn_nr_last_fastcall(a0, nr, callee)
230 }
231 #[inline]
indirect_syscall2( callee: SyscallType, nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, ) -> RetReg<R0>232 pub(in crate::backend) unsafe fn indirect_syscall2(
233     callee: SyscallType,
234     nr: SyscallNumber<'_>,
235     a0: ArgReg<'_, A0>,
236     a1: ArgReg<'_, A1>,
237 ) -> RetReg<R0> {
238     rustix_indirect_syscall2_nr_last_fastcall(a1, a0, nr, callee)
239 }
240 #[inline]
indirect_syscall3( callee: SyscallType, nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, ) -> RetReg<R0>241 pub(in crate::backend) unsafe fn indirect_syscall3(
242     callee: SyscallType,
243     nr: SyscallNumber<'_>,
244     a0: ArgReg<'_, A0>,
245     a1: ArgReg<'_, A1>,
246     a2: ArgReg<'_, A2>,
247 ) -> RetReg<R0> {
248     rustix_indirect_syscall3_nr_last_fastcall(a1, a2, a0, nr, callee)
249 }
250 #[inline]
indirect_syscall4( callee: SyscallType, nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, ) -> RetReg<R0>251 pub(in crate::backend) unsafe fn indirect_syscall4(
252     callee: SyscallType,
253     nr: SyscallNumber<'_>,
254     a0: ArgReg<'_, A0>,
255     a1: ArgReg<'_, A1>,
256     a2: ArgReg<'_, A2>,
257     a3: ArgReg<'_, A3>,
258 ) -> RetReg<R0> {
259     rustix_indirect_syscall4_nr_last_fastcall(a1, a2, a0, a3, nr, callee)
260 }
261 #[inline]
indirect_syscall5( callee: SyscallType, nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, ) -> RetReg<R0>262 pub(in crate::backend) unsafe fn indirect_syscall5(
263     callee: SyscallType,
264     nr: SyscallNumber<'_>,
265     a0: ArgReg<'_, A0>,
266     a1: ArgReg<'_, A1>,
267     a2: ArgReg<'_, A2>,
268     a3: ArgReg<'_, A3>,
269     a4: ArgReg<'_, A4>,
270 ) -> RetReg<R0> {
271     rustix_indirect_syscall5_nr_last_fastcall(a1, a2, a0, a3, a4, nr, callee)
272 }
273 #[inline]
indirect_syscall6( callee: SyscallType, nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, a5: ArgReg<'_, A5>, ) -> RetReg<R0>274 pub(in crate::backend) unsafe fn indirect_syscall6(
275     callee: SyscallType,
276     nr: SyscallNumber<'_>,
277     a0: ArgReg<'_, A0>,
278     a1: ArgReg<'_, A1>,
279     a2: ArgReg<'_, A2>,
280     a3: ArgReg<'_, A3>,
281     a4: ArgReg<'_, A4>,
282     a5: ArgReg<'_, A5>,
283 ) -> RetReg<R0> {
284     rustix_indirect_syscall6_nr_last_fastcall(a1, a2, a0, a3, a4, a5, nr, callee)
285 }
286