Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/libexec/ld.elf_so/arch/aarch64 Adapt https://svnweb.freebsd....



details:   https://anonhg.NetBSD.org/src/rev/0e61f7b3261f
branches:  trunk
changeset: 996063:0e61f7b3261f
user:      skrll <skrll%NetBSD.org@localhost>
date:      Fri Jan 18 11:59:03 2019 +0000

description:
Adapt https://svnweb.freebsd.org/base?view=revision&revision=342113 to
NetBSD.

This brings us resolving for dynamically loaded libraries and makes
tests/libexec/ld.elf_so/t_thread_local_dtor pass.

With suggestions from joerg@

diffstat:

 libexec/ld.elf_so/arch/aarch64/mdreloc.c    |  105 ++++++++---------
 libexec/ld.elf_so/arch/aarch64/rtld_start.S |  164 ++++++++++++++++++++++-----
 2 files changed, 179 insertions(+), 90 deletions(-)

diffs (truncated from 373 to 300 lines):

diff -r 975c8f7f36b9 -r 0e61f7b3261f libexec/ld.elf_so/arch/aarch64/mdreloc.c
--- a/libexec/ld.elf_so/arch/aarch64/mdreloc.c  Fri Jan 18 07:05:36 2019 +0000
+++ b/libexec/ld.elf_so/arch/aarch64/mdreloc.c  Fri Jan 18 11:59:03 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.12 2018/11/23 11:26:05 skrll Exp $ */
+/* $NetBSD: mdreloc.c,v 1.13 2019/01/18 11:59:03 skrll Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.12 2018/11/23 11:26:05 skrll Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.13 2019/01/18 11:59:03 skrll Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -70,17 +70,16 @@
 #include "rtld.h"
 
 struct tls_data {
-       int64_t index;
-       Obj_Entry *obj;
-       const Elf_Rela *rela;
+       size_t          td_tlsindex;
+       Elf_Addr        td_tlsoffs;
 };
 
 void _rtld_bind_start(void);
 void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
 Elf_Addr _rtld_bind(const Obj_Entry *, Elf_Word);
-void *_rtld_tlsdesc(void *);
+void *_rtld_tlsdesc_static(void *);
+void *_rtld_tlsdesc_undef(void *);
 void *_rtld_tlsdesc_dynamic(void *);
-int64_t _rtld_tlsdesc_handle(struct tls_data *, u_int);
 
 /*
  * AARCH64 PLT looks like this;
@@ -117,67 +116,63 @@
 }
 
 static struct tls_data *
-_rtld_tlsdesc_alloc(Obj_Entry *obj, const Elf_Rela *rela)
+_rtld_tlsdesc_alloc(size_t tlsindex, Elf_Addr offs)
 {
        struct tls_data *tlsdesc;
 
        tlsdesc = xmalloc(sizeof(*tlsdesc));
-       tlsdesc->index = -1;
-       tlsdesc->obj = obj;
-       tlsdesc->rela = rela;
+       tlsdesc->td_tlsindex = tlsindex;
+       tlsdesc->td_tlsoffs = offs;
 
        return tlsdesc;
 }
 
-static int64_t
-_rtld_tlsdesc_handle_locked(struct tls_data *tlsdesc, u_int flags)
+static void
+_rtld_tlsdesc_fill(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *where, u_int flags)
 {
-       const Elf_Rela *rela;
        const Elf_Sym *def;
        const Obj_Entry *defobj;
-       Obj_Entry *obj;
-
-       rela = tlsdesc->rela;
-       obj = tlsdesc->obj;
-
-       def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, flags);
-       if (def == NULL)
-               _rtld_die();
+       Elf_Addr offs = 0;
+       unsigned long symnum = ELF_R_SYM(rela->r_info);
 
-       tlsdesc->index = defobj->tlsoffset + def->st_value + rela->r_addend +
-           sizeof(struct tls_tcb);
+       if (symnum != 0) {
+               def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
+                   flags);
+               if (def == NULL)
+                       _rtld_die();
+               if (def == &_rtld_sym_zero) {
+                       /* Weak undefined thread variable */
+                       where[0] = (Elf_Addr)_rtld_tlsdesc_undef;
+                       where[1] = rela->r_addend;
 
-       return tlsdesc->index;
-}
-
-int64_t
-_rtld_tlsdesc_handle(struct tls_data *tlsdesc, u_int flags)
-{
-       sigset_t mask;
+                       rdbg(("TLSDESC %s (weak) in %s --> %p",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)where[1]));
 
