aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzabolcs Nagy <szabolcs.nagy@arm.com>2022-08-31 11:26:46 +0100
committerSzabolcs Nagy <szabolcs.nagy@arm.com>2022-10-12 14:22:03 +0100
commit11e0080cd54f35d11ed45ba18a52419608203ad8 (patch)
tree49de2416f70fb2af3df4c049d69ea0bace534fdb
parentbb624b6c4376d3b3a3c4fe3ed5d1cd6366fd3ac6 (diff)
downloadglibc-11e0080cd54f35d11ed45ba18a52419608203ad8.zip
glibc-11e0080cd54f35d11ed45ba18a52419608203ad8.tar.gz
glibc-11e0080cd54f35d11ed45ba18a52419608203ad8.tar.bz2
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.
-rw-r--r--sysdeps/aarch64/morello/dl-start.c68
-rw-r--r--sysdeps/aarch64/morello/start.c68
2 files changed, 85 insertions, 51 deletions
diff --git a/sysdeps/aarch64/morello/dl-start.c b/sysdeps/aarch64/morello/dl-start.c
index b0bedc4..f1b792d 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 fbc9512..de7aeab 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 ();
}