]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
TODO(ddc): aarch64: morello: purecap support in the CSU
authorCarlos Eduardo Seo <carlos.seo@arm.com>
Thu, 18 Mar 2021 18:02:54 +0000 (15:02 -0300)
committerSzabolcs Nagy <szabolcs.nagy@arm.com>
Fri, 5 Aug 2022 18:45:19 +0000 (19:45 +0100)
Purecap ABI versions of start.S, crti.S and crtn.S.

TODO: must not use ddc but caps from auxv
TODO: start.S: dynamic linked case is now detected by x0 != 0 (ld.so passes
__rtld_fini there), but the value of c0 on entry is not abi, just that
it has to be passed back to the libc start code in c5, so ideally the
linker should be fixed to reliably emit __rela_dyn_start when a static
exe must self relocate.

sysdeps/aarch64/morello/crti.S [new file with mode: 0644]
sysdeps/aarch64/morello/crtn.S [new file with mode: 0644]
sysdeps/aarch64/morello/start.S [new file with mode: 0644]

diff --git a/sysdeps/aarch64/morello/crti.S b/sysdeps/aarch64/morello/crti.S
new file mode 100644 (file)
index 0000000..b8b2010
--- /dev/null
@@ -0,0 +1,93 @@
+/* Special .init and .fini section support for Morello.
+   Copyright (C) 1995-2022 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file. (The GNU Lesser General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   Note that people who make modified versions of this file are not
+   obligated to grant this special exception for their modified
+   versions; it is their choice whether to do so. The GNU Lesser
+   General Public License gives permission to release a modified
+   version without this exception; this exception also makes it
+   possible to release a modified version which carries forward this
+   exception.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* crti.S puts a function prologue at the beginning of the .init and
+   .fini sections and defines global symbols for those addresses, so
+   they can be called as functions.  The symbols _init and _fini are
+   magic and cause the linker to emit DT_INIT and DT_FINI.  */
+
+#include <sysdep.h>
+#include <libc-symbols.h>
+
+#ifndef PREINIT_FUNCTION
+# define PREINIT_FUNCTION __gmon_start__
+#endif
+
+#ifndef PREINIT_FUNCTION_WEAK
+# define PREINIT_FUNCTION_WEAK 1
+#endif
+
+#if PREINIT_FUNCTION_WEAK
+       weak_extern (PREINIT_FUNCTION)
+#else
+       .hidden PREINIT_FUNCTION
+#endif
+
+#if PREINIT_FUNCTION_WEAK
+       .align  2
+       .type   call_weak_fn, %function
+call_weak_fn:
+       adrp    c0, :got:PREINIT_FUNCTION
+       ldr     c0, [c0, #:got_lo12:PREINIT_FUNCTION]
+       cbz     x0, 1f
+       b       PREINIT_FUNCTION
+1:
+       RET
+       .size   call_weak_fn, .-call_weak_fn
+#endif
+
+       .section .init,"ax",%progbits
+       .align  2
+       .global _init
+       .hidden _init
+       .type   _init, %function
+_init:
+       stp     c29, c30, [csp, -32]!
+       mov     c29, csp
+#if PREINIT_FUNCTION_WEAK
+       bl      call_weak_fn
+#else
+       bl      PREINIT_FUNCTION
+#endif
+
+       .section        .fini,"ax",%progbits
+       .align  2
+       .global _fini
+       .hidden _fini
+       .type   _fini, %function
+_fini:
+       stp     c29, c30, [csp, -32]!
+       mov     c29, csp
diff --git a/sysdeps/aarch64/morello/crtn.S b/sysdeps/aarch64/morello/crtn.S
new file mode 100644 (file)
index 0000000..f405acc
--- /dev/null
@@ -0,0 +1,48 @@
+/* Special .init and .fini section support for Morello.
+   Copyright (C) 1995-2022 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file. (The GNU Lesser General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   Note that people who make modified versions of this file are not
+   obligated to grant this special exception for their modified
+   versions; it is their choice whether to do so. The GNU Lesser
+   General Public License gives permission to release a modified
+   version without this exception; this exception also makes it
+   possible to release a modified version which carries forward this
+   exception.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* crtn.S puts function epilogues in the .init and .fini sections
+   corresponding to the prologues in crti.S. */
+
+#include <sysdep.h>
+
+       .section .init,"ax",%progbits
+       ldp     c29, c30, [csp], 32
+       RET
+
+       .section .fini,"ax",%progbits
+       ldp     c29, c30, [csp], 32
+       RET
diff --git a/sysdeps/aarch64/morello/start.S b/sysdeps/aarch64/morello/start.S
new file mode 100644 (file)
index 0000000..2706019
--- /dev/null
@@ -0,0 +1,216 @@
+/* Copyright (C) 2022 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <linux/auxvec.h>
+#include <cheri_perms.h>
+
+weak_extern (__rela_dyn_start)
+weak_extern (__rela_dyn_end)
+
+/* This is the canonical entry point, usually the first thing in the text
+   segment.
+
+   Note that 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'.
+               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
+ */
+
+       .text
+ENTRY(_start)
+
+       /* Create an initial frame with 0 LR and FP */
+       cfi_undefined (c30)
+       mov     c29, czr
+       mov     c30, czr
+
+       /* TODO: Use the presence of __rela_dyn_start.  */
+       mov     c5, c0
+       cbnz    x0, L(rtld_done)
+
+       /* Initialize capabilities.  */
+#ifndef SHARED
+       /* The GNU Linker emits a R_MORELLO_RELATIVE relocation along with
+          __rela_dyn_start and __rela_dyn_end symbols around the relocation section.
+          r_offset contains the location, size and permissions:
+
+               capability location             // offset 0 (64 bits)
+               length                          // offset 8 (56 bits)
+               permissions                     //           (8 bits)
+               addend (capability offset)      // offset 16
+
+          according to the ABI document in:
+          https://github.com/ARM-software/abi-aa/blob/main/aaelf64-morello/aaelf64-morello.rst#dynamic-linking-with-morello
+
+       The addend is the capability offset.
+
+          Note that this will not work with clang, since lld emits a __cap_relocs
+          struct that has a different layout.  If we need to support clang+lld, then
+          we need to copy the capability initialization steps from Bionic, in:
+          libc/arch-morello/bionic/__morello_init_static.S.  */
+
+       adrp    c0, __rela_dyn_start
+       add     c0, c0, #:lo12:__rela_dyn_start
+       adrp    c1, __rela_dyn_end
+       add     c1, c1, #:lo12:__rela_dyn_end
+
+1:
+       /* No capabilities to initialize. Skip to stack adjustment.  */
+       cmp     c0, c1
+       b.eq    3f
+
+       /* Load the address of capability.  */
+       ldr     x2, [c0, #0]
+
+       /* Construct capability location from DDC and r_offset.  */
+       cvtd    c2, x2
+
+       /* Base in x3.  */
+       ldr     x3, [c2]
+
+       /* Length + permissions in x5.  */
+       ldr     x5, [c2, #8]
+
+       /* Permissions in x6.  */
+       lsr     x6, x5, #56
+
+       /* Permissions encoded as:
+          4 = X (executable)
+          2 = W (read/write)
+          1 = R (read only)
+
+          Permissions to clear in x8 and x11.  */
+       mov     x8, (CAP_PERM_STORE_CAP | CAP_PERM_EXECUTE)
+       movk    x8, (CAP_PERM_STORE >> 16), lsl #16
+       mov     x9, (CAP_PERM_EXECUTE)
+       mov     x10, (CAP_PERM_STORE_CAP)
+       movk    x10, (CAP_PERM_STORE >> 16), lsl #16
+       mov     x11, (CAP_PERM_UNSEAL | CAP_PERM_SEAL | CAP_PERM_COMPARTMENT_ID)
+       cmp     x6, #0x2
+       csel    x8, x9, x8, eq
+       cmp     x6, #0x4
+       csel    x8, x10, x8, eq
+
+       /* Length in x5.  */
+       and     x5, x5, #0xffffffffffffff
+
+       /* Offset in x7.  */
+       ldr     x7, [c0, #16]
+
+       /* Construct capability from DDC with value equal to base.  */
+       cvtd    c3, x3
+
+       /* Set bounds to [base ; base + length].  */
+       scbndse c3, c3, x5
+
+       /* Compute the capability value from addend.  */
+       add     c3, c3, x7
+
+       /* Clear permissions.  */
+       clrperm c3, c3, x8
+       clrperm c3, c3, x11
+
+       /* Seal capabilities, which provide execute permission, with MORELLO_RB */
+       tst     x8, #CAP_PERM_EXECUTE
+       b.ne    2f
+
+       seal    c3, c3, rb
+
+2:
+       /* Store the constructed capability to the target location.  */
+       str     c3, [c2]
+
+       /* Move to the next __rela_dyn entry.  */
+       add     c0, c0, #24
+       b       1b
+
+3:
+#endif /* !SHARED */
+
+       /* Setup rtld_fini in argument register */
+       mov     c5, czr
+
+L(rtld_done):
+
+       /* Load argc and a pointer to argv */
+       ldr     c1, [csp, #0]
+       add     c2, csp, #16
+
+       /* Setup stack limit in argument register */
+       mov     c6, csp
+
+#ifdef PIC
+# ifdef SHARED
+       adrp    c0, :got:main
+       ldr     c0, [c0, #:got_lo12:main]
+# else
+       adrp    c0, __wrap_main
+       add     c0, c0, :lo12:__wrap_main
+# endif /* SHARED */
+#else
+       /* Set up the other arguments in registers */
+       MOVL (0, main)
+       cvtd    c0, x0
+#endif /* PIC */
+
+       mov     x3, #0          /* Used to be init.  */
+       mov     x4, #0          /* Used to be fini.  */
+
+       /* __libc_start_main (main, argc, argv, init, fini, rtld_fini,
+                             stack_end) */
+
+       /* Let the libc call main and exit with its return code.  */
+       bl      __libc_start_main
+
+       /* should never get here....*/
+       bl      abort
+END(_start)
+
+#if defined PIC && !defined SHARED
+       /* When main is not defined in the executable but in a shared library
+          then a wrapper is needed in crt1.o of the static-pie enabled libc,
+          because crt1.o and rcrt1.o share code and the later must avoid the
+          use of GOT relocations before __libc_start_main is called.  */
+ENTRY(__wrap_main)
+       b       main
+END(__wrap_main)
+#endif
+
+       /* Define a symbol for the first piece of initialized data.  */
+       .data
+       .globl __data_start
+__data_start:
+       .long 0
+       .weak data_start
+       data_start = __data_start