-       /* We have already found the index, return it */
-       if (tlsdesc->index >= 0)
-               return tlsdesc->index;
-
-       _rtld_exclusive_enter(&mask);
-       /* tlsdesc->index may have been set by another thread */
-       if (tlsdesc->index == -1)
-               _rtld_tlsdesc_handle_locked(tlsdesc, flags);
-       _rtld_exclusive_exit(&mask);
+                       return;
+               }
+               offs = def->st_value;
+       } else {
+               defobj = obj;
+       }
+       offs += rela->r_addend;
 
-       return tlsdesc->index;
-}
+       if (defobj->tls_done) {
+               /* Variable is in initialy allocated TLS segment */
+               where[0] = (Elf_Addr)_rtld_tlsdesc_static;
+               where[1] = defobj->tlsoffset + offs +
+                   sizeof(struct tls_tcb);
 
-static void
-_rtld_tlsdesc_fill(Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *where)
-{
-       if (ELF_R_SYM(rela->r_info) == 0) {
-               where[0] = (Elf_Addr)_rtld_tlsdesc;
-               where[1] = obj->tlsoffset + rela->r_addend +
-                   sizeof(struct tls_tcb);
+               rdbg(("TLSDESC %s --> %p static",
+                   obj->path, (void *)where[1]));
        } else {
+               /* TLS offset is unknown at load time, use dynamic resolving */
                where[0] = (Elf_Addr)_rtld_tlsdesc_dynamic;
-               where[1] = (Elf_Addr)_rtld_tlsdesc_alloc(obj, rela);
+               where[1] = (Elf_Addr)_rtld_tlsdesc_alloc(defobj->tlsindex, offs);
+
+               rdbg(("TLSDESC %s in %s --> %p dynamic (%zu, %p)",
+                   obj->strtab + obj->symtab[symnum].st_name,
+                   obj->path, (void *)where[1], defobj->tlsindex, (void *)offs));
        }
 }
 
@@ -276,7 +271,7 @@
                        break;
 
                case R_TYPE(TLSDESC):
-                       _rtld_tlsdesc_fill(obj, rela, where);
+                       _rtld_tlsdesc_fill(obj, rela, where, 0);
                        break;
 
                case R_TLS_TYPE(TLS_DTPREL):
@@ -344,7 +339,7 @@
                        rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where));
                        break;
                case R_TYPE(TLSDESC):
-                       _rtld_tlsdesc_fill(obj, rela, where);
+                       _rtld_tlsdesc_fill(obj, rela, where, SYMLOOK_IN_PLT);
                        break;
                }
        }
@@ -408,11 +403,7 @@
                        *tp = new_value;
                break;
        case R_TYPE(TLSDESC):
-               if (ELF_R_SYM(rela->r_info) != 0) {
-                       struct tls_data *tlsdesc = (struct tls_data *)where[1];
-                       if (tlsdesc->index == -1)
-                               _rtld_tlsdesc_handle_locked(tlsdesc, SYMLOOK_IN_PLT);
-               }
+               _rtld_tlsdesc_fill(obj, rela, where, SYMLOOK_IN_PLT);
                break;
        }
 
diff -r 975c8f7f36b9 -r 0e61f7b3261f libexec/ld.elf_so/arch/aarch64/rtld_start.S
--- a/libexec/ld.elf_so/arch/aarch64/rtld_start.S       Fri Jan 18 07:05:36 2019 +0000
+++ b/libexec/ld.elf_so/arch/aarch64/rtld_start.S       Fri Jan 18 11:59:03 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld_start.S,v 1.3 2018/09/20 18:41:05 jakllsch Exp $ */
+/* $NetBSD: rtld_start.S,v 1.4 2019/01/18 11:59:03 skrll Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
 
 #include <machine/asm.h>
 
-RCSID("$NetBSD: rtld_start.S,v 1.3 2018/09/20 18:41:05 jakllsch Exp $")
+RCSID("$NetBSD: rtld_start.S,v 1.4 2019/01/18 11:59:03 skrll Exp $")
 
 /*
  * void _rtld_start(void (*cleanup)(void), const Obj_Entry *obj,
@@ -145,47 +145,145 @@
        br      x17                     /* call bound function */
 END(_rtld_bind_start)
 
