ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/dynlink.c
Revision: 908
Committed: Sun Nov 4 23:21:51 2007 UTC (16 years, 4 months ago) by stu
Content type: text/x-csrc
File size: 10420 byte(s)
Log Message:
Completely redo the build system.  Now uses libtool and automake.  Suggest you clean out your tree and then do ./autogen.sh.

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * dynlink.c: A module loader.
4 *
5 * Copyright (C) 2002 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 *
24 */
25 #include "stdinc.h"
26 #include "tools.h"
27 #include "irc_string.h"
28 #include "modules.h"
29 #include "s_log.h"
30 #include "client.h"
31 #include "send.h"
32
33 #ifndef RTLD_NOW
34 #define RTLD_NOW RTLD_LAZY /* openbsd deficiency */
35 #endif
36
37 #if defined(HAVE_DLINFO) && defined(HAVE_LINK_H)
38 # include <link.h>
39 #endif
40
41 #if USE_SHARED_MODULES
42
43 extern dlink_list mod_list;
44
45 static char unknown_ver[] = "<unknown>";
46
47 /* This file contains the core functions to use dynamic libraries.
48 * -TimeMr14C
49 */
50
51 #if !defined(HAVE_SHL_LOAD) && !defined(HAVE_DLFUNC)
52 /*
53 * Fake dlfunc(3) if we don't have it, cause it's happy.
54 */
55 typedef void (*__function_p)(void);
56
57 static __function_p
58 dlfunc(void *myHandle, const char *functionName)
59 {
60 /* XXX This is not guaranteed to work, but with
61 * traditional dl*(3), it is the best we can do.
62 * -jmallett
63 */
64 void *symbolp;
65
66 symbolp = dlsym(myHandle, functionName);
67 return((__function_p)(uintptr_t)symbolp);
68 }
69 #endif
70
71 #ifdef HAVE_MACH_O_DYLD_H
72 /*
73 ** jmallett's dl*(3) shims for NSModule(3) systems.
74 */
75 #include <mach-o/dyld.h>
76
77 #ifndef HAVE_DLOPEN
78 #ifndef RTLD_LAZY
79 #define RTLD_LAZY 2185 /* built-in dl*(3) don't care */
80 #endif
81
82 void undefinedErrorHandler(const char *);
83 NSModule multipleErrorHandler(NSSymbol, NSModule, NSModule);
84 void linkEditErrorHandler(NSLinkEditErrors, int, const char *, const char *);
85 char *dlerror(void);
86 void *dlopen(char *, int);
87 int dlclose(void *);
88 void *dlsym(void *, char *);
89
90 static int firstLoad = TRUE;
91 static int myDlError;
92 static const char *myErrorTable[] =
93 {
94 "Loading file as object failed\n",
95 "Loading file as object succeeded\n",
96 "Not a valid shared object\n",
97 "Architecture of object invalid on this architecture\n",
98 "Invalid or corrupt image\n",
99 "Could not access object\n",
100 "NSCreateObjectFileImageFromFile failed\n",
101 NULL
102 };
103
104 void
105 undefinedErrorHandler(const char *symbolName)
106 {
107 sendto_realops_flags(UMODE_ALL, L_ALL, "Undefined symbol: %s", symbolName);
108 ilog(L_WARN, "Undefined symbol: %s", symbolName);
109 return;
110 }
111
112 NSModule
113 multipleErrorHandler(NSSymbol s, NSModule old, NSModule new)
114 {
115 /* XXX
116 ** This results in substantial leaking of memory... Should free one
117 ** module, maybe?
118 */
119 sendto_realops_flags(UMODE_ALL, L_ALL, "Symbol `%s' found in `%s' and `%s'",
120 NSNameOfSymbol(s), NSNameOfModule(old), NSNameOfModule(new));
121 ilog(L_WARN, "Symbol `%s' found in `%s' and `%s'", NSNameOfSymbol(s),
122 NSNameOfModule(old), NSNameOfModule(new));
123 /* We return which module should be considered valid, I believe */
124 return(new);
125 }
126
127 void
128 linkEditErrorHandler(NSLinkEditErrors errorClass, int errnum,
129 const char *fileName, const char *errorString)
130 {
131 sendto_realops_flags(UMODE_ALL, L_ALL, "Link editor error: %s for %s",
132 errorString, fileName);
133 ilog(L_WARN, "Link editor error: %s for %s", errorString, fileName);
134 return;
135 }
136
137 char *
138 dlerror(void)
139 {
140 return(myDlError == NSObjectFileImageSuccess ? NULL : myErrorTable[myDlError % 7]);
141 }
142
143 void *
144 dlopen(char *filename, int unused)
145 {
146 NSObjectFileImage myImage;
147 NSModule myModule;
148
149 if (firstLoad)
150 {
151 /* If we are loading our first symbol (huzzah!) we should go ahead
152 * and install link editor error handling!
153 */
154 NSLinkEditErrorHandlers linkEditorErrorHandlers;
155
156 linkEditorErrorHandlers.undefined = undefinedErrorHandler;
157 linkEditorErrorHandlers.multiple = multipleErrorHandler;
158 linkEditorErrorHandlers.linkEdit = linkEditErrorHandler;
159 NSInstallLinkEditErrorHandlers(&linkEditorErrorHandlers);
160 firstLoad = FALSE;
161 }
162
163 myDlError = NSCreateObjectFileImageFromFile(filename, &myImage);
164
165 if (myDlError != NSObjectFileImageSuccess)
166 return(NULL);
167
168 myModule = NSLinkModule(myImage, filename, NSLINKMODULE_OPTION_PRIVATE);
169 return((void *)myModule);
170 }
171
172 int
173 dlclose(void *myModule)
174 {
175 NSUnLinkModule(myModule, FALSE);
176 return(0);
177 }
178
179 void *
180 dlsym(void *myModule, char *mySymbolName)
181 {
182 NSSymbol mySymbol;
183
184 mySymbol = NSLookupSymbolInModule((NSModule)myModule, mySymbolName);
185 return NSAddressOfSymbol(mySymbol);
186 }
187 #endif
188 #endif
189
190 /* unload_one_module()
191 *
192 * inputs - name of module to unload
193 * - 1 to say modules unloaded, 0 to not
194 * output - 0 if successful, -1 if error
195 * side effects - module is unloaded
196 */
197 int
198 unload_one_module(char *name, int warn)
199 {
200 dlink_node *ptr = NULL;
201 struct module *modp = NULL;
202
203 if ((ptr = findmodule_byname(name)) == NULL)
204 return -1;
205
206 modp = ptr->data;
207
208 if (modp->modremove)
209 (*modp->modremove)();
210
211 #ifdef HAVE_SHL_LOAD
212 /* shl_* and friends have a slightly different format than dl*. But it does not
213 * require creation of a totally new modules.c, instead proper usage of
214 * defines solve this case. -TimeMr14C
215 */
216 shl_unload((shl_t) & (modp->handle));
217 #else
218 /* We use FreeBSD's dlfunc(3) interface, or fake it as we
219 * used to here if it isn't there. The interface should
220 * be standardised some day, and so it eventually will be
221 * providing something guaranteed to do the right thing here.
222 * -jmallett
223 */
224 dlclose(modp->handle);
225 #endif
226 assert(dlink_list_length(&mod_list) > 0);
227 dlinkDelete(ptr, &mod_list);
228 MyFree(modp->name);
229 MyFree(modp);
230
231 if (warn == 1)
232 {
233 ilog(L_INFO, "Module %s unloaded", name);
234 sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s unloaded", name);
235 }
236
237 return 0;
238 }
239
240 /* load_a_module()
241 *
242 * inputs - path name of module, int to notice, int of core
243 * output - -1 if error 0 if success
244 * side effects - loads a module if successful
245 */
246 int
247 load_a_module(char *path, int warn, int core)
248 {
249 #ifdef HAVE_DLINFO
250 struct link_map *map;
251 #endif
252 #ifdef HAVE_SHL_LOAD
253 shl_t tmpptr;
254 #else
255 void *tmpptr = NULL;
256 #endif
257 void *addr = NULL;
258 char *mod_basename;
259 void (*initfunc)(void) = NULL;
260 void (*mod_deinit)(void) = NULL;
261 char **verp;
262 char *ver;
263 struct module *modp;
264
265 mod_basename = basename(path);
266
267 if (findmodule_byname(mod_basename) != NULL)
268 return(1);
269
270 #ifdef HAVE_SHL_LOAD
271 tmpptr = shl_load(path, BIND_IMMEDIATE, NULL);
272 #else
273 tmpptr = dlopen(path, RTLD_NOW);
274 #endif
275
276 if (tmpptr == NULL)
277 {
278 #ifdef HAVE_SHL_LOAD
279 const char *err = strerror(errno);
280 #else
281 const char *err = dlerror();
282 #endif
283 sendto_realops_flags(UMODE_ALL, L_ALL, "Error loading module %s: %s",
284 mod_basename, err);
285 ilog(L_WARN, "Error loading module %s: %s", mod_basename, err);
286
287 return(-1);
288 }
289
290 #ifdef HAVE_SHL_LOAD
291 if (shl_findsym(&tmpptr, "_modinit", TYPE_UNDEFINED, (void *)&initfunc) == -1)
292 {
293 if (shl_findsym(&tmpptr, "__modinit", TYPE_UNDEFINED, (void *)&initfunc) == -1)
294 {
295 ilog(L_WARN, "Module %s has no _modinit() function", mod_basename);
296 sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _modinit() function",
297 mod_basename);
298 shl_unload(tmpptr);
299 return(-1);
300 }
301 }
302
303 if (shl_findsym(&tmpptr, "_moddeinit", TYPE_UNDEFINED, (void *)&mod_deinit) == -1)
304 {
305 if (shl_findsym(&tmpptr, "__moddeinit", TYPE_UNDEFINED, (void *)&mod_deinit) == -1)
306 {
307 ilog(L_WARN, "Module %s has no _moddeinit() function", mod_basename);
308 sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _moddeinit() function",
309 mod_basename);
310 /* this is a soft error. we're allowed not to have one, i guess.
311 * (judging by the code in unload_one_module() */
312 mod_deinit = NULL;
313 }
314 }
315
316 if (shl_findsym(&tmpptr, "_version", TYPE_UNDEFINED, &verp) == -1)
317 {
318 if (shl_findsym(&tmpptr, "__version", TYPE_UNDEFINED, &verp) == -1)
319 ver = unknown_ver;
320 else
321 ver = *verp;
322 }
323 else
324 ver = *verp;
325 #else
326 if ((initfunc = (void(*)(void))dlfunc(tmpptr, "_modinit")) == NULL &&
327 /* Only for compatibility, because some systems have underscore
328 * prepended symbol names */
329 (initfunc = (void(*)(void))dlfunc(tmpptr, "__modinit")) == NULL)
330 {
331 sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _modinit() function",
332 mod_basename);
333 ilog(L_WARN, "Module %s has no _modinit() function", mod_basename);
334 dlclose(tmpptr);
335 return(-1);
336 }
337
338 mod_deinit = (void(*)(void))dlfunc(tmpptr, "_moddeinit");
339
340 if (mod_deinit == NULL && (mod_deinit = (void(*)(void))dlfunc(tmpptr, "__moddeinit")) == NULL)
341 {
342 sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _moddeinit() function",
343 mod_basename);
344 ilog(L_WARN, "Module %s has no _moddeinit() function", mod_basename);
345 /* blah blah soft error, see above. */
346 mod_deinit = NULL;
347 }
348
349 verp = (char **)dlsym(tmpptr, "_version");
350
351 if (verp == NULL && (verp = (char **)dlsym(tmpptr, "__version")) == NULL)
352 ver = unknown_ver;
353 else
354 ver = *verp;
355 #endif
356
357 modp = MyMalloc(sizeof(struct module));
358 #ifdef HAVE_DLINFO
359 dlinfo(tmpptr, RTLD_DI_LINKMAP, &map);
360 if (map != NULL)
361 addr = (void *)map->l_addr;
362 else
363 #endif
364 addr = tmpptr;
365
366 modp->handle = tmpptr;
367 modp->address = addr;
368 modp->version = ver;
369 modp->core = core;
370 modp->modremove = mod_deinit;
371
372 DupString(modp->name, mod_basename);
373 dlinkAdd(modp, &modp->node, &mod_list);
374
375 initfunc();
376
377 if (warn == 1)
378 {
379 sendto_realops_flags(UMODE_ALL, L_ALL,
380 "Module %s [version: %s] loaded at %p",
381 mod_basename, ver, addr);
382 ilog(L_WARN, "Module %s [version: %s] loaded at %p",
383 mod_basename, ver, addr);
384 }
385
386 return(0);
387 }
388 #endif

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision