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
load_library_symbols(const char * libname,LIB_FN * libfuncs,LIB_DP * libdata)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