From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1944) id 410CB385086C; Wed, 12 Oct 2022 14:17:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 410CB385086C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1665584226; bh=ws4VkeJ4YWbOv2ZuE5/euETPrB632QUNhYlSjQUbqis=; h=From:To:Subject:Date:From; b=eyrEyshWgkq1tnE3OFm1MsJ7VkERPaKtpYpI6fdI72KyrmjqxY2m+m+O/gkNq6XPk XeRmbAqa2tFOrSfhJUBDRv7C7p9YeVlffaFT82urWQ7POGloJPSmOGWT7HVcMHWWXi 0dfA1Q7EWm5c5vfyaJTOLrkHdLf6fGYB68WntYic= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Szabolcs Nagy To: glibc-cvs@sourceware.org Subject: [glibc/arm/morello/main] aarch64: morello: Use purecap ELF entry ABI in _start X-Act-Checkin: glibc X-Git-Author: Szabolcs Nagy X-Git-Refname: refs/heads/arm/morello/main X-Git-Oldrev: bb624b6c4376d3b3a3c4fe3ed5d1cd6366fd3ac6 X-Git-Newrev: 11e0080cd54f35d11ed45ba18a52419608203ad8 Message-Id: <20221012141706.410CB385086C@sourceware.org> Date: Wed, 12 Oct 2022 14:17:06 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=11e0080cd54f35d11ed45ba18a52419608203ad8 commit 11e0080cd54f35d11ed45ba18a52419608203ad8 Author: Szabolcs Nagy Date: Wed Aug 31 11:26:46 2022 +0100 aarch64: morello: Use purecap ELF entry ABI in _start The purecap ELF entry is special: passes separate argc, argv, envp, auxv in registers instead of on the stack. The ldso internal _dl_start still expects continuous argc, argv, envp, auxv, so that's emulated. Diff: --- sysdeps/aarch64/morello/dl-start.c | 68 +++++++++++++++++++++++++++----------- sysdeps/aarch64/morello/start.c | 68 +++++++++++++++++++++----------------- 2 files changed, 85 insertions(+), 51 deletions(-) diff --git a/sysdeps/aarch64/morello/dl-start.c b/sysdeps/aarch64/morello/dl-start.c index b0bedc4b8c..f1b792d957 100644 --- a/sysdeps/aarch64/morello/dl-start.c +++ b/sysdeps/aarch64/morello/dl-start.c @@ -28,23 +28,14 @@ asm("" " .cfi_undefined c30\n" " mov c29, czr\n" " mov c30, czr\n" -" mov c0, csp\n" -" bl __real_start\n" - /* Jump to the user's entry point, with original csp. */ -" mov c16, c0\n" -" mov c0, c1\n" -" br c16\n" +" b __real_start\n" " .cfi_endproc\n" " .size _start, .-_start\n"); -typedef void (entry_t) (void (*)(void)); +typedef void (entry_t) (int, char **, char **, void *, void (*)(void)); -typedef struct user_entry { - entry_t *fun; - void (*arg)(void); -}; - -struct user_entry +__attribute__ ((noinline, noreturn)) +void _dl_start_user (uintptr_t *args, entry_t *entry) { /* Setup argv, envp, auxv for the application. */ @@ -64,8 +55,22 @@ _dl_start_user (uintptr_t *args, entry_t *entry) uintptr_t *auxv = __builtin_cheri_bounds_set (p, n * sizeof *p); _dl_init (GL(dl_ns)[LM_ID_BASE]._ns_loaded, argc, argv, envp); - struct user_entry e = {entry, _dl_fini}; - return e; + entry (argc, argv, envp, auxv, _dl_fini); + __builtin_trap (); +} + +/* Count the array length needed for traditional ELF entry. */ +static inline long +count_args (int argc, char **argv, char **envp, uintptr_t *auxv) +{ + char **p; + uintptr_t *q; + long nargs = argc + 2; + for (p = envp; *p != NULL; p++); + nargs += p - envp + 1; + for (q = auxv; *q != AT_NULL; q += 2); + nargs += q - auxv + 2; + return nargs; } /* Generic ld.so start code in rtld.c. */ @@ -73,10 +78,33 @@ uintptr_t _dl_start (void *) attribute_hidden; /* ld.so entry point. */ -struct user_entry -__real_start (uintptr_t *sp) +void +__real_start (int argc, char **argv, char **envp, void *auxv) { - /* Run ls.so setup. */ - entry_t *entry = (entry_t *) _dl_start (sp); - return _dl_start_user (sp, entry); + long nargs = count_args (argc, argv, envp, auxv); + { + /* _dl_start requires continuous argv, envp, auxv. */ + uintptr_t args[nargs]; + long i = 0, j; + args[i++] = argc; + for (j = 0; argv[j] != NULL; j++) + args[i++] = (uintptr_t) argv[j]; + args[i++] = 0; + for (j = 0; envp[j] != NULL; j++) + args[i++] = (uintptr_t) envp[j]; + args[i++] = 0; + uintptr_t *a = auxv; + for (j = 0; a[j] != AT_NULL; j += 2) + { + args[i++] = a[j]; + args[i++] = a[j+1]; + } + args[i++] = AT_NULL; + args[i++] = 0; + assert (i == nargs); + + /* Run ls.so setup. */ + entry_t *entry = (entry_t *) _dl_start (args); + _dl_start_user (args, entry); + } } diff --git a/sysdeps/aarch64/morello/start.c b/sysdeps/aarch64/morello/start.c index fbc9512789..de7aeab4c9 100644 --- a/sysdeps/aarch64/morello/start.c +++ b/sysdeps/aarch64/morello/start.c @@ -43,24 +43,24 @@ Note that in case of dynamic linked exe the code in the .init section has already been run. This includes _init and _libc_init. - At this entry point, most registers' values are unspecified, except: - x0/w0 Contains a function pointer to be registered with `atexit'. + x0 argc + + c1 argv + + c2 envp + + c3 auxv + + c4 Contains a function pointer to be registered with `atexit'. This is how the dynamic linker arranges to have DT_FINI functions called for shared libraries that have been loaded - before this code runs. - - sp The stack contains the arguments and environment: - 0(sp) argc - 8(sp) argv[0] - ... - (8*argc)(sp) NULL - (8*(argc+1))(sp) envp[0] - ... - NULL - */ + before this code runs. It is unspecified in a static linked + executable. + csp The stack pointer. + */ asm("" ".global _start\n" ".type _start, %function\n" @@ -69,7 +69,7 @@ asm("" " .cfi_undefined c30\n" " mov c29, czr\n" " mov c30, czr\n" -" mov c1, csp\n" +" mov c5, csp\n" " b __real_start\n" " .cfi_endproc\n" " .size _start, .-_start\n"); @@ -113,14 +113,24 @@ get_rela_dyn_end (void) return p; } -static uintptr_t -get_base (void) +static void +get_caps (uintptr_t *cap_rx, uintptr_t *cap_rw, const uintptr_t *auxv) { - /* The base is always 0: only used for static linking and static pie - is not supported here. */ - uintptr_t p = 0; - asm volatile ("cvtd %0, %x0" : "+r"(p)); - return p; + for (;;) + { + switch ((unsigned long)auxv[0]) + { + case AT_NULL: + return; + case AT_CHERI_EXEC_RX_CAP: + *cap_rx = auxv[1]; + break; + case AT_CHERI_EXEC_RW_CAP: + *cap_rw = auxv[1]; + break; + } + auxv += 2; + } } static void @@ -144,27 +154,23 @@ void __libc_start_main (int main (int, char **, char **, void *), void rtld_fini (void), void *sp); void -__real_start (void rtld_fini (void), uintptr_t *sp) +__real_start (int argc, char **argv, char **envp, void *auxv, + void (*rtld_fini) (void), uintptr_t *sp) { #ifndef SHARED if (is_static_linked ()) { uintptr_t start = get_rela_dyn_start (); uintptr_t end = get_rela_dyn_end (); - uintptr_t base = get_base (); - apply_rel (base, base, start, end); + uintptr_t cap_rx = 0; + uintptr_t cap_rw = 0; + get_caps (&cap_rx, &cap_rw, auxv); + apply_rel (cap_rx, cap_rw, start, end); rtld_fini = 0; } /* Compiler barrier after relocs are processed. */ asm volatile ("" ::: "memory"); #endif - - int argc = *sp; - char **argv = (char **) (sp + 1); - char **envp = argv + argc + 1; - char **p = envp; - while (*p) p++; - void *auxv = p + 1; __libc_start_main (main, argc, argv, envp, auxv, rtld_fini, sp); __builtin_trap (); }