Tue Jan 22 21:47:29 2013 UTC ()
Pullup from HEAD:
Add .init_array/.fini_array support (conditionalized on HAVE_INITFINI_ARRAY).


(matt)
diff -r1.110 -r1.110.6.1 src/libexec/ld.elf_so/Makefile
diff -r1.41.4.1 -r1.41.4.1.2.1 src/libexec/ld.elf_so/headers.c
diff -r1.155 -r1.155.4.1 src/libexec/ld.elf_so/rtld.c
diff -r1.107 -r1.107.4.1 src/libexec/ld.elf_so/rtld.h
diff -r1.59 -r1.59.4.1 src/libexec/ld.elf_so/symbol.c
diff -r1.11 -r1.11.46.1 src/libexec/ld.elf_so/arch/arm/Makefile.inc
diff -r1.10 -r1.10.10.1 src/libexec/ld.elf_so/arch/arm/rtld_start.S

cvs diff -r1.110 -r1.110.6.1 src/libexec/ld.elf_so/Makefile (switch to unified diff)

--- 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
6WARNS?=4 6WARNS?=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
14PIE_CFLAGS= 14PIE_CFLAGS=
15PIE_LDFLAGS= 15PIE_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})
21ARCHSUBDIR= ${LDELFSO_MACHINE_CPU} 21ARCHSUBDIR= ${LDELFSO_MACHINE_CPU}
22.else 22.else
23ARCHSUBDIR= ${MACHINE_CPU} 23ARCHSUBDIR= ${MACHINE_CPU}
24.endif 24.endif
25M= ${.CURDIR}/arch/${ARCHSUBDIR} 25M= ${.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
41LDFLAGS+= ${${ACTIVE_CC} == "clang":? -Wl,-Bsymbolic : -symbolic} \ 41LDFLAGS+= ${${ACTIVE_CC} == "clang":? -Wl,-Bsymbolic : -symbolic} \
42 -shared -nostartfiles -nodefaultlibs 42 -shared -nostartfiles -nodefaultlibs
43LDFLAGS+= -Wl,-static 43LDFLAGS+= -Wl,-static
44LDFLAGS+= -Wl,--warn-shared-textrel 44LDFLAGS+= -Wl,--warn-shared-textrel
45 45
46CFLAGS+= -fvisibility=hidden 46COPTS+= -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)
56PROG= ld.elf_so-${MLIBDIR} 56PROG= ld.elf_so-${MLIBDIR}
57CPPFLAGS+= -DRTLD_ARCH_SUBDIR=\"${MLIBDIR}\" 57CPPFLAGS+= -DRTLD_ARCH_SUBDIR=\"${MLIBDIR}\"
58.else 58.else
59PROG= ld.elf_so 59PROG= ld.elf_so
60.endif 60.endif
61 61
62CLIBOBJ!= cd ${NETBSDSRCDIR}/lib/libc && ${PRINTOBJDIR} 62CLIBOBJ!= cd ${NETBSDSRCDIR}/lib/libc && ${PRINTOBJDIR}
63 63
64SRCS+= rtld.c reloc.c symbol.c xmalloc.c xprintf.c debug.c \ 64SRCS+= 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
70SRCS+= stack_protector.c 70SRCS+= stack_protector.c
71.endif 71.endif
72 72
73.PATH.c: ${NETBSDSRCDIR}/lib/libc/stdlib 73.PATH.c: ${NETBSDSRCDIR}/lib/libc/stdlib
74SRCS+= exit.c 74SRCS+= exit.c
75 75
76errlist_concat.h: ${NETBSDSRCDIR}/lib/libc/gen/errlist.awk ${NETBSDSRCDIR}/sys/sys/errno.h 76errlist_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
80xprintf.c: errlist_concat.h 80xprintf.c: errlist_concat.h
81 81
82CLEANFILES+= errlist_concat.h 82CLEANFILES+= errlist_concat.h
83 83
84BINDIR= ${SHLINKINSTALLDIR} 84BINDIR= ${SHLINKINSTALLDIR}
85 85
86CPPFLAGS+= -DLIBDIR=\"${LIBDIR}\" -D_PATH_RTLD=\"${BINDIR}/${PROG}\" 86CPPFLAGS+= -DLIBDIR=\"${LIBDIR}\" -D_PATH_RTLD=\"${BINDIR}/${PROG}\"
87CPPFLAGS+= -I${.CURDIR} -I. 87CPPFLAGS+= -I${.CURDIR} -I.
88CPPFLAGS+= -DRTLD_LOADER 88CPPFLAGS+= -DRTLD_LOADER
89CPPFLAGS+= -D_RTLD_SOURCE 89CPPFLAGS+= -D_RTLD_SOURCE
90CPPFLAGS+= -DCOMBRELOC 90CPPFLAGS+= -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
95DBG= -O3 -fomit-frame-pointer 95COPTS= -O3 -fomit-frame-pointer
96 96
97.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "x86_64" 97.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "x86_64"
98DBG+= -mno-3dnow -mno-mmx -mno-sse -mno-sse2 -mno-sse3 98COPTS+= -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}
103CPPFLAGS+= -DRTLD_DEFAULT_LIBRARY_PATH=\"${SHLIBDIR}:${LIBDIR}\" 103CPPFLAGS+= -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.
107COPTS.rtld.c+= -Wno-stack-protector 107COPTS.rtld.c+= -Wno-stack-protector
108COPTS.symbol.c+=-Wno-stack-protector 108COPTS.symbol.c+=-Wno-stack-protector
109 109
110LDADD+= -L${CLIBOBJ} -L${DESTDIR}${LIBDIR} 110LDADD+= -L${CLIBOBJ} -L${DESTDIR}${LIBDIR}
111.if ${MKPICLIB} != "no" 111.if ${MKPICLIB} != "no"
112LDADD+= -lc_pic 112LDADD+= -lc_pic
113.if ${MKPICINSTALL} != "no" 113.if ${MKPICINSTALL} != "no"
114DPADD+= ${LIBC_PIC} 114DPADD+= ${LIBC_PIC}
115.endif 115.endif
116DPADD+= ${CLIBOBJ}/libc_pic.a 116DPADD+= ${CLIBOBJ}/libc_pic.a
117.else 117.else
118LDADD+= -lc 118LDADD+= -lc
119DPADD+= ${CLIBOBJ}/libc.a 119DPADD+= ${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)
124LDADD+= -lgcc 124LDADD+= -lgcc
125DPADD+= ${LIBGCC} 125DPADD+= ${LIBGCC}
126.endif 126.endif
127 127
128STRIPFLAG= 128STRIPFLAG=
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"
137SYMLINKS+= ${SHLINKINSTALLDIR}/${PROG} /usr/libexec/${PROG} 137SYMLINKS+= ${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
143MAN= ld.elf_so.1 143MAN= ld.elf_so.1
144 144
145.include <bsd.man.mk> 145.include <bsd.man.mk>
146.endif 146.endif

cvs diff -r1.41.4.1 -r1.41.4.1.2.1 src/libexec/ld.elf_so/headers.c (switch to unified diff)

--- 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 */
66void 66void
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 */
337Obj_Entry * 359Obj_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}

