Search code examples
linuxsystem-callsc-libraries

Languages that make system calls directly


I have been learning about system calls in linux and how the GNU C library functions are really just wrappers that end up calling the actual system calls. I have also read that a lot/a few other languages don't actually make their own system calls but rather just call C and have the C library make the system call for it.
So my question is whether there is a programming language that makes the system calls itself without interacting with the C library at all? Like does the interrupt and sets up the registers etc?
I have tried looking up a few but there is either no information or they just call on C.
Thank you.


Solution

  • Go (golang) does this. Here's parts of the source code for the Go Linux AMD64 syscalls which sets up registers (Linux on x86_64 uses syscall rather than int 0x80):

    // func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
    TEXT ·Syscall6(SB),NOSPLIT,$0-80
        CALL    runtime·entersyscall(SB)
        MOVQ    a1+8(FP), DI
        MOVQ    a2+16(FP), SI
        MOVQ    a3+24(FP), DX
        MOVQ    a4+32(FP), R10
        MOVQ    a5+40(FP), R8
        MOVQ    a6+48(FP), R9
        MOVQ    trap+0(FP), AX  // syscall entry
        SYSCALL
        CMPQ    AX, $0xfffffffffffff001
        JLS ok6
        MOVQ    $-1, r1+56(FP)
        MOVQ    $0, r2+64(FP)
        NEGQ    AX
        MOVQ    AX, err+72(FP)
        CALL    runtime·exitsyscall(SB)
        RET
    ok6:
        MOVQ    AX, r1+56(FP)
        MOVQ    DX, r2+64(FP)
        MOVQ    $0, err+72(FP)
        CALL    runtime·exitsyscall(SB)
        RET
    

    This has the predictable downside of having to write and maintain one file for every kernel convention multiplied by every supported architecture. The directory currently has files indicating support for each of the following:

    • aix_ppc64, darwin_386, darwin_amd64, darwin_arm, darwin_arm64, freebsd_arm, linux_386, linux_amd64, linux_arm, linux_arm64, linux_mips64x, linux_mipsx, linux_ppc64x, linux_s390x, nacl_386, nacl_amd64p32, nacl_arm, netbsd_arm, openbsd_arm, plan9_386, plan9_amd64, plan9_arm, solaris_amd64, unix_386, unix_amd64

    It's also possible to link against libc for unsupported combinations or new ports, but go1.11.4 linux/amd64 defaults to using syscalls directly.