.\" $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 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
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