ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/dynlink.c
Revision: 188
Committed: Sun Oct 23 20:40:34 2005 UTC (20 years, 9 months ago) by adx
Content type: text/x-csrc
File size: 10864 byte(s)
Log Message:
* compile dynamic modules under win32

File Contents

# User Rev Content
1 adx 30 /*
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 knight 31 * $Id$
23 adx 30 *
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 adx 185 #ifdef _WIN32
43     /*
44     * jmallett's dl*(3) stubs for DLL management.
45     */
46    
47 adx 188 #define RTLD_LAZY 0
48    
49 adx 185 char *
50     dlerror(void)
51     {
52     static char errbuf[IRCD_BUFSIZE];
53 adx 188 char *p;
54 adx 185
55     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
56     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errbuf, sizeof(errbuf), NULL);
57    
58 adx 188 if ((p = strpbrk(errbuf, "\r\n")) != NULL)
59     *p = 0;
60    
61 adx 185 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 adx 188 dlsym(void *module, const char *sym)
78 adx 185 {
79     return GetProcAddress((HMODULE) module, sym);
80     }
81     #endif
82    
83 adx 30 #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 adx 185 return new;
136 adx 30 }
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 adx 188 #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 adx 30 /* 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 db 186 shl_unload((shl_t) & (modp->handle));
248 adx 30 #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 db 186 dlclose(modp->handle);
256 adx 30 #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 db 165 #ifdef HAVE_DLINFO
281 db 164 Link_map *map;
282     #endif
283 adx 30 #ifdef HAVE_SHL_LOAD
284     shl_t tmpptr;
285     #else
286     void *tmpptr = NULL;
287     #endif
288 db 165 void *addr = NULL;
289 adx 30 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 db 164
389 adx 30 modp = MyMalloc(sizeof(struct module));
390 db 165 #ifdef HAVE_DLINFO
391 db 164 dlinfo(tmpptr, RTLD_DI_LINKMAP, &map);
392     if (map != NULL)
393 db 165 addr = map->l_addr;
394 db 164 else
395 db 165 addr = tmpptr;
396 db 164 #endif
397 db 165
398 db 186 modp->handle = tmpptr;
399 db 165 modp->address = addr;
400 adx 30 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 db 165 mod_basename, ver, addr);
414 adx 30 ilog(L_WARN, "Module %s [version: %s] loaded at %p",
415 db 165 mod_basename, ver, addr);
416 adx 30 }
417    
418     return(0);
419     }

Properties

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