cvs diff -r1.155 -r1.155.4.1 src/libexec/ld.elf_so/rtld.c (switch to unified diff)

--- 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 */
73static void _rtld_init(caddr_t, caddr_t, const char *); 73static void _rtld_init(caddr_t, caddr_t, const char *);
74static void _rtld_exit(void); 74static void _rtld_exit(void);
75 75
76Elf_Addr _rtld(Elf_Addr *, Elf_Addr); 76Elf_Addr _rtld(Elf_Addr *, Elf_Addr);
77 77
78 78
79/* 79/*
80 * Data declarations. 80 * Data declarations.
81 */ 81 */
82static char *error_message; /* Message for dlopen(), or NULL */ 82static char *error_message; /* Message for dlopen(), or NULL */
83 83
84struct r_debug _rtld_debug; /* for GDB; */ 84struct r_debug _rtld_debug; /* for GDB; */
85bool _rtld_trust; /* False for setuid and setgid programs */ 85bool _rtld_trust; /* False for setuid and setgid programs */
86Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */ 86Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */
87Obj_Entry **_rtld_objtail; /* Link field of last object in list */ 87Obj_Entry **_rtld_objtail; /* Link field of last object in list */
88Obj_Entry *_rtld_objmain; /* The main program shared object */ 88Obj_Entry *_rtld_objmain; /* The main program shared object */
89Obj_Entry _rtld_objself; /* The dynamic linker shared object */ 89Obj_Entry _rtld_objself; /* The dynamic linker shared object */
90u_int _rtld_objcount; /* Number of objects in _rtld_objlist */ 90u_int _rtld_objcount; /* Number of objects in _rtld_objlist */
91u_int _rtld_objloads; /* Number of objects loaded in _rtld_objlist */ 91u_int _rtld_objloads; /* Number of objects loaded in _rtld_objlist */
92u_int _rtld_objgen; /* Generation count for _rtld_objlist */ 92u_int _rtld_objgen; /* Generation count for _rtld_objlist */
93const char _rtld_path[] = _PATH_RTLD; 93const 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. */
96Elf_Sym _rtld_sym_zero = { 96Elf_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};
100size_t _rtld_pagesz; /* Page size, as provided by kernel */ 100size_t _rtld_pagesz; /* Page size, as provided by kernel */
101 101
102Search_Path *_rtld_default_paths; 102Search_Path *_rtld_default_paths;
103Search_Path *_rtld_paths; 103Search_Path *_rtld_paths;
104 104
105Library_Xform *_rtld_xforms; 105Library_Xform *_rtld_xforms;
106 106
107/* 107/*
108 * Global declarations normally provided by crt0. 108 * Global declarations normally provided by crt0.
109 */ 109 */
110char *__progname; 110char *__progname;
111char **environ; 111char **environ;
112 112
113static volatile bool _rtld_mutex_may_recurse; 113static volatile bool _rtld_mutex_may_recurse;
114 114
115#if defined(RTLD_DEBUG) 115#if defined(RTLD_DEBUG)
116#ifndef __sh__ 116#ifndef __sh__
117extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; 117extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
118#else /* 32-bit SuperH */ 118#else /* 32-bit SuperH */
119register Elf_Addr *_GLOBAL_OFFSET_TABLE_ asm("r12"); 119register Elf_Addr *_GLOBAL_OFFSET_TABLE_ asm("r12");
120#endif 120#endif
121#endif /* RTLD_DEBUG */ 121#endif /* RTLD_DEBUG */
122extern Elf_Dyn _DYNAMIC; 122extern Elf_Dyn _DYNAMIC;
123 123
124static void _rtld_call_fini_functions(sigset_t *, int); 124static void _rtld_call_fini_functions(sigset_t *, int);
125static void _rtld_call_init_functions(sigset_t *); 125static void _rtld_call_init_functions(sigset_t *);
126static void _rtld_initlist_visit(Objlist *, Obj_Entry *, int); 126static void _rtld_initlist_visit(Objlist *, Obj_Entry *, int);
127static void _rtld_initlist_tsort(Objlist *, int); 127static void _rtld_initlist_tsort(Objlist *, int);
128static Obj_Entry *_rtld_dlcheck(void *); 128static Obj_Entry *_rtld_dlcheck(void *);
129static void _rtld_init_dag(Obj_Entry *); 129static void _rtld_init_dag(Obj_Entry *);
130static void _rtld_init_dag1(Obj_Entry *, Obj_Entry *); 130static void _rtld_init_dag1(Obj_Entry *, Obj_Entry *);
131static void _rtld_objlist_remove(Objlist *, Obj_Entry *); 131static void _rtld_objlist_remove(Objlist *, Obj_Entry *);
132static void _rtld_objlist_clear(Objlist *); 132static void _rtld_objlist_clear(Objlist *);
133static void _rtld_unload_object(sigset_t *, Obj_Entry *, bool); 133static void _rtld_unload_object(sigset_t *, Obj_Entry *, bool);
134static void _rtld_unref_dag(Obj_Entry *); 134static void _rtld_unref_dag(Obj_Entry *);
135static Obj_Entry *_rtld_obj_from_addr(const void *); 135static Obj_Entry *_rtld_obj_from_addr(const void *);
136 136
 137static 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
 145static 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