-
-ENTRY(_rtld_tlsdesc)
+/*
+ * struct rel_tlsdesc {
+ *  uint64_t resolver_fnc;
+ *  uint64_t resolver_arg;
+ *
+ *
+ * uint64_t _rtld_tlsdesc_static(struct rel_tlsdesc *);
+ *
+ * Resolver function for TLS symbols resolved at load time
+ */
+ENTRY(_rtld_tlsdesc_static)
+       .cfi_startproc
        ldr     x0, [x0, #8]
        ret
-END(_rtld_tlsdesc)
+       .cfi_endproc
+END(_rtld_tlsdesc_static)
 
 /*
- * uint64_t _rtld_tlsdesc_dynamic(struct tlsdesc *);
+ * uint64_t _rtld_tlsdesc_undef(void);
  *
- * TODO: We could lookup the saved index here to skip saving the entire stack.
+ * Resolver function for weak and undefined TLS symbols
+ */
+ENTRY(_rtld_tlsdesc_undef)
+       .cfi_startproc
+       str     x1, [sp, #-16]!
+       .cfi_adjust_cfa_offset  16
+
+       mrs     x1, tpidr_el0
+       ldr     x0, [x0, #8]
+       sub     x0, x0, x1
+
+       ldr     x1, [sp], #16
+       .cfi_adjust_cfa_offset  -16
+       .cfi_endproc
+       ret
+END(_rtld_tlsdesc_undef)
+
+/*
+ * uint64_t _rtld_tlsdesc_dynamic(struct rel_tlsdesc *);
+ *
+ * Resolver function for TLS symbols from dlopen()
  */
 ENTRY(_rtld_tlsdesc_dynamic)
-       /* Store any registers we may use in rtld_tlsdesc_handle */
-       stp     x29, x30, [sp, #-(10 * 16)]!
-       mov     x29, sp
-       stp     x1, x2,   [sp, #(1 * 16)]
-       stp     x3, x4,   [sp, #(2 * 16)]
-       stp     x5, x6,   [sp, #(3 * 16)]
-       stp     x7, x8,   [sp, #(4 * 16)]
-       stp     x9, x10,  [sp, #(5 * 16)]
-       stp     x11, x12, [sp, #(6 * 16)]
-       stp     x13, x14, [sp, #(7 * 16)]
-       stp     x15, x16, [sp, #(8 * 16)]
-       stp     x17, x18, [sp, #(9 * 16)]
+       .cfi_startproc
+
+       /* Save registers used in fast path */
+       stp     x1,  x2, [sp, #(-2 * 16)]!
+       stp     x3,  x4, [sp, #(1 * 16)]
+       .cfi_adjust_cfa_offset  2 * 16
+       .cfi_rel_offset         x1, 0
+       .cfi_rel_offset         x2, 8
+       .cfi_rel_offset         x3, 16
+       .cfi_rel_offset         x4, 24
+
+       /* Test fastpath - inlined version of __tls_get_addr. */
+
+       ldr     x1, [x0, #8]            /* tlsdesc ptr */
+       mrs     x4, tpidr_el0
+       ldr     x0, [x4]                /* DTV pointer (tcb->tcb_dtv) */
+
+       ldr     x3, [x0, #-8]           /* DTV_MAX_INDEX(dtv) */
+       ldr     x2, [x1, #0]            /* tlsdesc->td_tlsindex */
+       cmp     x2, x3
+       b.lt    1f                      /* Slow path */
+
+       ldr     x3, [x0, x2, lsl #3]    /* dtv[tlsdesc->td_tlsindex] */
+       cbz     x3, 1f
+
+       /* Return (dtv[tlsdesc->td_tlsindex] + tlsdesc->td_tlsoffs - tp) */
+       ldr     x2, [x1, #8]            /* tlsdesc->td_tlsoffs */
+       add     x2, x2, x3
+       sub     x0, x2, x4
+
+       /* Restore registers and return */
+       ldp      x3,  x4, [sp, #(1 * 16)]
+       ldp      x1,  x2, [sp], #(2 * 16)
+       .cfi_adjust_cfa_offset  -2 * 16
+       ret
+
+       /*
+        * Slow path
+        * return _rtld_tls_get_addr(tp, tlsdesc->td_tlsindex, tlsdesc->td_tlsoffs);
+        *



Home | Main Index | Thread Index | Old Index