ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/dynlink.c
Revision: 186
Committed: Sun Oct 23 16:05:01 2005 UTC (20 years, 9 months ago) by db
Content type: text/x-csrc
File size: 10779 byte(s)
Log Message:
- Q. When is an address not an address?
  A. When it is a handle!

  Keep track of handle address and base address of loaded module separately.
  The address is also used for modlist and could be derived in modlist
  from handle, but later.


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 db 186 shl_unload((shl_t) & (modp->handle));
242 adx 30 #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 db 186 dlclose(modp->handle);
250 adx 30 #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 db 186 modp->handle = tmpptr;
393 db 165 modp->address = addr;
394 adx 30 modp->version = ver;
395     modp->core = core;
396     modp->modremove = mod_deinit;
397    
398     DupString(modp->name, mod_basename);
399     dlinkAdd(modp, &modp->node, &mod_list);
400    
401     initfunc();
402    
403     if (warn == 1)
404     {
405     sendto_realops_flags(UMODE_ALL, L_ALL,
406     "Module %s [version: %s] loaded at %p",
407 db 165 mod_basename, ver, addr);
408 adx 30 ilog(L_WARN, "Module %s [version: %s] loaded at %p",
409 db 165 mod_basename, ver, addr);
410 adx 30 }
411    
412     return(0);
413     }

Properties

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