Pullup from HEAD: Add .init_array/.fini_array support (conditionalized on HAVE_INITFINI_ARRAY).diff -r1.110 -r1.110.6.1 src/libexec/ld.elf_so/Makefile
(matt)
--- src/libexec/ld.elf_so/Makefile 2011/10/07 09:15:21 1.110
+++ src/libexec/ld.elf_so/Makefile 2013/01/22 21:47:27 1.110.6.1
@@ -1,146 +1,146 @@ | @@ -1,146 +1,146 @@ | |||
1 | # $NetBSD: Makefile,v 1.110 2011/10/07 09:15:21 mrg Exp $ | 1 | # $NetBSD: Makefile,v 1.110.6.1 2013/01/22 21:47:27 matt Exp $ | |
2 | # | 2 | # | |
3 | # NOTE: when changing ld.so, ensure that ldd still compiles. | 3 | # NOTE: when changing ld.so, ensure that ldd still compiles. | |
4 | # | 4 | # | |
5 | 5 | |||
6 | WARNS?=4 | 6 | WARNS?=4 | |
7 | 7 | |||
8 | # This needs to be before bsd.init.mk | 8 | # This needs to be before bsd.init.mk | |
9 | .if defined(BSD_MK_COMPAT_FILE) | 9 | .if defined(BSD_MK_COMPAT_FILE) | |
10 | .include <${BSD_MK_COMPAT_FILE}> | 10 | .include <${BSD_MK_COMPAT_FILE}> | |
11 | .endif | 11 | .endif | |
12 | 12 | |||
13 | # We are not building this with PIE | 13 | # We are not building this with PIE | |
14 | PIE_CFLAGS= | 14 | PIE_CFLAGS= | |
15 | PIE_LDFLAGS= | 15 | PIE_LDFLAGS= | |
16 | .include <bsd.init.mk> # for MKPIC definition | 16 | .include <bsd.init.mk> # for MKPIC definition | |
17 | .include <bsd.shlib.mk> # for SHLINKINSTALLDIR definition | 17 | .include <bsd.shlib.mk> # for SHLINKINSTALLDIR definition | |
18 | 18 | |||
19 | .if defined(LDELFSO_MACHINE_CPU) && !empty(LDELFSO_MACHINE_CPU) && \ | 19 | .if defined(LDELFSO_MACHINE_CPU) && !empty(LDELFSO_MACHINE_CPU) && \ | |
20 | exists(${.CURDIR}/arch/${LDELFSO_MACHINE_CPU}) | 20 | exists(${.CURDIR}/arch/${LDELFSO_MACHINE_CPU}) | |
21 | ARCHSUBDIR= ${LDELFSO_MACHINE_CPU} | 21 | ARCHSUBDIR= ${LDELFSO_MACHINE_CPU} | |
22 | .else | 22 | .else | |
23 | ARCHSUBDIR= ${MACHINE_CPU} | 23 | ARCHSUBDIR= ${MACHINE_CPU} | |
24 | .endif | 24 | .endif | |
25 | M= ${.CURDIR}/arch/${ARCHSUBDIR} | 25 | M= ${.CURDIR}/arch/${ARCHSUBDIR} | |
26 | 26 | |||
27 | .if ((${MACHINE_ARCH} == "alpha") || \ | 27 | .if ((${MACHINE_ARCH} == "alpha") || \ | |
28 | (${MACHINE_CPU} == "arm") || \ | 28 | (${MACHINE_CPU} == "arm") || \ | |
29 | (${MACHINE_ARCH} == "hppa") || \ | 29 | (${MACHINE_ARCH} == "hppa") || \ | |
30 | (${MACHINE_ARCH} == "i386") || \ | 30 | (${MACHINE_ARCH} == "i386") || \ | |
31 | (${MACHINE_ARCH} == "m68k") || \ | 31 | (${MACHINE_ARCH} == "m68k") || \ | |
32 | (${MACHINE_CPU} == "mips") || \ | 32 | (${MACHINE_CPU} == "mips") || \ | |
33 | (${MACHINE_ARCH} == "powerpc") || \ | 33 | (${MACHINE_ARCH} == "powerpc") || \ | |
34 | (${MACHINE_CPU} == "sh3") || \ | 34 | (${MACHINE_CPU} == "sh3") || \ | |
35 | (${MACHINE_ARCH} == "sparc") || \ | 35 | (${MACHINE_ARCH} == "sparc") || \ | |
36 | (${MACHINE_ARCH} == "sparc64") || \ | 36 | (${MACHINE_ARCH} == "sparc64") || \ | |
37 | (${MACHINE_ARCH} == "x86_64") || \ | 37 | (${MACHINE_ARCH} == "x86_64") || \ | |
38 | (${MACHINE_ARCH} == "vax")) && \ | 38 | (${MACHINE_ARCH} == "vax")) && \ | |
39 | ${MKPIC} != "no" | 39 | ${MKPIC} != "no" | |
40 | 40 | |||
41 | LDFLAGS+= ${${ACTIVE_CC} == "clang":? -Wl,-Bsymbolic : -symbolic} \ | 41 | LDFLAGS+= ${${ACTIVE_CC} == "clang":? -Wl,-Bsymbolic : -symbolic} \ | |
42 | -shared -nostartfiles -nodefaultlibs | 42 | -shared -nostartfiles -nodefaultlibs | |
43 | LDFLAGS+= -Wl,-static | 43 | LDFLAGS+= -Wl,-static | |
44 | LDFLAGS+= -Wl,--warn-shared-textrel | 44 | LDFLAGS+= -Wl,--warn-shared-textrel | |
45 | 45 | |||
46 | CFLAGS+= -fvisibility=hidden | 46 | COPTS+= -fvisibility=hidden | |
47 | 47 | |||
48 | # Adds SRCS, CPPFLAGS, LDFLAGS, etc. Must go first so MD startup source | 48 | # Adds SRCS, CPPFLAGS, LDFLAGS, etc. Must go first so MD startup source | |
49 | # is first. | 49 | # is first. | |
50 | .if exists($M/Makefile.inc) | 50 | .if exists($M/Makefile.inc) | |
51 | .include "$M/Makefile.inc" | 51 | .include "$M/Makefile.inc" | |
52 | .endif | 52 | .endif | |
53 | 53 | |||
54 | # Support compat ld.elf_so. | 54 | # Support compat ld.elf_so. | |
55 | .if defined(MLIBDIR) | 55 | .if defined(MLIBDIR) | |
56 | PROG= ld.elf_so-${MLIBDIR} | 56 | PROG= ld.elf_so-${MLIBDIR} | |
57 | CPPFLAGS+= -DRTLD_ARCH_SUBDIR=\"${MLIBDIR}\" | 57 | CPPFLAGS+= -DRTLD_ARCH_SUBDIR=\"${MLIBDIR}\" | |
58 | .else | 58 | .else | |
59 | PROG= ld.elf_so | 59 | PROG= ld.elf_so | |
60 | .endif | 60 | .endif | |
61 | 61 | |||
62 | CLIBOBJ!= cd ${NETBSDSRCDIR}/lib/libc && ${PRINTOBJDIR} | 62 | CLIBOBJ!= cd ${NETBSDSRCDIR}/lib/libc && ${PRINTOBJDIR} | |
63 | 63 | |||
64 | SRCS+= rtld.c reloc.c symbol.c xmalloc.c xprintf.c debug.c \ | 64 | SRCS+= rtld.c reloc.c symbol.c xmalloc.c xprintf.c debug.c \ | |
65 | map_object.c load.c search.c headers.c paths.c expand.c \ | 65 | map_object.c load.c search.c headers.c paths.c expand.c \ | |
66 | tls.c symver.c | 66 | tls.c symver.c | |
67 | 67 | |||
68 | .if ${USE_FORT} == "yes" | 68 | .if ${USE_FORT} == "yes" | |
69 | .PATH.c: ${NETBSDSRCDIR}/lib/libc/misc | 69 | .PATH.c: ${NETBSDSRCDIR}/lib/libc/misc | |
70 | SRCS+= stack_protector.c | 70 | SRCS+= stack_protector.c | |
71 | .endif | 71 | .endif | |
72 | 72 | |||
73 | .PATH.c: ${NETBSDSRCDIR}/lib/libc/stdlib | 73 | .PATH.c: ${NETBSDSRCDIR}/lib/libc/stdlib | |
74 | SRCS+= exit.c | 74 | SRCS+= exit.c | |
75 | 75 | |||
76 | errlist_concat.h: ${NETBSDSRCDIR}/lib/libc/gen/errlist.awk ${NETBSDSRCDIR}/sys/sys/errno.h | 76 | errlist_concat.h: ${NETBSDSRCDIR}/lib/libc/gen/errlist.awk ${NETBSDSRCDIR}/sys/sys/errno.h | |
77 | ${TOOL_AWK} -v concat=1 -f ${.ALLSRC} > ${.TARGET}.tmp && \ | 77 | ${TOOL_AWK} -v concat=1 -f ${.ALLSRC} > ${.TARGET}.tmp && \ | |
78 | mv -f ${.TARGET}.tmp ${.TARGET} | 78 | mv -f ${.TARGET}.tmp ${.TARGET} | |
79 | 79 | |||
80 | xprintf.c: errlist_concat.h | 80 | xprintf.c: errlist_concat.h | |
81 | 81 | |||
82 | CLEANFILES+= errlist_concat.h | 82 | CLEANFILES+= errlist_concat.h | |
83 | 83 | |||
84 | BINDIR= ${SHLINKINSTALLDIR} | 84 | BINDIR= ${SHLINKINSTALLDIR} | |
85 | 85 | |||
86 | CPPFLAGS+= -DLIBDIR=\"${LIBDIR}\" -D_PATH_RTLD=\"${BINDIR}/${PROG}\" | 86 | CPPFLAGS+= -DLIBDIR=\"${LIBDIR}\" -D_PATH_RTLD=\"${BINDIR}/${PROG}\" | |
87 | CPPFLAGS+= -I${.CURDIR} -I. | 87 | CPPFLAGS+= -I${.CURDIR} -I. | |
88 | CPPFLAGS+= -DRTLD_LOADER | 88 | CPPFLAGS+= -DRTLD_LOADER | |
89 | CPPFLAGS+= -D_RTLD_SOURCE | 89 | CPPFLAGS+= -D_RTLD_SOURCE | |
90 | CPPFLAGS+= -DCOMBRELOC | 90 | CPPFLAGS+= -DCOMBRELOC | |
91 | #CPPFLAGS+= -DDEBUG | 91 | #CPPFLAGS+= -DDEBUG | |
92 | #CPPFLAGS+= -DRTLD_DEBUG | 92 | #CPPFLAGS+= -DRTLD_DEBUG | |
93 | #CPPFLAGS+= -DRTLD_DEBUG_RELOC | 93 | #CPPFLAGS+= -DRTLD_DEBUG_RELOC | |
94 | #DBG= -g | 94 | #DBG= -g | |
95 | DBG= -O3 -fomit-frame-pointer | 95 | COPTS= -O3 -fomit-frame-pointer | |
96 | 96 | |||
97 | .if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "x86_64" | 97 | .if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "x86_64" | |
98 | DBG+= -mno-3dnow -mno-mmx -mno-sse -mno-sse2 -mno-sse3 | 98 | COPTS+= -mno-3dnow -mno-mmx -mno-sse -mno-sse2 -mno-sse3 | |
99 | .endif | 99 | .endif | |
100 | 100 | |||
101 | 101 | |||
102 | .if ${SHLIBDIR} != ${LIBDIR} | 102 | .if ${SHLIBDIR} != ${LIBDIR} | |
103 | CPPFLAGS+= -DRTLD_DEFAULT_LIBRARY_PATH=\"${SHLIBDIR}:${LIBDIR}\" | 103 | CPPFLAGS+= -DRTLD_DEFAULT_LIBRARY_PATH=\"${SHLIBDIR}:${LIBDIR}\" | |
104 | .endif | 104 | .endif | |
105 | 105 | |||
106 | # rtld.c and symbol.c use alloca, so disable SSP warnings. | 106 | # rtld.c and symbol.c use alloca, so disable SSP warnings. | |
107 | COPTS.rtld.c+= -Wno-stack-protector | 107 | COPTS.rtld.c+= -Wno-stack-protector | |
108 | COPTS.symbol.c+=-Wno-stack-protector | 108 | COPTS.symbol.c+=-Wno-stack-protector | |
109 | 109 | |||
110 | LDADD+= -L${CLIBOBJ} -L${DESTDIR}${LIBDIR} | 110 | LDADD+= -L${CLIBOBJ} -L${DESTDIR}${LIBDIR} | |
111 | .if ${MKPICLIB} != "no" | 111 | .if ${MKPICLIB} != "no" | |
112 | LDADD+= -lc_pic | 112 | LDADD+= -lc_pic | |
113 | .if ${MKPICINSTALL} != "no" | 113 | .if ${MKPICINSTALL} != "no" | |
114 | DPADD+= ${LIBC_PIC} | 114 | DPADD+= ${LIBC_PIC} | |
115 | .endif | 115 | .endif | |
116 | DPADD+= ${CLIBOBJ}/libc_pic.a | 116 | DPADD+= ${CLIBOBJ}/libc_pic.a | |
117 | .else | 117 | .else | |
118 | LDADD+= -lc | 118 | LDADD+= -lc | |
119 | DPADD+= ${CLIBOBJ}/libc.a | 119 | DPADD+= ${CLIBOBJ}/libc.a | |
120 | .endif | 120 | .endif | |
121 | 121 | |||
122 | .if ${MACHINE_CPU} == "hppa" || ${MACHINE_CPU} == "sh3" | 122 | .if ${MACHINE_CPU} == "hppa" || ${MACHINE_CPU} == "sh3" | |
123 | # for $$divU, $$remU etc. (millicode) | 123 | # for $$divU, $$remU etc. (millicode) | |
124 | LDADD+= -lgcc | 124 | LDADD+= -lgcc | |
125 | DPADD+= ${LIBGCC} | 125 | DPADD+= ${LIBGCC} | |
126 | .endif | 126 | .endif | |
127 | 127 | |||
128 | STRIPFLAG= | 128 | STRIPFLAG= | |
129 | 129 | |||
130 | .PATH: $M | 130 | .PATH: $M | |
131 | 131 | |||
132 | ${PROG}: ${OBJS} ${DPADD} | 132 | ${PROG}: ${OBJS} ${DPADD} | |
133 | ${_MKMSG_LINK} ${PROG} | 133 | ${_MKMSG_LINK} ${PROG} | |
134 | ${CC} ${LDFLAGS} -o ${PROG} ${OBJS} ${LDADD} | 134 | ${CC} ${LDFLAGS} -o ${PROG} ${OBJS} ${LDADD} | |
135 | 135 | |||
136 | .if ${SHLINKINSTALLDIR} != "/usr/libexec" | 136 | .if ${SHLINKINSTALLDIR} != "/usr/libexec" | |
137 | SYMLINKS+= ${SHLINKINSTALLDIR}/${PROG} /usr/libexec/${PROG} | 137 | SYMLINKS+= ${SHLINKINSTALLDIR}/${PROG} /usr/libexec/${PROG} | |
138 | .endif | 138 | .endif | |
139 | 139 | |||
140 | .include <bsd.prog.mk> | 140 | .include <bsd.prog.mk> | |
141 | .else | 141 | .else | |
142 | 142 | |||
143 | MAN= ld.elf_so.1 | 143 | MAN= ld.elf_so.1 | |
144 | 144 | |||
145 | .include <bsd.man.mk> | 145 | .include <bsd.man.mk> | |
146 | .endif | 146 | .endif |
--- src/libexec/ld.elf_so/headers.c 2012/08/08 06:24:51 1.41.4.1
+++ src/libexec/ld.elf_so/headers.c 2013/01/22 21:47:27 1.41.4.1.2.1
@@ -1,401 +1,423 @@ | @@ -1,401 +1,423 @@ | |||
1 | /* $NetBSD: headers.c,v 1.41.4.1 2012/08/08 06:24:51 jdc Exp $ */ | 1 | /* $NetBSD: headers.c,v 1.41.4.1.2.1 2013/01/22 21:47:27 matt Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright 1996 John D. Polstra. | 4 | * Copyright 1996 John D. Polstra. | |
5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | 5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | |
6 | * Copyright 2002 Charles M. Hannum <root@ihack.net> | 6 | * Copyright 2002 Charles M. Hannum <root@ihack.net> | |
7 | * All rights reserved. | 7 | * All rights reserved. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in the | 15 | * notice, this list of conditions and the following disclaimer in the | |
16 | * documentation and/or other materials provided with the distribution. | 16 | * documentation and/or other materials provided with the distribution. | |
17 | * 3. All advertising materials mentioning features or use of this software | 17 | * 3. All advertising materials mentioning features or use of this software | |
18 | * must display the following acknowledgement: | 18 | * must display the following acknowledgement: | |
19 | * This product includes software developed by John Polstra. | 19 | * This product includes software developed by John Polstra. | |
20 | * 4. The name of the author may not be used to endorse or promote products | 20 | * 4. The name of the author may not be used to endorse or promote products | |
21 | * derived from this software without specific prior written permission. | 21 | * derived from this software without specific prior written permission. | |
22 | * | 22 | * | |
23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
26 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 26 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
33 | */ | 33 | */ | |
34 | 34 | |||
35 | /* | 35 | /* | |
36 | * Dynamic linker for ELF. | 36 | * Dynamic linker for ELF. | |
37 | * | 37 | * | |
38 | * John Polstra <jdp@polstra.com>. | 38 | * John Polstra <jdp@polstra.com>. | |
39 | */ | 39 | */ | |
40 | 40 | |||
41 | #include <sys/cdefs.h> | 41 | #include <sys/cdefs.h> | |
42 | #ifndef lint | 42 | #ifndef lint | |
43 | __RCSID("$NetBSD: headers.c,v 1.41.4.1 2012/08/08 06:24:51 jdc Exp $"); | 43 | __RCSID("$NetBSD: headers.c,v 1.41.4.1.2.1 2013/01/22 21:47:27 matt Exp $"); | |
44 | #endif /* not lint */ | 44 | #endif /* not lint */ | |
45 | 45 | |||
46 | #include <err.h> | 46 | #include <err.h> | |
47 | #include <errno.h> | 47 | #include <errno.h> | |
48 | #include <fcntl.h> | 48 | #include <fcntl.h> | |
49 | #include <stdarg.h> | 49 | #include <stdarg.h> | |
50 | #include <stdio.h> | 50 | #include <stdio.h> | |
51 | #include <stdlib.h> | 51 | #include <stdlib.h> | |
52 | #include <string.h> | 52 | #include <string.h> | |
53 | #include <unistd.h> | 53 | #include <unistd.h> | |
54 | #include <sys/types.h> | 54 | #include <sys/types.h> | |
55 | #include <sys/mman.h> | 55 | #include <sys/mman.h> | |
56 | #include <sys/bitops.h> | 56 | #include <sys/bitops.h> | |
57 | #include <dirent.h> | 57 | #include <dirent.h> | |
58 | 58 | |||
59 | #include "debug.h" | 59 | #include "debug.h" | |
60 | #include "rtld.h" | 60 | #include "rtld.h" | |
61 | 61 | |||
62 | /* | 62 | /* | |
63 | * Process a shared object's DYNAMIC section, and save the important | 63 | * Process a shared object's DYNAMIC section, and save the important | |
64 | * information in its Obj_Entry structure. | 64 | * information in its Obj_Entry structure. | |
65 | */ | 65 | */ | |
66 | void | 66 | void | |
67 | _rtld_digest_dynamic(const char *execname, Obj_Entry *obj) | 67 | _rtld_digest_dynamic(const char *execname, Obj_Entry *obj) | |
68 | { | 68 | { | |
69 | Elf_Dyn *dynp; | 69 | Elf_Dyn *dynp; | |
70 | Needed_Entry **needed_tail = &obj->needed; | 70 | Needed_Entry **needed_tail = &obj->needed; | |
71 | const Elf_Dyn *dyn_rpath = NULL; | 71 | const Elf_Dyn *dyn_rpath = NULL; | |
72 | bool use_pltrel = false; | 72 | bool use_pltrel = false; | |
73 | bool use_pltrela = false; | 73 | bool use_pltrela = false; | |
74 | Elf_Addr relsz = 0, relasz = 0; | 74 | Elf_Addr relsz = 0, relasz = 0; | |
75 | Elf_Addr pltrel = 0, pltrelsz = 0; | 75 | Elf_Addr pltrel = 0, pltrelsz = 0; | |
76 | Elf_Addr init = 0, fini = 0; | 76 | Elf_Addr init = 0, fini = 0; | |
77 | 77 | |||
78 | for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; ++dynp) { | 78 | for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; ++dynp) { | |
79 | switch (dynp->d_tag) { | 79 | switch (dynp->d_tag) { | |
80 | 80 | |||
81 | case DT_REL: | 81 | case DT_REL: | |
82 | obj->rel = (const Elf_Rel *) | 82 | obj->rel = (const Elf_Rel *) | |
83 | (obj->relocbase + dynp->d_un.d_ptr); | 83 | (obj->relocbase + dynp->d_un.d_ptr); | |
84 | break; | 84 | break; | |
85 | 85 | |||
86 | case DT_RELSZ: | 86 | case DT_RELSZ: | |
87 | relsz = dynp->d_un.d_val; | 87 | relsz = dynp->d_un.d_val; | |
88 | break; | 88 | break; | |
89 | 89 | |||
90 | case DT_RELENT: | 90 | case DT_RELENT: | |
91 | assert(dynp->d_un.d_val == sizeof(Elf_Rel)); | 91 | assert(dynp->d_un.d_val == sizeof(Elf_Rel)); | |
92 | break; | 92 | break; | |
93 | 93 | |||
94 | case DT_JMPREL: | 94 | case DT_JMPREL: | |
95 | pltrel = dynp->d_un.d_ptr; | 95 | pltrel = dynp->d_un.d_ptr; | |
96 | break; | 96 | break; | |
97 | 97 | |||
98 | case DT_PLTRELSZ: | 98 | case DT_PLTRELSZ: | |
99 | pltrelsz = dynp->d_un.d_val; | 99 | pltrelsz = dynp->d_un.d_val; | |
100 | break; | 100 | break; | |
101 | 101 | |||
102 | case DT_RELA: | 102 | case DT_RELA: | |
103 | obj->rela = (const Elf_Rela *) | 103 | obj->rela = (const Elf_Rela *) | |
104 | (obj->relocbase + dynp->d_un.d_ptr); | 104 | (obj->relocbase + dynp->d_un.d_ptr); | |
105 | break; | 105 | break; | |
106 | 106 | |||
107 | case DT_RELASZ: | 107 | case DT_RELASZ: | |
108 | relasz = dynp->d_un.d_val; | 108 | relasz = dynp->d_un.d_val; | |
109 | break; | 109 | break; | |
110 | 110 | |||
111 | case DT_RELAENT: | 111 | case DT_RELAENT: | |
112 | assert(dynp->d_un.d_val == sizeof(Elf_Rela)); | 112 | assert(dynp->d_un.d_val == sizeof(Elf_Rela)); | |
113 | break; | 113 | break; | |
114 | 114 | |||
115 | case DT_PLTREL: | 115 | case DT_PLTREL: | |
116 | use_pltrel = dynp->d_un.d_val == DT_REL; | 116 | use_pltrel = dynp->d_un.d_val == DT_REL; | |
117 | use_pltrela = dynp->d_un.d_val == DT_RELA; | 117 | use_pltrela = dynp->d_un.d_val == DT_RELA; | |
118 | assert(use_pltrel || use_pltrela); | 118 | assert(use_pltrel || use_pltrela); | |
119 | break; | 119 | break; | |
120 | 120 | |||
121 | case DT_SYMTAB: | 121 | case DT_SYMTAB: | |
122 | obj->symtab = (const Elf_Sym *) | 122 | obj->symtab = (const Elf_Sym *) | |
123 | (obj->relocbase + dynp->d_un.d_ptr); | 123 | (obj->relocbase + dynp->d_un.d_ptr); | |
124 | break; | 124 | break; | |
125 | 125 | |||
126 | case DT_SYMENT: | 126 | case DT_SYMENT: | |
127 | assert(dynp->d_un.d_val == sizeof(Elf_Sym)); | 127 | assert(dynp->d_un.d_val == sizeof(Elf_Sym)); | |
128 | break; | 128 | break; | |
129 | 129 | |||
130 | case DT_STRTAB: | 130 | case DT_STRTAB: | |
131 | obj->strtab = (const char *) | 131 | obj->strtab = (const char *) | |
132 | (obj->relocbase + dynp->d_un.d_ptr); | 132 | (obj->relocbase + dynp->d_un.d_ptr); | |
133 | break; | 133 | break; | |
134 | 134 | |||
135 | case DT_STRSZ: | 135 | case DT_STRSZ: | |
136 | obj->strsize = dynp->d_un.d_val; | 136 | obj->strsize = dynp->d_un.d_val; | |
137 | break; | 137 | break; | |
138 | 138 | |||
139 | case DT_VERNEED: | 139 | case DT_VERNEED: | |
140 | obj->verneed = (const Elf_Verneed *) | 140 | obj->verneed = (const Elf_Verneed *) | |
141 | (obj->relocbase + dynp->d_un.d_ptr); | 141 | (obj->relocbase + dynp->d_un.d_ptr); | |
142 | break; | 142 | break; | |
143 | 143 | |||
144 | case DT_VERNEEDNUM: | 144 | case DT_VERNEEDNUM: | |
145 | obj->verneednum = dynp->d_un.d_val; | 145 | obj->verneednum = dynp->d_un.d_val; | |
146 | break; | 146 | break; | |
147 | 147 | |||
148 | case DT_VERDEF: | 148 | case DT_VERDEF: | |
149 | obj->verdef = (const Elf_Verdef *) | 149 | obj->verdef = (const Elf_Verdef *) | |
150 | (obj->relocbase + dynp->d_un.d_ptr); | 150 | (obj->relocbase + dynp->d_un.d_ptr); | |
151 | break; | 151 | break; | |
152 | 152 | |||
153 | case DT_VERDEFNUM: | 153 | case DT_VERDEFNUM: | |
154 | obj->verdefnum = dynp->d_un.d_val; | 154 | obj->verdefnum = dynp->d_un.d_val; | |
155 | break; | 155 | break; | |
156 | 156 | |||
157 | case DT_VERSYM: | 157 | case DT_VERSYM: | |
158 | obj->versyms = (const Elf_Versym *) | 158 | obj->versyms = (const Elf_Versym *) | |
159 | (obj->relocbase + dynp->d_un.d_ptr); | 159 | (obj->relocbase + dynp->d_un.d_ptr); | |
160 | break; | 160 | break; | |
161 | 161 | |||
162 | case DT_HASH: | 162 | case DT_HASH: | |
163 | { | 163 | { | |
164 | const Elf_Symindx *hashtab = (const Elf_Symindx *) | 164 | const Elf_Symindx *hashtab = (const Elf_Symindx *) | |
165 | (obj->relocbase + dynp->d_un.d_ptr); | 165 | (obj->relocbase + dynp->d_un.d_ptr); | |
166 | 166 | |||
167 | if (hashtab[0] > UINT32_MAX) | 167 | if (hashtab[0] > UINT32_MAX) | |
168 | obj->nbuckets = UINT32_MAX; | 168 | obj->nbuckets = UINT32_MAX; | |
169 | else | 169 | else | |
170 | obj->nbuckets = hashtab[0]; | 170 | obj->nbuckets = hashtab[0]; | |
171 | obj->nchains = hashtab[1]; | 171 | obj->nchains = hashtab[1]; | |
172 | obj->buckets = hashtab + 2; | 172 | obj->buckets = hashtab + 2; | |
173 | obj->chains = obj->buckets + obj->nbuckets; | 173 | obj->chains = obj->buckets + obj->nbuckets; | |
174 | /* | 174 | /* | |
175 | * Should really be in _rtld_relocate_objects, | 175 | * Should really be in _rtld_relocate_objects, | |
176 | * but _rtld_symlook_obj might be used before. | 176 | * but _rtld_symlook_obj might be used before. | |
177 | */ | 177 | */ | |
178 | if (obj->nbuckets) { | 178 | if (obj->nbuckets) { | |
179 | fast_divide32_prepare(obj->nbuckets, | 179 | fast_divide32_prepare(obj->nbuckets, | |
180 | &obj->nbuckets_m, | 180 | &obj->nbuckets_m, | |
181 | &obj->nbuckets_s1, | 181 | &obj->nbuckets_s1, | |
182 | &obj->nbuckets_s2); | 182 | &obj->nbuckets_s2); | |
183 | } | 183 | } | |
184 | } | 184 | } | |
185 | break; | 185 | break; | |
186 | 186 | |||
187 | case DT_NEEDED: | 187 | case DT_NEEDED: | |
188 | { | 188 | { | |
189 | Needed_Entry *nep = NEW(Needed_Entry); | 189 | Needed_Entry *nep = NEW(Needed_Entry); | |
190 | 190 | |||
191 | nep->name = dynp->d_un.d_val; | 191 | nep->name = dynp->d_un.d_val; | |
192 | nep->obj = NULL; | 192 | nep->obj = NULL; | |
193 | nep->next = NULL; | 193 | nep->next = NULL; | |
194 | 194 | |||
195 | *needed_tail = nep; | 195 | *needed_tail = nep; | |
196 | needed_tail = &nep->next; | 196 | needed_tail = &nep->next; | |
197 | } | 197 | } | |
198 | break; | 198 | break; | |
199 | 199 | |||
200 | case DT_PLTGOT: | 200 | case DT_PLTGOT: | |
201 | obj->pltgot = (Elf_Addr *) | 201 | obj->pltgot = (Elf_Addr *) | |
202 | (obj->relocbase + dynp->d_un.d_ptr); | 202 | (obj->relocbase + dynp->d_un.d_ptr); | |
203 | break; | 203 | break; | |
204 | 204 | |||
205 | case DT_TEXTREL: | 205 | case DT_TEXTREL: | |
206 | obj->textrel = true; | 206 | obj->textrel = true; | |
207 | break; | 207 | break; | |
208 | 208 | |||
209 | case DT_SYMBOLIC: | 209 | case DT_SYMBOLIC: | |
210 | obj->symbolic = true; | 210 | obj->symbolic = true; | |
211 | break; | 211 | break; | |
212 | 212 | |||
213 | case DT_RPATH: | 213 | case DT_RPATH: | |
214 | /* | 214 | /* | |
215 | * We have to wait until later to process this, because | 215 | * We have to wait until later to process this, because | |
216 | * we might not have gotten the address of the string | 216 | * we might not have gotten the address of the string | |
217 | * table yet. | 217 | * table yet. | |
218 | */ | 218 | */ | |
219 | dyn_rpath = dynp; | 219 | dyn_rpath = dynp; | |
220 | break; | 220 | break; | |
221 | 221 | |||
222 | case DT_SONAME: | 222 | case DT_SONAME: | |
223 | /* Not used by the dynamic linker. */ | 223 | /* Not used by the dynamic linker. */ | |
224 | break; | 224 | break; | |
225 | 225 | |||
226 | case DT_INIT: | 226 | case DT_INIT: | |
227 | init = dynp->d_un.d_ptr; | 227 | init = dynp->d_un.d_ptr; | |
228 | break; | 228 | break; | |
229 | 229 | |||
230 | #ifdef HAVE_INITFINI_ARRAY | |||
231 | case DT_INIT_ARRAY: | |||
232 | obj->init_array = | |||
233 | (fptr_t *)(obj->relocbase + dynp->d_un.d_ptr); | |||
234 | break; | |||
235 | ||||
236 | case DT_INIT_ARRAYSZ: | |||
237 | obj->init_arraysz = dynp->d_un.d_val / sizeof(fptr_t); | |||
238 | break; | |||
239 | #endif | |||
240 | ||||
230 | case DT_FINI: | 241 | case DT_FINI: | |
231 | fini = dynp->d_un.d_ptr; | 242 | fini = dynp->d_un.d_ptr; | |
232 | break; | 243 | break; | |
233 | 244 | |||
245 | #ifdef HAVE_INITFINI_ARRAY | |||
246 | case DT_FINI_ARRAY: | |||
247 | obj->fini_array = | |||
248 | (fptr_t *)(obj->relocbase + dynp->d_un.d_ptr); | |||
249 | break; | |||
250 | ||||
251 | case DT_FINI_ARRAYSZ: | |||
252 | obj->fini_arraysz = dynp->d_un.d_val / sizeof(fptr_t); | |||
253 | break; | |||
254 | #endif | |||
255 | ||||
234 | /* | 256 | /* | |
235 | * Don't process DT_DEBUG on MIPS as the dynamic section | 257 | * Don't process DT_DEBUG on MIPS as the dynamic section | |
236 | * is mapped read-only. DT_MIPS_RLD_MAP is used instead. | 258 | * is mapped read-only. DT_MIPS_RLD_MAP is used instead. | |
237 | * XXX: n32/n64 may use DT_DEBUG, not sure yet. | 259 | * XXX: n32/n64 may use DT_DEBUG, not sure yet. | |
238 | */ | 260 | */ | |
239 | #ifndef __mips__ | 261 | #ifndef __mips__ | |
240 | case DT_DEBUG: | 262 | case DT_DEBUG: | |
241 | #ifdef RTLD_LOADER | 263 | #ifdef RTLD_LOADER | |
242 | dynp->d_un.d_ptr = (Elf_Addr)&_rtld_debug; | 264 | dynp->d_un.d_ptr = (Elf_Addr)&_rtld_debug; | |
243 | #endif | 265 | #endif | |
244 | break; | 266 | break; | |
245 | #endif | 267 | #endif | |
246 | 268 | |||
247 | #ifdef __mips__ | 269 | #ifdef __mips__ | |
248 | case DT_MIPS_LOCAL_GOTNO: | 270 | case DT_MIPS_LOCAL_GOTNO: | |
249 | obj->local_gotno = dynp->d_un.d_val; | 271 | obj->local_gotno = dynp->d_un.d_val; | |
250 | break; | 272 | break; | |
251 | 273 | |||
252 | case DT_MIPS_SYMTABNO: | 274 | case DT_MIPS_SYMTABNO: | |
253 | obj->symtabno = dynp->d_un.d_val; | 275 | obj->symtabno = dynp->d_un.d_val; | |
254 | break; | 276 | break; | |
255 | 277 | |||
256 | case DT_MIPS_GOTSYM: | 278 | case DT_MIPS_GOTSYM: | |
257 | obj->gotsym = dynp->d_un.d_val; | 279 | obj->gotsym = dynp->d_un.d_val; | |
258 | break; | 280 | break; | |
259 | 281 | |||
260 | case DT_MIPS_RLD_MAP: | 282 | case DT_MIPS_RLD_MAP: | |
261 | #ifdef RTLD_LOADER | 283 | #ifdef RTLD_LOADER | |
262 | *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr) | 284 | *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr) | |
263 | &_rtld_debug; | 285 | &_rtld_debug; | |
264 | #endif | 286 | #endif | |
265 | break; | 287 | break; | |
266 | #endif | 288 | #endif | |
267 | #ifdef __powerpc__ | 289 | #ifdef __powerpc__ | |
268 | case DT_PPC_GOT: | 290 | case DT_PPC_GOT: | |
269 | obj->gotptr = (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr); | 291 | obj->gotptr = (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr); | |
270 | break; | 292 | break; | |
271 | #endif | 293 | #endif | |
272 | case DT_FLAGS_1: | 294 | case DT_FLAGS_1: | |
273 | obj->z_now = | 295 | obj->z_now = | |
274 | ((dynp->d_un.d_val & DF_1_BIND_NOW) != 0); | 296 | ((dynp->d_un.d_val & DF_1_BIND_NOW) != 0); | |
275 | obj->z_nodelete = | 297 | obj->z_nodelete = | |
276 | ((dynp->d_un.d_val & DF_1_NODELETE) != 0); | 298 | ((dynp->d_un.d_val & DF_1_NODELETE) != 0); | |
277 | obj->z_initfirst = | 299 | obj->z_initfirst = | |
278 | ((dynp->d_un.d_val & DF_1_INITFIRST) != 0); | 300 | ((dynp->d_un.d_val & DF_1_INITFIRST) != 0); | |
279 | obj->z_noopen = | 301 | obj->z_noopen = | |
280 | ((dynp->d_un.d_val & DF_1_NOOPEN) != 0); | 302 | ((dynp->d_un.d_val & DF_1_NOOPEN) != 0); | |
281 | break; | 303 | break; | |
282 | } | 304 | } | |
283 | } | 305 | } | |
284 | 306 | |||
285 | obj->rellim = (const Elf_Rel *)((const uint8_t *)obj->rel + relsz); | 307 | obj->rellim = (const Elf_Rel *)((const uint8_t *)obj->rel + relsz); | |
286 | obj->relalim = (const Elf_Rela *)((const uint8_t *)obj->rela + relasz); | 308 | obj->relalim = (const Elf_Rela *)((const uint8_t *)obj->rela + relasz); | |
287 | if (use_pltrel) { | 309 | if (use_pltrel) { | |
288 | obj->pltrel = (const Elf_Rel *)(obj->relocbase + pltrel); | 310 | obj->pltrel = (const Elf_Rel *)(obj->relocbase + pltrel); | |
289 | obj->pltrellim = (const Elf_Rel *)(obj->relocbase + pltrel + pltrelsz); | 311 | obj->pltrellim = (const Elf_Rel *)(obj->relocbase + pltrel + pltrelsz); | |
290 | obj->pltrelalim = 0; | 312 | obj->pltrelalim = 0; | |
291 | /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL. | 313 | /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL. | |
292 | Trim rel(a)lim to save time later. */ | 314 | Trim rel(a)lim to save time later. */ | |
293 | if (obj->rellim && obj->pltrel && | 315 | if (obj->rellim && obj->pltrel && | |
294 | obj->rellim > obj->pltrel && | 316 | obj->rellim > obj->pltrel && | |
295 | obj->rellim <= obj->pltrellim) | 317 | obj->rellim <= obj->pltrellim) | |
296 | obj->rellim = obj->pltrel; | 318 | obj->rellim = obj->pltrel; | |
297 | } else if (use_pltrela) { | 319 | } else if (use_pltrela) { | |
298 | obj->pltrela = (const Elf_Rela *)(obj->relocbase + pltrel); | 320 | obj->pltrela = (const Elf_Rela *)(obj->relocbase + pltrel); | |
299 | obj->pltrellim = 0; | 321 | obj->pltrellim = 0; | |
300 | obj->pltrelalim = (const Elf_Rela *)(obj->relocbase + pltrel + pltrelsz); | 322 | obj->pltrelalim = (const Elf_Rela *)(obj->relocbase + pltrel + pltrelsz); | |
301 | /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL. | 323 | /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL. | |
302 | Trim rel(a)lim to save time later. */ | 324 | Trim rel(a)lim to save time later. */ | |
303 | if (obj->relalim && obj->pltrela && | 325 | if (obj->relalim && obj->pltrela && | |
304 | obj->relalim > obj->pltrela && | 326 | obj->relalim > obj->pltrela && | |
305 | obj->relalim <= obj->pltrelalim) | 327 | obj->relalim <= obj->pltrelalim) | |
306 | obj->relalim = obj->pltrela; | 328 | obj->relalim = obj->pltrela; | |
307 | } | 329 | } | |
308 | 330 | |||
309 | #if defined(RTLD_LOADER) && defined(__HAVE_FUNCTION_DESCRIPTORS) | 331 | #if defined(RTLD_LOADER) && defined(__HAVE_FUNCTION_DESCRIPTORS) | |
310 | if (init != 0) | 332 | if (init != 0) | |
311 | obj->init = (void (*)(void)) | 333 | obj->init = (void (*)(void)) | |
312 | _rtld_function_descriptor_alloc(obj, NULL, init); | 334 | _rtld_function_descriptor_alloc(obj, NULL, init); | |
313 | if (fini != 0) | 335 | if (fini != 0) | |
314 | obj->fini = (void (*)(void)) | 336 | obj->fini = (void (*)(void)) | |
315 | _rtld_function_descriptor_alloc(obj, NULL, fini); | 337 | _rtld_function_descriptor_alloc(obj, NULL, fini); | |
316 | #else | 338 | #else | |
317 | if (init != 0) | 339 | if (init != 0) | |
318 | obj->init = (void (*)(void)) | 340 | obj->init = (void (*)(void)) | |
319 | (obj->relocbase + init); | 341 | (obj->relocbase + init); | |
320 | if (fini != 0) | 342 | if (fini != 0) | |
321 | obj->fini = (void (*)(void)) | 343 | obj->fini = (void (*)(void)) | |
322 | (obj->relocbase + fini); | 344 | (obj->relocbase + fini); | |
323 | #endif | 345 | #endif | |
324 | 346 | |||
325 | if (dyn_rpath != NULL) { | 347 | if (dyn_rpath != NULL) { | |
326 | _rtld_add_paths(execname, &obj->rpaths, obj->strtab + | 348 | _rtld_add_paths(execname, &obj->rpaths, obj->strtab + | |
327 | dyn_rpath->d_un.d_val); | 349 | dyn_rpath->d_un.d_val); | |
328 | } | 350 | } | |
329 | } | 351 | } | |
330 | 352 | |||
331 | /* | 353 | /* | |
332 | * Process a shared object's program header. This is used only for the | 354 | * Process a shared object's program header. This is used only for the | |
333 | * main program, when the kernel has already loaded the main program | 355 | * main program, when the kernel has already loaded the main program | |
334 | * into memory before calling the dynamic linker. It creates and | 356 | * into memory before calling the dynamic linker. It creates and | |
335 | * returns an Obj_Entry structure. | 357 | * returns an Obj_Entry structure. | |
336 | */ | 358 | */ | |
337 | Obj_Entry * | 359 | Obj_Entry * | |
338 | _rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry) | 360 | _rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry) | |
339 | { | 361 | { | |
340 | Obj_Entry *obj; | 362 | Obj_Entry *obj; | |
341 | const Elf_Phdr *phlimit = phdr + phnum; | 363 | const Elf_Phdr *phlimit = phdr + phnum; | |
342 | const Elf_Phdr *ph; | 364 | const Elf_Phdr *ph; | |
343 | int nsegs = 0; | 365 | int nsegs = 0; | |
344 | Elf_Addr vaddr; | 366 | Elf_Addr vaddr; | |
345 | 367 | |||
346 | obj = _rtld_obj_new(); | 368 | obj = _rtld_obj_new(); | |
347 | 369 | |||
348 | for (ph = phdr; ph < phlimit; ++ph) { | 370 | for (ph = phdr; ph < phlimit; ++ph) { | |
349 | if (ph->p_type != PT_PHDR) | 371 | if (ph->p_type != PT_PHDR) | |
350 | continue; | 372 | continue; | |
351 | 373 | |||
352 | obj->phdr = (void *)(uintptr_t)phdr->p_vaddr; | 374 | obj->phdr = (void *)(uintptr_t)phdr->p_vaddr; | |
353 | obj->phsize = phdr->p_memsz; | 375 | obj->phsize = phdr->p_memsz; | |
354 | obj->relocbase = (caddr_t)((uintptr_t)phdr - (uintptr_t)ph->p_vaddr); | 376 | obj->relocbase = (caddr_t)((uintptr_t)phdr - (uintptr_t)ph->p_vaddr); | |
355 | dbg(("headers: phdr %p phsize %zu relocbase %lx", obj->phdr, | 377 | dbg(("headers: phdr %p phsize %zu relocbase %lx", obj->phdr, | |
356 | obj->phsize, (long)obj->relocbase)); | 378 | obj->phsize, (long)obj->relocbase)); | |
357 | break; | 379 | break; | |
358 | } | 380 | } | |
359 | 381 | |||
360 | for (ph = phdr; ph < phlimit; ++ph) { | 382 | for (ph = phdr; ph < phlimit; ++ph) { | |
361 | vaddr = (Elf_Addr)(uintptr_t)(obj->relocbase + ph->p_vaddr); | 383 | vaddr = (Elf_Addr)(uintptr_t)(obj->relocbase + ph->p_vaddr); | |
362 | switch (ph->p_type) { | 384 | switch (ph->p_type) { | |
363 | 385 | |||
364 | case PT_INTERP: | 386 | case PT_INTERP: | |
365 | obj->interp = (const char *)(uintptr_t)vaddr; | 387 | obj->interp = (const char *)(uintptr_t)vaddr; | |
366 | break; | 388 | break; | |
367 | 389 | |||
368 | case PT_LOAD: | 390 | case PT_LOAD: | |
369 | assert(nsegs < 2); | 391 | assert(nsegs < 2); | |
370 | if (nsegs == 0) { /* First load segment */ | 392 | if (nsegs == 0) { /* First load segment */ | |
371 | obj->vaddrbase = round_down(vaddr); | 393 | obj->vaddrbase = round_down(vaddr); | |
372 | obj->mapbase = (caddr_t)(uintptr_t)obj->vaddrbase; | 394 | obj->mapbase = (caddr_t)(uintptr_t)obj->vaddrbase; | |
373 | obj->textsize = round_up(vaddr + ph->p_memsz) - | 395 | obj->textsize = round_up(vaddr + ph->p_memsz) - | |
374 | obj->vaddrbase; | 396 | obj->vaddrbase; | |
375 | } else { /* Last load segment */ | 397 | } else { /* Last load segment */ | |
376 | obj->mapsize = round_up(vaddr + ph->p_memsz) - | 398 | obj->mapsize = round_up(vaddr + ph->p_memsz) - | |
377 | obj->vaddrbase; | 399 | obj->vaddrbase; | |
378 | } | 400 | } | |
379 | ++nsegs; | 401 | ++nsegs; | |
380 | break; | 402 | break; | |
381 | 403 | |||
382 | case PT_DYNAMIC: | 404 | case PT_DYNAMIC: | |
383 | obj->dynamic = (Elf_Dyn *)(uintptr_t)vaddr; | 405 | obj->dynamic = (Elf_Dyn *)(uintptr_t)vaddr; | |
384 | break; | 406 | break; | |
385 | 407 | |||
386 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | 408 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | |
387 | case PT_TLS: | 409 | case PT_TLS: | |
388 | obj->tlsindex = 1; | 410 | obj->tlsindex = 1; | |
389 | obj->tlssize = ph->p_memsz; | 411 | obj->tlssize = ph->p_memsz; | |
390 | obj->tlsalign = ph->p_align; | 412 | obj->tlsalign = ph->p_align; | |
391 | obj->tlsinitsize = ph->p_filesz; | 413 | obj->tlsinitsize = ph->p_filesz; | |
392 | obj->tlsinit = (void *)(uintptr_t)ph->p_vaddr; | 414 | obj->tlsinit = (void *)(uintptr_t)ph->p_vaddr; | |
393 | break; | 415 | break; | |
394 | #endif | 416 | #endif | |
395 | } | 417 | } | |
396 | } | 418 | } | |
397 | assert(nsegs == 2); | 419 | assert(nsegs == 2); | |
398 | 420 | |||
399 | obj->entry = entry; | 421 | obj->entry = entry; | |
400 | return obj; | 422 | return obj; | |
401 | } | 423 | } |
--- src/libexec/ld.elf_so/rtld.c 2011/11/25 21:27:15 1.155
+++ src/libexec/ld.elf_so/rtld.c 2013/01/22 21:47:28 1.155.4.1
@@ -1,1255 +1,1289 @@ | @@ -1,1255 +1,1289 @@ | |||
1 | /* $NetBSD: rtld.c,v 1.155 2011/11/25 21:27:15 joerg Exp $ */ | 1 | /* $NetBSD: rtld.c,v 1.155.4.1 2013/01/22 21:47:28 matt Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright 1996 John D. Polstra. | 4 | * Copyright 1996 John D. Polstra. | |
5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | 5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | |
6 | * Copyright 2002 Charles M. Hannum <root@ihack.net> | 6 | * Copyright 2002 Charles M. Hannum <root@ihack.net> | |
7 | * All rights reserved. | 7 | * All rights reserved. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in the | 15 | * notice, this list of conditions and the following disclaimer in the | |
16 | * documentation and/or other materials provided with the distribution. | 16 | * documentation and/or other materials provided with the distribution. | |
17 | * 3. All advertising materials mentioning features or use of this software | 17 | * 3. All advertising materials mentioning features or use of this software | |
18 | * must display the following acknowledgement: | 18 | * must display the following acknowledgement: | |
19 | * This product includes software developed by John Polstra. | 19 | * This product includes software developed by John Polstra. | |
20 | * 4. The name of the author may not be used to endorse or promote products | 20 | * 4. The name of the author may not be used to endorse or promote products | |
21 | * derived from this software without specific prior written permission. | 21 | * derived from this software without specific prior written permission. | |
22 | * | 22 | * | |
23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
26 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 26 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
33 | */ | 33 | */ | |
34 | 34 | |||
35 | /* | 35 | /* | |
36 | * Dynamic linker for ELF. | 36 | * Dynamic linker for ELF. | |
37 | * | 37 | * | |
38 | * John Polstra <jdp@polstra.com>. | 38 | * John Polstra <jdp@polstra.com>. | |
39 | */ | 39 | */ | |
40 | 40 | |||
41 | #include <sys/cdefs.h> | 41 | #include <sys/cdefs.h> | |
42 | #ifndef lint | 42 | #ifndef lint | |
43 | __RCSID("$NetBSD: rtld.c,v 1.155 2011/11/25 21:27:15 joerg Exp $"); | 43 | __RCSID("$NetBSD: rtld.c,v 1.155.4.1 2013/01/22 21:47:28 matt Exp $"); | |
44 | #endif /* not lint */ | 44 | #endif /* not lint */ | |
45 | 45 | |||
46 | #include <sys/param.h> | 46 | #include <sys/param.h> | |
47 | #include <sys/atomic.h> | 47 | #include <sys/atomic.h> | |
48 | #include <sys/mman.h> | 48 | #include <sys/mman.h> | |
49 | #include <err.h> | 49 | #include <err.h> | |
50 | #include <errno.h> | 50 | #include <errno.h> | |
51 | #include <fcntl.h> | 51 | #include <fcntl.h> | |
52 | #include <lwp.h> | 52 | #include <lwp.h> | |
53 | #include <stdarg.h> | 53 | #include <stdarg.h> | |
54 | #include <stdio.h> | 54 | #include <stdio.h> | |
55 | #include <stdlib.h> | 55 | #include <stdlib.h> | |
56 | #include <string.h> | 56 | #include <string.h> | |
57 | #include <unistd.h> | 57 | #include <unistd.h> | |
58 | #include <dirent.h> | 58 | #include <dirent.h> | |
59 | 59 | |||
60 | #include <ctype.h> | 60 | #include <ctype.h> | |
61 | 61 | |||
62 | #include <dlfcn.h> | 62 | #include <dlfcn.h> | |
63 | #include "debug.h" | 63 | #include "debug.h" | |
64 | #include "rtld.h" | 64 | #include "rtld.h" | |
65 | 65 | |||
66 | #if !defined(lint) | 66 | #if !defined(lint) | |
67 | #include "sysident.h" | 67 | #include "sysident.h" | |
68 | #endif | 68 | #endif | |
69 | 69 | |||
70 | /* | 70 | /* | |
71 | * Function declarations. | 71 | * Function declarations. | |
72 | */ | 72 | */ | |
73 | static void _rtld_init(caddr_t, caddr_t, const char *); | 73 | static void _rtld_init(caddr_t, caddr_t, const char *); | |
74 | static void _rtld_exit(void); | 74 | static void _rtld_exit(void); | |
75 | 75 | |||
76 | Elf_Addr _rtld(Elf_Addr *, Elf_Addr); | 76 | Elf_Addr _rtld(Elf_Addr *, Elf_Addr); | |
77 | 77 | |||
78 | 78 | |||
79 | /* | 79 | /* | |
80 | * Data declarations. | 80 | * Data declarations. | |
81 | */ | 81 | */ | |
82 | static char *error_message; /* Message for dlopen(), or NULL */ | 82 | static char *error_message; /* Message for dlopen(), or NULL */ | |
83 | 83 | |||
84 | struct r_debug _rtld_debug; /* for GDB; */ | 84 | struct r_debug _rtld_debug; /* for GDB; */ | |
85 | bool _rtld_trust; /* False for setuid and setgid programs */ | 85 | bool _rtld_trust; /* False for setuid and setgid programs */ | |
86 | Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */ | 86 | Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */ | |
87 | Obj_Entry **_rtld_objtail; /* Link field of last object in list */ | 87 | Obj_Entry **_rtld_objtail; /* Link field of last object in list */ | |
88 | Obj_Entry *_rtld_objmain; /* The main program shared object */ | 88 | Obj_Entry *_rtld_objmain; /* The main program shared object */ | |
89 | Obj_Entry _rtld_objself; /* The dynamic linker shared object */ | 89 | Obj_Entry _rtld_objself; /* The dynamic linker shared object */ | |
90 | u_int _rtld_objcount; /* Number of objects in _rtld_objlist */ | 90 | u_int _rtld_objcount; /* Number of objects in _rtld_objlist */ | |
91 | u_int _rtld_objloads; /* Number of objects loaded in _rtld_objlist */ | 91 | u_int _rtld_objloads; /* Number of objects loaded in _rtld_objlist */ | |
92 | u_int _rtld_objgen; /* Generation count for _rtld_objlist */ | 92 | u_int _rtld_objgen; /* Generation count for _rtld_objlist */ | |
93 | const char _rtld_path[] = _PATH_RTLD; | 93 | const char _rtld_path[] = _PATH_RTLD; | |
94 | 94 | |||
95 | /* Initialize a fake symbol for resolving undefined weak references. */ | 95 | /* Initialize a fake symbol for resolving undefined weak references. */ | |
96 | Elf_Sym _rtld_sym_zero = { | 96 | Elf_Sym _rtld_sym_zero = { | |
97 | .st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), | 97 | .st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), | |
98 | .st_shndx = SHN_ABS, | 98 | .st_shndx = SHN_ABS, | |
99 | }; | 99 | }; | |
100 | size_t _rtld_pagesz; /* Page size, as provided by kernel */ | 100 | size_t _rtld_pagesz; /* Page size, as provided by kernel */ | |
101 | 101 | |||
102 | Search_Path *_rtld_default_paths; | 102 | Search_Path *_rtld_default_paths; | |
103 | Search_Path *_rtld_paths; | 103 | Search_Path *_rtld_paths; | |
104 | 104 | |||
105 | Library_Xform *_rtld_xforms; | 105 | Library_Xform *_rtld_xforms; | |
106 | 106 | |||
107 | /* | 107 | /* | |
108 | * Global declarations normally provided by crt0. | 108 | * Global declarations normally provided by crt0. | |
109 | */ | 109 | */ | |
110 | char *__progname; | 110 | char *__progname; | |
111 | char **environ; | 111 | char **environ; | |
112 | 112 | |||
113 | static volatile bool _rtld_mutex_may_recurse; | 113 | static volatile bool _rtld_mutex_may_recurse; | |
114 | 114 | |||
115 | #if defined(RTLD_DEBUG) | 115 | #if defined(RTLD_DEBUG) | |
116 | #ifndef __sh__ | 116 | #ifndef __sh__ | |
117 | extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; | 117 | extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; | |
118 | #else /* 32-bit SuperH */ | 118 | #else /* 32-bit SuperH */ | |
119 | register Elf_Addr *_GLOBAL_OFFSET_TABLE_ asm("r12"); | 119 | register Elf_Addr *_GLOBAL_OFFSET_TABLE_ asm("r12"); | |
120 | #endif | 120 | #endif | |
121 | #endif /* RTLD_DEBUG */ | 121 | #endif /* RTLD_DEBUG */ | |
122 | extern Elf_Dyn _DYNAMIC; | 122 | extern Elf_Dyn _DYNAMIC; | |
123 | 123 | |||
124 | static void _rtld_call_fini_functions(sigset_t *, int); | 124 | static void _rtld_call_fini_functions(sigset_t *, int); | |
125 | static void _rtld_call_init_functions(sigset_t *); | 125 | static void _rtld_call_init_functions(sigset_t *); | |
126 | static void _rtld_initlist_visit(Objlist *, Obj_Entry *, int); | 126 | static void _rtld_initlist_visit(Objlist *, Obj_Entry *, int); | |
127 | static void _rtld_initlist_tsort(Objlist *, int); | 127 | static void _rtld_initlist_tsort(Objlist *, int); | |
128 | static Obj_Entry *_rtld_dlcheck(void *); | 128 | static Obj_Entry *_rtld_dlcheck(void *); | |
129 | static void _rtld_init_dag(Obj_Entry *); | 129 | static void _rtld_init_dag(Obj_Entry *); | |
130 | static void _rtld_init_dag1(Obj_Entry *, Obj_Entry *); | 130 | static void _rtld_init_dag1(Obj_Entry *, Obj_Entry *); | |
131 | static void _rtld_objlist_remove(Objlist *, Obj_Entry *); | 131 | static void _rtld_objlist_remove(Objlist *, Obj_Entry *); | |
132 | static void _rtld_objlist_clear(Objlist *); | 132 | static void _rtld_objlist_clear(Objlist *); | |
133 | static void _rtld_unload_object(sigset_t *, Obj_Entry *, bool); | 133 | static void _rtld_unload_object(sigset_t *, Obj_Entry *, bool); | |
134 | static void _rtld_unref_dag(Obj_Entry *); | 134 | static void _rtld_unref_dag(Obj_Entry *); | |
135 | static Obj_Entry *_rtld_obj_from_addr(const void *); | 135 | static Obj_Entry *_rtld_obj_from_addr(const void *); | |
136 | 136 | |||
137 | static inline void | |||
138 | _rtld_call_initfini_function(fptr_t func, sigset_t *mask) | |||
139 | { | |||
140 | _rtld_exclusive_exit(mask); | |||
141 | (*func)(); | |||
142 | _rtld_exclusive_enter(mask); | |||
143 | } | |||
144 | ||||
145 | static void | |||
146 | _rtld_call_fini_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen) | |||
147 | { | |||
148 | if (obj->fini_arraysz == 0 && (obj->fini == NULL || obj->fini_called)) { | |||
149 | return; | |||
150 | } | |||
151 | if (obj->fini != NULL && !obj->fini_called) { | |||
152 | dbg (("calling fini function %s at %p%s", obj->path, | |||
153 | (void *)obj->fini, | |||
154 | obj->z_initfirst ? " (DF_1_INITFIRST)" : "")); | |||
155 | obj->fini_called = 1; | |||
156 | _rtld_call_initfini_function(obj->fini, mask); | |||
157 | } | |||
158 | #ifdef HAVE_INITFINI_ARRAY | |||
159 | /* | |||
160 | * Now process the fini_array if it exists. Simply go from | |||
161 | * start to end. We need to make restartable so just advance | |||
162 | * the array pointer and decrement the size each time through | |||
163 | * the loop. | |||
164 | */ | |||
165 | while (obj->fini_arraysz > 0 && _rtld_objgen == cur_objgen) { | |||
166 | fptr_t fini = *obj->fini_array++; | |||
167 | obj->fini_arraysz--; | |||
168 | dbg (("calling fini array function %s at %p%s", obj->path, | |||
169 | (void *)fini, | |||
170 | obj->z_initfirst ? " (DF_1_INITFIRST)" : "")); | |||
171 | _rtld_call_initfini_function(fini, mask); | |||
172 | } | |||
173 | #endif /* HAVE_INITFINI_ARRAY */ | |||
174 | } | |||
175 | ||||
137 | static void | 176 | static void | |
138 | _rtld_call_fini_functions(sigset_t *mask, int force) | 177 | _rtld_call_fini_functions(sigset_t *mask, int force) | |
139 | { | 178 | { | |
140 | Objlist_Entry *elm; | 179 | Objlist_Entry *elm; | |
141 | Objlist finilist; | 180 | Objlist finilist; | |
142 | Obj_Entry *obj; | |||
143 | void (*fini)(void); | |||
144 | u_int cur_objgen; | 181 | u_int cur_objgen; | |
145 | 182 | |||
146 | dbg(("_rtld_call_fini_functions(%d)", force)); | 183 | dbg(("_rtld_call_fini_functions(%d)", force)); | |
147 | 184 | |||
148 | restart: | 185 | restart: | |
149 | cur_objgen = ++_rtld_objgen; | 186 | cur_objgen = ++_rtld_objgen; | |
150 | SIMPLEQ_INIT(&finilist); | 187 | SIMPLEQ_INIT(&finilist); | |
151 | _rtld_initlist_tsort(&finilist, 1); | 188 | _rtld_initlist_tsort(&finilist, 1); | |
152 | 189 | |||
153 | /* First pass: objects _not_ marked with DF_1_INITFIRST. */ | 190 | /* First pass: objects _not_ marked with DF_1_INITFIRST. */ | |
154 | SIMPLEQ_FOREACH(elm, &finilist, link) { | 191 | SIMPLEQ_FOREACH(elm, &finilist, link) { | |
155 | obj = elm->obj; | 192 | Obj_Entry * const obj = elm->obj; | |
156 | if (obj->refcount > 0 && !force) { | 193 | if (!obj->z_initfirst) { | |
157 | continue; | 194 | if (obj->refcount > 0 && !force) { | |
158 | } | 195 | continue; | |
159 | if (obj->fini == NULL || obj->fini_called || obj->z_initfirst) { | 196 | } | |
160 | continue; | 197 | /* | |
198 | * XXX This can race against a concurrent dlclose(). | |||
199 | * XXX In that case, the object could be unmapped before | |||
200 | * XXX the fini() call or the fini_array has completed. | |||
201 | */ | |||
202 | _rtld_call_fini_function(obj, mask, cur_objgen); | |||
203 | if (_rtld_objgen != cur_objgen) { | |||
204 | dbg(("restarting fini iteration")); | |||
205 | _rtld_objlist_clear(&finilist); | |||
206 | goto restart; | |||
161 | } | 207 | } | |
162 | dbg (("calling fini function %s at %p", obj->path, | |||
163 | (void *)obj->fini)); | |||
164 | obj->fini_called = 1; | |||
165 | /* | |||
166 | * XXX This can race against a concurrent dlclose(). | |||
167 | * XXX In that case, the object could be unmapped before | |||
168 | * XXX the fini() call is done. | |||
169 | */ | |||
170 | fini = obj->fini; | |||
171 | _rtld_exclusive_exit(mask); | |||
172 | (*fini)(); | |||
173 | _rtld_exclusive_enter(mask); | |||
174 | if (_rtld_objgen != cur_objgen) { | |||
175 | dbg(("restarting fini iteration")); | |||
176 | _rtld_objlist_clear(&finilist); | |||
177 | goto restart; | |||
178 | } | 208 | } | |
179 | } | 209 | } | |
180 | 210 | |||
181 | /* Second pass: objects marked with DF_1_INITFIRST. */ | 211 | /* Second pass: objects marked with DF_1_INITFIRST. */ | |
182 | SIMPLEQ_FOREACH(elm, &finilist, link) { | 212 | SIMPLEQ_FOREACH(elm, &finilist, link) { | |
183 | obj = elm->obj; | 213 | Obj_Entry * const obj = elm->obj; | |
184 | if (obj->refcount > 0 && !force) { | 214 | if (obj->refcount > 0 && !force) { | |
185 | continue; | 215 | continue; | |
186 | } | 216 | } | |
187 | if (obj->fini == NULL || obj->fini_called) { | |||
188 | continue; | |||
189 | } | |||
190 | dbg (("calling fini function %s at %p (DF_1_INITFIRST)", | |||
191 | obj->path, (void *)obj->fini)); | |||
192 | obj->fini_called = 1; | |||
193 | /* XXX See above for the race condition here */ | 217 | /* XXX See above for the race condition here */ | |
194 | fini = obj->fini; | 218 | _rtld_call_fini_function(obj, mask, cur_objgen); | |
195 | _rtld_exclusive_exit(mask); | |||
196 | (*fini)(); | |||
197 | _rtld_exclusive_enter(mask); | |||
198 | if (_rtld_objgen != cur_objgen) { | 219 | if (_rtld_objgen != cur_objgen) { | |
199 | dbg(("restarting fini iteration")); | 220 | dbg(("restarting fini iteration")); | |
200 | _rtld_objlist_clear(&finilist); | 221 | _rtld_objlist_clear(&finilist); | |
201 | goto restart; | 222 | goto restart; | |
202 | } | 223 | } | |
203 | } | 224 | } | |
204 | 225 | |||
205 | _rtld_objlist_clear(&finilist); | 226 | _rtld_objlist_clear(&finilist); | |
206 | } | 227 | } | |
207 | 228 | |||
208 | static void | 229 | static void | |
230 | _rtld_call_init_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen) | |||
231 | { | |||
232 | if (obj->init_arraysz == 0 && (obj->init_called || obj->init == NULL)) { | |||
233 | return; | |||
234 | } | |||
235 | if (!obj->init_called && obj->init != NULL) { | |||
236 | dbg (("calling init function %s at %p%s", | |||
237 | obj->path, (void *)obj->init, | |||
238 | obj->z_initfirst ? " (DF_1_INITFIRST)" : "")); | |||
239 | obj->init_called = 1; | |||
240 | _rtld_call_initfini_function(obj->init, mask); | |||
241 | } | |||
242 | ||||
243 | #ifdef HAVE_INITFINI_ARRAY | |||
244 | /* | |||
245 | * Now process the init_array if it exists. Simply go from | |||
246 | * start to end. We need to make restartable so just advance | |||
247 | * the array pointer and decrement the size each time through | |||
248 | * the loop. | |||
249 | */ | |||
250 | while (obj->init_arraysz > 0 && _rtld_objgen == cur_objgen) { | |||
251 | fptr_t init = *obj->init_array++; | |||
252 | obj->init_arraysz--; | |||
253 | dbg (("calling init_array function %s at %p%s", | |||
254 | obj->path, (void *)init, | |||
255 | obj->z_initfirst ? " (DF_1_INITFIRST)" : "")); | |||
256 | _rtld_call_initfini_function(init, mask); | |||
257 | } | |||
258 | #endif /* HAVE_INITFINI_ARRAY */ | |||
259 | } | |||
260 | ||||
261 | static void | |||
209 | _rtld_call_init_functions(sigset_t *mask) | 262 | _rtld_call_init_functions(sigset_t *mask) | |
210 | { | 263 | { | |
211 | Objlist_Entry *elm; | 264 | Objlist_Entry *elm; | |
212 | Objlist initlist; | 265 | Objlist initlist; | |
213 | Obj_Entry *obj; | |||
214 | void (*init)(void); | |||
215 | u_int cur_objgen; | 266 | u_int cur_objgen; | |
216 | 267 | |||
217 | dbg(("_rtld_call_init_functions()")); | 268 | dbg(("_rtld_call_init_functions()")); | |
218 | 269 | |||
219 | restart: | 270 | restart: | |
220 | cur_objgen = ++_rtld_objgen; | 271 | cur_objgen = ++_rtld_objgen; | |
221 | SIMPLEQ_INIT(&initlist); | 272 | SIMPLEQ_INIT(&initlist); | |
222 | _rtld_initlist_tsort(&initlist, 0); | 273 | _rtld_initlist_tsort(&initlist, 0); | |
223 | 274 | |||
224 | /* First pass: objects marked with DF_1_INITFIRST. */ | 275 | /* First pass: objects marked with DF_1_INITFIRST. */ | |
225 | SIMPLEQ_FOREACH(elm, &initlist, link) { | 276 | SIMPLEQ_FOREACH(elm, &initlist, link) { | |
226 | obj = elm->obj; | 277 | Obj_Entry * const obj = elm->obj; | |
227 | if (obj->init == NULL || obj->init_called || !obj->z_initfirst) { | 278 | if (obj->z_initfirst) { | |
228 | continue; | 279 | _rtld_call_init_function(obj, mask, cur_objgen); | |
229 | } | 280 | if (_rtld_objgen != cur_objgen) { | |
230 | dbg (("calling init function %s at %p (DF_1_INITFIRST)", | 281 | dbg(("restarting init iteration")); | |
231 | obj->path, (void *)obj->init)); | 282 | _rtld_objlist_clear(&initlist); | |
232 | obj->init_called = 1; | 283 | goto restart; | |
233 | init = obj->init; | 284 | } | |
234 | _rtld_exclusive_exit(mask); | |||
235 | (*init)(); | |||
236 | _rtld_exclusive_enter(mask); | |||
237 | if (_rtld_objgen != cur_objgen) { | |||
238 | dbg(("restarting init iteration")); | |||
239 | _rtld_objlist_clear(&initlist); | |||
240 | goto restart; | |||
241 | } | 285 | } | |
242 | } | 286 | } | |
243 | 287 | |||
244 | /* Second pass: all other objects. */ | 288 | /* Second pass: all other objects. */ | |
245 | SIMPLEQ_FOREACH(elm, &initlist, link) { | 289 | SIMPLEQ_FOREACH(elm, &initlist, link) { | |
246 | obj = elm->obj; | 290 | _rtld_call_init_function(elm->obj, mask, cur_objgen); | |
247 | if (obj->init == NULL || obj->init_called) { | |||
248 | continue; | |||
249 | } | |||
250 | dbg (("calling init function %s at %p", obj->path, | |||
251 | (void *)obj->init)); | |||
252 | obj->init_called = 1; | |||
253 | init = obj->init; | |||
254 | _rtld_exclusive_exit(mask); | |||
255 | (*init)(); | |||
256 | _rtld_exclusive_enter(mask); | |||
257 | if (_rtld_objgen != cur_objgen) { | 291 | if (_rtld_objgen != cur_objgen) { | |
258 | dbg(("restarting init iteration")); | 292 | dbg(("restarting init iteration")); | |
259 | _rtld_objlist_clear(&initlist); | 293 | _rtld_objlist_clear(&initlist); | |
260 | goto restart; | 294 | goto restart; | |
261 | } | 295 | } | |
262 | } | 296 | } | |
263 | 297 | |||
264 | _rtld_objlist_clear(&initlist); | 298 | _rtld_objlist_clear(&initlist); | |
265 | } | 299 | } | |
266 | 300 | |||
267 | /* | 301 | /* | |
268 | * Initialize the dynamic linker. The argument is the address at which | 302 | * Initialize the dynamic linker. The argument is the address at which | |
269 | * the dynamic linker has been mapped into memory. The primary task of | 303 | * the dynamic linker has been mapped into memory. The primary task of | |
270 | * this function is to create an Obj_Entry for the dynamic linker and | 304 | * this function is to create an Obj_Entry for the dynamic linker and | |
271 | * to resolve the PLT relocation for platforms that need it (those that | 305 | * to resolve the PLT relocation for platforms that need it (those that | |
272 | * define __HAVE_FUNCTION_DESCRIPTORS | 306 | * define __HAVE_FUNCTION_DESCRIPTORS | |
273 | */ | 307 | */ | |
274 | static void | 308 | static void | |
275 | _rtld_init(caddr_t mapbase, caddr_t relocbase, const char *execname) | 309 | _rtld_init(caddr_t mapbase, caddr_t relocbase, const char *execname) | |
276 | { | 310 | { | |
277 | 311 | |||
278 | /* Conjure up an Obj_Entry structure for the dynamic linker. */ | 312 | /* Conjure up an Obj_Entry structure for the dynamic linker. */ | |
279 | _rtld_objself.path = __UNCONST(_rtld_path); | 313 | _rtld_objself.path = __UNCONST(_rtld_path); | |
280 | _rtld_objself.pathlen = sizeof(_rtld_path)-1; | 314 | _rtld_objself.pathlen = sizeof(_rtld_path)-1; | |
281 | _rtld_objself.rtld = true; | 315 | _rtld_objself.rtld = true; | |
282 | _rtld_objself.mapbase = mapbase; | 316 | _rtld_objself.mapbase = mapbase; | |
283 | _rtld_objself.relocbase = relocbase; | 317 | _rtld_objself.relocbase = relocbase; | |
284 | _rtld_objself.dynamic = (Elf_Dyn *) &_DYNAMIC; | 318 | _rtld_objself.dynamic = (Elf_Dyn *) &_DYNAMIC; | |
285 | _rtld_objself.strtab = "_rtld_sym_zero"; | 319 | _rtld_objself.strtab = "_rtld_sym_zero"; | |
286 | 320 | |||
287 | /* | 321 | /* | |
288 | * Set value to -relocbase so that | 322 | * Set value to -relocbase so that | |
289 | * | 323 | * | |
290 | * _rtld_objself.relocbase + _rtld_sym_zero.st_value == 0 | 324 | * _rtld_objself.relocbase + _rtld_sym_zero.st_value == 0 | |
291 | * | 325 | * | |
292 | * This allows unresolved references to weak symbols to be computed | 326 | * This allows unresolved references to weak symbols to be computed | |
293 | * to a value of 0. | 327 | * to a value of 0. | |
294 | */ | 328 | */ | |
295 | _rtld_sym_zero.st_value = -(uintptr_t)relocbase; | 329 | _rtld_sym_zero.st_value = -(uintptr_t)relocbase; | |
296 | 330 | |||
297 | _rtld_digest_dynamic(_rtld_path, &_rtld_objself); | 331 | _rtld_digest_dynamic(_rtld_path, &_rtld_objself); | |
298 | assert(!_rtld_objself.needed); | 332 | assert(!_rtld_objself.needed); | |
299 | #if !defined(__hppa__) | 333 | #if !defined(__hppa__) | |
300 | assert(!_rtld_objself.pltrel && !_rtld_objself.pltrela); | 334 | assert(!_rtld_objself.pltrel && !_rtld_objself.pltrela); | |
301 | #else | 335 | #else | |
302 | _rtld_relocate_plt_objects(&_rtld_objself); | 336 | _rtld_relocate_plt_objects(&_rtld_objself); | |
303 | #endif | 337 | #endif | |
304 | #if !defined(__mips__) && !defined(__hppa__) | 338 | #if !defined(__mips__) && !defined(__hppa__) | |
305 | assert(!_rtld_objself.pltgot); | 339 | assert(!_rtld_objself.pltgot); | |
306 | #endif | 340 | #endif | |
307 | #if !defined(__arm__) && !defined(__mips__) && !defined(__sh__) | 341 | #if !defined(__arm__) && !defined(__mips__) && !defined(__sh__) | |
308 | /* ARM, MIPS and SH{3,5} have a bogus DT_TEXTREL. */ | 342 | /* ARM, MIPS and SH{3,5} have a bogus DT_TEXTREL. */ | |
309 | assert(!_rtld_objself.textrel); | 343 | assert(!_rtld_objself.textrel); | |
310 | #endif | 344 | #endif | |
311 | 345 | |||
312 | _rtld_add_paths(execname, &_rtld_default_paths, | 346 | _rtld_add_paths(execname, &_rtld_default_paths, | |
313 | RTLD_DEFAULT_LIBRARY_PATH); | 347 | RTLD_DEFAULT_LIBRARY_PATH); | |
314 | 348 | |||
315 | #ifdef RTLD_ARCH_SUBDIR | 349 | #ifdef RTLD_ARCH_SUBDIR | |
316 | _rtld_add_paths(execname, &_rtld_default_paths, | 350 | _rtld_add_paths(execname, &_rtld_default_paths, | |
317 | RTLD_DEFAULT_LIBRARY_PATH "/" RTLD_ARCH_SUBDIR); | 351 | RTLD_DEFAULT_LIBRARY_PATH "/" RTLD_ARCH_SUBDIR); | |
318 | #endif | 352 | #endif | |
319 | 353 | |||
320 | /* | 354 | /* | |
321 | * Set up the _rtld_objlist pointer, so that rtld symbols can be found. | 355 | * Set up the _rtld_objlist pointer, so that rtld symbols can be found. | |
322 | */ | 356 | */ | |
323 | _rtld_objlist = &_rtld_objself; | 357 | _rtld_objlist = &_rtld_objself; | |
324 | 358 | |||
325 | /* Make the object list empty again. */ | 359 | /* Make the object list empty again. */ | |
326 | _rtld_objlist = NULL; | 360 | _rtld_objlist = NULL; | |
327 | _rtld_objtail = &_rtld_objlist; | 361 | _rtld_objtail = &_rtld_objlist; | |
328 | _rtld_objcount = 0; | 362 | _rtld_objcount = 0; | |
329 | 363 | |||
330 | _rtld_debug.r_brk = _rtld_debug_state; | 364 | _rtld_debug.r_brk = _rtld_debug_state; | |
331 | _rtld_debug.r_state = RT_CONSISTENT; | 365 | _rtld_debug.r_state = RT_CONSISTENT; | |
332 | } | 366 | } | |
333 | 367 | |||
334 | /* | 368 | /* | |
335 | * Cleanup procedure. It will be called (by the atexit() mechanism) just | 369 | * Cleanup procedure. It will be called (by the atexit() mechanism) just | |
336 | * before the process exits. | 370 | * before the process exits. | |
337 | */ | 371 | */ | |
338 | static void | 372 | static void | |
339 | _rtld_exit(void) | 373 | _rtld_exit(void) | |
340 | { | 374 | { | |
341 | sigset_t mask; | 375 | sigset_t mask; | |
342 | 376 | |||
343 | dbg(("rtld_exit()")); | 377 | dbg(("rtld_exit()")); | |
344 | 378 | |||
345 | _rtld_exclusive_enter(&mask); | 379 | _rtld_exclusive_enter(&mask); | |
346 | 380 | |||
347 | _rtld_call_fini_functions(&mask, 1); | 381 | _rtld_call_fini_functions(&mask, 1); | |
348 | 382 | |||
349 | _rtld_exclusive_exit(&mask); | 383 | _rtld_exclusive_exit(&mask); | |
350 | } | 384 | } | |
351 | 385 | |||
352 | /* | 386 | /* | |
353 | * Main entry point for dynamic linking. The argument is the stack | 387 | * Main entry point for dynamic linking. The argument is the stack | |
354 | * pointer. The stack is expected to be laid out as described in the | 388 | * pointer. The stack is expected to be laid out as described in the | |
355 | * SVR4 ABI specification, Intel 386 Processor Supplement. Specifically, | 389 | * SVR4 ABI specification, Intel 386 Processor Supplement. Specifically, | |
356 | * the stack pointer points to a word containing ARGC. Following that | 390 | * the stack pointer points to a word containing ARGC. Following that | |
357 | * in the stack is a null-terminated sequence of pointers to argument | 391 | * in the stack is a null-terminated sequence of pointers to argument | |
358 | * strings. Then comes a null-terminated sequence of pointers to | 392 | * strings. Then comes a null-terminated sequence of pointers to | |
359 | * environment strings. Finally, there is a sequence of "auxiliary | 393 | * environment strings. Finally, there is a sequence of "auxiliary | |
360 | * vector" entries. | 394 | * vector" entries. | |
361 | * | 395 | * | |
362 | * This function returns the entry point for the main program, the dynamic | 396 | * This function returns the entry point for the main program, the dynamic | |
363 | * linker's exit procedure in sp[0], and a pointer to the main object in | 397 | * linker's exit procedure in sp[0], and a pointer to the main object in | |
364 | * sp[1]. | 398 | * sp[1]. | |
365 | */ | 399 | */ | |
366 | Elf_Addr | 400 | Elf_Addr | |
367 | _rtld(Elf_Addr *sp, Elf_Addr relocbase) | 401 | _rtld(Elf_Addr *sp, Elf_Addr relocbase) | |
368 | { | 402 | { | |
369 | const AuxInfo *pAUX_base, *pAUX_entry, *pAUX_execfd, *pAUX_phdr, | 403 | const AuxInfo *pAUX_base, *pAUX_entry, *pAUX_execfd, *pAUX_phdr, | |
370 | *pAUX_phent, *pAUX_phnum, *pAUX_euid, *pAUX_egid, | 404 | *pAUX_phent, *pAUX_phnum, *pAUX_euid, *pAUX_egid, | |
371 | *pAUX_ruid, *pAUX_rgid; | 405 | *pAUX_ruid, *pAUX_rgid; | |
372 | const AuxInfo *pAUX_pagesz; | 406 | const AuxInfo *pAUX_pagesz; | |
373 | char **env, **oenvp; | 407 | char **env, **oenvp; | |
374 | const AuxInfo *aux; | 408 | const AuxInfo *aux; | |
375 | const AuxInfo *auxp; | 409 | const AuxInfo *auxp; | |
376 | Obj_Entry *obj; | 410 | Obj_Entry *obj; | |
377 | Elf_Addr *const osp = sp; | 411 | Elf_Addr *const osp = sp; | |
378 | bool bind_now = 0; | 412 | bool bind_now = 0; | |
379 | const char *ld_bind_now, *ld_preload, *ld_library_path; | 413 | const char *ld_bind_now, *ld_preload, *ld_library_path; | |
380 | const char **argv; | 414 | const char **argv; | |
381 | const char *execname; | 415 | const char *execname; | |
382 | long argc; | 416 | long argc; | |
383 | const char **real___progname; | 417 | const char **real___progname; | |
384 | const Obj_Entry **real___mainprog_obj; | 418 | const Obj_Entry **real___mainprog_obj; | |
385 | char ***real_environ; | 419 | char ***real_environ; | |
386 | sigset_t mask; | 420 | sigset_t mask; | |
387 | #ifdef DEBUG | 421 | #ifdef DEBUG | |
388 | const char *ld_debug; | 422 | const char *ld_debug; | |
389 | #endif | 423 | #endif | |
390 | #ifdef RTLD_DEBUG | 424 | #ifdef RTLD_DEBUG | |
391 | int i = 0; | 425 | int i = 0; | |
392 | #endif | 426 | #endif | |
393 | 427 | |||
394 | /* | 428 | /* | |
395 | * On entry, the dynamic linker itself has not been relocated yet. | 429 | * On entry, the dynamic linker itself has not been relocated yet. | |
396 | * Be very careful not to reference any global data until after | 430 | * Be very careful not to reference any global data until after | |
397 | * _rtld_init has returned. It is OK to reference file-scope statics | 431 | * _rtld_init has returned. It is OK to reference file-scope statics | |
398 | * and string constants, and to call static and global functions. | 432 | * and string constants, and to call static and global functions. | |
399 | */ | 433 | */ | |
400 | /* Find the auxiliary vector on the stack. */ | 434 | /* Find the auxiliary vector on the stack. */ | |
401 | /* first Elf_Word reserved to address of exit routine */ | 435 | /* first Elf_Word reserved to address of exit routine */ | |
402 | #if defined(RTLD_DEBUG) | 436 | #if defined(RTLD_DEBUG) | |
403 | debug = 1; | 437 | debug = 1; | |
404 | dbg(("sp = %p, argc = %ld, argv = %p <%s> relocbase %p", sp, | 438 | dbg(("sp = %p, argc = %ld, argv = %p <%s> relocbase %p", sp, | |
405 | (long)sp[2], &sp[3], (char *) sp[3], (void *)relocbase)); | 439 | (long)sp[2], &sp[3], (char *) sp[3], (void *)relocbase)); | |
406 | #if 0 | 440 | #if 0 | |
407 | dbg(("got is at %p, dynamic is at %p", _GLOBAL_OFFSET_TABLE_, | 441 | dbg(("got is at %p, dynamic is at %p", _GLOBAL_OFFSET_TABLE_, | |
408 | &_DYNAMIC)); | 442 | &_DYNAMIC)); | |
409 | #endif | 443 | #endif | |
410 | dbg(("_ctype_ is %p", _ctype_)); | 444 | dbg(("_ctype_ is %p", _ctype_)); | |
411 | #endif | 445 | #endif | |
412 | 446 | |||
413 | sp += 2; /* skip over return argument space */ | 447 | sp += 2; /* skip over return argument space */ | |
414 | argv = (const char **) &sp[1]; | 448 | argv = (const char **) &sp[1]; | |
415 | argc = *(long *)sp; | 449 | argc = *(long *)sp; | |
416 | sp += 2 + argc; /* Skip over argc, arguments, and NULL | 450 | sp += 2 + argc; /* Skip over argc, arguments, and NULL | |
417 | * terminator */ | 451 | * terminator */ | |
418 | env = (char **) sp; | 452 | env = (char **) sp; | |
419 | while (*sp++ != 0) { /* Skip over environment, and NULL terminator */ | 453 | while (*sp++ != 0) { /* Skip over environment, and NULL terminator */ | |
420 | #if defined(RTLD_DEBUG) | 454 | #if defined(RTLD_DEBUG) | |
421 | dbg(("env[%d] = %p %s", i++, (void *)sp[-1], (char *)sp[-1])); | 455 | dbg(("env[%d] = %p %s", i++, (void *)sp[-1], (char *)sp[-1])); | |
422 | #endif | 456 | #endif | |
423 | } | 457 | } | |
424 | aux = (const AuxInfo *) sp; | 458 | aux = (const AuxInfo *) sp; | |
425 | 459 | |||
426 | pAUX_base = pAUX_entry = pAUX_execfd = NULL; | 460 | pAUX_base = pAUX_entry = pAUX_execfd = NULL; | |
427 | pAUX_phdr = pAUX_phent = pAUX_phnum = NULL; | 461 | pAUX_phdr = pAUX_phent = pAUX_phnum = NULL; | |
428 | pAUX_euid = pAUX_ruid = pAUX_egid = pAUX_rgid = NULL; | 462 | pAUX_euid = pAUX_ruid = pAUX_egid = pAUX_rgid = NULL; | |
429 | pAUX_pagesz = NULL; | 463 | pAUX_pagesz = NULL; | |
430 | 464 | |||
431 | execname = NULL; | 465 | execname = NULL; | |
432 | 466 | |||
433 | /* Digest the auxiliary vector. */ | 467 | /* Digest the auxiliary vector. */ | |
434 | for (auxp = aux; auxp->a_type != AT_NULL; ++auxp) { | 468 | for (auxp = aux; auxp->a_type != AT_NULL; ++auxp) { | |
435 | switch (auxp->a_type) { | 469 | switch (auxp->a_type) { | |
436 | case AT_BASE: | 470 | case AT_BASE: | |
437 | pAUX_base = auxp; | 471 | pAUX_base = auxp; | |
438 | break; | 472 | break; | |
439 | case AT_ENTRY: | 473 | case AT_ENTRY: | |
440 | pAUX_entry = auxp; | 474 | pAUX_entry = auxp; | |
441 | break; | 475 | break; | |
442 | case AT_EXECFD: | 476 | case AT_EXECFD: | |
443 | pAUX_execfd = auxp; | 477 | pAUX_execfd = auxp; | |
444 | break; | 478 | break; | |
445 | case AT_PHDR: | 479 | case AT_PHDR: | |
446 | pAUX_phdr = auxp; | 480 | pAUX_phdr = auxp; | |
447 | break; | 481 | break; | |
448 | case AT_PHENT: | 482 | case AT_PHENT: | |
449 | pAUX_phent = auxp; | 483 | pAUX_phent = auxp; | |
450 | break; | 484 | break; | |
451 | case AT_PHNUM: | 485 | case AT_PHNUM: | |
452 | pAUX_phnum = auxp; | 486 | pAUX_phnum = auxp; | |
453 | break; | 487 | break; | |
454 | #ifdef AT_EUID | 488 | #ifdef AT_EUID | |
455 | case AT_EUID: | 489 | case AT_EUID: | |
456 | pAUX_euid = auxp; | 490 | pAUX_euid = auxp; | |
457 | break; | 491 | break; | |
458 | case AT_RUID: | 492 | case AT_RUID: | |
459 | pAUX_ruid = auxp; | 493 | pAUX_ruid = auxp; | |
460 | break; | 494 | break; | |
461 | case AT_EGID: | 495 | case AT_EGID: | |
462 | pAUX_egid = auxp; | 496 | pAUX_egid = auxp; | |
463 | break; | 497 | break; | |
464 | case AT_RGID: | 498 | case AT_RGID: | |
465 | pAUX_rgid = auxp; | 499 | pAUX_rgid = auxp; | |
466 | break; | 500 | break; | |
467 | #endif | 501 | #endif | |
468 | #ifdef AT_SUN_EXECNAME | 502 | #ifdef AT_SUN_EXECNAME | |
469 | case AT_SUN_EXECNAME: | 503 | case AT_SUN_EXECNAME: | |
470 | execname = (const char *)(const void *)auxp->a_v; | 504 | execname = (const char *)(const void *)auxp->a_v; | |
471 | break; | 505 | break; | |
472 | #endif | 506 | #endif | |
473 | case AT_PAGESZ: | 507 | case AT_PAGESZ: | |
474 | pAUX_pagesz = auxp; | 508 | pAUX_pagesz = auxp; | |
475 | break; | 509 | break; | |
476 | } | 510 | } | |
477 | } | 511 | } | |
478 | 512 | |||
479 | /* Initialize and relocate ourselves. */ | 513 | /* Initialize and relocate ourselves. */ | |
480 | if (pAUX_base == NULL) { | 514 | if (pAUX_base == NULL) { | |
481 | _rtld_error("Bad pAUX_base"); | 515 | _rtld_error("Bad pAUX_base"); | |
482 | _rtld_die(); | 516 | _rtld_die(); | |
483 | } | 517 | } | |
484 | assert(pAUX_pagesz != NULL); | 518 | assert(pAUX_pagesz != NULL); | |
485 | _rtld_pagesz = (int)pAUX_pagesz->a_v; | 519 | _rtld_pagesz = (int)pAUX_pagesz->a_v; | |
486 | _rtld_init((caddr_t)pAUX_base->a_v, (caddr_t)relocbase, execname); | 520 | _rtld_init((caddr_t)pAUX_base->a_v, (caddr_t)relocbase, execname); | |
487 | 521 | |||
488 | __progname = _rtld_objself.path; | 522 | __progname = _rtld_objself.path; | |
489 | environ = env; | 523 | environ = env; | |
490 | 524 | |||
491 | _rtld_trust = ((pAUX_euid ? (uid_t)pAUX_euid->a_v : geteuid()) == | 525 | _rtld_trust = ((pAUX_euid ? (uid_t)pAUX_euid->a_v : geteuid()) == | |
492 | (pAUX_ruid ? (uid_t)pAUX_ruid->a_v : getuid())) && | 526 | (pAUX_ruid ? (uid_t)pAUX_ruid->a_v : getuid())) && | |
493 | ((pAUX_egid ? (gid_t)pAUX_egid->a_v : getegid()) == | 527 | ((pAUX_egid ? (gid_t)pAUX_egid->a_v : getegid()) == | |
494 | (pAUX_rgid ? (gid_t)pAUX_rgid->a_v : getgid())); | 528 | (pAUX_rgid ? (gid_t)pAUX_rgid->a_v : getgid())); | |
495 | 529 | |||
496 | #ifdef DEBUG | 530 | #ifdef DEBUG | |
497 | ld_debug = NULL; | 531 | ld_debug = NULL; | |
498 | #endif | 532 | #endif | |
499 | ld_bind_now = NULL; | 533 | ld_bind_now = NULL; | |
500 | ld_library_path = NULL; | 534 | ld_library_path = NULL; | |
501 | ld_preload = NULL; | 535 | ld_preload = NULL; | |
502 | /* | 536 | /* | |
503 | * Inline avoid using normal getenv/unsetenv here as the libc | 537 | * Inline avoid using normal getenv/unsetenv here as the libc | |
504 | * code is quite a bit more complicated. | 538 | * code is quite a bit more complicated. | |
505 | */ | 539 | */ | |
506 | for (oenvp = env; *env != NULL; ++env) { | 540 | for (oenvp = env; *env != NULL; ++env) { | |
507 | static const char bind_var[] = "LD_BIND_NOW="; | 541 | static const char bind_var[] = "LD_BIND_NOW="; | |
508 | static const char debug_var[] = "LD_DEBUG="; | 542 | static const char debug_var[] = "LD_DEBUG="; | |
509 | static const char path_var[] = "LD_LIBRARY_PATH="; | 543 | static const char path_var[] = "LD_LIBRARY_PATH="; | |
510 | static const char preload_var[] = "LD_PRELOAD="; | 544 | static const char preload_var[] = "LD_PRELOAD="; | |
511 | #define LEN(x) (sizeof(x) - 1) | 545 | #define LEN(x) (sizeof(x) - 1) | |
512 | 546 | |||
513 | if ((*env)[0] != 'L' || (*env)[1] != 'D') { | 547 | if ((*env)[0] != 'L' || (*env)[1] != 'D') { | |
514 | /* | 548 | /* | |
515 | * Special case to skip most entries without | 549 | * Special case to skip most entries without | |
516 | * the more expensive calls to strncmp. | 550 | * the more expensive calls to strncmp. | |
517 | */ | 551 | */ | |
518 | *oenvp++ = *env; | 552 | *oenvp++ = *env; | |
519 | } else if (strncmp(*env, debug_var, LEN(debug_var)) == 0) { | 553 | } else if (strncmp(*env, debug_var, LEN(debug_var)) == 0) { | |
520 | if (_rtld_trust) { | 554 | if (_rtld_trust) { | |
521 | #ifdef DEBUG | 555 | #ifdef DEBUG | |
522 | ld_debug = *env + LEN(debug_var); | 556 | ld_debug = *env + LEN(debug_var); | |
523 | #endif | 557 | #endif | |
524 | *oenvp++ = *env; | 558 | *oenvp++ = *env; | |
525 | } | 559 | } | |
526 | } else if (strncmp(*env, bind_var, LEN(bind_var)) == 0) { | 560 | } else if (strncmp(*env, bind_var, LEN(bind_var)) == 0) { | |
527 | ld_bind_now = *env + LEN(bind_var); | 561 | ld_bind_now = *env + LEN(bind_var); | |
528 | } else if (strncmp(*env, path_var, LEN(path_var)) == 0) { | 562 | } else if (strncmp(*env, path_var, LEN(path_var)) == 0) { | |
529 | if (_rtld_trust) { | 563 | if (_rtld_trust) { | |
530 | ld_library_path = *env + LEN(path_var); | 564 | ld_library_path = *env + LEN(path_var); | |
531 | *oenvp++ = *env; | 565 | *oenvp++ = *env; | |
532 | } | 566 | } | |
533 | } else if (strncmp(*env, preload_var, LEN(preload_var)) == 0) { | 567 | } else if (strncmp(*env, preload_var, LEN(preload_var)) == 0) { | |
534 | if (_rtld_trust) { | 568 | if (_rtld_trust) { | |
535 | ld_preload = *env + LEN(preload_var); | 569 | ld_preload = *env + LEN(preload_var); | |
536 | *oenvp++ = *env; | 570 | *oenvp++ = *env; | |
537 | } | 571 | } | |
538 | } else { | 572 | } else { | |
539 | *oenvp++ = *env; | 573 | *oenvp++ = *env; | |
540 | } | 574 | } | |
541 | #undef LEN | 575 | #undef LEN | |
542 | } | 576 | } | |
543 | *oenvp++ = NULL; | 577 | *oenvp++ = NULL; | |
544 | 578 | |||
545 | if (ld_bind_now != NULL && *ld_bind_now != '\0') | 579 | if (ld_bind_now != NULL && *ld_bind_now != '\0') | |
546 | bind_now = true; | 580 | bind_now = true; | |
547 | if (_rtld_trust) { | 581 | if (_rtld_trust) { | |
548 | #ifdef DEBUG | 582 | #ifdef DEBUG | |
549 | #ifdef RTLD_DEBUG | 583 | #ifdef RTLD_DEBUG | |
550 | debug = 0; | 584 | debug = 0; | |
551 | #endif | 585 | #endif | |
552 | if (ld_debug != NULL && *ld_debug != '\0') | 586 | if (ld_debug != NULL && *ld_debug != '\0') | |
553 | debug = 1; | 587 | debug = 1; | |
554 | #endif | 588 | #endif | |
555 | _rtld_add_paths(execname, &_rtld_paths, ld_library_path); | 589 | _rtld_add_paths(execname, &_rtld_paths, ld_library_path); | |
556 | } else { | 590 | } else { | |
557 | execname = NULL; | 591 | execname = NULL; | |
558 | } | 592 | } | |
559 | _rtld_process_hints(execname, &_rtld_paths, &_rtld_xforms, | 593 | _rtld_process_hints(execname, &_rtld_paths, &_rtld_xforms, | |
560 | _PATH_LD_HINTS); | 594 | _PATH_LD_HINTS); | |
561 | dbg(("dynamic linker is initialized, mapbase=%p, relocbase=%p", | 595 | dbg(("dynamic linker is initialized, mapbase=%p, relocbase=%p", | |
562 | _rtld_objself.mapbase, _rtld_objself.relocbase)); | 596 | _rtld_objself.mapbase, _rtld_objself.relocbase)); | |
563 | 597 | |||
564 | /* | 598 | /* | |
565 | * Load the main program, or process its program header if it is | 599 | * Load the main program, or process its program header if it is | |
566 | * already loaded. | 600 | * already loaded. | |
567 | */ | 601 | */ | |
568 | if (pAUX_execfd != NULL) { /* Load the main program. */ | 602 | if (pAUX_execfd != NULL) { /* Load the main program. */ | |
569 | int fd = pAUX_execfd->a_v; | 603 | int fd = pAUX_execfd->a_v; | |
570 | const char *obj_name = argv[0] ? argv[0] : "main program"; | 604 | const char *obj_name = argv[0] ? argv[0] : "main program"; | |
571 | dbg(("loading main program")); | 605 | dbg(("loading main program")); | |
572 | _rtld_objmain = _rtld_map_object(obj_name, fd, NULL); | 606 | _rtld_objmain = _rtld_map_object(obj_name, fd, NULL); | |
573 | close(fd); | 607 | close(fd); | |
574 | if (_rtld_objmain == NULL) | 608 | if (_rtld_objmain == NULL) | |
575 | _rtld_die(); | 609 | _rtld_die(); | |
576 | } else { /* Main program already loaded. */ | 610 | } else { /* Main program already loaded. */ | |
577 | const Elf_Phdr *phdr; | 611 | const Elf_Phdr *phdr; | |
578 | int phnum; | 612 | int phnum; | |
579 | caddr_t entry; | 613 | caddr_t entry; | |
580 | 614 | |||
581 | dbg(("processing main program's program header")); | 615 | dbg(("processing main program's program header")); | |
582 | assert(pAUX_phdr != NULL); | 616 | assert(pAUX_phdr != NULL); | |
583 | phdr = (const Elf_Phdr *) pAUX_phdr->a_v; | 617 | phdr = (const Elf_Phdr *) pAUX_phdr->a_v; | |
584 | assert(pAUX_phnum != NULL); | 618 | assert(pAUX_phnum != NULL); | |
585 | phnum = pAUX_phnum->a_v; | 619 | phnum = pAUX_phnum->a_v; | |
586 | assert(pAUX_phent != NULL); | 620 | assert(pAUX_phent != NULL); | |
587 | assert(pAUX_phent->a_v == sizeof(Elf_Phdr)); | 621 | assert(pAUX_phent->a_v == sizeof(Elf_Phdr)); | |
588 | assert(pAUX_entry != NULL); | 622 | assert(pAUX_entry != NULL); | |
589 | entry = (caddr_t) pAUX_entry->a_v; | 623 | entry = (caddr_t) pAUX_entry->a_v; | |
590 | _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry); | 624 | _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry); | |
591 | _rtld_objmain->path = xstrdup(argv[0] ? argv[0] : | 625 | _rtld_objmain->path = xstrdup(argv[0] ? argv[0] : | |
592 | "main program"); | 626 | "main program"); | |
593 | _rtld_objmain->pathlen = strlen(_rtld_objmain->path); | 627 | _rtld_objmain->pathlen = strlen(_rtld_objmain->path); | |
594 | } | 628 | } | |
595 | 629 | |||
596 | _rtld_objmain->mainprog = true; | 630 | _rtld_objmain->mainprog = true; | |
597 | 631 | |||
598 | /* | 632 | /* | |
599 | * Get the actual dynamic linker pathname from the executable if | 633 | * Get the actual dynamic linker pathname from the executable if | |
600 | * possible. (It should always be possible.) That ensures that | 634 | * possible. (It should always be possible.) That ensures that | |
601 | * gdb will find the right dynamic linker even if a non-standard | 635 | * gdb will find the right dynamic linker even if a non-standard | |
602 | * one is being used. | 636 | * one is being used. | |
603 | */ | 637 | */ | |
604 | if (_rtld_objmain->interp != NULL && | 638 | if (_rtld_objmain->interp != NULL && | |
605 | strcmp(_rtld_objmain->interp, _rtld_objself.path) != 0) | 639 | strcmp(_rtld_objmain->interp, _rtld_objself.path) != 0) | |
606 | _rtld_objself.path = xstrdup(_rtld_objmain->interp); | 640 | _rtld_objself.path = xstrdup(_rtld_objmain->interp); | |
607 | dbg(("actual dynamic linker is %s", _rtld_objself.path)); | 641 | dbg(("actual dynamic linker is %s", _rtld_objself.path)); | |
608 | 642 | |||
609 | _rtld_digest_dynamic(execname, _rtld_objmain); | 643 | _rtld_digest_dynamic(execname, _rtld_objmain); | |
610 | 644 | |||
611 | /* Link the main program into the list of objects. */ | 645 | /* Link the main program into the list of objects. */ | |
612 | *_rtld_objtail = _rtld_objmain; | 646 | *_rtld_objtail = _rtld_objmain; | |
613 | _rtld_objtail = &_rtld_objmain->next; | 647 | _rtld_objtail = &_rtld_objmain->next; | |
614 | _rtld_objcount++; | 648 | _rtld_objcount++; | |
615 | _rtld_objloads++; | 649 | _rtld_objloads++; | |
616 | 650 | |||
617 | _rtld_linkmap_add(_rtld_objmain); | 651 | _rtld_linkmap_add(_rtld_objmain); | |
618 | _rtld_linkmap_add(&_rtld_objself); | 652 | _rtld_linkmap_add(&_rtld_objself); | |
619 | 653 | |||
620 | ++_rtld_objmain->refcount; | 654 | ++_rtld_objmain->refcount; | |
621 | _rtld_objmain->mainref = 1; | 655 | _rtld_objmain->mainref = 1; | |
622 | _rtld_objlist_push_tail(&_rtld_list_main, _rtld_objmain); | 656 | _rtld_objlist_push_tail(&_rtld_list_main, _rtld_objmain); | |
623 | 657 | |||
624 | if (ld_preload) { | 658 | if (ld_preload) { | |
625 | /* | 659 | /* | |
626 | * Pre-load user-specified objects after the main program | 660 | * Pre-load user-specified objects after the main program | |
627 | * but before any shared object dependencies. | 661 | * but before any shared object dependencies. | |
628 | */ | 662 | */ | |
629 | dbg(("preloading objects")); | 663 | dbg(("preloading objects")); | |
630 | if (_rtld_preload(ld_preload) == -1) | 664 | if (_rtld_preload(ld_preload) == -1) | |
631 | _rtld_die(); | 665 | _rtld_die(); | |
632 | } | 666 | } | |
633 | 667 | |||
634 | dbg(("loading needed objects")); | 668 | dbg(("loading needed objects")); | |
635 | if (_rtld_load_needed_objects(_rtld_objmain, _RTLD_MAIN) == -1) | 669 | if (_rtld_load_needed_objects(_rtld_objmain, _RTLD_MAIN) == -1) | |
636 | _rtld_die(); | 670 | _rtld_die(); | |
637 | 671 | |||
638 | dbg(("checking for required versions")); | 672 | dbg(("checking for required versions")); | |
639 | for (obj = _rtld_objlist; obj != NULL; obj = obj->next) { | 673 | for (obj = _rtld_objlist; obj != NULL; obj = obj->next) { | |
640 | if (_rtld_verify_object_versions(obj) == -1) | 674 | if (_rtld_verify_object_versions(obj) == -1) | |
641 | _rtld_die(); | 675 | _rtld_die(); | |
642 | } | 676 | } | |
643 | 677 | |||
644 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | 678 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | |
645 | dbg(("initializing initial Thread Local Storage offsets")); | 679 | dbg(("initializing initial Thread Local Storage offsets")); | |
646 | /* | 680 | /* | |
647 | * All initial objects get the TLS space from the static block. | 681 | * All initial objects get the TLS space from the static block. | |
648 | */ | 682 | */ | |
649 | for (obj = _rtld_objlist; obj != NULL; obj = obj->next) | 683 | for (obj = _rtld_objlist; obj != NULL; obj = obj->next) | |
650 | _rtld_tls_offset_allocate(obj); | 684 | _rtld_tls_offset_allocate(obj); | |
651 | #endif | 685 | #endif | |
652 | 686 | |||
653 | dbg(("relocating objects")); | 687 | dbg(("relocating objects")); | |
654 | if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1) | 688 | if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1) | |
655 | _rtld_die(); | 689 | _rtld_die(); | |
656 | 690 | |||
657 | dbg(("doing copy relocations")); | 691 | dbg(("doing copy relocations")); | |
658 | if (_rtld_do_copy_relocations(_rtld_objmain) == -1) | 692 | if (_rtld_do_copy_relocations(_rtld_objmain) == -1) | |
659 | _rtld_die(); | 693 | _rtld_die(); | |
660 | 694 | |||
661 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | 695 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | |
662 | dbg(("initializing Thread Local Storage for main thread")); | 696 | dbg(("initializing Thread Local Storage for main thread")); | |
663 | /* | 697 | /* | |
664 | * Set up TLS area for the main thread. | 698 | * Set up TLS area for the main thread. | |
665 | * This has to be done after all relocations are processed, | 699 | * This has to be done after all relocations are processed, | |
666 | * since .tdata may contain relocations. | 700 | * since .tdata may contain relocations. | |
667 | */ | 701 | */ | |
668 | _rtld_tls_initial_allocation(); | 702 | _rtld_tls_initial_allocation(); | |
669 | #endif | 703 | #endif | |
670 | 704 | |||
671 | /* | 705 | /* | |
672 | * Set the __progname, environ and, __mainprog_obj before | 706 | * Set the __progname, environ and, __mainprog_obj before | |
673 | * calling anything that might use them. | 707 | * calling anything that might use them. | |
674 | */ | 708 | */ | |
675 | real___progname = _rtld_objmain_sym("__progname"); | 709 | real___progname = _rtld_objmain_sym("__progname"); | |
676 | if (real___progname) { | 710 | if (real___progname) { | |
677 | if (argv[0] != NULL) { | 711 | if (argv[0] != NULL) { | |
678 | if ((*real___progname = strrchr(argv[0], '/')) == NULL) | 712 | if ((*real___progname = strrchr(argv[0], '/')) == NULL) | |
679 | (*real___progname) = argv[0]; | 713 | (*real___progname) = argv[0]; | |
680 | else | 714 | else | |
681 | (*real___progname)++; | 715 | (*real___progname)++; | |
682 | } else { | 716 | } else { | |
683 | (*real___progname) = NULL; | 717 | (*real___progname) = NULL; | |
684 | } | 718 | } | |
685 | } | 719 | } | |
686 | real_environ = _rtld_objmain_sym("environ"); | 720 | real_environ = _rtld_objmain_sym("environ"); | |
687 | if (real_environ) | 721 | if (real_environ) | |
688 | *real_environ = environ; | 722 | *real_environ = environ; | |
689 | /* | 723 | /* | |
690 | * Set __mainprog_obj for old binaries. | 724 | * Set __mainprog_obj for old binaries. | |
691 | */ | 725 | */ | |
692 | real___mainprog_obj = _rtld_objmain_sym("__mainprog_obj"); | 726 | real___mainprog_obj = _rtld_objmain_sym("__mainprog_obj"); | |
693 | if (real___mainprog_obj) | 727 | if (real___mainprog_obj) | |
694 | *real___mainprog_obj = _rtld_objmain; | 728 | *real___mainprog_obj = _rtld_objmain; | |
695 | 729 | |||
696 | _rtld_exclusive_enter(&mask); | 730 | _rtld_exclusive_enter(&mask); | |
697 | 731 | |||
698 | dbg(("calling _init functions")); | 732 | dbg(("calling _init functions")); | |
699 | _rtld_call_init_functions(&mask); | 733 | _rtld_call_init_functions(&mask); | |
700 | 734 | |||
701 | dbg(("control at program entry point = %p, obj = %p, exit = %p", | 735 | dbg(("control at program entry point = %p, obj = %p, exit = %p", | |
702 | _rtld_objmain->entry, _rtld_objmain, _rtld_exit)); | 736 | _rtld_objmain->entry, _rtld_objmain, _rtld_exit)); | |
703 | 737 | |||
704 | _rtld_exclusive_exit(&mask); | 738 | _rtld_exclusive_exit(&mask); | |
705 | 739 | |||
706 | /* | 740 | /* | |
707 | * Return with the entry point and the exit procedure in at the top | 741 | * Return with the entry point and the exit procedure in at the top | |
708 | * of stack. | 742 | * of stack. | |
709 | */ | 743 | */ | |
710 | 744 | |||
711 | _rtld_debug_state(); /* say hello to gdb! */ | 745 | _rtld_debug_state(); /* say hello to gdb! */ | |
712 | 746 | |||
713 | ((void **) osp)[0] = _rtld_exit; | 747 | ((void **) osp)[0] = _rtld_exit; | |
714 | ((void **) osp)[1] = _rtld_objmain; | 748 | ((void **) osp)[1] = _rtld_objmain; | |
715 | return (Elf_Addr) _rtld_objmain->entry; | 749 | return (Elf_Addr) _rtld_objmain->entry; | |
716 | } | 750 | } | |
717 | 751 | |||
718 | void | 752 | void | |
719 | _rtld_die(void) | 753 | _rtld_die(void) | |
720 | { | 754 | { | |
721 | const char *msg = dlerror(); | 755 | const char *msg = dlerror(); | |
722 | 756 | |||
723 | if (msg == NULL) | 757 | if (msg == NULL) | |
724 | msg = "Fatal error"; | 758 | msg = "Fatal error"; | |
725 | xerrx(1, "%s", msg); | 759 | xerrx(1, "%s", msg); | |
726 | } | 760 | } | |
727 | 761 | |||
728 | static Obj_Entry * | 762 | static Obj_Entry * | |
729 | _rtld_dlcheck(void *handle) | 763 | _rtld_dlcheck(void *handle) | |
730 | { | 764 | { | |
731 | Obj_Entry *obj; | 765 | Obj_Entry *obj; | |
732 | 766 | |||
733 | for (obj = _rtld_objlist; obj != NULL; obj = obj->next) | 767 | for (obj = _rtld_objlist; obj != NULL; obj = obj->next) | |
734 | if (obj == (Obj_Entry *) handle) | 768 | if (obj == (Obj_Entry *) handle) | |
735 | break; | 769 | break; | |
736 | 770 | |||
737 | if (obj == NULL || obj->dl_refcount == 0) { | 771 | if (obj == NULL || obj->dl_refcount == 0) { | |
738 | xwarnx("Invalid shared object handle %p", handle); | 772 | xwarnx("Invalid shared object handle %p", handle); | |
739 | return NULL; | 773 | return NULL; | |
740 | } | 774 | } | |
741 | return obj; | 775 | return obj; | |
742 | } | 776 | } | |
743 | 777 | |||
744 | static void | 778 | static void | |
745 | _rtld_initlist_visit(Objlist* list, Obj_Entry *obj, int rev) | 779 | _rtld_initlist_visit(Objlist* list, Obj_Entry *obj, int rev) | |
746 | { | 780 | { | |
747 | Needed_Entry* elm; | 781 | Needed_Entry* elm; | |
748 | 782 | |||
749 | /* dbg(("_rtld_initlist_visit(%s)", obj->path)); */ | 783 | /* dbg(("_rtld_initlist_visit(%s)", obj->path)); */ | |
750 | 784 | |||
751 | if (obj->init_done) | 785 | if (obj->init_done) | |
752 | return; | 786 | return; | |
753 | obj->init_done = 1; | 787 | obj->init_done = 1; | |
754 | 788 | |||
755 | for (elm = obj->needed; elm != NULL; elm = elm->next) { | 789 | for (elm = obj->needed; elm != NULL; elm = elm->next) { | |
756 | if (elm->obj != NULL) { | 790 | if (elm->obj != NULL) { | |
757 | _rtld_initlist_visit(list, elm->obj, rev); | 791 | _rtld_initlist_visit(list, elm->obj, rev); | |
758 | } | 792 | } | |
759 | } | 793 | } | |
760 | 794 | |||
761 | if (rev) { | 795 | if (rev) { | |
762 | _rtld_objlist_push_head(list, obj); | 796 | _rtld_objlist_push_head(list, obj); | |
763 | } else { | 797 | } else { | |
764 | _rtld_objlist_push_tail(list, obj); | 798 | _rtld_objlist_push_tail(list, obj); | |
765 | } | 799 | } | |
766 | } | 800 | } | |
767 | 801 | |||
768 | static void | 802 | static void | |
769 | _rtld_initlist_tsort(Objlist* list, int rev) | 803 | _rtld_initlist_tsort(Objlist* list, int rev) | |
770 | { | 804 | { | |
771 | dbg(("_rtld_initlist_tsort")); | 805 | dbg(("_rtld_initlist_tsort")); | |
772 | 806 | |||
773 | Obj_Entry* obj; | 807 | Obj_Entry* obj; | |
774 | 808 | |||
775 | for (obj = _rtld_objlist->next; obj; obj = obj->next) { | 809 | for (obj = _rtld_objlist->next; obj; obj = obj->next) { | |
776 | obj->init_done = 0; | 810 | obj->init_done = 0; | |
777 | } | 811 | } | |
778 | 812 | |||
779 | for (obj = _rtld_objlist->next; obj; obj = obj->next) { | 813 | for (obj = _rtld_objlist->next; obj; obj = obj->next) { | |
780 | _rtld_initlist_visit(list, obj, rev); | 814 | _rtld_initlist_visit(list, obj, rev); | |
781 | } | 815 | } | |
782 | } | 816 | } | |
783 | 817 | |||
784 | static void | 818 | static void | |
785 | _rtld_init_dag(Obj_Entry *root) | 819 | _rtld_init_dag(Obj_Entry *root) | |
786 | { | 820 | { | |
787 | 821 | |||
788 | _rtld_init_dag1(root, root); | 822 | _rtld_init_dag1(root, root); | |
789 | } | 823 | } | |
790 | 824 | |||
791 | static void | 825 | static void | |
792 | _rtld_init_dag1(Obj_Entry *root, Obj_Entry *obj) | 826 | _rtld_init_dag1(Obj_Entry *root, Obj_Entry *obj) | |
793 | { | 827 | { | |
794 | const Needed_Entry *needed; | 828 | const Needed_Entry *needed; | |
795 | 829 | |||
796 | if (!obj->mainref) { | 830 | if (!obj->mainref) { | |
797 | if (_rtld_objlist_find(&obj->dldags, root)) | 831 | if (_rtld_objlist_find(&obj->dldags, root)) | |
798 | return; | 832 | return; | |
799 | dbg(("add %p (%s) to %p (%s) DAG", obj, obj->path, root, | 833 | dbg(("add %p (%s) to %p (%s) DAG", obj, obj->path, root, | |
800 | root->path)); | 834 | root->path)); | |
801 | _rtld_objlist_push_tail(&obj->dldags, root); | 835 | _rtld_objlist_push_tail(&obj->dldags, root); | |
802 | _rtld_objlist_push_tail(&root->dagmembers, obj); | 836 | _rtld_objlist_push_tail(&root->dagmembers, obj); | |
803 | } | 837 | } | |
804 | for (needed = obj->needed; needed != NULL; needed = needed->next) | 838 | for (needed = obj->needed; needed != NULL; needed = needed->next) | |
805 | if (needed->obj != NULL) | 839 | if (needed->obj != NULL) | |
806 | _rtld_init_dag1(root, needed->obj); | 840 | _rtld_init_dag1(root, needed->obj); | |
807 | } | 841 | } | |
808 | 842 | |||
809 | /* | 843 | /* | |
810 | * Note, this is called only for objects loaded by dlopen(). | 844 | * Note, this is called only for objects loaded by dlopen(). | |
811 | */ | 845 | */ | |
812 | static void | 846 | static void | |
813 | _rtld_unload_object(sigset_t *mask, Obj_Entry *root, bool do_fini_funcs) | 847 | _rtld_unload_object(sigset_t *mask, Obj_Entry *root, bool do_fini_funcs) | |
814 | { | 848 | { | |
815 | 849 | |||
816 | _rtld_unref_dag(root); | 850 | _rtld_unref_dag(root); | |
817 | if (root->refcount == 0) { /* We are finished with some objects. */ | 851 | if (root->refcount == 0) { /* We are finished with some objects. */ | |
818 | Obj_Entry *obj; | 852 | Obj_Entry *obj; | |
819 | Obj_Entry **linkp; | 853 | Obj_Entry **linkp; | |
820 | Objlist_Entry *elm; | 854 | Objlist_Entry *elm; | |
821 | 855 | |||
822 | /* Finalize objects that are about to be unmapped. */ | 856 | /* Finalize objects that are about to be unmapped. */ | |
823 | if (do_fini_funcs) | 857 | if (do_fini_funcs) | |
824 | _rtld_call_fini_functions(mask, 0); | 858 | _rtld_call_fini_functions(mask, 0); | |
825 | 859 | |||
826 | /* Remove the DAG from all objects' DAG lists. */ | 860 | /* Remove the DAG from all objects' DAG lists. */ | |
827 | SIMPLEQ_FOREACH(elm, &root->dagmembers, link) | 861 | SIMPLEQ_FOREACH(elm, &root->dagmembers, link) | |
828 | _rtld_objlist_remove(&elm->obj->dldags, root); | 862 | _rtld_objlist_remove(&elm->obj->dldags, root); | |
829 | 863 | |||
830 | /* Remove the DAG from the RTLD_GLOBAL list. */ | 864 | /* Remove the DAG from the RTLD_GLOBAL list. */ | |
831 | if (root->globalref) { | 865 | if (root->globalref) { | |
832 | root->globalref = 0; | 866 | root->globalref = 0; | |
833 | _rtld_objlist_remove(&_rtld_list_global, root); | 867 | _rtld_objlist_remove(&_rtld_list_global, root); | |
834 | } | 868 | } | |
835 | 869 | |||
836 | /* Unmap all objects that are no longer referenced. */ | 870 | /* Unmap all objects that are no longer referenced. */ | |
837 | linkp = &_rtld_objlist->next; | 871 | linkp = &_rtld_objlist->next; | |
838 | while ((obj = *linkp) != NULL) { | 872 | while ((obj = *linkp) != NULL) { | |
839 | if (obj->refcount == 0) { | 873 | if (obj->refcount == 0) { | |
840 | dbg(("unloading \"%s\"", obj->path)); | 874 | dbg(("unloading \"%s\"", obj->path)); | |
841 | if (obj->ehdr != MAP_FAILED) | 875 | if (obj->ehdr != MAP_FAILED) | |
842 | munmap(obj->ehdr, _rtld_pagesz); | 876 | munmap(obj->ehdr, _rtld_pagesz); | |
843 | munmap(obj->mapbase, obj->mapsize); | 877 | munmap(obj->mapbase, obj->mapsize); | |
844 | _rtld_objlist_remove(&_rtld_list_global, obj); | 878 | _rtld_objlist_remove(&_rtld_list_global, obj); | |
845 | _rtld_linkmap_delete(obj); | 879 | _rtld_linkmap_delete(obj); | |
846 | *linkp = obj->next; | 880 | *linkp = obj->next; | |
847 | _rtld_objcount--; | 881 | _rtld_objcount--; | |
848 | _rtld_obj_free(obj); | 882 | _rtld_obj_free(obj); | |
849 | } else | 883 | } else | |
850 | linkp = &obj->next; | 884 | linkp = &obj->next; | |
851 | } | 885 | } | |
852 | _rtld_objtail = linkp; | 886 | _rtld_objtail = linkp; | |
853 | } | 887 | } | |
854 | } | 888 | } | |
855 | 889 | |||
856 | void | 890 | void | |
857 | _rtld_ref_dag(Obj_Entry *root) | 891 | _rtld_ref_dag(Obj_Entry *root) | |
858 | { | 892 | { | |
859 | const Needed_Entry *needed; | 893 | const Needed_Entry *needed; | |
860 | 894 | |||
861 | assert(root); | 895 | assert(root); | |
862 | 896 | |||
863 | ++root->refcount; | 897 | ++root->refcount; | |
864 | 898 | |||
865 | dbg(("incremented reference on \"%s\" (%d)", root->path, | 899 | dbg(("incremented reference on \"%s\" (%d)", root->path, | |
866 | root->refcount)); | 900 | root->refcount)); | |
867 | for (needed = root->needed; needed != NULL; | 901 | for (needed = root->needed; needed != NULL; | |
868 | needed = needed->next) { | 902 | needed = needed->next) { | |
869 | if (needed->obj != NULL) | 903 | if (needed->obj != NULL) | |
870 | _rtld_ref_dag(needed->obj); | 904 | _rtld_ref_dag(needed->obj); | |
871 | } | 905 | } | |
872 | } | 906 | } | |
873 | 907 | |||
874 | static void | 908 | static void | |
875 | _rtld_unref_dag(Obj_Entry *root) | 909 | _rtld_unref_dag(Obj_Entry *root) | |
876 | { | 910 | { | |
877 | 911 | |||
878 | assert(root); | 912 | assert(root); | |
879 | assert(root->refcount != 0); | 913 | assert(root->refcount != 0); | |
880 | 914 | |||
881 | --root->refcount; | 915 | --root->refcount; | |
882 | dbg(("decremented reference on \"%s\" (%d)", root->path, | 916 | dbg(("decremented reference on \"%s\" (%d)", root->path, | |
883 | root->refcount)); | 917 | root->refcount)); | |
884 | 918 | |||
885 | if (root->refcount == 0) { | 919 | if (root->refcount == 0) { | |
886 | const Needed_Entry *needed; | 920 | const Needed_Entry *needed; | |
887 | 921 | |||
888 | for (needed = root->needed; needed != NULL; | 922 | for (needed = root->needed; needed != NULL; | |
889 | needed = needed->next) { | 923 | needed = needed->next) { | |
890 | if (needed->obj != NULL) | 924 | if (needed->obj != NULL) | |
891 | _rtld_unref_dag(needed->obj); | 925 | _rtld_unref_dag(needed->obj); | |
892 | } | 926 | } | |
893 | } | 927 | } | |
894 | } | 928 | } | |
895 | 929 | |||
896 | __strong_alias(__dlclose,dlclose) | 930 | __strong_alias(__dlclose,dlclose) | |
897 | int | 931 | int | |
898 | dlclose(void *handle) | 932 | dlclose(void *handle) | |
899 | { | 933 | { | |
900 | Obj_Entry *root; | 934 | Obj_Entry *root; | |
901 | sigset_t mask; | 935 | sigset_t mask; | |
902 | 936 | |||
903 | dbg(("dlclose of %p", handle)); | 937 | dbg(("dlclose of %p", handle)); | |
904 | 938 | |||
905 | _rtld_exclusive_enter(&mask); | 939 | _rtld_exclusive_enter(&mask); | |
906 | 940 | |||
907 | root = _rtld_dlcheck(handle); | 941 | root = _rtld_dlcheck(handle); | |
908 | 942 | |||
909 | if (root == NULL) { | 943 | if (root == NULL) { | |
910 | _rtld_exclusive_exit(&mask); | 944 | _rtld_exclusive_exit(&mask); | |
911 | return -1; | 945 | return -1; | |
912 | } | 946 | } | |
913 | 947 | |||
914 | _rtld_debug.r_state = RT_DELETE; | 948 | _rtld_debug.r_state = RT_DELETE; | |
915 | _rtld_debug_state(); | 949 | _rtld_debug_state(); | |
916 | 950 | |||
917 | --root->dl_refcount; | 951 | --root->dl_refcount; | |
918 | _rtld_unload_object(&mask, root, true); | 952 | _rtld_unload_object(&mask, root, true); | |
919 | 953 | |||
920 | _rtld_debug.r_state = RT_CONSISTENT; | 954 | _rtld_debug.r_state = RT_CONSISTENT; | |
921 | _rtld_debug_state(); | 955 | _rtld_debug_state(); | |
922 | 956 | |||
923 | _rtld_exclusive_exit(&mask); | 957 | _rtld_exclusive_exit(&mask); | |
924 | 958 | |||
925 | return 0; | 959 | return 0; | |
926 | } | 960 | } | |
927 | 961 | |||
928 | __strong_alias(__dlerror,dlerror) | 962 | __strong_alias(__dlerror,dlerror) | |
929 | char * | 963 | char * | |
930 | dlerror(void) | 964 | dlerror(void) | |
931 | { | 965 | { | |
932 | char *msg = error_message; | 966 | char *msg = error_message; | |
933 | 967 | |||
934 | error_message = NULL; | 968 | error_message = NULL; | |
935 | return msg; | 969 | return msg; | |
936 | } | 970 | } | |
937 | 971 | |||
938 | __strong_alias(__dlopen,dlopen) | 972 | __strong_alias(__dlopen,dlopen) | |
939 | void * | 973 | void * | |
940 | dlopen(const char *name, int mode) | 974 | dlopen(const char *name, int mode) | |
941 | { | 975 | { | |
942 | Obj_Entry **old_obj_tail = _rtld_objtail; | 976 | Obj_Entry **old_obj_tail = _rtld_objtail; | |
943 | Obj_Entry *obj = NULL; | 977 | Obj_Entry *obj = NULL; | |
944 | int flags = _RTLD_DLOPEN; | 978 | int flags = _RTLD_DLOPEN; | |
945 | bool nodelete; | 979 | bool nodelete; | |
946 | bool now; | 980 | bool now; | |
947 | sigset_t mask; | 981 | sigset_t mask; | |
948 | int result; | 982 | int result; | |
949 | 983 | |||
950 | dbg(("dlopen of %s %d", name, mode)); | 984 | dbg(("dlopen of %s %d", name, mode)); | |
951 | 985 | |||
952 | _rtld_exclusive_enter(&mask); | 986 | _rtld_exclusive_enter(&mask); | |
953 | 987 | |||
954 | flags |= (mode & RTLD_GLOBAL) ? _RTLD_GLOBAL : 0; | 988 | flags |= (mode & RTLD_GLOBAL) ? _RTLD_GLOBAL : 0; | |
955 | flags |= (mode & RTLD_NOLOAD) ? _RTLD_NOLOAD : 0; | 989 | flags |= (mode & RTLD_NOLOAD) ? _RTLD_NOLOAD : 0; | |
956 | 990 | |||
957 | nodelete = (mode & RTLD_NODELETE) ? true : false; | 991 | nodelete = (mode & RTLD_NODELETE) ? true : false; | |
958 | now = ((mode & RTLD_MODEMASK) == RTLD_NOW) ? true : false; | 992 | now = ((mode & RTLD_MODEMASK) == RTLD_NOW) ? true : false; | |
959 | 993 | |||
960 | _rtld_debug.r_state = RT_ADD; | 994 | _rtld_debug.r_state = RT_ADD; | |
961 | _rtld_debug_state(); | 995 | _rtld_debug_state(); | |
962 | 996 | |||
963 | if (name == NULL) { | 997 | if (name == NULL) { | |
964 | obj = _rtld_objmain; | 998 | obj = _rtld_objmain; | |
965 | obj->refcount++; | 999 | obj->refcount++; | |
966 | } else | 1000 | } else | |
967 | obj = _rtld_load_library(name, _rtld_objmain, flags); | 1001 | obj = _rtld_load_library(name, _rtld_objmain, flags); | |
968 | 1002 | |||
969 | 1003 | |||
970 | if (obj != NULL) { | 1004 | if (obj != NULL) { | |
971 | ++obj->dl_refcount; | 1005 | ++obj->dl_refcount; | |
972 | if (*old_obj_tail != NULL) { /* We loaded something new. */ | 1006 | if (*old_obj_tail != NULL) { /* We loaded something new. */ | |
973 | assert(*old_obj_tail == obj); | 1007 | assert(*old_obj_tail == obj); | |
974 | 1008 | |||
975 | result = _rtld_load_needed_objects(obj, flags); | 1009 | result = _rtld_load_needed_objects(obj, flags); | |
976 | if (result != -1) { | 1010 | if (result != -1) { | |
977 | Objlist_Entry *entry; | 1011 | Objlist_Entry *entry; | |
978 | _rtld_init_dag(obj); | 1012 | _rtld_init_dag(obj); | |
979 | SIMPLEQ_FOREACH(entry, &obj->dagmembers, link) { | 1013 | SIMPLEQ_FOREACH(entry, &obj->dagmembers, link) { | |
980 | result = _rtld_verify_object_versions(entry->obj); | 1014 | result = _rtld_verify_object_versions(entry->obj); | |
981 | if (result == -1) | 1015 | if (result == -1) | |
982 | break; | 1016 | break; | |
983 | } | 1017 | } | |
984 | } | 1018 | } | |
985 | if (result == -1 || _rtld_relocate_objects(obj, | 1019 | if (result == -1 || _rtld_relocate_objects(obj, | |
986 | (now || obj->z_now)) == -1) { | 1020 | (now || obj->z_now)) == -1) { | |
987 | _rtld_unload_object(&mask, obj, false); | 1021 | _rtld_unload_object(&mask, obj, false); | |
988 | obj->dl_refcount--; | 1022 | obj->dl_refcount--; | |
989 | obj = NULL; | 1023 | obj = NULL; | |
990 | } else { | 1024 | } else { | |
991 | _rtld_call_init_functions(&mask); | 1025 | _rtld_call_init_functions(&mask); | |
992 | } | 1026 | } | |
993 | } | 1027 | } | |
994 | if (obj != NULL) { | 1028 | if (obj != NULL) { | |
995 | if ((nodelete || obj->z_nodelete) && !obj->ref_nodel) { | 1029 | if ((nodelete || obj->z_nodelete) && !obj->ref_nodel) { | |
996 | dbg(("dlopen obj %s nodelete", obj->path)); | 1030 | dbg(("dlopen obj %s nodelete", obj->path)); | |
997 | _rtld_ref_dag(obj); | 1031 | _rtld_ref_dag(obj); | |
998 | obj->z_nodelete = obj->ref_nodel = true; | 1032 | obj->z_nodelete = obj->ref_nodel = true; | |
999 | } | 1033 | } | |
1000 | } | 1034 | } | |
1001 | } | 1035 | } | |
1002 | _rtld_debug.r_state = RT_CONSISTENT; | 1036 | _rtld_debug.r_state = RT_CONSISTENT; | |
1003 | _rtld_debug_state(); | 1037 | _rtld_debug_state(); | |
1004 | 1038 | |||
1005 | _rtld_exclusive_exit(&mask); | 1039 | _rtld_exclusive_exit(&mask); | |
1006 | 1040 | |||
1007 | return obj; | 1041 | return obj; | |
1008 | } | 1042 | } | |
1009 | 1043 | |||
1010 | /* | 1044 | /* | |
1011 | * Find a symbol in the main program. | 1045 | * Find a symbol in the main program. | |
1012 | */ | 1046 | */ | |
1013 | void * | 1047 | void * | |
1014 | _rtld_objmain_sym(const char *name) | 1048 | _rtld_objmain_sym(const char *name) | |
1015 | { | 1049 | { | |
1016 | unsigned long hash; | 1050 | unsigned long hash; | |
1017 | const Elf_Sym *def; | 1051 | const Elf_Sym *def; | |
1018 | const Obj_Entry *obj; | 1052 | const Obj_Entry *obj; | |
1019 | DoneList donelist; | 1053 | DoneList donelist; | |
1020 | 1054 | |||
1021 | hash = _rtld_elf_hash(name); | 1055 | hash = _rtld_elf_hash(name); | |
1022 | obj = _rtld_objmain; | 1056 | obj = _rtld_objmain; | |
1023 | _rtld_donelist_init(&donelist); | 1057 | _rtld_donelist_init(&donelist); | |
1024 | 1058 | |||
1025 | def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, 0, | 1059 | def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, 0, | |
1026 | NULL, &donelist); | 1060 | NULL, &donelist); | |
1027 | 1061 | |||
1028 | if (def != NULL) | 1062 | if (def != NULL) | |
1029 | return obj->relocbase + def->st_value; | 1063 | return obj->relocbase + def->st_value; | |
1030 | return NULL; | 1064 | return NULL; | |
1031 | } | 1065 | } | |
1032 | 1066 | |||
1033 | #ifdef __powerpc__ | 1067 | #ifdef __powerpc__ | |
1034 | static void * | 1068 | static void * | |
1035 | hackish_return_address(void) | 1069 | hackish_return_address(void) | |
1036 | { | 1070 | { | |
1037 | return __builtin_return_address(1); | 1071 | return __builtin_return_address(1); | |
1038 | } | 1072 | } | |
1039 | #endif | 1073 | #endif | |
1040 | 1074 | |||
1041 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | 1075 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | |
1042 | #define lookup_mutex_enter() _rtld_exclusive_enter(&mask) | 1076 | #define lookup_mutex_enter() _rtld_exclusive_enter(&mask) | |
1043 | #define lookup_mutex_exit() _rtld_exclusive_exit(&mask) | 1077 | #define lookup_mutex_exit() _rtld_exclusive_exit(&mask) | |
1044 | #else | 1078 | #else | |
1045 | #define lookup_mutex_enter() _rtld_shared_enter() | 1079 | #define lookup_mutex_enter() _rtld_shared_enter() | |
1046 | #define lookup_mutex_exit() _rtld_shared_exit() | 1080 | #define lookup_mutex_exit() _rtld_shared_exit() | |
1047 | #endif | 1081 | #endif | |
1048 | 1082 | |||
1049 | static void * | 1083 | static void * | |
1050 | do_dlsym(void *handle, const char *name, const Ver_Entry *ventry, void *retaddr) | 1084 | do_dlsym(void *handle, const char *name, const Ver_Entry *ventry, void *retaddr) | |
1051 | { | 1085 | { | |
1052 | const Obj_Entry *obj; | 1086 | const Obj_Entry *obj; | |
1053 | unsigned long hash; | 1087 | unsigned long hash; | |
1054 | const Elf_Sym *def; | 1088 | const Elf_Sym *def; | |
1055 | const Obj_Entry *defobj; | 1089 | const Obj_Entry *defobj; | |
1056 | DoneList donelist; | 1090 | DoneList donelist; | |
1057 | const u_int flags = SYMLOOK_DLSYM | SYMLOOK_IN_PLT; | 1091 | const u_int flags = SYMLOOK_DLSYM | SYMLOOK_IN_PLT; | |
1058 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | 1092 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | |
1059 | sigset_t mask; | 1093 | sigset_t mask; | |
1060 | #endif | 1094 | #endif | |
1061 | 1095 | |||
1062 | lookup_mutex_enter(); | 1096 | lookup_mutex_enter(); | |
1063 | 1097 | |||
1064 | hash = _rtld_elf_hash(name); | 1098 | hash = _rtld_elf_hash(name); | |
1065 | def = NULL; | 1099 | def = NULL; | |
1066 | defobj = NULL; | 1100 | defobj = NULL; | |
1067 | 1101 | |||
1068 | switch ((intptr_t)handle) { | 1102 | switch ((intptr_t)handle) { | |
1069 | case (intptr_t)NULL: | 1103 | case (intptr_t)NULL: | |
1070 | case (intptr_t)RTLD_NEXT: | 1104 | case (intptr_t)RTLD_NEXT: | |
1071 | case (intptr_t)RTLD_DEFAULT: | 1105 | case (intptr_t)RTLD_DEFAULT: | |
1072 | case (intptr_t)RTLD_SELF: | 1106 | case (intptr_t)RTLD_SELF: | |
1073 | if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) { | 1107 | if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) { | |
1074 | _rtld_error("Cannot determine caller's shared object"); | 1108 | _rtld_error("Cannot determine caller's shared object"); | |
1075 | lookup_mutex_exit(); | 1109 | lookup_mutex_exit(); | |
1076 | return NULL; | 1110 | return NULL; | |
1077 | } | 1111 | } | |
1078 | 1112 | |||
1079 | switch ((intptr_t)handle) { | 1113 | switch ((intptr_t)handle) { | |
1080 | case (intptr_t)NULL: /* Just the caller's shared object. */ | 1114 | case (intptr_t)NULL: /* Just the caller's shared object. */ | |
1081 | def = _rtld_symlook_obj(name, hash, obj, flags, ventry); | 1115 | def = _rtld_symlook_obj(name, hash, obj, flags, ventry); | |
1082 | defobj = obj; | 1116 | defobj = obj; | |
1083 | break; | 1117 | break; | |
1084 | 1118 | |||
1085 | case (intptr_t)RTLD_NEXT: /* Objects after callers */ | 1119 | case (intptr_t)RTLD_NEXT: /* Objects after callers */ | |
1086 | obj = obj->next; | 1120 | obj = obj->next; | |
1087 | /*FALLTHROUGH*/ | 1121 | /*FALLTHROUGH*/ | |
1088 | 1122 | |||
1089 | case (intptr_t)RTLD_SELF: /* Caller included */ | 1123 | case (intptr_t)RTLD_SELF: /* Caller included */ | |
1090 | for (; obj; obj = obj->next) { | 1124 | for (; obj; obj = obj->next) { | |
1091 | if ((def = _rtld_symlook_obj(name, hash, obj, | 1125 | if ((def = _rtld_symlook_obj(name, hash, obj, | |
1092 | flags, ventry)) != NULL) { | 1126 | flags, ventry)) != NULL) { | |
1093 | defobj = obj; | 1127 | defobj = obj; | |
1094 | break; | 1128 | break; | |
1095 | } | 1129 | } | |
1096 | } | 1130 | } | |
1097 | break; | 1131 | break; | |
1098 | 1132 | |||
1099 | case (intptr_t)RTLD_DEFAULT: | 1133 | case (intptr_t)RTLD_DEFAULT: | |
1100 | def = _rtld_symlook_default(name, hash, obj, &defobj, | 1134 | def = _rtld_symlook_default(name, hash, obj, &defobj, | |
1101 | flags, ventry); | 1135 | flags, ventry); | |
1102 | break; | 1136 | break; | |
1103 | 1137 | |||
1104 | default: | 1138 | default: | |
1105 | abort(); | 1139 | abort(); | |
1106 | } | 1140 | } | |
1107 | break; | 1141 | break; | |
1108 | 1142 | |||
1109 | default: | 1143 | default: | |
1110 | if ((obj = _rtld_dlcheck(handle)) == NULL) { | 1144 | if ((obj = _rtld_dlcheck(handle)) == NULL) { | |
1111 | lookup_mutex_exit(); | 1145 | lookup_mutex_exit(); | |
1112 | return NULL; | 1146 | return NULL; | |
1113 | } | 1147 | } | |
1114 | 1148 | |||
1115 | _rtld_donelist_init(&donelist); | 1149 | _rtld_donelist_init(&donelist); | |
1116 | 1150 | |||
1117 | if (obj->mainprog) { | 1151 | if (obj->mainprog) { | |
1118 | /* Search main program and all libraries loaded by it */ | 1152 | /* Search main program and all libraries loaded by it */ | |
1119 | def = _rtld_symlook_list(name, hash, &_rtld_list_main, | 1153 | def = _rtld_symlook_list(name, hash, &_rtld_list_main, | |
1120 | &defobj, flags, ventry, &donelist); | 1154 | &defobj, flags, ventry, &donelist); | |
1121 | } else { | 1155 | } else { | |
1122 | Needed_Entry fake; | 1156 | Needed_Entry fake; | |
1123 | DoneList depth; | 1157 | DoneList depth; | |
1124 | 1158 | |||
1125 | /* Search the object and all the libraries loaded by it. */ | 1159 | /* Search the object and all the libraries loaded by it. */ | |
1126 | fake.next = NULL; | 1160 | fake.next = NULL; | |
1127 | fake.obj = __UNCONST(obj); | 1161 | fake.obj = __UNCONST(obj); | |
1128 | fake.name = 0; | 1162 | fake.name = 0; | |
1129 | 1163 | |||
1130 | _rtld_donelist_init(&depth); | 1164 | _rtld_donelist_init(&depth); | |
1131 | def = _rtld_symlook_needed(name, hash, &fake, &defobj, | 1165 | def = _rtld_symlook_needed(name, hash, &fake, &defobj, | |
1132 | flags, ventry, &donelist, &depth); | 1166 | flags, ventry, &donelist, &depth); | |
1133 | } | 1167 | } | |
1134 | 1168 | |||
1135 | break; | 1169 | break; | |
1136 | } | 1170 | } | |
1137 | 1171 | |||
1138 | if (def != NULL) { | 1172 | if (def != NULL) { | |
1139 | void *p; | 1173 | void *p; | |
1140 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | 1174 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | |
1141 | if (ELF_ST_TYPE(def->st_info) == STT_FUNC) { | 1175 | if (ELF_ST_TYPE(def->st_info) == STT_FUNC) { | |
1142 | p = (void *)_rtld_function_descriptor_alloc(defobj, | 1176 | p = (void *)_rtld_function_descriptor_alloc(defobj, | |
1143 | def, 0); | 1177 | def, 0); | |
1144 | lookup_mutex_exit(); | 1178 | lookup_mutex_exit(); | |
1145 | return p; | 1179 | return p; | |
1146 | } | 1180 | } | |
1147 | #endif /* __HAVE_FUNCTION_DESCRIPTORS */ | 1181 | #endif /* __HAVE_FUNCTION_DESCRIPTORS */ | |
1148 | p = defobj->relocbase + def->st_value; | 1182 | p = defobj->relocbase + def->st_value; | |
1149 | lookup_mutex_exit(); | 1183 | lookup_mutex_exit(); | |
1150 | return p; | 1184 | return p; | |
1151 | } | 1185 | } | |
1152 | 1186 | |||
1153 | _rtld_error("Undefined symbol \"%s\"", name); | 1187 | _rtld_error("Undefined symbol \"%s\"", name); | |
1154 | lookup_mutex_exit(); | 1188 | lookup_mutex_exit(); | |
1155 | return NULL; | 1189 | return NULL; | |
1156 | } | 1190 | } | |
1157 | 1191 | |||
1158 | __strong_alias(__dlsym,dlsym) | 1192 | __strong_alias(__dlsym,dlsym) | |
1159 | void * | 1193 | void * | |
1160 | dlsym(void *handle, const char *name) | 1194 | dlsym(void *handle, const char *name) | |
1161 | { | 1195 | { | |
1162 | void *retaddr; | 1196 | void *retaddr; | |
1163 | 1197 | |||
1164 | dbg(("dlsym of %s in %p", name, handle)); | 1198 | dbg(("dlsym of %s in %p", name, handle)); | |
1165 | 1199 | |||
1166 | #ifdef __powerpc__ | 1200 | #ifdef __powerpc__ | |
1167 | retaddr = hackish_return_address(); | 1201 | retaddr = hackish_return_address(); | |
1168 | #else | 1202 | #else | |
1169 | retaddr = __builtin_return_address(0); | 1203 | retaddr = __builtin_return_address(0); | |
1170 | #endif | 1204 | #endif | |
1171 | return do_dlsym(handle, name, NULL, retaddr); | 1205 | return do_dlsym(handle, name, NULL, retaddr); | |
1172 | } | 1206 | } | |
1173 | 1207 | |||
1174 | __strong_alias(__dlvsym,dlvsym) | 1208 | __strong_alias(__dlvsym,dlvsym) | |
1175 | void * | 1209 | void * | |
1176 | dlvsym(void *handle, const char *name, const char *version) | 1210 | dlvsym(void *handle, const char *name, const char *version) | |
1177 | { | 1211 | { | |
1178 | Ver_Entry *ventry = NULL; | 1212 | Ver_Entry *ventry = NULL; | |
1179 | Ver_Entry ver_entry; | 1213 | Ver_Entry ver_entry; | |
1180 | void *retaddr; | 1214 | void *retaddr; | |
1181 | 1215 | |||
1182 | dbg(("dlvsym of %s@%s in %p", name, version ? version : NULL, handle)); | 1216 | dbg(("dlvsym of %s@%s in %p", name, version ? version : NULL, handle)); | |
1183 | 1217 | |||
1184 | if (version != NULL) { | 1218 | if (version != NULL) { | |
1185 | ver_entry.name = version; | 1219 | ver_entry.name = version; | |
1186 | ver_entry.file = NULL; | 1220 | ver_entry.file = NULL; | |
1187 | ver_entry.hash = _rtld_elf_hash(version); | 1221 | ver_entry.hash = _rtld_elf_hash(version); | |
1188 | ver_entry.flags = 0; | 1222 | ver_entry.flags = 0; | |
1189 | ventry = &ver_entry; | 1223 | ventry = &ver_entry; | |
1190 | } | 1224 | } | |
1191 | #ifdef __powerpc__ | 1225 | #ifdef __powerpc__ | |
1192 | retaddr = hackish_return_address(); | 1226 | retaddr = hackish_return_address(); | |
1193 | #else | 1227 | #else | |
1194 | retaddr = __builtin_return_address(0); | 1228 | retaddr = __builtin_return_address(0); | |
1195 | #endif | 1229 | #endif | |
1196 | return do_dlsym(handle, name, ventry, retaddr); | 1230 | return do_dlsym(handle, name, ventry, retaddr); | |
1197 | } | 1231 | } | |
1198 | 1232 | |||
1199 | __strong_alias(__dladdr,dladdr) | 1233 | __strong_alias(__dladdr,dladdr) | |
1200 | int | 1234 | int | |
1201 | dladdr(const void *addr, Dl_info *info) | 1235 | dladdr(const void *addr, Dl_info *info) | |
1202 | { | 1236 | { | |
1203 | const Obj_Entry *obj; | 1237 | const Obj_Entry *obj; | |
1204 | const Elf_Sym *def, *best_def; | 1238 | const Elf_Sym *def, *best_def; | |
1205 | void *symbol_addr; | 1239 | void *symbol_addr; | |
1206 | unsigned long symoffset; | 1240 | unsigned long symoffset; | |
1207 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | 1241 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | |
1208 | sigset_t mask; | 1242 | sigset_t mask; | |
1209 | #endif | 1243 | #endif | |
1210 | 1244 | |||
1211 | dbg(("dladdr of %p", addr)); | 1245 | dbg(("dladdr of %p", addr)); | |
1212 | 1246 | |||
1213 | lookup_mutex_enter(); | 1247 | lookup_mutex_enter(); | |
1214 | 1248 | |||
1215 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | 1249 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | |
1216 | addr = _rtld_function_descriptor_function(addr); | 1250 | addr = _rtld_function_descriptor_function(addr); | |
1217 | #endif /* __HAVE_FUNCTION_DESCRIPTORS */ | 1251 | #endif /* __HAVE_FUNCTION_DESCRIPTORS */ | |
1218 | 1252 | |||
1219 | obj = _rtld_obj_from_addr(addr); | 1253 | obj = _rtld_obj_from_addr(addr); | |
1220 | if (obj == NULL) { | 1254 | if (obj == NULL) { | |
1221 | _rtld_error("No shared object contains address"); | 1255 | _rtld_error("No shared object contains address"); | |
1222 | lookup_mutex_enter(); | 1256 | lookup_mutex_enter(); | |
1223 | return 0; | 1257 | return 0; | |
1224 | } | 1258 | } | |
1225 | info->dli_fname = obj->path; | 1259 | info->dli_fname = obj->path; | |
1226 | info->dli_fbase = obj->mapbase; | 1260 | info->dli_fbase = obj->mapbase; | |
1227 | info->dli_saddr = (void *)0; | 1261 | info->dli_saddr = (void *)0; | |
1228 | info->dli_sname = NULL; | 1262 | info->dli_sname = NULL; | |
1229 | 1263 | |||
1230 | /* | 1264 | /* | |
1231 | * Walk the symbol list looking for the symbol whose address is | 1265 | * Walk the symbol list looking for the symbol whose address is | |
1232 | * closest to the address sent in. | 1266 | * closest to the address sent in. | |
1233 | */ | 1267 | */ | |
1234 | best_def = NULL; | 1268 | best_def = NULL; | |
1235 | for (symoffset = 0; symoffset < obj->nchains; symoffset++) { | 1269 | for (symoffset = 0; symoffset < obj->nchains; symoffset++) { | |
1236 | def = obj->symtab + symoffset; | 1270 | def = obj->symtab + symoffset; | |
1237 | 1271 | |||
1238 | /* | 1272 | /* | |
1239 | * For skip the symbol if st_shndx is either SHN_UNDEF or | 1273 | * For skip the symbol if st_shndx is either SHN_UNDEF or | |
1240 | * SHN_COMMON. | 1274 | * SHN_COMMON. | |
1241 | */ | 1275 | */ | |
1242 | if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON) | 1276 | if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON) | |
1243 | continue; | 1277 | continue; | |
1244 | 1278 | |||
1245 | /* | 1279 | /* | |
1246 | * If the symbol is greater than the specified address, or if it | 1280 | * If the symbol is greater than the specified address, or if it | |
1247 | * is further away from addr than the current nearest symbol, | 1281 | * is further away from addr than the current nearest symbol, | |
1248 | * then reject it. | 1282 | * then reject it. | |
1249 | */ | 1283 | */ | |
1250 | symbol_addr = obj->relocbase + def->st_value; | 1284 | symbol_addr = obj->relocbase + def->st_value; | |
1251 | if (symbol_addr > addr || symbol_addr < info->dli_saddr) | 1285 | if (symbol_addr > addr || symbol_addr < info->dli_saddr) | |
1252 | continue; | 1286 | continue; | |
1253 | 1287 | |||
1254 | /* Update our idea of the nearest symbol. */ | 1288 | /* Update our idea of the nearest symbol. */ | |
1255 | info->dli_sname = obj->strtab + def->st_name; | 1289 | info->dli_sname = obj->strtab + def->st_name; |
--- src/libexec/ld.elf_so/rtld.h 2011/12/02 09:06:49 1.107
+++ src/libexec/ld.elf_so/rtld.h 2013/01/22 21:47:28 1.107.4.1
@@ -1,457 +1,464 @@ | @@ -1,457 +1,464 @@ | |||
1 | /* $NetBSD: rtld.h,v 1.107 2011/12/02 09:06:49 skrll Exp $ */ | 1 | /* $NetBSD: rtld.h,v 1.107.4.1 2013/01/22 21:47:28 matt Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright 1996 John D. Polstra. | 4 | * Copyright 1996 John D. Polstra. | |
5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | 5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | |
6 | * All rights reserved. | 6 | * All rights reserved. | |
7 | * | 7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | 10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | 15 | * documentation and/or other materials provided with the distribution. | |
16 | * 3. All advertising materials mentioning features or use of this software | 16 | * 3. All advertising materials mentioning features or use of this software | |
17 | * must display the following acknowledgement: | 17 | * must display the following acknowledgement: | |
18 | * This product includes software developed by John Polstra. | 18 | * This product includes software developed by John Polstra. | |
19 | * 4. The name of the author may not be used to endorse or promote products | 19 | * 4. The name of the author may not be used to endorse or promote products | |
20 | * derived from this software without specific prior written permission. | 20 | * derived from this software without specific prior written permission. | |
21 | * | 21 | * | |
22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #ifndef RTLD_H | 34 | #ifndef RTLD_H | |
35 | #define RTLD_H | 35 | #define RTLD_H | |
36 | 36 | |||
37 | #include <dlfcn.h> | 37 | #include <dlfcn.h> | |
38 | #include <signal.h> | 38 | #include <signal.h> | |
39 | #include <stdbool.h> | 39 | #include <stdbool.h> | |
40 | #include <stddef.h> | 40 | #include <stddef.h> | |
41 | #include <sys/param.h> | 41 | #include <sys/param.h> | |
42 | #include <sys/types.h> | 42 | #include <sys/types.h> | |
43 | #include <sys/queue.h> | 43 | #include <sys/queue.h> | |
44 | #include <sys/exec_elf.h> | 44 | #include <sys/exec_elf.h> | |
45 | #include <sys/tls.h> | 45 | #include <sys/tls.h> | |
46 | #include "rtldenv.h" | 46 | #include "rtldenv.h" | |
47 | #include "link.h" | 47 | #include "link.h" | |
48 | 48 | |||
49 | #if defined(_RTLD_SOURCE) | 49 | #if defined(_RTLD_SOURCE) | |
50 | 50 | |||
51 | #ifndef RTLD_DEFAULT_LIBRARY_PATH | 51 | #ifndef RTLD_DEFAULT_LIBRARY_PATH | |
52 | #define RTLD_DEFAULT_LIBRARY_PATH "/usr/lib" | 52 | #define RTLD_DEFAULT_LIBRARY_PATH "/usr/lib" | |
53 | #endif | 53 | #endif | |
54 | #define _PATH_LD_HINTS "/etc/ld.so.conf" | 54 | #define _PATH_LD_HINTS "/etc/ld.so.conf" | |
55 | 55 | |||
56 | extern size_t _rtld_pagesz; | 56 | extern size_t _rtld_pagesz; | |
57 | 57 | |||
58 | #define round_down(x) ((x) & ~(_rtld_pagesz - 1)) | 58 | #define round_down(x) ((x) & ~(_rtld_pagesz - 1)) | |
59 | #define round_up(x) round_down((x) + _rtld_pagesz - 1) | 59 | #define round_up(x) round_down((x) + _rtld_pagesz - 1) | |
60 | 60 | |||
61 | #define NEW(type) ((type *) xmalloc(sizeof(type))) | 61 | #define NEW(type) ((type *) xmalloc(sizeof(type))) | |
62 | #define CNEW(type) ((type *) xcalloc(sizeof(type))) | 62 | #define CNEW(type) ((type *) xcalloc(sizeof(type))) | |
63 | 63 | |||
64 | /* | 64 | /* | |
65 | * Fill in a DoneList with an allocation large enough to hold all of | 65 | * Fill in a DoneList with an allocation large enough to hold all of | |
66 | * the currently-loaded objects. Keep this in a macro since it calls | 66 | * the currently-loaded objects. Keep this in a macro since it calls | |
67 | * alloca and we want that to occur within the scope of the caller. | 67 | * alloca and we want that to occur within the scope of the caller. | |
68 | */ | 68 | */ | |
69 | #define _rtld_donelist_init(dlp) \ | 69 | #define _rtld_donelist_init(dlp) \ | |
70 | ((dlp)->num_alloc = _rtld_objcount, \ | 70 | ((dlp)->num_alloc = _rtld_objcount, \ | |
71 | (dlp)->objs = alloca((dlp)->num_alloc * sizeof((dlp)->objs[0])), \ | 71 | (dlp)->objs = alloca((dlp)->num_alloc * sizeof((dlp)->objs[0])), \ | |
72 | assert((dlp)->objs != NULL), \ | 72 | assert((dlp)->objs != NULL), \ | |
73 | (dlp)->num_used = 0) | 73 | (dlp)->num_used = 0) | |
74 | 74 | |||
75 | #endif /* _RTLD_SOURCE */ | 75 | #endif /* _RTLD_SOURCE */ | |
76 | 76 | |||
77 | /* | 77 | /* | |
78 | * C++ has mandated the use of the following keywords for its new boolean | 78 | * C++ has mandated the use of the following keywords for its new boolean | |
79 | * type. We might as well follow their lead. | 79 | * type. We might as well follow their lead. | |
80 | */ | 80 | */ | |
81 | struct Struct_Obj_Entry; | 81 | struct Struct_Obj_Entry; | |
82 | 82 | |||
83 | typedef struct Struct_Objlist_Entry { | 83 | typedef struct Struct_Objlist_Entry { | |
84 | SIMPLEQ_ENTRY(Struct_Objlist_Entry) link; | 84 | SIMPLEQ_ENTRY(Struct_Objlist_Entry) link; | |
85 | struct Struct_Obj_Entry *obj; | 85 | struct Struct_Obj_Entry *obj; | |
86 | } Objlist_Entry; | 86 | } Objlist_Entry; | |
87 | 87 | |||
88 | typedef SIMPLEQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist; | 88 | typedef SIMPLEQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist; | |
89 | 89 | |||
90 | typedef struct Struct_Name_Entry { | 90 | typedef struct Struct_Name_Entry { | |
91 | STAILQ_ENTRY(Struct_Name_Entry) link; | 91 | STAILQ_ENTRY(Struct_Name_Entry) link; | |
92 | char name[1]; | 92 | char name[1]; | |
93 | } Name_Entry; | 93 | } Name_Entry; | |
94 | 94 | |||
95 | typedef struct Struct_Needed_Entry { | 95 | typedef struct Struct_Needed_Entry { | |
96 | struct Struct_Needed_Entry *next; | 96 | struct Struct_Needed_Entry *next; | |
97 | struct Struct_Obj_Entry *obj; | 97 | struct Struct_Obj_Entry *obj; | |
98 | unsigned long name; /* Offset of name in string table */ | 98 | unsigned long name; /* Offset of name in string table */ | |
99 | } Needed_Entry; | 99 | } Needed_Entry; | |
100 | 100 | |||
101 | typedef struct _rtld_search_path_t { | 101 | typedef struct _rtld_search_path_t { | |
102 | struct _rtld_search_path_t *sp_next; | 102 | struct _rtld_search_path_t *sp_next; | |
103 | const char *sp_path; | 103 | const char *sp_path; | |
104 | size_t sp_pathlen; | 104 | size_t sp_pathlen; | |
105 | } Search_Path; | 105 | } Search_Path; | |
106 | 106 | |||
107 | typedef struct Struct_Ver_Entry { | 107 | typedef struct Struct_Ver_Entry { | |
108 | Elf_Word hash; | 108 | Elf_Word hash; | |
109 | u_int flags; | 109 | u_int flags; | |
110 | const char *name; | 110 | const char *name; | |
111 | const char *file; | 111 | const char *file; | |
112 | } Ver_Entry; | 112 | } Ver_Entry; | |
113 | 113 | |||
114 | /* Ver_Entry.flags */ | 114 | /* Ver_Entry.flags */ | |
115 | #define VER_INFO_HIDDEN 0x01 | 115 | #define VER_INFO_HIDDEN 0x01 | |
116 | 116 | |||
117 | ||||
118 | #define RTLD_MAX_ENTRY 10 | 117 | #define RTLD_MAX_ENTRY 10 | |
119 | #define RTLD_MAX_LIBRARY 4 | 118 | #define RTLD_MAX_LIBRARY 4 | |
120 | #define RTLD_MAX_CTL 2 | 119 | #define RTLD_MAX_CTL 2 | |
121 | typedef struct _rtld_library_xform_t { | 120 | typedef struct _rtld_library_xform_t { | |
122 | struct _rtld_library_xform_t *next; | 121 | struct _rtld_library_xform_t *next; | |
123 | char *name; | 122 | char *name; | |
124 | const char *ctlname; | 123 | const char *ctlname; | |
125 | struct { | 124 | struct { | |
126 | char *value; | 125 | char *value; | |
127 | char *library[RTLD_MAX_LIBRARY]; | 126 | char *library[RTLD_MAX_LIBRARY]; | |
128 | } entry[RTLD_MAX_ENTRY]; | 127 | } entry[RTLD_MAX_ENTRY]; | |
129 | } Library_Xform; | 128 | } Library_Xform; | |
130 | 129 | |||
131 | /* | 130 | /* | |
132 | * Shared object descriptor. | 131 | * Shared object descriptor. | |
133 | * | 132 | * | |
134 | * Items marked with "(%)" are dynamically allocated, and must be freed | 133 | * Items marked with "(%)" are dynamically allocated, and must be freed | |
135 | * when the structure is destroyed. | 134 | * when the structure is destroyed. | |
136 | * | 135 | * | |
137 | * The layout of this structure needs to be preserved because pre-2.0 binaries | 136 | * The layout of this structure needs to be preserved because pre-2.0 binaries | |
138 | * hard-coded the location of dlopen() and friends. | 137 | * hard-coded the location of dlopen() and friends. | |
139 | */ | 138 | */ | |
140 | 139 | |||
141 | #define RTLD_MAGIC 0xd550b87a | 140 | #define RTLD_MAGIC 0xd550b87a | |
142 | #define RTLD_VERSION 1 | 141 | #define RTLD_VERSION 1 | |
143 | 142 | |||
143 | typedef void (*fptr_t)(void); | |||
144 | ||||
144 | typedef struct Struct_Obj_Entry { | 145 | typedef struct Struct_Obj_Entry { | |
145 | Elf32_Word magic; /* Magic number (sanity check) */ | 146 | Elf32_Word magic; /* Magic number (sanity check) */ | |
146 | Elf32_Word version; /* Version number of struct format */ | 147 | Elf32_Word version; /* Version number of struct format */ | |
147 | 148 | |||
148 | struct Struct_Obj_Entry *next; | 149 | struct Struct_Obj_Entry *next; | |
149 | char *path; /* Pathname of underlying file (%) */ | 150 | char *path; /* Pathname of underlying file (%) */ | |
150 | int refcount; | 151 | int refcount; | |
151 | int dl_refcount; /* Number of times loaded by dlopen */ | 152 | int dl_refcount; /* Number of times loaded by dlopen */ | |
152 | 153 | |||
153 | /* These items are computed by map_object() or by digest_phdr(). */ | 154 | /* These items are computed by map_object() or by digest_phdr(). */ | |
154 | caddr_t mapbase; /* Base address of mapped region */ | 155 | caddr_t mapbase; /* Base address of mapped region */ | |
155 | size_t mapsize; /* Size of mapped region in bytes */ | 156 | size_t mapsize; /* Size of mapped region in bytes */ | |
156 | size_t textsize; /* Size of text segment in bytes */ | 157 | size_t textsize; /* Size of text segment in bytes */ | |
157 | Elf_Addr vaddrbase; /* Base address in shared object file */ | 158 | Elf_Addr vaddrbase; /* Base address in shared object file */ | |
158 | caddr_t relocbase; /* Reloc const = mapbase - *vaddrbase */ | 159 | caddr_t relocbase; /* Reloc const = mapbase - *vaddrbase */ | |
159 | Elf_Dyn *dynamic; /* Dynamic section */ | 160 | Elf_Dyn *dynamic; /* Dynamic section */ | |
160 | caddr_t entry; /* Entry point */ | 161 | caddr_t entry; /* Entry point */ | |
161 | const Elf_Phdr *phdr; /* Program header (may be xmalloc'ed) */ | 162 | const Elf_Phdr *phdr; /* Program header (may be xmalloc'ed) */ | |
162 | size_t phsize; /* Size of program header in bytes */ | 163 | size_t phsize; /* Size of program header in bytes */ | |
163 | 164 | |||
164 | /* Items from the dynamic section. */ | 165 | /* Items from the dynamic section. */ | |
165 | Elf_Addr *pltgot; /* PLTGOT table */ | 166 | Elf_Addr *pltgot; /* PLTGOT table */ | |
166 | const Elf_Rel *rel; /* Relocation entries */ | 167 | const Elf_Rel *rel; /* Relocation entries */ | |
167 | const Elf_Rel *rellim; /* Limit of Relocation entries */ | 168 | const Elf_Rel *rellim; /* Limit of Relocation entries */ | |
168 | const Elf_Rela *rela; /* Relocation entries */ | 169 | const Elf_Rela *rela; /* Relocation entries */ | |
169 | const Elf_Rela *relalim; /* Limit of Relocation entries */ | 170 | const Elf_Rela *relalim; /* Limit of Relocation entries */ | |
170 | const Elf_Rel *pltrel; /* PLT relocation entries */ | 171 | const Elf_Rel *pltrel; /* PLT relocation entries */ | |
171 | const Elf_Rel *pltrellim; /* Limit of PLT relocation entries */ | 172 | const Elf_Rel *pltrellim; /* Limit of PLT relocation entries */ | |
172 | const Elf_Rela *pltrela; /* PLT relocation entries */ | 173 | const Elf_Rela *pltrela; /* PLT relocation entries */ | |
173 | const Elf_Rela *pltrelalim; /* Limit of PLT relocation entries */ | 174 | const Elf_Rela *pltrelalim; /* Limit of PLT relocation entries */ | |
174 | const Elf_Sym *symtab; /* Symbol table */ | 175 | const Elf_Sym *symtab; /* Symbol table */ | |
175 | const char *strtab; /* String table */ | 176 | const char *strtab; /* String table */ | |
176 | unsigned long strsize; /* Size in bytes of string table */ | 177 | unsigned long strsize; /* Size in bytes of string table */ | |
177 | #ifdef __mips__ | 178 | #ifdef __mips__ | |
178 | Elf_Word local_gotno; /* Number of local GOT entries */ | 179 | Elf_Word local_gotno; /* Number of local GOT entries */ | |
179 | Elf_Word symtabno; /* Number of dynamic symbols */ | 180 | Elf_Word symtabno; /* Number of dynamic symbols */ | |
180 | Elf_Word gotsym; /* First dynamic symbol in GOT */ | 181 | Elf_Word gotsym; /* First dynamic symbol in GOT */ | |
181 | #endif | 182 | #endif | |
182 | 183 | |||
183 | const Elf_Symindx *buckets; /* Hash table buckets array */ | 184 | const Elf_Symindx *buckets; /* Hash table buckets array */ | |
184 | unsigned long unused1; /* Used to be nbuckets */ | 185 | unsigned long unused1; /* Used to be nbuckets */ | |
185 | const Elf_Symindx *chains; /* Hash table chain array */ | 186 | const Elf_Symindx *chains; /* Hash table chain array */ | |
186 | unsigned long nchains; /* Number of chains */ | 187 | unsigned long nchains; /* Number of chains */ | |
187 | 188 | |||
188 | Search_Path *rpaths; /* Search path specified in object */ | 189 | Search_Path *rpaths; /* Search path specified in object */ | |
189 | Needed_Entry *needed; /* Shared objects needed by this (%) */ | 190 | Needed_Entry *needed; /* Shared objects needed by this (%) */ | |
190 | 191 | |||
191 | void (*init)(void); /* Initialization function to call */ | 192 | fptr_t init; /* Initialization function to call */ | |
192 | void (*fini)(void); /* Termination function to call */ | 193 | fptr_t fini; /* Termination function to call */ | |
193 | 194 | |||
194 | /* | 195 | /* | |
195 | * BACKWARDS COMPAT Entry points for dlopen() and friends. | 196 | * BACKWARDS COMPAT Entry points for dlopen() and friends. | |
196 | * | 197 | * | |
197 | * DO NOT MOVE OR ADD TO THE LIST | 198 | * DO NOT MOVE OR ADD TO THE LIST | |
198 | * | 199 | * | |
199 | */ | 200 | */ | |
200 | void *(*dlopen)(const char *, int); | 201 | void *(*dlopen)(const char *, int); | |
201 | void *(*dlsym)(void *, const char *); | 202 | void *(*dlsym)(void *, const char *); | |
202 | char *(*dlerror)(void); | 203 | char *(*dlerror)(void); | |
203 | int (*dlclose)(void *); | 204 | int (*dlclose)(void *); | |
204 | int (*dladdr)(const void *, Dl_info *); | 205 | int (*dladdr)(const void *, Dl_info *); | |
205 | 206 | |||
206 | u_int32_t mainprog:1, /* True if this is the main program */ | 207 | u_int32_t mainprog:1, /* True if this is the main program */ | |
207 | rtld:1, /* True if this is the dynamic linker */ | 208 | rtld:1, /* True if this is the dynamic linker */ | |
208 | textrel:1, /* True if there are relocations to | 209 | textrel:1, /* True if there are relocations to | |
209 | * text seg */ | 210 | * text seg */ | |
210 | symbolic:1, /* True if generated with | 211 | symbolic:1, /* True if generated with | |
211 | * "-Bsymbolic" */ | 212 | * "-Bsymbolic" */ | |
212 | printed:1, /* True if ldd has printed it */ | 213 | printed:1, /* True if ldd has printed it */ | |
213 | isdynamic:1, /* True if this is a pure PIC object */ | 214 | isdynamic:1, /* True if this is a pure PIC object */ | |
214 | mainref:1, /* True if on _rtld_list_main */ | 215 | mainref:1, /* True if on _rtld_list_main */ | |
215 | globalref:1, /* True if on _rtld_list_global */ | 216 | globalref:1, /* True if on _rtld_list_global */ | |
216 | init_done:1, /* True if .init has been added */ | 217 | init_done:1, /* True if .init has been added */ | |
217 | init_called:1, /* True if .init function has been | 218 | init_called:1, /* True if .init function has been | |
218 | * called */ | 219 | * called */ | |
219 | fini_called:1, /* True if .fini function has been | 220 | fini_called:1, /* True if .fini function has been | |
220 | * called */ | 221 | * called */ | |
221 | z_now:1, /* True if object's symbols should be | 222 | z_now:1, /* True if object's symbols should be | |
222 | bound immediately */ | 223 | bound immediately */ | |
223 | z_nodelete:1, /* True if object should never be | 224 | z_nodelete:1, /* True if object should never be | |
224 | unloaded */ | 225 | unloaded */ | |
225 | z_initfirst:1, /* True if object's .init/.fini take | 226 | z_initfirst:1, /* True if object's .init/.fini take | |
226 | * priority over others */ | 227 | * priority over others */ | |
227 | z_noopen:1, /* True if object should never be | 228 | z_noopen:1, /* True if object should never be | |
228 | dlopen'ed */ | 229 | dlopen'ed */ | |
229 | phdr_loaded:1, /* Phdr is loaded and doesn't need to | 230 | phdr_loaded:1, /* Phdr is loaded and doesn't need to | |
230 | * be freed. */ | 231 | * be freed. */ | |
231 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | 232 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | |
232 | tls_done:1, /* True if static TLS offset | 233 | tls_done:1, /* True if static TLS offset | |
233 | * has been allocated */ | 234 | * has been allocated */ | |
234 | #endif | 235 | #endif | |
235 | ref_nodel:1; /* Refcount increased to prevent dlclose */ | 236 | ref_nodel:1; /* Refcount increased to prevent dlclose */ | |
236 | 237 | |||
237 | struct link_map linkmap; /* for GDB */ | 238 | struct link_map linkmap; /* for GDB */ | |
238 | 239 | |||
239 | /* These items are computed by map_object() or by digest_phdr(). */ | 240 | /* These items are computed by map_object() or by digest_phdr(). */ | |
240 | const char *interp; /* Pathname of the interpreter, if any */ | 241 | const char *interp; /* Pathname of the interpreter, if any */ | |
241 | Objlist dldags; /* Object belongs to these dlopened DAGs (%) */ | 242 | Objlist dldags; /* Object belongs to these dlopened DAGs (%) */ | |
242 | Objlist dagmembers; /* DAG has these members (%) */ | 243 | Objlist dagmembers; /* DAG has these members (%) */ | |
243 | dev_t dev; /* Object's filesystem's device */ | 244 | dev_t dev; /* Object's filesystem's device */ | |
244 | ino_t ino; /* Object's inode number */ | 245 | ino_t ino; /* Object's inode number */ | |
245 | 246 | |||
246 | void *ehdr; | 247 | void *ehdr; | |
247 | 248 | |||
248 | uint32_t nbuckets; /* Number of buckets */ | 249 | uint32_t nbuckets; /* Number of buckets */ | |
249 | uint32_t nbuckets_m; /* Precomputed for fast remainder */ | 250 | uint32_t nbuckets_m; /* Precomputed for fast remainder */ | |
250 | uint8_t nbuckets_s1; | 251 | uint8_t nbuckets_s1; | |
251 | uint8_t nbuckets_s2; | 252 | uint8_t nbuckets_s2; | |
252 | size_t pathlen; /* Pathname length */ | 253 | size_t pathlen; /* Pathname length */ | |
253 | STAILQ_HEAD(, Struct_Name_Entry) names; /* List of names for this object we | 254 | STAILQ_HEAD(, Struct_Name_Entry) names; /* List of names for this object we | |
254 | know about. */ | 255 | know about. */ | |
255 | 256 | |||
256 | #ifdef __powerpc__ | 257 | #ifdef __powerpc__ | |
257 | Elf_Addr *gotptr; /* GOT table (secure-plt only) */ | 258 | Elf_Addr *gotptr; /* GOT table (secure-plt only) */ | |
258 | #endif | 259 | #endif | |
259 | 260 | |||
260 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | 261 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | |
261 | /* Thread Local Storage support for this module */ | 262 | /* Thread Local Storage support for this module */ | |
262 | size_t tlsindex; /* Index in DTV */ | 263 | size_t tlsindex; /* Index in DTV */ | |
263 | void *tlsinit; /* Base address of TLS init block */ | 264 | void *tlsinit; /* Base address of TLS init block */ | |
264 | size_t tlsinitsize; /* Size of TLS init block */ | 265 | size_t tlsinitsize; /* Size of TLS init block */ | |
265 | size_t tlssize; /* Size of TLS block */ | 266 | size_t tlssize; /* Size of TLS block */ | |
266 | size_t tlsoffset; /* Offset in the static TLS block */ | 267 | size_t tlsoffset; /* Offset in the static TLS block */ | |
267 | size_t tlsalign; /* Needed alignment for static TLS */ | 268 | size_t tlsalign; /* Needed alignment for static TLS */ | |
268 | #endif | 269 | #endif | |
269 | 270 | |||
270 | /* symbol versioning */ | 271 | /* symbol versioning */ | |
271 | const Elf_Verneed *verneed; /* Required versions. */ | 272 | const Elf_Verneed *verneed; /* Required versions. */ | |
272 | Elf_Word verneednum; /* Number of entries in verneed table */ | 273 | Elf_Word verneednum; /* Number of entries in verneed table */ | |
273 | const Elf_Verdef *verdef; /* Provided versions. */ | 274 | const Elf_Verdef *verdef; /* Provided versions. */ | |
274 | Elf_Word verdefnum; /* Number of entries in verdef table */ | 275 | Elf_Word verdefnum; /* Number of entries in verdef table */ | |
275 | const Elf_Versym *versyms; /* Symbol versions table */ | 276 | const Elf_Versym *versyms; /* Symbol versions table */ | |
276 | 277 | |||
277 | Ver_Entry *vertab; /* Versions required/defined by this | 278 | Ver_Entry *vertab; /* Versions required/defined by this | |
278 | * object */ | 279 | * object */ | |
279 | int vertabnum; /* Number of entries in vertab */ | 280 | int vertabnum; /* Number of entries in vertab */ | |
281 | ||||
282 | /* init_array/fini_array */ | |||
283 | fptr_t *init_array; /* start of init array */ | |||
284 | size_t init_arraysz; /* # of entries in it */ | |||
285 | fptr_t *fini_array; /* start of fini array */ | |||
286 | size_t fini_arraysz; /* # of entries in it */ | |||
280 | } Obj_Entry; | 287 | } Obj_Entry; | |
281 | 288 | |||
282 | typedef struct Struct_DoneList { | 289 | typedef struct Struct_DoneList { | |
283 | const Obj_Entry **objs; /* Array of object pointers */ | 290 | const Obj_Entry **objs; /* Array of object pointers */ | |
284 | unsigned int num_alloc; /* Allocated size of the array */ | 291 | unsigned int num_alloc; /* Allocated size of the array */ | |
285 | unsigned int num_used; /* Number of array slots used */ | 292 | unsigned int num_used; /* Number of array slots used */ | |
286 | } DoneList; | 293 | } DoneList; | |
287 | 294 | |||
288 | 295 | |||
289 | #if defined(_RTLD_SOURCE) | 296 | #if defined(_RTLD_SOURCE) | |
290 | 297 | |||
291 | extern struct r_debug _rtld_debug; | 298 | extern struct r_debug _rtld_debug; | |
292 | extern Search_Path *_rtld_default_paths; | 299 | extern Search_Path *_rtld_default_paths; | |
293 | extern Obj_Entry *_rtld_objlist; | 300 | extern Obj_Entry *_rtld_objlist; | |
294 | extern Obj_Entry **_rtld_objtail; | 301 | extern Obj_Entry **_rtld_objtail; | |
295 | extern u_int _rtld_objcount; | 302 | extern u_int _rtld_objcount; | |
296 | extern u_int _rtld_objloads; | 303 | extern u_int _rtld_objloads; | |
297 | extern Obj_Entry *_rtld_objmain; | 304 | extern Obj_Entry *_rtld_objmain; | |
298 | extern Obj_Entry _rtld_objself; | 305 | extern Obj_Entry _rtld_objself; | |
299 | extern Search_Path *_rtld_paths; | 306 | extern Search_Path *_rtld_paths; | |
300 | extern Library_Xform *_rtld_xforms; | 307 | extern Library_Xform *_rtld_xforms; | |
301 | extern bool _rtld_trust; | 308 | extern bool _rtld_trust; | |
302 | extern Objlist _rtld_list_global; | 309 | extern Objlist _rtld_list_global; | |
303 | extern Objlist _rtld_list_main; | 310 | extern Objlist _rtld_list_main; | |
304 | extern Elf_Sym _rtld_sym_zero; | 311 | extern Elf_Sym _rtld_sym_zero; | |
305 | 312 | |||
306 | #define RTLD_MODEMASK 0x3 | 313 | #define RTLD_MODEMASK 0x3 | |
307 | 314 | |||
308 | /* Flags to be passed into _rtld_symlook_ family of functions. */ | 315 | /* Flags to be passed into _rtld_symlook_ family of functions. */ | |
309 | #define SYMLOOK_IN_PLT 0x01 /* Lookup for PLT symbol */ | 316 | #define SYMLOOK_IN_PLT 0x01 /* Lookup for PLT symbol */ | |
310 | #define SYMLOOK_DLSYM 0x02 /* Return newes versioned symbol. | 317 | #define SYMLOOK_DLSYM 0x02 /* Return newes versioned symbol. | |
311 | Used by dlsym. */ | 318 | Used by dlsym. */ | |
312 | 319 | |||
313 | /* Flags for _rtld_load_object() and friends. */ | 320 | /* Flags for _rtld_load_object() and friends. */ | |
314 | #define _RTLD_GLOBAL 0x01 /* Add object to global DAG. */ | 321 | #define _RTLD_GLOBAL 0x01 /* Add object to global DAG. */ | |
315 | #define _RTLD_MAIN 0x02 | 322 | #define _RTLD_MAIN 0x02 | |
316 | #define _RTLD_NOLOAD 0x04 /* dlopen() specified RTLD_NOLOAD. */ | 323 | #define _RTLD_NOLOAD 0x04 /* dlopen() specified RTLD_NOLOAD. */ | |
317 | #define _RTLD_DLOPEN 0x08 /* Load_object() called from dlopen(). */ | 324 | #define _RTLD_DLOPEN 0x08 /* Load_object() called from dlopen(). */ | |
318 | 325 | |||
319 | /* Preallocation for static TLS model */ | 326 | /* Preallocation for static TLS model */ | |
320 | #define RTLD_STATIC_TLS_RESERVATION 64 | 327 | #define RTLD_STATIC_TLS_RESERVATION 64 | |
321 | 328 | |||
322 | /* rtld.c */ | 329 | /* rtld.c */ | |
323 | 330 | |||
324 | /* We export these symbols using _rtld_symbol_lookup and is_exported. */ | 331 | /* We export these symbols using _rtld_symbol_lookup and is_exported. */ | |
325 | __dso_public char *dlerror(void); | 332 | __dso_public char *dlerror(void); | |
326 | __dso_public void *dlopen(const char *, int); | 333 | __dso_public void *dlopen(const char *, int); | |
327 | __dso_public void *dlsym(void *, const char *); | 334 | __dso_public void *dlsym(void *, const char *); | |
328 | __dso_public int dlclose(void *); | 335 | __dso_public int dlclose(void *); | |
329 | __dso_public int dladdr(const void *, Dl_info *); | 336 | __dso_public int dladdr(const void *, Dl_info *); | |
330 | __dso_public int dlinfo(void *, int, void *); | 337 | __dso_public int dlinfo(void *, int, void *); | |
331 | __dso_public int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), | 338 | __dso_public int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), | |
332 | void *); | 339 | void *); | |
333 | 340 | |||
334 | /* These aren't exported */ | 341 | /* These aren't exported */ | |
335 | void _rtld_error(const char *, ...) | 342 | void _rtld_error(const char *, ...) | |
336 | __attribute__((__format__(__printf__,1,2))); | 343 | __attribute__((__format__(__printf__,1,2))); | |
337 | void _rtld_die(void) __attribute__((__noreturn__)); | 344 | void _rtld_die(void) __attribute__((__noreturn__)); | |
338 | void *_rtld_objmain_sym(const char *); | 345 | void *_rtld_objmain_sym(const char *); | |
339 | __dso_public void _rtld_debug_state(void); | 346 | __dso_public void _rtld_debug_state(void); | |
340 | void _rtld_linkmap_add(Obj_Entry *); | 347 | void _rtld_linkmap_add(Obj_Entry *); | |
341 | void _rtld_linkmap_delete(Obj_Entry *); | 348 | void _rtld_linkmap_delete(Obj_Entry *); | |
342 | void _rtld_objlist_push_head(Objlist *, Obj_Entry *); | 349 | void _rtld_objlist_push_head(Objlist *, Obj_Entry *); | |
343 | void _rtld_objlist_push_tail(Objlist *, Obj_Entry *); | 350 | void _rtld_objlist_push_tail(Objlist *, Obj_Entry *); | |
344 | Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *); | 351 | Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *); | |
345 | void _rtld_ref_dag(Obj_Entry *); | 352 | void _rtld_ref_dag(Obj_Entry *); | |
346 | 353 | |||
347 | void _rtld_shared_enter(void); | 354 | void _rtld_shared_enter(void); | |
348 | void _rtld_shared_exit(void); | 355 | void _rtld_shared_exit(void); | |
349 | void _rtld_exclusive_enter(sigset_t *); | 356 | void _rtld_exclusive_enter(sigset_t *); | |
350 | void _rtld_exclusive_exit(sigset_t *); | 357 | void _rtld_exclusive_exit(sigset_t *); | |
351 | 358 | |||
352 | /* expand.c */ | 359 | /* expand.c */ | |
353 | size_t _rtld_expand_path(char *, size_t, const char *, const char *,\ | 360 | size_t _rtld_expand_path(char *, size_t, const char *, const char *,\ | |
354 | const char *); | 361 | const char *); | |
355 | 362 | |||
356 | /* headers.c */ | 363 | /* headers.c */ | |
357 | void _rtld_digest_dynamic(const char *, Obj_Entry *); | 364 | void _rtld_digest_dynamic(const char *, Obj_Entry *); | |
358 | Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t); | 365 | Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t); | |
359 | 366 | |||
360 | /* load.c */ | 367 | /* load.c */ | |
361 | Obj_Entry *_rtld_load_object(const char *, int); | 368 | Obj_Entry *_rtld_load_object(const char *, int); | |
362 | int _rtld_load_needed_objects(Obj_Entry *, int); | 369 | int _rtld_load_needed_objects(Obj_Entry *, int); | |
363 | int _rtld_preload(const char *); | 370 | int _rtld_preload(const char *); | |
364 | 371 | |||
365 | #define OBJ_ERR (Obj_Entry *)(-1) | 372 | #define OBJ_ERR (Obj_Entry *)(-1) | |
366 | /* path.c */ | 373 | /* path.c */ | |
367 | void _rtld_add_paths(const char *, Search_Path **, const char *); | 374 | void _rtld_add_paths(const char *, Search_Path **, const char *); | |
368 | void _rtld_process_hints(const char *, Search_Path **, Library_Xform **, | 375 | void _rtld_process_hints(const char *, Search_Path **, Library_Xform **, | |
369 | const char *); | 376 | const char *); | |
370 | int _rtld_sysctl(const char *, void *, size_t *); | 377 | int _rtld_sysctl(const char *, void *, size_t *); | |
371 | 378 | |||
372 | /* reloc.c */ | 379 | /* reloc.c */ | |
373 | int _rtld_do_copy_relocations(const Obj_Entry *); | 380 | int _rtld_do_copy_relocations(const Obj_Entry *); | |
374 | int _rtld_relocate_objects(Obj_Entry *, bool); | 381 | int _rtld_relocate_objects(Obj_Entry *, bool); | |
375 | int _rtld_relocate_nonplt_objects(Obj_Entry *); | 382 | int _rtld_relocate_nonplt_objects(Obj_Entry *); | |
376 | int _rtld_relocate_plt_lazy(const Obj_Entry *); | 383 | int _rtld_relocate_plt_lazy(const Obj_Entry *); | |
377 | int _rtld_relocate_plt_objects(const Obj_Entry *); | 384 | int _rtld_relocate_plt_objects(const Obj_Entry *); | |
378 | void _rtld_setup_pltgot(const Obj_Entry *); | 385 | void _rtld_setup_pltgot(const Obj_Entry *); | |
379 | 386 | |||
380 | /* search.c */ | 387 | /* search.c */ | |
381 | Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int); | 388 | Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int); | |
382 | 389 | |||
383 | /* symbol.c */ | 390 | /* symbol.c */ | |
384 | unsigned long _rtld_elf_hash(const char *); | 391 | unsigned long _rtld_elf_hash(const char *); | |
385 | const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long, | 392 | const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long, | |
386 | const Obj_Entry *, u_int, const Ver_Entry *); | 393 | const Obj_Entry *, u_int, const Ver_Entry *); | |
387 | const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *, | 394 | const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *, | |
388 | const Obj_Entry **, u_int); | 395 | const Obj_Entry **, u_int); | |
389 | const Elf_Sym *_rtld_find_plt_symdef(unsigned long, const Obj_Entry *, | 396 | const Elf_Sym *_rtld_find_plt_symdef(unsigned long, const Obj_Entry *, | |
390 | const Obj_Entry **, bool); | 397 | const Obj_Entry **, bool); | |
391 | 398 | |||
392 | const Elf_Sym *_rtld_symlook_list(const char *, unsigned long, | 399 | const Elf_Sym *_rtld_symlook_list(const char *, unsigned long, | |
393 | const Objlist *, const Obj_Entry **, u_int, const Ver_Entry *, DoneList *); | 400 | const Objlist *, const Obj_Entry **, u_int, const Ver_Entry *, DoneList *); | |
394 | const Elf_Sym *_rtld_symlook_default(const char *, unsigned long, | 401 | const Elf_Sym *_rtld_symlook_default(const char *, unsigned long, | |
395 | const Obj_Entry *, const Obj_Entry **, u_int, const Ver_Entry *); | 402 | const Obj_Entry *, const Obj_Entry **, u_int, const Ver_Entry *); | |
396 | const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long, | 403 | const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long, | |
397 | const Needed_Entry *, const Obj_Entry **, u_int, const Ver_Entry *, | 404 | const Needed_Entry *, const Obj_Entry **, u_int, const Ver_Entry *, | |
398 | DoneList *, DoneList *); | 405 | DoneList *, DoneList *); | |
399 | #ifdef COMBRELOC | 406 | #ifdef COMBRELOC | |
400 | void _rtld_combreloc_reset(const Obj_Entry *); | 407 | void _rtld_combreloc_reset(const Obj_Entry *); | |
401 | #endif | 408 | #endif | |
402 | 409 | |||
403 | /* symver.c */ | 410 | /* symver.c */ | |
404 | int _rtld_object_match_name(const Obj_Entry *, const char *); | 411 | int _rtld_object_match_name(const Obj_Entry *, const char *); | |
405 | int _rtld_verify_object_versions(Obj_Entry *); | 412 | int _rtld_verify_object_versions(Obj_Entry *); | |
406 | 413 | |||
407 | static __inline const Ver_Entry * | 414 | static __inline const Ver_Entry * | |
408 | _rtld_fetch_ventry(const Obj_Entry *obj, unsigned long symnum) | 415 | _rtld_fetch_ventry(const Obj_Entry *obj, unsigned long symnum) | |
409 | { | 416 | { | |
410 | Elf_Half vernum; | 417 | Elf_Half vernum; | |
411 | 418 | |||
412 | if (obj->vertab) { | 419 | if (obj->vertab) { | |
413 | vernum = VER_NDX(obj->versyms[symnum].vs_vers); | 420 | vernum = VER_NDX(obj->versyms[symnum].vs_vers); | |
414 | if (vernum >= obj->vertabnum) { | 421 | if (vernum >= obj->vertabnum) { | |
415 | _rtld_error("%s: symbol %s has wrong verneed value %d", | 422 | _rtld_error("%s: symbol %s has wrong verneed value %d", | |
416 | obj->path, &obj->strtab[symnum], vernum); | 423 | obj->path, &obj->strtab[symnum], vernum); | |
417 | } else if (obj->vertab[vernum].hash) { | 424 | } else if (obj->vertab[vernum].hash) { | |
418 | return &obj->vertab[vernum]; | 425 | return &obj->vertab[vernum]; | |
419 | } | 426 | } | |
420 | } | 427 | } | |
421 | return NULL; | 428 | return NULL; | |
422 | } | 429 | } | |
423 | 430 | |||
424 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | 431 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | |
425 | /* tls.c */ | 432 | /* tls.c */ | |
426 | void *_rtld_tls_get_addr(void *, size_t, size_t); | 433 | void *_rtld_tls_get_addr(void *, size_t, size_t); | |
427 | void _rtld_tls_initial_allocation(void); | 434 | void _rtld_tls_initial_allocation(void); | |
428 | void *_rtld_tls_module_allocate(size_t index); | 435 | void *_rtld_tls_module_allocate(size_t index); | |
429 | int _rtld_tls_offset_allocate(Obj_Entry *); | 436 | int _rtld_tls_offset_allocate(Obj_Entry *); | |
430 | void _rtld_tls_offset_free(Obj_Entry *); | 437 | void _rtld_tls_offset_free(Obj_Entry *); | |
431 | 438 | |||
432 | extern size_t _rtld_tls_dtv_generation; | 439 | extern size_t _rtld_tls_dtv_generation; | |
433 | extern size_t _rtld_tls_max_index; | 440 | extern size_t _rtld_tls_max_index; | |
434 | 441 | |||
435 | __dso_public extern void *__tls_get_addr(void *); | 442 | __dso_public extern void *__tls_get_addr(void *); | |
436 | #ifdef __i386__ | 443 | #ifdef __i386__ | |
437 | __dso_public extern void *___tls_get_addr(void *) | 444 | __dso_public extern void *___tls_get_addr(void *) | |
438 | __attribute__((__regparm__(1))); | 445 | __attribute__((__regparm__(1))); | |
439 | #endif | 446 | #endif | |
440 | #endif | 447 | #endif | |
441 | 448 | |||
442 | /* map_object.c */ | 449 | /* map_object.c */ | |
443 | struct stat; | 450 | struct stat; | |
444 | Obj_Entry *_rtld_map_object(const char *, int, const struct stat *); | 451 | Obj_Entry *_rtld_map_object(const char *, int, const struct stat *); | |
445 | void _rtld_obj_free(Obj_Entry *); | 452 | void _rtld_obj_free(Obj_Entry *); | |
446 | Obj_Entry *_rtld_obj_new(void); | 453 | Obj_Entry *_rtld_obj_new(void); | |
447 | 454 | |||
448 | /* function descriptors */ | 455 | /* function descriptors */ | |
449 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | 456 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | |
450 | Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *, | 457 | Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *, | |
451 | const Elf_Sym *, Elf_Addr); | 458 | const Elf_Sym *, Elf_Addr); | |
452 | const void *_rtld_function_descriptor_function(const void *); | 459 | const void *_rtld_function_descriptor_function(const void *); | |
453 | #endif /* __HAVE_FUNCTION_DESCRIPTORS */ | 460 | #endif /* __HAVE_FUNCTION_DESCRIPTORS */ | |
454 | 461 | |||
455 | #endif /* _RTLD_SOURCE */ | 462 | #endif /* _RTLD_SOURCE */ | |
456 | 463 | |||
457 | #endif /* RTLD_H */ | 464 | #endif /* RTLD_H */ |
--- src/libexec/ld.elf_so/symbol.c 2011/11/25 14:39:02 1.59
+++ src/libexec/ld.elf_so/symbol.c 2013/01/22 21:47:28 1.59.4.1
@@ -1,583 +1,581 @@ | @@ -1,583 +1,581 @@ | |||
1 | /* $NetBSD: symbol.c,v 1.59 2011/11/25 14:39:02 joerg Exp $ */ | 1 | /* $NetBSD: symbol.c,v 1.59.4.1 2013/01/22 21:47:28 matt Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright 1996 John D. Polstra. | 4 | * Copyright 1996 John D. Polstra. | |
5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | 5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | |
6 | * Copyright 2002 Charles M. Hannum <root@ihack.net> | 6 | * Copyright 2002 Charles M. Hannum <root@ihack.net> | |
7 | * All rights reserved. | 7 | * All rights reserved. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in the | 15 | * notice, this list of conditions and the following disclaimer in the | |
16 | * documentation and/or other materials provided with the distribution. | 16 | * documentation and/or other materials provided with the distribution. | |
17 | * 3. All advertising materials mentioning features or use of this software | 17 | * 3. All advertising materials mentioning features or use of this software | |
18 | * must display the following acknowledgement: | 18 | * must display the following acknowledgement: | |
19 | * This product includes software developed by John Polstra. | 19 | * This product includes software developed by John Polstra. | |
20 | * 4. The name of the author may not be used to endorse or promote products | 20 | * 4. The name of the author may not be used to endorse or promote products | |
21 | * derived from this software without specific prior written permission. | 21 | * derived from this software without specific prior written permission. | |
22 | * | 22 | * | |
23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
26 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 26 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
33 | */ | 33 | */ | |
34 | 34 | |||
35 | /* | 35 | /* | |
36 | * Dynamic linker for ELF. | 36 | * Dynamic linker for ELF. | |
37 | * | 37 | * | |
38 | * John Polstra <jdp@polstra.com>. | 38 | * John Polstra <jdp@polstra.com>. | |
39 | */ | 39 | */ | |
40 | 40 | |||
41 | #include <sys/cdefs.h> | 41 | #include <sys/cdefs.h> | |
42 | #ifndef lint | 42 | #ifndef lint | |
43 | __RCSID("$NetBSD: symbol.c,v 1.59 2011/11/25 14:39:02 joerg Exp $"); | 43 | __RCSID("$NetBSD: symbol.c,v 1.59.4.1 2013/01/22 21:47:28 matt Exp $"); | |
44 | #endif /* not lint */ | 44 | #endif /* not lint */ | |
45 | 45 | |||
46 | #include <err.h> | 46 | #include <err.h> | |
47 | #include <errno.h> | 47 | #include <errno.h> | |
48 | #include <fcntl.h> | 48 | #include <fcntl.h> | |
49 | #include <stdarg.h> | 49 | #include <stdarg.h> | |
50 | #include <stdio.h> | 50 | #include <stdio.h> | |
51 | #include <stdlib.h> | 51 | #include <stdlib.h> | |
52 | #include <string.h> | 52 | #include <string.h> | |
53 | #include <unistd.h> | 53 | #include <unistd.h> | |
54 | #include <sys/types.h> | 54 | #include <sys/types.h> | |
55 | #include <sys/mman.h> | 55 | #include <sys/mman.h> | |
56 | #include <sys/bitops.h> | 56 | #include <sys/bitops.h> | |
57 | #include <dirent.h> | 57 | #include <dirent.h> | |
58 | 58 | |||
59 | #include "debug.h" | 59 | #include "debug.h" | |
60 | #include "rtld.h" | 60 | #include "rtld.h" | |
61 | 61 | |||
62 | typedef void (*fptr_t)(void); | |||
63 | ||||
64 | /* | 62 | /* | |
65 | * If the given object is already in the donelist, return true. Otherwise | 63 | * If the given object is already in the donelist, return true. Otherwise | |
66 | * add the object to the list and return false. | 64 | * add the object to the list and return false. | |
67 | */ | 65 | */ | |
68 | static bool | 66 | static bool | |
69 | _rtld_donelist_check(DoneList *dlp, const Obj_Entry *obj) | 67 | _rtld_donelist_check(DoneList *dlp, const Obj_Entry *obj) | |
70 | { | 68 | { | |
71 | unsigned int i; | 69 | unsigned int i; | |
72 | 70 | |||
73 | for (i = 0; i < dlp->num_used; i++) | 71 | for (i = 0; i < dlp->num_used; i++) | |
74 | if (dlp->objs[i] == obj) | 72 | if (dlp->objs[i] == obj) | |
75 | return true; | 73 | return true; | |
76 | /* | 74 | /* | |
77 | * Our donelist allocation may not always be sufficient as we're not | 75 | * Our donelist allocation may not always be sufficient as we're not | |
78 | * thread safe. We'll handle it properly anyway. | 76 | * thread safe. We'll handle it properly anyway. | |
79 | */ | 77 | */ | |
80 | if (dlp->num_used < dlp->num_alloc) | 78 | if (dlp->num_used < dlp->num_alloc) | |
81 | dlp->objs[dlp->num_used++] = obj; | 79 | dlp->objs[dlp->num_used++] = obj; | |
82 | return false; | 80 | return false; | |
83 | } | 81 | } | |
84 | 82 | |||
85 | static bool | 83 | static bool | |
86 | _rtld_is_exported(const Elf_Sym *def) | 84 | _rtld_is_exported(const Elf_Sym *def) | |
87 | { | 85 | { | |
88 | static const fptr_t _rtld_exports[] = { | 86 | static const fptr_t _rtld_exports[] = { | |
89 | (fptr_t)dlopen, | 87 | (fptr_t)dlopen, | |
90 | (fptr_t)dlclose, | 88 | (fptr_t)dlclose, | |
91 | (fptr_t)dlsym, | 89 | (fptr_t)dlsym, | |
92 | (fptr_t)dlvsym, | 90 | (fptr_t)dlvsym, | |
93 | (fptr_t)dlerror, | 91 | (fptr_t)dlerror, | |
94 | (fptr_t)dladdr, | 92 | (fptr_t)dladdr, | |
95 | (fptr_t)dlinfo, | 93 | (fptr_t)dlinfo, | |
96 | (fptr_t)dl_iterate_phdr, | 94 | (fptr_t)dl_iterate_phdr, | |
97 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | 95 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | |
98 | (fptr_t)_rtld_tls_allocate, | 96 | (fptr_t)_rtld_tls_allocate, | |
99 | (fptr_t)_rtld_tls_free, | 97 | (fptr_t)_rtld_tls_free, | |
100 | (fptr_t)__tls_get_addr, | 98 | (fptr_t)__tls_get_addr, | |
101 | #ifdef __i386__ | 99 | #ifdef __i386__ | |
102 | (fptr_t)___tls_get_addr, | 100 | (fptr_t)___tls_get_addr, | |
103 | #endif | 101 | #endif | |
104 | #endif | 102 | #endif | |
105 | NULL | 103 | NULL | |
106 | }; | 104 | }; | |
107 | int i; | 105 | int i; | |
108 | fptr_t value; | 106 | fptr_t value; | |
109 | 107 | |||
110 | value = (fptr_t)(_rtld_objself.relocbase + def->st_value); | 108 | value = (fptr_t)(_rtld_objself.relocbase + def->st_value); | |
111 | for (i = 0; _rtld_exports[i] != NULL; i++) { | 109 | for (i = 0; _rtld_exports[i] != NULL; i++) { | |
112 | if (value == _rtld_exports[i]) | 110 | if (value == _rtld_exports[i]) | |
113 | return true; | 111 | return true; | |
114 | } | 112 | } | |
115 | return false; | 113 | return false; | |
116 | } | 114 | } | |
117 | 115 | |||
118 | /* | 116 | /* | |
119 | * Hash function for symbol table lookup. Don't even think about changing | 117 | * Hash function for symbol table lookup. Don't even think about changing | |
120 | * this. It is specified by the System V ABI. | 118 | * this. It is specified by the System V ABI. | |
121 | */ | 119 | */ | |
122 | unsigned long | 120 | unsigned long | |
123 | _rtld_elf_hash(const char *name) | 121 | _rtld_elf_hash(const char *name) | |
124 | { | 122 | { | |
125 | const unsigned char *p = (const unsigned char *) name; | 123 | const unsigned char *p = (const unsigned char *) name; | |
126 | unsigned long h = 0; | 124 | unsigned long h = 0; | |
127 | unsigned long g; | 125 | unsigned long g; | |
128 | unsigned long c; | 126 | unsigned long c; | |
129 | 127 | |||
130 | for (; __predict_true((c = *p) != '\0'); p++) { | 128 | for (; __predict_true((c = *p) != '\0'); p++) { | |
131 | h <<= 4; | 129 | h <<= 4; | |
132 | h += c; | 130 | h += c; | |
133 | if ((g = h & 0xf0000000) != 0) { | 131 | if ((g = h & 0xf0000000) != 0) { | |
134 | h ^= g; | 132 | h ^= g; | |
135 | h ^= g >> 24; | 133 | h ^= g >> 24; | |
136 | } | 134 | } | |
137 | } | 135 | } | |
138 | return (h); | 136 | return (h); | |
139 | } | 137 | } | |
140 | 138 | |||
141 | const Elf_Sym * | 139 | const Elf_Sym * | |
142 | _rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist, | 140 | _rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist, | |
143 | const Obj_Entry **defobj_out, u_int flags, const Ver_Entry *ventry, | 141 | const Obj_Entry **defobj_out, u_int flags, const Ver_Entry *ventry, | |
144 | DoneList *dlp) | 142 | DoneList *dlp) | |
145 | { | 143 | { | |
146 | const Elf_Sym *symp; | 144 | const Elf_Sym *symp; | |
147 | const Elf_Sym *def; | 145 | const Elf_Sym *def; | |
148 | const Obj_Entry *defobj; | 146 | const Obj_Entry *defobj; | |
149 | const Objlist_Entry *elm; | 147 | const Objlist_Entry *elm; | |
150 | 148 | |||
151 | def = NULL; | 149 | def = NULL; | |
152 | defobj = NULL; | 150 | defobj = NULL; | |
153 | SIMPLEQ_FOREACH(elm, objlist, link) { | 151 | SIMPLEQ_FOREACH(elm, objlist, link) { | |
154 | if (_rtld_donelist_check(dlp, elm->obj)) | 152 | if (_rtld_donelist_check(dlp, elm->obj)) | |
155 | continue; | 153 | continue; | |
156 | rdbg(("search object %p (%s) for %s", elm->obj, elm->obj->path, | 154 | rdbg(("search object %p (%s) for %s", elm->obj, elm->obj->path, | |
157 | name)); | 155 | name)); | |
158 | symp = _rtld_symlook_obj(name, hash, elm->obj, flags, ventry); | 156 | symp = _rtld_symlook_obj(name, hash, elm->obj, flags, ventry); | |
159 | if (symp != NULL) { | 157 | if (symp != NULL) { | |
160 | if ((def == NULL) || | 158 | if ((def == NULL) || | |
161 | (ELF_ST_BIND(symp->st_info) != STB_WEAK)) { | 159 | (ELF_ST_BIND(symp->st_info) != STB_WEAK)) { | |
162 | def = symp; | 160 | def = symp; | |
163 | defobj = elm->obj; | 161 | defobj = elm->obj; | |
164 | if (ELF_ST_BIND(def->st_info) != STB_WEAK) | 162 | if (ELF_ST_BIND(def->st_info) != STB_WEAK) | |
165 | break; | 163 | break; | |
166 | } | 164 | } | |
167 | } | 165 | } | |
168 | } | 166 | } | |
169 | if (def != NULL) | 167 | if (def != NULL) | |
170 | *defobj_out = defobj; | 168 | *defobj_out = defobj; | |
171 | return def; | 169 | return def; | |
172 | } | 170 | } | |
173 | 171 | |||
174 | /* | 172 | /* | |
175 | * Search the symbol table of a shared object and all objects needed by it for | 173 | * Search the symbol table of a shared object and all objects needed by it for | |
176 | * a symbol of the given name. Search order is breadth-first. Returns a pointer | 174 | * a symbol of the given name. Search order is breadth-first. Returns a pointer | |
177 | * to the symbol, or NULL if no definition was found. | 175 | * to the symbol, or NULL if no definition was found. | |
178 | */ | 176 | */ | |
179 | const Elf_Sym * | 177 | const Elf_Sym * | |
180 | _rtld_symlook_needed(const char *name, unsigned long hash, | 178 | _rtld_symlook_needed(const char *name, unsigned long hash, | |
181 | const Needed_Entry *needed, const Obj_Entry **defobj_out, u_int flags, | 179 | const Needed_Entry *needed, const Obj_Entry **defobj_out, u_int flags, | |
182 | const Ver_Entry *ventry, DoneList *breadth, DoneList *depth) | 180 | const Ver_Entry *ventry, DoneList *breadth, DoneList *depth) | |
183 | { | 181 | { | |
184 | const Elf_Sym *def, *def_w; | 182 | const Elf_Sym *def, *def_w; | |
185 | const Needed_Entry *n; | 183 | const Needed_Entry *n; | |
186 | const Obj_Entry *obj, *defobj, *defobj1; | 184 | const Obj_Entry *obj, *defobj, *defobj1; | |
187 | 185 | |||
188 | def = def_w = NULL; | 186 | def = def_w = NULL; | |
189 | defobj = NULL; | 187 | defobj = NULL; | |
190 | for (n = needed; n != NULL; n = n->next) { | 188 | for (n = needed; n != NULL; n = n->next) { | |
191 | if ((obj = n->obj) == NULL) | 189 | if ((obj = n->obj) == NULL) | |
192 | continue; | 190 | continue; | |
193 | if (_rtld_donelist_check(breadth, obj)) | 191 | if (_rtld_donelist_check(breadth, obj)) | |
194 | continue; | 192 | continue; | |
195 | def = _rtld_symlook_obj(name, hash, obj, flags, ventry); | 193 | def = _rtld_symlook_obj(name, hash, obj, flags, ventry); | |
196 | if (def == NULL) | 194 | if (def == NULL) | |
197 | continue; | 195 | continue; | |
198 | defobj = obj; | 196 | defobj = obj; | |
199 | if (ELF_ST_BIND(def->st_info) != STB_WEAK) { | 197 | if (ELF_ST_BIND(def->st_info) != STB_WEAK) { | |
200 | *defobj_out = defobj; | 198 | *defobj_out = defobj; | |
201 | 199 | |||
202 | return (def); | 200 | return (def); | |
203 | } | 201 | } | |
204 | } | 202 | } | |
205 | /* | 203 | /* | |
206 | * Either the symbol definition has not been found in directly needed | 204 | * Either the symbol definition has not been found in directly needed | |
207 | * objects, or the found symbol is weak. | 205 | * objects, or the found symbol is weak. | |
208 | */ | 206 | */ | |
209 | for (n = needed; n != NULL; n = n->next) { | 207 | for (n = needed; n != NULL; n = n->next) { | |
210 | if ((obj = n->obj) == NULL) | 208 | if ((obj = n->obj) == NULL) | |
211 | continue; | 209 | continue; | |
212 | if (_rtld_donelist_check(depth, obj)) | 210 | if (_rtld_donelist_check(depth, obj)) | |
213 | continue; | 211 | continue; | |
214 | def_w = _rtld_symlook_needed(name, hash, obj->needed, &defobj1, | 212 | def_w = _rtld_symlook_needed(name, hash, obj->needed, &defobj1, | |
215 | flags, ventry, breadth, depth); | 213 | flags, ventry, breadth, depth); | |
216 | if (def_w == NULL) | 214 | if (def_w == NULL) | |
217 | continue; | 215 | continue; | |
218 | if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) { | 216 | if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) { | |
219 | def = def_w; | 217 | def = def_w; | |
220 | defobj = defobj1; | 218 | defobj = defobj1; | |
221 | if (ELF_ST_BIND(def_w->st_info) != STB_WEAK) | 219 | if (ELF_ST_BIND(def_w->st_info) != STB_WEAK) | |
222 | break; | 220 | break; | |
223 | } | 221 | } | |
224 | } | 222 | } | |
225 | if (def != NULL) | 223 | if (def != NULL) | |
226 | *defobj_out = defobj; | 224 | *defobj_out = defobj; | |
227 | 225 | |||
228 | return def; | 226 | return def; | |
229 | } | 227 | } | |
230 | 228 | |||
231 | /* | 229 | /* | |
232 | * Search the symbol table of a single shared object for a symbol of | 230 | * Search the symbol table of a single shared object for a symbol of | |
233 | * the given name. Returns a pointer to the symbol, or NULL if no | 231 | * the given name. Returns a pointer to the symbol, or NULL if no | |
234 | * definition was found. | 232 | * definition was found. | |
235 | * | 233 | * | |
236 | * The symbol's hash value is passed in for efficiency reasons; that | 234 | * The symbol's hash value is passed in for efficiency reasons; that | |
237 | * eliminates many recomputations of the hash value. | 235 | * eliminates many recomputations of the hash value. | |
238 | */ | 236 | */ | |
239 | const Elf_Sym * | 237 | const Elf_Sym * | |
240 | _rtld_symlook_obj(const char *name, unsigned long hash, | 238 | _rtld_symlook_obj(const char *name, unsigned long hash, | |
241 | const Obj_Entry *obj, u_int flags, const Ver_Entry *ventry) | 239 | const Obj_Entry *obj, u_int flags, const Ver_Entry *ventry) | |
242 | { | 240 | { | |
243 | unsigned long symnum; | 241 | unsigned long symnum; | |
244 | const Elf_Sym *vsymp = NULL; | 242 | const Elf_Sym *vsymp = NULL; | |
245 | Elf_Half verndx; | 243 | Elf_Half verndx; | |
246 | int vcount = 0; | 244 | int vcount = 0; | |
247 | 245 | |||
248 | for (symnum = obj->buckets[fast_remainder32(hash, obj->nbuckets, | 246 | for (symnum = obj->buckets[fast_remainder32(hash, obj->nbuckets, | |
249 | obj->nbuckets_m, obj->nbuckets_s1, obj->nbuckets_s2)]; | 247 | obj->nbuckets_m, obj->nbuckets_s1, obj->nbuckets_s2)]; | |
250 | symnum != ELF_SYM_UNDEFINED; | 248 | symnum != ELF_SYM_UNDEFINED; | |
251 | symnum = obj->chains[symnum]) { | 249 | symnum = obj->chains[symnum]) { | |
252 | const Elf_Sym *symp; | 250 | const Elf_Sym *symp; | |
253 | const char *strp; | 251 | const char *strp; | |
254 | 252 | |||
255 | assert(symnum < obj->nchains); | 253 | assert(symnum < obj->nchains); | |
256 | symp = obj->symtab + symnum; | 254 | symp = obj->symtab + symnum; | |
257 | strp = obj->strtab + symp->st_name; | 255 | strp = obj->strtab + symp->st_name; | |
258 | rdbg(("check \"%s\" vs \"%s\" in %s", name, strp, obj->path)); | 256 | rdbg(("check \"%s\" vs \"%s\" in %s", name, strp, obj->path)); | |
259 | if (name[1] != strp[1] || strcmp(name, strp)) | 257 | if (name[1] != strp[1] || strcmp(name, strp)) | |
260 | continue; | 258 | continue; | |
261 | #ifdef __mips__ | 259 | #ifdef __mips__ | |
262 | if (symp->st_shndx == SHN_UNDEF) | 260 | if (symp->st_shndx == SHN_UNDEF) | |
263 | continue; | 261 | continue; | |
264 | #else | 262 | #else | |
265 | /* | 263 | /* | |
266 | * XXX DANGER WILL ROBINSON! | 264 | * XXX DANGER WILL ROBINSON! | |
267 | * If we have a function pointer in the executable's | 265 | * If we have a function pointer in the executable's | |
268 | * data section, it points to the executable's PLT | 266 | * data section, it points to the executable's PLT | |
269 | * slot, and there is NO relocation emitted. To make | 267 | * slot, and there is NO relocation emitted. To make | |
270 | * the function pointer comparable to function pointers | 268 | * the function pointer comparable to function pointers | |
271 | * in shared libraries, we must resolve data references | 269 | * in shared libraries, we must resolve data references | |
272 | * in the libraries to point to PLT slots in the | 270 | * in the libraries to point to PLT slots in the | |
273 | * executable, if they exist. | 271 | * executable, if they exist. | |
274 | */ | 272 | */ | |
275 | if (symp->st_shndx == SHN_UNDEF && | 273 | if (symp->st_shndx == SHN_UNDEF && | |
276 | ((flags & SYMLOOK_IN_PLT) || | 274 | ((flags & SYMLOOK_IN_PLT) || | |
277 | symp->st_value == 0 || | 275 | symp->st_value == 0 || | |
278 | ELF_ST_TYPE(symp->st_info) != STT_FUNC)) | 276 | ELF_ST_TYPE(symp->st_info) != STT_FUNC)) | |
279 | continue; | 277 | continue; | |
280 | #endif | 278 | #endif | |
281 | 279 | |||
282 | if (ventry == NULL) { | 280 | if (ventry == NULL) { | |
283 | if (obj->versyms != NULL) { | 281 | if (obj->versyms != NULL) { | |
284 | verndx = VER_NDX(obj->versyms[symnum].vs_vers); | 282 | verndx = VER_NDX(obj->versyms[symnum].vs_vers); | |
285 | if (verndx > obj->vertabnum) { | 283 | if (verndx > obj->vertabnum) { | |
286 | _rtld_error("%s: symbol %s references " | 284 | _rtld_error("%s: symbol %s references " | |
287 | "wrong version %d", obj->path, | 285 | "wrong version %d", obj->path, | |
288 | &obj->strtab[symnum], verndx); | 286 | &obj->strtab[symnum], verndx); | |
289 | continue; | 287 | continue; | |
290 | } | 288 | } | |
291 | 289 | |||
292 | /* | 290 | /* | |
293 | * If we are not called from dlsym (i.e. this | 291 | * If we are not called from dlsym (i.e. this | |
294 | * is a normal relocation from unversioned | 292 | * is a normal relocation from unversioned | |
295 | * binary), accept the symbol immediately | 293 | * binary), accept the symbol immediately | |
296 | * if it happens to have first version after | 294 | * if it happens to have first version after | |
297 | * this shared object became versioned. | 295 | * this shared object became versioned. | |
298 | * Otherwise, if symbol is versioned and not | 296 | * Otherwise, if symbol is versioned and not | |
299 | * hidden, remember it. If it is the only | 297 | * hidden, remember it. If it is the only | |
300 | * symbol with this name exported by the shared | 298 | * symbol with this name exported by the shared | |
301 | * object, it will be returned as a match at the | 299 | * object, it will be returned as a match at the | |
302 | * end of the function. If symbol is global | 300 | * end of the function. If symbol is global | |
303 | * (verndx < 2) accept it unconditionally. | 301 | * (verndx < 2) accept it unconditionally. | |
304 | */ | 302 | */ | |
305 | if (!(flags & SYMLOOK_DLSYM) && | 303 | if (!(flags & SYMLOOK_DLSYM) && | |
306 | verndx == VER_NDX_GIVEN) { | 304 | verndx == VER_NDX_GIVEN) { | |
307 | return symp; | 305 | return symp; | |
308 | } else if (verndx >= VER_NDX_GIVEN) { | 306 | } else if (verndx >= VER_NDX_GIVEN) { | |
309 | if (!(obj->versyms[symnum].vs_vers & VER_NDX_HIDDEN)) { | 307 | if (!(obj->versyms[symnum].vs_vers & VER_NDX_HIDDEN)) { | |
310 | if (vsymp == NULL) | 308 | if (vsymp == NULL) | |
311 | vsymp = symp; | 309 | vsymp = symp; | |
312 | vcount++; | 310 | vcount++; | |
313 | } | 311 | } | |
314 | continue; | 312 | continue; | |
315 | } | 313 | } | |
316 | } | 314 | } | |
317 | return symp; | 315 | return symp; | |
318 | } else { | 316 | } else { | |
319 | if (obj->versyms == NULL) { | 317 | if (obj->versyms == NULL) { | |
320 | if (_rtld_object_match_name(obj, ventry->name)){ | 318 | if (_rtld_object_match_name(obj, ventry->name)){ | |
321 | _rtld_error("%s: object %s should " | 319 | _rtld_error("%s: object %s should " | |
322 | "provide version %s for symbol %s", | 320 | "provide version %s for symbol %s", | |
323 | _rtld_objself.path, obj->path, | 321 | _rtld_objself.path, obj->path, | |
324 | ventry->name, &obj->strtab[symnum]); | 322 | ventry->name, &obj->strtab[symnum]); | |
325 | continue; | 323 | continue; | |
326 | } | 324 | } | |
327 | } else { | 325 | } else { | |
328 | verndx = VER_NDX(obj->versyms[symnum].vs_vers); | 326 | verndx = VER_NDX(obj->versyms[symnum].vs_vers); | |
329 | if (verndx > obj->vertabnum) { | 327 | if (verndx > obj->vertabnum) { | |
330 | _rtld_error("%s: symbol %s references " | 328 | _rtld_error("%s: symbol %s references " | |
331 | "wrong version %d", obj->path, | 329 | "wrong version %d", obj->path, | |
332 | &obj->strtab[symnum], verndx); | 330 | &obj->strtab[symnum], verndx); | |
333 | continue; | 331 | continue; | |
334 | } | 332 | } | |
335 | if (obj->vertab[verndx].hash != ventry->hash || | 333 | if (obj->vertab[verndx].hash != ventry->hash || | |
336 | strcmp(obj->vertab[verndx].name, ventry->name)) { | 334 | strcmp(obj->vertab[verndx].name, ventry->name)) { | |
337 | /* | 335 | /* | |
338 | * Version does not match. Look if this | 336 | * Version does not match. Look if this | |
339 | * is a global symbol and if it is not | 337 | * is a global symbol and if it is not | |
340 | * hidden. If global symbol (verndx < 2) | 338 | * hidden. If global symbol (verndx < 2) | |
341 | * is available, use it. Do not return | 339 | * is available, use it. Do not return | |
342 | * symbol if we are called by dlvsym, | 340 | * symbol if we are called by dlvsym, | |
343 | * because dlvsym looks for a specific | 341 | * because dlvsym looks for a specific | |
344 | * version and default one is not what | 342 | * version and default one is not what | |
345 | * dlvsym wants. | 343 | * dlvsym wants. | |
346 | */ | 344 | */ | |
347 | if ((flags & SYMLOOK_DLSYM) || | 345 | if ((flags & SYMLOOK_DLSYM) || | |
348 | (obj->versyms[symnum].vs_vers & VER_NDX_HIDDEN) || | 346 | (obj->versyms[symnum].vs_vers & VER_NDX_HIDDEN) || | |
349 | (verndx >= VER_NDX_GIVEN)) | 347 | (verndx >= VER_NDX_GIVEN)) | |
350 | continue; | 348 | continue; | |
351 | } | 349 | } | |
352 | } | 350 | } | |
353 | return symp; | 351 | return symp; | |
354 | } | 352 | } | |
355 | } | 353 | } | |
356 | if (vcount == 1) | 354 | if (vcount == 1) | |
357 | return vsymp; | 355 | return vsymp; | |
358 | return NULL; | 356 | return NULL; | |
359 | } | 357 | } | |
360 | 358 | |||
361 | #ifdef COMBRELOC | 359 | #ifdef COMBRELOC | |
362 | static const Obj_Entry *_rtld_last_refobj; | 360 | static const Obj_Entry *_rtld_last_refobj; | |
363 | 361 | |||
364 | /* | 362 | /* | |
365 | * Called when an object is freed. Reset the cached symbol look up if | 363 | * Called when an object is freed. Reset the cached symbol look up if | |
366 | * our last referencing or definition object just got unloaded. | 364 | * our last referencing or definition object just got unloaded. | |
367 | */ | 365 | */ | |
368 | void | 366 | void | |
369 | _rtld_combreloc_reset(const Obj_Entry *obj) | 367 | _rtld_combreloc_reset(const Obj_Entry *obj) | |
370 | { | 368 | { | |
371 | if (_rtld_last_refobj == obj) | 369 | if (_rtld_last_refobj == obj) | |
372 | _rtld_last_refobj = NULL; | 370 | _rtld_last_refobj = NULL; | |
373 | } | 371 | } | |
374 | #endif | 372 | #endif | |
375 | 373 | |||
376 | /* | 374 | /* | |
377 | * Given a symbol number in a referencing object, find the corresponding | 375 | * Given a symbol number in a referencing object, find the corresponding | |
378 | * definition of the symbol. Returns a pointer to the symbol, or NULL if | 376 | * definition of the symbol. Returns a pointer to the symbol, or NULL if | |
379 | * no definition was found. Returns a pointer to the Obj_Entry of the | 377 | * no definition was found. Returns a pointer to the Obj_Entry of the | |
380 | * defining object via the reference parameter DEFOBJ_OUT. | 378 | * defining object via the reference parameter DEFOBJ_OUT. | |
381 | */ | 379 | */ | |
382 | const Elf_Sym * | 380 | const Elf_Sym * | |
383 | _rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj, | 381 | _rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj, | |
384 | const Obj_Entry **defobj_out, u_int flags) | 382 | const Obj_Entry **defobj_out, u_int flags) | |
385 | { | 383 | { | |
386 | const Elf_Sym *ref; | 384 | const Elf_Sym *ref; | |
387 | const Elf_Sym *def; | 385 | const Elf_Sym *def; | |
388 | const Obj_Entry *defobj; | 386 | const Obj_Entry *defobj; | |
389 | const char *name; | 387 | const char *name; | |
390 | unsigned long hash; | 388 | unsigned long hash; | |
391 | 389 | |||
392 | #ifdef COMBRELOC | 390 | #ifdef COMBRELOC | |
393 | /* | 391 | /* | |
394 | * COMBRELOC combines multiple reloc sections and sorts them to make | 392 | * COMBRELOC combines multiple reloc sections and sorts them to make | |
395 | * dynamic symbol lookup caching possible. | 393 | * dynamic symbol lookup caching possible. | |
396 | * | 394 | * | |
397 | * So if the lookup we are doing is the same as the previous lookup | 395 | * So if the lookup we are doing is the same as the previous lookup | |
398 | * return the cached results. | 396 | * return the cached results. | |
399 | */ | 397 | */ | |
400 | static unsigned long last_symnum; | 398 | static unsigned long last_symnum; | |
401 | static const Obj_Entry *last_defobj; | 399 | static const Obj_Entry *last_defobj; | |
402 | static const Elf_Sym *last_def; | 400 | static const Elf_Sym *last_def; | |
403 | 401 | |||
404 | if (symnum == last_symnum && refobj == _rtld_last_refobj | 402 | if (symnum == last_symnum && refobj == _rtld_last_refobj | |
405 | && !(flags & SYMLOOK_IN_PLT)) { | 403 | && !(flags & SYMLOOK_IN_PLT)) { | |
406 | *defobj_out = last_defobj; | 404 | *defobj_out = last_defobj; | |
407 | return last_def; | 405 | return last_def; | |
408 | } | 406 | } | |
409 | #endif | 407 | #endif | |
410 | 408 | |||
411 | ref = refobj->symtab + symnum; | 409 | ref = refobj->symtab + symnum; | |
412 | name = refobj->strtab + ref->st_name; | 410 | name = refobj->strtab + ref->st_name; | |
413 | 411 | |||
414 | /* | 412 | /* | |
415 | * We don't have to do a full scale lookup if the symbol is local. | 413 | * We don't have to do a full scale lookup if the symbol is local. | |
416 | * We know it will bind to the instance in this load module; to | 414 | * We know it will bind to the instance in this load module; to | |
417 | * which we already have a pointer (ie ref). | 415 | * which we already have a pointer (ie ref). | |
418 | */ | 416 | */ | |
419 | if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) { | 417 | if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) { | |
420 | if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { | 418 | if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { | |
421 | _rtld_error("%s: Bogus symbol table entry %lu", | 419 | _rtld_error("%s: Bogus symbol table entry %lu", | |
422 | refobj->path, symnum); | 420 | refobj->path, symnum); | |
423 | } | 421 | } | |
424 | 422 | |||
425 | hash = _rtld_elf_hash(name); | 423 | hash = _rtld_elf_hash(name); | |
426 | defobj = NULL; | 424 | defobj = NULL; | |
427 | def = _rtld_symlook_default(name, hash, refobj, &defobj, flags, | 425 | def = _rtld_symlook_default(name, hash, refobj, &defobj, flags, | |
428 | _rtld_fetch_ventry(refobj, symnum)); | 426 | _rtld_fetch_ventry(refobj, symnum)); | |
429 | } else { | 427 | } else { | |
430 | rdbg(("STB_LOCAL symbol %s in %s", name, refobj->path)); | 428 | rdbg(("STB_LOCAL symbol %s in %s", name, refobj->path)); | |
431 | def = ref; | 429 | def = ref; | |
432 | defobj = refobj; | 430 | defobj = refobj; | |
433 | } | 431 | } | |
434 | 432 | |||
435 | /* | 433 | /* | |
436 | * If we found no definition and the reference is weak, treat the | 434 | * If we found no definition and the reference is weak, treat the | |
437 | * symbol as having the value zero. | 435 | * symbol as having the value zero. | |
438 | */ | 436 | */ | |
439 | if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) { | 437 | if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) { | |
440 | rdbg((" returning _rtld_sym_zero@_rtld_objself")); | 438 | rdbg((" returning _rtld_sym_zero@_rtld_objself")); | |
441 | def = &_rtld_sym_zero; | 439 | def = &_rtld_sym_zero; | |
442 | defobj = &_rtld_objself; | 440 | defobj = &_rtld_objself; | |
443 | } | 441 | } | |
444 | 442 | |||
445 | if (def != NULL) { | 443 | if (def != NULL) { | |
446 | *defobj_out = defobj; | 444 | *defobj_out = defobj; | |
447 | #ifdef COMBRELOC | 445 | #ifdef COMBRELOC | |
448 | if (!(flags & SYMLOOK_IN_PLT)) { | 446 | if (!(flags & SYMLOOK_IN_PLT)) { | |
449 | /* | 447 | /* | |
450 | * Cache the lookup arguments and results if this was | 448 | * Cache the lookup arguments and results if this was | |
451 | * non-PLT lookup. | 449 | * non-PLT lookup. | |
452 | */ | 450 | */ | |
453 | last_symnum = symnum; | 451 | last_symnum = symnum; | |
454 | _rtld_last_refobj = refobj; | 452 | _rtld_last_refobj = refobj; | |
455 | last_def = def; | 453 | last_def = def; | |
456 | last_defobj = defobj; | 454 | last_defobj = defobj; | |
457 | } | 455 | } | |
458 | #endif | 456 | #endif | |
459 | } else { | 457 | } else { | |
460 | rdbg(("lookup failed")); | 458 | rdbg(("lookup failed")); | |
461 | _rtld_error("%s: Undefined %ssymbol \"%s\" (symnum = %ld)", | 459 | _rtld_error("%s: Undefined %ssymbol \"%s\" (symnum = %ld)", | |
462 | refobj->path, (flags & SYMLOOK_IN_PLT) ? "PLT " : "", | 460 | refobj->path, (flags & SYMLOOK_IN_PLT) ? "PLT " : "", | |
463 | name, symnum); | 461 | name, symnum); | |
464 | } | 462 | } | |
465 | return def; | 463 | return def; | |
466 | } | 464 | } | |
467 | 465 | |||
468 | const Elf_Sym * | 466 | const Elf_Sym * | |
469 | _rtld_find_plt_symdef(unsigned long symnum, const Obj_Entry *obj, | 467 | _rtld_find_plt_symdef(unsigned long symnum, const Obj_Entry *obj, | |
470 | const Obj_Entry **defobj, bool imm) | 468 | const Obj_Entry **defobj, bool imm) | |
471 | { | 469 | { | |
472 | const Elf_Sym *def = _rtld_find_symdef(symnum, obj, defobj, | 470 | const Elf_Sym *def = _rtld_find_symdef(symnum, obj, defobj, | |
473 | SYMLOOK_IN_PLT); | 471 | SYMLOOK_IN_PLT); | |
474 | if (__predict_false(def == NULL)) | 472 | if (__predict_false(def == NULL)) | |
475 | return NULL; | 473 | return NULL; | |
476 | 474 | |||
477 | if (__predict_false(def == &_rtld_sym_zero)) { | 475 | if (__predict_false(def == &_rtld_sym_zero)) { | |
478 | /* tp is set during lazy binding. */ | 476 | /* tp is set during lazy binding. */ | |
479 | if (imm) { | 477 | if (imm) { | |
480 | const Elf_Sym *ref = obj->symtab + symnum; | 478 | const Elf_Sym *ref = obj->symtab + symnum; | |
481 | const char *name = obj->strtab + ref->st_name; | 479 | const char *name = obj->strtab + ref->st_name; | |
482 | 480 | |||
483 | _rtld_error( | 481 | _rtld_error( | |
484 | "%s: Trying to call undefined weak symbol `%s'", | 482 | "%s: Trying to call undefined weak symbol `%s'", | |
485 | obj->path, name); | 483 | obj->path, name); | |
486 | return NULL; | 484 | return NULL; | |
487 | } | 485 | } | |
488 | } | 486 | } | |
489 | return def; | 487 | return def; | |
490 | } | 488 | } | |
491 | 489 | |||
492 | /* | 490 | /* | |
493 | * Given a symbol name in a referencing object, find the corresponding | 491 | * Given a symbol name in a referencing object, find the corresponding | |
494 | * definition of the symbol. Returns a pointer to the symbol, or NULL if | 492 | * definition of the symbol. Returns a pointer to the symbol, or NULL if | |
495 | * no definition was found. Returns a pointer to the Obj_Entry of the | 493 | * no definition was found. Returns a pointer to the Obj_Entry of the | |
496 | * defining object via the reference parameter DEFOBJ_OUT. | 494 | * defining object via the reference parameter DEFOBJ_OUT. | |
497 | */ | 495 | */ | |
498 | const Elf_Sym * | 496 | const Elf_Sym * | |
499 | _rtld_symlook_default(const char *name, unsigned long hash, | 497 | _rtld_symlook_default(const char *name, unsigned long hash, | |
500 | const Obj_Entry *refobj, const Obj_Entry **defobj_out, u_int flags, | 498 | const Obj_Entry *refobj, const Obj_Entry **defobj_out, u_int flags, | |
501 | const Ver_Entry *ventry) | 499 | const Ver_Entry *ventry) | |
502 | { | 500 | { | |
503 | const Elf_Sym *def; | 501 | const Elf_Sym *def; | |
504 | const Elf_Sym *symp; | 502 | const Elf_Sym *symp; | |
505 | const Obj_Entry *obj; | 503 | const Obj_Entry *obj; | |
506 | const Obj_Entry *defobj; | 504 | const Obj_Entry *defobj; | |
507 | const Objlist_Entry *elm; | 505 | const Objlist_Entry *elm; | |
508 | def = NULL; | 506 | def = NULL; | |
509 | defobj = NULL; | 507 | defobj = NULL; | |
510 | DoneList donelist; | 508 | DoneList donelist; | |
511 | 509 | |||
512 | _rtld_donelist_init(&donelist); | 510 | _rtld_donelist_init(&donelist); | |
513 | 511 | |||
514 | /* Look first in the referencing object if linked symbolically. */ | 512 | /* Look first in the referencing object if linked symbolically. */ | |
515 | if (refobj->symbolic && !_rtld_donelist_check(&donelist, refobj)) { | 513 | if (refobj->symbolic && !_rtld_donelist_check(&donelist, refobj)) { | |
516 | rdbg(("search referencing object for %s", name)); | 514 | rdbg(("search referencing object for %s", name)); | |
517 | symp = _rtld_symlook_obj(name, hash, refobj, flags, ventry); | 515 | symp = _rtld_symlook_obj(name, hash, refobj, flags, ventry); | |
518 | if (symp != NULL) { | 516 | if (symp != NULL) { | |
519 | def = symp; | 517 | def = symp; | |
520 | defobj = refobj; | 518 | defobj = refobj; | |
521 | } | 519 | } | |
522 | } | 520 | } | |
523 | 521 | |||
524 | /* Search all objects loaded at program start up. */ | 522 | /* Search all objects loaded at program start up. */ | |
525 | if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { | 523 | if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { | |
526 | rdbg(("search _rtld_list_main for %s", name)); | 524 | rdbg(("search _rtld_list_main for %s", name)); | |
527 | symp = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, | 525 | symp = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, | |
528 | flags, ventry, &donelist); | 526 | flags, ventry, &donelist); | |
529 | if (symp != NULL && | 527 | if (symp != NULL && | |
530 | (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { | 528 | (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { | |
531 | def = symp; | 529 | def = symp; | |
532 | defobj = obj; | 530 | defobj = obj; | |
533 | } | 531 | } | |
534 | } | 532 | } | |
535 | 533 | |||
536 | /* Search all RTLD_GLOBAL objects. */ | 534 | /* Search all RTLD_GLOBAL objects. */ | |
537 | if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { | 535 | if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { | |
538 | rdbg(("search _rtld_list_global for %s", name)); | 536 | rdbg(("search _rtld_list_global for %s", name)); | |
539 | symp = _rtld_symlook_list(name, hash, &_rtld_list_global, | 537 | symp = _rtld_symlook_list(name, hash, &_rtld_list_global, | |
540 | &obj, flags, ventry, &donelist); | 538 | &obj, flags, ventry, &donelist); | |
541 | if (symp != NULL && | 539 | if (symp != NULL && | |
542 | (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { | 540 | (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { | |
543 | def = symp; | 541 | def = symp; | |
544 | defobj = obj; | 542 | defobj = obj; | |
545 | } | 543 | } | |
546 | } | 544 | } | |
547 | 545 | |||
548 | /* Search all dlopened DAGs containing the referencing object. */ | 546 | /* Search all dlopened DAGs containing the referencing object. */ | |
549 | SIMPLEQ_FOREACH(elm, &refobj->dldags, link) { | 547 | SIMPLEQ_FOREACH(elm, &refobj->dldags, link) { | |
550 | if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) | 548 | if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) | |
551 | break; | 549 | break; | |
552 | rdbg(("search DAG with root %p (%s) for %s", elm->obj, | 550 | rdbg(("search DAG with root %p (%s) for %s", elm->obj, | |
553 | elm->obj->path, name)); | 551 | elm->obj->path, name)); | |
554 | symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers, | 552 | symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers, | |
555 | &obj, flags, ventry, &donelist); | 553 | &obj, flags, ventry, &donelist); | |
556 | if (symp != NULL && | 554 | if (symp != NULL && | |
557 | (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { | 555 | (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { | |
558 | def = symp; | 556 | def = symp; | |
559 | defobj = obj; | 557 | defobj = obj; | |
560 | } | 558 | } | |
561 | } | 559 | } | |
562 | 560 | |||
563 | /* | 561 | /* | |
564 | * Search the dynamic linker itself, and possibly resolve the | 562 | * Search the dynamic linker itself, and possibly resolve the | |
565 | * symbol from there. This is how the application links to | 563 | * symbol from there. This is how the application links to | |
566 | * dynamic linker services such as dlopen. Only the values listed | 564 | * dynamic linker services such as dlopen. Only the values listed | |
567 | * in the "_rtld_exports" array can be resolved from the dynamic | 565 | * in the "_rtld_exports" array can be resolved from the dynamic | |
568 | * linker. | 566 | * linker. | |
569 | */ | 567 | */ | |
570 | if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { | 568 | if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { | |
571 | rdbg(("Search the dynamic linker itself.")); | 569 | rdbg(("Search the dynamic linker itself.")); | |
572 | symp = _rtld_symlook_obj(name, hash, &_rtld_objself, flags, | 570 | symp = _rtld_symlook_obj(name, hash, &_rtld_objself, flags, | |
573 | ventry); | 571 | ventry); | |
574 | if (symp != NULL && _rtld_is_exported(symp)) { | 572 | if (symp != NULL && _rtld_is_exported(symp)) { | |
575 | def = symp; | 573 | def = symp; | |
576 | defobj = &_rtld_objself; | 574 | defobj = &_rtld_objself; | |
577 | } | 575 | } | |
578 | } | 576 | } | |
579 | 577 | |||
580 | if (def != NULL) | 578 | if (def != NULL) | |
581 | *defobj_out = defobj; | 579 | *defobj_out = defobj; | |
582 | return def; | 580 | return def; | |
583 | } | 581 | } |
--- src/libexec/ld.elf_so/arch/arm/Makefile.inc 2005/06/04 16:17:17 1.11
+++ src/libexec/ld.elf_so/arch/arm/Makefile.inc 2013/01/22 21:47:28 1.11.46.1
@@ -1,10 +1,13 @@ | @@ -1,10 +1,13 @@ | |||
1 | # $NetBSD: Makefile.inc,v 1.11 2005/06/04 16:17:17 lukem Exp $ | 1 | # $NetBSD: Makefile.inc,v 1.11.46.1 2013/01/22 21:47:28 matt Exp $ | |
2 | 2 | |||
3 | SRCS+= rtld_start.S mdreloc.c | 3 | SRCS+= rtld_start.S mdreloc.c | |
4 | 4 | |||
5 | # XXX Should not be in CPPFLAGS! | 5 | # XXX Should not be in CPPFLAGS! | |
6 | CPPFLAGS+= -fpic | 6 | CPPFLAGS+= -fpic | |
7 | 7 | |||
8 | CPPFLAGS+= -DELFSIZE=32 | 8 | CPPFLAGS+= -DELFSIZE=32 | |
9 | .if ${MACHINE_ARCH} == "earm" || ${MACHINE_ARCH} == "earmeb" | |||
10 | CPPFLAGS+= -DHAVE_INITFINI_ARRAY | |||
11 | .endif | |||
9 | 12 | |||
10 | LDFLAGS+= -Wl,-e,_rtld_start | 13 | LDFLAGS+= -Wl,-e,_rtld_start |
--- src/libexec/ld.elf_so/arch/arm/rtld_start.S 2009/11/11 14:15:41 1.10
+++ src/libexec/ld.elf_so/arch/arm/rtld_start.S 2013/01/22 21:47:28 1.10.10.1
@@ -1,104 +1,103 @@ | @@ -1,104 +1,103 @@ | |||
1 | /* $NetBSD: rtld_start.S,v 1.10 2009/11/11 14:15:41 skrll Exp $ */ | 1 | /* $NetBSD: rtld_start.S,v 1.10.10.1 2013/01/22 21:47:28 matt Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Matt Thomas and by Charles M. Hannum. | 8 | * by Matt Thomas and by Charles M. Hannum. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <machine/asm.h> | 32 | #include <machine/asm.h> | |
33 | 33 | |||
34 | RCSID("$NetBSD: rtld_start.S,v 1.10 2009/11/11 14:15:41 skrll Exp $") | 34 | RCSID("$NetBSD: rtld_start.S,v 1.10.10.1 2013/01/22 21:47:28 matt Exp $") | |
35 | 35 | |||
36 | .text | 36 | .text | |
37 | .align 0 | 37 | .align 0 | |
38 | .globl _rtld_start | 38 | .globl _rtld_start | |
39 | .type _rtld_start,%function | 39 | .type _rtld_start,%function | |
40 | _rtld_start: | 40 | _rtld_start: | |
41 | sub sp, sp, #8 /* make room for obj_main & exit proc */ | 41 | sub sp, sp, #8 /* make room for obj_main & exit proc */ | |
42 | mov r4, r0 /* save ps_strings */ | 42 | mov r4, r0 /* save ps_strings */ | |
43 | 43 | |||
44 | ldr sl, .L2 | 44 | ldr sl, .L2 | |
45 | ldr r5, .L2+4 | 45 | ldr r5, .L2+4 | |
46 | ldr r0, .L2+8 | 46 | ldr r0, .L2+8 | |
47 | .L1: | 47 | .L1: | |
48 | add sl, pc, sl | 48 | add sl, pc, sl | |
49 | ldr r5, [sl, r5] | 49 | ldr r5, [sl, r5] | |
50 | ldr r0, [sl, r0] | 50 | ldr r0, [sl, r0] | |
51 | 51 | |||
52 | sub r1, sl, r5 /* relocbase */ | 52 | sub r1, sl, r5 /* relocbase */ | |
53 | add r0, r1, r0 /* &_DYNAMIC */ | 53 | add r0, r1, r0 /* &_DYNAMIC */ | |
54 | bl _rtld_relocate_nonplt_self | 54 | bl _rtld_relocate_nonplt_self | |
55 | 55 | |||
56 | sub r1, sl, r5 /* relocbase */ | 56 | sub r1, sl, r5 /* relocbase */ | |
57 | mov r0, sp /* sp */ | 57 | mov r0, sp /* sp */ | |
58 | bl _rtld /* call the shared loader */ | 58 | bl _rtld /* call the shared loader */ | |
59 | mov r3, r0 /* save entry point */ | 59 | mov r3, r0 /* save entry point */ | |
60 | 60 | |||
61 | ldr r2, [sp, #0] /* r2 = cleanup */ | 61 | ldr r2, [sp], #4 /* pop r2 = cleanup */ | |
62 | ldr r1, [sp, #4] /* r1 = obj_main */ | 62 | ldr r1, [sp], #4 /* pop r1 = obj_main */ | |
63 | add sp, sp, #8 /* restore stack */ | |||
64 | mov r0, r4 /* restore ps_strings */ | 63 | mov r0, r4 /* restore ps_strings */ | |
65 | #ifdef _ARM_ARCH_4T | 64 | #ifdef _ARM_ARCH_4T | |
66 | bx r3 /* jump to the entry point */ | 65 | bx r3 /* jump to the entry point */ | |
67 | #else | 66 | #else | |
68 | mov pc, r3 /* jump to the entry point */ | 67 | mov pc, r3 /* jump to the entry point */ | |
69 | #endif | 68 | #endif | |
70 | .L2: | 69 | .L2: | |
71 | .word _GLOBAL_OFFSET_TABLE_ - (.L1+8) | 70 | .word _GLOBAL_OFFSET_TABLE_ - (.L1+8) | |
72 | .word _GLOBAL_OFFSET_TABLE_(GOT) | 71 | .word _GLOBAL_OFFSET_TABLE_(GOT) | |
73 | .word _DYNAMIC(GOT) | 72 | .word _DYNAMIC(GOT) | |
74 | 73 | |||
75 | .align 0 | 74 | .align 0 | |
76 | .globl _rtld_bind_start | 75 | .globl _rtld_bind_start | |
77 | .type _rtld_bind_start,%function | 76 | .type _rtld_bind_start,%function | |
78 | /* | 77 | /* | |
79 | * stack[0] = RA | 78 | * stack[0] = RA | |
80 | * ip = &GOT[n+3] | 79 | * ip = &GOT[n+3] | |
81 | * lr = &GOT[2] | 80 | * lr = &GOT[2] | |
82 | */ | 81 | */ | |
83 | _rtld_bind_start: | 82 | _rtld_bind_start: | |
84 | stmdb sp!,{r0-r4,sl,fp} | 83 | stmdb sp!,{r0-r4,sl,fp} /* 8 byte aligned (lr already saved) */ | |
85 | 84 | |||
86 | sub r1, ip, lr /* r1 = 4 * (n + 1) */ | 85 | sub r1, ip, lr /* r1 = 4 * (n + 1) */ | |
87 | sub r1, r1, #4 /* r1 = 4 * n */ | 86 | sub r1, r1, #4 /* r1 = 4 * n */ | |
88 | add r1, r1, r1 /* r1 = 8 * n */ | 87 | add r1, r1, r1 /* r1 = 8 * n */ | |
89 | 88 | |||
90 | ldr r0, [lr, #-4] /* get obj ptr from GOT[1] */ | 89 | ldr r0, [lr, #-4] /* get obj ptr from GOT[1] */ | |
91 | mov r4, ip /* save GOT location */ | 90 | mov r4, ip /* save GOT location */ | |
92 | 91 | |||
93 | bl _rtld_bind /* Call the binder */ | 92 | bl _rtld_bind /* Call the binder */ | |
94 | 93 | |||
95 | str r0, [r4] /* save address in GOT */ | 94 | str r0, [r4] /* save address in GOT */ | |
96 | mov ip, r0 /* save new address */ | 95 | mov ip, r0 /* save new address */ | |
97 | 96 | |||
98 | ldmia sp!,{r0-r4,sl,fp,lr} /* restore the stack */ | 97 | ldmia sp!,{r0-r4,sl,fp,lr} /* restore the stack */ | |
99 | #ifdef _ARM_ARCH_4T | 98 | #ifdef _ARM_ARCH_4T | |
100 | bx ip /* jump to the new address */ | 99 | bx ip /* jump to the new address */ | |
101 | #else | 100 | #else | |
102 | mov pc, ip /* jump to the new address */ | 101 | mov pc, ip /* jump to the new address */ | |
103 | #endif | 102 | #endif | |
104 | 103 |