Home | History | Annotate | Line # | Download | only in dlfcn
dlfcn_elf.c revision 1.15.4.1
      1  1.15.4.1  christos /*	$NetBSD: dlfcn_elf.c,v 1.15.4.1 2019/06/10 22:05:19 christos Exp $	*/
      2       1.1   minoura 
      3       1.1   minoura /*
      4       1.1   minoura  * Copyright (c) 2000 Takuya SHIOZAKI
      5       1.1   minoura  * All rights reserved.
      6       1.1   minoura  *
      7       1.1   minoura  * Redistribution and use in source and binary forms, with or without
      8       1.1   minoura  * modification, are permitted provided that the following conditions
      9       1.1   minoura  * are met:
     10       1.1   minoura  * 1. Redistributions of source code must retain the above copyright
     11       1.1   minoura  *    notice, this list of conditions and the following disclaimer.
     12       1.1   minoura  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1   minoura  *    notice, this list of conditions and the following disclaimer in the
     14       1.1   minoura  *    documentation and/or other materials provided with the distribution.
     15       1.1   minoura  *
     16       1.1   minoura  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17       1.1   minoura  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18       1.1   minoura  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19       1.1   minoura  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20       1.1   minoura  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21       1.1   minoura  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22       1.1   minoura  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23       1.1   minoura  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24       1.1   minoura  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25       1.1   minoura  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26       1.1   minoura  */
     27       1.1   minoura 
     28       1.1   minoura #include <sys/cdefs.h>
     29       1.1   minoura #if defined(LIBC_SCCS) && !defined(lint)
     30  1.15.4.1  christos __RCSID("$NetBSD: dlfcn_elf.c,v 1.15.4.1 2019/06/10 22:05:19 christos Exp $");
     31       1.1   minoura #endif /* LIBC_SCCS and not lint */
     32       1.1   minoura 
     33       1.1   minoura #include "namespace.h"
     34       1.9     joerg #include <sys/atomic.h>
     35      1.12  christos #include <assert.h>
     36       1.8     joerg #include <elf.h>
     37       1.8     joerg #include <errno.h>
     38       1.8     joerg #include <string.h>
     39       1.9     joerg #include <stdbool.h>
     40       1.1   minoura 
     41      1.15     kamil #undef dl_iterate_phdr
     42       1.5   thorpej #undef dlopen
     43       1.5   thorpej #undef dlclose
     44       1.5   thorpej #undef dlsym
     45       1.5   thorpej #undef dlerror
     46       1.5   thorpej #undef dladdr
     47       1.6     pooka #undef dfinfo
     48       1.5   thorpej 
     49       1.5   thorpej #define	dlopen		___dlopen
     50       1.5   thorpej #define	dlclose		___dlclose
     51       1.5   thorpej #define	dlsym		___dlsym
     52      1.10    nonaka #define	dlvsym		___dlvsym
     53       1.5   thorpej #define	dlerror		___dlerror
     54       1.5   thorpej #define	dladdr		___dladdr
     55       1.6     pooka #define	dlinfo		___dlinfo
     56       1.7     skrll #define	dl_iterate_phdr		___dl_iterate_phdr
     57       1.5   thorpej 
     58       1.1   minoura #define ELFSIZE ARCH_ELFSIZE
     59       1.1   minoura #include "rtld.h"
     60       1.1   minoura 
     61       1.1   minoura #ifdef __weak_alias
     62       1.5   thorpej __weak_alias(dlopen,___dlopen)
     63       1.5   thorpej __weak_alias(dlclose,___dlclose)
     64       1.5   thorpej __weak_alias(dlsym,___dlsym)
     65      1.10    nonaka __weak_alias(dlvsym,___dlvsym)
     66       1.5   thorpej __weak_alias(dlerror,___dlerror)
     67       1.5   thorpej __weak_alias(dladdr,___dladdr)
     68       1.6     pooka __weak_alias(dlinfo,___dlinfo)
     69       1.7     skrll __weak_alias(dl_iterate_phdr,___dl_iterate_phdr)
     70       1.5   thorpej 
     71       1.5   thorpej __weak_alias(__dlopen,___dlopen)
     72       1.5   thorpej __weak_alias(__dlclose,___dlclose)
     73       1.5   thorpej __weak_alias(__dlsym,___dlsym)
     74      1.10    nonaka __weak_alias(__dlvsym,___dlvsym)
     75       1.5   thorpej __weak_alias(__dlerror,___dlerror)
     76       1.5   thorpej __weak_alias(__dladdr,___dladdr)
     77       1.6     pooka __weak_alias(__dlinfo,___dlinfo)
     78       1.7     skrll __weak_alias(__dl_iterate_phdr,___dl_iterate_phdr)
     79      1.14     joerg __weak_alias(__dl_cxa_refcount, ___dl_cxa_refcount)
     80       1.1   minoura #endif
     81       1.1   minoura 
     82       1.4     skrll /*
     83       1.4     skrll  * For ELF, the dynamic linker directly resolves references to its
     84       1.4     skrll  * services to functions inside the dynamic linker itself.  These
     85       1.4     skrll  * weak-symbol stubs are necessary so that "ld" won't complain about
     86       1.4     skrll  * undefined symbols.  The stubs are executed only when the program is
     87       1.4     skrll  * linked statically, or when a given service isn't implemented in the
     88       1.4     skrll  * dynamic linker.  They must return an error if called, and they must
     89       1.4     skrll  * be weak symbols so that the dynamic linker can override them.
     90       1.4     skrll  */
     91       1.4     skrll 
     92       1.4     skrll static char dlfcn_error[] = "Service unavailable";
     93       1.4     skrll 
     94       1.4     skrll /*ARGSUSED*/
     95       1.4     skrll void *
     96       1.4     skrll dlopen(const char *name, int mode)
     97       1.4     skrll {
     98       1.4     skrll 
     99       1.4     skrll 	return NULL;
    100       1.4     skrll }
    101       1.4     skrll 
    102       1.4     skrll /*ARGSUSED*/
    103       1.4     skrll int
    104       1.4     skrll dlclose(void *fd)
    105       1.4     skrll {
    106       1.4     skrll 
    107       1.4     skrll 	return -1;
    108       1.4     skrll }
    109       1.4     skrll 
    110       1.4     skrll /*ARGSUSED*/
    111       1.4     skrll void *
    112       1.4     skrll dlsym(void *handle, const char *name)
    113       1.4     skrll {
    114       1.4     skrll 
    115       1.4     skrll 	return NULL;
    116       1.4     skrll }
    117       1.4     skrll 
    118       1.4     skrll /*ARGSUSED*/
    119      1.10    nonaka void *
    120      1.10    nonaka dlvsym(void *handle, const char *name, const char *version)
    121      1.10    nonaka {
    122      1.10    nonaka 
    123      1.10    nonaka 	return NULL;
    124      1.10    nonaka }
    125      1.10    nonaka 
    126      1.10    nonaka /*ARGSUSED*/
    127       1.4     skrll __aconst char *
    128      1.13  christos dlerror(void)
    129       1.4     skrll {
    130       1.4     skrll 
    131       1.4     skrll 	return dlfcn_error;
    132       1.4     skrll }
    133       1.4     skrll 
    134       1.4     skrll /*ARGSUSED*/
    135       1.4     skrll int
    136       1.4     skrll dladdr(const void *addr, Dl_info *dli)
    137       1.4     skrll {
    138       1.4     skrll 
    139       1.4     skrll 	return 0;
    140       1.4     skrll }
    141       1.6     pooka 
    142       1.6     pooka /*ARGSUSED*/
    143       1.6     pooka int
    144       1.6     pooka dlinfo(void *handle, int req, void *v)
    145       1.6     pooka {
    146       1.6     pooka 
    147       1.6     pooka 	return -1;
    148       1.6     pooka }
    149       1.7     skrll 
    150       1.8     joerg static const char *dlpi_name;
    151       1.8     joerg static Elf_Addr dlpi_addr;
    152       1.8     joerg static const Elf_Phdr *dlpi_phdr;
    153       1.8     joerg static Elf_Half dlpi_phnum;
    154       1.8     joerg 
    155       1.8     joerg static void
    156       1.8     joerg dl_iterate_phdr_setup(void)
    157       1.8     joerg {
    158       1.8     joerg 	const AuxInfo *aux;
    159       1.8     joerg 
    160      1.11     joerg 	_DIAGASSERT(_dlauxinfo() != NULL);
    161       1.8     joerg 
    162      1.11     joerg 	for (aux = _dlauxinfo(); aux->a_type != AT_NULL; ++aux) {
    163       1.8     joerg 		switch (aux->a_type) {
    164       1.8     joerg 		case AT_BASE:
    165       1.8     joerg 			dlpi_addr = aux->a_v;
    166       1.8     joerg 			break;
    167       1.8     joerg 		case AT_PHDR:
    168       1.8     joerg 			dlpi_phdr = (void *)aux->a_v;
    169       1.8     joerg 			break;
    170       1.8     joerg 		case AT_PHNUM:
    171      1.12  christos 			_DIAGASSERT(__type_fit(Elf_Half, aux->a_v));
    172      1.12  christos 			dlpi_phnum = (Elf_Half)aux->a_v;
    173       1.8     joerg 			break;
    174       1.8     joerg 		case AT_SUN_EXECNAME:
    175       1.8     joerg 			dlpi_name = (void *)aux->a_v;
    176       1.8     joerg 			break;
    177       1.8     joerg 		}
    178       1.8     joerg 	}
    179  1.15.4.1  christos 
    180  1.15.4.1  christos 	if (!dlpi_phdr)
    181  1.15.4.1  christos 		return;
    182  1.15.4.1  christos 
    183  1.15.4.1  christos 	const Elf_Phdr *phdr = (const Elf_Phdr *)dlpi_phdr;
    184  1.15.4.1  christos 	const Elf_Phdr *phlimit = phdr + dlpi_phnum;
    185  1.15.4.1  christos 
    186  1.15.4.1  christos 	for (; phdr < phlimit; ++phdr) {
    187  1.15.4.1  christos 		if (phdr->p_type == PT_PHDR)
    188  1.15.4.1  christos 			dlpi_addr = (uintptr_t)phdr - phdr->p_vaddr;
    189  1.15.4.1  christos 	}
    190       1.8     joerg }
    191       1.8     joerg 
    192       1.7     skrll /*ARGSUSED*/
    193       1.7     skrll int
    194       1.7     skrll dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
    195       1.7     skrll     void *data)
    196       1.7     skrll {
    197       1.9     joerg 	static bool setup_done;
    198       1.8     joerg 	struct dl_phdr_info phdr_info;
    199       1.8     joerg 
    200       1.9     joerg 	if (!setup_done) {
    201       1.9     joerg 		/*
    202       1.9     joerg 		 * This can race on the first call to dl_iterate_phdr.
    203       1.9     joerg 		 * dl_iterate_phdr_setup only touches field of pointer size
    204       1.9     joerg 		 * and smaller and such stores are atomic.
    205       1.9     joerg 		 */
    206       1.9     joerg 		dl_iterate_phdr_setup();
    207       1.9     joerg 		membar_producer();
    208       1.9     joerg 		setup_done = true;
    209       1.9     joerg 	}
    210       1.8     joerg 
    211       1.8     joerg 	memset(&phdr_info, 0, sizeof(phdr_info));
    212       1.8     joerg 	phdr_info.dlpi_addr = dlpi_addr;
    213       1.8     joerg 	phdr_info.dlpi_phdr = dlpi_phdr;
    214       1.8     joerg 	phdr_info.dlpi_phnum = dlpi_phnum;
    215       1.8     joerg 	phdr_info.dlpi_name = dlpi_name;
    216       1.8     joerg 
    217       1.8     joerg 	return callback(&phdr_info, sizeof(phdr_info), data);
    218       1.7     skrll }
    219      1.14     joerg 
    220      1.14     joerg void ___dl_cxa_refcount(void *, ssize_t);
    221      1.14     joerg 
    222      1.14     joerg /*ARGSUSED*/
    223      1.14     joerg void
    224      1.14     joerg ___dl_cxa_refcount(void *dso_symbol, ssize_t delta)
    225      1.14     joerg {
    226      1.14     joerg }
    227