Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

macOS 64-bit System Call Table [duplicate]

I can find a Linux 64-bit system call table, but the call numbers do not work on macOS - I get a Bus Error: 10 whenever I try to use them.

What are the macOS call numbers for operations like sys_write?

like image 711
Bennett Avatar asked Feb 17 '18 20:02

Bennett


2 Answers

You can get the list of system call numbers from user mode in (/usr/include/)sys/syscall.h. The numbers ARE NOT the same as in Linux. The file is autogenerated during XNU build from bsd/kern/syscalls/syscalls.master.

If you use the libsystem_kernel syscall export you can use the numbers as they are. If you use assembly you have to add 0x2000000 to mark them for the BSD layer (rather than 0x1000000, which would mean Mach traps, or 0x3000000, which would mean machine dependent).

To see examples of system call usage in assembly, you can easily disassemble the exported wrappers: x86_64's /usr/lib/system/libsystem_kernel.dylib (or ARM64's using jtool from the shared library cache).

like image 182
Technologeeks Avatar answered Oct 01 '22 18:10

Technologeeks


As was already pointed out, you need to add 0x2000000 to the call number. The explanation of that magic number comes from the xnu kernel sources in osfmk/mach/i386/syscall_sw.h (search 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.

There are classes of system calls on OSX. All system calls enter the kernel via the syscall instruction. At that point there are Mach system calls, BSD system calls, NONE, diagnostic and machine-dependent.

#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 */

Each system call is tagged with a class enumeration which is left-shifted 24 bits, SYSCALL_CLASS_SHIFT. The enumeration for BSD system calls is 2, SYSCALL_CLASS_UNIX. So that magic number 0x2000000 is constructed as:

// 2 << 24
#define SYSCALL_CONSTRUCT_UNIX(syscall_number) \
            ((SYSCALL_CLASS_UNIX << SYSCALL_CLASS_SHIFT) | \
             (SYSCALL_NUMBER_MASK & (syscall_number)))

Apparently you can get that magic number from the kernel sources but not from the developer include files. I think this means that Apple really wants you to link against library object files that resolve your system call shim rather than use an inline routine: object compatibility rather than source compatibility.

On x86_64, the system call itself uses the System V ABI (section A.2.1) as Linux does and it uses the syscall instruction (int 0x80 for syscall in Linux). Arguments are passed in rdi, rsi, rdx, r10, r8 and r9. The syscall number is in the rax register.

like image 43
Olsonist Avatar answered Oct 01 '22 18:10

Olsonist