1/* $NetBSD: load_lib.c,v 1.3 2022/10/08 16:12:50 christos Exp $ */ 2 3/*++ 4/* NAME 5/* load_lib 3 6/* SUMMARY 7/* library loading wrappers 8/* SYNOPSIS 9/* #include <load_lib.h> 10/* 11/* void load_library_symbols(const char *, LIB_FN *, LIB_DP *); 12/* const char *libname; 13/* LIB_FN *libfuncs; 14/* LIB_DP *libdata; 15/* DESCRIPTION 16/* load_library_symbols() loads the specified shared object 17/* and looks up the function or data pointers for the specified 18/* symbols. All errors are fatal. 19/* 20/* Arguments: 21/* .IP libname 22/* shared-library pathname. 23/* .IP libfuncs 24/* Array of LIB_FN structures. The last name member must be null. 25/* .IP libdata 26/* Array of LIB_DP structures. The last name member must be null. 27/* SEE ALSO 28/* msg(3) diagnostics interface 29/* DIAGNOSTICS 30/* Problems are reported via the msg(3) diagnostics routines: 31/* library not found, symbols not found, other fatal errors. 32/* LICENSE 33/* .ad 34/* .fi 35/* The Secure Mailer license must be distributed with this software. 36/* AUTHOR(S) 37/* LaMont Jones 38/* Hewlett-Packard Company 39/* 3404 Harmony Road 40/* Fort Collins, CO 80528, USA 41/* 42/* Wietse Venema 43/* IBM T.J. Watson Research 44/* P.O. Box 704 45/* Yorktown Heights, NY 10598, USA 46/*--*/ 47 48 /* 49 * System libraries. 50 */ 51#include "sys_defs.h" 52#include <stdlib.h> 53#include <stddef.h> 54#include <string.h> 55#ifdef USE_DYNAMIC_MAPS 56#if defined(HAS_DLOPEN) 57#include <dlfcn.h> 58#elif defined(HAS_SHL_LOAD) 59#include <dl.h> 60#else 61#error "USE_DYNAMIC_LIBS requires HAS_DLOPEN or HAS_SHL_LOAD" 62#endif 63 64 /* 65 * Utility library. 66 */ 67#include <msg.h> 68#include <load_lib.h> 69 70/* load_library_symbols - load shared library and look up symbols */ 71 72void load_library_symbols(const char *libname, LIB_FN *libfuncs, 73 LIB_DP *libdata) 74{ 75 static const char myname[] = "load_library_symbols"; 76 LIB_FN *fn; 77 LIB_DP *dp; 78 79#if defined(HAS_DLOPEN) 80 void *handle; 81 char *emsg; 82 83 /* 84 * XXX This is basically how FreeBSD dlfunc() silences a compiler warning 85 * about a data/function pointer conversion. The solution below is non- 86 * portable: it assumes that both data and function pointers are the same 87 * in size, and that both have the same representation. 88 */ 89 union { 90 void *dptr; /* data pointer */ 91 void (*fptr) (void); /* function pointer */ 92 } non_portable_union; 93 94 if ((handle = dlopen(libname, RTLD_NOW)) == 0) { 95 emsg = dlerror(); 96 msg_fatal("%s: dlopen failure loading %s: %s", myname, libname, 97 emsg ? emsg : "don't know why"); 98 } 99 if (libfuncs) { 100 for (fn = libfuncs; fn->name; fn++) { 101 if ((non_portable_union.dptr = dlsym(handle, fn->name)) == 0) { 102 emsg = dlerror(); 103 msg_fatal("%s: dlsym failure looking up %s in %s: %s", myname, 104 fn->name, libname, emsg ? emsg : "don't know why"); 105 } 106 fn->fptr = non_portable_union.fptr; 107 if (msg_verbose > 1) 108 msg_info("loaded %s = %p", fn->name, non_portable_union.dptr); 109 } 110 } 111 if (libdata) { 112 for (dp = libdata; dp->name; dp++) { 113 if ((dp->dptr = dlsym(handle, dp->name)) == 0) { 114 emsg = dlerror(); 115 msg_fatal("%s: dlsym failure looking up %s in %s: %s", myname, 116 dp->name, libname, emsg ? emsg : "don't know why"); 117 } 118 if (msg_verbose > 1) 119 msg_info("loaded %s = %p", dp->name, dp->dptr); 120 } 121 } 122#elif defined(HAS_SHL_LOAD) 123 shl_t handle; 124 125 handle = shl_load(libname, BIND_IMMEDIATE, 0); 126 127 if (libfuncs) { 128 for (fn = libfuncs; fn->name; fn++) { 129 if (shl_findsym(&handle, fn->name, TYPE_PROCEDURE, &fn->fptr) != 0) 130 msg_fatal("%s: shl_findsym failure looking up %s in %s: %m", 131 myname, fn->name, libname); 132 if (msg_verbose > 1) 133 msg_info("loaded %s = %p", fn->name, (void *) fn->fptr); 134 } 135 } 136 if (libdata) { 137 for (dp = libdata; dp->name; dp++) { 138 if (shl_findsym(&handle, dp->name, TYPE_DATA, &dp->dptr) != 0) 139 msg_fatal("%s: shl_findsym failure looking up %s in %s: %m", 140 myname, dp->name, libname); 141 if (msg_verbose > 1) 142 msg_info("loaded %s = %p", dp->name, dp->dptr); 143 } 144 } 145#endif 146} 147 148#endif 149