public inbox for glibc-cvs@sourceware.org
help / color / mirror / Atom feed
* [glibc/arm/morello/main] aarch64: morello: Use purecap ELF entry ABI in _start
@ 2022-10-12 14:17 Szabolcs Nagy
  0 siblings, 0 replies; only message in thread
From: Szabolcs Nagy @ 2022-10-12 14:17 UTC (permalink / raw)
  To: glibc-cvs

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=11e0080cd54f35d11ed45ba18a52419608203ad8

commit 11e0080cd54f35d11ed45ba18a52419608203ad8
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
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 ();
 }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-10-12 14:17 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-12 14:17 [glibc/arm/morello/main] aarch64: morello: Use purecap ELF entry ABI in _start Szabolcs Nagy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).