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$");
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	unsigned int i;
153
154	for (auxp = __elf_aux_vector; auxp->a_type != AT_NULL; auxp++) {
155		switch (auxp->a_type) {
156		case AT_BASE:
157			phdr_info.dlpi_addr = (Elf_Addr)auxp->a_un.a_ptr;
158			break;
159		case AT_EXECPATH:
160			phdr_info.dlpi_name = (const char *)auxp->a_un.a_ptr;
161			break;
162		case AT_PHDR:
163			phdr_info.dlpi_phdr =
164			    (const Elf_Phdr *)auxp->a_un.a_ptr;
165			break;
166		case AT_PHNUM:
167			phdr_info.dlpi_phnum = (Elf_Half)auxp->a_un.a_val;
168			break;
169		}
170	}
171	for (i = 0; i < phdr_info.dlpi_phnum; i++) {
172		if (phdr_info.dlpi_phdr[i].p_type == PT_TLS) {
173			phdr_info.dlpi_tls_modid = 1;
174			phdr_info.dlpi_tls_data =
175			    (void*)phdr_info.dlpi_phdr[i].p_vaddr;
176		}
177	}
178	phdr_info.dlpi_adds = 1;
179}
180
181#pragma weak dl_iterate_phdr
182int
183dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
184    void *data)
185{
186
187	__init_elf_aux_vector();
188	if (__elf_aux_vector == NULL)
189		return (1);
190	_once(&dl_phdr_info_once, dl_init_phdr_info);
191	return (callback(&phdr_info, sizeof(phdr_info), data));
192}
193
194#pragma weak fdlopen
195void *
196fdlopen(int fd, int mode)
197{
198
199	_rtld_error(sorry);
200	return NULL;
201}
202
203#pragma weak _rtld_atfork_pre
204void
205_rtld_atfork_pre(int *locks)
206{
207}
208
209#pragma weak _rtld_atfork_post
210void
211_rtld_atfork_post(int *locks)
212{
213}
214
215#pragma weak _rtld_addr_phdr
216int
217_rtld_addr_phdr(const void *addr, struct dl_phdr_info *phdr_info)
218{
219
220	return (0);
221}
222
223#pragma weak _rtld_get_stack_prot
224int
225_rtld_get_stack_prot(void)
226{
227
228	return (PROT_EXEC | PROT_READ | PROT_WRITE);
229}
230
231#pragma weak _rtld_is_dlopened
232int
233_rtld_is_dlopened(void *arg)
234{
235
236	return (0);
237}
238