Source-Changes-HG archive

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

[src/trunk]: src Add basic support for indirect functions. It allows providin...



details:   https://anonhg.NetBSD.org/src/rev/80faf2730043
branches:  trunk
changeset: 801967:80faf2730043
user:      joerg <joerg%NetBSD.org@localhost>
date:      Mon Aug 25 20:40:52 2014 +0000

description:
Add basic support for indirect functions. It allows providing a public
function symbol with an implementation choosen at run time.
Refactor calls to functions by address in ld.elf_so to create temporary
function descriptors on the stack, if the address is not leaked outside.

Limitations:
- no support for initialising static storage with function pointers
- no support for unnamed resolver functions

Inspired by FreeBSD's r228435 by kib%freebsd.org@localhost.

diffstat:

 distrib/sets/lists/debug/mi                               |   5 +-
 distrib/sets/lists/debug/shl.mi                           |   3 +-
 distrib/sets/lists/tests/mi                               |   4 +-
 distrib/sets/lists/tests/shl.mi                           |  12 +-
 libexec/ld.elf_so/arch/aarch64/mdreloc.c                  |  12 +-
 libexec/ld.elf_so/arch/alpha/alpha_reloc.c                |  12 +-
 libexec/ld.elf_so/arch/arm/mdreloc.c                      |  12 +-
 libexec/ld.elf_so/arch/hppa/hppa_reloc.c                  |  46 ++++++-
 libexec/ld.elf_so/arch/i386/mdreloc.c                     |  12 +-
 libexec/ld.elf_so/arch/m68k/mdreloc.c                     |  16 +-
 libexec/ld.elf_so/arch/mips/mips_reloc.c                  |  12 +-
 libexec/ld.elf_so/arch/powerpc/ppc_reloc.c                |  12 +-
 libexec/ld.elf_so/arch/sh3/mdreloc.c                      |  14 +-
 libexec/ld.elf_so/arch/sparc/mdreloc.c                    |  12 +-
 libexec/ld.elf_so/arch/sparc64/mdreloc.c                  |  12 +-
 libexec/ld.elf_so/arch/vax/mdreloc.c                      |  16 +-
 libexec/ld.elf_so/arch/x86_64/mdreloc.c                   |  15 +-
 libexec/ld.elf_so/headers.c                               |  24 +--
 libexec/ld.elf_so/reloc.c                                 |  17 ++-
 libexec/ld.elf_so/rtld.c                                  |  45 ++++--
 libexec/ld.elf_so/rtld.h                                  |  25 +++-
 sys/sys/cdefs_elf.h                                       |  14 ++-
 sys/sys/exec_elf.h                                        |   3 +-
 tests/libexec/ld.elf_so/Makefile                          |  12 +-
 tests/libexec/ld.elf_so/h_ifunc.c                         |  43 +++++++
 tests/libexec/ld.elf_so/helper_ifunc_dso/Makefile         |  19 +++
 tests/libexec/ld.elf_so/helper_ifunc_dso/h_helper_ifunc.c |  52 ++++++++
 tests/libexec/ld.elf_so/t_ifunc.c                         |  92 +++++++++++++++
 28 files changed, 473 insertions(+), 100 deletions(-)

diffs (truncated from 1149 to 300 lines):

diff -r 1b7082d354ff -r 80faf2730043 distrib/sets/lists/debug/mi
--- a/distrib/sets/lists/debug/mi       Mon Aug 25 20:34:36 2014 +0000
+++ b/distrib/sets/lists/debug/mi       Mon Aug 25 20:40:52 2014 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.84 2014/08/25 18:44:03 pooka Exp $
+# $NetBSD: mi,v 1.85 2014/08/25 20:40:52 joerg Exp $
 
 ./etc/mtree/set.debug                           comp-sys-root
 ./usr/lib/i18n/libBIG5_g.a                     comp-c-debuglib         debuglib
