When producing a Linux binary, or when deploying tools to customer servers, an annoying issue that comes up regularly is glibc version conflicts.
Linux is famous for prioritizing backwards compatibility of syscalls. You can find many examples online of Linus Torvalds telling people not to break userspace. Despite this, most Linux binaries are very fragile.
uint64_t syscall0(uint64_t number) {
size_t res;
asm volatile("syscall" : "=a"(res) : "a"(number) : "rcx", "r11", "memory");
return res;
}
uint64_t syscall1(uint64_t number, uint64_t arg0) {
size_t res;
asm volatile("syscall"
: "=a"(res)
: "a"(number), "D"(arg0)
: "rcx", "r11", "memory");
return res;
}
uint64_t syscall2(uint64_t number, uint64_t arg0, uint64_t arg1) {
size_t res;
asm volatile("syscall"
: "=a"(res)
: "a"(number), "D"(arg0), "S"(arg1)
: "rcx", "r11", "memory");
return res;
}
uint64_t syscall3(uint64_t number, uint64_t arg0, uint64_t arg1,
uint64_t arg2) {
uint64_t res;
asm volatile("syscall"
: "=a"(res)
: "a"(number), "D"(arg0), "S"(arg1), "d"(arg2)
: "rcx", "r11", "memory");
return res;
}
uint64_t syscall6(uint64_t number, uint64_t arg0, uint64_t arg1, uint64_t arg2,
uint64_t arg3, uint64_t arg4, uint64_t arg5) {
uint64_t res;
register uint64_t r10 asm("r10") = arg3;
register uint64_t r8 asm("r8") = arg4;
register uint64_t r9 asm("r9") = arg5;
asm volatile("syscall"
: "=a"(res)
: "a"(number), "D"(arg0), "S"(arg1), "d"(arg2), "r"(r10),
"r"(r8), "r"(r9)
: "rcx", "r11", "memory");
return res;
}