2

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.

  • also c cannot make system calls directly, there is (inline) assembly code for this. – thejonny Feb 26 '19 at 21:02
  • - is your question correctly rephrased as "is there a standard library for another programming language that does not depend on a library in/for c for making system calls"? - is it linux specific? in redox, rust is used as main programming language – thejonny Feb 26 '19 at 21:11
  • @thejonny yes I would say that would be a good way to rephrase it. I did know about the assembly in C so your way of asking it would be just as well. –  Feb 27 '19 at 13:21

1 Answers1

2

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.

that other guy
  • 116,971
  • 11
  • 170
  • 194
  • Thank you, this is just what I was looking for and couldn't find. A followup question though- Why does Go and even C use assembly to make syscalls? Why couldn't they write it in the same language (C for example) and have the compiler turn that into assembly? Which gnu C does already. Thank you –  Feb 27 '19 at 13:48
  • At some point, someone needs to sit down and design the sequence of assembly code above. If you say that the library dev should just use a compiler intrinsic function `__linux_arm64_syscall(....)` and have the compiler generate that assembly code, then you've just pushed the exact same work onto the compiler backend dev instead. If you say that the library dev should write `copyReg64(stack64[1], registers.DI);` etc, then you've just reinvented a more awkward and tightly coupled inline assembly syntax. – that other guy Feb 27 '19 at 17:17