Source-Changes-HG archive

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

[src/trunk]: src Add sparc/sparc64 support for irelative relocations.



details:   https://anonhg.NetBSD.org/src/rev/6543a86133cf
branches:  trunk
changeset: 826046:6543a86133cf
user:      joerg <joerg%NetBSD.org@localhost>
date:      Sat Aug 12 09:03:27 2017 +0000

description:
Add sparc/sparc64 support for irelative relocations.

diffstat:

 libexec/ld.elf_so/arch/sparc/mdreloc.c                    |  105 ++++++++--
 libexec/ld.elf_so/arch/sparc64/mdreloc.c                  |  138 +++++++++----
 libexec/ld.elf_so/rtld.c                                  |   10 +-
 libexec/ld.elf_so/rtld.h                                  |    6 +-
 sys/arch/sparc/include/elf_machdep.h                      |    5 +-
 sys/arch/sparc64/include/elf_machdep.h                    |    5 +-
 tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c |    7 +
 tests/libexec/ld.elf_so/t_ifunc.c                         |   14 +-
 8 files changed, 217 insertions(+), 73 deletions(-)

diffs (truncated from 523 to 300 lines):

diff -r 0c6b8e55080e -r 6543a86133cf libexec/ld.elf_so/arch/sparc/mdreloc.c
--- a/libexec/ld.elf_so/arch/sparc/mdreloc.c    Sat Aug 12 08:45:58 2017 +0000
+++ b/libexec/ld.elf_so/arch/sparc/mdreloc.c    Sat Aug 12 09:03:27 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mdreloc.c,v 1.51 2017/08/10 19:03:26 joerg Exp $       */
+/*     $NetBSD: mdreloc.c,v 1.52 2017/08/12 09:03:27 joerg Exp $       */
 
 /*-
  * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.51 2017/08/10 19:03:26 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.52 2017/08/12 09:03:27 joerg Exp $");
 #endif /* not lint */
 
 #include <errno.h>
@@ -220,6 +220,13 @@
                if (type == R_TYPE(JMP_SLOT))
                        continue;
 
+               /* IFUNC relocations are handled in _rtld_call_ifunc */
+               if (type == R_TYPE(IRELATIVE)) {
+                       if (obj->ifunc_remaining_nonplt == 0)
+                               obj->ifunc_remaining_nonplt = rela - obj->rela + 1;
+                       continue;
+               }
+
                /* COPY relocs are also handled elsewhere */
                if (type == R_TYPE(COPY))
                        continue;