@@ -2131,11 +2131,13 @@
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_dl_symver_v0.debug   tests-libexec-debug     debug,atf,pic
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_dl_symver_v1.debug   tests-libexec-debug     debug,atf,pic
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_dl_symver_v2.debug   tests-libexec-debug     debug,atf,pic
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_ifunc.debug  tests-libexec-debug     debug,atf,pic
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_locking.debug        tests-libexec-debug     debug,atf,pic
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-cleared.debug        tests-libexec-debug     debug,atf,pic
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-false.debug  tests-libexec-debug     debug,atf,pic
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlinfo.debug         tests-libexec-debug     debug,atf,pic
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlvsym.debug         tests-libexec-debug     debug,atf,pic
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_ifunc.debug  tests-libexec-debug     debug,atf,pic
 ./usr/libdata/debug/usr/tests/net/bpf/t_bpf.debug              tests-net-debug         debug,atf,rump
 ./usr/libdata/debug/usr/tests/net/bpf/t_div-by-zero.debug              tests-net-debug         debug,atf,rump
 ./usr/libdata/debug/usr/tests/net/bpf/t_mbuf.debug             tests-net-debug         debug,atf,rump
@@ -2224,3 +2226,4 @@
 ./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso_g.a  comp-c-debuglib atf,debuglib
 ./usr/tests/libexec/ld.elf_so/libh_helper_dso1_g.a     comp-c-debuglib atf,debuglib
 ./usr/tests/libexec/ld.elf_so/libh_helper_dso2_g.a     comp-c-debuglib atf,debuglib
+./usr/tests/libexec/ld.elf_so/libh_helper_ifunc_dso_g.a        comp-c-debuglib atf,debuglib
diff -r 1b7082d354ff -r 80faf2730043 distrib/sets/lists/debug/shl.mi
--- a/distrib/sets/lists/debug/shl.mi   Mon Aug 25 20:34:36 2014 +0000
+++ b/distrib/sets/lists/debug/shl.mi   Mon Aug 25 20:40:52 2014 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: shl.mi,v 1.72 2014/08/25 18:44:03 pooka Exp $
+# $NetBSD: shl.mi,v 1.73 2014/08/25 20:40:52 joerg Exp $
 ./usr/libdata/debug/lib/libc.so.12.193.debug           comp-sys-debug  debug
 ./usr/libdata/debug/lib/libcrypt.so.1.0.debug          comp-sys-debug  debug
 ./usr/libdata/debug/lib/libcrypto.so.8.3.debug         comp-sys-debug  debug
@@ -287,3 +287,4 @@
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso.so.1.debug tests-libexec-debug     debug,atf
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/libh_helper_dso1.so.1.debug    tests-libexec-debug     debug,atf
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/libh_helper_dso2.so.1.debug    tests-libexec-debug     debug,atf
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/libh_helper_ifunc_dso.so.1.debug       tests-libexec-debug     debug,atf
diff -r 1b7082d354ff -r 80faf2730043 distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi       Mon Aug 25 20:34:36 2014 +0000
+++ b/distrib/sets/lists/tests/mi       Mon Aug 25 20:40:52 2014 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.589 2014/08/24 11:52:45 apb Exp $
+# $NetBSD: mi,v 1.590 2014/08/25 20:40:52 joerg Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -3068,6 +3068,7 @@
 ./usr/tests/libexec/ld.elf_so/h_helper_symver_dso0     tests-libexec-tests     atf
 ./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1     tests-libexec-tests     atf
 ./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2     tests-libexec-tests     atf
+./usr/tests/libexec/ld.elf_so/h_ifunc          tests-libexec-tests     atf,pic
 ./usr/tests/libexec/ld.elf_so/h_locking                tests-libexec-tests     atf,pic
 ./usr/tests/libexec/ld.elf_so/t_df_1_noopen    tests-libexec-tests     atf,pic
 ./usr/tests/libexec/ld.elf_so/t_dl_symver      tests-libexec-tests     atf,pic
