Commit | Line | Data |
---|---|---|
984263bc MD |
1 | /*- |
2 | * Copyright (c) 1998 John D. Polstra | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * | |
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
24 | * SUCH DAMAGE. | |
25 | * | |
fcf53d9b | 26 | * $FreeBSD: src/lib/libc/gen/dlfcn.c 217154 2011-01-08 17:13:43Z kib $ |
984263bc MD |
27 | */ |
28 | ||
e9de6dcc | 29 | #include <sys/mman.h> |
984263bc | 30 | #include <dlfcn.h> |
fcf53d9b | 31 | #include <link.h> |
984263bc | 32 | #include <stddef.h> |
e3b4bb34 | 33 | #include <string.h> |
f45ae2bf SW |
34 | #include "libc_private.h" |
35 | ||
6ba1d1f2 | 36 | struct dl_phdr_info build_phdr_info(void) __dso_hidden; |
f45ae2bf SW |
37 | void _rtld_thread_childfork(void); |
38 | void _rtld_thread_init(void *); | |
39 | void _rtld_thread_postfork(void); | |
40 | void _rtld_thread_prefork(void); | |
50caca1a | 41 | void _rtld_setthreaded(void); |
984263bc | 42 | |
f0a144b4 | 43 | extern char **environ; |
4ce464e1 | 44 | |
fcf53d9b | 45 | static char sorry[] = "Service unavailable"; |
984263bc MD |
46 | |
47 | /* | |
48 | * For ELF, the dynamic linker directly resolves references to its | |
49 | * services to functions inside the dynamic linker itself. These | |
50 | * weak-symbol stubs are necessary so that "ld" won't complain about | |
51 | * undefined symbols. The stubs are executed only when the program is | |
52 | * linked statically, or when a given service isn't implemented in the | |
53 | * dynamic linker. They must return an error if called, and they must | |
54 | * be weak symbols so that the dynamic linker can override them. | |
55 | */ | |
56 | ||
57 | #pragma weak _rtld_error | |
58 | void | |
4ce464e1 | 59 | _rtld_error(const char *fmt __unused, ...) |
984263bc MD |
60 | { |
61 | } | |
62 | ||
63 | #pragma weak dladdr | |
64 | int | |
4ce464e1 | 65 | dladdr(const void *addr __unused, Dl_info *dlip __unused) |
984263bc MD |
66 | { |
67 | _rtld_error(sorry); | |
68 | return 0; | |
69 | } | |
70 | ||
71 | #pragma weak dlclose | |
72 | int | |
4ce464e1 | 73 | dlclose(void *handle __unused) |
984263bc MD |
74 | { |
75 | _rtld_error(sorry); | |
76 | return -1; | |
77 | } | |
78 | ||
79 | #pragma weak dlerror | |
fcf53d9b | 80 | char * |
984263bc MD |
81 | dlerror(void) |
82 | { | |
83 | return sorry; | |
84 | } | |
85 | ||
984263bc MD |
86 | #pragma weak dlopen |
87 | void * | |
4ce464e1 | 88 | dlopen(const char *name __unused, int mode __unused) |
984263bc MD |
89 | { |
90 | _rtld_error(sorry); | |
91 | return NULL; | |
92 | } | |
93 | ||
94 | #pragma weak dlsym | |
95 | void * | |
4ce464e1 | 96 | dlsym(void *handle __unused, const char *name __unused) |
984263bc MD |
97 | { |
98 | _rtld_error(sorry); | |
99 | return NULL; | |
100 | } | |
101 | ||
fcf53d9b JM |
102 | #pragma weak dlfunc |
103 | dlfunc_t | |
104 | dlfunc(void * handle __unused, const char * name __unused) | |
105 | { | |
106 | _rtld_error(sorry); | |
107 | return NULL; | |
108 | } | |
109 | ||
110 | #pragma weak dlvsym | |
111 | void * | |
112 | dlvsym(void *handle __unused,const char *name __unused, | |
113 | const char *version __unused) | |
114 | { | |
115 | _rtld_error(sorry); | |
116 | return NULL; | |
117 | } | |
118 | ||
847f4e75 JM |
119 | #pragma weak _rtld_thread_init |
120 | void | |
5dcdf778 | 121 | _rtld_thread_init(void * li __unused) |
847f4e75 JM |
122 | { |
123 | _rtld_error(sorry); | |
124 | } | |
125 | ||
984263bc MD |
126 | #pragma weak dlinfo |
127 | int | |
4ce464e1 | 128 | dlinfo(void *handle __unused, int request __unused, void *p __unused) |
984263bc MD |
129 | { |
130 | _rtld_error(sorry); | |
3641b7ca | 131 | return 0; |
984263bc | 132 | } |
fcf53d9b | 133 | |
6ba1d1f2 | 134 | struct dl_phdr_info |
f0a144b4 JM |
135 | build_phdr_info(void) |
136 | { | |
137 | struct dl_phdr_info phdr_info; | |
138 | Elf_Addr *sp; | |
139 | Elf_Auxinfo *aux, *auxp; | |
f0a144b4 JM |
140 | unsigned int i; |
141 | ||
142 | sp = (Elf_Addr *) environ; | |
143 | while (*sp++ != 0) | |
144 | ; | |
145 | aux = (Elf_Auxinfo *) sp; | |
f0a144b4 JM |
146 | memset (&phdr_info, 0, sizeof(phdr_info)); |
147 | for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { | |
148 | switch (auxp->a_type) { | |
149 | case AT_BASE: | |
150 | phdr_info.dlpi_addr = (Elf_Addr) auxp->a_un.a_ptr; | |
151 | break; | |
f0a144b4 JM |
152 | case AT_EXECPATH: |
153 | phdr_info.dlpi_name = (const char *) auxp->a_un.a_ptr; | |
154 | break; | |
f0a144b4 JM |
155 | case AT_PHDR: |
156 | phdr_info.dlpi_phdr = (const Elf_Phdr *) auxp->a_un.a_ptr; | |
157 | break; | |
f0a144b4 JM |
158 | case AT_PHNUM: |
159 | phdr_info.dlpi_phnum = (Elf_Half) auxp->a_un.a_val; | |
160 | break; | |
161 | } | |
162 | } | |
163 | ||
164 | for (i = 0; i < phdr_info.dlpi_phnum; i++) | |
165 | if (phdr_info.dlpi_phdr[i].p_type == PT_TLS) { | |
166 | phdr_info.dlpi_tls_modid = 1; | |
167 | phdr_info.dlpi_tls_data = | |
752fcd15 | 168 | (void*)phdr_info.dlpi_phdr[i].p_vaddr; |
f0a144b4 JM |
169 | } |
170 | ||
171 | return (phdr_info); | |
172 | } | |
173 | ||
fcf53d9b JM |
174 | #pragma weak dl_iterate_phdr |
175 | int | |
176 | dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), | |
177 | void *data) | |
178 | { | |
e3b4bb34 | 179 | static int seen = 0; |
f0a144b4 JM |
180 | static struct dl_phdr_info phdr_info; |
181 | if (!seen) { | |
182 | seen = 1; | |
183 | phdr_info = build_phdr_info(); | |
184 | } | |
185 | ||
186 | return callback(&phdr_info, sizeof(phdr_info), data); | |
fcf53d9b JM |
187 | } |
188 | ||
d679f65e | 189 | #pragma weak fdlopen |
303c1887 | 190 | void * |
6d7019e6 | 191 | fdlopen(int fd __unused, int mode __unused) |
303c1887 | 192 | { |
752fcd15 JM |
193 | _rtld_error(sorry); |
194 | return NULL; | |
303c1887 JM |
195 | } |
196 | ||
fcf53d9b JM |
197 | #pragma weak _rtld_addr_phdr |
198 | int | |
6d7019e6 SW |
199 | _rtld_addr_phdr(const void *addr __unused, |
200 | struct dl_phdr_info *phdr_info __unused) | |
fcf53d9b JM |
201 | { |
202 | ||
203 | return (0); | |
204 | } | |
205 | ||
e9de6dcc JM |
206 | #pragma weak _rtld_get_stack_prot |
207 | int | |
208 | _rtld_get_stack_prot(void) | |
209 | { | |
210 | return (PROT_EXEC | PROT_READ | PROT_WRITE); | |
211 | } | |
f53c59ab MD |
212 | |
213 | #pragma weak _rtld_thread_prefork | |
214 | void | |
215 | _rtld_thread_prefork(void) | |
216 | { | |
217 | } | |
218 | ||
219 | #pragma weak _rtld_thread_postfork | |
220 | void | |
221 | _rtld_thread_postfork(void) | |
222 | { | |
223 | } | |
224 | ||
225 | #pragma weak _rtld_thread_childfork | |
226 | void | |
227 | _rtld_thread_childfork(void) | |
228 | { | |
229 | } | |
50caca1a MD |
230 | |
231 | #pragma weak _rtld_setthreaded | |
50caca1a MD |
232 | void |
233 | _rtld_setthreaded(void) | |
234 | { | |
235 | } |