Return to BSD News archive
Xref: sserve comp.unix.bsd:3237 comp.bugs.4bsd:1869 Path: sserve!manuel!munnari.oz.au!news.hawaii.edu!ames!olivea!uunet!iWarp.intel.com|ichips!intelhf!agora!davidg From: davidg@agora.rain.com (David Greenman) Newsgroups: comp.unix.bsd,comp.bugs.4bsd Subject: Patches for kernel namelist db bugs and kvm.c bugs (386BSD) Message-ID: <1992Aug6.070211.23697@agora.uucp> Date: 6 Aug 92 07:02:11 GMT Sender: davidg@agora.uucp (David Greenman) Organization: Open Communications Forum Lines: 291 There are several bugs in the kernel namelist db creation/use and bugs in kvm.c which causes ps and several other utils to fail to work correctly. The kvm.c patches are based in part on, but supersede, the patches posted on usenet by pk@cs.few.eur.nl (Paul Kranenburg) [which introduced bugs of its own]. In order for kvm_mkdb to work correctly, vers.o MUST be the first object linked in the kernel. The Makefile.i386 should read: SYSTEM_LD= @${LD} -z -T FE000000 -o $@ -X vers.o ${SYSTEM_OBJS} (or vers.o should be first in SYSTEM_OBJS) And, of course all things that depend on libutil.a will have to be rebuilt. I should also like to point out that the bug which causes a Floating Point Exception with 'ps aux' doesn't seem to be in 'ps'. It appears that, under some conditions, some of the pages in the process data region become write protected. This is the symptom as it appears to me...I might be completely wrong :-). I can't explain it any other way. Specifically, the statement "_pw_keynum = 0;" in setpassent() is usually where the FP exception occurs for ps. The variable is in valid data space, and gcc produces valid "mov" assem. I should also note that ps aux often works just after bootup, but once it starts failing, it is consistant. The following are the fixes for kvm.c, & kvm_mkdb: *** /usr/src/lib/libutil/kvm.c.01orig Mon Jul 13 02:20:51 1992 --- /usr/src/lib/libutil/kvm.c Wed Aug 5 03:41:16 1992 *************** *** 309,315 **** * read version out of database */ bcopy("VERSION", symbuf, sizeof ("VERSION")-1); ! key.dsize = (sizeof ("VERSION") - 1) + 1; data = dbm_fetch(db, key); if (data.dptr == NULL) goto hard1; --- 309,315 ---- * read version out of database */ bcopy("VERSION", symbuf, sizeof ("VERSION")-1); ! key.dsize = (sizeof ("VERSION") - 1); data = dbm_fetch(db, key); if (data.dptr == NULL) goto hard1; *************** *** 319,325 **** * read version string from kernel memory */ bcopy("_version", symbuf, sizeof ("_version")-1); ! key.dsize = (sizeof ("_version")-1) + 1; data = dbm_fetch(db, key); if (data.dptr == NULL) goto hard1; --- 319,325 ---- * read version string from kernel memory */ bcopy("_version", symbuf, sizeof ("_version")-1); ! key.dsize = (sizeof ("_version")-1); data = dbm_fetch(db, key); if (data.dptr == NULL) goto hard1; *************** *** 356,362 **** return (-1); } (void)strcpy(symbuf, n->n_name); ! key.dsize = len + 1; data = dbm_fetch(db, key); if (data.dptr == NULL || data.dsize != sizeof (struct nlist)) continue; --- 356,362 ---- return (-1); } (void)strcpy(symbuf, n->n_name); ! key.dsize = len; data = dbm_fetch(db, key); if (data.dptr == NULL || data.dsize != sizeof (struct nlist)) continue; *************** *** 634,639 **** --- 634,644 ---- } } + #ifdef i386 + /* See also ./sys/kern/kern_execve.c */ + #define ARGSIZE (roundup(ARG_MAX, NBPG)) + #endif + #ifdef NEWVM struct user * kvm_getu(p) *************** *** 691,713 **** #endif #ifdef i386 ! if (kp->kp_eproc.e_vm.vm_pmap.pm_pdir) { ! struct pde pde; ! klseek(kmem, ! (long)(kp->kp_eproc.e_vm.vm_pmap.pm_pdir + UPTDI), 0); ! if (read(kmem, (char *)&pde, sizeof pde) == sizeof pde && ! pde.pd_v) { ! ! struct pte pte; ! ! lseek(mem, (long)ctob(pde.pd_pfnum) + ! (ptei(USRSTACK-CLBYTES) * sizeof pte), 0); ! if (read(mem, (char *)&pte, sizeof pte) == sizeof pte && + pte.pg_v) { ! argaddr1 = (long)ctob(pte.pg_pfnum); ! } ! } ! } #endif return(&user.user); } --- 696,727 ---- #endif #ifdef i386 ! if (kp->kp_eproc.e_vm.vm_pmap.pm_pdir) { ! struct pde pde; ! u_int vaddr = USRSTACK-ARGSIZE; ! ! if ((u_int)kp->kp_eproc.e_vm.vm_maxsaddr + MAXSSIZ < USRSTACK) ! vaddr -= MAXSSIZ; ! #if 0 ! klseek(kmem, ! (long)(kp->kp_eproc.e_vm.vm_pmap.pm_pdir + UPTDI), 0); ! #else ! klseek(kmem, ! (long)(&kp->kp_eproc.e_vm.vm_pmap.pm_pdir[pdei(vaddr)]), 0); ! #endif ! if (read(kmem, (char *)&pde, sizeof pde) == sizeof pde ! && pde.pd_v) { ! struct pte pte; ! ! lseek(mem, (long)ctob(pde.pd_pfnum) + ! (ptei(vaddr) * sizeof pte), 0); ! if (read(mem, (char *)&pte, sizeof pte) == sizeof pte ! && pte.pg_v) { ! argaddr1 = (long)ctob(pte.pg_pfnum); ! } ! } ! } #endif return(&user.user); } *************** *** 786,796 **** --- 800,819 ---- const struct proc *p; const struct user *up; { + #ifdef i386 + /* See also ./sys/kern/kern_execve.c */ + static char cmdbuf[ARGSIZE]; + static union { + char argc[ARGSIZE]; + int argi[ARGSIZE/sizeof (int)]; + } argspac; + #else static char cmdbuf[CLBYTES*2]; static union { char argc[CLBYTES*2]; int argi[CLBYTES*2/sizeof (int)]; } argspac; + #endif register char *cp; register int *ip; char c; *************** *** 824,829 **** --- 847,857 ---- file = swapf; #endif } else { + #ifdef i386 + lseek(mem, (long)argaddr1, 0); + if (read(mem, &argspac.argc[0], ARGSIZE) != ARGSIZE) + goto bad; + #else if (argaddr0) { lseek(mem, (long)argaddr0, 0); if (read(mem, (char *)&argspac, CLBYTES) != CLBYTES) *************** *** 833,842 **** lseek(mem, (long)argaddr1, 0); if (read(mem, &argspac.argc[CLBYTES], CLBYTES) != CLBYTES) goto bad; file = (char *) memf; } #ifdef i386 ! ip = &argspac.argi[(CLBYTES + CLBYTES/2)/sizeof (int)]; #else ip = &argspac.argi[CLBYTES*2/sizeof (int)]; ip -= 2; /* last arg word and .long 0 */ --- 861,874 ---- lseek(mem, (long)argaddr1, 0); if (read(mem, &argspac.argc[CLBYTES], CLBYTES) != CLBYTES) goto bad; + #endif file = (char *) memf; } #ifdef i386 ! ip = &argspac.argi[(ARGSIZE-ARG_MAX)/sizeof (int)]; ! ! nbad = 0; ! for (cp = (char *)ip; cp < &argspac.argc[ARGSIZE-stkoff]; cp++) { #else ip = &argspac.argi[CLBYTES*2/sizeof (int)]; ip -= 2; /* last arg word and .long 0 */ *************** *** 848,865 **** *(char *)ip = ' '; ip++; nbad = 0; ! #endif for (cp = (char *)ip; cp < &argspac.argc[CLBYTES*2-stkoff]; cp++) { ! c = *cp & 0177; ! if (c == 0) *cp = ' '; else if (c < ' ' || c > 0176) { ! if (++nbad >= 5*(0+1)) { /* eflg -> 0 XXX */ ! *cp++ = ' '; break; } *cp = '?'; ! } else if (0 == 0 && c == '=') { /* eflg -> 0 XXX */ while (*--cp != ' ') if (cp <= (char *)ip) break; --- 880,901 ---- *(char *)ip = ' '; ip++; nbad = 0; ! for (cp = (char *)ip; cp < &argspac.argc[CLBYTES*2-stkoff]; cp++) { ! #endif ! c = *cp; ! if (c == 0) { /* convert null between arguments to space */ *cp = ' '; + if (*(cp+1) == 0) break; /* if null argument follows then no more args */ + } else if (c < ' ' || c > 0176) { ! if (++nbad >= 5*(0+1)) { /* eflg -> 0 XXX */ /* limit number of bad chars to 5 */ ! *cp++ = '?'; break; } *cp = '?'; ! } ! else if (0 == 0 && c == '=') { /* eflg -> 0 XXX */ while (*--cp != ' ') if (cp <= (char *)ip) break; *************** *** 870,876 **** while (*--cp == ' ') *cp = 0; cp = (char *)ip; ! (void) strncpy(cmdbuf, cp, &argspac.argc[CLBYTES*2] - cp); if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') { (void) strcat(cmdbuf, " ("); (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm)); --- 906,912 ---- while (*--cp == ' ') *cp = 0; cp = (char *)ip; ! (void) strcpy(cmdbuf, cp); if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') { (void) strcat(cmdbuf, " ("); (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm)); *** /usr/src/usr.sbin/kvm_mkdb/nlist.c.01orig Sat Apr 27 16:23:58 1991 --- /usr/src/usr.sbin/kvm_mkdb/nlist.c Wed Aug 5 03:39:37 1992 *************** *** 138,143 **** --- 138,146 ---- #ifdef vax rel_off = nbuf.n_value & ~KERNBASE; #endif + #ifdef i386 + rel_off = ((nbuf.n_value & ~KERNBASE) + CLBYTES); + #endif /* * When loaded, data is rounded to next page cluster * after text, but not in file.