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