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.
Asked
Active
Viewed 288 times
2
-
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 Answers
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