@@ -3075,6 +3076,7 @@
 ./usr/tests/libexec/ld.elf_so/t_dlerror-false  tests-libexec-tests     atf,pic
 ./usr/tests/libexec/ld.elf_so/t_dlinfo         tests-libexec-tests     atf,pic
 ./usr/tests/libexec/ld.elf_so/t_dlvsym         tests-libexec-tests     atf,pic
+./usr/tests/libexec/ld.elf_so/t_ifunc          tests-libexec-tests     atf,pic
 ./usr/tests/modules                            tests-sys-tests
 ./usr/tests/net                                        tests-net-tests
 ./usr/tests/net/Atffile                                tests-net-tests         atf
diff -r 1b7082d354ff -r 80faf2730043 distrib/sets/lists/tests/shl.mi
--- a/distrib/sets/lists/tests/shl.mi   Mon Aug 25 20:34:36 2014 +0000
+++ b/distrib/sets/lists/tests/shl.mi   Mon Aug 25 20:40:52 2014 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: shl.mi,v 1.8 2013/08/11 22:29:03 joerg Exp $
+# $NetBSD: shl.mi,v 1.9 2014/08/25 20:40:52 joerg Exp $
 #
 ./usr/tests/lib/csu/h_initfini3_dso.so         tests-lib-tests         atf
 ./usr/tests/lib/csu/h_initfini3_dso.so.1       tests-lib-tests         atf
@@ -16,9 +16,11 @@
 ./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1/libh_helper_symver_dso.so.1 tests-libexec-tests     atf
 ./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso.so   tests-libexec-tests     atf
 ./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso.so.1 tests-libexec-tests     atf
-./usr/tests/libexec/ld.elf_so/libh_helper_dso1.so      tests-libexec-tests     atf
-./usr/tests/libexec/ld.elf_so/libh_helper_dso1.so.1    tests-libexec-tests     atf
-./usr/tests/libexec/ld.elf_so/libh_helper_dso2.so      tests-libexec-tests     atf
-./usr/tests/libexec/ld.elf_so/libh_helper_dso2.so.1    tests-libexec-tests     atf
+./usr/tests/libexec/ld.elf_so/libh_helper_dso1.so                              tests-libexec-tests     atf
+./usr/tests/libexec/ld.elf_so/libh_helper_dso1.so.1                            tests-libexec-tests     atf
+./usr/tests/libexec/ld.elf_so/libh_helper_dso2.so                              tests-libexec-tests     atf
+./usr/tests/libexec/ld.elf_so/libh_helper_dso2.so.1                            tests-libexec-tests     atf
+./usr/tests/libexec/ld.elf_so/libh_helper_ifunc_dso.so                         tests-libexec-tests     atf
+./usr/tests/libexec/ld.elf_so/libh_helper_ifunc_dso.so.1                       tests-libexec-tests     atf
 ./usr/tests/util/id/libfake.so.0               tests-obsolete          obsolete
 ./usr/tests/util/id/libfake.so.0.0             tests-obsolete          obsolete
