1 /* HDL.C        (c) Copyright Jan Jaeger, 2003-2009                  */
2 /*              Hercules Dynamic Loader                              */
3 
4 #include "hstdinc.h"
5 
6 #define _HDL_C_
7 #define _HUTIL_DLL_
8 
9 #if !defined(WIN32) && !defined(__FreeBSD__) && !defined(__APPLE__)
10 #define ZZ_NO_BACKLINK
11 #endif
12 
13 #include "hercules.h"
14 #ifdef ZZ_NO_BACKLINK
15 #include "opcode.h" /* for the opcode tables */
16 #endif
17 
18 /*
19 extern HDLPRE hdl_preload[];
20 */
21 
22 #if defined(OPTION_DYNAMIC_LOAD)
23 HDLPRE hdl_preload[] = {
24     { "hdteq",          HDL_LOAD_NOMSG },
25     { "dyncrypt",       HDL_LOAD_NOMSG },
26 #if 0
27     { "dyn_test1",      HDL_LOAD_DEFAULT },
28     { "dyn_test2",      HDL_LOAD_NOMSG },
29     { "dyn_test3",      HDL_LOAD_NOMSG | HDL_LOAD_NOUNLOAD },
30 #endif
31     { NULL,             0  } };
32 
33 #if 0
34 /* Forward definitions from hdlmain.c stuff */
35 /* needed because we cannot depend on dlopen(self) */
36 extern void *HDL_DEPC;
37 extern void *HDL_INIT;
38 extern void *HDL_RESO;
39 extern void *HDL_DDEV;
40 extern void *HDL_DINS;
41 extern void *HDL_FINI;
42 #endif
43 
44 
45 static DLLENT *hdl_dll;                  /* dll chain                */
46 static LOCK   hdl_lock;                  /* loader lock              */
47 static DLLENT *hdl_cdll;                 /* current dll (hdl_lock)   */
48 
49 static HDLDEP *hdl_depend;               /* Version codes in hdlmain */
50 
51 static char *hdl_modpath = NULL;
52 
53 #endif
54 
55 static LOCK   hdl_sdlock;                /* shutdown lock            */
56 static HDLSHD *hdl_shdlist;              /* Shutdown call list       */
57 
58 static void hdl_didf (int, int, char *, void *);
59 #ifdef ZZ_NO_BACKLINK
60 static void hdl_modify_opcode(int, HDLINS *);
61 #endif
62 
63 /* Global hdl_device_type_equates */
64 
65 DLL_EXPORT char *(*hdl_device_type_equates)(const char *);
66 
67 /* hdl_adsc - add shutdown call
68  */
hdl_adsc(char * shdname,void * shdcall,void * shdarg)69 DLL_EXPORT void hdl_adsc (char* shdname, void * shdcall, void * shdarg)
70 {
71 HDLSHD *newcall;
72 
73     newcall = malloc(sizeof(HDLSHD));
74     newcall->shdname = shdname;
75     newcall->shdcall = shdcall;
76     newcall->shdarg = shdarg;
77     newcall->next = hdl_shdlist;
78     hdl_shdlist = newcall;
79 }
80 
81 
82 /* hdl_rmsc - remove shutdown call
83  */
hdl_rmsc(void * shdcall,void * shdarg)84 DLL_EXPORT int hdl_rmsc (void *shdcall, void *shdarg)
85 {
86 HDLSHD **tmpcall;
87 
88     for(tmpcall = &(hdl_shdlist); *tmpcall; tmpcall = &((*tmpcall)->next) )
89     {
90         if( (*tmpcall)->shdcall == shdcall
91           && (*tmpcall)->shdarg == shdarg )
92         {
93         HDLSHD *frecall;
94             frecall = *tmpcall;
95             *tmpcall = (*tmpcall)->next;
96             free(frecall);
97             return 0;
98         }
99     }
100     return -1;
101 }
102 
103 
104 /* hdl_shut - call all shutdown call entries in LIFO order
105  */
hdl_shut(void)106 DLL_EXPORT void hdl_shut (void)
107 {
108 HDLSHD *shdent;
109 
110 #if defined( _MSVC_ )
111 HDLSHD *loggercall;
112 int logger_flag = 0;
113 #endif // defined( _MSVC_ )
114 
115     logmsg("HHCHD900I Begin shutdown sequence\n");
116 
117     obtain_lock (&hdl_sdlock);
118 
119     for(shdent = hdl_shdlist; shdent; shdent = hdl_shdlist)
120     {
121 #if defined( _MSVC_ )
122         if ( strcmp( shdent->shdname, "logger_term" ) == 0 )
123         {
124             loggercall = malloc(sizeof(HDLSHD));
125             loggercall->shdname = shdent->shdname;
126             loggercall->shdcall = shdent->shdcall;
127             loggercall->shdarg = shdent->shdarg;
128             logger_flag = 1;
129         }
130         else
131 #endif // defined( _MSVC_ )
132         {
133             logmsg("HHCHD901I Calling %s\n",shdent->shdname);
134             {
135                 (shdent->shdcall) (shdent->shdarg);
136             }
137             logmsg("HHCHD902I %s complete\n",shdent->shdname);
138         }
139         /* Remove shutdown call entry to ensure it is called once */
140         hdl_shdlist = shdent->next;
141         free(shdent);
142     }
143 
144     release_lock (&hdl_sdlock);
145 #if defined( _MSVC_ )
146     if ( logger_flag == 1 )
147     {
148         if ( sysblk.shutimmed )
149             /* shutdown of logger is skipped in a Windows Environment
150              * because we still have messages to write to the log file
151              */
152             logmsg("HHCHD903I (%s) skipped during Windows SHUTDOWN immediate\n",
153                     loggercall->shdname);
154         else
155         {
156             logmsg("HHCHD901I Calling %s\n",loggercall->shdname);
157             {
158                 (loggercall->shdcall) (loggercall->shdarg);
159             }
160             logmsg("HHCHD902I %s complete\n",loggercall->shdname);
161             free(loggercall);
162         }
163     }
164 #endif // defined( _MSVC_ )
165 
166     logmsg("HHCHD909I Shutdown sequence complete\n");
167 }
168 
169 #if defined(OPTION_DYNAMIC_LOAD)
170 
171 
172 /* hdl_setpath - set path for module load
173  */
hdl_setpath(char * path)174 DLL_EXPORT void hdl_setpath(char *path)
175 {
176     if(hdl_modpath)
177         free(hdl_modpath);
178 
179     hdl_modpath = strdup(path);
180 
181     logmsg(_("HHCHD018I Loadable module directory is %s\n"),hdl_modpath);
182 }
183 
184 
hdl_dlopen(char * filename,int flag _HDL_UNUSED)185 static void * hdl_dlopen(char *filename, int flag _HDL_UNUSED)
186 {
187 char *fullname;
188 void *ret;
189 size_t fulllen = 0;
190 
191     if(filename && *filename != '/' && *filename != '.')
192     {
193         if(hdl_modpath && *hdl_modpath)
194         {
195             fulllen = strlen(filename) + strlen(hdl_modpath) + 2 + HDL_SUFFIX_LENGTH;
196             fullname = malloc(fulllen);
197             strlcpy(fullname,hdl_modpath,fulllen);
198             strlcat(fullname,"/",fulllen);
199             strlcat(fullname,filename,fulllen);
200 #if defined(HDL_MODULE_SUFFIX)
201             strlcat(fullname,HDL_MODULE_SUFFIX,fulllen);
202 #endif
203         }
204         else
205             fullname = filename;
206 
207         if((ret = dlopen(fullname,flag)))
208         {
209             if(fulllen)
210                 free(fullname);
211 
212             return ret;
213         }
214 
215 #if defined(HDL_MODULE_SUFFIX)
216         fullname[strlen(fullname) - HDL_SUFFIX_LENGTH] = '\0';
217 
218         if((ret = dlopen(fullname,flag)))
219         {
220             if(fulllen)
221                 free(fullname);
222 
223             return ret;
224         }
225 #endif
226 
227         if(fulllen)
228             free(fullname);
229         fulllen=0;
230     }
231     if(filename && *filename != '/' && *filename != '.')
232     {
233         fulllen = strlen(filename) + 1 + HDL_SUFFIX_LENGTH;
234         fullname = malloc(fulllen);
235         strlcpy(fullname,filename,fulllen);
236 #if defined(HDL_MODULE_SUFFIX)
237         strlcat(fullname,HDL_MODULE_SUFFIX,fulllen);
238 #endif
239         if((ret = dlopen(fullname,flag)))
240         {
241             if(fulllen)
242                 free(fullname);
243 
244             return ret;
245         }
246 
247 #if defined(HDL_MODULE_SUFFIX)
248         fullname[strlen(fullname) - HDL_SUFFIX_LENGTH] = '\0';
249 
250         if((ret = dlopen(fullname,flag)))
251         {
252             if(fulllen)
253                 free(fullname);
254 
255             return ret;
256         }
257 #endif
258 
259         if(fulllen)
260             free(fullname);
261         fulllen=0;
262     }
263 
264     return dlopen(filename,flag);
265 }
266 
267 
268 /* hdl_dvad - register device type
269  */
hdl_dvad(char * devname,DEVHND * devhnd)270 DLL_EXPORT void hdl_dvad (char *devname, DEVHND *devhnd)
271 {
272 HDLDEV *newhnd;
273 
274     newhnd = malloc(sizeof(HDLDEV));
275     newhnd->name = strdup(devname);
276     newhnd->hnd = devhnd;
277     newhnd->next = hdl_cdll->hndent;
278     hdl_cdll->hndent = newhnd;
279 }
280 
281 
282 /* hdl_fhnd - find registered device handler
283  */
hdl_fhnd(const char * devname)284 static DEVHND * hdl_fhnd (const char *devname)
285 {
286 DLLENT *dllent;
287 HDLDEV *hndent;
288 
289     for(dllent = hdl_dll; dllent; dllent = dllent->dllnext)
290     {
291         for(hndent = dllent->hndent; hndent; hndent = hndent->next)
292         {
293             if(!strcasecmp(devname,hndent->name))
294             {
295                 return hndent->hnd;
296             }
297         }
298     }
299 
300     return NULL;
301 }
302 
303 
304 /* hdl_bdnm - build device module name
305  */
hdl_bdnm(const char * ltype)306 static char * hdl_bdnm (const char *ltype)
307 {
308 char *dtname;
309 unsigned int n;
310 
311     /* Don't forget the extra +1 for the \0 ending.             @PJJ */
312     dtname = malloc(strlen(ltype) + sizeof(HDL_HDTP_Q) + 1);
313     strcpy(dtname,HDL_HDTP_Q);
314     strcat(dtname,ltype);
315 
316     for(n = 0; n < strlen(dtname); n++)
317         if(isupper(dtname[n]))
318             dtname[n] = tolower(dtname[n]);
319 
320     return dtname;
321 }
322 
323 
324 /* hdl_ghnd - obtain device handler
325  */
hdl_ghnd(const char * devtype)326 DLL_EXPORT DEVHND * hdl_ghnd (const char *devtype)
327 {
328 DEVHND *hnd;
329 char *hdtname;
330 char *ltype;
331 
332     if((hnd = hdl_fhnd(devtype)))
333         return hnd;
334 
335     hdtname = hdl_bdnm(devtype);
336 
337     if(hdl_load(hdtname,HDL_LOAD_NOMSG) || !hdl_fhnd(devtype))
338     {
339         if(hdl_device_type_equates)
340         {
341             if((ltype = hdl_device_type_equates(devtype)))
342             {
343                 free(hdtname);
344 
345                 hdtname = hdl_bdnm(ltype);
346 
347                 hdl_load(hdtname,HDL_LOAD_NOMSG);
348             }
349         }
350     }
351 
352     free(hdtname);
353 
354     return hdl_fhnd(devtype);
355 }
356 
357 
358 /* hdl_list - list all entry points
359  */
hdl_list(int flags)360 DLL_EXPORT void hdl_list (int flags)
361 {
362 DLLENT *dllent;
363 MODENT *modent;
364 
365     for(dllent = hdl_dll; dllent; dllent = dllent->dllnext)
366     {
367         logmsg("dll type = %s",(dllent->flags & HDL_LOAD_MAIN) ? "main" : "load");
368         logmsg(", name = %s",dllent->name);
369 
370         if (dllent->flags & (HDL_LOAD_NOUNLOAD | HDL_LOAD_WAS_FORCED))
371         {
372             logmsg(", flags = (%s%s%s)"
373                 ,(dllent->flags & HDL_LOAD_NOUNLOAD)   ? "nounload" : ""
374                 ,(dllent->flags & HDL_LOAD_NOUNLOAD) &&
375                  (dllent->flags & HDL_LOAD_WAS_FORCED) ? ", "       : ""
376                 ,(dllent->flags & HDL_LOAD_WAS_FORCED) ? "forced"   : ""
377                 );
378         }
379 
380         logmsg("\n");
381 
382         for(modent = dllent->modent; modent; modent = modent->modnext)
383             if((flags & HDL_LIST_ALL)
384               || !((dllent->flags & HDL_LOAD_MAIN) && !modent->fep))
385             {
386                 logmsg(" symbol = %s",modent->name);
387 //              logmsg(", ep = %p",modent->fep);
388                 if(modent->fep)
389                     logmsg(", loadcount = %d",modent->count);
390                 else
391                     logmsg(", unresolved");
392                 logmsg(", owner = %s\n",dllent->name);
393             }
394 
395         if(dllent->hndent)
396         {
397         HDLDEV *hndent;
398             logmsg(" devtype =");
399             for(hndent = dllent->hndent; hndent; hndent = hndent->next)
400                 logmsg(" %s",hndent->name);
401             logmsg("\n");
402         }
403 
404         if(dllent->insent)
405         {
406         HDLINS *insent;
407             for(insent = dllent->insent; insent; insent = insent->next)
408             {
409                 logmsg(" instruction = %s, opcode = %4.4X",insent->instname,insent->opcode);
410                 if(insent->archflags & HDL_INSTARCH_370)
411                     logmsg(", archmode = " _ARCH_370_NAME);
412                 if(insent->archflags & HDL_INSTARCH_390)
413                     logmsg(", archmode = " _ARCH_390_NAME);
414                 if(insent->archflags & HDL_INSTARCH_900)
415                     logmsg(", archmode = " _ARCH_900_NAME);
416                 logmsg("\n");
417             }
418         }
419     }
420 }
421 
422 
423 /* hdl_dlst - list all dependencies
424  */
hdl_dlst(void)425 DLL_EXPORT void hdl_dlst (void)
426 {
427 HDLDEP *depent;
428 
429     for(depent = hdl_depend;
430       depent;
431       depent = depent->next)
432         logmsg("dependency(%s) version(%s) size(%d)\n",
433           depent->name,depent->version,depent->size);
434 }
435 
436 
437 /* hdl_dadd - add dependency
438  */
hdl_dadd(char * name,char * version,int size)439 static int hdl_dadd (char *name, char *version, int size)
440 {
441 HDLDEP **newdep;
442 
443     for (newdep = &(hdl_depend);
444         *newdep;
445          newdep = &((*newdep)->next));
446 
447     (*newdep) = malloc(sizeof(HDLDEP));
448     (*newdep)->next    = NULL;
449     (*newdep)->name    = strdup(name);
450     (*newdep)->version = strdup(version);
451     (*newdep)->size    = size;
452 
453     return 0;
454 }
455 
456 
457 /* hdl_dchk - dependency check
458  */
hdl_dchk(char * name,char * version,int size)459 static int hdl_dchk (char *name, char *version, int size)
460 {
461 HDLDEP *depent;
462 
463     for(depent = hdl_depend;
464       depent && strcmp(name,depent->name);
465       depent = depent->next);
466 
467     if(depent)
468     {
469         if(strcmp(version,depent->version))
470         {
471             logmsg(_("HHCHD010I Dependency check failed for %s, version(%s) expected(%s)\n"),
472                name,version,depent->version);
473             return -1;
474         }
475 
476         if(size != depent->size)
477         {
478             logmsg(_("HHCHD011I Dependency check failed for %s, size(%d) expected(%d)\n"),
479                name,size,depent->size);
480             return -1;
481         }
482     }
483     else
484     {
485         hdl_dadd(name,version,size);
486     }
487 
488     return 0;
489 }
490 
491 
492 /* hdl_fent - find entry point
493  */
hdl_fent(char * name)494 DLL_EXPORT void * hdl_fent (char *name)
495 {
496 DLLENT *dllent;
497 MODENT *modent;
498 void *fep;
499 
500     /* Find entry point and increase loadcount */
501     for(dllent = hdl_dll; dllent; dllent = dllent->dllnext)
502     {
503         for(modent = dllent->modent; modent; modent = modent->modnext)
504         {
505             if(!strcmp(name,modent->name))
506             {
507                 modent->count++;
508                 return modent->fep;
509             }
510         }
511     }
512 
513     /* If not found then lookup as regular symbol */
514     for(dllent = hdl_dll; dllent; dllent = dllent->dllnext)
515     {
516         if((fep = dlsym(dllent->dll,name)))
517         {
518             if(!(modent = malloc(sizeof(MODENT))))
519             {
520                 logmsg(_("HHCHD001E registration malloc failed for %s\n"),
521                   name);
522                 return NULL;
523             }
524 
525             modent->fep = fep;
526             modent->name = strdup(name);
527             modent->count = 1;
528 
529             /* Insert current entry as first in chain */
530             modent->modnext = dllent->modent;
531             dllent->modent = modent;
532 
533             return fep;
534         }
535     }
536 
537     /* No entry point found */
538     return NULL;
539 }
540 
541 
542 /* hdl_nent - find next entry point in chain
543  */
hdl_nent(void * fep)544 DLL_EXPORT void * hdl_nent (void *fep)
545 {
546 DLLENT *dllent;
547 MODENT *modent = NULL;
548 char   *name;
549 
550     for(dllent = hdl_dll; dllent; dllent = dllent->dllnext)
551     {
552         for(modent = dllent->modent; modent; modent = modent->modnext)
553         {
554             if(modent->fep == fep)
555                 break;
556         }
557 
558         if(modent && modent->fep == fep)
559             break;
560     }
561 
562     if(!modent)
563         return NULL;
564 
565     name = modent->name;
566 
567     if(!(modent = modent->modnext))
568     {
569         if((dllent = dllent->dllnext))
570             modent = dllent->modent;
571         else
572             return NULL;
573     }
574 
575     /* Find entry point */
576     for(; dllent; dllent = dllent->dllnext, modent = dllent->modent)
577     {
578         for(; modent; modent = modent->modnext)
579         {
580             if(!strcmp(name,modent->name))
581             {
582                 return modent->fep;
583             }
584         }
585     }
586 
587     return NULL;
588 }
589 
590 
591 /* hdl_regi - register entry point
592  */
hdl_regi(char * name,void * fep)593 static void hdl_regi (char *name, void *fep)
594 {
595 MODENT *modent;
596 
597     modent = malloc(sizeof(MODENT));
598 
599     modent->fep = fep;
600     modent->name = strdup(name);
601     modent->count = 0;
602 
603     modent->modnext = hdl_cdll->modent;
604     hdl_cdll->modent = modent;
605 
606 }
607 
608 
609 /* hdl_term - process all "HDL_FINAL_SECTION"s
610  */
hdl_term(void * unused _HDL_UNUSED)611 static void hdl_term (void *unused _HDL_UNUSED)
612 {
613 DLLENT *dllent;
614 
615     logmsg("HHCHD950I Begin HDL termination sequence\n");
616 
617     /* Call all final routines, in reverse load order */
618     for(dllent = hdl_dll; dllent; dllent = dllent->dllnext)
619     {
620         if(dllent->hdlfini)
621         {
622             logmsg("HHCHD951I Calling module %s cleanup routine\n",dllent->name);
623             {
624                 (dllent->hdlfini)();
625             }
626             logmsg("HHCHD952I Module %s cleanup complete\n",dllent->name);
627         }
628     }
629 
630     logmsg("HHCHD959I HDL Termination sequence complete\n");
631 }
632 
633 
634 #if defined(_MSVC_)
635 /* hdl_lexe - load exe
636  */
hdl_lexe()637 static int hdl_lexe ()
638 {
639 DLLENT *dllent;
640 MODENT *modent;
641 
642     for(dllent = hdl_dll; dllent; dllent = dllent->dllnext);
643 
644     dllent->name = strdup("*Main");
645 
646     if(!(dllent->dll = (void*)GetModuleHandle( NULL ) ));
647     {
648         logmsg(_("HHCHD007E unable to open DLL %s: %s\n"),
649           dllent->name,dlerror());
650         free(dllent);
651         return -1;
652     }
653 
654     dllent->flags = HDL_LOAD_MAIN;
655 
656     if(!(dllent->hdldepc = dlsym(dllent->dll,HDL_DEPC_Q)))
657     {
658         logmsg(_("HHCHD013E No dependency section in %s: %s\n"),
659           dllent->name, dlerror());
660         free(dllent);
661         return -1;
662     }
663 
664     dllent->hdlinit = dlsym(dllent->dll,HDL_INIT_Q);
665 
666     dllent->hdlreso = dlsym(dllent->dll,HDL_RESO_Q);
667 
668     dllent->hdlddev = dlsym(dllent->dll,HDL_DDEV_Q);
669 
670     dllent->hdldins = dlsym(dllent->dll,HDL_DINS_Q);
671 
672     dllent->hdlfini = dlsym(dllent->dll,HDL_FINI_Q);
673 
674     /* No modules or device types registered yet */
675     dllent->modent = NULL;
676     dllent->hndent = NULL;
677     dllent->insent = NULL;
678 
679     obtain_lock(&hdl_lock);
680 
681     if(dllent->hdldepc)
682     {
683         if((dllent->hdldepc)(&hdl_dchk))
684         {
685             logmsg(_("HHCHD014E Dependency check failed for module %s\n"),
686               dllent->name);
687         }
688     }
689 
690     hdl_cdll = dllent;
691 
692     /* Call initializer */
693     if(hdl_cdll->hdlinit)
694         (dllent->hdlinit)(&hdl_regi);
695 
696     /* Insert current entry as first in chain */
697     dllent->dllnext = hdl_dll;
698     hdl_dll = dllent;
699 
700     /* Reset the loadcounts */
701     for(dllent = hdl_dll; dllent; dllent = dllent->dllnext)
702         for(modent = dllent->modent; modent; modent = modent->modnext)
703             modent->count = 0;
704 
705     /* Call all resolvers */
706     for(dllent = hdl_dll; dllent; dllent = dllent->dllnext)
707     {
708         if(dllent->hdlreso)
709             (dllent->hdlreso)(&hdl_fent);
710     }
711 
712     /* register any device types */
713     if(hdl_cdll->hdlddev)
714         (hdl_cdll->hdlddev)(&hdl_dvad);
715 
716     /* register any new instructions */
717     if(hdl_cdll->hdldins)
718         (hdl_cdll->hdldins)(&hdl_didf);
719 
720     hdl_cdll = NULL;
721 
722     release_lock(&hdl_lock);
723 
724     return 0;
725 }
726 #endif
727 
728 
729 /* hdl_main - initialize hercules dynamic loader
730  */
hdl_main(void)731 DLL_EXPORT void hdl_main (void)
732 {
733 HDLPRE *preload;
734 
735     initialize_lock(&hdl_lock);
736     initialize_lock(&hdl_sdlock);
737 
738     hdl_setpath(HDL_DEFAULT_PATH);
739 
740     dlinit();
741 
742     if(!(hdl_cdll = hdl_dll = malloc(sizeof(DLLENT))))
743     {
744         fprintf(stderr, _("HHCHD002E cannot allocate memory for DLL descriptor: %s\n"),
745           strerror(errno));
746         exit(1);
747     }
748 
749     hdl_cdll->name = strdup("*Hercules");
750 
751 /* This was a nice trick. Unfortunately, on some platforms  */
752 /* it becomes impossible. Some platforms need fully defined */
753 /* DLLs, some other platforms do not allow dlopen(self)     */
754 
755 #if 1
756 
757     if(!(hdl_cdll->dll = hdl_dlopen(NULL, RTLD_NOW )))
758     {
759         fprintf(stderr, _("HHCHD003E unable to open hercules as DLL: %s\n"),
760           dlerror());
761         exit(1);
762     }
763 
764     hdl_cdll->flags = HDL_LOAD_MAIN | HDL_LOAD_NOUNLOAD;
765 
766     if(!(hdl_cdll->hdldepc = dlsym(hdl_cdll->dll,HDL_DEPC_Q)))
767     {
768         fprintf(stderr, _("HHCHD012E No dependency section in %s: %s\n"),
769           hdl_cdll->name, dlerror());
770         exit(1);
771     }
772 
773     hdl_cdll->hdlinit = dlsym(hdl_cdll->dll,HDL_INIT_Q);
774 
775     hdl_cdll->hdlreso = dlsym(hdl_cdll->dll,HDL_RESO_Q);
776 
777     hdl_cdll->hdlddev = dlsym(hdl_cdll->dll,HDL_DDEV_Q);
778 
779     hdl_cdll->hdldins = dlsym(hdl_cdll->dll,HDL_DINS_Q);
780 
781     hdl_cdll->hdlfini = dlsym(hdl_cdll->dll,HDL_FINI_Q);
782 #else
783 
784     hdl_cdll->flags = HDL_LOAD_MAIN | HDL_LOAD_NOUNLOAD;
785 
786     hdl_cdll->hdldepc = &HDL_DEPC;
787 
788     hdl_cdll->hdlinit = &HDL_INIT;
789 
790     hdl_cdll->hdlreso = &HDL_RESO;
791 
792     hdl_cdll->hdlddev = &HDL_DDEV;
793 
794     hdl_cdll->hdldins = &HDL_DINS;
795 
796     hdl_cdll->hdlfini = &HDL_FINI;
797 #endif
798 
799     /* No modules or device types registered yet */
800     hdl_cdll->modent = NULL;
801     hdl_cdll->hndent = NULL;
802     hdl_cdll->insent = NULL;
803 
804     /* No dll's loaded yet */
805     hdl_cdll->dllnext = NULL;
806 
807     obtain_lock(&hdl_lock);
808 
809     if(hdl_cdll->hdldepc)
810         (hdl_cdll->hdldepc)(&hdl_dadd);
811 
812     if(hdl_cdll->hdlinit)
813         (hdl_cdll->hdlinit)(&hdl_regi);
814 
815     if(hdl_cdll->hdlreso)
816         (hdl_cdll->hdlreso)(&hdl_fent);
817 
818     if(hdl_cdll->hdlddev)
819         (hdl_cdll->hdlddev)(&hdl_dvad);
820 
821     if(hdl_cdll->hdldins)
822         (hdl_cdll->hdldins)(&hdl_didf);
823 
824     release_lock(&hdl_lock);
825 
826     /* Register termination exit */
827     hdl_adsc( "hdl_term", hdl_term, NULL);
828 
829     for(preload = hdl_preload; preload->name; preload++)
830         hdl_load(preload->name, preload->flag);
831 
832 #if defined(_MSVC_) && 0
833     hdl_lexe();
834 #endif
835 }
836 
837 
838 /* hdl_load - load a dll
839  */
hdl_load(char * name,int flags)840 DLL_EXPORT int hdl_load (char *name,int flags)
841 {
842 DLLENT *dllent, *tmpdll;
843 MODENT *modent;
844 char *modname;
845 
846     modname = (modname = strrchr(name,'/')) ? modname+1 : name;
847 
848     for(dllent = hdl_dll; dllent; dllent = dllent->dllnext)
849     {
850         if(strfilenamecmp(modname,dllent->name) == 0)
851         {
852             logmsg(_("HHCHD005E %s already loaded\n"),dllent->name);
853             return -1;
854         }
855     }
856 
857     if(!(dllent = malloc(sizeof(DLLENT))))
858     {
859         logmsg(_("HHCHD006S cannot allocate memory for DLL descriptor: %s\n"),
860           strerror(errno));
861         return -1;
862     }
863 
864     dllent->name = strdup(modname);
865 
866     if(!(dllent->dll = hdl_dlopen(name, RTLD_NOW)))
867     {
868         if(!(flags & HDL_LOAD_NOMSG))
869             logmsg(_("HHCHD007E unable to open DLL %s: %s\n"),
870               name,dlerror());
871         free(dllent);
872         return -1;
873     }
874 
875     dllent->flags = (flags & (~HDL_LOAD_WAS_FORCED));
876 
877     if(!(dllent->hdldepc = dlsym(dllent->dll,HDL_DEPC_Q)))
878     {
879         logmsg(_("HHCHD013E No dependency section in %s: %s\n"),
880           dllent->name, dlerror());
881         dlclose(dllent->dll);
882         free(dllent);
883         return -1;
884     }
885 
886     for(tmpdll = hdl_dll; tmpdll; tmpdll = tmpdll->dllnext)
887     {
888         if(tmpdll->hdldepc == dllent->hdldepc)
889         {
890             logmsg(_("HHCHD016E DLL %s is duplicate of %s\n"),
891               dllent->name, tmpdll->name);
892             dlclose(dllent->dll);
893             free(dllent);
894             return -1;
895         }
896     }
897 
898 
899     dllent->hdlinit = dlsym(dllent->dll,HDL_INIT_Q);
900 
901     dllent->hdlreso = dlsym(dllent->dll,HDL_RESO_Q);
902 
903     dllent->hdlddev = dlsym(dllent->dll,HDL_DDEV_Q);
904 
905     dllent->hdldins = dlsym(dllent->dll,HDL_DINS_Q);
906 
907     dllent->hdlfini = dlsym(dllent->dll,HDL_FINI_Q);
908 
909     /* No modules or device types registered yet */
910     dllent->modent = NULL;
911     dllent->hndent = NULL;
912     dllent->insent = NULL;
913 
914     obtain_lock(&hdl_lock);
915 
916     if(dllent->hdldepc)
917     {
918         if((dllent->hdldepc)(&hdl_dchk))
919         {
920             logmsg(_("HHCHD014E Dependency check failed for module %s\n"),
921               dllent->name);
922             if(!(flags & HDL_LOAD_FORCE))
923             {
924                 dlclose(dllent->dll);
925                 free(dllent);
926                 release_lock(&hdl_lock);
927                 return -1;
928             }
929             dllent->flags |= HDL_LOAD_WAS_FORCED;
930         }
931     }
932 
933     hdl_cdll = dllent;
934 
935     /* Call initializer */
936     if(hdl_cdll->hdlinit)
937         (dllent->hdlinit)(&hdl_regi);
938 
939     /* Insert current entry as first in chain */
940     dllent->dllnext = hdl_dll;
941     hdl_dll = dllent;
942 
943     /* Reset the loadcounts */
944     for(dllent = hdl_dll; dllent; dllent = dllent->dllnext)
945         for(modent = dllent->modent; modent; modent = modent->modnext)
946             modent->count = 0;
947 
948     /* Call all resolvers */
949     for(dllent = hdl_dll; dllent; dllent = dllent->dllnext)
950     {
951         if(dllent->hdlreso)
952             (dllent->hdlreso)(&hdl_fent);
953     }
954 
955     /* register any device types */
956     if(hdl_cdll->hdlddev)
957         (hdl_cdll->hdlddev)(&hdl_dvad);
958 
959     /* register any new instructions */
960     if(hdl_cdll->hdldins)
961         (hdl_cdll->hdldins)(&hdl_didf);
962 
963     hdl_cdll = NULL;
964 
965     release_lock(&hdl_lock);
966 
967     return 0;
968 }
969 
970 
971 /* hdl_dele - unload a dll
972  */
hdl_dele(char * name)973 DLL_EXPORT int hdl_dele (char *name)
974 {
975 DLLENT **dllent, *tmpdll;
976 MODENT *modent, *tmpmod;
977 DEVBLK *dev;
978 HDLDEV *hnd;
979 HDLINS *ins;
980 char *modname;
981 
982     modname = (modname = strrchr(name,'/')) ? modname+1 : name;
983 
984     obtain_lock(&hdl_lock);
985 
986     for(dllent = &(hdl_dll); *dllent; dllent = &((*dllent)->dllnext))
987     {
988         if(strfilenamecmp(modname,(*dllent)->name) == 0)
989         {
990             if((*dllent)->flags & (HDL_LOAD_MAIN | HDL_LOAD_NOUNLOAD))
991             {
992                 logmsg(_("HHCHD015E Unloading of %s not allowed\n"),(*dllent)->name);
993                 release_lock(&hdl_lock);
994                 return -1;
995             }
996 
997             for(dev = sysblk.firstdev; dev; dev = dev->nextdev)
998                 if(dev->pmcw.flag5 & PMCW5_V)
999                     for(hnd = (*dllent)->hndent; hnd; hnd = hnd->next)
1000                         if(hnd->hnd == dev->hnd)
1001                         {
1002                             logmsg(_("HHCHD008E Device %4.4X bound to %s\n"),dev->devnum,(*dllent)->name);
1003                             release_lock(&hdl_lock);
1004                             return -1;
1005                         }
1006 
1007             /* Call dll close routine */
1008             if((*dllent)->hdlfini)
1009             {
1010             int rc;
1011 
1012                 if((rc = ((*dllent)->hdlfini)()))
1013                 {
1014                     logmsg(_("HHCHD017E Unload of %s rejected by final section\n"),(*dllent)->name);
1015                     release_lock(&hdl_lock);
1016                     return rc;
1017                 }
1018             }
1019 
1020             modent = (*dllent)->modent;
1021             while(modent)
1022             {
1023                 tmpmod = modent;
1024 
1025                 /* remove current entry from chain */
1026                 modent = modent->modnext;
1027 
1028                 /* free module resources */
1029                 free(tmpmod->name);
1030                 free(tmpmod);
1031             }
1032 
1033             tmpdll = *dllent;
1034 
1035             /* remove current entry from chain */
1036             *dllent = (*dllent)->dllnext;
1037 
1038             for(hnd = tmpdll->hndent; hnd;)
1039             {
1040             HDLDEV *nexthnd;
1041                 free(hnd->name);
1042                 nexthnd = hnd->next;
1043                 free(hnd);
1044                 hnd = nexthnd;
1045             }
1046 
1047             for(ins = tmpdll->insent; ins;)
1048             {
1049             HDLINS *nextins;
1050 #ifdef ZZ_NO_BACKLINK
1051                 hdl_modify_opcode(FALSE, ins);
1052 #endif
1053                 free(ins->instname);
1054                 nextins = ins->next;
1055                 free(ins);
1056                 ins = nextins;
1057             }
1058 
1059 //          dlclose(tmpdll->dll);
1060 
1061             /* free dll resources */
1062             free(tmpdll->name);
1063             free(tmpdll);
1064 
1065             /* Reset the loadcounts */
1066             for(tmpdll = hdl_dll; tmpdll; tmpdll = tmpdll->dllnext)
1067                 for(tmpmod = tmpdll->modent; tmpmod; tmpmod = tmpmod->modnext)
1068                     tmpmod->count = 0;
1069 
1070             /* Call all resolvers */
1071             for(tmpdll = hdl_dll; tmpdll; tmpdll = tmpdll->dllnext)
1072             {
1073                 if(tmpdll->hdlreso)
1074                     (tmpdll->hdlreso)(&hdl_fent);
1075             }
1076 
1077             release_lock(&hdl_lock);
1078 
1079             return 0;
1080         }
1081 
1082     }
1083 
1084     release_lock(&hdl_lock);
1085 
1086     logmsg(_("HHCHD009E %s not found\n"),modname);
1087 
1088     return -1;
1089 }
1090 
1091 
1092 #ifdef ZZ_NO_BACKLINK
hdl_modify_optab(int insert,zz_func * tabent,HDLINS * instr)1093 static void hdl_modify_optab(int insert,zz_func *tabent, HDLINS *instr)
1094 {
1095     if(insert)
1096     {
1097 #if defined(_370)
1098         if(instr->archflags & HDL_INSTARCH_370)
1099         {
1100             instr->original = tabent[ARCH_370];
1101             tabent[ARCH_370] = instr->instruction;
1102         }
1103 #endif
1104 #if defined(_390)
1105         if(instr->archflags & HDL_INSTARCH_390)
1106         {
1107             instr->original = tabent[ARCH_390];
1108             tabent[ARCH_390] = instr->instruction;
1109         }
1110 #endif
1111 #if defined(_900)
1112         if(instr->archflags & HDL_INSTARCH_900)
1113         {
1114             instr->original = tabent[ARCH_900];
1115             tabent[ARCH_900] = instr->instruction;
1116         }
1117 #endif
1118     }
1119     else
1120     {
1121 #if defined(_370)
1122         if(instr->archflags & HDL_INSTARCH_370)
1123             tabent[ARCH_370] = instr->original;
1124 #endif
1125 #if defined(_900)
1126         if(instr->archflags & HDL_INSTARCH_390)
1127             tabent[ARCH_390] = instr->original;
1128 #endif
1129 #if defined(_900)
1130         if(instr->archflags & HDL_INSTARCH_900)
1131             tabent[ARCH_900] = instr->original;
1132 #endif
1133     }
1134 }
1135 
1136 
hdl_modify_opcode(int insert,HDLINS * instr)1137 static void hdl_modify_opcode(int insert, HDLINS *instr)
1138 {
1139     switch(instr->opcode & 0xff00)
1140     {
1141         case 0x0100:
1142             hdl_modify_optab(insert,opcode_01xx[instr->opcode & 0xff],instr);
1143             break;
1144 
1145 #if defined (FEATURE_VECTOR_FACILITY)
1146         case 0xA400:
1147             hdl_modify_optab(insert,v_opcode_a4xx[instr->opcode & 0xff],instr);
1148             table = v_opcode_a4xx;
1149             break;
1150 #endif
1151 
1152         case 0xA500:
1153             hdl_modify_optab(insert,opcode_a5xx[instr->opcode & 0x0f],instr);
1154             break;
1155 
1156         case 0xA700:
1157             hdl_modify_optab(insert,opcode_a7xx[instr->opcode & 0x0f],instr);
1158             break;
1159 
1160         case 0xB200:
1161             hdl_modify_optab(insert,opcode_b2xx[instr->opcode & 0xff],instr);
1162             break;
1163 
1164         case 0xB300:
1165             hdl_modify_optab(insert,opcode_b3xx[instr->opcode & 0xff],instr);
1166             break;
1167 
1168         case 0xB900:
1169             hdl_modify_optab(insert,opcode_b9xx[instr->opcode & 0xff],instr);
1170             break;
1171 
1172         case 0xC000:
1173             hdl_modify_optab(insert,opcode_c0xx[instr->opcode & 0x0f],instr);
1174             break;
1175 
1176         case 0xC200:
1177             hdl_modify_optab(insert,opcode_c2xx[instr->opcode & 0x0f],instr);
1178             break;
1179 
1180         case 0xC400:
1181             hdl_modify_optab(insert,opcode_c4xx[instr->opcode & 0x0f],instr);
1182             break;
1183 
1184         case 0xC600:
1185             hdl_modify_optab(insert,opcode_c6xx[instr->opcode & 0x0f],instr);
1186             break;
1187 
1188         case 0xC800:
1189             hdl_modify_optab(insert,opcode_c8xx[instr->opcode & 0x0f],instr);
1190             break;
1191 
1192         case 0xCC00:                                                              /*810*/
1193             hdl_modify_optab(insert,opcode_ccxx[instr->opcode & 0x0f],instr);     /*810*/
1194             break;                                                                /*810*/
1195 
1196         case 0xE300:
1197             hdl_modify_optab(insert,opcode_e3xx[instr->opcode & 0xff],instr);
1198             break;
1199 
1200         case 0xE500:
1201             hdl_modify_optab(insert,opcode_e5xx[instr->opcode & 0xff],instr);
1202             break;
1203 
1204         case 0xE600:
1205             hdl_modify_optab(insert,opcode_e6xx[instr->opcode & 0xff],instr);
1206             break;
1207 
1208         case 0xEB00:
1209             hdl_modify_optab(insert,opcode_ebxx[instr->opcode & 0xff],instr);
1210             break;
1211 
1212         case 0xEC00:
1213             hdl_modify_optab(insert,opcode_ecxx[instr->opcode & 0xff],instr);
1214             break;
1215 
1216         case 0xED00:
1217             hdl_modify_optab(insert,opcode_edxx[instr->opcode & 0xff],instr);
1218             break;
1219 
1220         default:
1221             hdl_modify_optab(insert,opcode_table[instr->opcode >> 8],instr);
1222     }
1223 
1224     /* Copy opcodes to shadow tables */
1225     copy_opcode_tables();
1226 
1227 }
1228 #endif
1229 
1230 
1231 /* hdl_didf - Define instruction call */
hdl_didf(int archflags,int opcode,char * name,void * routine)1232 static void hdl_didf (int archflags, int opcode, char *name, void *routine)
1233 {
1234 HDLINS *newins;
1235 
1236     newins = malloc(sizeof(HDLINS));
1237     newins->opcode = opcode > 0xff ? opcode : (opcode << 8) ;
1238     newins->archflags = archflags;
1239     newins->instname = strdup(name);
1240     newins->instruction = routine;
1241     newins->next = hdl_cdll->insent;
1242     hdl_cdll->insent = newins;
1243 #ifdef ZZ_NO_BACKLINK
1244     hdl_modify_opcode(TRUE, newins);
1245 #endif
1246 }
1247 
1248 #endif /*defined(OPTION_DYNAMIC_LOAD)*/
1249