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