303 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			303 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| .\" $Header$
 | |
| .wh 0 hd
 | |
| .wh 60 fo
 | |
| .de hd
 | |
| 'sp 5
 | |
| ..
 | |
| .de fo
 | |
| 'bp
 | |
| ..
 | |
| .nr e 0 1
 | |
| .de ER
 | |
| .br
 | |
| .ne 20
 | |
| .sp 2
 | |
| .in 5
 | |
| .ti -5
 | |
| ERROR \\n+e:
 | |
| ..
 | |
| .de PS
 | |
| .sp
 | |
| .nf
 | |
| .in +5
 | |
| ..
 | |
| .de PE
 | |
| .sp
 | |
| .fi
 | |
| .in -5
 | |
| ..
 | |
| .sp 3
 | |
| .ce
 | |
| UNIX version 7 bugs
 | |
| .sp 3
 | |
| This document describes the UNIX version 7 errors fixed at the
 | |
| Vrije Universiteit, Amsterdam.
 | |
| Several of these are discovered at the VU.
 | |
| Others are quoted from a list of bugs distributed by BellLabs.
 | |
| .sp
 | |
| For each error the differences between the original and modified
 | |
| source files are given,
 | |
| as well as a test program.
 | |
| .ER
 | |
| C optimizer bug for unsigned comparison
 | |
| .sp
 | |
| The following C program caused an IOT trap, while it should not
 | |
| (compile with 'cc -O prog.c'):
 | |
| .PS
 | |
| unsigned	i = 0;
 | |
| 
 | |
| main() {
 | |
| 	register j;
 | |
| 
 | |
| 	j = -1;
 | |
| 	if (i > 40000)
 | |
| 		abort();
 | |
| }
 | |
| .PE
 | |
| BellLabs suggests to make the following patch in c21.c:
 | |
| .PS
 | |
| /* modified /usr/src/cmd/c/c21.c */
 | |
| 
 | |
