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