macOS 64 位系统调用 Table

macOS 64-bit System Call Table

我可以找到一个 Linux 64 位系统调用 table,但调用号码在 macOS 上不起作用 - 我每次尝试使用它们时都会收到 Bus Error: 10

sys_write等操作的 macOS 呼叫号码是多少?

您需要使用 syscalls.master 文件将 0x2000000 添加到索书号。我正在使用 the XNU bds/kern/syscalls.master file。这是 syscalls.master 文件中我要调用的函数:

4   AUE_NULL    ALL { user_ssize_t write(int fd, user_addr_t cbuf, user_size_t nbyte); } 

关于向哪些寄存器传递参数,它与 64 位相同Linux。参数分别通过 rdirsirdxr10r8r9 寄存器传递。 write 函数采用三个参数,这些参数在以下程序集中进行了描述:

mov rax, 0x2000004     ; sys_write call identifier
mov rdi, 1             ; STDOUT file descriptor
mov rsi, myMessage     ; buffer to print
mov rdx, myMessageLen  ; length of buffer
syscall                ; make the system call

您可以在(/usr/include/)sys/syscall.h中从用户模式获取系统调用号码列表。这些数字与 Linux 中的数字不同。该文件是在 XNU 构建期间从 bsd/kern/syscalls/syscalls.master.

自动生成的

如果您使用 libsystem_kernel 系统调用导出,您可以按原样使用这些数字。如果您使用汇编,则必须添加 0x2000000 以将它们标记为 BSD 层(而不是 0x1000000,这意味着 Mach 陷阱,或 0x3000000,这意味着机器相关)。

要查看系统调用在汇编中的使用示例,您可以轻松反汇编导出的包装器:x86_64 的 /usr/lib/system/libsystem_kernel.dylib(或 ARM64 使用共享库缓存中的 jtool)。

如前所述,您需要在索书号中添加0x2000000。那个幻数的解释来自 osfmk/mach/i386/syscall_sw.h 中的 xnu 内核源代码(搜索 SYSCALL_CLASS_SHIFT)。

/*
 * 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 上有 class 个系统调用。所有的系统调用都是通过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 */

每个系统调用都带有一个 class 枚举标记,该枚举左移 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 真的希望你 link 反对解析你的 系统调用 shim 的库对象文件,而不是使用内联例程:对象兼容性而不是源兼容性。

在 x86_64 上,系统调用本身像 Linux 一样使用 System V ABI(第 A.2.1 节),并且它使用 syscall 指令(int 0x80 Linux 中的系统调用)。参数在 rdi、rsi、rdx、r10、r8 和 r9 中传递。系统调用号在 rax 寄存器中。