1 /* $NetBSD: load_lib.c,v 1.2 2017/02/14 01:16:49 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 strucures. The last name member must be null. 25 /* .IP libdata 26 /* Array of LIB_DP strucures. 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 72 void 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