diff --git a/lib/csu/aarch64c/crt1_c.c b/lib/csu/aarch64c/crt1_c.c index ca3cf8d39ee3..3fba07a6ae41 100644 --- a/lib/csu/aarch64c/crt1_c.c +++ b/lib/csu/aarch64c/crt1_c.c @@ -49,6 +49,7 @@ struct Struct_Obj_Entry; void _start(void *, void (*)(void), struct Struct_Obj_Entry *) __dead2 __exported; +void __start(void *, void (*)(void), struct Struct_Obj_Entry *) __dead2; #ifdef GCRT /* Profiling support. */ @@ -69,11 +70,10 @@ Elf_Auxinfo *__auxargs; * linker takes care of initialization otherwise. */ void -_start(void *auxv, +__start(void *auxv, void (*cleanup)(void), /* from shared loader */ struct Struct_Obj_Entry *obj) /* from shared loader */ { - __asm__ volatile(".cfi_undefined c30"); int argc = 0; char **argv = NULL; char **env = NULL; @@ -131,3 +131,20 @@ _start(void *auxv, __libc_start1(argc, argv, env, cleanup, main, data_cap, code_cap); } + +/* + * The real entry point _start just sets the unwind info for CRA to undefined + * which tells libunwind to stop unwinding and then calls the real __start. + * This is needed because ".cfi_undefined" inline assembly in a non-naked + * function could be overridden by the default unwinding information. + */ +__attribute__((naked, used)) void +_start(void *auxv, + void (*cleanup)(void), /* from shared loader */ + struct Struct_Obj_Entry *obj) /* from shared loader */ +{ + __asm__( + ".cfi_undefined c30\n" + "bl %0" + :: "i"(__start)); +} diff --git a/lib/csu/riscv/crt1_c.c b/lib/csu/riscv/crt1_c.c index 41ae7cff9f2a..04d6e7b26749 100644 --- a/lib/csu/riscv/crt1_c.c +++ b/lib/csu/riscv/crt1_c.c @@ -57,7 +57,6 @@ void __start(int argc, char **argv, char **env, void (*cleanup)(void)) __dead2; void __start(int argc, char **argv, char **env, void (*cleanup)(void)) { - __asm__ volatile(".cfi_undefined ra"); #ifdef SHOULD_PROCESS_CAP_RELOCS /* * Initialize __cap_relocs for static executables. The run-time linker diff --git a/lib/csu/riscv/crt1_s.S b/lib/csu/riscv/crt1_s.S index 8f77d2358ae7..bf69d1435bb8 100644 --- a/lib/csu/riscv/crt1_s.S +++ b/lib/csu/riscv/crt1_s.S @@ -35,6 +35,7 @@ #include ENTRY(_start) + .cfi_undefined ra # Stop unwinding here mv a3, a2 # cleanup addi a1, a0, 8 # get argv ld a0, 0(a0) # load argc diff --git a/lib/csu/riscv64c/crt1_c.c b/lib/csu/riscv64c/crt1_c.c index 3108ebf562c9..ef4e8a43ab83 100644 --- a/lib/csu/riscv64c/crt1_c.c +++ b/lib/csu/riscv64c/crt1_c.c @@ -49,6 +49,7 @@ struct Struct_Obj_Entry; void _start(void *, void (*)(void), struct Struct_Obj_Entry *) __dead2 __exported; +void __start(void *, void (*)(void), struct Struct_Obj_Entry *) __dead2; #ifdef GCRT /* Profiling support. */ @@ -69,11 +70,10 @@ Elf_Auxinfo *__auxargs; * linker takes care of initialization otherwise. */ void -_start(void *auxv, +__start(void *auxv, void (*cleanup)(void), /* from shared loader */ struct Struct_Obj_Entry *obj) /* from shared loader */ { - __asm__ volatile(".cfi_undefined cra"); int argc = 0; char **argv = NULL; char **env = NULL; @@ -128,3 +128,20 @@ _start(void *auxv, __libc_start1(argc, argv, env, cleanup, main, NULL, NULL); } + +/* + * The real entry point _start just sets the unwind info for CRA to undefined + * which tells libunwind to stop unwinding and then calls the real __start. + * This is needed because ".cfi_undefined" inline assembly in a non-naked + * function could be overridden by the default unwinding information. + */ +__attribute__((naked, used)) void +_start(void *auxv, + void (*cleanup)(void), /* from shared loader */ + struct Struct_Obj_Entry *obj) /* from shared loader */ +{ + __asm__( + ".cfi_undefined cra\n" + "ccall %0" + :: "i"(__start)); +}