Hacker News new | ask | show | jobs
by jmillikin 1399 days ago
IMO it's worth distinguishing between what the OS allows and what the OS vendor supports. The macOS kernel still has a lot of FreeBSD heritage, including the ability to make direct syscalls, but Apple only guarantees compatibility for syscalls made via libSystem.

This is a reflection of historical differences in opinion about whether the stable ABI for an OS kernel should be the kernel itself (ala Linux), libc (ala Solaris or OpenBSD), or a language-agnostic library (Windows NT's ntdll).

macOS seems to be in a transition period toward the Windows model, with libSystem providing trampolines into the kernel. However, they don't yet enforce this model like OpenBSD does, so if you're willing to risk the syscall numbers changing you can do without libSystem.

Here's an example, lightly adapted from <https://john-millikin.com/unix-syscalls#darwin-x86-64>:

  .data
   .set L_STDOUT,        1
   .set L_SYSCALL_EXIT,  0x2000001
   .set L_SYSCALL_WRITE, 0x2000004
   L_message:
    .ascii "Hello, world!\n"
    .set L_message_len, . - L_message
  
  .text
   .global start
   start:
    # write(STDOUT, message, message_len)
    mov     $L_SYSCALL_WRITE, %rax
    mov     $L_STDOUT,        %rdi
    lea     L_message(%rip),  %rsi
    mov     $L_message_len,   %rdx
    syscall
  
    # exit(0)
    mov     $L_SYSCALL_EXIT, %rax
    mov     $0,              %rdi
    syscall
Compile (assemble?) it to a static binary:

  $ as -arch x86_64 hello.S -o hello.o
  $ ld -arch x86_64 -o hello -static hello.o
  $ file hello
  hello: Mach-O 64-bit executable x86_64
It runs fine:

  $ ./hello
  Hello, world!
1 comments

Hey John,

Thanks for commenting. I had read your article via another comment here. I had not thought about the syscall approach before, because as you note Apple does not (well, did not previously) guarantee syscall stability.