summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-08-28 19:03:24 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2023-08-28 19:03:24 -0700
commit1c59d383390f970b891b503b7f79b63a02db2ec5 (patch)
treed8f965dd0deac6bcc28a4022b51b772129ebdad6
parent815c24a085dd8ab9bb7381e455afdb3f9c260e38 (diff)
parent556fb7131e03b0283672fb40f6dc2d151752aaa7 (diff)
downloadlinux-1c59d383390f970b891b503b7f79b63a02db2ec5.tar.gz
linux-1c59d383390f970b891b503b7f79b63a02db2ec5.tar.bz2
linux-1c59d383390f970b891b503b7f79b63a02db2ec5.zip
Merge tag 'linux-kselftest-nolibc-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull nolibc updates from Shuah Khan: "Nolibc: - improved portability by removing build errors with -ENOSYS - added syscall6() on MIPS to support pselect6() and mmap() - added setvbuf(), rmdir(), pipe(), pipe2() - add support for ppc/ppc64 - environ is no longer optional - fixed frame pointer issues at -O0 - dropped sys_stat() in favor of sys_statx() - centralized _start_c() to remove lots of asm code - switched size_t to __SIZE_TYPE__ Selftests: - improved status reporting (success/warning/failure counts, path to log file) - various code cleanups (indent, unused variables, ...) - more consistent test numbering - enabled compiler warnings - dropped unreliable chmod_net test - improved reliability (create /dev/zero & /tmp, rely less on /proc) - new tests (brk/sbrk/mmap/munmap) - improved compatibility with musl - new run-nolibc-test target to build and run natively - new run-libc-test target to build and run against native libc - made the cmdline parser more reliable against boolean arguments - dropped dependency on memfd for vfprintf() test - nolibc-test is no longer stripped - added support for extending ARCH via XARCH Other: - add Thomas as co-maintainer" * tag 'linux-kselftest-nolibc-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (103 commits) tools/nolibc: avoid undesired casts in the __sysret() macro tools/nolibc: keep brk(), sbrk(), mmap() away from __sysret() tools/nolibc: silence ppc64 compile warnings selftests/nolibc: libc-test: use HOSTCC instead of CC tools/nolibc: stackprotector.h: make __stack_chk_init static selftests/nolibc: allow report with existing test log selftests/nolibc: add test support for ppc64 selftests/nolibc: add test support for ppc64le selftests/nolibc: add test support for ppc selftests/nolibc: add XARCH and ARCH mapping support tools/nolibc: add support for powerpc64 tools/nolibc: add support for powerpc MAINTAINERS: nolibc: add myself as co-maintainer selftests/nolibc: enable compiler warnings selftests/nolibc: don't strip nolibc-test selftests/nolibc: prevent out of bounds access in expect_vfprintf selftests/nolibc: use correct return type for read() and write() selftests/nolibc: avoid sign-compare warnings selftests/nolibc: avoid unused parameter warnings selftests/nolibc: make functions static if possible ...
-rw-r--r--MAINTAINERS1
-rw-r--r--tools/include/nolibc/Makefile1
-rw-r--r--tools/include/nolibc/arch-aarch64.h85
-rw-r--r--tools/include/nolibc/arch-arm.h111
-rw-r--r--tools/include/nolibc/arch-i386.h86
-rw-r--r--tools/include/nolibc/arch-loongarch.h83
-rw-r--r--tools/include/nolibc/arch-mips.h147
-rw-r--r--tools/include/nolibc/arch-powerpc.h221
-rw-r--r--tools/include/nolibc/arch-riscv.h83
-rw-r--r--tools/include/nolibc/arch-s390.h77
-rw-r--r--tools/include/nolibc/arch-x86_64.h86
-rw-r--r--tools/include/nolibc/arch.h2
-rw-r--r--tools/include/nolibc/crt.h61
-rw-r--r--tools/include/nolibc/nolibc.h9
-rw-r--r--tools/include/nolibc/stackprotector.h5
-rw-r--r--tools/include/nolibc/stdint.h2
-rw-r--r--tools/include/nolibc/stdio.h27
-rw-r--r--tools/include/nolibc/stdlib.h12
-rw-r--r--tools/include/nolibc/sys.h534
-rw-r--r--tools/include/nolibc/types.h22
-rw-r--r--tools/include/nolibc/unistd.h13
-rw-r--r--tools/testing/selftests/nolibc/Makefile111
-rw-r--r--tools/testing/selftests/nolibc/nolibc-test.c608
23 files changed, 1221 insertions, 1166 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 7f6426284e73..4b8d634f3a4e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15010,6 +15010,7 @@ F: include/linux/power/bq27xxx_battery.h
NOLIBC HEADER FILE
M: Willy Tarreau <w@1wt.eu>
+M: Thomas Weißschuh <linux@weissschuh.net>
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/nolibc.git
F: tools/include/nolibc/
diff --git a/tools/include/nolibc/Makefile b/tools/include/nolibc/Makefile
index 64d67b080744..909b6eb500fe 100644
--- a/tools/include/nolibc/Makefile
+++ b/tools/include/nolibc/Makefile
@@ -27,6 +27,7 @@ nolibc_arch := $(patsubst arm64,aarch64,$(ARCH))
arch_file := arch-$(nolibc_arch).h
all_files := \
compiler.h \
+ crt.h \
ctype.h \
errno.h \
nolibc.h \
diff --git a/tools/include/nolibc/arch-aarch64.h b/tools/include/nolibc/arch-aarch64.h
index 11f294a406b7..6c33c46848e3 100644
--- a/tools/include/nolibc/arch-aarch64.h
+++ b/tools/include/nolibc/arch-aarch64.h
@@ -8,34 +8,7 @@
#define _NOLIBC_ARCH_AARCH64_H
#include "compiler.h"
-
-/* The struct returned by the newfstatat() syscall. Differs slightly from the
- * x86_64's stat one by field ordering, so be careful.
- */
-struct sys_stat_struct {
- unsigned long st_dev;
- unsigned long st_ino;
- unsigned int st_mode;
- unsigned int st_nlink;
- unsigned int st_uid;
- unsigned int st_gid;
-
- unsigned long st_rdev;
- unsigned long __pad1;
- long st_size;
- int st_blksize;
- int __pad2;
-
- long st_blocks;
- long st_atime;
- unsigned long st_atime_nsec;
- long st_mtime;
-
- unsigned long st_mtime_nsec;
- long st_ctime;
- unsigned long st_ctime_nsec;
- unsigned int __unused[2];
-};
+#include "crt.h"
/* Syscalls for AARCH64 :
* - registers are 64-bit
@@ -56,8 +29,8 @@ struct sys_stat_struct {
({ \
register long _num __asm__ ("x8") = (num); \
register long _arg1 __asm__ ("x0"); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
"svc #0\n" \
: "=r"(_arg1) \
: "r"(_num) \
@@ -70,8 +43,8 @@ struct sys_stat_struct {
({ \
register long _num __asm__ ("x8") = (num); \
register long _arg1 __asm__ ("x0") = (long)(arg1); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
"svc #0\n" \
: "=r"(_arg1) \
: "r"(_arg1), \
@@ -86,8 +59,8 @@ struct sys_stat_struct {
register long _num __asm__ ("x8") = (num); \
register long _arg1 __asm__ ("x0") = (long)(arg1); \
register long _arg2 __asm__ ("x1") = (long)(arg2); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
"svc #0\n" \
: "=r"(_arg1) \
: "r"(_arg1), "r"(_arg2), \
@@ -103,8 +76,8 @@ struct sys_stat_struct {
register long _arg1 __asm__ ("x0") = (long)(arg1); \
register long _arg2 __asm__ ("x1") = (long)(arg2); \
register long _arg3 __asm__ ("x2") = (long)(arg3); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
"svc #0\n" \
: "=r"(_arg1) \
: "r"(_arg1), "r"(_arg2), "r"(_arg3), \
@@ -121,8 +94,8 @@ struct sys_stat_struct {
register long _arg2 __asm__ ("x1") = (long)(arg2); \
register long _arg3 __asm__ ("x2") = (long)(arg3); \
register long _arg4 __asm__ ("x3") = (long)(arg4); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
"svc #0\n" \
: "=r"(_arg1) \
: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
@@ -140,8 +113,8 @@ struct sys_stat_struct {
register long _arg3 __asm__ ("x2") = (long)(arg3); \
register long _arg4 __asm__ ("x3") = (long)(arg4); \
register long _arg5 __asm__ ("x4") = (long)(arg5); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
"svc #0\n" \
: "=r" (_arg1) \
: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
@@ -160,8 +133,8 @@ struct sys_stat_struct {
register long _arg4 __asm__ ("x3") = (long)(arg4); \
register long _arg5 __asm__ ("x4") = (long)(arg5); \
register long _arg6 __asm__ ("x5") = (long)(arg6); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
"svc #0\n" \
: "=r" (_arg1) \
: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
@@ -171,33 +144,13 @@ struct sys_stat_struct {
_arg1; \
})
-char **environ __attribute__((weak));
-const unsigned long *_auxv __attribute__((weak));
-
/* startup code */
-void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) __no_stack_protector _start(void)
+void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
{
__asm__ volatile (
-#ifdef _NOLIBC_STACKPROTECTOR
- "bl __stack_chk_init\n" /* initialize stack protector */
-#endif
- "ldr x0, [sp]\n" /* argc (x0) was in the stack */
- "add x1, sp, 8\n" /* argv (x1) = sp */
- "lsl x2, x0, 3\n" /* envp (x2) = 8*argc ... */
- "add x2, x2, 8\n" /* + 8 (skip null) */
- "add x2, x2, x1\n" /* + argv */
- "adrp x3, environ\n" /* x3 = &environ (high bits) */
- "str x2, [x3, #:lo12:environ]\n" /* store envp into environ */
- "mov x4, x2\n" /* search for auxv (follows NULL after last env) */
- "0:\n"
- "ldr x5, [x4], 8\n" /* x5 = *x4; x4 += 8 */
- "cbnz x5, 0b\n" /* and stop at NULL after last env */
- "adrp x3, _auxv\n" /* x3 = &_auxv (high bits) */
- "str x4, [x3, #:lo12:_auxv]\n" /* store x4 into _auxv */
- "and sp, x1, -16\n" /* sp must be 16-byte aligned in the callee */
- "bl main\n" /* main() returns the status code, we'll exit with it. */
- "mov x8, 93\n" /* NR_exit == 93 */
- "svc #0\n"
+ "mov x0, sp\n" /* save stack pointer to x0, as arg1 of _start_c */
+ "and sp, x0, -16\n" /* sp must be 16-byte aligned in the callee */
+ "bl _start_c\n" /* transfer to c runtime */
);
__builtin_unreachable();
}
diff --git a/tools/include/nolibc/arch-arm.h b/tools/include/nolibc/arch-arm.h
index ca4c66987497..cae4afa7c1c7 100644
--- a/tools/include/nolibc/arch-arm.h
+++ b/tools/include/nolibc/arch-arm.h
@@ -8,43 +8,7 @@
#define _NOLIBC_ARCH_ARM_H
#include "compiler.h"
-
-/* The struct returned by the stat() syscall, 32-bit only, the syscall returns
- * exactly 56 bytes (stops before the unused array). In big endian, the format
- * differs as devices are returned as short only.
- */
-struct sys_stat_struct {
-#if defined(__ARMEB__)
- unsigned short st_dev;
- unsigned short __pad1;
-#else
- unsigned long st_dev;
-#endif
- unsigned long st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
-
-#if defined(__ARMEB__)
- unsigned short st_rdev;
- unsigned short __pad2;
-#else
- unsigned long st_rdev;
-#endif
- unsigned long st_size;
- unsigned long st_blksize;
- unsigned long st_blocks;
-
- unsigned long st_atime;
- unsigned long st_atime_nsec;
- unsigned long st_mtime;
- unsigned long st_mtime_nsec;
-
- unsigned long st_ctime;
- unsigned long st_ctime_nsec;
- unsigned long __unused[2];
-};
+#include "crt.h"
/* Syscalls for ARM in ARM or Thumb modes :
* - registers are 32-bit
@@ -90,8 +54,8 @@ struct sys_stat_struct {
({ \
register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \
register long _arg1 __asm__ ("r0"); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
_NOLIBC_THUMB_SET_R7 \
"svc #0\n" \
_NOLIBC_THUMB_RESTORE_R7 \
@@ -107,8 +71,8 @@ struct sys_stat_struct {
({ \
register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \
register long _arg1 __asm__ ("r0") = (long)(arg1); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
_NOLIBC_THUMB_SET_R7 \
"svc #0\n" \
_NOLIBC_THUMB_RESTORE_R7 \
@@ -125,8 +89,8 @@ struct sys_stat_struct {
register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \
register long _arg1 __asm__ ("r0") = (long)(arg1); \
register long _arg2 __asm__ ("r1") = (long)(arg2); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
_NOLIBC_THUMB_SET_R7 \
"svc #0\n" \
_NOLIBC_THUMB_RESTORE_R7 \
@@ -144,8 +108,8 @@ struct sys_stat_struct {
register long _arg1 __asm__ ("r0") = (long)(arg1); \
register long _arg2 __asm__ ("r1") = (long)(arg2); \
register long _arg3 __asm__ ("r2") = (long)(arg3); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
_NOLIBC_THUMB_SET_R7 \
"svc #0\n" \
_NOLIBC_THUMB_RESTORE_R7 \
@@ -164,8 +128,8 @@ struct sys_stat_struct {
register long _arg2 __asm__ ("r1") = (long)(arg2); \
register long _arg3 __asm__ ("r2") = (long)(arg3); \
register long _arg4 __asm__ ("r3") = (long)(arg4); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
_NOLIBC_THUMB_SET_R7 \
"svc #0\n" \
_NOLIBC_THUMB_RESTORE_R7 \
@@ -185,8 +149,8 @@ struct sys_stat_struct {
register long _arg3 __asm__ ("r2") = (long)(arg3); \
register long _arg4 __asm__ ("r3") = (long)(arg4); \
register long _arg5 __asm__ ("r4") = (long)(arg5); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
_NOLIBC_THUMB_SET_R7 \
"svc #0\n" \
_NOLIBC_THUMB_RESTORE_R7 \
@@ -207,8 +171,8 @@ struct sys_stat_struct {
register long _arg4 __asm__ ("r3") = (long)(arg4); \
register long _arg5 __asm__ ("r4") = (long)(arg5); \
register long _arg6 __asm__ ("r5") = (long)(arg6); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
_NOLIBC_THUMB_SET_R7 \
"svc #0\n" \
_NOLIBC_THUMB_RESTORE_R7 \
@@ -220,49 +184,14 @@ struct sys_stat_struct {
_arg1; \
})
-
-char **environ __attribute__((weak));
-const unsigned long *_auxv __attribute__((weak));
-
/* startup code */
-void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) __no_stack_protector _start(void)
+void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
{
__asm__ volatile (
-#ifdef _NOLIBC_STACKPROTECTOR
- "bl __stack_chk_init\n" /* initialize stack protector */
-#endif
- "pop {%r0}\n" /* argc was in the stack */
- "mov %r1, %sp\n" /* argv = sp */
-
- "add %r2, %r0, $1\n" /* envp = (argc + 1) ... */
- "lsl %r2, %r2, $2\n" /* * 4 ... */
- "add %r2, %r2, %r1\n" /* + argv */
- "ldr %r3, 1f\n" /* r3 = &environ (see below) */
- "str %r2, [r3]\n" /* store envp into environ */
-
- "mov r4, r2\n" /* search for auxv (follows NULL after last env) */
- "0:\n"
- "mov r5, r4\n" /* r5 = r4 */
- "add r4, r4, #4\n" /* r4 += 4 */
- "ldr r5,[r5]\n" /* r5 = *r5 = *(r4-4) */
- "cmp r5, #0\n" /* and stop at NULL after last env */
- "bne 0b\n"
- "ldr %r3, 2f\n" /* r3 = &_auxv (low bits) */
- "str r4, [r3]\n" /* store r4 into _auxv */
-
- "mov %r3, $8\n" /* AAPCS : sp must be 8-byte aligned in the */
- "neg %r3, %r3\n" /* callee, and bl doesn't push (lr=pc) */
- "and %r3, %r3, %r1\n" /* so we do sp = r1(=sp) & r3(=-8); */
- "mov %sp, %r3\n"
-
- "bl main\n" /* main() returns the status code, we'll exit with it. */
- "movs r7, $1\n" /* NR_exit == 1 */
- "svc $0x00\n"
- ".align 2\n" /* below are the pointers to a few variables */
- "1:\n"
- ".word environ\n"
- "2:\n"
- ".word _auxv\n"
+ "mov %r0, sp\n" /* save stack pointer to %r0, as arg1 of _start_c */
+ "and ip, %r0, #-8\n" /* sp must be 8-byte aligned in the callee */
+ "mov sp, ip\n"
+ "bl _start_c\n" /* transfer to c runtime */
);
__builtin_unreachable();
}
diff --git a/tools/include/nolibc/arch-i386.h b/tools/include/nolibc/arch-i386.h
index 3d672d925e9e..64415b9fac77 100644
--- a/tools/include/nolibc/arch-i386.h
+++ b/tools/include/nolibc/arch-i386.h
@@ -8,32 +8,7 @@
#define _NOLIBC_ARCH_I386_H
#include "compiler.h"
-
-/* The struct returned by the stat() syscall, 32-bit only, the syscall returns
- * exactly 56 bytes (stops before the unused array).
- */
-struct sys_stat_struct {
- unsigned long st_dev;
- unsigned long st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
-
- unsigned long st_rdev;
- unsigned long st_size;
- unsigned long st_blksize;
- unsigned long st_blocks;
-
- unsigned long st_atime;
- unsigned long st_atime_nsec;
- unsigned long st_mtime;
- unsigned long st_mtime_nsec;
-
- unsigned long st_ctime;
- unsigned long st_ctime_nsec;
- unsigned long __unused[2];
-};
+#include "crt.h"
/* Syscalls for i386 :
* - mostly similar to x86_64
@@ -57,8 +32,8 @@ struct sys_stat_struct {
({ \
long _ret; \
register long _num __asm__ ("eax") = (num); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
"int $0x80\n" \
: "=a" (_ret) \
: "0"(_num) \
@@ -72,8 +47,8 @@ struct sys_stat_struct {
long _ret; \
register long _num __asm__ ("eax") = (num); \
register long _arg1 __asm__ ("ebx") = (long)(arg1); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
"int $0x80\n" \
: "=a" (_ret) \
: "r"(_arg1), \
@@ -89,8 +64,8 @@ struct sys_stat_struct {
register long _num __asm__ ("eax") = (num); \
register long _arg1 __asm__ ("ebx") = (long)(arg1); \
register long _arg2 __asm__ ("ecx") = (long)(arg2); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
"int $0x80\n" \
: "=a" (_ret) \
: "r"(_arg1), "r"(_arg2), \
@@ -107,8 +82,8 @@ struct sys_stat_struct {
register long _arg1 __asm__ ("ebx") = (long)(arg1); \
register long _arg2 __asm__ ("ecx") = (long)(arg2); \
register long _arg3 __asm__ ("edx") = (long)(arg3); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
"int $0x80\n" \
: "=a" (_ret) \
: "r"(_arg1), "r"(_arg2), "r"(_arg3), \
@@ -126,8 +101,8 @@ struct sys_stat_struct {
register long _arg2 __asm__ ("ecx") = (long)(arg2); \
register long _arg3 __asm__ ("edx") = (long)(arg3); \
register long _arg4 __asm__ ("esi") = (long)(arg4); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
"int $0x80\n" \
: "=a" (_ret) \
: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
@@ -146,8 +121,8 @@ struct sys_stat_struct {
register long _arg3 __asm__ ("edx") = (long)(arg3); \
register long _arg4 __asm__ ("esi") = (long)(arg4); \
register long _arg5 __asm__ ("edi") = (long)(arg5); \
- \
- __asm__ volatile ( \
+ \
+ __asm__ volatile ( \
"int $0x80\n" \
: "=a" (_ret) \
: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
@@ -180,9 +155,6 @@ struct sys_stat_struct {
_eax; \
})
-char **environ __attribute__((weak));
-const unsigned long *_auxv __attribute__((weak));
-
/* startup code */
/*
* i386 System V ABI mandates:
@@ -190,33 +162,15 @@ const unsigned long *_auxv __attribute__((weak));
* 2) The deepest stack frame should be set to zero
*
*/
-void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) __no_stack_protector _start(void)
+void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
{
__asm__ volatile (
-#ifdef _NOLIBC_STACKPROTECTOR
- "call __stack_chk_init\n" /* initialize stack protector */
-#endif
- "pop %eax\n" /* argc (first arg, %eax) */
- "mov %esp, %ebx\n" /* argv[] (second arg, %ebx) */
- "lea 4(%ebx,%eax,4),%ecx\n" /* then a NULL then envp (third arg, %ecx) */
- "mov %ecx, environ\n" /* save environ */
- "xor %ebp, %ebp\n" /* zero the stack frame */
- "mov %ecx, %edx\n" /* search for auxv (follows NULL after last env) */
- "0:\n"
- "add $4, %edx\n" /* search for auxv using edx, it follows the */
- "cmp -4(%edx), %ebp\n" /* ... NULL after last env (ebp is zero here) */
- "jnz 0b\n"
- "mov %edx, _auxv\n" /* save it into _auxv */
- "and $-16, %esp\n" /* x86 ABI : esp must be 16-byte aligned before */
- "sub $4, %esp\n" /* the call instruction (args are aligned) */
- "push %ecx\n" /* push all registers on the stack so that we */
- "push %ebx\n" /* support both regparm and plain stack modes */
- "push %eax\n"
- "call main\n" /* main() returns the status code in %eax */
- "mov %eax, %ebx\n" /* retrieve exit code (32-bit int) */
- "movl $1, %eax\n" /* NR_exit == 1 */
- "int $0x80\n" /* exit now */
- "hlt\n" /* ensure it does not */
+ "xor %ebp, %ebp\n" /* zero the stack frame */
+ "mov %esp, %eax\n" /* save stack pointer to %eax, as arg1 of _start_c */
+ "and $-16, %esp\n" /* last pushed argument must be 16-byte aligned */
+ "push %eax\n" /* push arg1 on stack to support plain stack modes too */
+ "call _start_c\n" /* transfer to c runtime */
+ "hlt\n" /* ensure it does not return */
);
__builtin_unreachable();
}
diff --git a/tools/include/nolibc/arch-loongarch.h b/tools/include/nolibc/arch-loongarch.h
index ad3f266e7093..bf98f6220195 100644
--- a/tools/include/nolibc/arch-loongarch.h
+++ b/tools/include/nolibc/arch-loongarch.h
@@ -8,6 +8,7 @@
#define _NOLIBC_ARCH_LOONGARCH_H
#include "compiler.h"
+#include "crt.h"
/* Syscalls for LoongArch :
* - stack is 16-byte aligned
@@ -22,18 +23,19 @@
* On LoongArch, select() is not implemented so we have to use pselect6().
*/
#define __ARCH_WANT_SYS_PSELECT6
+#define _NOLIBC_SYSCALL_CLOBBERLIST \
+ "memory", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8"
#define my_syscall0(num) \
({ \
register long _num __asm__ ("a7") = (num); \
register long _arg1 __asm__ ("a0"); \
\
- __asm__ volatile ( \
+ __asm__ volatile ( \
"syscall 0\n" \
: "=r"(_arg1) \
: "r"(_num) \
- : "memory", "$t0", "$t1", "$t2", "$t3", \
- "$t4", "$t5", "$t6", "$t7", "$t8" \
+ : _NOLIBC_SYSCALL_CLOBBERLIST \
); \
_arg1; \
})
@@ -43,12 +45,11 @@
register long _num __asm__ ("a7") = (num); \
register long _arg1 __asm__ ("a0") = (long)(arg1); \
\
- __asm__ volatile ( \
+ __asm__ volatile ( \
"syscall 0\n" \
: "+r"(_arg1) \
: "r"(_num) \
- : "memory", "$t0", "$t1", "$t2", "$t3", \
- "$t4", "$t5", "$t6", "$t7", "$t8" \
+ : _NOLIBC_SYSCALL_CLOBBERLIST \
); \
_arg1; \
})
@@ -59,13 +60,12 @@
register long _arg1 __asm__ ("a0") = (long)(arg1); \
register long _arg2 __asm__ ("a1") = (long)(arg2); \
\
- __asm__ volatile ( \
+ __asm__ volatile ( \
"syscall 0\n" \
: "+r"(_arg1) \
: "r"(_arg2), \
"r"(_num) \
- : "memory", "$t0", "$t1", "$t2", "$t3", \
- "$t4", "$t5", "$t6", "$t7", "$t8" \
+ : _NOLIBC_SYSCALL_CLOBBERLIST \
); \
_arg1; \
})
@@ -77,13 +77,12 @@
register long _arg2 __asm__ ("a1") = (long)(arg2); \
register long _arg3 __asm__ ("a2") = (long)(arg3); \
\
- __asm__ volatile ( \
+ __asm__ volatile ( \
"syscall 0\n" \
: "+r"(_arg1) \
: "r"(_arg2), "r"(_arg3), \
"r"(_num) \
- : "memory", "$t0", "$t1", "$t2", "$t3", \
- "$t4", "$t5", "$t6", "$t7", "$t8" \
+ : _NOLIBC_SYSCALL_CLOBBERLIST \
); \
_arg1;