• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Syscall wrappers for platforms which pass the syscall number specially.
2 //!
3 //! Rustix aims to minimize the amount of assembly code it needs. To that end,
4 //! this code reorders syscall arguments as close as feasible to the actual
5 //! syscall convention before calling the assembly functions.
6 //!
7 //! Many architectures use a convention where the syscall number is passed in a
8 //! special register, with the regular syscall arguments passed in either the
9 //! same or similar registers as the platform C convention. This code
10 //! approximates that order by passing the regular syscall arguments first, and
11 //! the syscall number last. That way, the outline assembly code typically just
12 //! needs to move the syscall number to its special register, and leave the
13 //! other arguments mostly as they are.
14 
15 #[cfg(target_arch = "mips")]
16 use crate::backend::reg::A6;
17 use crate::backend::reg::{ArgReg, RetReg, SyscallNumber, A0, A1, A2, A3, A4, A5, R0};
18 
19 // First we declare the actual assembly routines with `*_nr_last` names and
20 // reordered arguments. If the signatures or calling conventions are ever
21 // changed, the symbol names should also be updated accordingly, to avoid
22 // collisions with other versions of this crate.
23 //
24 // We don't define `_readonly` versions of these because we have no way to tell
25 // Rust that calls to our outline assembly are readonly.
26 extern "C" {
rustix_syscall0_nr_last(nr: SyscallNumber<'_>) -> RetReg<R0>27     fn rustix_syscall0_nr_last(nr: SyscallNumber<'_>) -> RetReg<R0>;
rustix_syscall1_nr_last(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> RetReg<R0>28     fn rustix_syscall1_nr_last(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> RetReg<R0>;
rustix_syscall1_noreturn_nr_last(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> !29     fn rustix_syscall1_noreturn_nr_last(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> !;
rustix_syscall2_nr_last( a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, nr: SyscallNumber<'_>, ) -> RetReg<R0>30     fn rustix_syscall2_nr_last(
31         a0: ArgReg<'_, A0>,
32         a1: ArgReg<'_, A1>,
33         nr: SyscallNumber<'_>,
34     ) -> RetReg<R0>;
rustix_syscall3_nr_last( a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, nr: SyscallNumber<'_>, ) -> RetReg<R0>35     fn rustix_syscall3_nr_last(
36         a0: ArgReg<'_, A0>,
37         a1: ArgReg<'_, A1>,
38         a2: ArgReg<'_, A2>,
39         nr: SyscallNumber<'_>,
40     ) -> RetReg<R0>;
rustix_syscall4_nr_last( a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, nr: SyscallNumber<'_>, ) -> RetReg<R0>41     fn rustix_syscall4_nr_last(
42         a0: ArgReg<'_, A0>,
43         a1: ArgReg<'_, A1>,
44         a2: ArgReg<'_, A2>,
45         a3: ArgReg<'_, A3>,
46         nr: SyscallNumber<'_>,
47     ) -> RetReg<R0>;
rustix_syscall5_nr_last( a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, nr: SyscallNumber<'_>, ) -> RetReg<R0>48     fn rustix_syscall5_nr_last(
49         a0: ArgReg<'_, A0>,
50         a1: ArgReg<'_, A1>,
51         a2: ArgReg<'_, A2>,
52         a3: ArgReg<'_, A3>,
53         a4: ArgReg<'_, A4>,
54         nr: SyscallNumber<'_>,
55     ) -> RetReg<R0>;
rustix_syscall6_nr_last( a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, a5: ArgReg<'_, A5>, nr: SyscallNumber<'_>, ) -> RetReg<R0>56     fn rustix_syscall6_nr_last(
57         a0: ArgReg<'_, A0>,
58         a1: ArgReg<'_, A1>,
59         a2: ArgReg<'_, A2>,
60         a3: ArgReg<'_, A3>,
61         a4: ArgReg<'_, A4>,
62         a5: ArgReg<'_, A5>,
63         nr: SyscallNumber<'_>,
64     ) -> RetReg<R0>;
65     #[cfg(target_arch = "mips")]
rustix_syscall7_nr_last( a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, a5: ArgReg<'_, A5>, a6: ArgReg<'_, A6>, nr: SyscallNumber<'_>, ) -> RetReg<R0>66     fn rustix_syscall7_nr_last(
67         a0: ArgReg<'_, A0>,
68         a1: ArgReg<'_, A1>,
69         a2: ArgReg<'_, A2>,
70         a3: ArgReg<'_, A3>,
71         a4: ArgReg<'_, A4>,
72         a5: ArgReg<'_, A5>,
73         a6: ArgReg<'_, A6>,
74         nr: SyscallNumber<'_>,
75     ) -> RetReg<R0>;
76 }
77 
78 // Then we define inline wrapper functions that do the reordering.
79 
80 #[inline]
syscall0(nr: SyscallNumber<'_>) -> RetReg<R0>81 pub(in crate::backend) unsafe fn syscall0(nr: SyscallNumber<'_>) -> RetReg<R0> {
82     rustix_syscall0_nr_last(nr)
83 }
84 #[inline]
syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0>85 pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
86     rustix_syscall1_nr_last(a0, nr)
87 }
88 #[inline]
syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> !89 pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
90     rustix_syscall1_noreturn_nr_last(a0, nr)
91 }
92 #[inline]
syscall2( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, ) -> RetReg<R0>93 pub(in crate::backend) unsafe fn syscall2(
94     nr: SyscallNumber<'_>,
95     a0: ArgReg<'_, A0>,
96     a1: ArgReg<'_, A1>,
97 ) -> RetReg<R0> {
98     rustix_syscall2_nr_last(a0, a1, nr)
99 }
100 #[inline]
syscall3( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, ) -> RetReg<R0>101 pub(in crate::backend) unsafe fn syscall3(
102     nr: SyscallNumber<'_>,
103     a0: ArgReg<'_, A0>,
104     a1: ArgReg<'_, A1>,
105     a2: ArgReg<'_, A2>,
106 ) -> RetReg<R0> {
107     rustix_syscall3_nr_last(a0, a1, a2, nr)
108 }
109 #[inline]
syscall4( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, ) -> RetReg<R0>110 pub(in crate::backend) unsafe fn syscall4(
111     nr: SyscallNumber<'_>,
112     a0: ArgReg<'_, A0>,
113     a1: ArgReg<'_, A1>,
114     a2: ArgReg<'_, A2>,
115     a3: ArgReg<'_, A3>,
116 ) -> RetReg<R0> {
117     rustix_syscall4_nr_last(a0, a1, a2, a3, nr)
118 }
119 #[inline]
syscall5( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, ) -> RetReg<R0>120 pub(in crate::backend) unsafe fn syscall5(
121     nr: SyscallNumber<'_>,
122     a0: ArgReg<'_, A0>,
123     a1: ArgReg<'_, A1>,
124     a2: ArgReg<'_, A2>,
125     a3: ArgReg<'_, A3>,
126     a4: ArgReg<'_, A4>,
127 ) -> RetReg<R0> {
128     rustix_syscall5_nr_last(a0, a1, a2, a3, a4, nr)
129 }
130 #[inline]
syscall6( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, a5: ArgReg<'_, A5>, ) -> RetReg<R0>131 pub(in crate::backend) unsafe fn syscall6(
132     nr: SyscallNumber<'_>,
133     a0: ArgReg<'_, A0>,
134     a1: ArgReg<'_, A1>,
135     a2: ArgReg<'_, A2>,
136     a3: ArgReg<'_, A3>,
137     a4: ArgReg<'_, A4>,
138     a5: ArgReg<'_, A5>,
139 ) -> RetReg<R0> {
140     rustix_syscall6_nr_last(a0, a1, a2, a3, a4, a5, nr)
141 }
142 #[cfg(target_arch = "mips")]
143 #[inline]
syscall7( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, a5: ArgReg<'_, A5>, a6: ArgReg<'_, A6>, ) -> RetReg<R0>144 pub(in crate::backend) unsafe fn syscall7(
145     nr: SyscallNumber<'_>,
146     a0: ArgReg<'_, A0>,
147     a1: ArgReg<'_, A1>,
148     a2: ArgReg<'_, A2>,
149     a3: ArgReg<'_, A3>,
150     a4: ArgReg<'_, A4>,
151     a5: ArgReg<'_, A5>,
152     a6: ArgReg<'_, A6>,
153 ) -> RetReg<R0> {
154     rustix_syscall7_nr_last(a0, a1, a2, a3, a4, a5, a6, nr)
155 }
156 
157 // Then we define the `_readonly` versions of the wrappers. We don't have
158 // separate `_readonly` implementations, so these can just be aliases to
159 // their non-`_readonly` counterparts.
160 #[cfg(target_arch = "mips")]
161 pub(in crate::backend) use syscall7 as syscall7_readonly;
162 pub(in crate::backend) use {
163     syscall0 as syscall0_readonly, syscall1 as syscall1_readonly, syscall2 as syscall2_readonly,
164     syscall3 as syscall3_readonly, syscall4 as syscall4_readonly, syscall5 as syscall5_readonly,
165     syscall6 as syscall6_readonly,
166 };
167