1const builtin = @import("builtin");
2const std = @import("../../std.zig");
3const SYS = std.os.linux.SYS;
4
5pub const syscall_arg_t = u32;
6
7pub fn syscall0(
8 number: SYS,
9) u32 {
10 return asm volatile ("int $0x80"
11 : [ret] "={eax}" (-> u32),
12 : [number] "{eax}" (@backingInt(number)),
13 : .{ .memory = true });
14}
15
16pub fn syscall1(
17 number: SYS,
18 arg1: syscall_arg_t,
19) u32 {
20 return asm volatile ("int $0x80"
21 : [ret] "={eax}" (-> u32),
22 : [number] "{eax}" (@backingInt(number)),
23 [arg1] "{ebx}" (arg1),
24 : .{ .memory = true });
25}
26
27pub fn syscall2(
28 number: SYS,
29 arg1: syscall_arg_t,
30 arg2: syscall_arg_t,
31) u32 {
32 return asm volatile ("int $0x80"
33 : [ret] "={eax}" (-> u32),
34 : [number] "{eax}" (@backingInt(number)),
35 [arg1] "{ebx}" (arg1),
36 [arg2] "{ecx}" (arg2),
37 : .{ .memory = true });
38}
39
40pub fn syscall3(
41 number: SYS,
42 arg1: syscall_arg_t,
43 arg2: syscall_arg_t,
44 arg3: syscall_arg_t,
45) u32 {
46 return asm volatile ("int $0x80"
47 : [ret] "={eax}" (-> u32),
48 : [number] "{eax}" (@backingInt(number)),
49 [arg1] "{ebx}" (arg1),
50 [arg2] "{ecx}" (arg2),
51 [arg3] "{edx}" (arg3),
52 : .{ .memory = true });
53}
54
55pub fn syscall4(
56 number: SYS,
57 arg1: syscall_arg_t,
58 arg2: syscall_arg_t,
59 arg3: syscall_arg_t,
60 arg4: syscall_arg_t,
61) u32 {
62 return asm volatile ("int $0x80"
63 : [ret] "={eax}" (-> u32),
64 : [number] "{eax}" (@backingInt(number)),
65 [arg1] "{ebx}" (arg1),
66 [arg2] "{ecx}" (arg2),
67 [arg3] "{edx}" (arg3),
68 [arg4] "{esi}" (arg4),
69 : .{ .memory = true });
70}
71
72pub fn syscall5(
73 number: SYS,
74 arg1: syscall_arg_t,
75 arg2: syscall_arg_t,
76 arg3: syscall_arg_t,
77 arg4: syscall_arg_t,
78 arg5: syscall_arg_t,
79) u32 {
80 return asm volatile ("int $0x80"
81 : [ret] "={eax}" (-> u32),
82 : [number] "{eax}" (@backingInt(number)),
83 [arg1] "{ebx}" (arg1),
84 [arg2] "{ecx}" (arg2),
85 [arg3] "{edx}" (arg3),
86 [arg4] "{esi}" (arg4),
87 [arg5] "{edi}" (arg5),
88 : .{ .memory = true });
89}
90
91pub fn syscall6(
92 number: SYS,
93 arg1: syscall_arg_t,
94 arg2: syscall_arg_t,
95 arg3: syscall_arg_t,
96 arg4: syscall_arg_t,
97 arg5: syscall_arg_t,
98 arg6: syscall_arg_t,
99) u32 {
100 // arg6 can't be passed to asm in a register because ebp might be reserved as the frame pointer
101 // and there are no more GPRs available; so we'll need a memory operand for it. Adding that
102 // memory operand means that on PIC we might need a reference to the GOT, which in turn needs
103 // *its* own GPR, so we need to pass another arg in memory too! This is surprisingly hard to get
104 // right, because we can't touch esp or ebp until we're done with the memory input (as that
105 // input could be relative to esp or ebp).
106 const args56: [2]syscall_arg_t = .{ arg5, arg6 };
107 return asm volatile (
108 \\ push %[args56]
109 \\ push %%ebp
110 \\ mov 4(%%esp), %%ebp
111 \\ mov %%edi, 4(%%esp)
112 \\ // The saved %%edi and %%ebp are on the stack, and %%ebp points to `args56`.
113 \\ // Prepare the last two args, syscall, then pop the saved %%ebp and %%edi.
114 \\ mov (%%ebp), %%edi
115 \\ mov 4(%%ebp), %%ebp
116 \\ int $0x80
117 \\ pop %%ebp
118 \\ pop %%edi
119 : [ret] "={eax}" (-> u32),
120 : [number] "{eax}" (@backingInt(number)),
121 [arg1] "{ebx}" (arg1),
122 [arg2] "{ecx}" (arg2),
123 [arg3] "{edx}" (arg3),
124 [arg4] "{esi}" (arg4),
125 [args56] "rm" (&args56),
126 : .{ .memory = true });
127}
128
129pub fn socketcall(call: u32, args: [*]const u32) u32 {
130 return asm volatile ("int $0x80"
131 : [ret] "={eax}" (-> u32),
132 : [number] "{eax}" (@backingInt(SYS.socketcall)),
133 [arg1] "{ebx}" (call),
134 [arg2] "{ecx}" (@intFromPtr(args)),
135 : .{ .memory = true });
136}
137
138pub fn clone() callconv(.naked) u32 {
139 // __clone(func, stack, flags, arg, ptid, tls, ctid)
140 // +8, +12, +16, +20, +24, +28, +32
141 //
142 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
143 // eax, ebx, ecx, edx, esi, edi
144 asm volatile (
145 \\ pushl %%ebp
146 \\ movl %%esp,%%ebp
147 \\ pushl %%ebx
148 \\ pushl %%esi
149 \\ pushl %%edi
150 \\ // Setup the arguments
151 \\ movl 16(%%ebp),%%ebx
152 \\ movl 12(%%ebp),%%ecx
153 \\ andl $-16,%%ecx
154 \\ subl $20,%%ecx
155 \\ movl 20(%%ebp),%%eax
156 \\ movl %%eax,4(%%ecx)
157 \\ movl 8(%%ebp),%%eax
158 \\ movl %%eax,0(%%ecx)
159 \\ movl 24(%%ebp),%%edx
160 \\ movl 28(%%ebp),%%esi
161 \\ movl 32(%%ebp),%%edi
162 \\ movl $120,%%eax // SYS_clone
163 \\ int $128
164 \\ testl %%eax,%%eax
165 \\ jz 1f
166 \\ popl %%edi
167 \\ popl %%esi
168 \\ popl %%ebx
169 \\ popl %%ebp
170 \\ retl
171 \\
172 \\1:
173 );
174 if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
175 \\ .cfi_undefined %%eip
176 );
177 asm volatile (
178 \\ xorl %%ebp,%%ebp
179 \\
180 \\ popl %%eax
181 \\ calll *%%eax
182 \\ movl %%eax,%%ebx
183 \\ movl $1,%%eax // SYS_exit
184 \\ int $128
185 );
186}
187
188pub fn restore() callconv(.naked) noreturn {
189 asm volatile (
190 \\ addl $4, %%esp
191 \\ movl %[number], %%eax
192 \\ int $0x80
193 :
194 : [number] "i" (@backingInt(SYS.sigreturn)),
195 );
196}
197
198pub fn restore_rt() callconv(.naked) noreturn {
199 asm volatile (
200 \\ movl %[number], %%eax
201 \\ int $0x80
202 :
203 : [number] "i" (@backingInt(SYS.rt_sigreturn)),
204 );
205}
206
207pub const VDSO = struct {
208 pub const CGT_SYM = "__vdso_clock_gettime";
209 pub const CGT_VER = "LINUX_2.6";
210};
211
212pub const time_t = i32;
213
214pub const user_desc = extern struct {
215 entry_number: u32,
216 base_addr: u32,
217 limit: u32,
218 flags: packed struct(u32) {
219 seg_32bit: u1,
220 contents: u2,
221 read_exec_only: u1,
222 limit_in_pages: u1,
223 seg_not_present: u1,
224 useable: u1,
225 _: u25 = undefined,
226 },
227};
228
229/// socketcall() call numbers
230pub const SC = struct {
231 pub const socket = 1;
232 pub const bind = 2;
233 pub const connect = 3;
234 pub const listen = 4;
235 pub const accept = 5;
236 pub const getsockname = 6;
237 pub const getpeername = 7;
238 pub const socketpair = 8;
239 pub const send = 9;
240 pub const recv = 10;
241 pub const sendto = 11;
242 pub const recvfrom = 12;
243 pub const shutdown = 13;
244 pub const setsockopt = 14;
245 pub const getsockopt = 15;
246 pub const sendmsg = 16;
247 pub const recvmsg = 17;
248 pub const accept4 = 18;
249 pub const recvmmsg = 19;
250 pub const sendmmsg = 20;
251};