133180Sjdp/*-
233180Sjdp * Copyright (c) 1998 John D. Polstra
333180Sjdp * All rights reserved.
433180Sjdp *
533180Sjdp * Redistribution and use in source and binary forms, with or without
633180Sjdp * modification, are permitted provided that the following conditions
733180Sjdp * are met:
833180Sjdp * 1. Redistributions of source code must retain the above copyright
933180Sjdp *    notice, this list of conditions and the following disclaimer.
1033180Sjdp * 2. Redistributions in binary form must reproduce the above copyright
1133180Sjdp *    notice, this list of conditions and the following disclaimer in the
1233180Sjdp *    documentation and/or other materials provided with the distribution.
1333180Sjdp *
1433180Sjdp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1533180Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1633180Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1733180Sjdp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1833180Sjdp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1933180Sjdp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2033180Sjdp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2133180Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2233180Sjdp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2333180Sjdp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2433180Sjdp * SUCH DAMAGE.
2533180Sjdp */
2633180Sjdp
2790039Sobrien#include <sys/cdefs.h>
2890039Sobrien__FBSDID("$FreeBSD$");
2990039Sobrien
3033180Sjdp/*
31103436Speter * Linkage to services provided by the dynamic linker.
3233180Sjdp */
33217154Skib#include <sys/mman.h>
3434196Sjdp#include <dlfcn.h>
35168314Skan#include <link.h>
3634196Sjdp#include <stddef.h>
37232388Skib#include "namespace.h"
38232388Skib#include <pthread.h>
39232388Skib#include "un-namespace.h"
40232388Skib#include "libc_private.h"
4134196Sjdp
42205606Sgahrstatic char sorry[] = "Service unavailable";
4334196Sjdp
4434196Sjdp/*
4534196Sjdp * For ELF, the dynamic linker directly resolves references to its
4634196Sjdp * services to functions inside the dynamic linker itself.  These
4734196Sjdp * weak-symbol stubs are necessary so that "ld" won't complain about
4834196Sjdp * undefined symbols.  The stubs are executed only when the program is
4934196Sjdp * linked statically, or when a given service isn't implemented in the
5034196Sjdp * dynamic linker.  They must return an error if called, and they must
5134196Sjdp * be weak symbols so that the dynamic linker can override them.
5234196Sjdp */
5334196Sjdp
5434196Sjdp#pragma weak _rtld_error
5534196Sjdpvoid
5634196Sjdp_rtld_error(const char *fmt, ...)
5734196Sjdp{
5834196Sjdp}
5934196Sjdp
6034196Sjdp#pragma weak dladdr
6134196Sjdpint
6234196Sjdpdladdr(const void *addr, Dl_info *dlip)
6334196Sjdp{
6434196Sjdp	_rtld_error(sorry);
6534196Sjdp	return 0;
6634196Sjdp}
6734196Sjdp
6834196Sjdp#pragma weak dlclose
6934196Sjdpint
7034196Sjdpdlclose(void *handle)
7134196Sjdp{
7234196Sjdp	_rtld_error(sorry);
7334196Sjdp	return -1;
7434196Sjdp}
7534196Sjdp
7634196Sjdp#pragma weak dlerror
77205606Sgahrchar *
7834196Sjdpdlerror(void)
7934196Sjdp{
8034196Sjdp	return sorry;
8134196Sjdp}
8234196Sjdp
8355122Sjdp#pragma weak dllockinit
8455122Sjdpvoid
8555122Sjdpdllockinit(void *context,
8655122Sjdp	   void *(*lock_create)(void *context),
8755122Sjdp	   void (*rlock_acquire)(void *lock),
8855122Sjdp	   void (*wlock_acquire)(void *lock),
8955122Sjdp	   void (*lock_release)(void *lock),
9055122Sjdp	   void (*lock_destroy)(void *lock),
9155122Sjdp	   void (*context_destroy)(void *context))
9255122Sjdp{
9355122Sjdp	if (context_destroy != NULL)
9455122Sjdp		context_destroy(context);
9555122Sjdp}
9655122Sjdp
9734196Sjdp#pragma weak dlopen
9834196Sjdpvoid *
9934196Sjdpdlopen(const char *name, int mode)
10034196Sjdp{
10134196Sjdp	_rtld_error(sorry);
10234196Sjdp	return NULL;
10334196Sjdp}
10434196Sjdp
10534196Sjdp#pragma weak dlsym
10634196Sjdpvoid *
107103213Smikedlsym(void * __restrict handle, const char * __restrict name)
10834196Sjdp{
10934196Sjdp	_rtld_error(sorry);
11034196Sjdp	return NULL;
11134196Sjdp}
112110804Skan
113190673Skib#pragma weak dlfunc
114190673Skibdlfunc_t
115190673Skibdlfunc(void * __restrict handle, const char * __restrict name)
116190673Skib{
117190673Skib	_rtld_error(sorry);
118190673Skib	return NULL;
119190673Skib}
120190673Skib
121153515Skan#pragma weak dlvsym
122153515Skanvoid *
123153515Skandlvsym(void * __restrict handle, const char * __restrict name,
124153515Skan    const char * __restrict version)
125153515Skan{
126153515Skan	_rtld_error(sorry);
127153515Skan	return NULL;
128153515Skan}
129153515Skan
130110804Skan#pragma weak dlinfo
131110804Skanint
132110804Skandlinfo(void * __restrict handle, int request, void * __restrict p)
133110804Skan{
134110804Skan	_rtld_error(sorry);
135126643Smarkm	return 0;
136110804Skan}
137115401Skan
138115401Skan#pragma weak _rtld_thread_init
139115401Skanvoid
140115401Skan_rtld_thread_init(void * li)
141115401Skan{
142115401Skan	_rtld_error(sorry);
143115401Skan}
144168314Skan
145232388Skibstatic pthread_once_t dl_phdr_info_once = PTHREAD_ONCE_INIT;
146232388Skibstatic struct dl_phdr_info phdr_info;
147232388Skib
148232388Skibstatic void
149232388Skibdl_init_phdr_info(void)
150232388Skib{
151232388Skib	Elf_Auxinfo *auxp;
152232388Skib	size_t phent;
153232388Skib	unsigned int i;
154232388Skib
155232388Skib	phent = 0;
156232388Skib	for (auxp = __elf_aux_vector; auxp->a_type != AT_NULL; auxp++) {
157232388Skib		switch (auxp->a_type) {
158232388Skib		case AT_BASE:
159232388Skib			phdr_info.dlpi_addr = (Elf_Addr)auxp->a_un.a_ptr;
160232388Skib			break;
161232388Skib		case AT_EXECPATH:
162232388Skib			phdr_info.dlpi_name = (const char *)auxp->a_un.a_ptr;
163232388Skib			break;
164232388Skib		case AT_PHDR:
165232388Skib			phdr_info.dlpi_phdr =
166232388Skib			    (const Elf_Phdr *)auxp->a_un.a_ptr;
167232388Skib			break;
168232388Skib		case AT_PHENT:
169232388Skib			phent = auxp->a_un.a_val;
170232388Skib			break;
171232388Skib		case AT_PHNUM:
172232388Skib			phdr_info.dlpi_phnum = (Elf_Half)auxp->a_un.a_val;
173232388Skib			break;
174232388Skib		}
175232388Skib	}
176232388Skib	for (i = 0; i < phdr_info.dlpi_phnum; i++) {
177232388Skib		if (phdr_info.dlpi_phdr[i].p_type == PT_TLS) {
178232388Skib			phdr_info.dlpi_tls_modid = 1;
179232388Skib			phdr_info.dlpi_tls_data =
180232388Skib			    (void*)phdr_info.dlpi_phdr[i].p_vaddr;
181232388Skib		}
182232388Skib	}
183232388Skib	phdr_info.dlpi_adds = 1;
184232388Skib}
185232388Skib
186168314Skan#pragma weak dl_iterate_phdr
187168314Skanint
188168314Skandl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
189168314Skan    void *data)
190168314Skan{
191232388Skib
192232388Skib	__init_elf_aux_vector();
193232388Skib	if (__elf_aux_vector == NULL)
194232388Skib		return (1);
195232388Skib	_once(&dl_phdr_info_once, dl_init_phdr_info);
196232388Skib	return (callback(&phdr_info, sizeof(phdr_info), data));
197168314Skan}
198185369Skib
199230410Skib#pragma weak fdlopen
200230410Skibvoid *
201230410Skibfdlopen(int fd, int mode)
202230410Skib{
203230410Skib
204230410Skib	_rtld_error(sorry);
205230410Skib	return NULL;
206230410Skib}
207230410Skib
208185369Skib#pragma weak _rtld_atfork_pre
209185369Skibvoid
210185369Skib_rtld_atfork_pre(int *locks)
211185369Skib{
212185369Skib}
213185369Skib
214185369Skib#pragma weak _rtld_atfork_post
215185369Skibvoid
216185369Skib_rtld_atfork_post(int *locks)
217185369Skib{
218185369Skib}
219211705Skib
220211705Skib#pragma weak _rtld_addr_phdr
221211705Skibint
222211705Skib_rtld_addr_phdr(const void *addr, struct dl_phdr_info *phdr_info)
223211705Skib{
224211705Skib
225211705Skib	return (0);
226211705Skib}
227217154Skib
228217154Skib#pragma weak _rtld_get_stack_prot
229217154Skibint
230217154Skib_rtld_get_stack_prot(void)
231217154Skib{
232217154Skib
233217154Skib	return (PROT_EXEC | PROT_READ | PROT_WRITE);
234217154Skib}
235217154Skib
236