ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/dynlink.c
Revision: 257
Committed: Sat Nov 12 16:00:08 2005 UTC (19 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 10863 byte(s)
Log Message:
- Forgot to remove my debugging code ..

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

Properties

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