My application builds on environments that are older, and do not support newer (specific) system calls. I can’t go upgrading them for reasons I can’t disclose, but instead of making it compile time (which would lose out on any ‘benefits’) I was wondering if there’s a way to do in inline assembly. For example:
#include <syscall.h> static int function() { int z; #ifdef SYS_some_system_call do_this(some_newer_syscall); z=1; #else do_that(older_syscall); z=0; #endif }
Is there a way to check for system call support in assembly and use that instead (first time around)?
Advertisement
Answer
If a system call does not exist, it fails with the error ENOSYS
(Function not implemented). So the easiest way to test for the existence of a system call is to call it and assume it exists if it didn’t fail with ENOSYS
. You don’t need to write assembly code for that, just use the syscall
function from unistd.h
.
Generally this works as system call numbers are governed by the Linux kernel project. While it is possible that people might add their own system calls with numbers conflicting with possible future system calls, I wouldn’t assume that this is possible. People who modify their systems like that are liable for the results from this kind of action.
Another way that works for library functions in general is to use dlsym
or dlfunc
to check if a symbol for the desired system call is available. For example, you might want to do:
ssize_t (*getrandom)(void *, size_t, unsigned); getrandom = (ssize_t (*)(void *, size_t unsigned))dlfunc(RTLD_DEFAULT, "getrandom"); if (getrandom != NULL) /* getrandom is available */ else /* getrandom is not available */
to check if a function named getrandom
is available. Make sure to not accidentally reference the symbol getrandom
normally or your program won’t link on platforms that don’t have it. Of course, mentioning getrandom
in a string doesn’t count.