tools/nolibc/unistd: add syscall()
authorThomas Weißschuh <linux@weissschuh.net>
Sat, 20 May 2023 07:58:57 +0000 (09:58 +0200)
committerPaul E. McKenney <paulmck@kernel.org>
Fri, 9 Jun 2023 18:46:07 +0000 (11:46 -0700)
syscall() is used by "normal" libcs to allow users to directly call
syscalls.
By having the same syntax inside nolibc users can more easily write code
that works with different libcs.

The macro logic is adapted from systemtaps STAP_PROBEV() macro that is
released in the public domain / CC0.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
tools/include/nolibc/unistd.h
tools/testing/selftests/nolibc/nolibc-test.c

index ac7d53d986cd11ac84dd0a17e5a7055c779b2b10..0e832e10a0b2784fc5b1fa2efc1bdd276907785d 100644 (file)
@@ -56,6 +56,21 @@ int tcsetpgrp(int fd, pid_t pid)
        return ioctl(fd, TIOCSPGRP, &pid);
 }
 
+#define _syscall(N, ...)                                                      \
+({                                                                            \
+       long _ret = my_syscall##N(__VA_ARGS__);                               \
+       if (_ret < 0) {                                                       \
+               SET_ERRNO(-_ret);                                             \
+               _ret = -1;                                                    \
+       }                                                                     \
+       _ret;                                                                 \
+})
+
+#define _syscall_narg(...) __syscall_narg(__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0)
+#define __syscall_narg(_0, _1, _2, _3, _4, _5, _6, N, ...) N
+#define _syscall_n(N, ...) _syscall(N, __VA_ARGS__)
+#define syscall(...) _syscall_n(_syscall_narg(__VA_ARGS__), ##__VA_ARGS__)
+
 /* make sure to include all global symbols */
 #include "nolibc.h"
 
index f042a6436b6bf5c537de18b5c0215ed740a7fc49..54bf91847af3fbe7f65f225ed146667d70427de0 100644 (file)
@@ -588,6 +588,8 @@ int run_syscall(int min, int max)
                CASE_TEST(waitpid_child);     EXPECT_SYSER(1, waitpid(getpid(), &tmp, WNOHANG), -1, ECHILD); break;
                CASE_TEST(write_badf);        EXPECT_SYSER(1, write(-1, &tmp, 1), -1, EBADF); break;
                CASE_TEST(write_zero);        EXPECT_SYSZR(1, write(1, &tmp, 0)); break;
+               CASE_TEST(syscall_noargs);    EXPECT_SYSEQ(1, syscall(__NR_getpid), getpid()); break;
+               CASE_TEST(syscall_args);      EXPECT_SYSER(1, syscall(__NR_fstat, 0, NULL), -1, EFAULT); break;
                case __LINE__:
                        return ret; /* must be last */
                /* note: do not set any defaults so as to permit holes above */