Skip to content

Commit 861ea34

Browse files
committed
Merge tag 'nolibc-20260206-for-7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/nolibc/linux-nolibc
Pull nolibc updates from Thomas Weißschuh: - All time-related functionality uses 64-bit timestamps for y2038 compatibility - fread() and fskeek() support - ptrace() support - Addition of libc-test to the regular kselftests - Smaller cleanups and fixes to the code and build system * tag 'nolibc-20260206-for-7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/nolibc/linux-nolibc: (25 commits) tools/nolibc: Add a simple test for writing to a FILE and reading it back tools/nolibc: Add fseek() to stdio.h tools/nolibc: Add fread() to stdio.h selftests/nolibc: also test libc-test through regular selftest framework selftests/nolibc: scope custom flags to the nolibc-test target selftests/nolibc: try to read from stdin in readv_zero test selftests/nolibc: always build sparc32 tests with -mcpu=v8 tools/nolibc: align sys_vfork() with sys_fork() selftests/nolibc: drop NOLIBC_SYSROOT=0 logic selftests/nolibc: add static assertions around time types handling tools/nolibc: add __nolibc_static_assert() tools/nolibc: add compiler version detection macros tools/nolibc: remove time conversions selftests/nolibc: test compatibility of nolibc and kernel time types tools/nolibc: always use 64-bit time types tools/nolibc: use custom structs timespec and timeval tools/nolibc/select: avoid libgcc 64-bit multiplications tools/nolibc/gettimeofday: avoid libgcc 64-bit divisions tools/nolibc: prefer explicit 64-bit time-related system calls tools/nolibc/time: drop invocation of gettimeofday system call ...
2 parents d16738a + a5f00be commit 861ea34

17 files changed

Lines changed: 299 additions & 153 deletions

File tree

tools/include/nolibc/Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ all_files := \
5454
sys/mman.h \
5555
sys/mount.h \
5656
sys/prctl.h \
57+
sys/ptrace.h \
5758
sys/random.h \
5859
sys/reboot.h \
5960
sys/resource.h \
@@ -103,9 +104,12 @@ headers_standalone: headers
103104
$(Q)$(MAKE) -C $(srctree) headers
104105
$(Q)$(MAKE) -C $(srctree) headers_install INSTALL_HDR_PATH=$(OUTPUT)sysroot
105106

107+
CFLAGS_s390 := -m64
108+
CFLAGS := $(CFLAGS_$(ARCH))
109+
106110
headers_check: headers_standalone
107111
$(Q)for header in $(filter-out crt.h std.h,$(all_files)); do \
108-
$(CC) $(CLANG_CROSS_FLAGS) -Wall -Werror -nostdinc -fsyntax-only -x c /dev/null \
112+
$(CC) $(CFLAGS) $(CLANG_CROSS_FLAGS) -Wall -Werror -nostdinc -fsyntax-only -x c /dev/null \
109113
-I$(or $(objtree),$(srctree))/usr/include -include $$header -include $$header || exit 1; \
110114
done
111115

tools/include/nolibc/arch-s390.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
#ifndef _NOLIBC_ARCH_S390_H
77
#define _NOLIBC_ARCH_S390_H
8+
9+
#include "types.h"
10+
11+
#include <linux/sched.h>
812
#include <linux/signal.h>
913
#include <linux/unistd.h>
1014

@@ -186,4 +190,11 @@ pid_t sys_fork(void)
186190
}
187191
#define sys_fork sys_fork
188192

193+
static __attribute__((unused))
194+
pid_t sys_vfork(void)
195+
{
196+
return my_syscall5(__NR_clone, 0, CLONE_VM | CLONE_VFORK | SIGCHLD, 0, 0, 0);
197+
}
198+
#define sys_vfork sys_vfork
199+
189200
#endif /* _NOLIBC_ARCH_S390_H */

tools/include/nolibc/compiler.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,28 @@
4747
# define __nolibc_fallthrough do { } while (0)
4848
#endif /* __nolibc_has_attribute(fallthrough) */
4949

