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

Properties

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