dlfcn_elf.c revision 1.8 1 /* $NetBSD: dlfcn_elf.c,v 1.8 2011/03/07 05:09:11 joerg Exp $ */
2
3 /*
4 * Copyright (c) 2000 Takuya SHIOZAKI
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 #if defined(LIBC_SCCS) && !defined(lint)
30 __RCSID("$NetBSD: dlfcn_elf.c,v 1.8 2011/03/07 05:09:11 joerg Exp $");
31 #endif /* LIBC_SCCS and not lint */
32
33 #include "reentrant.h"
34 #include "namespace.h"
35 #include <elf.h>
36 #include <errno.h>
37 #include <string.h>
38
39 #undef dlopen
40 #undef dlclose
41 #undef dlsym
42 #undef dlerror
43 #undef dladdr
44 #undef dfinfo
45
46 #define dlopen ___dlopen
47 #define dlclose ___dlclose
48 #define dlsym ___dlsym
49 #define dlerror ___dlerror
50 #define dladdr ___dladdr
51 #define dlinfo ___dlinfo
52 #define dl_iterate_phdr ___dl_iterate_phdr
53
54 #define ELFSIZE ARCH_ELFSIZE
55 #include "rtld.h"
56
57 #ifdef __weak_alias
58 __weak_alias(dlopen,___dlopen)
59 __weak_alias(dlclose,___dlclose)
60 __weak_alias(dlsym,___dlsym)
61 __weak_alias(dlerror,___dlerror)
62 __weak_alias(dladdr,___dladdr)
63 __weak_alias(dlinfo,___dlinfo)
64 __weak_alias(dl_iterate_phdr,___dl_iterate_phdr)
65
66 __weak_alias(__dlopen,___dlopen)
67 __weak_alias(__dlclose,___dlclose)
68 __weak_alias(__dlsym,___dlsym)
69 __weak_alias(__dlerror,___dlerror)
70 __weak_alias(__dladdr,___dladdr)
71 __weak_alias(__dlinfo,___dlinfo)
72 __weak_alias(__dl_iterate_phdr,___dl_iterate_phdr)
73 #endif
74
75 /*
76 * For ELF, the dynamic linker directly resolves references to its
77 * services to functions inside the dynamic linker itself. These
78 * weak-symbol stubs are necessary so that "ld" won't complain about
79 * undefined symbols. The stubs are executed only when the program is
80 * linked statically, or when a given service isn't implemented in the
81 * dynamic linker. They must return an error if called, and they must
82 * be weak symbols so that the dynamic linker can override them.
83 */
84
85 static char dlfcn_error[] = "Service unavailable";
86
87 /*ARGSUSED*/
88 void *
89 dlopen(const char *name, int mode)
90 {
91
92 return NULL;
93 }
94
95 /*ARGSUSED*/
96 int
97 dlclose(void *fd)
98 {
99
100 return -1;
101 }
102
103 /*ARGSUSED*/
104 void *
105 dlsym(void *handle, const char *name)
106 {
107
108 return NULL;
109 }
110
111 /*ARGSUSED*/
112 __aconst char *
113 dlerror()
114 {
115
116 return dlfcn_error;
117 }
118
119 /*ARGSUSED*/
120 int
121 dladdr(const void *addr, Dl_info *dli)
122 {
123
124 return 0;
125 }
126
127 /*ARGSUSED*/
128 int
129 dlinfo(void *handle, int req, void *v)
130 {
131
132 return -1;
133 }
134
135 static once_t dl_iterate_phdr_once = ONCE_INITIALIZER;
136 static const char *dlpi_name;
137 static Elf_Addr dlpi_addr;
138 static const Elf_Phdr *dlpi_phdr;
139 static Elf_Half dlpi_phnum;
140
141 /*
142 * Declare as common symbol to allow new libc with older binaries to
143 * not trigger an undefined reference.
144 */
145 extern __dso_hidden void *__auxinfo;
146
147 static void
148 dl_iterate_phdr_setup(void)
149 {
150 const AuxInfo *aux;
151
152 if (__auxinfo == NULL)
153 return;
154
155 for (aux = __auxinfo; aux->a_type != AT_NULL; ++aux) {
156 switch (aux->a_type) {
157 case AT_BASE:
158 dlpi_addr = aux->a_v;
159 break;
160 case AT_PHDR:
161 dlpi_phdr = (void *)aux->a_v;
162 break;
163 case AT_PHNUM:
164 dlpi_phnum = aux->a_v;
165 break;
166 case AT_SUN_EXECNAME:
167 dlpi_name = (void *)aux->a_v;
168 break;
169 }
170 }
171 }
172
173 /*ARGSUSED*/
174 int
175 dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
176 void *data)
177 {
178 struct dl_phdr_info phdr_info;
179
180 if (__auxinfo == NULL)
181 return EOPNOTSUPP;
182
183 thr_once(&dl_iterate_phdr_once, dl_iterate_phdr_setup);
184
185 memset(&phdr_info, 0, sizeof(phdr_info));
186 phdr_info.dlpi_addr = dlpi_addr;
187 phdr_info.dlpi_phdr = dlpi_phdr;
188 phdr_info.dlpi_phnum = dlpi_phnum;
189 phdr_info.dlpi_name = dlpi_name;
190
191 return callback(&phdr_info, sizeof(phdr_info), data);
192 }
193