50+
#define __nolibc_version(_major, _minor, _patch) ((_major) * 10000 + (_minor) * 100 + (_patch))
51+
52+
#ifdef __GNUC__
53+
# define __nolibc_gnuc_version \
54+
__nolibc_version(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
55+
#else
56+
# define __nolibc_gnuc_version 0
57+
#endif /* __GNUC__ */
58+
59+
#ifdef __clang__
60+
# define __nolibc_clang_version \
61+
__nolibc_version(__clang_major__, __clang_minor__, __clang_patchlevel__)
62+
#else
63+
# define __nolibc_clang_version 0
64+
#endif /* __clang__ */
65+
66+
#if __STDC_VERSION__ >= 201112L || \
67+
__nolibc_gnuc_version >= __nolibc_version(4, 6, 0) || \
68+
__nolibc_clang_version >= __nolibc_version(3, 0, 0)
69+
# define __nolibc_static_assert(_t) _Static_assert(_t, "")
70+
#else
71+
# define __nolibc_static_assert(_t)
72+
#endif
73+
5074
#endif /* _NOLIBC_COMPILER_H */

tools/include/nolibc/nolibc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
#include "sys/mman.h"
102102
#include "sys/mount.h"
103103
#include "sys/prctl.h"
104+
#include "sys/ptrace.h"
104105
#include "sys/random.h"
105106
#include "sys/reboot.h"
106107
#include "sys/resource.h"

tools/include/nolibc/poll.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,22 @@
2323
static __attribute__((unused))
2424
int sys_poll(struct pollfd *fds, int nfds, int timeout)
2525
{
26-
#if defined(__NR_ppoll)
27-
struct timespec t;
26+
#if defined(__NR_ppoll_time64)
27+
struct __kernel_timespec t;
2828

2929
if (timeout >= 0) {
3030
t.tv_sec = timeout / 1000;
3131
t.tv_nsec = (timeout % 1000) * 1000000;
3232
}
33-
return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
34-
#elif defined(__NR_ppoll_time64)
35-
struct __kernel_timespec t;
33+
return my_syscall5(__NR_ppoll_time64, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
34+
#else
35+
struct __kernel_old_timespec t;
3636

3737
if (timeout >= 0) {
3838
t.tv_sec = timeout / 1000;
3939
t.tv_nsec = (timeout % 1000) * 1000000;
4040
}
41-
return my_syscall5(__NR_ppoll_time64, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
42-
#else
43-
return my_syscall3(__NR_poll, fds, nfds, timeout);
41+
return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
4442
#endif
4543
}
4644

tools/include/nolibc/std.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ typedef unsigned long nlink_t;
2929
typedef int64_t off_t;
3030
typedef signed long blksize_t;
3131
typedef signed long blkcnt_t;
32-
typedef __kernel_time_t time_t;
32+
typedef __kernel_time64_t time_t;
3333

3434
#endif /* _NOLIBC_STD_H */

tools/include/nolibc/stdio.h

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ int putchar(int c)
170170
}
171171

172172

173-
/* fwrite(), puts(), fputs(). Note that puts() emits '\n' but not fputs(). */
173+
/* fwrite(), fread(), puts(), fputs(). Note that puts() emits '\n' but not fputs(). */
174174

175175
/* internal fwrite()-like function which only takes a size and returns 0 on
176176
* success or EOF on error. It automatically retries on short writes.
@@ -204,6 +204,38 @@ size_t fwrite(const void *s, size_t size, size_t nmemb, FILE *stream)
204204
return written;
205205
}
206206

207+
/* internal fread()-like function which only takes a size and returns 0 on
208+
* success or EOF on error. It automatically retries on short reads.
209+
*/
210+
static __attribute__((unused))
211+
int _fread(void *buf, size_t size, FILE *stream)
212+
{
213+
int fd = fileno(stream);
214+
ssize_t ret;
215+
216+
while (size) {
217+
ret = read(fd, buf, size);
218+
if (ret <= 0)
219+
return EOF;
220+
size -= ret;
221+
buf += ret;
222+
}
223+
return 0;
224+
}
225+
226+
static __attribute__((unused))
227+
size_t fread(void *s, size_t size, size_t nmemb, FILE *stream)
228+
{
229+
size_t nread;
230+
231+
for (nread = 0; nread < nmemb; nread++) {
232+
if (_fread(s, size, stream) != 0)
233+
break;
234+
s += size;
235+
}
236+
return nread;
237+
}
238+
207239
static __attribute__((unused))
208240
int fputs(const char *s, FILE *stream)
209241
{
@@ -240,6 +272,25 @@ char *fgets(char *s, int size, FILE *stream)
240272
}
241273

242274

275+
/* fseek */
276+
static __attribute__((unused))
277+
int fseek(FILE *stream, long offset, int whence)
278+
{
279+
int fd = fileno(stream);
280+
off_t ret;
281+
282+
ret = lseek(fd, offset, whence);
283+
284+
/* lseek() and fseek() differ in that lseek returns the new
285+
* position or -1, fseek() returns either 0 or -1.
286+
*/
287+
if (ret >= 0)
288+
return 0;
289+
290+
return -1;
291+
}
292+
293+
243294
/* minimal printf(). It supports the following formats:
244295
* - %[l*]{d,u,c,x,p}
245296
* - %s

tools/include/nolibc/sys.h

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include <linux/time.h>
2323
#include <linux/auxvec.h>
2424
#include <linux/fcntl.h> /* for O_* and AT_* */
25-
#include <linux/sched.h> /* for clone_args */
25+
#include <linux/sched.h> /* for CLONE_* */
2626
#include <linux/stat.h> /* for statx() */
2727

2828
#include "errno.h"
@@ -363,19 +363,11 @@ pid_t fork(void)
363363
static __attribute__((unused))
364364
pid_t sys_vfork(void)
365365
{
366-
#if defined(__NR_vfork)
366+
#if defined(__NR_clone)
367+
/* See the note in sys_fork(). */
368+
return my_syscall5(__NR_clone, CLONE_VM | CLONE_VFORK | SIGCHLD, 0, 0, 0, 0);
369+
#elif defined(__NR_vfork)
367370
return my_syscall0(__NR_vfork);
368-
#else
369-
/*
370-
* clone() could be used but has different argument orders per
371-
* architecture.
372-
*/
373-
struct clone_args args = {
374-
.flags = CLONE_VM | CLONE_VFORK,
375-
.exit_signal = SIGCHLD,
376-
};
377-
378-
return my_syscall2(__NR_clone3, &args, sizeof(args));
379371
#endif
380372
}
381373
#endif

tools/include/nolibc/sys/ptrace.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2+
/*
3+
* ptrace for NOLIBC
4+
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
5+
* Copyright (C) 2025 Intel Corporation
6+
*/
7+
8+
/* make sure to include all global symbols */
9+
#include "../nolibc.h"
10+
11+
#ifndef _NOLIBC_SYS_PTRACE_H
12+
#define _NOLIBC_SYS_PTRACE_H
13+
14+
#include "../sys.h"
15+
16+
#include <linux/ptrace.h>
17+
18+
/*
19+
* long ptrace(int op, pid_t pid, void *addr, void *data);
20+
*/
21+
static __attribute__((unused))
22+
long sys_ptrace(int op, pid_t pid, void *addr, void *data)
23+
{
24+
return my_syscall4(__NR_ptrace, op, pid, addr, data);
25+
}
26+
27+
static __attribute__((unused))
28+
ssize_t ptrace(int op, pid_t pid, void *addr, void *data)
29+
{
30+
return __sysret(sys_ptrace(op, pid, addr, data));
31+
}
32+
33+
#endif /* _NOLIBC_SYS_PTRACE_H */

tools/include/nolibc/sys/select.h

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,33 +63,22 @@ typedef struct {
6363
static __attribute__((unused))
6464
int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
6565
{
66-
#if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect)
67-
struct sel_arg_struct {
68-
unsigned long n;
69-
fd_set *r, *w, *e;
70-
struct timeval *t;
71-
} arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout };
72-
return my_syscall1(__NR_select, &arg);
73-
#elif defined(__NR__newselect)
74-
return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout);
75-
#elif defined(__NR_select)
76-
return my_syscall5(__NR_select, nfds, rfds, wfds, efds, timeout);
77-
#elif defined(__NR_pselect6)
78-
struct timespec t;
66+
#if defined(__NR_pselect6_time64)
67+
struct __kernel_timespec t;
7968

8069
if (timeout) {
8170
t.tv_sec = timeout->tv_sec;
82-
t.tv_nsec = timeout->tv_usec * 1000;
71+
t.tv_nsec = (uint32_t)timeout->tv_usec * 1000;
8372
}
84-
return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
73+
return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
8574
#else
86-
struct __kernel_timespec t;
75+
struct __kernel_old_timespec t;
8776

8877
if (timeout) {
8978
t.tv_sec = timeout->tv_sec;
90-
t.tv_nsec = timeout->tv_usec * 1000;
79+
t.tv_nsec = (uint32_t)timeout->tv_usec * 1000;
9180
}
92-
return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
81+
return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
9382
#endif
9483
}
9584

0 commit comments

Comments
 (0)