137static void 176static 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
148restart: 185restart:
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
208static void 229static 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
 261static 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
219restart: 270restart:
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 */
274static void 308static 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 */
338static void 372static 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 */
366Elf_Addr 400Elf_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
718void 752void
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
728static Obj_Entry * 762static 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
744static void 778static 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
768static void 802static 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
784static void 818static 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
791static void 825static 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 */
812static void 846static 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
856void 890void
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
874static void 908static 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)
897int 931int
898dlclose(void *handle) 932dlclose(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)
929char * 963char *
930dlerror(void) 964dlerror(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)
939void * 973void *
940dlopen(const char *name, int mode) 974dlopen(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 */
1013void * 1047void *
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__
1034static void * 1068static void *
1035hackish_return_address(void) 1069hackish_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
1049static void * 1083static void *
1050do_dlsym(void *handle, const char *name, const Ver_Entry *ventry, void *retaddr) 1084do_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)
1159void * 1193void *
1160dlsym(void *handle, const char *name) 1194dlsym(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)
1175void * 1209void *
1176dlvsym(void *handle, const char *name, const char *version) 1210dlvsym(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)
1200int 1234int
1201dladdr(const void *addr, Dl_info *info) 1235dladdr(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;

cvs diff -r1.107 -r1.107.4.1 src/libexec/ld.elf_so/rtld.h (switch to unified diff)

--- 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
56extern size_t _rtld_pagesz; 56extern 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 */
81struct Struct_Obj_Entry; 81struct Struct_Obj_Entry;
82 82
83typedef struct Struct_Objlist_Entry { 83typedef 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
88typedef SIMPLEQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist; 88typedef SIMPLEQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist;
89 89
90typedef struct Struct_Name_Entry { 90typedef 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
95typedef struct Struct_Needed_Entry { 95typedef 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
101typedef struct _rtld_search_path_t { 101typedef 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
107typedef struct Struct_Ver_Entry { 107typedef 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
121typedef struct _rtld_library_xform_t { 120typedef 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
 143typedef void (*fptr_t)(void);
 144
144typedef struct Struct_Obj_Entry { 145typedef 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
282typedef struct Struct_DoneList { 289typedef 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
291extern struct r_debug _rtld_debug; 298extern struct r_debug _rtld_debug;
292extern Search_Path *_rtld_default_paths; 299extern Search_Path *_rtld_default_paths;
293extern Obj_Entry *_rtld_objlist; 300extern Obj_Entry *_rtld_objlist;
294extern Obj_Entry **_rtld_objtail; 301extern Obj_Entry **_rtld_objtail;
295extern u_int _rtld_objcount; 302extern u_int _rtld_objcount;
296extern u_int _rtld_objloads; 303extern u_int _rtld_objloads;
297extern Obj_Entry *_rtld_objmain; 304extern Obj_Entry *_rtld_objmain;
298extern Obj_Entry _rtld_objself; 305extern Obj_Entry _rtld_objself;
299extern Search_Path *_rtld_paths; 306extern Search_Path *_rtld_paths;
300extern Library_Xform *_rtld_xforms; 307extern Library_Xform *_rtld_xforms;
301extern bool _rtld_trust; 308extern bool _rtld_trust;
302extern Objlist _rtld_list_global; 309extern Objlist _rtld_list_global;
303extern Objlist _rtld_list_main; 310extern Objlist _rtld_list_main;
304extern Elf_Sym _rtld_sym_zero; 311extern 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 */
335void _rtld_error(const char *, ...) 342void _rtld_error(const char *, ...)
336 __attribute__((__format__(__printf__,1,2))); 343 __attribute__((__format__(__printf__,1,2)));
337void _rtld_die(void) __attribute__((__noreturn__)); 344void _rtld_die(void) __attribute__((__noreturn__));
338void *_rtld_objmain_sym(const char *); 345void *_rtld_objmain_sym(const char *);
339__dso_public void _rtld_debug_state(void); 346__dso_public void _rtld_debug_state(void);
340void _rtld_linkmap_add(Obj_Entry *); 347void _rtld_linkmap_add(Obj_Entry *);
341void _rtld_linkmap_delete(Obj_Entry *); 348void _rtld_linkmap_delete(Obj_Entry *);
342void _rtld_objlist_push_head(Objlist *, Obj_Entry *); 349void _rtld_objlist_push_head(Objlist *, Obj_Entry *);
343void _rtld_objlist_push_tail(Objlist *, Obj_Entry *); 350void _rtld_objlist_push_tail(Objlist *, Obj_Entry *);
344Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *); 351Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *);
345void _rtld_ref_dag(Obj_Entry *); 352void _rtld_ref_dag(Obj_Entry *);
346 353
347void _rtld_shared_enter(void); 354void _rtld_shared_enter(void);
348void _rtld_shared_exit(void); 355void _rtld_shared_exit(void);
349void _rtld_exclusive_enter(sigset_t *); 356void _rtld_exclusive_enter(sigset_t *);
350void _rtld_exclusive_exit(sigset_t *); 357void _rtld_exclusive_exit(sigset_t *);
351 358
352/* expand.c */ 359/* expand.c */
353size_t _rtld_expand_path(char *, size_t, const char *, const char *,\ 360size_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 */
357void _rtld_digest_dynamic(const char *, Obj_Entry *); 364void _rtld_digest_dynamic(const char *, Obj_Entry *);
358Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t); 365Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t);
359 366
360/* load.c */ 367/* load.c */
361Obj_Entry *_rtld_load_object(const char *, int); 368Obj_Entry *_rtld_load_object(const char *, int);
362int _rtld_load_needed_objects(Obj_Entry *, int); 369int _rtld_load_needed_objects(Obj_Entry *, int);
363int _rtld_preload(const char *); 370int _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 */
367void _rtld_add_paths(const char *, Search_Path **, const char *); 374void _rtld_add_paths(const char *, Search_Path **, const char *);
368void _rtld_process_hints(const char *, Search_Path **, Library_Xform **, 375void _rtld_process_hints(const char *, Search_Path **, Library_Xform **,
369 const char *); 376 const char *);
370int _rtld_sysctl(const char *, void *, size_t *); 377int _rtld_sysctl(const char *, void *, size_t *);
371 378
372/* reloc.c */ 379/* reloc.c */
373int _rtld_do_copy_relocations(const Obj_Entry *); 380int _rtld_do_copy_relocations(const Obj_Entry *);
374int _rtld_relocate_objects(Obj_Entry *, bool); 381int _rtld_relocate_objects(Obj_Entry *, bool);
375int _rtld_relocate_nonplt_objects(Obj_Entry *); 382int _rtld_relocate_nonplt_objects(Obj_Entry *);
376int _rtld_relocate_plt_lazy(const Obj_Entry *); 383int _rtld_relocate_plt_lazy(const Obj_Entry *);
377int _rtld_relocate_plt_objects(const Obj_Entry *); 384int _rtld_relocate_plt_objects(const Obj_Entry *);
378void _rtld_setup_pltgot(const Obj_Entry *); 385void _rtld_setup_pltgot(const Obj_Entry *);
379 386
380/* search.c */ 387/* search.c */
381Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int); 388Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int);
382 389
383/* symbol.c */ 390/* symbol.c */
384unsigned long _rtld_elf_hash(const char *); 391unsigned long _rtld_elf_hash(const char *);
385const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long, 392const 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 *);
387const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *, 394const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *,
388 const Obj_Entry **, u_int); 395 const Obj_Entry **, u_int);
389const Elf_Sym *_rtld_find_plt_symdef(unsigned long, const Obj_Entry *,  396const Elf_Sym *_rtld_find_plt_symdef(unsigned long, const Obj_Entry *,
390 const Obj_Entry **, bool); 397 const Obj_Entry **, bool);
391 398
392const Elf_Sym *_rtld_symlook_list(const char *, unsigned long, 399const 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 *);
394const Elf_Sym *_rtld_symlook_default(const char *, unsigned long, 401const 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 *);
396const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long, 403const 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
400void _rtld_combreloc_reset(const Obj_Entry *); 407void _rtld_combreloc_reset(const Obj_Entry *);
401#endif 408#endif
402 409
403/* symver.c */ 410/* symver.c */
404int _rtld_object_match_name(const Obj_Entry *, const char *); 411int _rtld_object_match_name(const Obj_Entry *, const char *);
405int _rtld_verify_object_versions(Obj_Entry *); 412int _rtld_verify_object_versions(Obj_Entry *);
406 413
407static __inline const Ver_Entry * 414static __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 */
426void *_rtld_tls_get_addr(void *, size_t, size_t); 433void *_rtld_tls_get_addr(void *, size_t, size_t);
427void _rtld_tls_initial_allocation(void); 434void _rtld_tls_initial_allocation(void);
428void *_rtld_tls_module_allocate(size_t index); 435void *_rtld_tls_module_allocate(size_t index);
429int _rtld_tls_offset_allocate(Obj_Entry *); 436int _rtld_tls_offset_allocate(Obj_Entry *);
430void _rtld_tls_offset_free(Obj_Entry *); 437void _rtld_tls_offset_free(Obj_Entry *);
431 438
432extern size_t _rtld_tls_dtv_generation; 439extern size_t _rtld_tls_dtv_generation;
433extern size_t _rtld_tls_max_index; 440extern 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 */
443struct stat; 450struct stat;
444Obj_Entry *_rtld_map_object(const char *, int, const struct stat *); 451Obj_Entry *_rtld_map_object(const char *, int, const struct stat *);
445void _rtld_obj_free(Obj_Entry *); 452void _rtld_obj_free(Obj_Entry *);
446Obj_Entry *_rtld_obj_new(void); 453Obj_Entry *_rtld_obj_new(void);
447 454
448/* function descriptors */ 455/* function descriptors */
449#ifdef __HAVE_FUNCTION_DESCRIPTORS 456#ifdef __HAVE_FUNCTION_DESCRIPTORS
450Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *,  457Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *,
451 const Elf_Sym *, Elf_Addr); 458 const Elf_Sym *, Elf_Addr);
452const void *_rtld_function_descriptor_function(const void *); 459const 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 */

