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> 37231868Skib#include "namespace.h" 38231868Skib#include <pthread.h> 39231868Skib#include "un-namespace.h" 40231868Skib#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 145231868Skibstatic pthread_once_t dl_phdr_info_once = PTHREAD_ONCE_INIT; 146231868Skibstatic struct dl_phdr_info phdr_info; 147231868Skib 148231868Skibstatic void 149231868Skibdl_init_phdr_info(void) 150231868Skib{ 151231868Skib Elf_Auxinfo *auxp; 152231868Skib size_t phent; 153231868Skib unsigned int i; 154231868Skib 155231868Skib phent = 0; 156231868Skib for (auxp = __elf_aux_vector; auxp->a_type != AT_NULL; auxp++) { 157231868Skib switch (auxp->a_type) { 158231868Skib case AT_BASE: 159231868Skib phdr_info.dlpi_addr = (Elf_Addr)auxp->a_un.a_ptr; 160231868Skib break; 161231868Skib case AT_EXECPATH: 162231868Skib phdr_info.dlpi_name = (const char *)auxp->a_un.a_ptr; 163231868Skib break; 164231868Skib case AT_PHDR: 165231868Skib phdr_info.dlpi_phdr = 166231868Skib (const Elf_Phdr *)auxp->a_un.a_ptr; 167231868Skib break; 168231868Skib case AT_PHENT: 169231868Skib phent = auxp->a_un.a_val; 170231868Skib break; 171231868Skib case AT_PHNUM: 172231868Skib phdr_info.dlpi_phnum = (Elf_Half)auxp->a_un.a_val; 173231868Skib break; 174231868Skib } 175231868Skib } 176231868Skib for (i = 0; i < phdr_info.dlpi_phnum; i++) { 177231868Skib if (phdr_info.dlpi_phdr[i].p_type == PT_TLS) { 178231868Skib phdr_info.dlpi_tls_modid = 1; 179231868Skib phdr_info.dlpi_tls_data = 180231868Skib (void*)phdr_info.dlpi_phdr[i].p_vaddr; 181231868Skib } 182231868Skib } 183231868Skib phdr_info.dlpi_adds = 1; 184231868Skib} 185231868Skib 186168314Skan#pragma weak dl_iterate_phdr 187168314Skanint 188168314Skandl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), 189168314Skan void *data) 190168314Skan{ 191231868Skib 192231868Skib __init_elf_aux_vector(); 193231868Skib if (__elf_aux_vector == NULL) 194231868Skib return (1); 195231868Skib _once(&dl_phdr_info_once, dl_init_phdr_info); 196231868Skib return (callback(&phdr_info, sizeof(phdr_info), data)); 197168314Skan} 198185369Skib 199229768Skib#pragma weak fdlopen 200229768Skibvoid * 201229768Skibfdlopen(int fd, int mode) 202229768Skib{ 203229768Skib 204229768Skib _rtld_error(sorry); 205229768Skib return NULL; 206229768Skib} 207229768Skib 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