303 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			303 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
.\" $Id$
 | 
						|
.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 5n
 | 
						|
.ti -5n
 | 
						|
ERROR \\n+e:
 | 
						|
..
 | 
						|
.de PS
 | 
						|
.sp
 | 
						|
.nf
 | 
						|
.in +5n
 | 
						|
..
 | 
						|
.de PE
 | 
						|
.sp
 | 
						|
.fi
 | 
						|
.in -5n
 | 
						|
..
 | 
						|
.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
 | 
						|
Some digging into the kernel is required 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 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 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
 |