/[ascend]/trunk/base/generic/utilities/ascDynaLoad.c
ViewVC logotype

Contents of /trunk/base/generic/utilities/ascDynaLoad.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 66 - (show annotations) (download) (as text)
Wed Nov 30 09:33:54 2005 UTC (18 years, 6 months ago) by johnpye
File MIME type: text/x-csrc
File size: 79297 byte(s)
Fixing a typo
1 /* ex: set ts=8 : */
2 /*
3 * -----------------------------------------------------------------
4 * Copyright 1993 D.I.S. - Universita` di Pavia - Italy
5 * -----------------------------------------------------------------
6 *
7 * Permission to use, copy, modify, distribute this software
8 * and its documentation foar any purpose is hereby granted without
9 * fee, provided that the above copyright notice appear in all
10 * copies and that both that copyright notice and this permission
11 * notice appear in supporting documentation, and that the name of
12 * D.I.S. not be used in advertising or publicity pertaining to
13 * distribution of the software without specific, written prior per-
14 * mission. D.I.S. makes no representations about the suitability
15 * of this software for any purpose. It is provided "as is" without
16 * express or implied warranty.
17 *
18 * D.I.S. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, IN-
19 * CLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
20 * NO EVENT SHALL D.I.S. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
23 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNEC-
24 * TION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 */
26
27 /*
28 * Small changes made by Michael Moore (mdm@cis.ohio-state.edu)
29 * December 24th, 1993.
30 * The tcl sections ripped out by Kirk Abbott (ka0p@edrc.cmu.edu)
31 * September 3rd, 1994.
32 * To date the architectures supported are:
33 * sun - pure sunos, defines also handle MACH.
34 * osf,
35 * solaris,
36 * hpux
37 * sgi
38 * ultrix
39 * Windows
40 *
41 * Remember that under most systems, profiling does not work
42 * with dynamic libraries. !
43 */
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <stdarg.h>
48 #include "utilities/ascConfig.h"
49 #include "utilities/ascPrint.h"
50 #include "utilities/ascMalloc.h"
51
52 struct ascend_dlrecord {
53 char *path; /* library name */
54 void *dlreturn; /* return from dlopen */
55 struct ascend_dlrecord *next;
56 };
57
58 /* Linked list of library names & dlopen() return values. */
59 static
60 struct ascend_dlrecord *g_ascend_dllist = NULL;
61
62 /*
63 * Adds a record of the path and handle to the list.
64 * If it fails to do this, returns 1, else 0.
65 */
66 static
67 int AscAddRecord(void *dlreturn, CONST char *path)
68 {
69 struct ascend_dlrecord *new;
70 char *keeppath;
71 if (dlreturn == NULL || path == NULL) {
72 return 1;
73 }
74 keeppath = strdup((char *)path);
75 if (keeppath==NULL) return 1;
76 new = (struct ascend_dlrecord *)malloc(sizeof(struct ascend_dlrecord));
77 if (new==NULL) {
78 free(keeppath);
79 return 1;
80 }
81 new->next = g_ascend_dllist; /* insert at head */
82 g_ascend_dllist = new;
83 new->path = keeppath;
84 new->dlreturn = dlreturn;
85 return 0;
86 }
87
88 /*
89 * Finds a record of the path given and returns the associated handle.
90 * If it fails to do this, returns NULL.
91 */
92 static
93 void *AscFindDLRecord(CONST char *path)
94 {
95 struct ascend_dlrecord *new;
96 if (path == NULL) {
97 return NULL;
98 }
99 new = g_ascend_dllist;
100 while (new != NULL && strcmp(new->path,path) != 0) {
101 /* advance new until no more new or new with path found */
102 new = new->next;
103 }
104 return (new != NULL) ? new->dlreturn : NULL;
105 }
106
107 /*
108 * Finds and returns the handle to path, if one matches, and
109 * deletes the record from the list. Returns NULL if not found.
110 */
111 static
112 void *AscDeleteRecord(char *path)
113 {
114 struct ascend_dlrecord *nextptr, *lastptr, *old;
115 void *dlreturn = NULL;
116
117 if ((g_ascend_dllist == NULL) || (NULL == path)) return NULL;
118
119 if (strcmp(path,g_ascend_dllist->path)==0) {
120 /* head case */
121 old = g_ascend_dllist;
122 g_ascend_dllist = old->next;
123 dlreturn = old->dlreturn;
124 free(old->path);
125 free(old);
126 } else {
127 lastptr = g_ascend_dllist;
128 nextptr = lastptr->next;
129 while (nextptr != NULL && strcmp(nextptr->path,path) != 0) {
130 lastptr = nextptr;
131 nextptr = nextptr->next;
132 }
133 /* so either nextptr is NULL and not in list, or nextptr is
134 * what we want to delete and lastptr is the link to it.
135 */
136 if (nextptr != NULL) {
137 old = nextptr;
138 lastptr->next = nextptr->next;
139 dlreturn = old->dlreturn;
140 free(old->path);
141 free(old);
142 }
143 }
144 return dlreturn;
145 }
146
147 /*
148 * Checks the list for a conflicting handle so we can issue
149 * a more helpful warning, if need be, than the standard message.
150 */
151 static
152 void AscCheckDuplicateLoad(CONST char *path)
153 {
154 struct ascend_dlrecord *r;
155
156 if (NULL == path) {
157 FPRINTF(stderr,"Null path in AscCheckDuplicateLoad\n");
158 return;
159 }
160
161 r = g_ascend_dllist;
162 while (r != NULL) {
163 if (strcmp(path,r->path)==0) {
164 FPRINTF(stderr,"Attempt to load already loaded %s\n",path);
165 return;
166 }
167 r = r->next;
168 }
169 }
170
171 #ifdef __WIN32__
172 #include <windows.h>
173 /*
174 WINDOWS
175 */
176 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
177 {
178 #define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
179 HINSTANCE xlib;
180 int (*install)() = NULL;
181
182 if (NULL == path) {
183 FPRINTF(stderr,"Asc_DynamicLoad failed: Null path\n");
184 return 1;
185 }
186
187 AscCheckDuplicateLoad(path); /* whine if we've see it before */
188 /*
189 * If the named library does not exist, if it's not loadable or if
190 * it does not define the named install proc, report an error
191 */
192
193 xlib = LoadLibrary(path);
194 if (xlib == NULL) {
195 FPRINTF(stderr,"Asc_DynamicLoad: LoadLibrary failed\n");
196 return 1;
197 }
198 if (NULL != initFun) {
199 install = (int (*)())GetProcAddress(xlib,initFun);
200 if (install == NULL) {
201 FPRINTF(stderr,"Asc_DynamicLoad: Required function %s not found\n", initFun);
202 (void)FreeLibrary(xlib);
203 return 1;
204 }else{
205 FPRINTF(ASCERR,"FOUND INITFCN %s AT %d\n",initFun,install);
206 }
207 }
208 if (0 != AscAddRecord(xlib,path)) {
209 FPRINTF(stderr,"Asc_DynamicLoad failed to record library (%s)\n",path);
210 }
211 return (install == NULL) ? 0 : (*install)();
212 }
213 #endif /* __WIN32__ */
214
215 #if defined(sun) || defined(linux)
216 #ifndef MACH
217 #include <dlfcn.h>
218
219 /*
220 SOLARIS and LINUX
221 */
222 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
223 {
224 #define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
225 void *xlib;
226 int (*install)() = NULL;
227 FILE *fp;
228
229 FPRINTF(ASCERR,"LOADING LIBRARY %s\n",path);
230
231 if (NULL == path) {
232 FPRINTF(ASCERR,"Asc_DynamicLoad failed: Null path\n");
233 return 1;
234 }
235
236 AscCheckDuplicateLoad(path); /* whine if we've see it before */
237
238 FPRINTF(ASCERR,"PATH IS NOT A DUPE\n");
239
240 fp = fopen(path,"rb");
241 if(fp==NULL){
242 FPRINTF(ASCERR,"FILE %s ISN'T THERE\n",path);
243 return 1;
244 }
245 FPRINTF(ASCERR,"FILE %s IS THERE AND CAN BE OPENED\n",path);
246 fclose(fp);
247
248 /* clear error message first */
249 dlerror();
250
251 xlib = dlopen(path,RTLD_GLOBAL|RTLD_NOW);
252 if(xlib==NULL){
253 FPRINTF(ASCERR,"COULDN'T LOAD LIBRARY %s\n",path);
254 FPRINTF(ASCERR,"DLERROR: %s\n\n",dlerror());
255 return 1;
256 }
257
258 FPRINTF(ASCERR,"LIBRARY OPENED; HUNTING FOR initFun %s\n",initFun);
259 if (xlib == NULL) {
260 FPRINTF(ASCERR,"DLERROR: %s\n",(char *)dlerror());
261 return 1;
262 }
263 if (NULL != initFun) {
264 install = (int (*)())dlsym(xlib, initFun);
265 if (install == NULL) {
266 FPRINTF(stderr,"%s\n",(char *)dlerror());
267 dlclose(xlib);
268 return 1;
269 }
270 }
271 if (0 != AscAddRecord(xlib,path)) {
272 FPRINTF(ASCERR,"Asc_DynamicLoad failed to record library (%s)\n",path);
273 }
274 return (install == NULL) ? 0 : (*install)();
275 }
276
277 int DynamicLoad(CONST char *path, CONST char *initFun)
278 {
279 void *xlib;
280 int (*install)() = NULL;
281
282 if (NULL == path) {
283 FPRINTF(stderr,"DynamicLoad failed: Null path\n");
284 return 1;
285 }
286
287 /*
288 * If the named library does not exist, if it's not loadable or if
289 * it does not define the named install proc, report an error
290 */
291 xlib = dlopen(path, 1);
292 if (xlib == NULL) {
293 FPRINTF(stderr,"%s\n",(char *)dlerror());
294 return 1;
295 }
296 if (NULL != initFun) {
297 install = (int (*)())dlsym(xlib, initFun);
298 if (install == NULL) {
299 FPRINTF(stderr,"%s\n",(char *)dlerror());
300 dlclose(xlib);
301 return 1;
302 }
303 }
304 /* Try to install the extension and report success or failure */
305 return (install == NULL) ? 0 : (*install)();
306 }
307 #else /* MACH */
308 int DynamicLoad(CONST char *path, CONST char *initFun)
309 {
310 return 0;
311 }
312 #endif /* MACH */
313 #endif /* sun */
314
315
316 #ifdef __osf__
317 #include <dlfcn.h>
318 /*
319 OSF (??)
320 */
321 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
322 {
323 #define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
324 void *xlib;
325 int (*install)() = NULL;
326
327 if (NULL == path) {
328 FPRINTF(stderr,"Asc_DynamicLoad failed: Null path\n");
329 return 1;
330 }
331
332 AscCheckDuplicateLoad(path); /* whine if we've see it before */
333
334 /*
335 * If the named library does not exist, if it's not loadable or if
336 * it does not define the named install proc, report an error
337 */
338 xlib = dlopen((char *)path, 1);
339 if (xlib == NULL) {
340 FPRINTF(stderr,"%s\n",(char *)dlerror());
341 return 1;
342 }
343 if (NULL != initFun) {
344 install = (int (*)())dlsym(xlib,(char *)initFun);
345 if (install==NULL) {
346 FPRINTF(stderr,"%s\n",(char *)dlerror());
347 dlclose(xlib);
348 return 1;
349 }
350 }
351 if (0 != AscAddRecord(xlib,path)) {
352 FPRINTF(stderr,"Asc_DynamicLoad failed to record library (%s)\n",path);
353 }
354 return (install == NULL) ? 0 : (*install)();
355 }
356
357 int DynamicLoad(CONST char *path, CONST char *initFun)
358 {
359 void *xlib;
360 int (*install)() = NULL;
361
362 if (NULL == path) {
363 FPRINTF(stderr,"DynamicLoad failed: Null path\n");
364 return 1;
365 }
366
367 /*
368 * If the named library does not exist, if it's not loadable or if
369 * it does not define the named install proc, report an error
370 */
371 xlib = dlopen((char *)path, 1);
372 if (xlib == NULL) {
373 FPRINTF(stderr,"%s\n",(char *)dlerror());
374 return 1;
375 }
376 if (NULL != initFun) {
377 install = (int (*)())dlsym(xlib,(char *)initFun);
378 if (install==NULL) {
379 FPRINTF(stderr,"%s\n",(char *)dlerror());
380 dlclose(xlib);
381 return 1;
382 }
383 }
384 /* Try to install the extension and report success or failure */
385 return (install == NULL) ? 0 : (*install)();
386 }
387 #endif /* osf */
388
389 #if defined(solaris) || defined(_AIX)
390 #if defined(solaris)
391 #include <dlfcn.h>
392 #else
393 /* under aix we have do also define dlopen and the rest of the
394 * dl interface, so swipe it from tcl.
395 * :r ../compat/dlfcn.h
396 * :r tclLoadAix.c
397 */
398 /*
399 * dlfcn.h --
400 *
401 * This file provides a replacement for the header file "dlfcn.h"
402 * on systems where dlfcn.h is missing. It's primary use is for
403 * AIX, where tcl emulates the dl library.
404 *
405 * This file is subject to the following copyright notice, which is
406 * different from the notice used elsewhere in tcl but rougly
407 * equivalent in meaning.
408 *
409 * Copyright (c) 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH
410 * Not derived from licensed software.
411 *
412 * Permission is granted to freely use, copy, modify, and redistribute
413 * this software, provided that the author is not construed to be liable
414 * for any results of using the software, alterations are clearly marked
415 * as such, and this notice is not modified.
416 *
417 * SCCS: @(#) dlfcn.h 1.4 96/09/17 09:05:59
418 */
419
420 /*
421 * @(#)dlfcn.h 1.4 revision of 95/04/25 09:36:52
422 * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH
423 * 30159 Hannover, Germany
424 */
425
426 #ifndef __dlfcn_h__
427 #define __dlfcn_h__
428
429 /*_#ifndef _TCL */
430 /*_#include <tcl.h> */
431 /*_#endif */
432
433 #ifdef __cplusplus
434 extern "C" {
435 #endif
436
437 /*
438 * Mode flags for the dlopen routine.
439 */
440 #define RTLD_LAZY 1 /* lazy function call binding */
441 #define RTLD_NOW 2 /* immediate function call binding */
442 #define RTLD_GLOBAL 0x100 /* allow symbols to be global */
443
444 /*
445 * To be able to intialize, a library may provide a dl_info structure
446 * that contains functions to be called to initialize and terminate.
447 */
448 struct dl_info {
449 void (*init)(void);
450 void (*fini)(void);
451 };
452
453 void *dlopen(const char *path, int mode);
454 void *dlsym(void *handle, const char *symbol);
455 char *dlerror(void);
456 int dlclose(void *handle);
457
458 #ifdef __cplusplus
459 }
460 #endif
461
462 /*
463 * tclLoadAix.c --
464 *
465 * This file implements the dlopen and dlsym APIs under the
466 * AIX operating system, to enable the tcl "load" command to
467 * work. This code was provided by Jens-Uwe Mager.
468 *
469 * This file is subject to the following copyright notice, which is
470 * different from the notice used elsewhere in tcl. The file has
471 * been modified to incorporate the file dlfcn.h in-line.
472 *
473 * Copyright (c) 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH
474 * Not derived from licensed software.
475
476 * Permission is granted to freely use, copy, modify, and redistribute
477 * this software, provided that the author is not construed to be liable
478 * for any results of using the software, alterations are clearly marked
479 * as such, and this notice is not modified.
480 *
481 * SCCS: @(#) tclLoadAix.c 1.11 96/10/07 10:41:24
482 *
483 * Note: this file has been altered from the original in a few
484 * ways in order to work properly with tcl.
485 */
486
487 /*
488 * @(#)dlfcn.c 1.7 revision of 95/08/14 19:08:38
489 * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH
490 * 30159 Hannover, Germany
491 */
492
493 #include <stdio.h>
494 #include <errno.h>
495 #include <string.h>
496 #include <stdlib.h>
497 #include <sys/types.h>
498 #include <sys/ldr.h>
499 #include <a.out.h>
500 #include <ldfcn.h>
501
502 /*
503 * We simulate dlopen() et al. through a call to load. Because AIX has
504 * no call to find an exported symbol we read the loader section of the
505 * loaded module and build a list of exported symbols and their virtual
506 * address.
507 */
508
509 typedef struct {
510 char *name; /* the symbols's name */
511 void *addr; /* its relocated virtual address */
512 } Export, *ExportPtr;
513
514 /*
515 * xlC uses the following structure to list its constructors and
516 * destructors. This is gleaned from the output of munch.
517 */
518 typedef struct {
519 void (*init)(void); /* call static constructors */
520 void (*term)(void); /* call static destructors */
521 } Cdtor, *CdtorPtr;
522
523 /*
524 * The void * handle returned from dlopen is actually a ModulePtr.
525 */
526 typedef struct Module {
527 struct Module *next;
528 char *name; /* module name for refcounting */
529 int refCnt; /* the number of references */
530 void *entry; /* entry point from load */
531 struct dl_info *info; /* optional init/terminate functions */
532 CdtorPtr cdtors; /* optional C++ constructors */
533 int nExports; /* the number of exports found */
534 ExportPtr exports; /* the array of exports */
535 } Module, *ModulePtr;
536
537 /*
538 * We keep a list of all loaded modules to be able to call the fini
539 * handlers and destructors at atexit() time.
540 */
541 static ModulePtr modList;
542
543 /*
544 * The last error from one of the dl* routines is kept in static
545 * variables here. Each error is returned only once to the caller.
546 */
547 static char errbuf[BUFSIZ];
548 static int errvalid;
549
550 static void caterr(char *);
551 static int readExports(ModulePtr);
552 static void terminate(void);
553 static void *findMain(void);
554
555 void *dlopen(const char *path, int mode)
556 {
557 register ModulePtr mp;
558 static void *mainModule;
559
560 /*
561 * Upon the first call register a terminate handler that will
562 * close all libraries. Also get a reference to the main module
563 * for use with loadbind.
564 */
565 if (!mainModule) {
566 if ((mainModule = findMain()) == NULL)
567 return NULL;
568 atexit(terminate);
569 }
570 /*
571 * Scan the list of modules if we have the module already loaded.
572 */
573 for (mp = modList; mp; mp = mp->next)
574 if (strcmp(mp->name, path) == 0) {
575 mp->refCnt++;
576 return (void *) mp;
577 }
578 if ((mp = (ModulePtr)calloc(1, sizeof(*mp))) == NULL) {
579 errvalid++;
580 strcpy(errbuf, "calloc: ");
581 strcat(errbuf, strerror(errno));
582 return (void *) NULL;
583 }
584 mp->name = malloc((unsigned) (strlen(path) + 1));
585 strcpy(mp->name, path);
586 /*
587 * load should be declared load(const char *...). Thus we
588 * cast the path to a normal char *. Ugly.
589 */
590 if ((mp->entry = (void *)load((char *)path, L_NOAUTODEFER, NULL)) == NULL) {
591 free(mp->name);
592 free(mp);
593 errvalid++;
594 strcpy(errbuf, "dlopen: ");
595 strcat(errbuf, path);
596 strcat(errbuf, ": ");
597 /*
598 * If AIX says the file is not executable, the error
599 * can be further described by querying the loader about
600 * the last error.
601 */
602 if (errno == ENOEXEC) {
603 char *tmp[BUFSIZ/sizeof(char *)];
604 if (loadquery(L_GETMESSAGES, tmp, sizeof(tmp)) == -1)
605 strcpy(errbuf, strerror(errno));
606 else {
607 char **p;
608 for (p = tmp; *p; p++)
609 caterr(*p);
610 }
611 } else
612 strcat(errbuf, strerror(errno));
613 return (void *) NULL;
614 }
615 mp->refCnt = 1;
616 mp->next = modList;
617 modList = mp;
618 if (loadbind(0, mainModule, mp->entry) == -1) {
619 dlclose(mp);
620 errvalid++;
621 strcpy(errbuf, "loadbind: ");
622 strcat(errbuf, strerror(errno));
623 return (void *) NULL;
624 }
625 /*
626 * If the user wants global binding, loadbind against all other
627 * loaded modules.
628 */
629 if (mode & RTLD_GLOBAL) {
630 register ModulePtr mp1;
631 for (mp1 = mp->next; mp1; mp1 = mp1->next)
632 if (loadbind(0, mp1->entry, mp->entry) == -1) {
633 dlclose(mp);
634 errvalid++;
635 strcpy(errbuf, "loadbind: ");
636 strcat(errbuf, strerror(errno));
637 return (void *) NULL;
638 }
639 }
640 if (readExports(mp) == -1) {
641 dlclose(mp);
642 return (void *) NULL;
643 }
644 /*
645 * If there is a dl_info structure, call the init function.
646 */
647 if (mp->info = (struct dl_info *)dlsym(mp, "dl_info")) {
648 if (mp->info->init)
649 (*mp->info->init)();
650 } else
651 errvalid = 0;
652 /*
653 * If the shared object was compiled using xlC we will need
654 * to call static constructors (and later on dlclose destructors).
655 */
656 if (mp->cdtors = (CdtorPtr)dlsym(mp, "__cdtors")) {
657 while (mp->cdtors->init) {
658 (*mp->cdtors->init)();
659 mp->cdtors++;
660 }
661 } else
662 errvalid = 0;
663 return (void *) mp;
664 }
665
666 /*
667 * Attempt to decipher an AIX loader error message and append it
668 * to our static error message buffer.
669 */
670 static void caterr(char *s)
671 {
672 register char *p = s;
673
674 while (*p >= '0' && *p <= '9')
675 p++;
676 switch(atoi(s)) {
677 case L_ERROR_TOOMANY:
678 strcat(errbuf, "to many errors");
679 break;
680 case L_ERROR_NOLIB:
681 strcat(errbuf, "can't load library");
682 strcat(errbuf, p);
683 break;
684 case L_ERROR_UNDEF:
685 strcat(errbuf, "can't find symbol");
686 strcat(errbuf, p);
687 break;
688 case L_ERROR_RLDBAD:
689 strcat(errbuf, "bad RLD");
690 strcat(errbuf, p);
691 break;
692 case L_ERROR_FORMAT:
693 strcat(errbuf, "bad exec format in");
694 strcat(errbuf, p);
695 break;
696 case L_ERROR_ERRNO:
697 strcat(errbuf, strerror(atoi(++p)));
698 break;
699 default:
700 strcat(errbuf, s);
701 break;
702 }
703 }
704
705 void *dlsym(void *handle, const char *symbol)
706 {
707 register ModulePtr mp = (ModulePtr)handle;
708 register ExportPtr ep;
709 register int i;
710
711 /*
712 * Could speed up the search, but I assume that one assigns
713 * the result to function pointers anyways.
714 */
715 for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
716 if (strcmp(ep->name, symbol) == 0)
717 return ep->addr;
718 errvalid++;
719 strcpy(errbuf, "dlsym: undefined symbol ");
720 strcat(errbuf, symbol);
721 return NULL;
722 }
723
724 char *dlerror(void)
725 {
726 if (errvalid) {
727 errvalid = 0;
728 return errbuf;
729 }
730 return NULL;
731 }
732
733 int dlclose(void *handle)
734 {
735 register ModulePtr mp = (ModulePtr)handle;
736 int result;
737 register ModulePtr mp1;
738
739 if (--mp->refCnt > 0)
740 return 0;
741 if (mp->info && mp->info->fini)
742 (*mp->info->fini)();
743 if (mp->cdtors)
744 while (mp->cdtors->term) {
745 (*mp->cdtors->term)();
746 mp->cdtors++;
747 }
748 result = unload(mp->entry);
749 if (result == -1) {
750 errvalid++;
751 strcpy(errbuf, strerror(errno));
752 }
753 if (mp->exports) {
754 register ExportPtr ep;
755 register int i;
756 for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
757 if (ep->name)
758 free(ep->name);
759 free(mp->exports);
760 }
761 if (mp == modList)
762 modList = mp->next;
763 else {
764 for (mp1 = modList; mp1; mp1 = mp1->next)
765 if (mp1->next == mp) {
766 mp1->next = mp->next;
767 break;
768 }
769 }
770 free(mp->name);
771 free(mp);
772 return result;
773 }
774
775 static void terminate(void)
776 {
777 while (modList)
778 dlclose(modList);
779 }
780
781 /*
782 * Build the export table from the XCOFF .loader section.
783 */
784 static int readExports(ModulePtr mp)
785 {
786 LDFILE *ldp = NULL;
787 SCNHDR sh, shdata;
788 LDHDR *lhp;
789 char *ldbuf;
790 LDSYM *ls;
791 int i;
792 ExportPtr ep;
793
794 if ((ldp = ldopen(mp->name, ldp)) == NULL) {
795 struct ld_info *lp;
796 char *buf;
797 int size = 4*1024;
798 if (errno != ENOENT) {
799 errvalid++;
800 strcpy(errbuf, "readExports: ");
801 strcat(errbuf, strerror(errno));
802 return -1;
803 }
804 /*
805 * The module might be loaded due to the LIBPATH
806 * environment variable. Search for the loaded
807 * module using L_GETINFO.
808 */
809 if ((buf = malloc(size)) == NULL) {
810 errvalid++;
811 strcpy(errbuf, "readExports: ");
812 strcat(errbuf, strerror(errno));
813 return -1;
814 }
815 while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
816 free(buf);
817 size += 4*1024;
818 if ((buf = malloc(size)) == NULL) {
819 errvalid++;
820 strcpy(errbuf, "readExports: ");
821 strcat(errbuf, strerror(errno));
822 return -1;
823 }
824 }
825 if (i == -1) {
826 errvalid++;
827 strcpy(errbuf, "readExports: ");
828 strcat(errbuf, strerror(errno));
829 free(buf);
830 return -1;
831 }
832 /*
833 * Traverse the list of loaded modules. The entry point
834 * returned by load() does actually point to the data
835 * segment origin.
836 */
837 lp = (struct ld_info *)buf;
838 while (lp) {
839 if (lp->ldinfo_dataorg == mp->entry) {
840 ldp = ldopen(lp->ldinfo_filename, ldp);
841 break;
842 }
843 if (lp->ldinfo_next == 0)
844 lp = NULL;
845 else
846 lp = (struct ld_info *)((char *)lp + lp->ldinfo_next);
847 }
848 free(buf);
849 if (!ldp) {
850 errvalid++;
851 strcpy(errbuf, "readExports: ");
852 strcat(errbuf, strerror(errno));
853 return -1;
854 }
855 }
856 if (TYPE(ldp) != U802TOCMAGIC) {
857 errvalid++;
858 strcpy(errbuf, "readExports: bad magic");
859 while(ldclose(ldp) == FAILURE)
860 ;
861 return -1;
862 }
863 /*
864 * Get the padding for the data section. This is needed for
865 * AIX 4.1 compilers. This is used when building the final
866 * function pointer to the exported symbol.
867 */
868 if (ldnshread(ldp, _DATA, &shdata) != SUCCESS) {
869 errvalid++;
870 strcpy(errbuf, "readExports: cannot read data section header");
871 while(ldclose(ldp) == FAILURE)
872 ;
873 return -1;
874 }
875 if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) {
876 errvalid++;
877 strcpy(errbuf, "readExports: cannot read loader section header");
878 while(ldclose(ldp) == FAILURE)
879 ;
880 return -1;
881 }
882 /*
883 * We read the complete loader section in one chunk, this makes
884 * finding long symbol names residing in the string table easier.
885 */
886 if ((ldbuf = (char *)malloc(sh.s_size)) == NULL) {
887 errvalid++;
888 strcpy(errbuf, "readExports: ");
889 strcat(errbuf, strerror(errno));
890 while(ldclose(ldp) == FAILURE)
891 ;
892 return -1;
893 }
894 if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) {
895 errvalid++;
896 strcpy(errbuf, "readExports: cannot seek to loader section");
897 free(ldbuf);
898 while(ldclose(ldp) == FAILURE)
899 ;
900 return -1;
901 }
902 if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) {
903 errvalid++;
904 strcpy(errbuf, "readExports: cannot read loader section");
905 free(ldbuf);
906 while(ldclose(ldp) == FAILURE)
907 ;
908 return -1;
909 }
910 lhp = (LDHDR *)ldbuf;
911 ls = (LDSYM *)(ldbuf+LDHDRSZ);
912 /*
913 * Count the number of exports to include in our export table.
914 */
915 for (i = lhp->l_nsyms; i; i--, ls++) {
916 if (!LDR_EXPORT(*ls))
917 continue;
918 mp->nExports++;
919 }
920 if ((mp->exports = (ExportPtr)calloc(mp->nExports, sizeof(*mp->exports))) == NULL) {
921 errvalid++;
922 strcpy(errbuf, "readExports: ");
923 strcat(errbuf, strerror(errno));
924 free(ldbuf);
925 while(ldclose(ldp) == FAILURE)
926 ;
927 return -1;
928 }
929 /*
930 * Fill in the export table. All entries are relative to
931 * the entry point we got from load.
932 */
933 ep = mp->exports;
934 ls = (LDSYM *)(ldbuf+LDHDRSZ);
935 for (i = lhp->l_nsyms; i; i--, ls++) {
936 char *symname;
937 char tmpsym[SYMNMLEN+1];
938 if (!LDR_EXPORT(*ls))
939 continue;
940 if (ls->l_zeroes == 0)
941 symname = ls->l_offset+lhp->l_stoff+ldbuf;
942 else {
943 /*
944 * The l_name member is not zero terminated, we
945 * must copy the first SYMNMLEN chars and make
946 * sure we have a zero byte at the end.
947 */
948 strncpy(tmpsym, ls->l_name, SYMNMLEN);
949 tmpsym[SYMNMLEN] = '\0';
950 symname = tmpsym;
951 }
952 ep->name = malloc((unsigned) (strlen(symname) + 1));
953 strcpy(ep->name, symname);
954 ep->addr = (void *)((unsigned long)mp->entry +
955 ls->l_value - shdata.s_vaddr);
956 ep++;
957 }
958 free(ldbuf);
959 while(ldclose(ldp) == FAILURE)
960 ;
961 return 0;
962 }
963
964 /*
965 * Find the main modules entry point. This is used as export pointer
966 * for loadbind() to be able to resolve references to the main part.
967 */
968 static void * findMain(void)
969 {
970 struct ld_info *lp;
971 char *buf;
972 int size = 4*1024;
973 int i;
974 void *ret;
975
976 if ((buf = malloc(size)) == NULL) {
977 errvalid++;
978 strcpy(errbuf, "findMain: ");
979 strcat(errbuf, strerror(errno));
980 return NULL;
981 }
982 while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
983 free(buf);
984 size += 4*1024;
985 if ((buf = malloc(size)) == NULL) {
986 errvalid++;
987 strcpy(errbuf, "findMain: ");
988 strcat(errbuf, strerror(errno));
989 return NULL;
990 }
991 }
992 if (i == -1) {
993 errvalid++;
994 strcpy(errbuf, "findMain: ");
995 strcat(errbuf, strerror(errno));
996 free(buf);
997 return NULL;
998 }
999 /*
1000 * The first entry is the main module. The entry point
1001 * returned by load() does actually point to the data
1002 * segment origin.
1003 */
1004 lp = (struct ld_info *)buf;
1005 ret = lp->ldinfo_dataorg;
1006 free(buf);
1007 return ret;
1008 }
1009
1010 #endif /* __dlfcn_h__ */
1011
1012 #endif /* solaris or aix dlfcn */
1013
1014 /*
1015 ???
1016 */
1017 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
1018 {
1019 #define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
1020 void *xlib;
1021 int (*install)() = NULL;
1022
1023 if (NULL == path) {
1024 FPRINTF(stderr,"Asc_DynamicLoad failed: Null path\n");
1025 return 1;
1026 }
1027
1028 AscCheckDuplicateLoad(path); /* whine if we've see it before */
1029
1030 /*
1031 * If the named library does not exist, if it's not loadable or if
1032 * it does not define the named install proc, report an error
1033 */
1034 xlib = dlopen(path, 1);
1035 if (xlib == NULL) {
1036 FPRINTF(stderr,"%s\n",(char *)dlerror());
1037 return 1;
1038 }
1039 if (NULL != initFun) {
1040 install = (int (*)())dlsym(xlib, initFun);
1041 if (install == NULL) {
1042 FPRINTF(stderr,"%s\n",(char *)dlerror());
1043 dlclose(xlib);
1044 return 1;
1045 }
1046 }
1047
1048 if (0 != AscAddRecord(xlib,path)) {
1049 FPRINTF(stderr,"Asc_DynamicLoad failed to record library (%s)\n",path);
1050 }
1051 return (install == NULL) ? 0 : (*install)();
1052 }
1053
1054 int DynamicLoad(CONST char *path, CONST char *initFun)
1055 {
1056 void *xlib;
1057 int (*install)() = NULL;
1058
1059 if (NULL == path) {
1060 FPRINTF(stderr,"DynamicLoad failed: Null path\n");
1061 return 1;
1062 }
1063
1064 /*
1065 * If the named library does not exist, if it's not loadable or if
1066 * it does not define the named install proc, report an error
1067 */
1068 xlib = dlopen(path, 1);
1069 if (xlib == NULL) {
1070 FPRINTF(stderr,"%s\n",(char *)dlerror());
1071 return 1;
1072 }
1073 if (NULL != initFun) {
1074 install = (int (*)())dlsym(xlib, initFun);
1075 if (install == NULL) {
1076 FPRINTF(stderr,"%s\n",(char *)dlerror());
1077 dlclose(xlib);
1078 return 1;
1079 }
1080 }
1081
1082 /* Try to install the extension and report success or failure */
1083 return (install == NULL) ? 0 : (*install)();
1084 }
1085 #endif /* solaris, aix */
1086
1087
1088 #ifdef _SGI_SOURCE
1089 #include <dlfcn.h>
1090 /*
1091 SGI
1092 */
1093 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
1094 {
1095 #define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
1096 void *xlib;
1097 int (*install)() = NULL;
1098
1099 if (NULL == path) {
1100 FPRINTF(stderr,"Asc_DynamicLoad failed: Null path\n");
1101 return 1;
1102 }
1103
1104 AscCheckDuplicateLoad(path); /* whine if we've see it before */
1105
1106 /*
1107 * If the named library does not exist, if it's not loadable or if
1108 * it does not define the named install proc, report an error
1109 */
1110 xlib = dlopen(path, 1);
1111 if (xlib == NULL) {
1112 FPRINTF(stderr,"%s\n",(char *)dlerror());
1113 return 1;
1114 }
1115 if (NULL != initFun) {
1116 install = (int (*)())dlsym(xlib, initFun);
1117 if (install == NULL) {
1118 FPRINTF(stderr,"%s\n",(char *)dlerror());
1119 dlclose(xlib);
1120 return 1;
1121 }
1122 }
1123
1124 if (0 != AscAddRecord(xlib,path)) {
1125 FPRINTF(stderr,"Asc_DynamicLoad failed to record library (%s)\n",path);
1126 }
1127 return (install == NULL) ? 0 : (*install)();
1128 }
1129
1130 int DynamicLoad(CONST char *path, CONST char *initFun)
1131 {
1132 void *xlib;
1133 int (*install)() = NULL;
1134
1135 if (NULL == path) {
1136 FPRINTF(stderr,"DynamicLoad failed: Null path\n");
1137 return 1;
1138 }
1139
1140 /*
1141 * If the named library does not exist, if it's not loadable or if
1142 * it does not define the named install proc, report an error
1143 */
1144 xlib = dlopen(path, 1);
1145 if (xlib == NULL) {
1146 FPRINTF(stderr,"%s\n",(char *)dlerror());
1147 return 1;
1148 }
1149 if (NULL != initFun) {
1150 install = (int (*)())dlsym(xlib, initFun);
1151 if (install == NULL) {
1152 FPRINTF(stderr,"%s\n",(char *)dlerror());
1153 dlclose(xlib);
1154 return 1;
1155 }
1156 }
1157 /* Try to install the extension and report success or failure */
1158 return (install == NULL) ? 0 : (*install)();
1159 }
1160 #endif /* _SGI_SOURCE */
1161
1162
1163 #ifdef __hpux
1164 /*
1165 * Modified to work with HP/UX 9.X Operating System.
1166 * Michael Moore (mdm@cis.ohio-state.edu)
1167 * December 24th, 1993.
1168 * Further modified by Kirk Abbott (ka0p@edrc.cmu.edu)
1169 * to fit in with the ASCEND system.
1170 */
1171
1172 #include <dl.h>
1173 #include <errno.h>
1174
1175 /*
1176 HPUX
1177 */
1178 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
1179 {
1180 #define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
1181 shl_t xlib;
1182 int (*install)() = NULL;
1183 int i;
1184
1185 if (NULL == path) {
1186 FPRINTF(stderr,"Asc_DynamicLoad failed: Null path\n");
1187 return 1;
1188 }
1189
1190 AscCheckDuplicateLoad(path); /* whine if we've see it before */
1191
1192 /*
1193 * If the named library does not exist, if it's not loadable or if
1194 * it does not define the named install proc, report an error
1195 */
1196 xlib = shl_load(path, BIND_IMMEDIATE | BIND_VERBOSE, 0L);
1197 if (xlib == (shl_t) NULL) {
1198 FPRINTF(stderr,"Unable to load shared library : %s\n",strerror(errno));
1199 return 1;
1200 }
1201 if (NULL != initFun) {
1202 i = shl_findsym(&xlib, initFun, TYPE_PROCEDURE, &install);
1203 if (i == -1) {
1204 FPRINTF(stderr,"Unable to find needed symbol %s %s\n",
1205 initFun, strerror(errno));
1206 shl_unload(xlib); /* baa */
1207 return 1;
1208 }
1209 if (install == NULL) {
1210 FPRINTF(stderr,"Unable to find needed symbol %s\n",initFun);
1211 FPRINTF(stderr,"Error type unknown\n");
1212 shl_unload(xlib); /* baa */
1213 return 1;
1214 }
1215 }
1216 if (0 != AscAddRecord(xlib,path)) {
1217 FPRINTF(stderr,"Asc_DynamicLoad failed to record library (%s)\n",path);
1218 }
1219 return (install == NULL) ? 0 : (*install)();
1220 }
1221
1222 int DynamicLoad(CONST char *path, CONST char *initFun)
1223 {
1224 shl_t xlib;
1225 int (*install)() = NULL;
1226 int i;
1227
1228 if (NULL == path) {
1229 FPRINTF(stderr,"DynamicLoad failed: Null path\n");
1230 return 1;
1231 }
1232
1233 /*
1234 * If the named library does not exist, if it's not loadable or if
1235 * it does not define the named install proc, report an error
1236 */
1237 xlib = shl_load(path, BIND_IMMEDIATE | BIND_VERBOSE, 0L);
1238 if (xlib == (shl_t) NULL) {
1239 FPRINTF(stderr,"Unable to load shared library : %s\n",strerror(errno));
1240 return 1;
1241 }
1242 i = shl_findsym(&xlib, initFun, TYPE_PROCEDURE, &install);
1243 if (i == -1) {
1244 FPRINTF(stderr,"Unable to find needed symbol %s %s\n",
1245 initFun, strerror(errno));
1246 return 1;
1247 }
1248 if (install == NULL) {
1249 FPRINTF(stderr,"Unable to find needed symbol %s\n",initFun);
1250 FPRINTF(stderr,"Error type unknown\n");
1251 return 1;
1252 }
1253 /*
1254 * Try to install the extension and report success or failure
1255 */
1256 return (install == NULL) ? 0 : (*install)();
1257 }
1258 #endif /* __hpux */
1259
1260
1261
1262 #ifdef ultrix
1263 /*
1264 * Ultrix 4.x Dynamic Loader Library Version 1.0
1265 *
1266 * dl.h--
1267 * header file for the Dynamic Loader Library
1268 *
1269 *
1270 * Copyright (c) 1993 Andrew K. Yu, University of California at Berkeley
1271 * All rights reserved.
1272 *
1273 * Permission to use, copy, modify, and distribute this software and its
1274 * documentation for educational, research, and non-profit purposes and
1275 * without fee is hereby granted, provided that the above copyright
1276 * notice appear in all copies and that both that copyright notice and
1277 * this permission notice appear in supporting documentation. Permission
1278 * to incorporate this software into commercial products can be obtained
1279 * from the author. The University of California and the author make
1280 * no representations about the suitability of this software for any
1281 * purpose. It is provided "as is" without express or implied warranty.
1282 *
1283 */
1284 #include <filehdr.h>
1285 #include <syms.h>
1286 #include <reloc.h>
1287 #include <scnhdr.h>
1288 #include <fcntl.h>
1289 #include <ar.h>
1290
1291 typedef long CoreAddr;
1292
1293
1294 typedef struct ScnInfo {
1295 CoreAddr addr; /* starting address of the section */
1296 SCNHDR hdr; /* section header */
1297 RELOC *relocEntries; /* relocation entries */
1298 } ScnInfo;
1299
1300 typedef enum {
1301 DL_NEEDRELOC, /* still need relocation */
1302 DL_RELOCATED, /* no relocation necessary */
1303 DL_INPROG /* relocation in progress */
1304 } dlRStatus;
1305
1306 typedef struct JmpTbl {
1307 char *block; /* the jump table memory block */
1308 struct JmpTbl *next; /* next block */
1309 } JmpTbl;
1310
1311 typedef struct dlFile {
1312 char *filename; /* file name of the object file */
1313
1314 int textSize; /* used by mprotect */
1315 CoreAddr textAddress; /* start addr of text section */
1316 long textVaddr; /* vaddr of text section in obj file */
1317 CoreAddr rdataAddress; /* start addr of rdata section */
1318 long rdataVaddr; /* vaddr of text section in obj file */
1319 CoreAddr dataAddress; /* start addr of data section */
1320 long dataVaddr; /* vaddr of text section in obj file */
1321 CoreAddr bssAddress; /* start addr of bss section */
1322 long bssVaddr; /* vaddr of text section in obj file */
1323
1324 int nsect; /* number of sections */
1325 ScnInfo *sect; /* details of each section (array) */
1326
1327 int issExtMax; /* size of string space */
1328 char *extss; /* extern sym string space (in core) */
1329 int iextMax; /* maximum number of Symbols */
1330 pEXTR extsyms; /* extern syms */
1331
1332 dlRStatus relocStatus; /* what relocation needed? */
1333 int needReloc;
1334
1335 JmpTbl *jmptable; /* the jump table for R_JMPADDR */
1336
1337 struct dlFile *next; /* next member of the archive */
1338 } dlFile;
1339
1340 typedef struct dlSymbol {
1341 char *name; /* name of the symbol */
1342 long addr; /* address of the symbol */
1343 dlFile *objFile; /* from which file */
1344 } dlSymbol;
1345
1346 /*
1347 * prototypes for the dl* interface
1348 */
1349 extern void *dlopen(/* char *filename, int mode */);
1350 extern void *dlsym(/* void *handle, char *name */);
1351 extern void dlclose(/* void *handle */);
1352 extern char *dlerror(/* void */);
1353
1354 #define DL_LAZY 0 /* lazy resolution */
1355 #define DL_NOW 1 /* immediate resolution */
1356
1357 /*
1358 * Miscellaneous utility routines:
1359 */
1360 extern char **dl_undefinedSymbols(/* int *count */);
1361 extern void dl_printAllSymbols(/* void *handle */);
1362 extern void dl_setLibraries(/* char *libs */);
1363
1364 /* here we are in ultrix land */
1365 /*
1366 ULTRIX
1367 */
1368 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
1369 {
1370 #define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
1371 void *xlib;
1372 int (*install)() = NULL;
1373
1374 if (NULL == path) {
1375 FPRINTF(stderr,"Asc_DynamicLoad failed: Null path\n");
1376 return 1;
1377 }
1378
1379 AscCheckDuplicateLoad(path); /* whine if we've see it before */
1380 /*
1381 * If the named library does not exist, if it's not loadable or if
1382 * it does not define the named install proc, report an error
1383 */
1384 xlib = dlopen(path, 1);
1385 install = (int (*)())dlsym(xlib, initFun);
1386 if ((xlib == NULL) || (install==NULL)) {
1387 FPRINTF(stderr,"%s\n",(char *)dlerror());
1388 if ( xlib != NULL ) dlclose(xlib);
1389 return 1;
1390 }
1391 if (0 != AscAddRecord(xlib,path)) {
1392 FPRINTF(stderr,"Asc_DynamicLoad failed to record library (%s)\n",path);
1393 }
1394 return (install == NULL) ? 0 : (*install)();
1395 }
1396 /*
1397 * This is where we put a wrapper around all of the
1398 * ultrix based dynamic loading code.
1399 */
1400 int DynamicLoad(CONST char *path, CONST char *initFun)
1401 {
1402 void *xlib;
1403 int (*install)() = NULL;
1404
1405 if (NULL == path) {
1406 FPRINTF(stderr,"DynamicLoad failed: Null path\n");
1407 return 1;
1408 }
1409
1410 /*
1411 * If the named library does not exist, if it's not loadable or if
1412 * it does not define the named install proc, report an error
1413 */
1414 xlib = dlopen(path, 1);
1415 install = (int (*)())dlsym(xlib, initFun);
1416 if ((xlib == NULL) || (install==NULL)) {
1417 FPRINTF(stderr,"%s\n",(char *)dlerror());
1418 if ( xlib != NULL ) dlclose(xlib);
1419 return 1;
1420 }
1421 /* Try to install the extension and report success or failure */
1422 return (install == NULL) ? 0 : (*install)();
1423 }
1424
1425
1426 /*
1427 * dlPriv.h--
1428 * the Private header file for the Dynamic Loader Library. Normal
1429 * users should have no need to include this file.
1430 *
1431 *
1432 * Copyright (c) 1993 Andrew K. Yu, University of California at Berkeley
1433 * All rights reserved.
1434 *
1435 * Permission to use, copy, modify, and distribute this software and its
1436 * documentation for educational, research, and non-profit purposes and
1437 * without fee is hereby granted, provided that the above copyright
1438 * notice appear in all copies and that both that copyright notice and
1439 * this permission notice appear in supporting documentation. Permission
1440 * to incorporate this software into commercial products can be obtained
1441 * from the author. The University of California and the author make
1442 * no representations about the suitability of this software for any
1443 * purpose. It is provided "as is" without express or implied warranty.
1444 *
1445 */
1446
1447 extern dlSymbol *dl_hashSearchSymbol();
1448 extern dlSymbol *dl_hashInsertSymbolStrIdx();
1449
1450 #define STRCOPY(x) (char *)strcpy((char *)malloc(strlen(x)+1), x)
1451
1452 #define HASHTABSZ 1001
1453
1454 typedef struct HEnt_ {
1455 dlSymbol *symbol;
1456 struct HEnt_ *next;
1457 } HEnt;
1458
1459 typedef struct JmpTblHdr {
1460 int current; /* current empty slot */
1461 int max; /* max no. of slots */
1462 int dummy[2]; /* padding to make this 4 words */
1463 } JmpTblHdr;
1464
1465 extern HEnt **dlHashTable;
1466 extern int _dl_undefinedSymbolCount;
1467
1468 extern dlFile *_dl_openObject();
1469 extern void _dl_closeObject();
1470
1471 extern int _dl_loadSections();
1472 extern int _dl_loadSymbols();
1473
1474 dlFile *_dl_loadEntireArchive();
1475
1476
1477
1478 /*
1479 * dlArch.c--
1480 * handles loading of library archives.
1481 *
1482 *
1483 * Copyright (c) 1993 Andrew K. Yu, University of California at Berkeley
1484 * All rights reserved.
1485 *
1486 * Permission to use, copy, modify, and distribute this software and its
1487 * documentation for educational, research, and non-profit purposes and
1488 * without fee is hereby granted, provided that the above copyright
1489 * notice appear in all copies and that both that copyright notice and
1490 * this permission notice appear in supporting documentation. Permission
1491 * to incorporate this software into commercial products can be obtained
1492 * from the author. The University of California and the author make
1493 * no representations about the suitability of this software for any
1494 * purpose. It is provided "as is" without express or implied warranty.
1495 *
1496 */
1497 #include <stdio.h>
1498 #include <strings.h>
1499 /* #include <sys/types.h> */
1500 /* #include <sys/stat.h> */
1501
1502 /*
1503 * Sometimes, you might want to have undefined symbols searched from
1504 * standard libraries like libc.a and libm.a automatically. dl_setLibraries
1505 * is the interface to do this. dl_stdLibraries contain an arrary of
1506 * strings specifying the libraries to be searched.
1507 */
1508 char **dl_stdLibraries= NULL;
1509
1510 static int searchArchive();
1511 static int readArchiveRanlibs();
1512 static int archGetObjectName();
1513 static int archLoadObject();
1514 static int loadArchSections();
1515
1516 /*****************************************************************************
1517 * *
1518 * Searching of pre-set libraries *
1519 * *
1520 *****************************************************************************/
1521
1522 /*
1523 * dl_searchLibraries returns 1 if undefined symbols are found during the
1524 * searching. 0 otherwise.
1525 */
1526 int dl_searchLibraries()
1527 {
1528 char **libs= dl_stdLibraries;
1529 int result= 0;
1530
1531 if (dl_stdLibraries && _dl_undefinedSymbolCount) {
1532 while(*libs) {
1533 result|= searchArchive(*libs);
1534 libs++;
1535 }
1536 }
1537 return (result);
1538 }
1539
1540 /*
1541 * dl_setLibraries--
1542 * takes a string of the form <library>[:<library> ... ] which
1543 * specifies the libraries to be searched automatically when there are
1544 * undefined symbols.
1545 *
1546 * eg. dl_setLibraries("/usr/lib/libc_G0.a:/usr/lib/libm_G0.a");
1547 */
1548 void dl_setLibraries( libs )
1549 char *libs;
1550 {
1551 char *name, *t;
1552 char **stnlib;
1553 int numlibs= 0;
1554 int maxlibs= 4;
1555
1556 if(!libs)
1557 return;
1558 stnlib= (char **)malloc(sizeof(char *) * maxlibs);
1559 name=t= libs;
1560 while(*t!='\0') {
1561 while(*t!=':' && *t!='\0')
1562 t++;
1563 if (t-name>0) {
1564 stnlib[numlibs]= strncpy((char*)malloc(t-name+1),name,t-name);
1565 stnlib[numlibs++][t-name]='\0';
1566 if(numlibs==maxlibs-1) {
1567 maxlibs*= 2;
1568 stnlib= (char **)realloc(stnlib, sizeof(char *) * maxlibs);
1569 }
1570 }
1571 if (*t==':') {
1572 t++;
1573 name= t;
1574 }
1575 }
1576 stnlib[numlibs]= NULL;
1577 if (dl_stdLibraries) {
1578 char **s= dl_stdLibraries;
1579 while(*s!=NULL) {
1580 free(*s);
1581 s++;
1582 }
1583 free(dl_stdLibraries);
1584 }
1585 dl_stdLibraries= stnlib;
1586
1587 return;
1588 }
1589
1590 /*****************************************************************************
1591 * *
1592 * Internal Rountines *
1593 * *
1594 *****************************************************************************/
1595
1596 static int searchArchive( archname )
1597 char *archname;
1598 {
1599 int found= 0, done;
1600 struct ranlib *pran;
1601 char *pstr;
1602 int i;
1603 int fd;
1604
1605 /*
1606 * opens the archive file and reads in the ranlib hashtable
1607 */
1608 if ((fd=readArchiveRanlibs(archname, &pran, &pstr)) < 0) {
1609 FPRINTF(stderr, "dl: cannot open \"%s\"", archname);
1610 return 0;
1611 }
1612 /*
1613 * look through our symbol hash table and see if we find anything.
1614 * We have to scan until no undefined symbols can be found in the
1615 * archive. (Note that bringing in an object file might require another
1616 * object file in the archive. We'll have missed the symbol if we
1617 * do this one pass and the symbol happens to be inserted into buckets
1618 * we've examined already.)
1619 */
1620 do {
1621 done= 1;
1622 for(i=0; i < HASHTABSZ; i++) {
1623 HEnt *ent= dlHashTable[i];
1624 struct ranlib *r;
1625 while(ent) {
1626 if (!ent->symbol->objFile) {
1627 r= (struct ranlib *)ranlookup(ent->symbol->name);
1628 if (r->ran_off) {
1629 /*
1630 * we've found the undefined symbol in the archive
1631 */
1632 #if DEBUG
1633 PRINTF("*** found %s in ", ent->symbol->name);
1634 #endif
1635 if (archLoadObject(fd, r->ran_off)) {
1636 found= 1;
1637 done= 0;
1638 }
1639 }
1640 }
1641 ent=ent->next;
1642 }
1643 }
1644 } while (!done);
1645 /*
1646 * be a good citizen.
1647 */
1648 free(pran);
1649 free(pstr);
1650 close(fd);
1651
1652 return found;
1653 }
1654
1655 /*
1656 * readArchiveRanlibs--
1657 * opens a library and reads in the ranlib hash table and its
1658 * associated string table. It returns -1 if fails, the opened
1659 * file descriptor otherwise. It also inits the ranhashtable.
1660 */
1661 static int readArchiveRanlibs( archfile, pran, pstr )
1662 char *archfile; struct ranlib **pran; char **pstr;
1663 {
1664 int numRanlibs, numStrings;
1665 struct ranlib *ranlibs;
1666 char *strings;
1667 ARHDR ar_hdr;
1668 int fd, size;
1669 char mag[SARMAG];
1670
1671 *pran= NULL;
1672 *pstr= NULL;
1673 /*
1674 * opens the library and check the magic string
1675 */
1676 if ((fd= open(archfile, O_RDONLY)) < 0 ||
1677 read(fd, mag, SARMAG)!=SARMAG ||
1678 strncmp(mag, ARMAG, SARMAG)!=0) {
1679 close(fd);
1680 return -1;
1681 }
1682 /*
1683 * reads in the archive header (not used) and the number of ranlibs.
1684 */
1685 if (read(fd, &ar_hdr, sizeof(ARHDR))!=sizeof(ARHDR) ||
1686 read(fd, &numRanlibs, sizeof(int))!= sizeof(int)) {
1687 close(fd);
1688 return -1;
1689 }
1690 /*
1691 * reads in the ranlib hash table and the string table size.
1692 */
1693 size= sizeof(struct ranlib)*numRanlibs;
1694 ranlibs= (struct ranlib *)malloc(size);
1695 if (read(fd, ranlibs, size)!=size ||
1696 read(fd, &numStrings, sizeof(int))!=sizeof(int)) {
1697 close(fd);
1698 return -1;
1699 }
1700 /*
1701 * reads in the string table.
1702 */
1703 strings= (char *)malloc(numStrings);
1704 if (read(fd, strings, numStrings)!=numStrings) {
1705 close(fd);
1706 return -1;
1707 }
1708 *pran= ranlibs;
1709 *pstr= strings;
1710 ranhashinit(ranlibs, strings, numRanlibs);
1711 return fd;
1712 }
1713
1714 static int archLoadObject( fd, offset )
1715 int fd; int offset;
1716 {
1717 dlFile *dlfile;
1718 FILHDR filhdr;
1719 ARHDR arhdr;
1720 char ar_name[17];
1721
1722 if (lseek(fd, offset, SEEK_SET)==-1 ||
1723 read(fd, &arhdr, sizeof(ARHDR))!=sizeof(ARHDR) ||
1724 read(fd, &filhdr, sizeof(filhdr))!=sizeof(filhdr))
1725 return 0;
1726 sscanf(arhdr.ar_name, "%16s", ar_name);
1727 ar_name[16]='\0';
1728 #if DEBUG
1729 PRINTF("%.16s\n", ar_name);
1730 #endif
1731
1732 dlfile= (dlFile *)malloc(sizeof(dlFile));
1733 bzero(dlfile, sizeof(dlFile));
1734 dlfile->filename= STRCOPY(ar_name);
1735 dlfile->relocStatus= DL_NEEDRELOC;
1736
1737 if (!_dl_loadSymbols(dlfile, fd, filhdr, offset+sizeof(ARHDR)) ||
1738 !_dl_loadSections(dlfile, fd, offset+sizeof(ARHDR))) {
1739 _dl_closeObject(dlfile);
1740 return 0;
1741 }
1742
1743 if (!_dl_enterExternRef(dlfile)) {
1744 _dl_closeObject(dlfile);
1745 return 0;
1746 }
1747
1748 /*
1749 * need to relocate now and see if we need to bring in more files.
1750 */
1751 _dl_relocateSections(dlfile);
1752
1753 return 1;
1754 }
1755
1756 dlFile *_dl_loadEntireArchive( filename, fd )
1757 char *filename; int fd;
1758 {
1759 dlFile *dlfile, *df;
1760 int offset;
1761 FILHDR filhdr;
1762 ARHDR arhdr;
1763 int size;
1764 struct stat stat_buf;
1765
1766 /*
1767 * read in the header of the symbol list (the so-called symdef)
1768 */
1769 if (lseek(fd, SARMAG, SEEK_SET)==-1 ||
1770 read(fd, &arhdr, sizeof(arhdr))!=sizeof(arhdr)) {
1771 return 0;
1772 }
1773 /*
1774 * go after each member of the archive:
1775 */
1776 fstat(fd, &stat_buf);
1777 sscanf(arhdr.ar_size, "%d", &size);
1778 offset= SARMAG + sizeof(ARHDR) + size;
1779 dlfile= NULL;
1780 while( offset < stat_buf.st_size) {
1781 if (!lseek(fd, offset, SEEK_SET)==-1 ||
1782 read(fd, &arhdr, sizeof(arhdr))!=sizeof(arhdr) ||
1783 read(fd, &filhdr, sizeof(filhdr))!=sizeof(filhdr)) {
1784 _dl_closeObject(dlfile);
1785 return NULL;
1786 }
1787 offset+= sizeof(ARHDR);
1788 if (!(df=_dl_openObject(fd, filename, filhdr, offset, DL_LAZY))) {
1789 _dl_closeObject(dlfile);
1790 return NULL;
1791 }
1792 sscanf(arhdr.ar_size, "%d", &size);
1793 offset+= size;
1794 df->next= dlfile;
1795 dlfile= df;
1796 }
1797
1798 return dlfile;
1799 }
1800
1801 /*
1802 * dlRef.c--
1803 * handles symbol references
1804 *
1805 *
1806 * Copyright (c) 1993 Andrew K. Yu, University of California at Berkeley
1807 * All rights reserved.
1808 *
1809 * Permission to use, copy, modify, and distribute this software and its
1810 * documentation for educational, research, and non-profit purposes and
1811 * without fee is hereby granted, provided that the above copyright
1812 * notice appear in all copies and that both that copyright notice and
1813 * this permission notice appear in supporting documentation. Permission
1814 * to incorporate this software into commercial products can be obtained
1815 * from the author. The University of California and the author make
1816 * no representations about the suitability of this software for any
1817 * purpose. It is provided "as is" without express or implied warranty.
1818 *
1819 */
1820
1821 HEnt **dlHashTable; /* hash table for the symbols */
1822 int _dl_undefinedSymbolCount= 0; /* number of undefined symbols */
1823
1824 static unsigned hash();
1825
1826 /*****************************************************************************
1827 * *
1828 * Hash Table for symbols *
1829 * *
1830 *****************************************************************************/
1831
1832 /*
1833 * hash is taken from Robert Sedgewick's "Algorithms in C" (p.233). Okay, so
1834 * this is not the most sophisticated hash function in the world but this
1835 * will do the job quite nicely.
1836 */
1837 static unsigned hash( str )
1838 char *str;
1839 {
1840 int h;
1841 for(h=0; *str!='\0'; str++)
1842 h = (64*h + *str) % HASHTABSZ;
1843 return h;
1844 }
1845
1846 void _dl_hashInit()
1847 {
1848 dlHashTable= (HEnt **)malloc(sizeof(HEnt *) * HASHTABSZ);
1849 bzero(dlHashTable, sizeof(HEnt *) * HASHTABSZ);
1850 return;
1851 }
1852
1853 dlSymbol *dl_hashInsertSymbolStrIdx( extSs, idx, found )
1854 char *extSs; long idx; int *found;
1855 {
1856 dlSymbol *symbol;
1857 char *symname= extSs + idx;
1858 int hval= hash(symname);
1859 HEnt *ent, *prev, *e;
1860
1861 prev= e= dlHashTable[hval];
1862 while(e) {
1863 if(!strcmp(e->symbol->name, symname)) {
1864 *found= 1;
1865 return (e->symbol); /* return existing symbol */
1866 }
1867 prev= e;
1868 e= e->next;
1869 }
1870 ent= (HEnt *)malloc(sizeof(HEnt));
1871 symbol= (dlSymbol *)malloc(sizeof(dlSymbol));
1872 bzero(symbol, sizeof(dlSymbol));
1873 symbol->name= symname;
1874 ent->symbol= symbol;
1875 ent->next= NULL;
1876 if (!prev) {
1877 dlHashTable[hval]= ent;
1878 }else {
1879 prev->next= ent;
1880 }
1881 *found= 0;
1882 return symbol;
1883 }
1884
1885 dlSymbol *dl_hashSearchSymbol( symname )
1886 char *symname;
1887 {
1888 int hval= hash(symname);
1889 HEnt *ent= dlHashTable[hval];
1890 while(ent) {
1891 if(!strcmp(ent->symbol->name, symname))
1892 return ent->symbol;
1893 ent= ent->next;
1894 }
1895 return NULL;
1896 }
1897
1898 /*****************************************************************************
1899 * *
1900 * Entering External References *
1901 * *
1902 *****************************************************************************/
1903
1904 int _dl_enterInitialExternRef( dlfile )
1905 dlFile *dlfile;
1906 {
1907 char *extSs= dlfile->extss;
1908 pEXTR extsyms= dlfile->extsyms;
1909 dlSymbol *symbol;
1910 int i, found;
1911
1912 /*
1913 * this is done by init. Just enter the symbols and values:
1914 * (It cannot contain undefined symbols and the multiple defs.)
1915 */
1916 for(i=0; i < dlfile->iextMax ; i++) {
1917 pEXTR esym= &extsyms[i];
1918
1919 symbol= dl_hashInsertSymbolStrIdx(extSs, esym->asym.iss, &found);
1920 if (found) {
1921 _dl_setErrmsg("init error: symbol \"%s\" multiply defined",
1922 extSs+esym->asym.iss);
1923 return 0;
1924 }
1925 symbol->addr= esym->asym.value;
1926 symbol->objFile= dlfile;
1927 }
1928 free(dlfile->extsyms);
1929 dlfile->extsyms= NULL;
1930 dlfile->iextMax= 0;
1931 return 1;
1932 }
1933
1934 int _dl_enterExternRef( dlfile )
1935 dlFile *dlfile;
1936 {
1937 int i;
1938 char *extSs= dlfile->extss;
1939 dlSymbol *symbol;
1940 int found;
1941 long textAddress= (long)dlfile->textAddress - dlfile->textVaddr;
1942 long rdataAddress= (long)dlfile->rdataAddress - dlfile->rdataVaddr;
1943 long dataAddress= (long)dlfile->dataAddress - dlfile->dataVaddr;
1944 long bssAddress= (long)dlfile->bssAddress - dlfile->bssVaddr;
1945
1946 for(i=0; i < dlfile->iextMax ; i++) {
1947 pEXTR esym= &dlfile->extsyms[i];
1948 int found;
1949
1950 if (esym->asym.sc!=scNil && esym->asym.sc!=scUndefined) {
1951 symbol= dl_hashInsertSymbolStrIdx(extSs, esym->asym.iss,
1952 &found);
1953 if (symbol->objFile!=NULL) {
1954 _dl_setErrmsg("\"%s\" multiply defined",
1955 extSs+esym->asym.iss);
1956 return 0;
1957 }
1958 if (found) {
1959 /*
1960 * finally, we now have the undefined symbol. (A kludge
1961 * here: the symbol name of the undefined symbol is
1962 * malloc'ed. We need to free it.)
1963 */
1964 free(symbol->name);
1965 symbol->name= extSs+esym->asym.iss;
1966 _dl_undefinedSymbolCount--;
1967 }
1968 switch(esym->asym.sc) {
1969 case scAbs:
1970 symbol->addr= esym->asym.value;
1971 break;
1972 case scText:
1973 symbol->addr= textAddress + esym->asym.value;
1974 break;
1975 case scData:
1976 symbol->addr= dataAddress + esym->asym.value;
1977 break;
1978 case scBss:
1979 symbol->addr= bssAddress + esym->asym.value;
1980 break;
1981 case scRData:
1982 symbol->addr= rdataAddress + esym->asym.value;
1983 break;
1984 case scCommon: {
1985 char *block= (char *)malloc(esym->asym.value);
1986 bzero(block, esym->asym.value);
1987 symbol->addr= (long)block;
1988 break;
1989 }
1990 default:
1991 FPRINTF(stderr, "dl: extern symbol in unexpected section (%d)\n",
1992 esym->asym.sc);
1993 break;
1994 }
1995 symbol->objFile= dlfile;
1996 }
1997 }
1998 return 1;
1999 }
2000
2001 /*****************************************************************************
2002 * *
2003 * Misc. utilities *
2004 * *
2005 *****************************************************************************/
2006
2007 /*
2008 * dl_undefinedSymbols--
2009 * returns the number of undefined symbols in count and an array of
2010 * strings of the undefined symbols. The last element of the array
2011 * is guaranteed to be NULL.
2012 */
2013 char **dl_undefinedSymbols( count )
2014 int *count;
2015 {
2016 char **syms= NULL;
2017 int i, j;
2018
2019 *count= _dl_undefinedSymbolCount;
2020 if (_dl_undefinedSymbolCount) {
2021 syms= (char **)malloc(sizeof(char *) * (_dl_undefinedSymbolCount+1));
2022 for(i=0, j=0; i<HASHTABSZ && j<_dl_undefinedSymbolCount; i++) {
2023 HEnt *ent= dlHashTable[i];
2024 while(ent) {
2025 if (!ent->symbol->objFile) {
2026 syms[j++]= STRCOPY(ent->symbol->name);
2027 if (j==_dl_undefinedSymbolCount)
2028 break;
2029 }
2030 ent=ent->next;
2031 }
2032 }
2033 syms[j]=NULL;
2034 }
2035 return syms;
2036 }
2037
2038 /*
2039 * dl_printAllSymbols--
2040 * aids debugging. Prints out symbols in the hash table that matches
2041 * the file handle. For library archives, prints those that matches
2042 * any member or the archive. A NULL handle matches everything.
2043 */
2044 void dl_printAllSymbols( handle )
2045 void *handle;
2046 {
2047 int i, count= 0;
2048
2049 for(i=0; i < HASHTABSZ; i++) {
2050 HEnt *ent= dlHashTable[i];
2051 while(ent) {
2052 if (!handle || handle==ent->symbol->objFile) {
2053 PRINTF("(%3d) %-20s addr=0x%x dlfile=0x%x\n",
2054 i, ent->symbol->name, ent->symbol->addr,
2055 ent->symbol->objFile);
2056 count++;
2057 }else if (((dlFile *)handle)->next) {
2058 dlFile *dlfile= ((dlFile *)handle)->next;
2059 while(dlfile) {
2060 if (dlfile==ent->symbol->objFile) {
2061 PRINTF("(%3d) %-20s addr=0x%x dlfile=0x%x\n",
2062 i, ent->symbol->name, ent->symbol->addr,
2063 ent->symbol->objFile);
2064 count++;
2065 }
2066 dlfile= dlfile->next;
2067 }
2068 }
2069 ent= ent->next;
2070 }
2071 }
2072 PRINTF("total number of symbols= %d\n", count);
2073 return;
2074 }
2075
2076
2077 /*
2078 * dlReloc.c--
2079 * handles the relocation
2080 *
2081 *
2082 * Copyright (c) 1993 Andrew K. Yu, University of California at Berkeley
2083 * All rights reserved.
2084 *
2085 * Permission to use, copy, modify, and distribute this software and its
2086 * documentation for educational, research, and non-profit purposes and
2087 * without fee is hereby granted, provided that the above copyright
2088 * notice appear in all copies and that both that copyright notice and
2089 * this permission notice appear in supporting documentation. Permission
2090 * to incorporate this software into commercial products can be obtained
2091 * from the author. The University of California and the author make
2092 * no representations about the suitability of this software for any
2093 * purpose. It is provided "as is" without express or implied warranty.
2094 *
2095 */
2096
2097 #include <sys/mman.h>
2098 #include <mips/cachectl.h>
2099
2100 static void patchLongjump();
2101 static void protectText();
2102
2103 int _dl_relocateSections(dlfile)
2104 dlFile *dlfile;
2105 {
2106 long textAddress= dlfile->textAddress - dlfile->textVaddr;
2107 long rdataAddress= dlfile->rdataAddress - dlfile->rdataVaddr;
2108 long dataAddress= dlfile->dataAddress - dlfile->dataVaddr;
2109 long bssAddress= dlfile->bssAddress - dlfile->bssVaddr;
2110 int i, j;
2111 int hasUndefined= 0;
2112 pEXTR extsyms= dlfile->extsyms;
2113 char *extSs= dlfile->extss;
2114
2115 if (dlfile->relocStatus==DL_RELOCATED) /* just in case */
2116 return 1;
2117
2118 /* prevent circular relocation */
2119 dlfile->relocStatus= DL_INPROG;
2120
2121 for(i=0; i < dlfile->nsect; i++) {
2122 SCNHDR *hdr= &(dlfile->sect[i].hdr);
2123 RELOC *relocEnt= dlfile->sect[i].relocEntries;
2124 long sectAddr= dlfile->sect[i].addr - hdr->s_vaddr;
2125 long relocAddr;
2126 int *addr;
2127 int undefinedCount= 0;
2128
2129 for(j= 0; j < hdr->s_nreloc; j++) {
2130 if (relocEnt->r_extern) {
2131 pEXTR esym= &extsyms[relocEnt->r_symndx];
2132 char *symname= extSs + esym->asym.iss;
2133 dlSymbol *symbol;
2134
2135 symbol= dl_hashSearchSymbol(symname);
2136 if(!symbol || !symbol->objFile) {
2137 RELOC *rents= dlfile->sect[i].relocEntries;
2138 int found;
2139
2140 if (j!=undefinedCount)
2141 rents[undefinedCount]=rents[j];
2142 if (!symbol) {
2143 (void)dl_hashInsertSymbolStrIdx(STRCOPY(symname), 0,
2144 &found);
2145 _dl_undefinedSymbolCount++;
2146 }
2147 undefinedCount++;
2148 relocEnt++;
2149 continue; /* skip this one */
2150 }
2151 if(symbol->objFile->relocStatus==DL_NEEDRELOC) {
2152 /*
2153 * trigger an avalanche of relocates! (In fact, we
2154 * don't need to relocate unless the symbol references
2155 * unrelocated text but we do it anyway.)
2156 *
2157 * if we fail to relocate the object file containing the
2158 * symbol, we treat it as undefined and keep it around
2159 * to trigger relocation next time.
2160 */
2161 if (!_dl_relocateSections(symbol->objFile)) {
2162 RELOC *rents= dlfile->sect[i].relocEntries;
2163
2164 if (j!=undefinedCount)
2165 rents[undefinedCount]=rents[j];
2166 undefinedCount++;
2167 relocEnt++;
2168 continue; /* skip this one */
2169 }
2170 }
2171 relocAddr= symbol->addr;
2172 }else {
2173 switch(relocEnt->r_symndx) {
2174 case R_SN_TEXT:
2175 relocAddr= textAddress;
2176 break;
2177 case R_SN_RDATA:
2178 relocAddr= rdataAddress;
2179 break;
2180 case R_SN_DATA:
2181 relocAddr= dataAddress;
2182 break;
2183 case R_SN_BSS:
2184 relocAddr= bssAddress;
2185 break;
2186 case R_SN_NULL:
2187 case R_SN_SDATA:
2188 case R_SN_SBSS:
2189 _dl_setErrmsg("unknown section %d referenced",
2190 relocEnt->r_symndx);
2191 return 0;
2192 break;
2193 case R_SN_INIT:
2194 case R_SN_LIT8:
2195 case R_SN_LIT4:
2196 /*
2197 * I've never encounter these. (-G 0 should kill the
2198 * LIT4's and LIT8's. I'm not sure if INIT is even used.)
2199 */
2200 _dl_setErrmsg("section %d not implemented",
2201 relocEnt->r_symndx);
2202 return 0;
2203 break;
2204 default:
2205 FPRINTF(stderr, "dl: unknown section %d\n",
2206 relocEnt->r_symndx);
2207 }
2208 }
2209 addr= (int *)(sectAddr + relocEnt->r_vaddr);
2210 switch(relocEnt->r_type) {
2211 case R_ABS:
2212 break;
2213 case R_REFWORD:
2214 *addr += relocAddr;
2215 break;
2216 case R_JMPADDR:
2217 /*
2218 * relocAddr has the absolute address when referenced symbol
2219 * is external; otherwise, need to add the most significant
2220 * 4 bits of the address of the instruction to the jump target.
2221 */
2222 patchLongjump(dlfile, addr, relocAddr,
2223 (relocEnt->r_extern)?0:relocEnt->r_vaddr);
2224 break;
2225 case R_REFHI: {
2226 RELOC *nxtRent= relocEnt+1;
2227 if (nxtRent->r_type != R_REFLO) {
2228 /* documentation says this will not happen: */
2229 FPRINTF(stderr, "dl: R_REFHI not followed by R_REFLO\n");
2230
2231 /*
2232 * use old way-- just relocate R_REFHI. This will break if
2233 * R_REFLO has a negative offset.
2234 */
2235 if((short)(relocAddr&0xffff) < 0) {
2236 *addr += (((unsigned)relocAddr>>16)+ 1);
2237 }else {
2238 *addr += ((unsigned)relocAddr>> 16);
2239 }
2240 }else {
2241 int hi_done= 0;
2242 int hi_newaddr=0;
2243 /*
2244 * documentation lies again. You can have more than
2245 * one R_REFLO following a R_REFHI.
2246 */
2247 while(j<hdr->s_nreloc && nxtRent->r_type==R_REFLO) {
2248 int *lo_addr= (int *)(sectAddr + nxtRent->r_vaddr);
2249 int oldaddr, newaddr;
2250 int temphi;
2251
2252 oldaddr= ((*addr)<<16) + (short)((*lo_addr) & 0xffff);
2253 newaddr= relocAddr + oldaddr;
2254 if((short)(newaddr&0xffff) < 0) {
2255 temphi= (((unsigned)newaddr>>16)+ 1);
2256 }else {
2257 temphi= ((unsigned)newaddr>> 16);
2258 }
2259 if(!hi_done) {
2260 hi_newaddr= temphi;
2261 hi_done=1;
2262 }else {
2263 if(temphi!=hi_newaddr) {
2264 FPRINTF(stderr, "dl: REFHI problem: %d %d don't match\n",
2265 temphi, hi_newaddr);
2266 }
2267 }
2268 *lo_addr &= 0xffff0000;
2269 *lo_addr |= (newaddr & 0xffff);
2270 j++; /* the following R_REFLO(s) has been relocated */
2271 relocEnt++;
2272 nxtRent++;
2273 }
2274 *addr &= 0xffff0000; /* mask the immediate fields */
2275 *addr |= (hi_newaddr & 0xffff);
2276 }
2277 break;
2278 }
2279 case R_REFLO:
2280 /*
2281 * shouldn't be here (REFHI should have taken care of these)
2282 * -- just in case
2283 */
2284 FPRINTF(stderr, "dl: warning: dangling R_REFLO.\n");
2285 *addr += (relocAddr & 0xffff);
2286 break;
2287 case R_GPREL:
2288 FPRINTF(stderr,"dl: Hopeless: $gp used.\n");
2289 break;
2290 default:
2291 FPRINTF(stderr,"dl: This local relocation not implemented yet.\n");
2292 }
2293 relocEnt++;
2294 }
2295 hdr->s_nreloc= undefinedCount;
2296 if(undefinedCount>0) {
2297 hasUndefined= 1;
2298 }else {
2299 free(dlfile->sect[i].relocEntries);
2300 dlfile->sect[i].relocEntries= NULL;
2301 }
2302 }
2303 dlfile->relocStatus= hasUndefined? DL_NEEDRELOC : DL_RELOCATED;
2304 if(!hasUndefined) {
2305 free(dlfile->extsyms);
2306 dlfile->extsyms= NULL;
2307 dlfile->iextMax= 0;
2308 protectText(dlfile);
2309 }
2310 return (!hasUndefined);
2311 }
2312
2313 /*
2314 * patchLongjump patches R_JMPADDR references. The problem is that the
2315 * immediate field is only 28 bits and the references are often out of
2316 * range. We need to jump to a near place first (ie. the jmptable here)
2317 * and do a "jr" to jump farther away.
2318 */
2319 static void patchLongjump( dlfile, addr, relocAddr, vaddr )
2320 dlFile *dlfile; int *addr; long relocAddr; long vaddr;
2321 {
2322 int *patch, instr;
2323 JmpTbl *jmptable= dlfile->jmptable;
2324 JmpTblHdr *jhdr= (jmptable) ? (JmpTblHdr *)jmptable->block : NULL;
2325
2326 if (!jmptable || jhdr->current==jhdr->max) {
2327 int pagesize;
2328
2329 /* need new jump table */
2330 jmptable= (JmpTbl *)malloc(sizeof(JmpTbl));
2331 pagesize= getpagesize();
2332 jmptable->block= (char *)valloc(pagesize);
2333 bzero(jmptable->block, pagesize);
2334 jmptable->next= dlfile->jmptable;
2335 jhdr= (JmpTblHdr *)jmptable->block;
2336 jhdr->current= 0;
2337 jhdr->max= (pagesize - sizeof(JmpTblHdr))/16;
2338 dlfile->jmptable= jmptable;
2339 }
2340
2341 if ((unsigned)addr>>28!=relocAddr>>28) {
2342 patch= (int *)jmptable->block + jhdr->current*4 + 4;
2343 jhdr->current++;
2344 if ((unsigned)patch>>28!=(unsigned)patch>>28) {
2345 FPRINTF(stderr,"dl: out of luck! Can't jump.\n");
2346 return;
2347 }
2348 if ((*addr)&0x3ffffff) {
2349 relocAddr+= (*addr & 0x3ffffff)<<2;
2350 }
2351 if (vaddr) {
2352 relocAddr+= (vaddr & 0xf0000000);
2353 }
2354 if (relocAddr&0x3) {
2355 FPRINTF(stderr,"dl: relocation address not word-aligned!\n");
2356 }
2357 /* lui $at, hiOffset */
2358 *patch= 0x3c010000 | (relocAddr>>16);
2359 /* ori $at, $at, loOffset */
2360 *(patch+1)=0x34210000|(relocAddr&0xffff);
2361 /* jr $at */
2362 *(patch+2)= 0x00200008;
2363 /* nop */
2364 *(patch+3)= 0;
2365 *addr &= 0xfc000000; /* leave the jal */
2366 *addr |= (((long)patch>>2) & 0x3ffffff);
2367 }else {
2368 if (relocAddr&0x3) {
2369 FPRINTF(stderr,"dl: relocation address not word-aligned!\n");
2370 }
2371 *addr += (relocAddr>>2) & 0x3ffffff;
2372 }
2373 return;
2374 }
2375
2376 /*
2377 * change memory protection so that text and the jumptables cannot be
2378 * accidentally overwritten.
2379 */
2380 static void protectText( dlfile )
2381 dlFile *dlfile;
2382 {
2383 int pagesize= getpagesize();
2384 JmpTbl *jmptable= dlfile->jmptable;
2385
2386 if (dlfile->textAddress) {
2387 /* protect the text */
2388 if (mprotect((char *)dlfile->textAddress, dlfile->textSize,
2389 PROT_EXEC) == -1) {
2390 FPRINTF(stderr, "dl: fail to protect text of %s\n", dlfile->filename);
2391 }
2392 /* flush the caches */
2393 if (cacheflush((char *)dlfile->textAddress, dlfile->textSize,
2394 BCACHE) != 0) {
2395 FPRINTF(stderr, "dl: fail to flush text of %s\n", dlfile->filename);
2396 }
2397 /* protect jump tables, if any */
2398 while(jmptable) {
2399 if (mprotect((char *)jmptable->block, pagesize,
2400 PROT_EXEC) == -1) {
2401 FPRINTF(stderr, "dl: fail to protect a jump table of %s\n",
2402 dlfile->filename);
2403 }
2404 /* flush the caches */
2405 if (cacheflush((char *)jmptable->block, pagesize, BCACHE) != 0) {
2406 FPRINTF(stderr, "dl: fail to flush a jump table of %s\n", dlfile->filename);
2407 }
2408 jmptable= jmptable->next;
2409 }
2410 }
2411 return;
2412 }
2413
2414 /*
2415 * dlInterf.c--
2416 * implements the dl* interface
2417 *
2418 *
2419 * Copyright (c) 1993 Andrew K. Yu, University of California at Berkeley
2420 * All rights reserved.
2421 *
2422 * Permission to use, copy, modify, and distribute this software and its
2423 * documentation for educational, research, and non-profit purposes and
2424 * without fee is hereby granted, provided that the above copyright
2425 * notice appear in all copies and that both that copyright notice and
2426 * this permission notice appear in supporting documentation. Permission
2427 * to incorporate this software into commercial products can be obtained
2428 * from the author. The University of California and the author make
2429 * no representations about the suitability of this software for any
2430 * purpose. It is provided "as is" without express or implied warranty.
2431 *
2432 */
2433 #include <stdio.h>
2434 #include <varargs.h>
2435
2436 static char errmsg[500]; /* the error message buffer */
2437
2438 static int _dl_openFile();
2439
2440 #define OBJECT_MAGIC(x) \
2441 ((x)==MIPSEBMAGIC || (x)==MIPSELMAGIC || (x)==SMIPSEBMAGIC || \
2442 (x)==SMIPSELMAGIC || (x)==MIPSEBUMAGIC || (x)==MIPSELUMAGIC)
2443
2444
2445 /*****************************************************************************
2446 * *
2447 * dl_init, dl_open, dl_sym, dl_close, dl_error interface routines *
2448 * *
2449 *****************************************************************************/
2450
2451 /*
2452 * dl_init--
2453 * takes the pathname of the current executable and reads in the
2454 * symbols. It returns 1 if successful and 0 otherwise.
2455 */
2456 int dl_init( filename )
2457 char *filename;
2458 {
2459 int fd;
2460 dlFile *dlfile;
2461 FILHDR filhdr;
2462
2463 if (!filename) return 0;
2464
2465 /*
2466 * open the executable for extracting the symbols
2467 */
2468 if((fd=_dl_openFile(filename, &filhdr, 0)) < 0) {
2469 _dl_setErrmsg("cannot open \"%s\"", filename);
2470 return 0;
2471 }
2472 /*
2473 * create a dlFile entry for the executable
2474 */
2475 dlfile= (dlFile *)malloc(sizeof(dlFile));
2476 bzero(dlfile, sizeof(dlFile));
2477 dlfile->filename= STRCOPY(filename);
2478 dlfile->relocStatus= DL_RELOCATED;
2479
2480 /*
2481 * load in and enter the symbols
2482 */
2483 _dl_hashInit();
2484 if (!_dl_loadSymbols(dlfile, fd, filhdr, 0)) {
2485 _dl_closeObject(dlfile);
2486 _dl_setErrmsg("Cannot load symbol table from \"%s\"", filename);
2487 return 0;
2488 }
2489 if (!_dl_enterInitialExternRef(dlfile)) {
2490 _dl_closeObject(dlfile);
2491 return 0;
2492 }
2493
2494 close(fd);
2495
2496 return 1;
2497 }
2498
2499 /*
2500 * dl_open--
2501 * opens the object file or library archive specified by filename
2502 * It can be opened with either DL_LAZY or DL_NOW mode. DL_LAZY does
2503 * no perform symbol resolution until a symbol in the file is accessed.
2504 * DL_NOW performs symbol resolution at load time. It returns a
2505 * handle if successful, NULL otherwise.
2506 */
2507 void *dlopen( filename, mode )
2508 char *filename; int mode;
2509 {
2510 int fd;
2511 dlFile *dlfile;
2512 FILHDR filhdr;
2513
2514 if((fd=_dl_openFile(filename, &filhdr, 0)) < 0) {
2515 _dl_setErrmsg("cannot open \"%s\"", filename);
2516 return NULL;
2517 }
2518
2519 /*
2520 * determine whether we have an object file or a library
2521 */
2522 if (OBJECT_MAGIC(filhdr.f_magic)) {
2523 /*
2524 * an ordinary object file.
2525 */
2526 dlfile= _dl_openObject(fd, filename, filhdr, 0, mode);
2527 close(fd);
2528 }else if (!strncmp((char*)&filhdr, ARMAG, SARMAG)) {
2529 dlFile *df;
2530
2531 /*
2532 * a library: load in every object file.
2533 */
2534 if ((dlfile=_dl_loadEntireArchive(filename, fd))==NULL) {
2535 close(fd);
2536 _dl_setErrmsg("Cannot load archive \"%s\"", filename);
2537 return NULL;
2538 }
2539
2540 /*
2541 * do the relocation now if mode==DL_NOW. (note that we couldn't
2542 * relocate in the above loop since archive members might reference
2543 * each other.)
2544 */
2545 if (mode==DL_NOW) {
2546 int search= 0;
2547
2548 df= dlfile;
2549 while(df) {
2550 if (!_dl_relocateSections(df))
2551 search= 1;
2552 df= df->next;
2553 }
2554 if (search) {
2555 if (!dl_searchLibraries()) {
2556 _dl_setErrmsg("\"%s\" contains undefined symbols",
2557 filename);
2558 _dl_closeObject(dlfile);
2559 return NULL;
2560 }
2561 df= dlfile; /* one more time */
2562 while(df) {
2563 if (!_dl_relocateSections(df)) {
2564 _dl_setErrmsg("\"%s\" contains undefined symbols",
2565 filename);
2566 _dl_closeObject(dlfile);
2567 return NULL;
2568 }
2569 df= df->next;
2570 }
2571 }
2572 }
2573 }else {
2574 _dl_setErrmsg("\"%s\" neither an object file nor an archive",
2575 filename);
2576 }
2577
2578 return (void *)dlfile;
2579 }
2580
2581
2582 /*
2583 * dl_sym--
2584 * returns the location of the specified symbol. handle is not
2585 * actually used. It returns NULL if unsuccessful.
2586 */
2587 void *dlsym( handle, name )
2588 void *handle; char *name;
2589 {
2590 dlFile *dlfile;
2591 dlSymbol *symbol;
2592
2593 symbol = dl_hashSearchSymbol(name);
2594 if (symbol) {
2595 dlfile= symbol->objFile;
2596 /*
2597 * might have undefined symbols or have not been relocated yet.
2598 */
2599 if (dlfile->relocStatus==DL_NEEDRELOC) {
2600 if (!_dl_relocateSections(dlfile)) {
2601 if (dl_searchLibraries()) {
2602 /* find some undefined symbols, try again! */
2603 _dl_relocateSections(dlfile);
2604 }
2605 }
2606 }
2607 /*
2608 * only returns the symbol if the relocation has completed
2609 */
2610 if (dlfile->relocStatus==DL_RELOCATED)
2611 return (void *)symbol->addr;
2612 }
2613 if (symbol) {
2614 _dl_setErrmsg("\"%s\" has undefined symbols", dlfile->filename);
2615 }else {
2616 _dl_setErrmsg("no such symbol \"%s\"", name);
2617 }
2618 return NULL;
2619 }
2620
2621 /*
2622 * dl_close--
2623 * closes the file and deallocate all resources hold by the file.
2624 * note that any references to the deallocated resources will result
2625 * in undefined behavior.
2626 */
2627 void dlclose( handle )
2628 void *handle;
2629 {
2630 _dl_closeObject((dlFile *)handle);
2631 return;
2632 }
2633
2634 /*
2635 * dl_error--
2636 * returns the error message string of the previous error.
2637 */
2638 char *dlerror()
2639 {
2640 return errmsg;
2641 }
2642
2643 /*****************************************************************************
2644 * *
2645 * Object files handling Rountines *
2646 * *
2647 *****************************************************************************/
2648
2649 dlFile *_dl_openObject( fd, filename, filhdr, offset, mode )
2650 int fd; char *filename; FILHDR filhdr; int offset; int mode;
2651 {
2652 dlFile *dlfile;
2653
2654 dlfile= (dlFile *)malloc(sizeof(dlFile));
2655 bzero(dlfile, sizeof(dlFile));
2656 dlfile->relocStatus= DL_NEEDRELOC;
2657 dlfile->filename= STRCOPY(filename);
2658
2659 if (!_dl_loadSymbols(dlfile, fd, filhdr, offset) ||
2660 !_dl_loadSections(dlfile, fd, offset)) {
2661 _dl_setErrmsg("Cannot load symbol table or sections from \"%s\"",
2662 filename);
2663 _dl_closeObject(dlfile);
2664 return NULL;
2665 }
2666
2667 if (!_dl_enterExternRef(dlfile)) {
2668 _dl_closeObject(dlfile);
2669 return NULL;
2670 }
2671
2672 if(mode==DL_NOW) {
2673 if (!_dl_relocateSections(dlfile)) {
2674 /*
2675 * attempt to search the "standard" libraries before aborting
2676 */
2677 if (!dl_searchLibraries() ||
2678 !_dl_relocateSections(dlfile)) {
2679
2680 _dl_setErrmsg("\"%s\" contains undefined symbols",
2681 filename);
2682 _dl_closeObject(dlfile);
2683 return NULL;
2684 }
2685 }
2686 }else {
2687 dlfile->relocStatus= DL_NEEDRELOC;
2688 }
2689
2690 return dlfile;
2691 }
2692
2693 void _dl_closeObject( dlfile )
2694 dlFile *dlfile;
2695 {
2696 int i;
2697 dlFile *next;
2698
2699 while(dlfile) {
2700 next= dlfile->next;
2701 if (dlfile->filename)
2702 free(dlfile->filename);
2703 if (dlfile->sect)
2704 free(dlfile->sect);
2705 if (dlfile->extss)
2706 free(dlfile->extss);
2707 if (dlfile->extsyms)
2708 free(dlfile->extsyms);
2709 /* frees any symbols associated with it */
2710 for(i=0; i < HASHTABSZ; i++) {
2711 HEnt *ent= dlHashTable[i], *prev, *t;
2712 prev= dlHashTable[i];
2713 while(ent) {
2714 if (ent->symbol->objFile==dlfile) {
2715 t= ent->next;
2716 if (prev==dlHashTable[i]) {
2717 dlHashTable[i]= prev= ent->next;
2718 }else {
2719 prev->next= ent->next;
2720 }
2721 free(ent);
2722 ent= t;
2723 }else {
2724 prev= ent;
2725 ent=ent->next;
2726 }
2727 }
2728 }
2729 free(dlfile);
2730 dlfile= next;
2731 }
2732 }
2733
2734 int _dl_loadSymbols( dlfile, fd, filhdr, offset )
2735 dlFile *dlfile; int fd; FILHDR filhdr; int offset;
2736 {
2737 SCNHDR *scnhdr;
2738 HDRR symhdr;
2739 char *pssext;
2740 pEXTR pext;
2741 int nscn, size, i;
2742
2743 /*
2744 * load in section headers (don't need this for the executable during
2745 * init)
2746 */
2747 if (dlfile->relocStatus!=DL_RELOCATED) {
2748 nscn= filhdr.f_nscns;
2749 scnhdr= (SCNHDR *)malloc(sizeof(SCNHDR) * nscn);
2750 if (lseek(fd, filhdr.f_opthdr, SEEK_CUR)==-1 ||
2751 read(fd, scnhdr, sizeof(SCNHDR)*nscn)!= sizeof(SCNHDR)*nscn)
2752 return 0;
2753 }
2754 /*
2755 * load in symbolic header
2756 */
2757 if (lseek(fd, offset+filhdr.f_symptr, SEEK_SET)==-1 ||
2758 read(fd, &symhdr, sizeof(symhdr))!=sizeof(symhdr) ||
2759 symhdr.magic!=magicSym)
2760 return 0;
2761 /*
2762 * read external strings table
2763 */
2764 size= symhdr.issExtMax;
2765 pssext= (char *)malloc(size);
2766 if (lseek(fd, offset+symhdr.cbSsExtOffset, SEEK_SET)==-1 ||
2767 read(fd, pssext, size)!=size)
2768 return 0;
2769 /*
2770 * read external symbols table
2771 */
2772 size= symhdr.iextMax * sizeof(EXTR);
2773 pext= (pEXTR)malloc(size);
2774 if (lseek(fd, offset+symhdr.cbExtOffset, SEEK_SET)==-1 ||
2775 read(fd, pext, size)!=size)
2776 return 0;
2777 /*
2778 * copy the extern string space and symbols. The string space is
2779 * referenced by the hash table. We need the symbols either in
2780 * lazy resolution or when there are undefined symbols.
2781 */
2782 dlfile->extss= pssext;
2783 dlfile->issExtMax= symhdr.issExtMax;
2784 dlfile->extsyms= pext;
2785 dlfile->iextMax= symhdr.iextMax;
2786 /*
2787 * relocStatus should only be DL_RELOCATED for the executable's dlfile
2788 * during init. (Don't need to relocate the executable!)
2789 */
2790 if (dlfile->relocStatus==DL_RELOCATED)
2791 return 1;
2792 /*
2793 * otherwise, create the ScnInfo's
2794 */
2795 dlfile->nsect= nscn;
2796 size= sizeof(ScnInfo)*nscn;
2797 dlfile->sect= (ScnInfo *)malloc(size);
2798 bzero(dlfile->sect, size);
2799 for(i=0; i < nscn; i++) {
2800 dlfile->sect[i].hdr = scnhdr[i];
2801 }
2802 free(scnhdr);
2803 return 1;
2804 }
2805
2806 /*
2807 * _dl_loadSections--
2808 * loads all sections of an object file into memory.
2809 */
2810 int _dl_loadSections(dlfile, fd, offset)
2811 dlFile *dlfile; int fd; int offset;
2812 {
2813 int nsect= dlfile->nsect;
2814 int i;
2815 RELOC *relocEnt;
2816 int size;
2817
2818 for(i=0; i < nsect; i++) {
2819 SCNHDR *hdr= &(dlfile->sect[i].hdr);
2820 char *sectnam;
2821 char *addr;
2822 int isBss= 0;
2823
2824 sectnam= hdr->s_name;
2825 if(!strncmp(sectnam, ".text", 5)) {
2826 int pagesize= getpagesize();
2827 int size= (hdr->s_size%pagesize==0)? hdr->s_size :
2828 hdr->s_size - hdr->s_size % pagesize + pagesize;
2829
2830 /* page aligned */
2831 addr= (char *)valloc(size);
2832 dlfile->textAddress= (CoreAddr)addr;
2833 dlfile->textVaddr= hdr->s_vaddr;
2834 dlfile->textSize= size;
2835 }else {
2836 addr= (char *)malloc(hdr->s_size);
2837 if (!strncmp(sectnam, ".rdata", 6)) {
2838 dlfile->rdataAddress= (CoreAddr)addr;
2839 dlfile->rdataVaddr= hdr->s_vaddr;
2840 }else if (!strncmp(sectnam, ".data", 5)) {
2841 dlfile->dataAddress= (CoreAddr)addr;
2842 dlfile->dataVaddr= hdr->s_vaddr;
2843 }else if (!strncmp(sectnam, ".bss", 4)) {
2844 dlfile->bssAddress= (CoreAddr)addr;
2845 dlfile->bssVaddr= hdr->s_vaddr;
2846 bzero(addr, hdr->s_size); /* zero out bss segment */
2847 isBss= 1;
2848 }
2849 }
2850 dlfile->sect[i].addr= (CoreAddr)addr;
2851 if(!isBss) {
2852 /*
2853 * read in raw data from the file
2854 */
2855 if (hdr->s_size &&
2856 (lseek(fd, offset+hdr->s_scnptr, SEEK_SET)==-1 ||
2857 read(fd, addr, hdr->s_size)!=hdr->s_size))
2858 return 0;
2859 /*
2860 * read in relocation entries from the file
2861 */
2862 if (hdr->s_nreloc) {
2863 size= sizeof(RELOC)* hdr->s_nreloc;
2864 dlfile->sect[i].relocEntries= relocEnt=
2865 (RELOC *)malloc(size);
2866 if (lseek(fd, offset+hdr->s_relptr, SEEK_SET)==-1 ||
2867 read(fd, relocEnt, size)!=size)
2868 return 0;
2869 }
2870 }
2871 }
2872 return 1;
2873 }
2874
2875 static int _dl_openFile( filename, fhdr, offset )
2876 char *filename; FILHDR *fhdr; int offset;
2877 {
2878 int fd;
2879 if ((fd=open(filename, O_RDONLY)) >= 0) {
2880 /*
2881 * load in file header
2882 */
2883 if (lseek(fd, offset, SEEK_SET)==-1 ||
2884 read(fd, fhdr, sizeof(FILHDR))!=sizeof(FILHDR))
2885 return -1;
2886
2887 }
2888 return fd;
2889 }
2890
2891
2892 _dl_setErrmsg( va_alist )
2893 va_dcl
2894 {
2895 va_list pvar;
2896 char *fmt;
2897
2898 va_start(pvar);
2899 fmt= va_arg(pvar, char *);
2900 vsprintf(errmsg, fmt, pvar);
2901 va_end(pvar);
2902 }
2903 #endif /* ultrix */
2904
2905 #ifndef ASCDL_OK
2906 #error "Unable to build ascDynaload.o. Turn off strict ansi cc options."
2907 #endif /* adlok */
2908 #ifdef __hpux
2909 #define UNLOAD shl_unload
2910 #define DLL_CAST (shl_t)
2911 #define ASC_DLERRSTRING "NULL definition"
2912 #define UNLOAD_SUCCESS 0
2913 #endif /* __hpux */
2914 #ifdef __WIN32__
2915 #define UNLOAD FreeLibrary
2916 #define DLLSYM GetProcAddress
2917 #define DLL_CAST (HINSTANCE)
2918 #define ASC_DLERRSTRING "unknown"
2919 #define UNLOAD_SUCCESS TRUE
2920 #endif /* __WIN32__ */
2921 #ifndef UNLOAD
2922 #define UNLOAD dlclose
2923 #define DLLSYM dlsym
2924 #define DLL_CAST (void *)
2925 #define ASC_DLERRSTRING dlerror()
2926 #define UNLOAD_SUCCESS 0
2927 #endif /* UNLOAD */
2928
2929 int Asc_DynamicUnLoad(char *path)
2930 {
2931 void *dlreturn;
2932 int retval;
2933
2934 if (NULL == path) {
2935 FPRINTF(stderr, "Asc_DynamicUnLoad failed: Null path\n");
2936 return -3;
2937 }
2938
2939 dlreturn = AscDeleteRecord(path);
2940 if (dlreturn == NULL) {
2941 FPRINTF(stderr, "Asc_DynamicUnLoad: unable to remember or unload %s\n", path);
2942 return -3;
2943 }
2944 FPRINTF(stderr, "Asc_DynamicUnLoad: forgetting & unloading %s \n", path);
2945 /*
2946 * dlclose() returns 0 on success, FreeLibrary() returns TRUE.
2947 * A uniform convention is preferable, so trap and return 0 on success.
2948 */
2949 retval = UNLOAD(DLL_CAST dlreturn);
2950 return (retval == UNLOAD_SUCCESS) ? 0 : retval;
2951 }
2952
2953 /*
2954 * yourFuncOrVar = (YOURCAST)Asc_DynamicSymbol(libraryname,symbolname);
2955 * rPtr =
2956 * (double (*)(double *, double *))Asc_DynamicSymbol("lib.dll","calc");
2957 * returns you a pointer to a symbol exported from the dynamically
2958 * linked library named, if the library is loaded with Asc_DynamicLoad
2959 * and the symbol can be found in it.
2960 */
2961 extern void *Asc_DynamicSymbol(CONST char *libname, CONST char *symbol)
2962 {
2963 void *dlreturn;
2964 void *symreturn;
2965 #ifdef __hpux
2966 int i;
2967 #endif
2968
2969 if (libname == NULL) {
2970 FPRINTF(stderr,"Asc_DynamicSymbol failed: Null libname\n");
2971 return NULL;
2972 }
2973 if (symbol == NULL) {
2974 FPRINTF(stderr,"Asc_DynamicSymbol failed: Null symbol\n");
2975 return NULL;
2976 }
2977
2978 dlreturn = AscFindDLRecord(libname);
2979 if (dlreturn == NULL) {
2980 FPRINTF(stderr,"Asc_DynamicSymbol: Unable to find requested library %s\n", libname);
2981 return NULL;
2982 }
2983 #ifdef __hpux
2984 i = shl_findsym(&dlreturn, symbol, TYPE_UNDEFINED, &symreturn);
2985 if (i == -1) {
2986 FPRINTF(stderr,"Asc_DynamicSymbol: Unable to find requested symbol %s in %s (%s)\n",
2987 symbol, libname, strerror(errno));
2988 symreturn = NULL;
2989 }
2990 #else
2991 symreturn = (void *) DLLSYM(DLL_CAST dlreturn,symbol);
2992 #endif
2993 if (symreturn == NULL) {
2994 FPRINTF(stderr,"Asc_DynamicSymbol: Unable to find requested symbol %s in %s\n",symbol,libname);
2995 FPRINTF(stderr,"Error type %s\n",ASC_DLERRSTRING);
2996 }
2997 return symreturn;
2998 }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22