mirror of
https://github.com/torvalds/linux.git
synced 2026-10-23 15:32:04 +02:00
nolibc changes for v7.4
Changes: * New architectures: Hexagon, 64-bit parisc * New library functionality: sendfile(), pread(), pwrite() * Various bugfixes and cleanups -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQTg4lxklFHAidmUs57B+h1jyw5bOAUCatSDYwAKCRDB+h1jyw5b OJZOAP4vAP8wrFSsy0JqraUM2zxITIwX9bdqxlrgY4Yq8EECgwD/YT/GdjkJgVew HKIMnggJGIsNloLPeKlDiHEoKF8zgws= =Nzb1 -----END PGP SIGNATURE----- Merge tag 'nolibc-20261018-for-7.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/nolibc/linux-nolibc Pull nolibc updates from Thomas Weißschuh: - New architectures: Hexagon, 64-bit parisc - New library functionality: sendfile(), pread(), pwrite() - Various bugfixes and cleanups * tag 'nolibc-20261018-for-7.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/nolibc/linux-nolibc: (28 commits) selftests/nolibc: explicitly disable position independent executables selftests/nolibc: use the configured kernel header directory tools/nolibc: fix the function argument order of calloc() tools/nolibc: check for overflow in malloc() tools/nolibc: stop rounding malloc() sizes up to 4096 bytes tools/nolibc: add support for pread() and pwrite() tools/nolibc: introduce __NOLIBC_BITS_PER_SYSCALL_ARG tools/nolibc: move __NOLIBC_LLARGPART() to compiler.h tools/nolibc: make 64-bit systemcall argument padding generic selftests/nolibc: make the broken MIPS N32 argument detection reusable tools/nolibc: add 64-bit parisc support selftests/nolibc: test the FD_* macros tools/nolibc: fix FD_SET(), FD_CLR() and FD_ISSET() on 64-bit tools/nolibc: fix readdir_r() with 64-bit directory offsets tools/nolibc: fix verrx() and errx() message formatting selftests/nolibc: add tests for the wait status macros tools/nolibc: fix WIFSIGNALED() for status 0 tools/nolibc/parisc: consistently use %dp to refer to register %r27 selftests/nolibc: validate ENOTDIR return values from opendir()/fdopendir() tools/nolibc: verify that a directory is opened ...
This commit is contained in:
commit
542fed2ef2
|
|
@ -17,7 +17,23 @@ endif
|
|||
# it defaults to this nolibc directory.
|
||||
OUTPUT ?= $(CURDIR)/
|
||||
|
||||
architectures := alpha arm arm64 loongarch m68k mips openrisc parisc powerpc riscv s390 sh sparc x86
|
||||
architectures := \
|
||||
alpha \
|
||||
arm \
|
||||
arm64 \
|
||||
hexagon \
|
||||
loongarch \
|
||||
m68k \
|
||||
mips \
|
||||
openrisc \
|
||||
parisc \
|
||||
powerpc \
|
||||
riscv \
|
||||
s390 \
|
||||
sh \
|
||||
sparc \
|
||||
x86 \
|
||||
|
||||
arch_files := arch.h $(addsuffix .h, $(addprefix arch-, $(architectures)))
|
||||
all_files := \
|
||||
alloca.h \
|
||||
|
|
@ -59,6 +75,7 @@ all_files := \
|
|||
sys/reboot.h \
|
||||
sys/resource.h \
|
||||
sys/select.h \
|
||||
sys/sendfile.h \
|
||||
sys/stat.h \
|
||||
sys/syscall.h \
|
||||
sys/sysmacros.h \
|
||||
|
|
|
|||
|
|
@ -196,11 +196,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __nolibc_no_stack_prote
|
|||
}
|
||||
#endif /* NOLIBC_NO_RUNTIME */
|
||||
|
||||
static __attribute__((unused))
|
||||
int _sys_ftruncate64(int fd, uint32_t length0, uint32_t length1)
|
||||
{
|
||||
return __nolibc_syscall4(__NR_ftruncate64, fd, 0, length0, length1);
|
||||
}
|
||||
#define _sys_ftruncate64 _sys_ftruncate64
|
||||
#define __NOLIBC_PAD_64BIT_SYSCALL_ARGUMENT_PAIR
|
||||
|
||||
#endif /* _NOLIBC_ARCH_ARM_H */
|
||||
|
|
|
|||
159
tools/include/nolibc/arch-hexagon.h
Normal file
159
tools/include/nolibc/arch-hexagon.h
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* hexagon specific definitions for NOLIBC
|
||||
* Copyright (C) 2026 Thomas Weißschuh <linux@weissschuh.net>
|
||||
*/
|
||||
|
||||
#ifndef _NOLIBC_ARCH_HEXAGON_H
|
||||
#define _NOLIBC_ARCH_HEXAGON_H
|
||||
|
||||
#include <linux/unistd.h>
|
||||
|
||||
#include "compiler.h"
|
||||
#include "crt.h"
|
||||
|
||||
/*
|
||||
* Syscalls for hexagon:
|
||||
* - syscall number is passed in r6
|
||||
* - arguments are in r0, r1, r2, r3, r4, r5
|
||||
* - the system call is performed by calling trap0(#1)
|
||||
* - syscall return value is in r0
|
||||
*/
|
||||
|
||||
#define _NOLIBC_SYSCALL_CLOBBERLIST "memory"
|
||||
|
||||
#define __nolibc_syscall0(num) \
|
||||
({ \
|
||||
register long _num __asm__ ("r6") = (num); \
|
||||
register long _arg1 __asm__ ("r0"); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap0(#1)\n" \
|
||||
: "=r"(_arg1) \
|
||||
: "r"(_num) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define __nolibc_syscall1(num, arg1) \
|
||||
({ \
|
||||
register long _num __asm__ ("r6") = (num); \
|
||||
register long _arg1 __asm__ ("r0") = (long)(arg1); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap0(#1)\n" \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_num) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define __nolibc_syscall2(num, arg1, arg2) \
|
||||
({ \
|
||||
register long _num __asm__ ("r6") = (num); \
|
||||
register long _arg1 __asm__ ("r0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("r1") = (long)(arg2); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap0(#1)\n" \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), \
|
||||
"r"(_num) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define __nolibc_syscall3(num, arg1, arg2, arg3) \
|
||||
({ \
|
||||
register long _num __asm__ ("r6") = (num); \
|
||||
register long _arg1 __asm__ ("r0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("r1") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("r2") = (long)(arg3); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap0(#1)\n" \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), "r"(_arg3), \
|
||||
"r"(_num) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define __nolibc_syscall4(num, arg1, arg2, arg3, arg4) \
|
||||
({ \
|
||||
register long _num __asm__ ("r6") = (num); \
|
||||
register long _arg1 __asm__ ("r0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("r1") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("r2") = (long)(arg3); \
|
||||
register long _arg4 __asm__ ("r3") = (long)(arg4); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap0(#1)\n" \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), "r"(_arg3), "r"(_arg4), \
|
||||
"r"(_num) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define __nolibc_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
|
||||
({ \
|
||||
register long _num __asm__ ("r6") = (num); \
|
||||
register long _arg1 __asm__ ("r0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("r1") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("r2") = (long)(arg3); \
|
||||
register long _arg4 __asm__ ("r3") = (long)(arg4); \
|
||||
register long _arg5 __asm__ ("r4") = (long)(arg5); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap0(#1)\n" \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
|
||||
"r"(_num) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define __nolibc_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
|
||||
({ \
|
||||
register long _num __asm__ ("r6") = (num); \
|
||||
register long _arg1 __asm__ ("r0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("r1") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("r2") = (long)(arg3); \
|
||||
register long _arg4 __asm__ ("r3") = (long)(arg4); \
|
||||
register long _arg5 __asm__ ("r4") = (long)(arg5); \
|
||||
register long _arg6 __asm__ ("r5") = (long)(arg6); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap0(#1)\n" \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
|
||||
"r"(_num) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#ifndef NOLIBC_NO_RUNTIME
|
||||
/* startup code */
|
||||
void __attribute__((weak, noreturn))
|
||||
__nolibc_entrypoint __nolibc_no_stack_protector
|
||||
_start(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"r0 = sp\n" /* save stack pointer to r0, as arg1 of _start_c */
|
||||
"call _start_c\n" /* transfer to c runtime */
|
||||
);
|
||||
__nolibc_entrypoint_epilogue();
|
||||
}
|
||||
#endif /* NOLIBC_NO_RUNTIME */
|
||||
|
||||
#define __NOLIBC_PAD_64BIT_SYSCALL_ARGUMENT_PAIR
|
||||
|
||||
#endif /* _NOLIBC_ARCH_HEXAGON_H */
|
||||
|
|
@ -72,6 +72,7 @@
|
|||
#define _NOLIBC_SYSCALL_STACK_UNRESERVE
|
||||
|
||||
#define _NOLIBC_SYSCALL_REG register long long
|
||||
#define __NOLIBC_BITS_PER_SYSCALL_ARG 64
|
||||
|
||||
#endif /* _ABIO32 */
|
||||
|
||||
|
|
@ -286,12 +287,7 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __nolibc_no_stack_prote
|
|||
#endif /* NOLIBC_NO_RUNTIME */
|
||||
|
||||
#if defined(_ABIO32)
|
||||
static __attribute__((unused))
|
||||
int _sys_ftruncate64(int fd, uint32_t length0, uint32_t length1)
|
||||
{
|
||||
return __nolibc_syscall4(__NR_ftruncate64, fd, 0, length0, length1);
|
||||
}
|
||||
#define _sys_ftruncate64 _sys_ftruncate64
|
||||
#define __NOLIBC_PAD_64BIT_SYSCALL_ARGUMENT_PAIR
|
||||
#endif
|
||||
|
||||
#endif /* _NOLIBC_ARCH_MIPS_H */
|
||||
|
|
|
|||
|
|
@ -7,9 +7,7 @@
|
|||
#ifndef _NOLIBC_ARCH_PARISC_H
|
||||
#define _NOLIBC_ARCH_PARISC_H
|
||||
|
||||
#if defined(__LP64__)
|
||||
#error 64-bit not supported
|
||||
#endif
|
||||
#include <linux/unistd.h>
|
||||
|
||||
#include "compiler.h"
|
||||
#include "crt.h"
|
||||
|
|
@ -167,9 +165,15 @@
|
|||
void __attribute__((weak, noreturn)) __nolibc_entrypoint __nolibc_no_stack_protector _start(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
#ifdef __LP64__
|
||||
".import __gp\n" /* Set up the dp register */
|
||||
"ldil L%__gp, %dp\n"
|
||||
"ldo R%__gp(%dp), %dp\n"
|
||||
#else
|
||||
".import $global$\n" /* Set up the dp register */
|
||||
"ldil L%$global$, %dp\n"
|
||||
"ldo R%$global$(%r27), %dp\n"
|
||||
"ldo R%$global$(%dp), %dp\n"
|
||||
#endif
|
||||
|
||||
"b _start_c\n" /* Call _start_c, the load below is executed first */
|
||||
|
||||
|
|
@ -182,4 +186,20 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __nolibc_no_stack_prote
|
|||
}
|
||||
#endif /* NOLIBC_NO_RUNTIME */
|
||||
|
||||
#ifdef __LP64__
|
||||
/*
|
||||
* This override is normally only meant for 32-bit architectures.
|
||||
* But parisc 64-bit has __NR_ftruncate64, so this path is taken.
|
||||
* Add an unused second argument to satisfy the calling convention.
|
||||
*/
|
||||
static __attribute__((unused))
|
||||
int _sys_ftruncate64(int fd, uint64_t length, uint64_t unused)
|
||||
{
|
||||
(void)unused;
|
||||
|
||||
return __nolibc_syscall2(__NR_ftruncate64, fd, length);
|
||||
}
|
||||
#define _sys_ftruncate64 _sys_ftruncate64
|
||||
#endif
|
||||
|
||||
#endif /* _NOLIBC_ARCH_PARISC_H */
|
||||
|
|
|
|||
|
|
@ -222,12 +222,7 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __nolibc_no_stack_prote
|
|||
#endif /* NOLIBC_NO_RUNTIME */
|
||||
|
||||
#if !defined(__powerpc64__)
|
||||
static __attribute__((unused))
|
||||
int _sys_ftruncate64(int fd, uint32_t length0, uint32_t length1)
|
||||
{
|
||||
return __nolibc_syscall4(__NR_ftruncate64, fd, 0, length0, length1);
|
||||
}
|
||||
#define _sys_ftruncate64 _sys_ftruncate64
|
||||
#define __NOLIBC_PAD_64BIT_SYSCALL_ARGUMENT_PAIR
|
||||
#endif
|
||||
|
||||
#endif /* _NOLIBC_ARCH_POWERPC_H */
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
#include "compiler.h"
|
||||
#include "crt.h"
|
||||
|
||||
#include <linux/unistd.h>
|
||||
|
||||
/*
|
||||
* Syscalls for SuperH:
|
||||
* - registers are 32bit wide
|
||||
|
|
@ -161,4 +163,20 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __nolibc_no_stack_prote
|
|||
}
|
||||
#endif /* NOLIBC_NO_RUNTIME */
|
||||
|
||||
static __attribute__((unused))
|
||||
ssize_t _sys_pread(int fd, void *buf, size_t count, off_t offset)
|
||||
{
|
||||
return __nolibc_syscall6(__NR_pread64, fd, buf, count, 0,
|
||||
__NOLIBC_LLARGPART(offset, 0), __NOLIBC_LLARGPART(offset, 1));
|
||||
}
|
||||
#define _sys_pread _sys_pread
|
||||
|
||||
static __attribute__((unused))
|
||||
ssize_t _sys_pwrite(int fd, const void *buf, size_t count, off_t offset)
|
||||
{
|
||||
return __nolibc_syscall6(__NR_pwrite64, fd, buf, count, 0,
|
||||
__NOLIBC_LLARGPART(offset, 0), __NOLIBC_LLARGPART(offset, 1));
|
||||
}
|
||||
#define _sys_pwrite _sys_pwrite
|
||||
|
||||
#endif /* _NOLIBC_ARCH_SH_H */
|
||||
|
|
|
|||
|
|
@ -386,5 +386,7 @@ __asm__ (
|
|||
".popsection\n"
|
||||
);
|
||||
|
||||
#define __NOLIBC_BITS_PER_SYSCALL_ARG 64
|
||||
|
||||
#endif /* !defined(__x86_64__) */
|
||||
#endif /* _NOLIBC_ARCH_X86_H */
|
||||
|
|
|
|||
|
|
@ -34,8 +34,15 @@
|
|||
#include "arch-parisc.h"
|
||||
#elif defined(__alpha__)
|
||||
#include "arch-alpha.h"
|
||||
#elif defined(__hexagon__)
|
||||
#include "arch-hexagon.h"
|
||||
#else
|
||||
#error Unsupported Architecture
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __NOLIBC_BITS_PER_SYSCALL_ARG
|
||||
#define __NOLIBC_BITS_PER_SYSCALL_ARG __BITS_PER_LONG
|
||||
#endif
|
||||
|
||||
#endif /* _NOLIBC_ARCH_H */
|
||||
|
|
|
|||
|
|
@ -90,4 +90,13 @@
|
|||
# define __nolibc_no_sanitize_undefined
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper for 32-bit machines where a 64-bit syscall arg needs to be split into
|
||||
* two 32-bit parts while making sure the order of the low/high parts are correct
|
||||
* for the endianness:
|
||||
* __NOLIBC_LLARGPART(x, 0), __NOLIBC_LLARGPART(x, 1)
|
||||
*/
|
||||
#define __NOLIBC_LLARGPART(_arg, _part) \
|
||||
(((union { long long ll; long l[2]; }) { .ll = _arg }).l[_part])
|
||||
|
||||
#endif /* _NOLIBC_COMPILER_H */
|
||||
|
|
|
|||
|
|
@ -30,10 +30,23 @@ typedef struct {
|
|||
static __attribute__((unused))
|
||||
DIR *fdopendir(int fd)
|
||||
{
|
||||
struct stat buf;
|
||||
int ret;
|
||||
|
||||
if (fd < 0) {
|
||||
SET_ERRNO(EBADF);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = fstat(fd, &buf);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
|
||||
if (!S_ISDIR(buf.st_mode)) {
|
||||
SET_ERRNO(ENOTDIR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (DIR *)(intptr_t)~fd;
|
||||
}
|
||||
|
||||
|
|
@ -42,10 +55,11 @@ DIR *opendir(const char *name)
|
|||
{
|
||||
int fd;
|
||||
|
||||
fd = open(name, O_RDONLY);
|
||||
fd = open(name, O_RDONLY | O_DIRECTORY);
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
return fdopendir(fd);
|
||||
|
||||
return (DIR *)(intptr_t)~fd;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
|
|
@ -67,6 +81,7 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
|
|||
struct linux_dirent64 *ldir = (void *)buf;
|
||||
intptr_t i = (intptr_t)dirp;
|
||||
int fd, ret;
|
||||
off_t off;
|
||||
|
||||
if (i >= 0)
|
||||
return EBADF;
|
||||
|
|
@ -86,9 +101,9 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
|
|||
* readdir() can only return one entry at a time.
|
||||
* Make sure the non-returned ones are not skipped.
|
||||
*/
|
||||
ret = _sys_lseek(fd, ldir->d_off, SEEK_SET);
|
||||
if (ret < 0)
|
||||
return -ret;
|
||||
off = _sys_lseek(fd, ldir->d_off, SEEK_SET);
|
||||
if (off < 0)
|
||||
return -off;
|
||||
|
||||
entry->d_ino = ldir->d_ino;
|
||||
/* the destination should always be big enough */
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ void verr(int eval, const char *fmt, va_list args)
|
|||
static __attribute__((noreturn, unused))
|
||||
void verrx(int eval, const char *fmt, va_list args)
|
||||
{
|
||||
warnx(fmt, args);
|
||||
vwarnx(fmt, args);
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@
|
|||
#include "sys/reboot.h"
|
||||
#include "sys/resource.h"
|
||||
#include "sys/select.h"
|
||||
#include "sys/sendfile.h"
|
||||
#include "sys/stat.h"
|
||||
#include "sys/syscall.h"
|
||||
#include "sys/sysmacros.h"
|
||||
|
|
|
|||
|
|
@ -130,9 +130,11 @@ void *malloc(size_t len)
|
|||
{
|
||||
struct nolibc_heap *heap;
|
||||
|
||||
/* Always allocate memory with size multiple of 4096. */
|
||||
len = sizeof(*heap) + len;
|
||||
len = (len + 4095UL) & -4096UL;
|
||||
if (__builtin_expect(__builtin_add_overflow(len, sizeof(*heap), &len), 0)) {
|
||||
SET_ERRNO(ENOMEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
heap = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE,
|
||||
-1, 0);
|
||||
if (__builtin_expect(heap == MAP_FAILED, 0))
|
||||
|
|
@ -143,7 +145,7 @@ void *malloc(size_t len)
|
|||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
void *calloc(size_t size, size_t nmemb)
|
||||
void *calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
size_t x;
|
||||
|
||||
|
|
@ -230,7 +232,7 @@ int _nolibc_u64toa_base(uint64_t in, char *buffer, unsigned int base, uint64_t r
|
|||
|
||||
/* Generate least significant digit first */
|
||||
do {
|
||||
#if defined(__SIZEOF_INT128__) && !defined(__mips__) && !defined(__sparc__)
|
||||
#if defined(__SIZEOF_INT128__) && !defined(__mips__) && !defined(__sparc__) && !defined(__hppa__)
|
||||
q = ((unsigned __int128)in * recip) >> 64;
|
||||
#else
|
||||
uint64_t p = (uint32_t)in * (recip >> 32);
|
||||
|
|
|
|||
|
|
@ -71,16 +71,6 @@ static __inline__ int __nolibc_enosys(const char *syscall, ...)
|
|||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Helper for 32-bit machines where a 64-bit syscall arg needs to be split into
|
||||
* two 32-bit parts while making sure the order of the low/high parts are correct
|
||||
* for the endianness:
|
||||
* __NOLIBC_LLARGPART(x, 0), __NOLIBC_LLARGPART(x, 1)
|
||||
*/
|
||||
#define __NOLIBC_LLARGPART(_arg, _part) \
|
||||
(((union { long long ll; long l[2]; }) { .ll = _arg }).l[_part])
|
||||
|
||||
|
||||
/* Functions in this file only describe syscalls. They're declared static so
|
||||
* that the compiler usually decides to inline them while still being allowed
|
||||
* to pass a pointer to one of their instances. Each syscall exists in two
|
||||
|
|
@ -755,6 +745,56 @@ int pivot_root(const char *new, const char *old)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* ssize_t pread(int fd, void *buf, size_t count, off_t offset);
|
||||
* ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
|
||||
*/
|
||||
|
||||
#ifndef _sys_pread
|
||||
static __attribute__((unused))
|
||||
ssize_t _sys_pread(int fd, void *buf, size_t count, off_t offset)
|
||||
{
|
||||
#if __NOLIBC_BITS_PER_SYSCALL_ARG == 64
|
||||
return __nolibc_syscall4(__NR_pread64, fd, buf, count, offset);
|
||||
#elif defined(__NOLIBC_PAD_64BIT_SYSCALL_ARGUMENT_PAIR)
|
||||
return __nolibc_syscall6(__NR_pread64, fd, buf, count, 0,
|
||||
__NOLIBC_LLARGPART(offset, 0), __NOLIBC_LLARGPART(offset, 1));
|
||||
#else
|
||||
return __nolibc_syscall5(__NR_pread64, fd, buf, count,
|
||||
__NOLIBC_LLARGPART(offset, 0), __NOLIBC_LLARGPART(offset, 1));
|
||||
#endif
|
||||
}
|
||||
#endif /* _sys_pread */
|
||||
|
||||
static __attribute__((unused))
|
||||
ssize_t pread(int fd, void *buf, size_t count, off_t offset)
|
||||
{
|
||||
return __sysret(_sys_pread(fd, buf, count, offset));
|
||||
}
|
||||
|
||||
#ifndef _sys_pwrite
|
||||
static __attribute__((unused))
|
||||
ssize_t _sys_pwrite(int fd, const void *buf, size_t count, off_t offset)
|
||||
{
|
||||
#if __NOLIBC_BITS_PER_SYSCALL_ARG == 64
|
||||
return __nolibc_syscall4(__NR_pwrite64, fd, buf, count, offset);
|
||||
#elif defined(__NOLIBC_PAD_64BIT_SYSCALL_ARGUMENT_PAIR)
|
||||
return __nolibc_syscall6(__NR_pwrite64, fd, buf, count, 0,
|
||||
__NOLIBC_LLARGPART(offset, 0), __NOLIBC_LLARGPART(offset, 1));
|
||||
#else
|
||||
return __nolibc_syscall5(__NR_pwrite64, fd, buf, count,
|
||||
__NOLIBC_LLARGPART(offset, 0), __NOLIBC_LLARGPART(offset, 1));
|
||||
#endif
|
||||
}
|
||||
#endif /* _sys_pwrite */
|
||||
|
||||
static __attribute__((unused))
|
||||
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
|
||||
{
|
||||
return __sysret(_sys_pwrite(fd, buf, count, offset));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ssize_t read(int fd, void *buf, size_t count);
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ typedef struct {
|
|||
int __fd = (fd); \
|
||||
if (__fd >= 0) \
|
||||
__set->fds[__fd / FD_SETIDXMASK] &= \
|
||||
~(1U << (__fd & FD_SETBITMASK)); \
|
||||
~(1UL << (__fd & FD_SETBITMASK)); \
|
||||
} while (0)
|
||||
|
||||
#define FD_SET(fd, set) do { \
|
||||
|
|
@ -34,7 +34,7 @@ typedef struct {
|
|||
int __fd = (fd); \
|
||||
if (__fd >= 0) \
|
||||
__set->fds[__fd / FD_SETIDXMASK] |= \
|
||||
1 << (__fd & FD_SETBITMASK); \
|
||||
1UL << (__fd & FD_SETBITMASK); \
|
||||
} while (0)
|
||||
|
||||
#define FD_ISSET(fd, set) ({ \
|
||||
|
|
@ -43,7 +43,7 @@ typedef struct {
|
|||
int __r = 0; \
|
||||
if (__fd >= 0) \
|
||||
__r = !!(__set->fds[__fd / FD_SETIDXMASK] & \
|
||||
1U << (__fd & FD_SETBITMASK)); \
|
||||
1UL << (__fd & FD_SETBITMASK)); \
|
||||
__r; \
|
||||
})
|
||||
|
||||
|
|
|
|||
41
tools/include/nolibc/sys/sendfile.h
Normal file
41
tools/include/nolibc/sys/sendfile.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* sendfile for NOLIBC
|
||||
* Copyright (C) 2026 Daniel Palmer <daniel@thingy.jp>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_SENDFILE_H
|
||||
#define _NOLIBC_SYS_SENDFILE_H
|
||||
|
||||
#include "../sys.h"
|
||||
#include <linux/unistd.h>
|
||||
|
||||
/*
|
||||
* ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
ssize_t _sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
|
||||
{
|
||||
__nolibc_static_assert(sizeof(*offset) == sizeof(__kernel_loff_t));
|
||||
|
||||
#ifdef __NR_sendfile64
|
||||
/* 32-bit applications use sendfile64 so offset is treated as a __kernel_loff_t */
|
||||
return __nolibc_syscall4(__NR_sendfile64, out_fd, in_fd, offset, count);
|
||||
#else
|
||||
__nolibc_static_assert(sizeof(*offset) == sizeof(__kernel_off_t));
|
||||
|
||||
return __nolibc_syscall4(__NR_sendfile, out_fd, in_fd, offset, count);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
|
||||
{
|
||||
return __sysret(_sys_sendfile(out_fd, in_fd, offset, count));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_SENDFILE_H */
|
||||
|
|
@ -119,7 +119,7 @@ struct timeval {
|
|||
#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
|
||||
#define WIFEXITED(status) (((status) & 0x7f) == 0)
|
||||
#define WTERMSIG(status) ((status) & 0x7f)
|
||||
#define WIFSIGNALED(status) ((status) - 1 < 0xff)
|
||||
#define WIFSIGNALED(status) ((status) - 1U < 0xff)
|
||||
|
||||
/* standard exit() codes */
|
||||
#define EXIT_SUCCESS 0
|
||||
|
|
|
|||
|
|
@ -52,7 +52,11 @@ int access(const char *path, int amode)
|
|||
static __attribute__((unused))
|
||||
int _sys_ftruncate64(int fd, uint32_t length0, uint32_t length1)
|
||||
{
|
||||
#if defined(__NOLIBC_PAD_64BIT_SYSCALL_ARGUMENT_PAIR)
|
||||
return __nolibc_syscall4(__NR_ftruncate64, fd, 0, length0, length1);
|
||||
#else
|
||||
return __nolibc_syscall3(__NR_ftruncate64, fd, length0, length1);
|
||||
#endif
|
||||
}
|
||||
#define _sys_ftruncate64 _sys_ftruncate64
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ cc-option = $(call __cc-option, $(CC),,$(1),$(2))
|
|||
include Makefile.include
|
||||
|
||||
$(OUTPUT)/nolibc-test: CFLAGS = -nostdlib -nostdinc -static \
|
||||
-isystem $(top_srcdir)/tools/include/nolibc -isystem $(top_srcdir)/usr/include \
|
||||
-isystem $(top_srcdir)/tools/include/nolibc $(KHDR_INCLUDES) \
|
||||
$(CFLAGS_NOLIBC_TEST)
|
||||
$(OUTPUT)/nolibc-test: LDLIBS = $(if $(LLVM),,-lgcc)
|
||||
$(OUTPUT)/nolibc-test: $(NOLIBC_TEST_SOURCES) | headers
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ _CFLAGS_SANITIZER ?= $(call cc-option,-fsanitize=undefined -fsanitize-trap=all)
|
|||
CFLAGS_NOLIBC_TEST ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 -ggdb \
|
||||
-W -Wall -Wextra -Wundef -Wwrite-strings \
|
||||
$(call cc-option,-fno-stack-protector) $(call cc-option,-Wmissing-prototypes) \
|
||||
$(call cc-option,--start-no-unused-arguments) -no-pie $(call cc-option,--end-no-unused-arguments) \
|
||||
$(_CFLAGS_STACKPROTECTOR) $(_CFLAGS_SANITIZER)
|
||||
|
||||
NOLIBC_TEST_SOURCES := nolibc-test.c nolibc-test-linkage.c nolibc-test-ignore-errno.c
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ ARCH_sparc32 = sparc
|
|||
ARCH_sparc64 = sparc
|
||||
ARCH_sh4 = sh
|
||||
ARCH_parisc32 = parisc
|
||||
ARCH_parisc64 = parisc64
|
||||
ARCH := $(or $(ARCH_$(XARCH)),$(XARCH))
|
||||
|
||||
# kernel image names by architecture
|
||||
|
|
@ -113,6 +114,7 @@ EXTRACONFIG_sparc32 = -e CONFIG_TMPFS
|
|||
EXTRACONFIG_m68k = -e CONFIG_BLK_DEV_INITRD
|
||||
EXTRACONFIG_sh4 = -e CONFIG_BLK_DEV_INITRD -e CONFIG_CMDLINE_FROM_BOOTLOADER
|
||||
EXTRACONFIG_alpha = -e CONFIG_BLK_DEV_INITRD
|
||||
EXTRACONFIG_parisc64 = -d CONFIG_COMPAT
|
||||
EXTRACONFIG = $(EXTRACONFIG_$(XARCH))
|
||||
|
||||
# optional tests to run (default = all)
|
||||
|
|
@ -134,6 +136,7 @@ QEMU_ARCH_loongarch = loongarch64
|
|||
QEMU_ARCH_sparc32 = sparc
|
||||
QEMU_ARCH_openrisc = or1k
|
||||
QEMU_ARCH_parisc32 = hppa
|
||||
QEMU_ARCH_parisc64 = hppa
|
||||
QEMU_ARCH = $(or $(QEMU_ARCH_$(XARCH)),$(XARCH))
|
||||
|
||||
QEMU_ARCH_USER_ppc64le = ppc64le
|
||||
|
|
@ -175,6 +178,7 @@ QEMU_ARGS_m68k = -M virt -append "console=ttyGF0,115200 panic=-1 $(TEST:%=
|
|||
QEMU_ARGS_sh4 = -M r2d -serial file:/dev/stdout -append "console=ttySC1,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_openrisc = -M virt -m 512M -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_parisc32 = -M B160L -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_parisc64 = -M C3700 -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_alpha = -M clipper -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS = -m 1G $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_BIOS) $(QEMU_ARGS_EXTRA)
|
||||
|
||||
|
|
@ -193,6 +197,7 @@ CFLAGS_x32 = -mx32
|
|||
CFLAGS_arm = -marm
|
||||
CFLAGS_armthumb = -mthumb -march=armv6t2
|
||||
CFLAGS_parisc32 = -mfast-indirect-calls
|
||||
CFLAGS_parisc64 = -Wl,--no-dynamic-linker -Wl,--entry=_start -O2
|
||||
CFLAGS_ppc = -m32 -mbig-endian -mno-vsx $(call cc-option,-mmultiple)
|
||||
CFLAGS_ppc64 = -m64 -mbig-endian -mno-vsx $(call cc-option,-mmultiple)
|
||||
CFLAGS_ppc64le = -m64 -mlittle-endian -mno-vsx $(call cc-option,-mabi=elfv2)
|
||||
|
|
@ -206,6 +211,8 @@ CFLAGS_mips64be = -EB -mabi=64 -march=mips64r2
|
|||
CFLAGS_loongarch = $(if $(LLVM),-fuse-ld=lld)
|
||||
CFLAGS_sparc32 = $(call cc-option,-m32) -mcpu=v8
|
||||
CFLAGS_sh4 = -ml -m4
|
||||
# github.com/llvm/llvm-project/issues/216765
|
||||
CFLAGS_hexagon = -fno-sanitize=undefined
|
||||
ifeq ($(origin XARCH),command line)
|
||||
CFLAGS_XARCH = $(CFLAGS_$(XARCH))
|
||||
endif
|
||||
|
|
@ -222,10 +229,16 @@ LDFLAGS :=
|
|||
# Modify CFLAGS based on LLVM=
|
||||
include $(srctree)/tools/scripts/Makefile.include
|
||||
|
||||
ifeq ($(ARCH),hexagon)
|
||||
# tools/scripts/Makefile.include requires CROSS_COMPILE which does not exist for hexagon
|
||||
CFLAGS += --target=hexagon-linux-musl
|
||||
CLANG_CROSS_FLAGS += --target=hexagon-linux-musl
|
||||
endif
|
||||
|
||||
REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{if (!f) printf("\n"); f++; print;} /\[SKIPPED\][\r]*$$/{s++} \
|
||||
/^Total number of errors:/{done++} \
|
||||
END{ printf("\n%3d test(s): %3d passed, %3d skipped, %3d failed => status: ", p+s+f, p, s, f); \
|
||||
if (f || !p || !done) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \
|
||||
if (f || !p || !done) printf("failure\n"); else printf("success\n");; \
|
||||
printf("\nSee all results in %s\n", ARGV[1]); }'
|
||||
|
||||
# Execute the toplevel kernel Makefile
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <sys/random.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/sendfile.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
|
@ -1368,6 +1369,51 @@ int test_pipe(void)
|
|||
return !!memcmp(buf, msg, len);
|
||||
}
|
||||
|
||||
int test_pwrite_pread(void)
|
||||
{
|
||||
const off_t offset = (0x12ULL << 32) | 0x34;
|
||||
ssize_t ret;
|
||||
char buf[2];
|
||||
int fd, err;
|
||||
off_t offs;
|
||||
|
||||
fd = open("/tmp", O_TMPFILE | O_RDWR, 0644);
|
||||
if (fd == -1)
|
||||
return __LINE__;
|
||||
|
||||
/* Write into the middle of the file. */
|
||||
ret = pwrite(fd, "abc", 3, offset);
|
||||
if (ret != 3) {
|
||||
err = __LINE__;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Make sure the file offset points somewhere else before pread(). */
|
||||
offs = lseek(fd, 0, SEEK_END);
|
||||
if (offs != offset + 3) {
|
||||
err = __LINE__;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = pread(fd, buf, 2, offset + 1);
|
||||
if (ret != 2) {
|
||||
err = __LINE__;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (buf[0] != 'b' || buf[1] != 'c') {
|
||||
err = __LINE__;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
close(fd);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int test_rlimit(void)
|
||||
{
|
||||
struct rlimit rlim = {
|
||||
|
|
@ -1524,12 +1570,6 @@ int test_large_file(void)
|
|||
ssize_t written;
|
||||
off_t off;
|
||||
|
||||
#if defined(__mips__) && defined(_ABIN32)
|
||||
/* https://lore.kernel.org/qemu-devel/fed03914-a95a-4522-a432-f129264cb2ac@t-8ch.de/ */
|
||||
if (getpid() != 1)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (large_seek < UINT32_MAX) {
|
||||
errno = EOVERFLOW;
|
||||
return -1;
|
||||
|
|
@ -1563,6 +1603,72 @@ int test_large_file(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int test_sendfile(void)
|
||||
{
|
||||
char data_in[] = "This is some data";
|
||||
const size_t data_sz = sizeof(data_in);
|
||||
char data_out[data_sz + 10];
|
||||
int in_fd, out_fd;
|
||||
int ret;
|
||||
|
||||
/* Create two tmp files */
|
||||
in_fd = open("/tmp", O_TMPFILE | O_RDWR, 0644);
|
||||
out_fd = open("/tmp", O_TMPFILE | O_RDWR, 0644);
|
||||
|
||||
if (in_fd == -1 || out_fd == -1) {
|
||||
ret = __LINE__;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Populate the "in" file */
|
||||
ret = write(in_fd, data_in, data_sz);
|
||||
if (ret != data_sz) {
|
||||
ret = __LINE__;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Rewind the "in" file */
|
||||
if (lseek(in_fd, 0, SEEK_SET)) {
|
||||
ret = __LINE__;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Use sendfile() to copy "in" to "out" */
|
||||
ret = sendfile(out_fd, in_fd, NULL, data_sz + 5);
|
||||
if (ret != data_sz) {
|
||||
ret = __LINE__;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Rewind the "out" file */
|
||||
if (lseek(out_fd, 0, SEEK_SET)) {
|
||||
ret = __LINE__;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Read back the transferred data */
|
||||
ret = read(out_fd, data_out, sizeof(data_out));
|
||||
if (ret != data_sz) {
|
||||
ret = __LINE__;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check we have the same data in both files */
|
||||
if (memcmp(data_out, data_in, data_sz)) {
|
||||
ret = __LINE__;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Test passed */
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
close(out_fd);
|
||||
close(in_fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Run syscall tests between IDs <min> and <max>.
|
||||
* Return 0 on success, non-zero on failure.
|
||||
*/
|
||||
|
|
@ -1584,6 +1690,7 @@ int run_syscall(int min, int max)
|
|||
void *p1, *p2;
|
||||
int has_gettid = 1;
|
||||
int has_brk;
|
||||
int has_working_64bit_syscall_arg = 1;
|
||||
|
||||
/* <proc> indicates whether or not /proc is mounted */
|
||||
proc = stat("/proc", &stat_buf) == 0;
|
||||
|
|
@ -1599,6 +1706,11 @@ int run_syscall(int min, int max)
|
|||
/* on musl setting brk()/sbrk() always fails */
|
||||
has_brk = brk(0) == 0;
|
||||
|
||||
#if defined(__mips__) && defined(_ABIN32)
|
||||
/* https://lore.kernel.org/qemu-devel/fed03914-a95a-4522-a432-f129264cb2ac@t-8ch.de/ */
|
||||
has_working_64bit_syscall_arg = getpid() == 1;
|
||||
#endif
|
||||
|
||||
for (test = min; test >= 0 && test <= max; test++) {
|
||||
int llen = 0; /* line length */
|
||||
|
||||
|
|
@ -1644,6 +1756,7 @@ int run_syscall(int min, int max)
|
|||
CASE_TEST(execve_root); EXPECT_SYSER(1, execve("/", (char*[]){ [0] = (char []){"/"}, [1] = NULL }, NULL), -1, EACCES); break;
|
||||
CASE_TEST(fchdir_stdin); EXPECT_SYSER(1, fchdir(STDIN_FILENO), -1, ENOTDIR); break;
|
||||
CASE_TEST(fchdir_badfd); EXPECT_SYSER(1, fchdir(-1), -1, EBADF); break;
|
||||
CASE_TEST(fdopendir_notdir); EXPECT_SYSER(1, (uintptr_t)fdopendir(STDIN_FILENO), (uintptr_t)NULL, ENOTDIR); break;
|
||||
CASE_TEST(file_stream); EXPECT_SYSZR(1, test_file_stream()); break;
|
||||
CASE_TEST(file_stream_wsr); EXPECT_SYSZR(1, test_file_stream_wsr()); break;
|
||||
CASE_TEST(fork); EXPECT_SYSZR(1, test_fork(FORK_STANDARD)); break;
|
||||
|
|
@ -1672,11 +1785,13 @@ int run_syscall(int min, int max)
|
|||
CASE_TEST(open_blah); EXPECT_SYSER(1, tmp = open("/proc/self/blah", O_RDONLY), -1, ENOENT); if (tmp != -1) close(tmp); break;
|
||||
CASE_TEST(openat_dir); EXPECT_SYSZR(1, test_openat()); break;
|
||||
CASE_TEST(open_mode); EXPECT_SYSZR(1, test_open_mode()); break;
|
||||
CASE_TEST(opendir_notdir); EXPECT_SYSER(1, (uintptr_t)opendir("/dev/null"), (uintptr_t)NULL, ENOTDIR); break;
|
||||
CASE_TEST(pipe); EXPECT_SYSZR(1, test_pipe()); break;
|
||||
CASE_TEST(poll_null); EXPECT_SYSZR(1, poll(NULL, 0, 0)); break;
|
||||
CASE_TEST(poll_stdout); EXPECT_SYSNE(1, ({ struct pollfd fds = { 1, POLLOUT, 0}; poll(&fds, 1, 0); }), -1); break;
|
||||
CASE_TEST(poll_fault); EXPECT_SYSER(1, poll(NULL, 1, 0), -1, EFAULT); break;
|
||||
CASE_TEST(prctl); EXPECT_SYSER(1, prctl(PR_SET_NAME, (unsigned long)NULL, 0, 0, 0), -1, EFAULT); break;
|
||||
CASE_TEST(pwrite_pread); EXPECT_SYSZR(has_working_64bit_syscall_arg, test_pwrite_pread()); break;
|
||||
CASE_TEST(read_badf); EXPECT_SYSER(1, read(-1, &tmp, 1), -1, EBADF); break;
|
||||
CASE_TEST(rlimit); EXPECT_SYSZR(1, test_rlimit()); break;
|
||||
CASE_TEST(rmdir_blah); EXPECT_SYSER(1, rmdir("/blah"), -1, ENOENT); break;
|
||||
|
|
@ -1684,6 +1799,7 @@ int run_syscall(int min, int max)
|
|||
CASE_TEST(select_null); EXPECT_SYSZR(1, ({ struct timeval tv = { 0 }; select(0, NULL, NULL, NULL, &tv); })); break;
|
||||
CASE_TEST(select_stdout); EXPECT_SYSNE(1, ({ fd_set fds; FD_ZERO(&fds); FD_SET(1, &fds); select(2, NULL, &fds, NULL, NULL); }), -1); break;
|
||||
CASE_TEST(select_fault); EXPECT_SYSER(1, select(1, (void *)1, NULL, NULL, 0), -1, EFAULT); break;
|
||||
CASE_TEST(sendfile); EXPECT_SYSZR(1, test_sendfile()); break;
|
||||
CASE_TEST(stat_blah); EXPECT_SYSER(1, stat("/proc/self/blah", &stat_buf), -1, ENOENT); break;
|
||||
CASE_TEST(stat_fault); EXPECT_SYSER(1, stat(NULL, &stat_buf), -1, EFAULT); break;
|
||||
CASE_TEST(stat_rdev); EXPECT_SYSZR(1, ({ int ret = stat("/dev/null", &stat_buf); ret ?: stat_buf.st_rdev != makedev(1, 3); })); break;
|
||||
|
|
@ -1711,7 +1827,7 @@ int run_syscall(int min, int max)
|
|||
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_TEST(largefile); EXPECT_SYSZR(1, test_large_file()); break;
|
||||
CASE_TEST(largefile); EXPECT_SYSZR(has_working_64bit_syscall_arg, test_large_file()); break;
|
||||
case __LINE__:
|
||||
return ret; /* must be last */
|
||||
/* note: do not set any defaults so as to permit holes above */
|
||||
|
|
@ -1771,6 +1887,26 @@ int test_time_types(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int test_fd_set(void)
|
||||
{
|
||||
fd_set set, clr;
|
||||
int fd, i;
|
||||
|
||||
/* FD_SET() and FD_CLR() must change exactly one fd */
|
||||
for (fd = 0; fd < FD_SETSIZE; fd++) {
|
||||
FD_ZERO(&set);
|
||||
FD_SET(fd, &set);
|
||||
memset(&clr, 0xff, sizeof(clr));
|
||||
FD_CLR(fd, &clr);
|
||||
for (i = 0; i < FD_SETSIZE; i++)
|
||||
if (!!FD_ISSET(i, &set) != (i == fd) ||
|
||||
!!FD_ISSET(i, &clr) != (i != fd))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_malloc(void)
|
||||
{
|
||||
size_t sz_array1, sz_array2, sz_array3;
|
||||
|
|
@ -1952,6 +2088,7 @@ int run_stdlib(int min, int max)
|
|||
CASE_TEST(memchr_foobar6_o); EXPECT_STREQ(1, memchr("foobar", 'o', 6), "oobar"); break;
|
||||
CASE_TEST(memchr_foobar3_b); EXPECT_STRZR(1, memchr("foobar", 'b', 3)); break;
|
||||
CASE_TEST(time_types); EXPECT_ZR(is_nolibc, test_time_types()); break;
|
||||
CASE_TEST(fd_set); EXPECT_ZR(1, test_fd_set()); break;
|
||||
CASE_TEST(makedev); EXPECT_EQ(1, makedev(0x12, 0x34), 0x1234); break;
|
||||
CASE_TEST(major); EXPECT_EQ(1, major(0x1234), 0x12); break;
|
||||
CASE_TEST(minor); EXPECT_EQ(1, minor(0x1234), 0x34); break;
|
||||
|
|
@ -1968,6 +2105,14 @@ int run_stdlib(int min, int max)
|
|||
CASE_TEST(htole32); EXPECT_EQ(1, htole32(is_le ? 0x01234567 : 0x67452301), 0x01234567); break;
|
||||
CASE_TEST(htobe64); EXPECT_EQ(1, htobe64(is_le ? 0x0123456789000000 : 0x8967452301), 0x8967452301); break;
|
||||
CASE_TEST(htole64); EXPECT_EQ(1, htole64(is_le ? 0x0123456789 : 0x8967452301000000), 0x0123456789); break;
|
||||
CASE_TEST(wexitstatus); EXPECT_EQ(1, WEXITSTATUS(0x1200), 0x12); break;
|
||||
CASE_TEST(wifexited_exit0); EXPECT_EQ(1, WIFEXITED(0), 1); break;
|
||||
CASE_TEST(wifexited_signal); EXPECT_EQ(1, WIFEXITED(SIGKILL), 0); break;
|
||||
CASE_TEST(wifsignaled_exit0); EXPECT_EQ(1, WIFSIGNALED(0), 0); break;
|
||||
CASE_TEST(wifsignaled_exit); EXPECT_EQ(1, WIFSIGNALED(0x1200), 0); break;
|
||||
CASE_TEST(wifsignaled_signal); EXPECT_EQ(1, WIFSIGNALED(SIGKILL), 1); break;
|
||||
CASE_TEST(wifsignaled_stopped); EXPECT_EQ(1, WIFSIGNALED((SIGSTOP << 8) | 0x7f), 0); break;
|
||||
CASE_TEST(wtermsig_core); EXPECT_EQ(1, WTERMSIG(0x80 | SIGSEGV), SIGSEGV); break;
|
||||
|
||||
case __LINE__:
|
||||
return ret; /* must be last */
|
||||
|
|
|
|||
|
|
@ -29,8 +29,9 @@ all_archs=(
|
|||
sparc32 sparc64
|
||||
m68k
|
||||
sh4
|
||||
parisc32
|
||||
parisc32 parisc64
|
||||
alpha
|
||||
hexagon
|
||||
)
|
||||
archs="${all_archs[@]}"
|
||||
|
||||
|
|
@ -121,6 +122,7 @@ crosstool_arch() {
|
|||
sparc*) echo sparc64;;
|
||||
x32*) echo x86_64;;
|
||||
parisc32) echo hppa;;
|
||||
parisc64) echo hppa64;;
|
||||
*) echo "$1";;
|
||||
esac
|
||||
}
|
||||
|
|
@ -132,6 +134,13 @@ crosstool_abi() {
|
|||
esac
|
||||
}
|
||||
|
||||
need_gcc() {
|
||||
case "$1" in
|
||||
hexagon);;
|
||||
*) echo "1";;
|
||||
esac
|
||||
}
|
||||
|
||||
download_crosstool() {
|
||||
arch="$(crosstool_arch "$1")"
|
||||
abi="$(crosstool_abi "$1")"
|
||||
|
|
@ -164,14 +173,18 @@ test_arch() {
|
|||
arch=$1
|
||||
ct_arch=$(crosstool_arch "$arch")
|
||||
ct_abi=$(crosstool_abi "$1")
|
||||
gcc="$(need_gcc "$1")"
|
||||
cross_compile=
|
||||
|
||||
if [ ! -d "${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}/bin/." ]; then
|
||||
if [ -n "$gcc" ] && [ ! -d "${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}/bin/." ]; then
|
||||
echo "No toolchain found in ${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}."
|
||||
echo "Did you install the toolchains or set the correct arch ? Rerun with -h for help."
|
||||
return 1
|
||||
fi
|
||||
|
||||
cross_compile=$(realpath "${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}/bin/${ct_arch}-${ct_abi}-")
|
||||
if [ -n "$gcc" ]; then
|
||||
cross_compile=$(realpath "${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}/bin/${ct_arch}-${ct_abi}-")
|
||||
fi
|
||||
build_dir="${build_location}/${arch}"
|
||||
if [ "$werror" -ne 0 ]; then
|
||||
CFLAGS_EXTRA="$CFLAGS_EXTRA -Werror -Wl,--fatal-warnings"
|
||||
|
|
@ -194,11 +207,18 @@ test_arch() {
|
|||
exit 1
|
||||
esac
|
||||
printf '%-15s' "$arch:"
|
||||
if [ "$arch" = "m68k" -o "$arch" = "sh4" -o "$arch" = "openrisc" -o "$arch" = "parisc32" -o "$arch" = "alpha" ] && [ "$llvm" = "1" ]; then
|
||||
if [ "$llvm" = "1" ] && \
|
||||
[ "$arch" = "m68k" -o "$arch" = "sh4" -o "$arch" = "openrisc" \
|
||||
-o "$arch" == "parisc32" -o "$arch" == "parisc64" -o "$arch" = "alpha" \
|
||||
]; then
|
||||
echo "Unsupported configuration"
|
||||
return
|
||||
fi
|
||||
if [ "$arch" = "x32" ] && [ "$test_mode" = "user" ]; then
|
||||
if [ "$test_mode" = "user" ] && [ "$arch" = "x32" -o "$arch" = "parisc64" ]; then
|
||||
echo "Unsupported configuration"
|
||||
return
|
||||
fi
|
||||
if [ -z "$llvm" -o "$test_mode" = "system" ] && [ "$arch" = "hexagon" ]; then
|
||||
echo "Unsupported configuration"
|
||||
return
|
||||
fi
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user