dlfcn.c revision 276908
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 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/10/lib/libc/gen/dlfcn.c 276908 2015-01-10 09:22:17Z kib $");
29
30/*
31 * Linkage to services provided by the dynamic linker.
32 */
33#include <sys/mman.h>
34#include <dlfcn.h>
35#include <link.h>
36#include <stddef.h>
37#include "namespace.h"
38#include <pthread.h>
39#include "un-namespace.h"
40#include "libc_private.h"
41
42static char sorry[] = "Service unavailable";
43
44/*
45 * For ELF, the dynamic linker directly resolves references to its
46 * services to functions inside the dynamic linker itself.  These
47 * weak-symbol stubs are necessary so that "ld" won't complain about
48 * undefined symbols.  The stubs are executed only when the program is
49 * linked statically, or when a given service isn't implemented in the
50 * dynamic linker.  They must return an error if called, and they must
51 * be weak symbols so that the dynamic linker can override them.
52 */
53
54#pragma weak _rtld_error
55void
56_rtld_error(const char *fmt, ...)
57{
58}
59
60#pragma weak dladdr
61int
62dladdr(const void *addr, Dl_info *dlip)
63{
64	_rtld_error(sorry);
65	return 0;
66}
67
68#pragma weak dlclose
69int
70dlclose(void *handle)
71{
72	_rtld_error(sorry);
73	return -1;
74}
75
76#pragma weak dlerror
77char *
78dlerror(void)
79{
80	return sorry;
81}
82
83#pragma weak dllockinit
84void
85dllockinit(void *context,
86	   void *(*lock_create)(void *context),
87	   void (*rlock_acquire)(void *lock),
88	   void (*wlock_acquire)(void *lock),
89	   void (*lock_release)(void *lock),
90	   void (*lock_destroy)(void *lock),
91	   void (*context_destroy)(void *context))
92{
93	if (context_destroy != NULL)
94		context_destroy(context);
95}
96
97#pragma weak dlopen
98void *
99dlopen(const char *name, int mode)
100{
101	_rtld_error(sorry);
102	return NULL;
103}
104
105#pragma weak dlsym
106void *
107dlsym(void * __restrict handle, const char * __restrict name)
108{
109	_rtld_error(sorry);
110	return NULL;
111}
112
113#pragma weak dlfunc
114dlfunc_t
115dlfunc(void * __restrict handle, const char * __restrict name)
116{
117	_rtld_error(sorry);
118	return NULL;
119}
120
121#pragma weak dlvsym
122void *
123dlvsym(void * __restrict handle, const char * __restrict name,
124    const char * __restrict version)
125{
126	_rtld_error(sorry);
127	return NULL;
128}
129
130#pragma weak dlinfo
131int
132dlinfo(void * __restrict handle, int request, void * __restrict p)
133{
134	_rtld_error(sorry);
135	return 0;
136}
137
138#pragma weak _rtld_thread_init
139void
140_rtld_thread_init(void * li)
141{
142	_rtld_error(sorry);
143}
144
145static pthread_once_t dl_phdr_info_once = PTHREAD_ONCE_INIT;
146static struct dl_phdr_info phdr_info;
147
148static void
149dl_init_phdr_info(void)
150{
151	Elf_Auxinfo *auxp;
152	size_t phent;
153	unsigned int i;
154
155	phent = 0;
156	for (auxp = __elf_aux_vector; auxp->a_type != AT_NULL; auxp++) {
157		switch (auxp->a_type) {
158		case AT_BASE:
159			phdr_info.dlpi_addr = (Elf_Addr)auxp->a_un.a_ptr;
160			break;
161		case AT_EXECPATH:
162			phdr_info.dlpi_name = (const char *)auxp->a_un.a_ptr;
163			break;
164		case AT_PHDR:
165			phdr_info.dlpi_phdr =
166			    (const Elf_Phdr *)auxp->a_un.a_ptr;
167			break;
168		case AT_PHENT:
169			phent = auxp->a_un.a_val;
170			break;
171		case AT_PHNUM:
172			phdr_info.dlpi_phnum = (Elf_Half)auxp->a_un.a_val;
173			break;
174		}
175	}
176	for (i = 0; i < phdr_info.dlpi_phnum; i++) {
177		if (phdr_info.dlpi_phdr[i].p_type == PT_TLS) {
178			phdr_info.dlpi_tls_modid = 1;
179			phdr_info.dlpi_tls_data =
180			    (void*)phdr_info.dlpi_phdr[i].p_vaddr;
181		}
182	}
183	phdr_info.dlpi_adds = 1;
184}
185
186#pragma weak dl_iterate_phdr
187int
188dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
189    void *data)
190{
191
192	__init_elf_aux_vector();
193	if (__elf_aux_vector == NULL)
194		return (1);
195	_once(&dl_phdr_info_once, dl_init_phdr_info);
196	return (callback(&phdr_info, sizeof(phdr_info), data));
197}
198
199#pragma weak fdlopen
200void *
201fdlopen(int fd, int mode)
202{
203
204	_rtld_error(sorry);
205	return NULL;
206}
207
208#pragma weak _rtld_atfork_pre
209void
210_rtld_atfork_pre(int *locks)
211{
212}
213
214#pragma weak _rtld_atfork_post
215void
216_rtld_atfork_post(int *locks)
217{
218}
219
220#pragma weak _rtld_addr_phdr
221int
222_rtld_addr_phdr(const void *addr, struct dl_phdr_info *phdr_info)
223{
224
225	return (0);
226}
227
228#pragma weak _rtld_get_stack_prot
229int
230_rtld_get_stack_prot(void)
231{
232
233	return (PROT_EXEC | PROT_READ | PROT_WRITE);
234}
235
236#pragma weak _rtld_is_dlopened
237int
238_rtld_is_dlopened(void *arg)
239{
240
241	return (0);
242}
243