304 lines
6.2 KiB
Plaintext
304 lines
6.2 KiB
Plaintext
.\" $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
|