正如已经指出的,您需要将 0x2000000 添加到索书号。这个幻数的解释来自osfmk/mach/i386/syscall_sw.h(搜索SYSCALL_CLASS_SHIFT)中的xnu内核源代码。
/*
* Syscall classes for 64-bit system call entry.
* For 64-bit users, the 32-bit syscall number is partitioned
* with the high-order bits representing the class and low-order
* bits being the syscall number within that class.
* The high-order 32-bits of the 64-bit syscall number are unused.
* All system classes enter the kernel via the syscall instruction.
在 OSX 上有多种系统调用。所有系统调用都通过 syscall 指令进入内核。那时有 Mach 系统调用、BSD 系统调用、NONE、诊断和机器相关。
#define SYSCALL_CLASS_NONE 0 /* Invalid */
#define SYSCALL_CLASS_MACH 1 /* Mach */
#define SYSCALL_CLASS_UNIX 2 /* Unix/BSD */
#define SYSCALL_CLASS_MDEP 3 /* Machine-dependent */
#define SYSCALL_CLASS_DIAG 4 /* Diagnostics */
每个系统调用都用一个左移 24 位的类枚举标记,SYSCALL_CLASS_SHIFT。 BSD 系统调用的枚举为 2,SYSCALL_CLASS_UNIX。所以这个幻数 0x2000000 被构造为:
// 2 << 24
#define SYSCALL_CONSTRUCT_UNIX(syscall_number) \
((SYSCALL_CLASS_UNIX << SYSCALL_CLASS_SHIFT) | \
(SYSCALL_NUMBER_MASK & (syscall_number)))
显然,您可以从内核源代码中获取该幻数,但不能从开发人员的包含文件中获取。我认为这意味着 Apple 真的希望您链接到解决您的系统调用 shim 的库对象文件,而不是使用内联例程:对象兼容性而不是源兼容性。
在 x86_64 上,系统调用本身像 Linux 一样使用 System V ABI(第 A.2.1 节),它使用 syscall 指令(int 0x80 用于 Linux 中的系统调用)。参数在 rdi、rsi、rdx、r10、r8 和 r9 中传递。系统调用号在 rax 寄存器中。