tools/nolibc: add the _syscall() macro

The standard syscall() function or macro uses the libc return value
convention. Errors returned from the kernel as negative values are
stored in errno and -1 is returned. Users who want to avoid using
errno don't have a way to call raw syscalls and check the returned
error.

Add a new macro _syscall() which works like the standard syscall()
but passes through the return value from the kernel unchanged.
The naming scheme and return values match the named _sys_foo()
system call wrappers already part of nolibc.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Acked-by: Willy Tarreau <w@1wt.eu>
Link: https://patch.msgid.link/20260405-nolibc-syscall-v1-3-e5b12bc63211@weissschuh.net
This commit is contained in:
Thomas Weißschuh
2026-04-05 11:06:25 +02:00
parent 022bbb5a41
commit 2eb64b936d
2 changed files with 6 additions and 1 deletions

View File

@@ -14,6 +14,7 @@
#define __nolibc_syscall_narg(...) ___nolibc_syscall_narg(__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0)
#define __nolibc_syscall(N, ...) __nolibc_syscall##N(__VA_ARGS__)
#define __nolibc_syscall_n(N, ...) __nolibc_syscall(N, __VA_ARGS__)
#define syscall(...) __sysret(__nolibc_syscall_n(__nolibc_syscall_narg(__VA_ARGS__), ##__VA_ARGS__))
#define _syscall(...) __nolibc_syscall_n(__nolibc_syscall_narg(__VA_ARGS__), ##__VA_ARGS__)
#define syscall(...) __sysret(_syscall(__VA_ARGS__))
#endif /* _NOLIBC_SYS_SYSCALL_H */

View File

@@ -95,6 +95,8 @@ static const int is_glibc =
/* readdir_r() is likely to be marked deprecated */
#undef readdir_r
#define readdir_r(dir, dirent, result) ((errno = EINVAL), -1)
#define _syscall(...) 0
#endif
/* definition of a series of tests */
@@ -1507,6 +1509,8 @@ int run_syscall(int min, int max)
CASE_TEST(ptrace); EXPECT_SYSER(1, ptrace(PTRACE_CONT, getpid(), NULL, NULL), -1, ESRCH); break;
CASE_TEST(syscall_noargs); EXPECT_SYSEQ(1, syscall(__NR_getpid), getpid()); break;
CASE_TEST(syscall_args); EXPECT_SYSER(1, syscall(__NR_statx, 0, NULL, 0, 0, NULL), -1, EFAULT); break;
CASE_TEST(_syscall_noargs); EXPECT_SYSEQ(is_nolibc, _syscall(__NR_getpid), getpid()); break;
CASE_TEST(_syscall_args); EXPECT_SYSEQ(is_nolibc, _syscall(__NR_statx, 0, NULL, 0, 0, NULL), -EFAULT); break;
CASE_TEST(namespace); EXPECT_SYSZR(euid0 && proc, test_namespace()); break;
case __LINE__:
return ret; /* must be last */