|
|
1.1 root 1: /*
2: * INETCO Coherent Driver Load Program
3: *
4: * $Log: drvld.c,v $
5: * Revision 1.2 91/08/01 12:34:08 bin
6: * updated by stevesf to include :/etc/drvld in error messages
7: * produced by drvld
8: *
9: * Revision 1.3 91/07/31 13:44:11 bin
10: * steve 7/31/91
11: * Corrected additional fatal error message.
12: *
13: * Revision 1.2 91/07/31 13:40:09 bin
14: * steve 7/31/91
15: * In warn(), added line to print "/etc/drvld: " preceding warnings
16: * or fatal error messages.
17: *
18: * Revision 1.1 91/07/31 13:38:11 bin
19: * Initial revision
20: *
21: * Revision 1.2 88/07/07 09:30:37 src
22: * Bug: Drivers whose prefix consisted had a numeric third character
23: * were not recognized by the drvld(1M) command.
24: * Fix: A numeric third digit is ignored in driver symbol aliasing.
25: * ie: rs0con_ will be recognized when searching for con_.
26: *
27: * Revision 1.1 88/07/07 08:49:44 src
28: * Initial revision
29: *
30: * 87/12/01 Allan Cornish /usr/src/cmd/etc/drvld.c
31: * relocate() now properly relocates uninitialized data.
32: */
33: #include <stdio.h>
34: #include <canon.h>
35: #include <errno.h>
36: #include <l.out.h>
37: #include <signal.h>
38: #include <sys/fcntl.h>
39:
40: extern long lseek();
41:
42: /*
43: * The following three variables are obtained from kernel data space.
44: */
45: static int NSLOT; /* Number of driver data slots */
46: static int slotsz; /* Number of bytes per slot */
47: static int * slotp; /* Slot offset in kernel data */
48:
49: /*
50: * Local Variables.
51: */
52: char * ksym_file = "/coherent";/* Kernel symbol file name */
53: char * kmem_file = "/dev/kmem";/* Kernel data file name */
54: char * text_file; /* Driver code file name */
55: char * dsym_file;
56: unsigned kmem_end; /* End of kernel data space */
57: int verbose; /* Non-zero for verbose debug */
58: int ksym_fd = -1; /* Kernel obj file descriptor */
59: int dsym_fd = -1; /* Driver obj file descriptor */
60: int kmem_fd = -1; /* Kernel data file descriptor */
61: int text_fd = -1; /* Driver text file descriptor */
62: int slot; /* First slot in current driver */
63: int nslot; /* Number slots for curr driver */
64: unsigned datap; /* Ptr to driver data in kernel */
65: struct ldsym * dsym_tab; /* Driver symbol table */
66: struct ldsym * ksym_tab; /* Kernel symbol table */
67: int dsym_cnt; /* Number of driver symbols */
68: int ksym_cnt; /* Number of kernel symbols */
69: int dsym_len; /* Number of bytes of symbols */
70: unsigned char * drel_tab; /* Driver relocation table */
71: int drel_len; /* Number of relocation bytes */
72: int dflag; /* Enable debugging output */
73: int rflag; /* Remove output file after exec*/
74: int sflag; /* Strip symbols from output */
75: struct ldheader ldh_ker; /* Kernel load header */
76: struct ldheader ldh_drv; /* Driver load header */
77:
78: /*
79: * Forward referenced functions.
80: */
81: void startup();
82: void cleanup();
83: void warn();
84: void fatal();
85: void canldh();
86: void relocate();
87: long symoff();
88: void symsave();
89: struct ldsym * drvalias();
90: struct ldsym * ksymbol();
91: char * basename();
92:
93: main( argc, argv )
94: int argc;
95: char ** argv;
96: {
97: /*
98: * Perform system initialization.
99: */
100: startup( argv );
101:
102: /*
103: * Load drivers.
104: */
105: for ( argc = 0; dsym_file = *++argv; ) {
106: if ( **argv != '-' ) {
107: drvload();
108: argc++;
109: }
110: }
111:
112: /*
113: * No drivers loaded.
114: */
115: if ( argc == 0 )
116: fatal( "usage", ": drv [-k/coherent] [-r] [-s] file ..." );
117:
118: /*
119: * Perform system cleanup.
120: */
121: cleanup( 0 );
122: }
123:
124: /**
125: *
126: * void
127: * startup( argv ) -- perform system initialization.
128: * char ** argv;
129: *
130: * Input: argv = pointer to null-terminated list of arguments.
131: *
132: * Action: Process flag arguments.
133: * Obtain kernel symbolic information.
134: * Obtain kernel loadable driver characteristics.
135: */
136: void
137: startup( argv )
138: register char ** argv;
139: {
140: register struct ldsym * ksymp;
141: register char * cp;
142: register int sig;
143:
144: #if EBUG > 0
145: static char obuf[BUFSIZ];
146: setbuf( stdout, obuf );
147: #endif
148:
149: /*
150: * Only super-use can load drivers.
151: */
152: if ( getuid() != 0 )
153: fatal( "not super-user", "" );
154:
155: /*
156: * Trap non-ignored signals.
157: */
158: for ( sig = 1; sig <= NSIG; sig++ )
159: if ( signal( sig, SIG_IGN ) != SIG_IGN )
160: signal( sig, cleanup );
161:
162: /*
163: * Trap alarm signal.
164: */
165: signal( SIGALRM, cleanup );
166:
167: /*
168: * Scan argument list for flags.
169: */
170: while ( cp = *++argv ) {
171:
172: /*
173: * Ignore drivers to be loaded.
174: */
175: if ( *cp != '-' )
176: continue;
177:
178: while ( *++cp ) {
179: switch ( *cp ) {
180:
181: case 'd':
182: /*
183: * -d specifies debugging output.
184: */
185: dflag = 1;
186: break;
187:
188: case 'k':
189: /*
190: * -k <KERNEL> specifies kernel to load against.
191: */
192: if ( argv[1] == NULL )
193: fatal( "Missing file arg after ", "-k" );
194: if ( argv[1][0] == '-' )
195: fatal( "Invalid kernel file: ", *argv );
196: ksym_file = *++argv;
197: *argv = "-";
198: break;
199:
200: case 'o':
201: /*
202: * -o outputfile
203: */
204: if ( argv[1] == NULL )
205: fatal( "Missing file arg after ", "-o" );
206: if ( argv[1][0] == '-' )
207: fatal( "Invalid output file: ", *argv );
208: text_file = *++argv;
209: *argv = "-";
210: break;
211:
212: case 'r':
213: /*
214: * -r removes output file after loading.
215: */
216: rflag = 1;
217: break;
218:
219: case 's':
220: /*
221: * -s strips symbols from output file.
222: */
223: sflag = 1;
224: break;
225:
226: case 'v':
227: /*
228: * -v turns verbose monitoring on.
229: */
230: verbose++;
231: break;
232:
233: default:
234: fatal( "Invalid flag: -", cp );
235: }
236: }
237: }
238:
239: /*
240: * Obtain kernel object module header.
241: */
242: ksym_fd = get_ldh( ksym_file, &ldh_ker );
243:
244: /*
245: * Kernel must not be relocatable.
246: */
247: if ( (ldh_ker.l_flag & LF_NRB) == 0 )
248: fatal( ksym_file, ": relocatable" );
249:
250: /*
251: * Allocate memory space for kernel symbol table.
252: */
253: ksym_cnt = ldh_ker.l_ssize[L_SYM] / sizeof(struct ldsym);
254: if ( (ksym_tab = malloc( (int) ldh_ker.l_ssize[L_SYM])) == NULL )
255: fatal( ksym_file, ": symbol table too large" );
256:
257: #if EBUG > 0
258: if ( dflag ) {
259: printf("startup: ksym_cnt=%d ksym_len=%d ksym_tab=%04x\n",
260: ksym_cnt, (int) ldh_ker.l_ssize[L_SYM], ksym_tab );
261: }
262: #endif
263:
264: /*
265: * Extract kernel symbol table from object module.
266: */
267: if ( lseek( ksym_fd, (long) symoff(&ldh_ker), 0 ) < 0 )
268: fatal( ksym_file, ": bad seek" );
269: if ( read( ksym_fd, ksym_tab, (int) ldh_ker.l_ssize[L_SYM] ) <= 0 )
270: fatal( ksym_file, ": bad read" );
271:
272: /*
273: * Open kernel data space.
274: */
275: if ((kmem_fd = open( kmem_file, O_RDWR )) < 0 )
276: fatal( kmem_file, ": can't open.");
277:
278: /*
279: * Obtain address of end of kernel data space - end.
280: */
281: if ( (ksymp = ksymbol( "end_" )) == NULL )
282: fatal( ksym_file, ": symbol 'end' not found" );
283: kmem_end = ksymp->ls_addr;
284:
285: /*
286: * Read NSLOT kernel variable.
287: */
288: if ( (ksymp = ksymbol( "NSLOT_" )) == NULL )
289: fatal( ksym_file, ": symbol NSLOT not found" );
290: if ( (lseek( kmem_fd, (long) ksymp->ls_addr, 0 ) < 0)
291: || (read( kmem_fd, &NSLOT, sizeof(NSLOT) ) < 0) )
292: fatal( kmem_file, ": can't access NSLOT var");
293:
294: /*
295: * Read slotsz kernel variable.
296: */
297: if ( (ksymp = ksymbol( "slotsz_" )) == NULL )
298: fatal( ksym_file, ": symbol slotsz not found" );
299: if ( (lseek( kmem_fd, (long) ksymp->ls_addr, 0 ) < 0)
300: || (read( kmem_fd, &slotsz, sizeof(slotsz) ) < 0) )
301: fatal( kmem_file, ": can't access slotsz var");
302:
303: /*
304: * Read slotp kernel variable.
305: */
306: if ( (ksymp = ksymbol( "slotp_" )) == NULL )
307: fatal( ksym_file, ": symbol slotp not found" );
308: if ( (lseek( kmem_fd, (long) ksymp->ls_addr, 0 ) < 0)
309: || (read( kmem_fd, &slotp, sizeof(slotp) ) < 0) )
310: fatal( kmem_file, ": can't access slotp var");
311:
312: #if EBUG > 0
313: if ( dflag )
314: printf("NSLOT=%d slotsz=%d slotp=%04x end=%04x\n",
315: NSLOT, slotsz, slotp, kmem_end );
316: #endif
317:
318: /*
319: * Validate kernel variables - NSLOT, slotsz, slotp.
320: */
321: if ( (NSLOT <= 0) || (slotsz <= 0) || (slotp == NULL) )
322: fatal( kmem_file, ": loadable drivers disabled." );
323: }
324:
325: /**
326: *
327: * void
328: * cleanup( sig ) -- clean up and terminate.
329: * int sig;
330: *
331: * Input: sig = signal causing termination, or 0.
332: *
333: * Action: Close special files.
334: * Exit.
335: */
336: void
337: cleanup( sig )
338: int sig;
339: {
340: /*
341: * Quietly accept alarm signals.
342: */
343: if ( sig == SIGALRM ) {
344: signal( sig, cleanup );
345: return;
346: }
347:
348: /*
349: * Remove output files.
350: */
351: if ( (sig != 0) || (rflag != 0) && (text_file[0] != 0) )
352: unlink( text_file );
353:
354: exit( sig );
355: }
356:
357: /**
358: *
359: * void
360: * warn( s1, s2 ) -- print error message.
361: * char * s1;
362: * char * s2;
363: *
364: * Input: s1 = pointer to null-terminated error string.
365: * s2 = pointer to null-terminated error string.
366: *
367: * Action: Output error messages.
368: * Output new-line.
369: */
370: void
371: warn( s1, s2 )
372: char * s1;
373: char * s2;
374: {
375: #if EBUG > 0
376: fflush( stdout );
377: fflush( stderr );
378: #endif
379:
380: write( 2, "/etc/drvld: ", 12);
381: write( 2, s1, strlen(s1) );
382: write( 2, s2, strlen(s2) );
383: write( 2, "\n", 1 );
384: }
385:
386: /**
387: *
388: * void
389: * fatal( s1, s2 ) -- print fatal error message, terminate.
390: * char * s1;
391: * char * s2;
392: *
393: * Input: s1 = pointer to null-terminated error string.
394: * s2 = pointer to null-terminated error string.
395: *
396: * Action: Output error messages.
397: * Output new-line.
398: * Exit with status 100.
399: */
400: void
401: fatal( s1, s2 )
402: char * s1;
403: char * s2;
404: {
405: warn( s1, s2 );
406: cleanup( 100 );
407: }
408:
409: /**
410: *
411: * void
412: * canldh( ldp ) - Convert a load file header from canonical form.
413: * ldheader * ldp;
414: *
415: * Input: ldp = pointer to load file header to be [de]canonized.
416: *
417: * Action: Convert load file header to/from canonical form.
418: */
419: void
420: canldh( ldp )
421: register struct ldheader * ldp;
422: {
423: register int seg;
424:
425: canint( ldp->l_magic );
426: canint( ldp->l_flag );
427: canint( ldp->l_machine );
428: canvaddr( ldp->l_entry );
429:
430: for ( seg = 0; seg < NLSEG; seg++ )
431: cansize( ldp->l_ssize[seg] );
432: }
433:
434: /**
435: *
436: * int
437: * drvload() - Spawn a kernel process.
438: *
439: * Action: Validate object module.
440: * Allocate and initialize kernel data slots for driver.
441: * Create and initialize driver code file.
442: * Create driver symbol table.
443: * Apply relocation to driver code and data.
444: * Fork and execute the driver code.
445: */
446: drvload()
447: {
448: register int n;
449: int cpid;
450: long off;
451: static char buf[BUFSIZ];
452: static char nambuf[64];
453:
454: /*
455: * Define name of driver code file if not already specified.
456: */
457: if ( (text_file == NULL) || (text_file == nambuf) ) {
458: text_file = nambuf;
459: strcpy( nambuf, "/tmp/" );
460: strcat( nambuf, basename(dsym_file) );
461: }
462:
463: /*
464: * Obtain driver object module header.
465: */
466: dsym_fd = get_ldh( dsym_file, &ldh_drv );
467:
468: /*
469: * Driver must be relocatable.
470: */
471: if ( ldh_drv.l_flag & LF_NRB )
472: fatal( dsym_file, ": not relocatable" );
473:
474: /*
475: * Build symbol table from driver and referenced kernel symbols.
476: * Allocate kernel data space.
477: * Adjust data relative symbols.
478: */
479: symload();
480: drvalloc();
481: symadjust();
482:
483: /*
484: * Prepare to install driver data into allocated slots.
485: */
486: off = sizeof(ldh_drv)+ldh_drv.l_ssize[L_SHRI]+ldh_drv.l_ssize[L_PRVI];
487: if ( lseek( dsym_fd, (long) off, 0 ) < 0 )
488: fatal( dsym_file, ": bad seek" );
489: if ( lseek( kmem_fd, (long) datap, 0 ) < 0 )
490: fatal( kmem_file, ": bad seek" );
491:
492: #if EBUG > 0
493: if ( dflag )
494: printf("driver data at kernel offset %04x\n", datap );
495: #endif
496:
497: /*
498: * Install initialized driver data.
499: */
500: off = ldh_drv.l_ssize[L_SHRD] + ldh_drv.l_ssize[L_PRVD];
501: #if EBUG > 0
502: if ( dflag ) printf("initialized data = %ld bytes\n", off );
503: #endif
504: while ( off > 0 ) {
505: n = (off > BUFSIZ) ? BUFSIZ : off;
506: if ( read( dsym_fd, buf, n ) != n )
507: fatal( dsym_file, ": truncated" );
508: if ( write( kmem_fd, buf, n ) != n )
509: fatal( kmem_file, ": bad write" );
510: #if EBUG > 0
511: if ( dflag ) printf("write %d bytes\n", n );
512: #endif
513: off -= n;
514: }
515:
516: /*
517: * Erase uninitialized driver data.
518: */
519: memset( buf, 0, sizeof(buf) );
520: off = ldh_drv.l_ssize[L_BSSD];
521: #if EBUG > 0
522: if ( dflag ) printf("uninitialized data = %ld bytes\n", off );
523: #endif
524: while ( off > 0 ) {
525: n = (off > BUFSIZ) ? BUFSIZ : off;
526: if ( write( kmem_fd, buf, n ) != n )
527: fatal( kmem_file, ": bad write" );
528: #if EBUG > 0
529: if ( dflag ) printf("clear %d bytes\n", n );
530: #endif
531: off -= n;
532: }
533:
534: /*
535: * Create driver code file.
536: */
537: unlink( text_file );
538: if ( (text_fd = creat( text_file, 0700)) < 0 )
539: fatal( text_file, ": can't create" );
540: close( text_fd );
541: if ( (text_fd = open( text_file, O_RDWR)) < 0 )
542: fatal( text_file, ": can't reopen" );
543:
544: /*
545: * Prepare to install driver code into new file.
546: */
547: if ( lseek( dsym_fd, (long) sizeof(ldh_drv), 0 ) < 0 )
548: fatal( dsym_file, ": bad seek" );
549: if ( lseek( text_fd, (long) sizeof(ldh_drv), 0 ) < 0 )
550: fatal( text_file, ": bad seek" );
551:
552: /*
553: * Install initialized driver code.
554: */
555: off = ldh_drv.l_ssize[L_SHRI] + ldh_drv.l_ssize[L_PRVI];
556: #if EBUG > 0
557: if ( dflag ) printf("initialized code = %ld bytes\n", off );
558: #endif
559: while ( off > 0 ) {
560: n = (off > BUFSIZ) ? BUFSIZ : off;
561: if ( read( dsym_fd, buf, n ) != n )
562: fatal( dsym_file, ": truncated" );
563: if ( write( text_fd, buf, n ) != n )
564: fatal( text_file, ": bad write" );
565: off -= n;
566: }
567:
568: /*
569: * Apply relocation directives to driver code and data.
570: */
571: relocate();
572:
573: /*
574: * Save symbol table in driver code file.
575: */
576: symsave();
577:
578: /*
579: * Close driver files.
580: */
581: close( dsym_fd );
582: close( text_fd );
583: fflush( stdout );
584: sync();
585:
586: /*
587: * Load driver - spawning kernel process.
588: */
589: if ( (cpid = sload(text_file)) < 0 )
590: fatal( text_file, ": can't load driver\n" );
591:
592: /*
593: * Lock all data slots required by server process.
594: */
595: for ( n = slot + nslot; --n >= slot; ) {
596: /*
597: * Lock data slot or kill server and terminate.
598: */
599: if ( skword( &slotp[n], cpid ) < 0 ) {
600: kill( cpid, SIGKILL );
601: fatal( kmem_file, ": bad write" );
602: }
603: }
604:
605: #if EBUG > 0 )
606: if ( dflag )
607: printf("Driver process id = %d\n", cpid );
608: #endif
609:
610: /*
611: * Remove text file.
612: */
613: if ( rflag )
614: unlink( text_file );
615: }
616:
617: /**
618: *
619: * int
620: * drvalloc() - Allocate kernel data slots.
621: */
622: int
623: drvalloc()
624: {
625: int baseslot = 0;
626: int pid;
627:
628: /*
629: * Determine number of required driver data slots.
630: */
631: nslot = (ldh_drv.l_ssize[L_SHRD] + ldh_drv.l_ssize[L_PRVD] +
632: ldh_drv.l_ssize[L_BSSD] + slotsz - 1) / slotsz;
633:
634: #if EBUG > 0
635: if ( dflag )
636: printf( "drvalloc: nslot=%d\n", nslot );
637: #endif
638:
639: /*
640: * No data space required.
641: */
642: if ( nslot == 0 ) {
643: datap = (unsigned) (&slotp[NSLOT]);
644: slot = 0;
645: return;
646: }
647:
648: /*
649: * Allocate driver data slots.
650: */
651: for ( slot = 0; slot < NSLOT; ) {
652:
653: #if EBUG > 0
654: if ( dflag )
655: printf( "checking slot %d ", slot );
656: #endif
657:
658: /*
659: * Obtain slot process id.
660: */
661: if ( fkword( &slotp[slot], &pid ) < 0 )
662: fatal( kmem_file, ": bad slot pid read." );
663:
664: #if EBUG > 0
665: if ( dflag )
666: printf("pid=%d\n", pid );
667: #endif
668:
669: /*
670: * Slot is not allocated.
671: */
672: if ( pid == 0 )
673: ;
674:
675: /*
676: * Validate process id and existence.
677: */
678: else if ( (pid < 0) || (kill(pid,0) < 0) ) {
679:
680: #if EBUG > 0
681: if ( dflag )
682: printf( "clearing slot %d\n", slot );
683: #endif
684:
685: /*
686: * Erase slot process id - this makes the slot empty.
687: */
688: if ( skword( &slotp[slot], 0 ) < 0 )
689: fatal( kmem_file, ": can't free slot." );
690:
691: pid = 0;
692: }
693:
694: /*
695: * Ignore busy slots.
696: */
697: if ( pid != 0 ) {
698: baseslot = ++slot;
699: continue;
700: }
701:
702: /*
703: * Sufficient contiguous slots found.
704: */
705: if ( (++slot - baseslot) >= nslot )
706: break;
707: }
708:
709: /*
710: * Insufficient contiguous slot space.
711: */
712: if ( (slot - baseslot) < nslot )
713: fatal( dsym_file, ": out of driver memory" );
714:
715: #if EBUG > 0
716: if ( dflag )
717: printf("%d slots allocated starting at slot %d\n",
718: nslot, baseslot );
719: #endif
720:
721: /*
722: * Compute offset of driver data in kernel memory.
723: */
724: datap = (unsigned) (&slotp[NSLOT]) + (baseslot * slotsz);
725: slot = baseslot;
726: }
727:
728: /**
729: *
730: * int
731: * get_ldh( filename, ldp )
732: * char * filename;
733: * struct ldheader * ldp;
734: *
735: * Input: filename = name of object file to be accessed.
736: * ldp = pointer to load header to be initialized.
737: *
738: * Return: Read-only file descriptor on object file.
739: */
740: int
741: get_ldh( filename, ldp )
742: char * filename;
743: register struct ldheader * ldp;
744: {
745: register int fd;
746:
747: /*
748: * Obtain kernel object module header.
749: */
750: if ( (fd = open(filename, O_RDONLY)) < 0 )
751: fatal( filename, ": can't open" );
752: if ( read( fd, ldp, sizeof(*ldp) ) < 0 )
753: fatal( filename, ": truncated" );
754:
755: /*
756: * Convert from canonical to machine format.
757: */
758: canldh( ldp );
759:
760: /*
761: * Validate object module.
762: */
763: if ( ldp->l_magic != L_MAGIC )
764: fatal( filename, ": not an object file" );
765: if ( ldp->l_machine != M_8086 )
766: fatal( filename, ": not an iAPX-86 object file" );
767:
768: /*
769: * Return read-only file descriptor.
770: */
771: return( fd );
772: }
773:
774: /**
775: *
776: * void
777: * relocate() - apply relocation directives to driver code and data.
778: *
779: * NOTE: This function only works on a iAPX-86 relocating iAPX-86 code.
780: */
781: void
782: relocate()
783: {
784: register unsigned char * cp;
785: long off;
786: unsigned char opcode;
787: unsigned short addr;
788: unsigned short symno;
789: unsigned short bias;
790: int txtlen;
791:
792: #if EBUG > 0
793: if ( dflag )
794: printf("relocate()\n");
795: #endif
796:
797: /*
798: * No relocation directives.
799: */
800: if ( (drel_len = ldh_drv.l_ssize[L_REL]) == 0 )
801: return;
802:
803: /*
804: * Calculate offset of relocation information.
805: */
806: off = sizeof(ldh_drv) + ldh_drv.l_ssize[L_SHRI ] +
807: ldh_drv.l_ssize[L_PRVI ] +
808: ldh_drv.l_ssize[L_SHRD ] +
809: ldh_drv.l_ssize[L_PRVD ] +
810: ldh_drv.l_ssize[L_DEBUG] +
811: ldh_drv.l_ssize[L_SYM ];
812:
813: /*
814: * Compute boundary location between code and data relocation.
815: */
816: txtlen = ldh_drv.l_ssize[L_SHRI] +
817: ldh_drv.l_ssize[L_PRVI] +
818: ldh_drv.l_ssize[L_BSSI];
819:
820: /*
821: * Obtain in-memory copy of driver relocation directives.
822: */
823: if ( (drel_tab = malloc( drel_len )) == NULL )
824: fatal( dsym_file, ": too many relocation directives" );
825: if ( lseek( dsym_fd, off, 0 ) < 0 )
826: fatal( dsym_file, ": bad seek" );
827: if ( read( dsym_fd, drel_tab, drel_len ) != drel_len )
828: fatal( dsym_file, ": bad read" );
829:
830: #if EBUG > 0
831: if ( dflag )
832: printf("drel_tab=%04x drel_len=%d\n", drel_tab, drel_len );
833: #endif
834:
835: /*
836: * Scan driver relocation directives.
837: */
838: for ( cp = drel_tab; drel_len >= 3; ) {
839:
840: /*
841: * Clear bias [high byte may not be read]
842: */
843: bias = 0;
844:
845: /*
846: * Read opcode and address.
847: */
848: opcode = cp[0];
849: addr = (cp[2] << 8) + cp[1];
850: drel_len -= 3;
851: cp += 3;
852:
853: /*
854: * Obtain code to be relocated.
855: */
856: if ( addr < txtlen ) {
857: off = sizeof(struct ldheader) + addr;
858: if ( lseek( text_fd, off, 0 ) < 0 )
859: fatal( text_file, ": bad seek" );
860: if (read(text_fd, &bias, (opcode & LR_WORD)?2:1) < 0)
861: fatal( text_file, ": bad read" );
862: }
863:
864: /*
865: * Obtain data to be relocated.
866: */
867: else {
868: off = datap + addr - txtlen;
869: if ( lseek( kmem_fd, off, 0 ) < 0 )
870: fatal( kmem_file, ": bad seek" );
871: if (read(kmem_fd, &bias, (opcode & LR_WORD)?2:1) < 0)
872: fatal( kmem_file, ": bad read" );
873: }
874:
875: #if EBUG > 0
876: if ( dflag )
877: printf("opcode=%02x, addr=%04x, offset=%04x, bias=%04x",
878: opcode, addr, (int) off, bias );
879: #endif
880:
881: /*
882: * Perform relocation.
883: * NOTE: Program Counter Relative relocation is ignored,
884: * since no code is being inserted.
885: */
886: switch ( opcode & LR_SEG ) {
887:
888: case L_SHRI:
889: case L_PRVI:
890: case L_BSSI:
891: /*
892: * No relocation required - no code was inserted.
893: */
894: #if EBUG > 0
895: if ( dflag )
896: printf("\n");
897: #endif
898: continue;
899:
900: case L_BSSD:
901: case L_PRVD:
902: case L_SHRD:
903: bias -= txtlen;
904: bias += datap;
905: break;
906:
907: case L_SYM:
908: /*
909: * Obtain symbol number.
910: */
911: symno = (cp[1] << 8) + cp[0];
912: drel_len -= 2;
913: cp += 2;
914:
915: /*
916: * Validate symbol number.
917: */
918: if ( (symno < 0) || (symno >= dsym_cnt) )
919: fatal( dsym_file, ": bad relocation" );
920:
921: #if EBUG > 0
922: if ( dflag )
923: printf("\n\t\t\t\tsymid=%.*s symaddr=%04x ",
924: NCPLN, dsym_tab[symno].ls_id,
925: dsym_tab[symno].ls_addr );
926: #endif
927:
928: /*
929: * Access symbol.
930: */
931: bias += dsym_tab[symno].ls_addr;
932: break;
933: }
934:
935: #if EBUG > 0
936: if ( dflag )
937: printf(" --> %04x\n", bias );
938: #endif
939:
940: /*
941: * Save relocated code.
942: */
943: if ( addr < txtlen ) {
944: if ( lseek( text_fd, off, 0 ) < 0 )
945: fatal( text_file, ": bad seek" );
946: if (write(text_fd, &bias, (opcode & LR_WORD)?2:1) < 0)
947: fatal( text_file, ": bad write" );
948: }
949:
950: /*
951: * Save relocated data.
952: */
953: else {
954: if ( lseek( kmem_fd, off, 0 ) < 0 )
955: fatal( kmem_file, ": bad seek" );
956: if (write(kmem_fd, &bias, (opcode & LR_WORD)?2:1) < 0)
957: fatal( kmem_file, ": bad write" );
958: }
959: }
960:
961: /*
962: * Release malloc'ed storage.
963: */
964: free( drel_tab );
965: }
966:
967: /**
968: *
969: * int
970: * symload() - load driver symbol table
971: */
972: symload()
973: {
974: register struct ldsym * dsymp;
975: register struct ldsym * ksymp;
976: long off;
977: int undef;
978:
979: /*
980: * Allocate memory space for driver symbol table.
981: */
982: dsym_cnt = ldh_drv.l_ssize[L_SYM] / sizeof(struct ldsym);
983: dsym_len = ldh_drv.l_ssize[L_SYM];
984: if ( (dsym_cnt != 0) && ((dsym_tab = malloc(dsym_len)) == NULL) )
985: fatal( dsym_file, ": symbol table too large" );
986:
987: #if EBUG > 0
988: if ( dflag ) {
989: printf("symload: dsym_cnt=%d dsym_len=%d\n", dsym_cnt, dsym_len );
990: printf("dsym_tab=%04x\n", dsym_tab );
991: }
992: #endif
993:
994: if ( dsym_cnt == 0 )
995: return;
996:
997: /*
998: * Extract driver symbol table from object module.
999: */
1000: if ( lseek( dsym_fd, (long) symoff(&ldh_drv), 0 ) < 0 )
1001: fatal( dsym_file, ": bad seek" );
1002: if (read(dsym_fd, dsym_tab, (int) ldh_drv.l_ssize[L_SYM]) <= 0)
1003: fatal( dsym_file, ": bad read" );
1004:
1005: /*
1006: * 1st Pass: Adjust symbol offsets.
1007: */
1008: for ( dsymp = &dsym_tab[dsym_cnt]; --dsymp >= dsym_tab; ) {
1009:
1010: switch ( dsymp->ls_type & LR_SEG ) {
1011:
1012: case L_SHRI:
1013: case L_PRVI:
1014: case L_BSSI:
1015: case L_ABS:
1016: /*
1017: * Leave code/absolute data references alone.
1018: */
1019: break;
1020:
1021: case L_SHRD:
1022: case L_PRVD:
1023: case L_BSSD:
1024: /*
1025: * Convert data references to uninitialized data ref.
1026: */
1027: dsymp->ls_type &= ~LR_SEG;
1028: dsymp->ls_type |= L_BSSD;
1029: #if EBUG > 0
1030: if ( dflag )
1031: printf("%.*s: DRIVER type=%d addr=%04x\n",
1032: NCPLN, dsymp->ls_id,
1033: dsymp->ls_type, dsymp->ls_addr );
1034: #endif
1035: break;
1036: }
1037: }
1038:
1039: /*
1040: * 2nd Pass: Resolve undefined references.
1041: */
1042: for ( undef = 0, dsymp = &dsym_tab[dsym_cnt]; --dsymp >= dsym_tab; ) {
1043:
1044: if ( (dsymp->ls_type & LR_SEG) != L_REF )
1045: continue;
1046:
1047: /*
1048: * Check for aliased driver configuration.
1049: * ie: 'con_' is an alias for '??con_'
1050: */
1051: if ( ksymp = drvalias(dsymp->ls_id) ) {
1052:
1053: #if EBUG > 0
1054: if ( dflag )
1055: printf("Driver prefix = '%.2s'\n",
1056: ksymp->ls_id );
1057: #endif
1058:
1059: /*
1060: * Update symbol information.
1061: */
1062: dsymp->ls_type = ksymp->ls_type;
1063: dsymp->ls_addr = ksymp->ls_addr;
1064:
1065: #if EBUG > 0
1066: if ( dflag )
1067: printf("%.*s: ALIAS %.*s type=%d addr=%04x\n",
1068: NCPLN, dsymp->ls_id,
1069: NCPLN, ksymp->ls_id,
1070: dsymp->ls_type, dsymp->ls_addr );
1071: #endif
1072: }
1073:
1074: /*
1075: * Search for undefined symbol in kernel symbol table.
1076: */
1077: else if ( ksymp = ksymbol( dsymp->ls_id ) ) {
1078: /*
1079: * Update symbol information.
1080: */
1081: dsymp->ls_type = ksymp->ls_type;
1082: dsymp->ls_addr = ksymp->ls_addr;
1083:
1084: /*
1085: * Convert kernel data references to absolute.
1086: */
1087: if ( ((dsymp->ls_type & LR_SEG) >= L_SHRD)
1088: && ((dsymp->ls_type & LR_SEG) <= L_BSSD) ) {
1089: dsymp->ls_type &= ~LR_SEG;
1090: dsymp->ls_type |= L_ABS;
1091: }
1092:
1093: #if EBUG > 0
1094: if ( dflag )
1095: printf("%.*s: KERNEL type=%d addr=%04x\n",
1096: NCPLN, dsymp->ls_id,
1097: dsymp->ls_type, dsymp->ls_addr );
1098: #endif
1099: }
1100:
1101: /*
1102: * Define commons as uninitialized data.
1103: */
1104: else if ( dsymp->ls_addr > 0 ) {
1105: /*
1106: * Ensure data size is even.
1107: */
1108: dsymp->ls_addr += 1;
1109: dsymp->ls_addr &= ~1;
1110:
1111: /*
1112: * Convert symbol to uninitialized data.
1113: */
1114: dsymp->ls_type &= ~LR_SEG;
1115: dsymp->ls_type |= L_BSSD;
1116:
1117: /*
1118: * Calculate new location of symbol.
1119: */
1120: off = ldh_drv.l_ssize[L_SHRI] +
1121: ldh_drv.l_ssize[L_PRVI] +
1122: ldh_drv.l_ssize[L_BSSI] +
1123: ldh_drv.l_ssize[L_SHRD] +
1124: ldh_drv.l_ssize[L_PRVD] +
1125: ldh_drv.l_ssize[L_BSSD];
1126:
1127: /*
1128: * Adjust size of uninitialized data.
1129: * Record new location of symbol.
1130: */
1131: ldh_drv.l_ssize[L_BSSD] += dsymp->ls_addr;
1132: dsymp->ls_addr = off;
1133:
1134: #if EBUG > 0
1135: if ( dflag )
1136: printf("%.*s: COMMON type=%d addr=%04x\n",
1137: NCPLN, dsymp->ls_id,
1138: dsymp->ls_type, dsymp->ls_addr );
1139: #endif
1140: }
1141:
1142: /*
1143: * Undefined symbol.
1144: */
1145: else {
1146: undef++;
1147: dsymp->ls_id[NCPLN] = 0;
1148: warn( dsymp->ls_id, ": undefined symbol" );
1149: }
1150: }
1151:
1152: /*
1153: * Terminate if symbols undefined.
1154: */
1155: if ( undef )
1156: cleanup( 100 );
1157: }
1158:
1159: /**
1160: *
1161: * void
1162: * symadjust() -- Adjust addresses of driver data symbols.
1163: *
1164: * NOTE: Has to be done AFTER kernel data space allocation.
1165: */
1166: symadjust()
1167: {
1168: register struct ldsym * dsymp;
1169: register unsigned txtlen;
1170:
1171: if ( dsym_cnt == 0 )
1172: return;
1173:
1174: txtlen = ldh_drv.l_ssize[L_SHRI] +
1175: ldh_drv.l_ssize[L_PRVI] +
1176: ldh_drv.l_ssize[L_BSSI];
1177:
1178: /*
1179: * Search driver symbol table.
1180: */
1181: for ( dsymp = &dsym_tab[ dsym_cnt ]; --dsymp >= dsym_tab; ) {
1182:
1183: /*
1184: * All driver data references are specified as uninitialized.
1185: * All kernel data references are specified as absolute.
1186: */
1187: if ( (dsymp->ls_type & LR_SEG) != L_BSSD )
1188: continue;
1189:
1190: #if EBUG > 0
1191: if ( dflag )
1192: printf("adjusting %.*s [type %d] from %04x by %04x\n",
1193: NCPLN, dsymp->ls_id,
1194: dsymp->ls_type,
1195: dsymp->ls_addr,
1196: datap );
1197: #endif
1198:
1199: /*
1200: * Validate data address.
1201: */
1202: if ( dsymp->ls_addr < txtlen ) {
1203: dsymp->ls_id[NCPLN] = 0;
1204: fatal( dsymp->ls_id, ": invalid address" );
1205: }
1206:
1207: /*
1208: * Adjust address of data symbol.
1209: * Separate code/data eliminates relocation after code.
1210: * Insertion into kernel data adds slot relocation.
1211: */
1212: dsymp->ls_addr -= txtlen;
1213: dsymp->ls_addr += datap;
1214: }
1215: }
1216:
1217: /**
1218: *
1219: * struct ldsym *
1220: * drvalias( s ) - Search driver for alias for undefined symbol.
1221: * char * s;
1222: */
1223: struct ldsym *
1224: drvalias( sym_id )
1225: register char * sym_id;
1226: {
1227: register struct ldsym * symp;
1228:
1229: /*
1230: * No driver symbols.
1231: */
1232: if ( dsym_cnt == 0 )
1233: return( NULL );
1234:
1235: /*
1236: * Not a symbol which can be aliased.
1237: */
1238: if ( strncmp("con_", sym_id, NCPLN ) != 0 )
1239: return( NULL );
1240:
1241: /*
1242: * Scan driver symbol table [backwards for efficiency].
1243: */
1244: for ( symp = &dsym_tab[dsym_cnt]; --symp >= dsym_tab; ) {
1245:
1246: /*
1247: * Ignore all except code/data declarations.
1248: */
1249: if ( (symp->ls_type & LR_SEG) > L_BSSD )
1250: continue;
1251:
1252: /*
1253: * Check id after discarding two char driver prefix.
1254: */
1255: if ( strncmp( sym_id, &symp->ls_id[2], NCPLN-2 ) == 0 )
1256: return( symp );
1257:
1258: /*
1259: * Bypass id if 3rd char is not a numeric digit.
1260: */
1261: if ( (symp->ls_id[2] < '0') || (symp->ls_id[2] > '9') )
1262: continue;
1263:
1264: /*
1265: * Check id after discarding three char driver prefix.
1266: */
1267: if ( strncmp( sym_id, &symp->ls_id[3], NCPLN-3 ) == 0 )
1268: return( symp );
1269: }
1270:
1271: return( NULL );
1272: }
1273:
1274: /**
1275: *
1276: * struct ldsym *
1277: * ksymbol( s ) - Search kernel for undefined symbol.
1278: * char * s;
1279: */
1280: struct ldsym *
1281: ksymbol( sym_id )
1282: register char * sym_id;
1283: {
1284: register struct ldsym * ksymp;
1285: register int i;
1286: char id[NCPLN];
1287:
1288: /*
1289: * Find last character in symbol identifier.
1290: */
1291: for ( i = NCPLN-1; (i > 0) && (sym_id[i] == 0); --i );
1292: ;
1293:
1294: /*
1295: * Scan kernel symbol table [backwards for efficiency].
1296: */
1297: for ( ksymp = &ksym_tab[ksym_cnt]; --ksymp >= ksym_tab; ) {
1298:
1299: if ( strncmp( sym_id, ksymp->ls_id, NCPLN ) != 0 )
1300: continue;
1301:
1302: /*
1303: * Disallow references to C-callable kernel code symbols.
1304: */
1305: if((sym_id[i] == '_') && ((ksymp->ls_type & LR_SEG) == L_SHRI))
1306: return( NULL );
1307:
1308: return( ksymp );
1309: }
1310:
1311: /*
1312: * Check symbol for 'K' prefix.
1313: * If found, try again after discarding prefix.
1314: */
1315: if ( (i < 3) || (sym_id[0] != 'K') )
1316: return( NULL );
1317: strncpy( &id[0], &sym_id[1], NCPLN-1 );
1318: id[NCPLN-1] = 0;
1319:
1320: /*
1321: * Scan kernel symbol table [backwards for efficiency].
1322: */
1323: for ( ksymp = &ksym_tab[ksym_cnt]; --ksymp >= ksym_tab; ) {
1324:
1325: /*
1326: * Only shared kernel code symbols accessible via K prefix.
1327: */
1328: if ( (ksymp->ls_type & LR_SEG) != L_SHRI)
1329: continue;
1330:
1331: if ( strncmp( id, ksymp->ls_id, NCPLN ) == 0 )
1332: return( ksymp );
1333: }
1334:
1335: return( NULL );
1336: }
1337:
1338: /**
1339: *
1340: * void
1341: * symsave() -- save revised driver symbol table in code file.
1342: */
1343: void
1344: symsave()
1345: {
1346: /*
1347: * Format driver code header.
1348: */
1349: ldh_drv.l_flag = LF_SEP | LF_NRB | LF_KER;
1350: ldh_drv.l_ssize[L_SHRD] = 0;
1351: ldh_drv.l_ssize[L_PRVD] = 0;
1352: ldh_drv.l_ssize[L_BSSD] = kmem_end;
1353: ldh_drv.l_ssize[L_DEBUG] = 0;
1354: ldh_drv.l_ssize[L_SYM ] = 0;
1355: ldh_drv.l_ssize[L_REL ] = 0;
1356:
1357: /*
1358: * Save symbol table BEFORE canonizing header.
1359: * NOTE: Reversing sequence will cause errors with symoff().
1360: * Don't save if removing or stripping object.
1361: */
1362: if ( (rflag == 0) && (sflag == 0) && (dsym_cnt != 0) ) {
1363:
1364: ldh_drv.l_ssize[L_SYM] = dsym_len;
1365:
1366: if ( lseek( text_fd, (long) symoff(&ldh_drv), 0 ) < 0 )
1367: fatal( text_file, ": bad seek" );
1368:
1369: if ( write( text_fd, (char *) dsym_tab, dsym_len ) < 0 )
1370: fatal( text_file, ": bad write" );
1371: }
1372:
1373: /*
1374: * Canonize and save driver code header AFTER saving symbol table.
1375: */
1376: canldh( &ldh_drv );
1377: if ( lseek( text_fd, 0L, 0 ) < 0 )
1378: fatal( text_file, ": bad seek" );
1379: if ( write( text_fd, &ldh_drv, sizeof(ldh_drv) ) < 0 )
1380: fatal( text_file, ": bad write" );
1381:
1382: /*
1383: * Release the malloc'ed storage.
1384: */
1385: if ( dsym_tab != NULL ) {
1386: free( dsym_tab );
1387: dsym_tab = NULL;
1388: }
1389: }
1390:
1391: /**
1392: *
1393: * long
1394: * symoff( ldp ) -- compute offset of symbol table in object module
1395: * struct ldheadr * ldp;
1396: */
1397: long
1398: symoff( ldp )
1399: register struct ldheader * ldp;
1400: {
1401: return( sizeof(*ldp) +
1402: ldp->l_ssize[L_SHRI] +
1403: ldp->l_ssize[L_PRVI] +
1404: ldp->l_ssize[L_SHRD] +
1405: ldp->l_ssize[L_PRVD] +
1406: ldp->l_ssize[L_DEBUG] );
1407: }
1408:
1409: /**
1410: *
1411: * int
1412: * fkword( kp, up ) - Fetch word from kernel locn 'kp' to user locn 'up'.
1413: * int * ip;
1414: * int * up;
1415: */
1416: int
1417: fkword( kp, up )
1418: int * kp;
1419: int * up;
1420: {
1421: if ( lseek( kmem_fd, (long) kp, 0 ) < 0 )
1422: return( -1 );
1423:
1424: if ( read( kmem_fd, up, sizeof(*up) ) < 0 )
1425: return( -1 );
1426:
1427: return( 0 );
1428: }
1429:
1430: /**
1431: *
1432: * int
1433: * skword( kp, w ) - Store word 'w' into kernel locn 'kp'.
1434: * int * kp;
1435: * int w;
1436: */
1437: int
1438: skword( kp, w )
1439: int * kp;
1440: int w;
1441: {
1442: if ( lseek( kmem_fd, (long) kp, 0 ) < 0 )
1443: return( -1 );
1444:
1445: if ( write( kmem_fd, &w, sizeof(w) ) < 0 )
1446: return( -1 );
1447:
1448: return( 0 );
1449: }
1450:
1451: char *
1452: basename( s )
1453: register char * s;
1454: {
1455: register char * base;
1456:
1457: for ( base = s; *s != '\0'; s++ ) {
1458: if ( (s[0] == '/') && (s[1] != '/') && (s[1] != '\0') )
1459: base = s+1;
1460: }
1461:
1462: return( base );
1463: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.