Files
linux/tools/include/nolibc/crt.h
Thomas Weißschuh 32db83195f tools/nolibc: add __nolibc_arg_to_reg()
In the architecture specific system call glue, all arguments are
currently casted to 'long' to fit into registers. This works for
pointers as 'long' has the same size as pointers.
However the system call registers for X32 and MIPS N32 need to be
'long long' to work correctly for 64-bit values expected by the system
call ABI. Casting a pointer to a 'long long' will produce a compiler
warning while casting 64-bit integers to 'long' will truncate those.

Add a helper which can be used to correctly cast both pointers and
integers into 'long long' registers. Cast the pointers through
'unsigned' to avoid any sign extensions.

Both builtins have been available since at least GCC 3 and clang 3.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Acked-by: Willy Tarreau <w@1wt.eu>
Link: https://patch.msgid.link/20260418-nolibc-largefile-v1-2-b91f0775bac3@weissschuh.net
2026-04-27 20:08:48 +02:00

122 lines
3.3 KiB
C

/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
/*
* C Run Time support for NOLIBC
* Copyright (C) 2023 Zhangjin Wu <falcon@tinylab.org>
*/
#ifndef _NOLIBC_CRT_H
#define _NOLIBC_CRT_H
#define __nolibc_arg_to_reg(_a) \
__builtin_choose_expr(__builtin_classify_type(_a) == __builtin_classify_type(NULL), \
(unsigned long)(_a), (_a))
#ifndef NOLIBC_NO_RUNTIME
#include "compiler.h"
char **environ __attribute__((weak));
const unsigned long *_auxv __attribute__((weak));
void _start(void);
static void __stack_chk_init(void);
static void exit(int);
static char *strrchr(const char *s, int c);
extern void (*const __preinit_array_start[])(int, char **, char**) __attribute__((weak));
extern void (*const __preinit_array_end[])(int, char **, char**) __attribute__((weak));
extern void (*const __init_array_start[])(int, char **, char**) __attribute__((weak));
extern void (*const __init_array_end[])(int, char **, char**) __attribute__((weak));
extern void (*const __fini_array_start[])(void) __attribute__((weak));
extern void (*const __fini_array_end[])(void) __attribute__((weak));
#ifndef NOLIBC_IGNORE_ERRNO
extern char *program_invocation_name __attribute__((weak));
extern char *program_invocation_short_name __attribute__((weak));
static __inline__
char *__nolibc_program_invocation_short_name(char *long_name)
{
char *short_name;
short_name = strrchr(long_name, '/');
if (!short_name || !short_name[0])
return long_name;
return short_name + 1;
}
#endif /* NOLIBC_IGNORE_ERRNO */
void _start_c(long *sp);
__attribute__((weak,used)) __nolibc_no_sanitize_undefined __nolibc_no_stack_protector
void _start_c(long *sp)
{
long argc;
char **argv;
char **envp;
int exitcode;
void (* const *ctor_func)(int, char **, char **);
void (* const *dtor_func)(void);
const unsigned long *auxv;
/* silence potential warning: conflicting types for 'main' */
int _nolibc_main(int, char **, char **) __asm__ ("main");
/* initialize stack protector */
__stack_chk_init();
/*
* sp : argc <-- argument count, required by main()
* argv: argv[0] <-- argument vector, required by main()
* argv[1]
* ...
* argv[argc-1]
* null
* environ: environ[0] <-- environment variables, required by main() and getenv()
* environ[1]
* ...
* null
* _auxv: _auxv[0] <-- auxiliary vector, required by getauxval()
* _auxv[1]
* ...
* null
*/
/* assign argc and argv */
argc = *sp;
argv = (void *)(sp + 1);
/* find environ */
environ = envp = argv + argc + 1;
/* find _auxv */
for (auxv = (void *)envp; *auxv++;)
__asm__("");
_auxv = auxv;
#ifndef NOLIBC_IGNORE_ERRNO
if (argc > 0 && argv[0]) {
program_invocation_name = argv[0];
program_invocation_short_name = __nolibc_program_invocation_short_name(argv[0]);
}
#endif /* NOLIBC_IGNORE_ERRNO */
for (ctor_func = __preinit_array_start; ctor_func < __preinit_array_end; ctor_func++)
(*ctor_func)(argc, argv, envp);
for (ctor_func = __init_array_start; ctor_func < __init_array_end; ctor_func++)
(*ctor_func)(argc, argv, envp);
/* go to application */
exitcode = _nolibc_main(argc, argv, envp);
for (dtor_func = __fini_array_end; dtor_func > __fini_array_start;)
(*--dtor_func)();
exit(exitcode);
}
#endif /* NOLIBC_NO_RUNTIME */
#endif /* _NOLIBC_CRT_H */