mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 05:44:11 +00:00
tools/nolibc: add support for constructors and destructors
With the startup code moved to C, implementing support for constructors and deconstructors is fairly easy to implement. Examples for code size impact: text data bss dec hex filename 21837 104 88 22029 560d nolibc-test.before 22135 120 88 22343 5747 nolibc-test.after 21970 104 88 22162 5692 nolibc-test.after-only-crt.h-changes The sections are defined by [0]. [0] https://refspecs.linuxfoundation.org/elf/gabi4+/ch5.dynamic.html Signed-off-by: Thomas Weißschuh <linux@weissschuh.net> Acked-by: Willy Tarreau <w@1wt.eu> Link: https://lore.kernel.org/lkml/20231007-nolibc-constructors-v2-1-ef84693efbc1@weissschuh.net/
This commit is contained in:
parent
eddfc3c742
commit
63aa531716
2 changed files with 39 additions and 1 deletions
|
@ -13,12 +13,23 @@ const unsigned long *_auxv __attribute__((weak));
|
||||||
static void __stack_chk_init(void);
|
static void __stack_chk_init(void);
|
||||||
static void exit(int);
|
static void exit(int);
|
||||||
|
|
||||||
|
extern void (*const __preinit_array_start[])(void) __attribute__((weak));
|
||||||
|
extern void (*const __preinit_array_end[])(void) __attribute__((weak));
|
||||||
|
|
||||||
|
extern void (*const __init_array_start[])(void) __attribute__((weak));
|
||||||
|
extern void (*const __init_array_end[])(void) __attribute__((weak));
|
||||||
|
|
||||||
|
extern void (*const __fini_array_start[])(void) __attribute__((weak));
|
||||||
|
extern void (*const __fini_array_end[])(void) __attribute__((weak));
|
||||||
|
|
||||||
__attribute__((weak))
|
__attribute__((weak))
|
||||||
void _start_c(long *sp)
|
void _start_c(long *sp)
|
||||||
{
|
{
|
||||||
long argc;
|
long argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
char **envp;
|
char **envp;
|
||||||
|
int exitcode;
|
||||||
|
void (* const *func)(void);
|
||||||
const unsigned long *auxv;
|
const unsigned long *auxv;
|
||||||
/* silence potential warning: conflicting types for 'main' */
|
/* silence potential warning: conflicting types for 'main' */
|
||||||
int _nolibc_main(int, char **, char **) __asm__ ("main");
|
int _nolibc_main(int, char **, char **) __asm__ ("main");
|
||||||
|
@ -55,8 +66,18 @@ void _start_c(long *sp)
|
||||||
;
|
;
|
||||||
_auxv = auxv;
|
_auxv = auxv;
|
||||||
|
|
||||||
|
for (func = __preinit_array_start; func < __preinit_array_end; func++)
|
||||||
|
(*func)();
|
||||||
|
for (func = __init_array_start; func < __init_array_end; func++)
|
||||||
|
(*func)();
|
||||||
|
|
||||||
/* go to application */
|
/* go to application */
|
||||||
exit(_nolibc_main(argc, argv, envp));
|
exitcode = _nolibc_main(argc, argv, envp);
|
||||||
|
|
||||||
|
for (func = __fini_array_end; func > __fini_array_start;)
|
||||||
|
(*--func)();
|
||||||
|
|
||||||
|
exit(exitcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _NOLIBC_CRT_H */
|
#endif /* _NOLIBC_CRT_H */
|
||||||
|
|
|
@ -57,6 +57,9 @@ static int test_argc;
|
||||||
/* will be used by some test cases as readable file, please don't write it */
|
/* will be used by some test cases as readable file, please don't write it */
|
||||||
static const char *argv0;
|
static const char *argv0;
|
||||||
|
|
||||||
|
/* will be used by constructor tests */
|
||||||
|
static int constructor_test_value;
|
||||||
|
|
||||||
/* definition of a series of tests */
|
/* definition of a series of tests */
|
||||||
struct test {
|
struct test {
|
||||||
const char *name; /* test name */
|
const char *name; /* test name */
|
||||||
|
@ -594,6 +597,19 @@ int expect_strne(const char *expr, int llen, const char *cmp)
|
||||||
#define CASE_TEST(name) \
|
#define CASE_TEST(name) \
|
||||||
case __LINE__: llen += printf("%d %s", test, #name);
|
case __LINE__: llen += printf("%d %s", test, #name);
|
||||||
|
|
||||||
|
/* constructors validate that they are executed in definition order */
|
||||||
|
__attribute__((constructor))
|
||||||
|
static void constructor1(void)
|
||||||
|
{
|
||||||
|
constructor_test_value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((constructor))
|
||||||
|
static void constructor2(void)
|
||||||
|
{
|
||||||
|
constructor_test_value *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
int run_startup(int min, int max)
|
int run_startup(int min, int max)
|
||||||
{
|
{
|
||||||
int test;
|
int test;
|
||||||
|
@ -630,6 +646,7 @@ int run_startup(int min, int max)
|
||||||
CASE_TEST(environ_HOME); EXPECT_PTRNZ(1, getenv("HOME")); break;
|
CASE_TEST(environ_HOME); EXPECT_PTRNZ(1, getenv("HOME")); break;
|
||||||
CASE_TEST(auxv_addr); EXPECT_PTRGT(test_auxv != (void *)-1, test_auxv, brk); break;
|
CASE_TEST(auxv_addr); EXPECT_PTRGT(test_auxv != (void *)-1, test_auxv, brk); break;
|
||||||
CASE_TEST(auxv_AT_UID); EXPECT_EQ(1, getauxval(AT_UID), getuid()); break;
|
CASE_TEST(auxv_AT_UID); EXPECT_EQ(1, getauxval(AT_UID), getuid()); break;
|
||||||
|
CASE_TEST(constructor); EXPECT_EQ(1, constructor_test_value, 2); break;
|
||||||
case __LINE__:
|
case __LINE__:
|
||||||
return ret; /* must be last */
|
return ret; /* must be last */
|
||||||
/* note: do not set any defaults so as to permit holes above */
|
/* note: do not set any defaults so as to permit holes above */
|
||||||
|
|
Loading…
Reference in a new issue