[PATCH 3/3] tools/nolibc: add the _syscall() macro
From: Thomas Weißschuh
Date: Sun Apr 05 2026 - 05:06:50 EST
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 which 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@xxxxxxxxxxxxxx>
---
tools/include/nolibc/sys/syscall.h | 3 ++-
tools/testing/selftests/nolibc/nolibc-test.c | 4 ++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/tools/include/nolibc/sys/syscall.h b/tools/include/nolibc/sys/syscall.h
index 3f43fac3d7b8..7f06314fcf0d 100644
--- a/tools/include/nolibc/sys/syscall.h
+++ b/tools/include/nolibc/sys/syscall.h
@@ -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 */
diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
index dd10402267ee..4bcf46867603 100644
--- a/tools/testing/selftests/nolibc/nolibc-test.c
+++ b/tools/testing/selftests/nolibc/nolibc-test.c
@@ -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 */
--
2.53.0