1

The man page for syscall says that the first argument is the system call number. On my system (linux x64), arguments are sent in rdi, rsi, rdx, rcx, r8 and r9. So, rdi receives the call number. The syscall in ASM expects the system call number to be in rax, which means by having a generic ASM function syscall(int number, ...arguments), some shifting has to be made, and it's what I've seen when looking at some implementations of the LIBC.

For every system call, take the first argument sent from C code (received in rdi), move it to rax for the system, take the second argument from C code (received in rsi) and move it to rdi (will be first argument for the system).

This makes extra computation, by having an exit(int status) writen straight in ASM, arguments are well placed for the system, and the ASM function just puts 0x3c code in rax and executes syscall.

Are there benefits from having an available generic syscall(int number, ...) in C which has to shift arguments, rather than 312 specific ASM functions ? Other than writing less code.

System calls for my system are here: https://syscalls.w3challs.com/?arch=x86_64

The syscall man page: https://man7.org/linux/man-pages/man2/syscall.2.html

PS: not trying to reinvent the standard, just doing stuff from scratch for fun.

2
  • The normal libc wrappers don't use that crappy syscall(2) stand-alone function that takes the call number as the first arg. Commented Apr 24, 2021 at 8:54
  • Also note that people have written macros for every system call for most arches Linux has been ported to, using some helper macros to combine generic handling of 3-arg system calls named macros for each system call: github.com/linux-on-ibm-z/linux-syscall-support/blob/master/… Commented Apr 24, 2021 at 9:27

1 Answer 1

4

syscall is a glue between your portable C code and the platform-specific syscall mechanism of your OS.

You call syscall with the standard C calling convention understood by your compiler. Yes, this calls for some extra tweaking with the registers on x86-64 but it also means that if you want to port your code to, say, Rasberry Pi, under the same kernel version, you only need to recompile your code.
You don't need to use a macro to switch on and off different implementations of each syscall you made.

syscall will also convert from the error convention used by the syscall interface (e.g. using negative numbers on Linux) to the standard errno C convention.

Using syscall will of course already limit the portability of your code but not as much as writing directly in assembly.

Could the syscall parameters have been reordered so that less shifting would be required (e.g. by having the syscall number last)?
Yes, but that would only be true for x86-64 and syscall existed well before that.
Furthermore, syscall is variadic and there is no concept of last in this case. I think it is still possible to make sure the first args are in the right register but it would be a very ugly interface (at that's now how syscall is already defined).

Wouldn't be better if glibc wrote a fast, tailored, handler for each syscall?
That's more a BSD fashioned choice (where kernel and user code are developed together) than a GNU fashioned one.
GNU is not Linux and glibc is not released together with the Linux kernel, having to maintain all the syscalls of Linux (and other OSes) would be too cumbersome. Also, C is more strict than assembly, you can somehow extend the assembly interface of an already existing syscall but it may be problematic in C (if you used a fully prototyped function with no varargs and with strict param types, for example).
I think I understand their need to be generic when dealing with this highly variable aspect of the platform.

Sign up to request clarification or add additional context in comments.

8 Comments

Wouldn't be better if glibc wrote a fast, tailored, handler for each syscall? - They do, using inline asm macros internally which they don't expose in .h headers for use outside glibc. If you disassemble /lib/libc.so.6 and look at the code for a function like rmdir, it starts with mov eax,0x54 / syscall because the other args are already in the right place (with at most a mov r10, rcx for syscalls with 4 or more args).
That craptastic syscall(2) wrapper function is only for use by user-space code that wants to mess around with stuff, and doesn't use something better like github.com/linux-on-ibm-z/linux-syscall-support/blob/master/… wrapper macros, or a slightly more generic macro or function setup with wrappers like syscall1, syscall2, etc. for different numbers of args. (Even as non-macro full functions, as syscall3 could be designed to take the call number as the last arg, and only have to mov eax, ecx, if anyone does that)
@PeterCordes I think the point is separating the interface from the implementation. Internally they will use tailored macros to call the syscalls but, I assume, only for those necessary to implement the public API. syscall is fundamentally ill-defined, it's must be a portable way to do non-portable things. It is natural that will fell out of synch with some architecture. In the x86 (32-bit) era, I don't think the missed optimization was so clear as it is in x86-64.
Hmm, yeah I'm now less sure about misconceptions in the question; I thought it was assuming that glibc used this internally (which would make for inefficiency in normal programs), but now I think maybe just asking about this function itself vs. inline macros.
You wrote that syscall() could take the call number last. Yes but in C, only by requiring 6 other args first, not variadic. Variadic functions don't know how many args they were passed, and having syscall() have to index the arg-passing registers if the call number isn't on the stack would also suck even if it had a way to do it. Maybe you meant by having syscall0, syscall1, ..., syscall6 different versions.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.