@@ -387,7 +394,74 @@
 int
 _rtld_relocate_plt_lazy(Obj_Entry *obj)
 {
-       return (0);
+       const Elf_Rela *rela;
+
+       if (!obj->relocbase)
+               return 0;
+
+       for (rela = obj->pltrelalim; rela-- > obj->pltrela; ) {
+               if (ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_IREL))
+                       obj->ifunc_remaining = obj->pltrelalim - rela + 1;
+       }
+
+       return 0;
+}
+
+static inline void
+_rtld_write_plt(Elf_Word *where, Elf_Addr value)
+{
+       /*
+        * At the PLT entry pointed at by `where', we now construct
+        * a direct transfer to the now fully resolved function
+        * address.  The resulting code in the jump slot is:
+        *
+        *      sethi   %hi(roffset), %g1
+        *      sethi   %hi(addr), %g1
+        *      jmp     %g1+%lo(addr)
+        *
+        * We write the third instruction first, since that leaves the
+        * previous `b,a' at the second word in place. Hence the whole
+        * PLT slot can be atomically change to the new sequence by
+        * writing the `sethi' instruction at word 2.
+        */
+       const uint32_t SETHI = 0x03000000U;
+       const uint32_t JMP = 0x81c06000U;
+       where[2] = JMP   | (value & 0x000003ff);
+       where[1] = SETHI | ((value >> 10) & 0x003fffff);
+       __asm volatile("iflush %0+8" : : "r" (where));
+       __asm volatile("iflush %0+4" : : "r" (where));
+}
+
+void
+_rtld_call_ifunc(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
+{
+       const Elf_Rela *rela;
+       Elf_Addr *where, target;
+
+       while (obj->ifunc_remaining > 0 && _rtld_objgen == cur_objgen) {
+               rela = obj->pltrelalim - --obj->ifunc_remaining;
+               if (ELF_R_TYPE(rela->r_info) != R_TYPE(JMP_IREL))
+                       continue;
+               where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+               target = (Elf_Addr)(obj->relocbase + rela->r_addend);
+               _rtld_exclusive_exit(mask);
+               target = _rtld_resolve_ifunc2(obj, target);
+               _rtld_exclusive_enter(mask);
+               _rtld_write_plt(where, target);
+       }
+
+       while (obj->ifunc_remaining_nonplt > 0 && _rtld_objgen == cur_objgen) {
+               rela = obj->relalim - --obj->ifunc_remaining_nonplt;
+               if (ELF_R_TYPE(rela->r_info) != R_TYPE(IRELATIVE))
+                       continue;
+               where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+               target = (Elf_Addr)(obj->relocbase + rela->r_addend);
+               _rtld_exclusive_exit(mask);
+               target = _rtld_resolve_ifunc2(obj, target);
+               _rtld_exclusive_enter(mask);
+               if (*where != target)
+                       *where = target;
+       }
 }
 
 caddr_t
@@ -429,6 +503,9 @@
        Elf_Addr value;
        unsigned long info = rela->r_info;
 
+       if (ELF_R_TYPE(info) == R_TYPE(JMP_IREL))
+               return 0;
+
        assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
 
        def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
@@ -447,27 +524,7 @@
        rdbg(("bind now/fixup in %s --> new=%p", 
            defobj->strtab + def->st_name, (void *)value));
 
-       /*
-        * At the PLT entry pointed at by `where', we now construct
-        * a direct transfer to the now fully resolved function
-        * address.  The resulting code in the jump slot is:
-        *
-        *      sethi   %hi(roffset), %g1
-        *      sethi   %hi(addr), %g1
-        *      jmp     %g1+%lo(addr)
-        *
-        * We write the third instruction first, since that leaves the
-        * previous `b,a' at the second word in place. Hence the whole
-        * PLT slot can be atomically change to the new sequence by
-        * writing the `sethi' instruction at word 2.
-        */
-#define SETHI  0x03000000
-#define JMP    0x81c06000
-#define NOP    0x01000000
-       where[2] = JMP   | (value & 0x000003ff);
-       where[1] = SETHI | ((value >> 10) & 0x003fffff);
-       __asm volatile("iflush %0+8" : : "r" (where));
-       __asm volatile("iflush %0+4" : : "r" (where));
+       _rtld_write_plt(where, value);
 
        if (tp)
                *tp = value;
diff -r 0c6b8e55080e -r 6543a86133cf libexec/ld.elf_so/arch/sparc64/mdreloc.c
--- a/libexec/ld.elf_so/arch/sparc64/mdreloc.c  Sat Aug 12 08:45:58 2017 +0000
+++ b/libexec/ld.elf_so/arch/sparc64/mdreloc.c  Sat Aug 12 09:03:27 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mdreloc.c,v 1.64 2017/08/10 19:03:26 joerg Exp $       */
+/*     $NetBSD: mdreloc.c,v 1.65 2017/08/12 09:03:27 joerg Exp $       */
 
 /*-
  * Copyright (c) 2000 Eduardo Horvath.
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.64 2017/08/10 19:03:26 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.65 2017/08/12 09:03:27 joerg Exp $");
 #endif /* not lint */
 
 #include <errno.h>
@@ -332,6 +332,13 @@
                if (type == R_TYPE(JMP_SLOT))
                        continue;
 
+               /* IFUNC relocations are handled in _rtld_call_ifunc */
+               if (type == R_TYPE(IRELATIVE)) {
+                       if (obj->ifunc_remaining_nonplt == 0)
+                               obj->ifunc_remaining_nonplt = rela - obj->rela + 1;
+                       continue;
+               }
+
                /* COPY relocs are also handled elsewhere */
                if (type == R_TYPE(COPY))
                        continue;
@@ -507,7 +514,17 @@
 int
 _rtld_relocate_plt_lazy(Obj_Entry *obj)
 {
-       return (0);
+       const Elf_Rela *rela;
+
+       if (!obj->relocbase)
+               return 0;
+
+       for (rela = obj->pltrelalim; rela-- > obj->pltrela; ) {
+               if (ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_IREL))
+                       obj->ifunc_remaining = obj->pltrelalim - rela + 1;
+       }
+
+       return 0;
 }
 
 caddr_t
