Skip to main content

lib_unknown/sys/
syscall.rs

1//! 裸系统调用 `syscall0~6`:Linux / Android / macOS / Windows 的多架构内联汇编分发,不支持的目标编译期报错。
2//!
3//! 需要启用 `"sys-syscall"` 特性。
4#![no_std]
5#![allow(unused)]
6
7macro_rules! unsupported_target {
8    ($name:literal) => {
9        #[cfg(not(any(
10            all(
11                any(target_os = "linux", target_os = "android"),
12                any(
13                    target_arch = "x86_64",
14                    target_arch = "aarch64",
15                    target_arch = "riscv64",
16                    target_arch = "x86"
17                )
18            ),
19            all(
20                target_os = "macos",
21                any(target_arch = "x86_64", target_arch = "aarch64")
22            ),
23            all(
24                target_os = "windows",
25                any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64")
26            )
27        )))]
28        {
29            compile_error!(concat!(
30                $name,
31                " is not supported on this target OS/Architecture combination."
32            ));
33            unreachable!()
34        }
35    };
36}
37
38/// 执行 0 参数裸系统调用。
39///
40/// # Safety
41///
42/// 调用此函数必须保证:
43/// 1. `n` 为当前 OS/Arch 下合法的系统调用号;
44/// 2. 调用者自行承担内核副作用(寄存器 `rcx/r11` 等按 ABI 被破坏)。
45///
46/// # Feature Requirement
47///
48/// 需要启用 `"sys-syscall"` 特性。
49///
50/// # Examples
51///
52/// ```rust,no_run
53/// use lib_unknown::sys::syscall::syscall0;
54///
55/// let pid = unsafe { syscall0(39) };
56/// let _ = pid;
57/// ```
58#[inline(always)]
59pub unsafe fn syscall0(n: usize) -> isize {
60    let ret: isize;
61
62    // =========================================================================
63    // Linux & Android
64    // =========================================================================
65
66    #[cfg(all(
67        any(target_os = "linux", target_os = "android"),
68        target_arch = "x86_64"
69    ))]
70    unsafe {
71        core::arch::asm!(
72        "syscall",
73        in("rax") n,
74        lateout("rax") ret,
75        lateout("rcx") _, // syscall 指令硬件语义:rcx 保存返回地址,被内核覆盖
76        lateout("r11") _, // syscall 指令硬件语义:r11 保存 RFLAGS,被内核覆盖
77        options(nostack)  // syscall 不触碰用户栈;内核可能修改 EFLAGS,故不加 preserves_flags
78        );
79    }
80
81    #[cfg(all(
82        any(target_os = "linux", target_os = "android"),
83        target_arch = "aarch64"
84    ))]
85    unsafe {
86        core::arch::asm!(
87        "svc #0",
88        in("x8") n,
89        lateout("x0") ret,
90        options(nostack) // Linux aarch64 syscall ABI 只保证修改 x0,其余寄存器保留
91        );
92    }
93
94    #[cfg(all(
95        any(target_os = "linux", target_os = "android"),
96        target_arch = "riscv64"
97    ))]
98    unsafe {
99        core::arch::asm!(
100        "ecall",
101        in("a7") n,
102        lateout("a0") ret,
103        options(nostack) // 同理,Linux riscv64 syscall 只保证修改 a0
104        );
105    }
106
107    #[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))]
108    unsafe {
109        core::arch::asm!(
110        "int 0x80",
111        in("eax") n,
112        lateout("eax") ret,
113        options(nostack)
114        );
115    }
116
117    // =========================================================================
118    // macOS (Darwin)
119    // =========================================================================
120
121    #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
122    unsafe {
123        let sys_num = n | 0x2000000;
124        core::arch::asm!(
125        "syscall",
126        "jnc 1f",
127        "neg rax",
128        "1:",
129        in("rax") sys_num,
130        lateout("rax") ret,
131        lateout("rcx") _,
132        lateout("r11") _,
133        options(nostack)
134        );
135    }
136
137    #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
138    unsafe {
139        core::arch::asm!(
140        "svc #0x80",
141        "b.cc 1f",
142        "neg x0, x0",
143        "1:",
144        in("x16") n,
145        lateout("x0") ret,
146        options(nostack)
147        );
148    }
149
150    // =========================================================================
151    // Windows (NT内核)
152    // =========================================================================
153
154    #[cfg(all(target_os = "windows", target_arch = "x86_64"))]
155    unsafe {
156        core::arch::asm!(
157        "syscall",
158        in("rax") n,
159        lateout("rax") ret,
160        lateout("rcx") _,
161        lateout("r11") _,
162        lateout("r10") _,
163        lateout("rdx") _,
164        lateout("r8") _,
165        lateout("r9") _,
166        options(nostack)
167        );
168    }
169
170    #[cfg(all(target_os = "windows", target_arch = "x86"))]
171    unsafe {
172        core::arch::asm!(
173        "int 0x2e",
174        in("eax") n,
175        lateout("eax") ret,
176        lateout("ecx") _,
177        lateout("edx") _,
178        options(nostack)
179        );
180    }
181
182    #[cfg(all(target_os = "windows", target_arch = "aarch64"))]
183    unsafe {
184        core::arch::asm!(
185        "svc #0",
186        in("x8") n,
187        lateout("x0") ret,
188        options(nostack)
189        );
190    }
191
192    unsupported_target!("syscall0");
193
194    ret
195}
196
197/// 执行 1 参数裸系统调用。
198///
199/// # Safety
200///
201/// 调用此函数必须保证:
202/// 1. `n` 合法且 `a1` 满足该调用的指针/值约束;
203/// 2. 若 `a1` 为指针,调用期间其指向内存有效。
204///
205/// # Feature Requirement
206///
207/// 需要启用 `"sys-syscall"` 特性.
208#[inline(always)]
209pub unsafe fn syscall1(n: usize, a1: usize) -> isize {
210    let ret: isize;
211
212    #[cfg(all(
213        any(target_os = "linux", target_os = "android"),
214        target_arch = "x86_64"
215    ))]
216    unsafe {
217        core::arch::asm!(
218        "syscall",
219        in("rax") n,
220        in("rdi") a1,
221        lateout("rax") ret,
222        lateout("rcx") _,
223        lateout("r11") _,
224        options(nostack)
225        );
226    }
227
228    #[cfg(all(
229        any(target_os = "linux", target_os = "android"),
230        target_arch = "aarch64"
231    ))]
232    unsafe {
233        core::arch::asm!(
234        "svc #0",
235        in("x8") n,
236        inlateout("x0") a1 => ret,
237        options(nostack)
238        );
239    }
240
241    #[cfg(all(
242        any(target_os = "linux", target_os = "android"),
243        target_arch = "riscv64"
244    ))]
245    unsafe {
246        core::arch::asm!(
247        "ecall",
248        in("a7") n,
249        inlateout("a0") a1 => ret,
250        options(nostack)
251        );
252    }
253
254    #[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))]
255    unsafe {
256        core::arch::asm!(
257        "int 0x80",
258        in("eax") n,
259        in("ebx") a1,
260        lateout("eax") ret,
261        options(nostack)
262        );
263    }
264
265    #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
266    unsafe {
267        let sys_num = n | 0x2000000;
268        core::arch::asm!(
269        "syscall",
270        "jnc 1f",
271        "neg rax",
272        "1:",
273        in("rax") sys_num,
274        in("rdi") a1,
275        lateout("rax") ret,
276        lateout("rcx") _,
277        lateout("r11") _,
278        options(nostack)
279        );
280    }
281
282    #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
283    unsafe {
284        core::arch::asm!(
285        "svc #0x80",
286        "b.cc 1f",
287        "neg x0, x0",
288        "1:",
289        in("x16") n,
290        inlateout("x0") a1 => ret,
291        options(nostack)
292        );
293    }
294
295    // Windows x64 NT syscall:第 1 个参数放在 r10(因 rcx 被 syscall 指令占用作
296    // 返回地址)。内核将 r10/rdx/r8/r9 视为易失寄存器(scratch),并不保证
297    // 保留其原值,因此对"作为输入使用过"的寄存器必须用 inout(..)=>_ 声明为
298    // "输入后即作废",未使用到的则用 lateout(_) 声明为纯粹的破坏。
299    #[cfg(all(target_os = "windows", target_arch = "x86_64"))]
300    unsafe {
301        core::arch::asm!(
302        "syscall",
303        in("rax") n,
304        inout("r10") a1 => _,
305        lateout("rax") ret,
306        lateout("rcx") _,
307        lateout("r11") _,
308        lateout("rdx") _,
309        lateout("r8") _,
310        lateout("r9") _,
311        options(nostack)
312        );
313    }
314
315    #[cfg(all(target_os = "windows", target_arch = "x86"))]
316    unsafe {
317        core::arch::asm!(
318        "push {a1}",
319        "mov edx, esp",
320        "int 0x2e",
321        "add esp, 4",
322        a1 = in(reg) a1,
323        inout("eax") n => ret,
324        lateout("ecx") _,
325        lateout("edx") _,
326        );
327    }
328
329    #[cfg(all(target_os = "windows", target_arch = "aarch64"))]
330    unsafe {
331        core::arch::asm!(
332        "svc #0",
333        in("x8") n,
334        inlateout("x0") a1 => ret,
335        options(nostack)
336        );
337    }
338
339    unsupported_target!("syscall1");
340
341    ret
342}
343
344/// 执行 2 参数裸系统调用。
345///
346/// # Safety
347///
348/// 调用此函数必须保证 `n/a1/a2` 符合目标调用约定,指针参数有效。
349///
350/// # Feature Requirement
351///
352/// 需要启用 `"sys-syscall"` 特性。
353#[inline(always)]
354pub unsafe fn syscall2(n: usize, a1: usize, a2: usize) -> isize {
355    let ret: isize;
356
357    #[cfg(all(
358        any(target_os = "linux", target_os = "android"),
359        target_arch = "x86_64"
360    ))]
361    unsafe {
362        core::arch::asm!(
363        "syscall",
364        in("rax") n,
365        in("rdi") a1,
366        in("rsi") a2,
367        lateout("rax") ret,
368        lateout("rcx") _,
369        lateout("r11") _,
370        options(nostack)
371        );
372    }
373
374    #[cfg(all(
375        any(target_os = "linux", target_os = "android"),
376        target_arch = "aarch64"
377    ))]
378    unsafe {
379        core::arch::asm!(
380        "svc #0",
381        in("x8") n,
382        inlateout("x0") a1 => ret,
383        in("x1") a2,
384        options(nostack)
385        );
386    }
387
388    #[cfg(all(
389        any(target_os = "linux", target_os = "android"),
390        target_arch = "riscv64"
391    ))]
392    unsafe {
393        core::arch::asm!(
394        "ecall",
395        in("a7") n,
396        inlateout("a0") a1 => ret,
397        in("a1") a2,
398        options(nostack)
399        );
400    }
401
402    #[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))]
403    unsafe {
404        core::arch::asm!(
405        "int 0x80",
406        in("eax") n,
407        in("ebx") a1,
408        in("ecx") a2,
409        lateout("eax") ret,
410        options(nostack)
411        );
412    }
413
414    #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
415    unsafe {
416        let sys_num = n | 0x2000000;
417        core::arch::asm!(
418        "syscall",
419        "jnc 1f",
420        "neg rax",
421        "1:",
422        in("rax") sys_num,
423        in("rdi") a1,
424        in("rsi") a2,
425        lateout("rax") ret,
426        lateout("rcx") _,
427        lateout("r11") _,
428        options(nostack)
429        );
430    }
431
432    #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
433    unsafe {
434        core::arch::asm!(
435        "svc #0x80",
436        "b.cc 1f",
437        "neg x0, x0",
438        "1:",
439        in("x16") n,
440        inlateout("x0") a1 => ret,
441        in("x1") a2,
442        options(nostack)
443        );
444    }
445
446    #[cfg(all(target_os = "windows", target_arch = "x86_64"))]
447    unsafe {
448        core::arch::asm!(
449        "syscall",
450        in("rax") n,
451        inout("r10") a1 => _,
452        inout("rdx") a2 => _,
453        lateout("rax") ret,
454        lateout("rcx") _,
455        lateout("r11") _,
456        lateout("r8") _,
457        lateout("r9") _,
458        options(nostack)
459        );
460    }
461
462    #[cfg(all(target_os = "windows", target_arch = "x86"))]
463    unsafe {
464        core::arch::asm!(
465        "push {a2}",
466        "push {a1}",
467        "mov edx, esp",
468        "int 0x2e",
469        "add esp, 8",
470        a1 = in(reg) a1,
471        a2 = in(reg) a2,
472        inout("eax") n => ret,
473        lateout("ecx") _,
474        lateout("edx") _,
475        );
476    }
477
478    #[cfg(all(target_os = "windows", target_arch = "aarch64"))]
479    unsafe {
480        core::arch::asm!(
481        "svc #0",
482        in("x8") n,
483        inlateout("x0") a1 => ret,
484        in("x1") a2,
485        options(nostack)
486        );
487    }
488
489    unsupported_target!("syscall2");
490
491    ret
492}
493
494/// 执行 3 参数裸系统调用。
495///
496/// # Safety
497///
498/// 调用此函数必须保证参数符合目标调用约定,指针参数有效。
499///
500/// # Feature Requirement
501///
502/// 需要启用 `"sys-syscall"` 特性。
503#[inline(always)]
504pub unsafe fn syscall3(n: usize, a1: usize, a2: usize, a3: usize) -> isize {
505    let ret: isize;
506
507    #[cfg(all(
508        any(target_os = "linux", target_os = "android"),
509        target_arch = "x86_64"
510    ))]
511    unsafe {
512        core::arch::asm!(
513        "syscall",
514        in("rax") n,
515        in("rdi") a1,
516        in("rsi") a2,
517        in("rdx") a3,
518        lateout("rax") ret,
519        lateout("rcx") _,
520        lateout("r11") _,
521        options(nostack)
522        );
523    }
524
525    #[cfg(all(
526        any(target_os = "linux", target_os = "android"),
527        target_arch = "aarch64"
528    ))]
529    unsafe {
530        core::arch::asm!(
531        "svc #0",
532        in("x8") n,
533        inlateout("x0") a1 => ret,
534        in("x1") a2,
535        in("x2") a3,
536        options(nostack)
537        );
538    }
539
540    #[cfg(all(
541        any(target_os = "linux", target_os = "android"),
542        target_arch = "riscv64"
543    ))]
544    unsafe {
545        core::arch::asm!(
546        "ecall",
547        in("a7") n,
548        inlateout("a0") a1 => ret,
549        in("a1") a2,
550        in("a2") a3,
551        options(nostack)
552        );
553    }
554
555    #[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))]
556    unsafe {
557        core::arch::asm!(
558        "int 0x80",
559        in("eax") n,
560        in("ebx") a1,
561        in("ecx") a2,
562        in("edx") a3,
563        lateout("eax") ret,
564        options(nostack)
565        );
566    }
567
568    #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
569    unsafe {
570        let sys_num = n | 0x2000000;
571        core::arch::asm!(
572        "syscall",
573        "jnc 1f",
574        "neg rax",
575        "1:",
576        in("rax") sys_num,
577        in("rdi") a1,
578        in("rsi") a2,
579        in("rdx") a3,
580        lateout("rax") ret,
581        lateout("rcx") _,
582        lateout("r11") _,
583        options(nostack)
584        );
585    }
586
587    #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
588    unsafe {
589        core::arch::asm!(
590        "svc #0x80",
591        "b.cc 1f",
592        "neg x0, x0",
593        "1:",
594        in("x16") n,
595        inlateout("x0") a1 => ret,
596        in("x1") a2,
597        in("x2") a3,
598        options(nostack)
599        );
600    }
601
602    #[cfg(all(target_os = "windows", target_arch = "x86_64"))]
603    unsafe {
604        core::arch::asm!(
605        "syscall",
606        in("rax") n,
607        inout("r10") a1 => _,
608        inout("rdx") a2 => _,
609        inout("r8") a3 => _,
610        lateout("rax") ret,
611        lateout("rcx") _,
612        lateout("r11") _,
613        lateout("r9") _,
614        options(nostack)
615        );
616    }
617
618    #[cfg(all(target_os = "windows", target_arch = "x86"))]
619    unsafe {
620        core::arch::asm!(
621        "push {a3}",
622        "push {a2}",
623        "push {a1}",
624        "mov edx, esp",
625        "int 0x2e",
626        "add esp, 12",
627        a1 = in(reg) a1,
628        a2 = in(reg) a2,
629        a3 = in(reg) a3,
630        inout("eax") n => ret,
631        lateout("ecx") _,
632        lateout("edx") _,
633        );
634    }
635
636    #[cfg(all(target_os = "windows", target_arch = "aarch64"))]
637    unsafe {
638        core::arch::asm!(
639        "svc #0",
640        in("x8") n,
641        inlateout("x0") a1 => ret,
642        in("x1") a2,
643        in("x2") a3,
644        options(nostack)
645        );
646    }
647
648    unsupported_target!("syscall3");
649
650    ret
651}
652
653/// 执行 4 参数裸系统调用。
654///
655/// # Safety
656///
657/// 调用此函数必须保证参数符合目标调用约定,指针参数有效。
658///
659/// # Feature Requirement
660///
661/// 需要启用 `"sys-syscall"` 特性。
662#[inline(always)]
663pub unsafe fn syscall4(n: usize, a1: usize, a2: usize, a3: usize, a4: usize) -> isize {
664    let ret: isize;
665
666    #[cfg(all(
667        any(target_os = "linux", target_os = "android"),
668        target_arch = "x86_64"
669    ))]
670    unsafe {
671        core::arch::asm!(
672        "syscall",
673        in("rax") n,
674        in("rdi") a1,
675        in("rsi") a2,
676        in("rdx") a3,
677        in("r10") a4,
678        lateout("rax") ret,
679        lateout("rcx") _,
680        lateout("r11") _,
681        options(nostack)
682        );
683    }
684
685    #[cfg(all(
686        any(target_os = "linux", target_os = "android"),
687        target_arch = "aarch64"
688    ))]
689    unsafe {
690        core::arch::asm!(
691        "svc #0",
692        in("x8") n,
693        inlateout("x0") a1 => ret,
694        in("x1") a2,
695        in("x2") a3,
696        in("x3") a4,
697        options(nostack)
698        );
699    }
700
701    #[cfg(all(
702        any(target_os = "linux", target_os = "android"),
703        target_arch = "riscv64"
704    ))]
705    unsafe {
706        core::arch::asm!(
707        "ecall",
708        in("a7") n,
709        inlateout("a0") a1 => ret,
710        in("a1") a2,
711        in("a2") a3,
712        in("a3") a4,
713        options(nostack)
714        );
715    }
716
717    // esi 被 LLVM 内部占用,不可作为显式操作数,只能手动 push/mov/pop 传递,
718    // 因此不能再用 options(nostack)。
719    #[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))]
720    unsafe {
721        core::arch::asm!(
722        "push esi",
723        "mov esi, {a4}",
724        "int 0x80",
725        "pop esi",
726        a4 = in(reg) a4,
727        in("eax") n,
728        in("ebx") a1,
729        in("ecx") a2,
730        in("edx") a3,
731        lateout("eax") ret,
732        );
733    }
734
735    #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
736    unsafe {
737        let sys_num = n | 0x2000000;
738        core::arch::asm!(
739        "syscall",
740        "jnc 1f",
741        "neg rax",
742        "1:",
743        in("rax") sys_num,
744        in("rdi") a1,
745        in("rsi") a2,
746        in("rdx") a3,
747        in("r10") a4,
748        lateout("rax") ret,
749        lateout("rcx") _,
750        lateout("r11") _,
751        options(nostack)
752        );
753    }
754
755    #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
756    unsafe {
757        core::arch::asm!(
758        "svc #0x80",
759        "b.cc 1f",
760        "neg x0, x0",
761        "1:",
762        in("x16") n,
763        inlateout("x0") a1 => ret,
764        in("x1") a2,
765        in("x2") a3,
766        in("x3") a4,
767        options(nostack)
768        );
769    }
770
771    #[cfg(all(target_os = "windows", target_arch = "x86_64"))]
772    unsafe {
773        core::arch::asm!(
774        "syscall",
775        in("rax") n,
776        inout("r10") a1 => _,
777        inout("rdx") a2 => _,
778        inout("r8") a3 => _,
779        inout("r9") a4 => _,
780        lateout("rax") ret,
781        lateout("rcx") _,
782        lateout("r11") _,
783        options(nostack)
784        );
785    }
786
787    #[cfg(all(target_os = "windows", target_arch = "x86"))]
788    unsafe {
789        core::arch::asm!(
790        "push {a4}",
791        "push {a3}",
792        "push {a2}",
793        "push {a1}",
794        "mov edx, esp",
795        "int 0x2e",
796        "add esp, 16",
797        a1 = in(reg) a1,
798        a2 = in(reg) a2,
799        a3 = in(reg) a3,
800        a4 = in(reg) a4,
801        inout("eax") n => ret,
802        lateout("ecx") _,
803        lateout("edx") _,
804        );
805    }
806
807    #[cfg(all(target_os = "windows", target_arch = "aarch64"))]
808    unsafe {
809        core::arch::asm!(
810        "svc #0",
811        in("x8") n,
812        inlateout("x0") a1 => ret,
813        in("x1") a2,
814        in("x2") a3,
815        in("x3") a4,
816        options(nostack)
817        );
818    }
819
820    unsupported_target!("syscall4");
821
822    ret
823}
824
825/// 执行 5 参数裸系统调用。
826///
827/// # Safety
828///
829/// 调用此函数必须保证参数符合目标调用约定;Windows x64 下会临时扩展栈 `0x30` 字节。
830///
831/// # Feature Requirement
832///
833/// 需要启用 `"sys-syscall"` 特性。
834#[inline(always)]
835pub unsafe fn syscall5(n: usize, a1: usize, a2: usize, a3: usize, a4: usize, a5: usize) -> isize {
836    let ret: isize;
837
838    #[cfg(all(
839        any(target_os = "linux", target_os = "android"),
840        target_arch = "x86_64"
841    ))]
842    unsafe {
843        core::arch::asm!(
844        "syscall",
845        in("rax") n,
846        in("rdi") a1,
847        in("rsi") a2,
848        in("rdx") a3,
849        in("r10") a4,
850        in("r8")  a5,
851        lateout("rax") ret,
852        lateout("rcx") _,
853        lateout("r11") _,
854        options(nostack)
855        );
856    }
857
858    #[cfg(all(
859        any(target_os = "linux", target_os = "android"),
860        target_arch = "aarch64"
861    ))]
862    unsafe {
863        core::arch::asm!(
864        "svc #0",
865        in("x8") n,
866        inlateout("x0") a1 => ret,
867        in("x1") a2,
868        in("x2") a3,
869        in("x3") a4,
870        in("x4") a5,
871        options(nostack)
872        );
873    }
874
875    #[cfg(all(
876        any(target_os = "linux", target_os = "android"),
877        target_arch = "riscv64"
878    ))]
879    unsafe {
880        core::arch::asm!(
881        "ecall",
882        in("a7") n,
883        inlateout("a0") a1 => ret,
884        in("a1") a2,
885        in("a2") a3,
886        in("a3") a4,
887        in("a4") a5,
888        options(nostack)
889        );
890    }
891
892    // esi 被 LLVM 内部占用,不可作为显式操作数,只能手动 push/mov/pop 传递,
893    // 因此不能再用 options(nostack)。
894    #[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))]
895    unsafe {
896        core::arch::asm!(
897        "push esi",
898        "mov esi, {a4}",
899        "int 0x80",
900        "pop esi",
901        a4 = in(reg) a4,
902        in("eax") n,
903        in("ebx") a1,
904        in("ecx") a2,
905        in("edx") a3,
906        in("edi") a5,
907        lateout("eax") ret,
908        );
909    }
910
911    #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
912    unsafe {
913        let sys_num = n | 0x2000000;
914        core::arch::asm!(
915        "syscall",
916        "jnc 1f",
917        "neg rax",
918        "1:",
919        in("rax") sys_num,
920        in("rdi") a1,
921        in("rsi") a2,
922        in("rdx") a3,
923        in("r10") a4,
924        in("r8")  a5,
925        lateout("rax") ret,
926        lateout("rcx") _,
927        lateout("r11") _,
928        options(nostack)
929        );
930    }
931
932    #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
933    unsafe {
934        core::arch::asm!(
935        "svc #0x80",
936        "b.cc 1f",
937        "neg x0, x0",
938        "1:",
939        in("x16") n,
940        inlateout("x0") a1 => ret,
941        in("x1") a2,
942        in("x2") a3,
943        in("x3") a4,
944        in("x4") a5,
945        options(nostack)
946        );
947    }
948
949    // Windows x64 NT syscall:前 4 个参数走 r10/rdx/r8/r9(均需按输入后作废处理),
950    // 第 5 个及以后的参数按 x64 调用约定放在 Shadow Space(0x20)之后的栈槽位,
951    // 此处手动开辟 0x30 字节栈空间并写入,不能再用 options(nostack)。
952    #[cfg(all(target_os = "windows", target_arch = "x86_64"))]
953    unsafe {
954        core::arch::asm!(
955        "sub rsp, 0x30",
956        "mov [rsp+0x20], {a5}",
957        "syscall",
958        "add rsp, 0x30",
959        a5 = in(reg) a5,
960        in("rax") n,
961        inout("r10") a1 => _,
962        inout("rdx") a2 => _,
963        inout("r8") a3 => _,
964        inout("r9") a4 => _,
965        lateout("rax") ret,
966        lateout("rcx") _,
967        lateout("r11") _,
968        );
969    }
970
971    #[cfg(all(target_os = "windows", target_arch = "x86"))]
972    unsafe {
973        core::arch::asm!(
974        "push {a5}",
975        "push {a4}",
976        "push {a3}",
977        "push {a2}",
978        "push {a1}",
979        "mov edx, esp",
980        "int 0x2e",
981        "add esp, 20",
982        a1 = in(reg) a1,
983        a2 = in(reg) a2,
984        a3 = in(reg) a3,
985        a4 = in(reg) a4,
986        a5 = in(reg) a5,
987        inout("eax") n => ret,
988        lateout("ecx") _,
989        lateout("edx") _,
990        );
991    }
992
993    #[cfg(all(target_os = "windows", target_arch = "aarch64"))]
994    unsafe {
995        core::arch::asm!(
996        "svc #0",
997        in("x8") n,
998        inlateout("x0") a1 => ret,
999        in("x1") a2,
1000        in("x2") a3,
1001        in("x3") a4,
1002        in("x4") a5,
1003        options(nostack)
1004        );
1005    }
1006
1007    unsupported_target!("syscall5");
1008
1009    ret
1010}
1011
1012/// 执行 6 参数裸系统调用。
1013///
1014/// # Safety
1015///
1016/// 调用此函数必须保证参数符合目标调用约定;x86 下会手动保存 `ebp`,Windows x64 下扩展栈。
1017///
1018/// # Feature Requirement
1019///
1020/// 需要启用 `"sys-syscall"` 特性。
1021#[inline(always)]
1022pub unsafe fn syscall6(
1023    n: usize,
1024    a1: usize,
1025    a2: usize,
1026    a3: usize,
1027    a4: usize,
1028    a5: usize,
1029    a6: usize,
1030) -> isize {
1031    let ret: isize;
1032
1033    #[cfg(all(
1034        any(target_os = "linux", target_os = "android"),
1035        target_arch = "x86_64"
1036    ))]
1037    unsafe {
1038        core::arch::asm!(
1039        "syscall",
1040        in("rax") n,
1041        in("rdi") a1,
1042        in("rsi") a2,
1043        in("rdx") a3,
1044        in("r10") a4,
1045        in("r8")  a5,
1046        in("r9")  a6,
1047        lateout("rax") ret,
1048        lateout("rcx") _,
1049        lateout("r11") _,
1050        options(nostack)
1051        );
1052    }
1053
1054    #[cfg(all(
1055        any(target_os = "linux", target_os = "android"),
1056        target_arch = "aarch64"
1057    ))]
1058    unsafe {
1059        core::arch::asm!(
1060        "svc #0",
1061        in("x8") n,
1062        inlateout("x0") a1 => ret,
1063        in("x1") a2,
1064        in("x2") a3,
1065        in("x3") a4,
1066        in("x4") a5,
1067        in("x5") a6,
1068        options(nostack)
1069        );
1070    }
1071
1072    #[cfg(all(
1073        any(target_os = "linux", target_os = "android"),
1074        target_arch = "riscv64"
1075    ))]
1076    unsafe {
1077        core::arch::asm!(
1078        "ecall",
1079        in("a7") n,
1080        inlateout("a0") a1 => ret,
1081        in("a1") a2,
1082        in("a2") a3,
1083        in("a3") a4,
1084        in("a4") a5,
1085        in("a5") a6,
1086        options(nostack)
1087        );
1088    }
1089
1090    // int 0x80 六参数约定的第 6 个参数放在 ebp,而 ebp/rbp 等帧指针寄存器被
1091    // rustc 显式禁止用作内联汇编的显式寄存器操作数(会直接编译报错),
1092    // 因此只能手动 push/pop 保存原 ebp,并通过通用寄存器模板传值。
1093    #[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86"))]
1094    unsafe {
1095        core::arch::asm!(
1096        "push ebp",
1097        "mov ebp, {a6}",
1098        "push esi",
1099        "mov esi, {a4}",
1100        "int 0x80",
1101        "pop esi",
1102        "pop ebp",
1103        a6 = in(reg) a6,
1104        a4 = in(reg) a4,
1105        inout("eax") n => ret,
1106        in("ebx") a1,
1107        in("ecx") a2,
1108        in("edx") a3,
1109        in("edi") a5,
1110        );
1111    }
1112
1113    #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
1114    unsafe {
1115        let sys_num = n | 0x2000000;
1116        core::arch::asm!(
1117        "syscall",
1118        "jnc 1f",
1119        "neg rax",
1120        "1:",
1121        in("rax") sys_num,
1122        in("rdi") a1,
1123        in("rsi") a2,
1124        in("rdx") a3,
1125        in("r10") a4,
1126        in("r8")  a5,
1127        in("r9")  a6,
1128        lateout("rax") ret,
1129        lateout("rcx") _,
1130        lateout("r11") _,
1131        options(nostack)
1132        );
1133    }
1134
1135    #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
1136    unsafe {
1137        core::arch::asm!(
1138        "svc #0x80",
1139        "b.cc 1f",
1140        "neg x0, x0",
1141        "1:",
1142        in("x16") n,
1143        inlateout("x0") a1 => ret,
1144        in("x1") a2,
1145        in("x2") a3,
1146        in("x3") a4,
1147        in("x4") a5,
1148        in("x5") a6,
1149        options(nostack)
1150        );
1151    }
1152
1153    #[cfg(all(target_os = "windows", target_arch = "x86_64"))]
1154    unsafe {
1155        core::arch::asm!(
1156        "sub rsp, 0x30",
1157        "mov [rsp+0x20], {a5}",
1158        "mov [rsp+0x28], {a6}",
1159        "syscall",
1160        "add rsp, 0x30",
1161        a5 = in(reg) a5,
1162        a6 = in(reg) a6,
1163        in("rax") n,
1164        inout("r10") a1 => _,
1165        inout("rdx") a2 => _,
1166        inout("r8") a3 => _,
1167        inout("r9") a4 => _,
1168        lateout("rax") ret,
1169        lateout("rcx") _,
1170        lateout("r11") _,
1171        );
1172    }
1173
1174    #[cfg(all(target_os = "windows", target_arch = "x86"))]
1175    unsafe {
1176        core::arch::asm!(
1177        "push {a6}",
1178        "push {a5}",
1179        "push {a4}",
1180        "push {a3}",
1181        "push {a2}",
1182        "push {a1}",
1183        "mov edx, esp",
1184        "int 0x2e",
1185        "add esp, 24",
1186        a1 = in(reg) a1,
1187        a2 = in(reg) a2,
1188        a3 = in(reg) a3,
1189        a4 = in(reg) a4,
1190        a5 = in(reg) a5,
1191        a6 = in(reg) a6,
1192        inout("eax") n => ret,
1193        lateout("ecx") _,
1194        lateout("edx") _,
1195        );
1196    }
1197
1198    #[cfg(all(target_os = "windows", target_arch = "aarch64"))]
1199    unsafe {
1200        core::arch::asm!(
1201        "svc #0",
1202        in("x8") n,
1203        inlateout("x0") a1 => ret,
1204        in("x1") a2,
1205        in("x2") a3,
1206        in("x3") a4,
1207        in("x4") a5,
1208        in("x5") a6,
1209        options(nostack)
1210        );
1211    }
1212
1213    unsupported_target!("syscall6");
1214
1215    ret
1216}