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

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

Parent Directory Parent Directory | Revision Log Revision Log


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