diff -r 1b7082d354ff -r 80faf2730043 libexec/ld.elf_so/arch/aarch64/mdreloc.c
--- a/libexec/ld.elf_so/arch/aarch64/mdreloc.c  Mon Aug 25 20:34:36 2014 +0000
+++ b/libexec/ld.elf_so/arch/aarch64/mdreloc.c  Mon Aug 25 20:40:52 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mdreloc.c,v 1.1 2014/08/10 05:47:37 matt Exp $ */
+/* $NetBSD: mdreloc.c,v 1.2 2014/08/25 20:40:52 joerg Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.1 2014/08/10 05:47:37 matt Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.2 2014/08/25 20:40:52 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -222,7 +222,13 @@
        if (__predict_false(def == &_rtld_sym_zero))
                return 0;
 
-       new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+       if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+               if (tp == NULL)
+                       return 0;
+               new_value = _rtld_resolve_ifunc(defobj, def);
+       } else {
+               new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+       }
        rdbg(("bind now/fixup in %s --> old=%p new=%p",
            defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
        if (*where != new_value)
diff -r 1b7082d354ff -r 80faf2730043 libexec/ld.elf_so/arch/alpha/alpha_reloc.c
--- a/libexec/ld.elf_so/arch/alpha/alpha_reloc.c        Mon Aug 25 20:34:36 2014 +0000
+++ b/libexec/ld.elf_so/arch/alpha/alpha_reloc.c        Mon Aug 25 20:40:52 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: alpha_reloc.c,v 1.40 2011/03/31 15:30:31 skrll Exp $   */
+/*     $NetBSD: alpha_reloc.c,v 1.41 2014/08/25 20:40:52 joerg Exp $   */
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -62,7 +62,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: alpha_reloc.c,v 1.40 2011/03/31 15:30:31 skrll Exp $");
+__RCSID("$NetBSD: alpha_reloc.c,v 1.41 2014/08/25 20:40:52 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -376,7 +376,13 @@
        if (__predict_false(def == &_rtld_sym_zero))
                return 0;
 
-       new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+       if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+               if (tp == NULL)
+                       return 0;
+               new_value = _rtld_resolve_ifunc(defobj, def);
+       } else {
+               new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+       }
        rdbg(("bind now/fixup in %s --> old=%p new=%p",
            defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
 
diff -r 1b7082d354ff -r 80faf2730043 libexec/ld.elf_so/arch/arm/mdreloc.c
--- a/libexec/ld.elf_so/arch/arm/mdreloc.c      Mon Aug 25 20:34:36 2014 +0000
+++ b/libexec/ld.elf_so/arch/arm/mdreloc.c      Mon Aug 25 20:40:52 2014 +0000
@@ -1,8 +1,8 @@
-/*     $NetBSD: mdreloc.c,v 1.37 2011/11/18 16:10:03 joerg Exp $       */
+/*     $NetBSD: mdreloc.c,v 1.38 2014/08/25 20:40:52 joerg Exp $       */
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.37 2011/11/18 16:10:03 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.38 2014/08/25 20:40:52 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -286,7 +286,13 @@
        if (__predict_false(def == &_rtld_sym_zero))
                return 0;
 
-       new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+       if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+               if (tp == NULL)
+                       return 0;
+               new_value = _rtld_resolve_ifunc(defobj, def);
+       } else {
+               new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
+       }
        /* Set the Thumb bit, if needed.  */
        if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC)
                new_value |= 1;
diff -r 1b7082d354ff -r 80faf2730043 libexec/ld.elf_so/arch/hppa/hppa_reloc.c
--- a/libexec/ld.elf_so/arch/hppa/hppa_reloc.c  Mon Aug 25 20:34:36 2014 +0000
+++ b/libexec/ld.elf_so/arch/hppa/hppa_reloc.c  Mon Aug 25 20:40:52 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: hppa_reloc.c,v 1.42 2012/01/06 10:38:57 skrll Exp $    */
+/*     $NetBSD: hppa_reloc.c,v 1.43 2014/08/25 20:40:52 joerg Exp $    */
 
 /*-
  * Copyright (c) 2002, 2004 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: hppa_reloc.c,v 1.42 2012/01/06 10:38:57 skrll Exp $");
+__RCSID("$NetBSD: hppa_reloc.c,v 1.43 2014/08/25 20:40:52 joerg Exp $");
 #endif /* not lint */
 
 #include <stdlib.h>
@@ -656,9 +656,19 @@
                if (__predict_false(def == &_rtld_sym_zero))
                        return 0;
 