| 189		if (r==0) {
 | |
| 190	/* next 2 lines replaced as indicated by
 | |
| 191	 * Bell Labs bug distribution ( v7optbug )
 | |
| 192			p->back->back->forw = p->forw;
 | |
| 193			p->forw->back = p->back->back;
 | |
| 194	  End of lines changed */
 | |
| 195			if (p->forw->op==CBR
 | |
| 196			  || p->forw->op==SXT
 | |
| 197			  || p->forw->op==CFCC) {
 | |
| 198				p->back->forw = p->forw;
 | |
| 199				p->forw->back = p->back;
 | |
| 200			} else {
 | |
| 201				p->back->back->forw = p->forw;
 | |
| 202				p->forw->back = p->back->back;
 | |
| 203			}
 | |
| 204	/* End of new lines */
 | |
| 205			decref(p->ref);
 | |
| 206			p = p->back->back;
 | |
| 207			nchange++;
 | |
| 208		} else if (r>0) {
 | |
| .PE
 | |
| Use the previous program to test before and after the modification.
 | |
| .ER
 | |
| The loader fails for large data or text portions
 | |
| .sp
 | |
| The loader 'ld' produces a "local symbol botch" error
 | |
| for the following C program.
 | |
| .PS
 | |
| int	big1[10000] = {
 | |
| 	1
 | |
| };
 | |
| int	big2[10000] = {
 | |
| 	2
 | |
| };
 | |
| 
 | |
| main() {
 | |
| 	printf("loader is fine\\n");
 | |
| }
 | |
| .PE
 | |
| We have made the following fix:
 | |
| .PS
 | |
| /* original /usr/src/cmd/ld.c */
 | |
| 
 | |
| 113	struct {
 | |
| 114		int	fmagic;
 | |
| 115		int	tsize;
 | |
| 116		int	dsize;
 | |
| 117		int	bsize;
 | |
| 118		int	ssize;
 | |
| 119		int	entry;
 | |
| 120		int	pad;
 | |
| 121		int	relflg;
 | |
| 122	} filhdr;
 | |
| 
 | |
| /* modified /usr/src/cmd/ld.c */
 | |
| 
 | |
| 113	/*
 | |
| 114	 * The original Version 7 loader had problems loading large
 | |
| 115	 * text or data portions.
 | |
| 116	 * Why not include <a.out.h> ???
 | |
| 117	 * then they would be declared unsigned
 | |
| 118	 */
 | |
| 119	struct {
 | |
| 120		int	fmagic;
 | |
| 121		unsigned	tsize;		/* not int !!! */
 | |
| 122		unsigned	dsize;		/* not int !!! */
 | |
| 123		unsigned	bsize;		/* not int !!! */
 | |
| 124		unsigned	ssize;		/* not int !!! */
 | |
| 125		unsigned	entry;		/* not int !!! */
 | |
| 126		unsigned	pad;		/* not int !!! */
 | |
| 127		unsigned	relflg;		/* not int !!! */
 | |
| 128	} filhdr;
 | |
| .PE
 | |
| .ER
 | |
| Floating point registers
 | |
| .sp
 | |
| When a program is swapped to disk if it needs more memory,
 | |
| then the floating point registers were not saved, so that
 | |
| it may have different registers when it is restarted.
 | |
| A small assembly program demonstrates this for the status register.
 | |
| If the error is not fixed, then the program generates an IOT error.
 | |
| A "memory fault" is generated if all is fine.
 | |
| .PS
 | |
| start:	ldfps	$7400
 | |
| 1:	stfps	r0
 | |
| 	mov	r0,-(sp)
 | |
| 	cmp	r0,$7400
 | |
| 	beq	1b
 | |
| 	4
 | |
| .PE
 | |
| You have to dig into the kernel to fix it.
 | |
| The following patch will do:
 | |
| .PS
 | |
| /* original /usr/sys/sys/slp.c */
 | |
| 
 | |
| 563		a2 = malloc(coremap, newsize);
 | |
| 564		if(a2 == NULL) {
 | |
| 565			xswap(p, 1, n);
 | |
| 566			p->p_flag |= SSWAP;
 | |
| 567			qswtch();
 | |
| 568			/* no return */
 | |
| 569		}
 | |
| 
 | |
| /* modified /usr/sys/sys/slp.c */
 | |
| 
 | |
| 590		a2 = malloc(coremap, newsize);
 | |
| 591		if(a2 == NULL) {
 | |
| 592	#ifdef FPBUG
 | |
| 593			/*
 | |
| 594			 * copy floating point register and status,
 | |
| 595			 * but only if you must switch processes
 | |
| 596			 */
 | |
| 597			if(u.u_fpsaved == 0) {
 | |
| 598				savfp(&u.u_fps);
 | |
| 599				u.u_fpsaved = 1;
 | |
| 600			}
 | |
| 601	#endif
 | |
| 602			xswap(p, 1, n);
 | |
| 603			p->p_flag |= SSWAP;
 | |
| 604			qswtch();
 | |
| 605			/* no return */
 | |
| 606		}
 | |
| .PE
 | |
| .ER
 | |
| Floating point registers.
 | |
| .sp
 | |
| A similar problem arises when a process forks.
 | |
| The child will have random floating point registers as is
 | |
| demonstrated by the following assembly language program.
 | |
| The child process will die by an IOT trap and the father prints
 | |
| the message "child failed".
 | |
| .PS
 | |
| exit	= 1.
 | |
| fork	= 2.
 | |
| write	= 4.
 | |
| wait	= 7.
 | |
| 
 | |
| start:	ldfps	$7400
 | |
| 	sys	fork
 | |
| 	br	child
 | |
| 	sys	wait
 | |
| 	tst	r1
 | |
| 	bne	bad
 | |
| 	stfps	r2
 | |
| 	cmp	r2,$7400
 | |
| 	beq	start
 | |
| 	4
 | |
| child:	stfps	r2
 | |
| 	cmp	r2,$7400
 | |
| 	beq	ex
 | |
| 	4
 | |
| bad:	clr	r0
 | |
| 	sys	write;mess;13.
 | |
| ex:	clr	r0
 | |
| 	sys	exit
 | |
| 
 | |
| 	.data
 | |
| mess:	<child failed\\n>
 | |
| .PE
 | |
| The same file slp.c should be patched as follows:
 | |
| .PS
 | |
| /* original /usr/sys/sys/slp.c */
 | |
| 
 | |
| 499		/*
 | |
| 500		 * When the resume is executed for the new process,
 | |
| 501		 * here's where it will resume.
 | |
| 502		 */
 | |
| 503		if (save(u.u_ssav)) {
 | |
| 504			sureg();
 | |
| 505			return(1);
 | |
| 506		}
 | |
| 507		a2 = malloc(coremap, n);
 | |
| 508		/*
 | |
| 509		 * If there is not enough core for the
 | |
| 510		 * new process, swap out the current process to generate the
 | |
| 511		 * copy.
 | |
| 512		 */
 | |
| 
 | |
| /* modified /usr/sys/sys/slp.c */
 | |
| 
 | |
| 519		/*
 | |
| 520		 * When the resume is executed for the new process,
 | |
| 521		 * here's where it will resume.
 | |
| 522		 */
 | |
| 523		if (save(u.u_ssav)) {
 | |
| 524			sureg();
 | |
| 525			return(1);
 | |
| 526		}
 | |
| 527	#ifdef FPBUG
 | |
| 528		/* copy the floating point registers and status to child */
 | |
| 529		if(u.u_fpsaved == 0) {
 | |
| 530			savfp(&u.u_fps);
 | |
| 531			u.u_fpsaved = 1;
 | |
| 532		}
 | |
| 533	#endif
 | |
| 534		a2 = malloc(coremap, n);
 | |
| 535		/*
 | |
| 536		 * If there is not enough core for the
 | |
| 537		 * new process, swap out the current process to generate the
 | |
| 538		 * copy.
 | |
| 539		 */
 | |
| .PE
 | |
| .ER
 | |
| /usr/src/libc/v6/stat.c
 | |
| .sp
 | |
| Some system calls are changed from version 6 to version 7.
 | |
| A library of system call entries, that make a version 6 UNIX look like
 | |
| a version 7 system, is provided to enable you to run some
 | |
| useful version 7 utilities, like 'tar', on UNIX-6.
 | |
| The entry for 'stat' contained two bugs:
 | |
| the 24-bit file size was incorrectly converted to 32 bits
 | |
| (sign extension of bit 15)
 | |
| and the uid/gid fields suffered from sign extension.
 | |
| .sp
 | |
| Transferring your files from version 6 to version 7 using 'tar'
 | |
| will fail for all files for which
 | |
| .sp
 | |
| 	( (size & 0100000) != 0 )
 | |
| .sp
 | |
| These two errors are fixed if stat.c is modified as follows:
 | |
| .PS
 | |
| /* original /usr/src/libc/v6/stat.c */
 | |
| 
 | |
| 11		char  os_size0;
 | |
| 12		short os_size1;
 | |
| 13		short os_addr[8];
 | |
| 
 | |
| 49		buf->st_nlink = osbuf.os_nlinks;
 | |
| 50		buf->st_uid = osbuf.os_uid;
 | |
| 51		buf->st_gid = osbuf.os_gid;
 | |
| 52		buf->st_rdev = 0;
 | |
| 
 | |
| /* modified /usr/src/libc/v6/stat.c */
 | |
| 
 | |
| 11		char  os_size0;
 | |
| 12		unsigned os_size1;
 | |
| 13		short os_addr[8];
 | |
| 
 | |
| 49		buf->st_nlink = osbuf.os_nlinks;
 | |
| 50		buf->st_uid = osbuf.os_uid & 0377;
 | |
| 51		buf->st_gid = osbuf.os_gid & 0377;
 | |
| 52		buf->st_rdev = 0;
 | |
| .PE
 |