cvs diff -r1.59 -r1.59.4.1 src/libexec/ld.elf_so/symbol.c (switch to unified diff)

--- 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
62typedef 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 */
68static bool 66static 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
85static bool 83static 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 */
122unsigned long 120unsigned 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
141const Elf_Sym * 139const 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 */
179const Elf_Sym * 177const 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 */
239const Elf_Sym * 237const 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
362static const Obj_Entry *_rtld_last_refobj; 360static 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 */
368void 366void
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 */
382const Elf_Sym * 380const 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
468const Elf_Sym * 466const 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 */
498const Elf_Sym * 496const 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}

cvs diff -r1.11 -r1.11.46.1 src/libexec/ld.elf_so/arch/arm/Makefile.inc (switch to unified diff)

--- 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
3SRCS+= rtld_start.S mdreloc.c 3SRCS+= rtld_start.S mdreloc.c
4 4
5# XXX Should not be in CPPFLAGS! 5# XXX Should not be in CPPFLAGS!
6CPPFLAGS+= -fpic 6CPPFLAGS+= -fpic
7 7
8CPPFLAGS+= -DELFSIZE=32 8CPPFLAGS+= -DELFSIZE=32
 9.if ${MACHINE_ARCH} == "earm" || ${MACHINE_ARCH} == "earmeb"
 10CPPFLAGS+= -DHAVE_INITFINI_ARRAY
 11.endif
9 12
10LDFLAGS+= -Wl,-e,_rtld_start 13LDFLAGS+= -Wl,-e,_rtld_start

cvs diff -r1.10 -r1.10.10.1 src/libexec/ld.elf_so/arch/arm/rtld_start.S (switch to unified diff)

--- 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
34RCSID("$NetBSD: rtld_start.S,v 1.10 2009/11/11 14:15:41 skrll Exp $") 34RCSID("$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