-               func_pc = (Elf_Addr)(defobj->relocbase + def->st_value +
-                   rela->r_addend);
-               func_sl = (Elf_Addr)(defobj->pltgot);
+               if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+                       if (tp == NULL)
+                               return 0;
+                       Elf_Addr ptr = _rtld_resolve_ifunc(defobj, def);
+                       assert(RTLD_IS_PLABEL(ptr));
+                       hppa_plabel *label = RTLD_GET_PLABEL(ptr);
+                       func_pc = label->hppa_plabel_pc;
+                       func_sl = label->hppa_plabel_sl;
+               } else {
+                       func_pc = (Elf_Addr)(defobj->relocbase + def->st_value +
+                           rela->r_addend);
+                       func_sl = (Elf_Addr)(defobj->pltgot);
+               }
 
                rdbg(("bind now/fixup in %s --> old=(%p,%p) new=(%p,%p)",
                    defobj->strtab + def->st_name,
@@ -710,3 +720,29 @@
        }
        return 0;
 }
+
+void
+_rtld_call_function_void(const Obj_Entry *obj, Elf_Addr ptr)
+{
+       volatile hppa_plabel plabel;
+       void (*f)(void);
+
+       plabel.hppa_plabel_pc = (Elf_Addr)ptr;
+       plabel.hppa_plabel_sl = (Elf_Addr)(obj->pltgot);
+       f = (void (*)(void))RTLD_MAKE_PLABEL(&plabel);
+
+       f();
+}
+
+Elf_Addr
+_rtld_call_function_addr(const Obj_Entry *obj, Elf_Addr ptr)
+{
+       volatile hppa_plabel plabel;
+       Elf_Addr (*f)(void);
+
+       plabel.hppa_plabel_pc = (Elf_Addr)ptr;
+       plabel.hppa_plabel_sl = (Elf_Addr)(obj->pltgot);
+       f = (Elf_Addr (*)(void))RTLD_MAKE_PLABEL(&plabel);
+
+       return f();
+}
diff -r 1b7082d354ff -r 80faf2730043 libexec/ld.elf_so/arch/i386/mdreloc.c
--- a/libexec/ld.elf_so/arch/i386/mdreloc.c     Mon Aug 25 20:34:36 2014 +0000
+++ b/libexec/ld.elf_so/arch/i386/mdreloc.c     Mon Aug 25 20:40:52 2014 +0000
@@ -1,8 +1,8 @@
-/*     $NetBSD: mdreloc.c,v 1.35 2012/11/07 07:24:46 apb Exp $ */
+/*     $NetBSD: mdreloc.c,v 1.36 2014/08/25 20:40:52 joerg Exp $       */
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.35 2012/11/07 07:24:46 apb Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.36 2014/08/25 20:40:52 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -230,6 +230,14 @@
        if (__predict_false(def == &_rtld_sym_zero))
                return 0;
 
+       if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+               if (tp == NULL)
+                       return 0;
+               target = _rtld_resolve_ifunc(defobj, def);
+       } else {
+               target = (Elf_Addr)(defobj->relocbase + def->st_value);
+       }
+
        target = (Elf_Addr)(defobj->relocbase + def->st_value);
        rdbg(("bind now/fixup in %s --> old=%p new=%p",
            defobj->strtab + def->st_name, (void *)*where, 
diff -r 1b7082d354ff -r 80faf2730043 libexec/ld.elf_so/arch/m68k/mdreloc.c
--- a/libexec/ld.elf_so/arch/m68k/mdreloc.c     Mon Aug 25 20:34:36 2014 +0000
+++ b/libexec/ld.elf_so/arch/m68k/mdreloc.c     Mon Aug 25 20:40:52 2014 +0000
@@ -1,13 +1,13 @@
-/*     $NetBSD: mdreloc.c,v 1.29 2011/11/22 15:25:28 joerg Exp $       */
+/*     $NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:52 joerg Exp $       */
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.29 2011/11/22 15:25:28 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:52 joerg Exp $");
 #endif /* not lint */
 



Home | Main Index | Thread Index | Old Index