dlfcn.c revision 34196
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 * 2634196Sjdp * $Id: dlfcn.c,v 1.1 1998/02/09 06:05:24 jdp Exp $ 2733180Sjdp */ 2833180Sjdp 2933180Sjdp/* 3034196Sjdp * Linkage to services provided by the dynamic linker. These are 3134196Sjdp * implemented differently in ELF and a.out, because the dynamic 3234196Sjdp * linkers have different interfaces. 3333180Sjdp */ 3433180Sjdp 3534196Sjdp#ifdef __ELF__ 3634196Sjdp 3734196Sjdp#include <dlfcn.h> 3834196Sjdp#include <stddef.h> 3934196Sjdp 4034196Sjdpstatic const char sorry[] = "Service unavailable"; 4134196Sjdp 4234196Sjdp/* 4334196Sjdp * For ELF, the dynamic linker directly resolves references to its 4434196Sjdp * services to functions inside the dynamic linker itself. These 4534196Sjdp * weak-symbol stubs are necessary so that "ld" won't complain about 4634196Sjdp * undefined symbols. The stubs are executed only when the program is 4734196Sjdp * linked statically, or when a given service isn't implemented in the 4834196Sjdp * dynamic linker. They must return an error if called, and they must 4934196Sjdp * be weak symbols so that the dynamic linker can override them. 5034196Sjdp */ 5134196Sjdp 5234196Sjdp#pragma weak _rtld_error 5334196Sjdpvoid 5434196Sjdp_rtld_error(const char *fmt, ...) 5534196Sjdp{ 5634196Sjdp} 5734196Sjdp 5834196Sjdp#pragma weak dladdr 5934196Sjdpint 6034196Sjdpdladdr(const void *addr, Dl_info *dlip) 6134196Sjdp{ 6234196Sjdp _rtld_error(sorry); 6334196Sjdp return 0; 6434196Sjdp} 6534196Sjdp 6634196Sjdp#pragma weak dlclose 6734196Sjdpint 6834196Sjdpdlclose(void *handle) 6934196Sjdp{ 7034196Sjdp _rtld_error(sorry); 7134196Sjdp return -1; 7234196Sjdp} 7334196Sjdp 7434196Sjdp#pragma weak dlerror 7534196Sjdpconst char * 7634196Sjdpdlerror(void) 7734196Sjdp{ 7834196Sjdp return sorry; 7934196Sjdp} 8034196Sjdp 8134196Sjdp#pragma weak dlopen 8234196Sjdpvoid * 8334196Sjdpdlopen(const char *name, int mode) 8434196Sjdp{ 8534196Sjdp _rtld_error(sorry); 8634196Sjdp return NULL; 8734196Sjdp} 8834196Sjdp 8934196Sjdp#pragma weak dlsym 9034196Sjdpvoid * 9134196Sjdpdlsym(void *handle, const char *name) 9234196Sjdp{ 9334196Sjdp _rtld_error(sorry); 9434196Sjdp return NULL; 9534196Sjdp} 9634196Sjdp 9734196Sjdp#else /* a.out format */ 9834196Sjdp 9933180Sjdp#include <sys/types.h> 10033180Sjdp#include <nlist.h> /* XXX - Required by link.h */ 10133180Sjdp#include <dlfcn.h> 10233180Sjdp#include <link.h> 10333180Sjdp#include <stddef.h> 10433180Sjdp 10533180Sjdp/* 10634196Sjdp * For a.out, entry to the dynamic linker is via these trampolines. 10734196Sjdp * They enter the dynamic linker through the ld_entry struct that was 10834196Sjdp * passed back from the dynamic linker at startup time. 10934196Sjdp */ 11034196Sjdp 11134196Sjdp/* GCC is needed because we use its __builtin_return_address construct. */ 11234196Sjdp 11334196Sjdp#ifndef __GNUC__ 11434196Sjdp#error "GCC is needed to compile this file" 11534196Sjdp#endif 11634196Sjdp 11734196Sjdp/* 11833180Sjdp * These variables are set by code in crt0.o. For compatibility with 11933180Sjdp * old executables, they must be common, not extern. 12033180Sjdp */ 12133180Sjdpstruct ld_entry *__ldso_entry; /* Entry points to dynamic linker */ 12233180Sjdpint __ldso_version; /* Dynamic linker version number */ 12333180Sjdp 12434196Sjdpint 12534196Sjdpdladdr(const void *addr, Dl_info *dlip) 12633180Sjdp{ 12734196Sjdp if (__ldso_entry == NULL || __ldso_version < LDSO_VERSION_HAS_DLADDR) 12834196Sjdp return 0; 12934196Sjdp return (__ldso_entry->dladdr)(addr, dlip); 13033180Sjdp} 13133180Sjdp 13233180Sjdpint 13334196Sjdpdlclose(void *handle) 13433180Sjdp{ 13533180Sjdp if (__ldso_entry == NULL) 13633180Sjdp return -1; 13734196Sjdp return (__ldso_entry->dlclose)(handle); 13833180Sjdp} 13933180Sjdp 14034196Sjdpconst char * 14134196Sjdpdlerror(void) 14234196Sjdp{ 14334196Sjdp if (__ldso_entry == NULL) 14434196Sjdp return "Service unavailable"; 14534196Sjdp return (__ldso_entry->dlerror)(); 14634196Sjdp} 14734196Sjdp 14833180Sjdpvoid * 14934196Sjdpdlopen(const char *name, int mode) 15033180Sjdp{ 15133180Sjdp if (__ldso_entry == NULL) 15233180Sjdp return NULL; 15334196Sjdp return (__ldso_entry->dlopen)(name, mode); 15433180Sjdp} 15533180Sjdp 15634196Sjdpvoid * 15734196Sjdpdlsym(void *handle, const char *name) 15833180Sjdp{ 15933180Sjdp if (__ldso_entry == NULL) 16034196Sjdp return NULL; 16134196Sjdp if (__ldso_version >= LDSO_VERSION_HAS_DLSYM3) { 16234196Sjdp void *retaddr = __builtin_return_address(0); /* __GNUC__ only */ 16334196Sjdp return (__ldso_entry->dlsym3)(handle, name, retaddr); 16434196Sjdp } else 16534196Sjdp return (__ldso_entry->dlsym)(handle, name); 16633180Sjdp} 16733180Sjdp 16834196Sjdp#endif /* __ELF__ */ 169