ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/dynlink.c
Revision: 258
Committed: Sat Nov 12 18:47:17 2005 UTC (18 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 10389 byte(s)
Log Message:
- Fixed another core on dlclose()

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

Properties

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