@@ -568,37 +585,11 @@
        return 0;
 }
 
-/*
- * New inline function that is called by _rtld_relocate_plt_object and
- * _rtld_bind
- */
-static inline int
-_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
-    Elf_Addr *tp)
+static inline void
+_rtld_write_plt(Elf_Word *where, Elf_Addr value, const Elf_Rela *rela,
+    const Obj_Entry *obj)
 {
-       Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
-       const Elf_Sym *def;
-       const Obj_Entry *defobj;
-       Elf_Addr value, offset, offBAA;
-       unsigned long info = rela->r_info;
-
-       assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
-
-       def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
-       if (__predict_false(def == NULL))
-               return -1;
-       if (__predict_false(def == &_rtld_sym_zero))
-               return 0;
-
-       if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
-               if (tp == NULL)
-                       return 0;
-               value = _rtld_resolve_ifunc(defobj, def);
-       } else {
-               value = (Elf_Addr)(defobj->relocbase + def->st_value);
-       }
-       rdbg(("bind now/fixup in %s at %p --> new=%p", 
-           defobj->strtab + def->st_name, (void*)where, (void *)value));
+       Elf_Addr offset, offBAA;
 
        /*
         * At the PLT entry pointed at by `where', we now construct a direct
@@ -625,8 +616,8 @@
         */
 
        offset = ((Elf_Addr)where) - value;
-       offBAA = value - (((Elf_Addr)where) +4);        /* ba,a at where[1] */
-       if (rela->r_addend) {
+       offBAA = value - (((Elf_Addr)where) + 4);       /* ba,a at where[1] */
+       if (rela && rela->r_addend) {
                Elf_Addr *ptr = (Elf_Addr *)where;
                /*
                 * This entry is >= 32768.  The relocations points to a
@@ -634,7 +625,6 @@
                 * PLT section.  Update it to point to the target function.
                 */
                ptr[0] += value - (Elf_Addr)obj->pltgot;
-
        } else if (offBAA <= (1L<<20) && (Elf_SOff)offBAA >= -(1L<<20)) {
                /* 
                 * We're within 1MB -- we can use a direct branch insn.
@@ -673,7 +663,6 @@
                where[1] = SETHI | HIVAL(value, 10);
                __asm volatile("iflush %0+8" : : "r" (where));
                __asm volatile("iflush %0+4" : : "r" (where));
-
        } else if ((Elf_SOff)value <= 0 && (Elf_SOff)value > -(1L<<32)) {
                /* 
                 * We're within 32-bits of address -1.
@@ -696,7 +685,6 @@
                __asm volatile("iflush %0+12" : : "r" (where));
                __asm volatile("iflush %0+8" : : "r" (where));
                __asm volatile("iflush %0+4" : : "r" (where));
-
        } else if ((offset+8) <= (1L<<31) &&
            (Elf_SOff)(offset+8) >= -((1L<<31) - 4)) {
                /* 
@@ -721,7 +709,6 @@
                __asm volatile("iflush %0+12" : : "r" (where));
                __asm volatile("iflush %0+8" : : "r" (where));
                __asm volatile("iflush %0+4" : : "r" (where));
-
        } else if ((Elf_SOff)value > 0 && value < (1L<<44)) {
                /* 
                 * We're within 44 bits.  We can generate this pattern:
@@ -746,7 +733,6 @@
                __asm volatile("iflush %0+12" : : "r" (where));
                __asm volatile("iflush %0+8" : : "r" (where));
                __asm volatile("iflush %0+4" : : "r" (where));
-
        } else if ((Elf_SOff)value < 0 && (Elf_SOff)value > -(1L<<44)) {
                /*
                 *  We're within 44 bits.  We can generate this pattern:
@@ -774,7 +760,6 @@
                __asm volatile("iflush %0+12" : : "r" (where));
                __asm volatile("iflush %0+8" : : "r" (where));
                __asm volatile("iflush %0+4" : : "r" (where));
-
        } else {
                /* 
                 * We need to load all 64-bits
@@ -803,11 +788,82 @@



Home | Main Index | Thread Index | Old Index