Return to BSD News archive
Newsgroups: comp.os.386bsd.development
Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!haven.umd.edu!uunet!mcsun!sun4nl!eur.nl!pk
From: pk@cs.few.eur.nl (Paul Kranenburg)
Subject: Command line arguments for ps(1) and w(1)
Message-ID: <1993Apr7.160932.16923@cs.few.eur.nl>
Keywords: Process status, KVM
Sender: news@cs.few.eur.nl
Reply-To: pk@cs.few.eur.nl
Organization: Erasmus University Rotterdam
Date: Wed, 7 Apr 1993 16:09:32 GMT
Lines: 594
Below is a patch (believed to be relative to kvm.c.pl2) to
`lib/libutil/kvm.c' which allows ps(1) and w(1) to lay
their hands on process command line arguments.
Thanks to David Greenman who taught me about VM shadow objects.
-pk
------------------------------------------------------------------------
*** kvm.c.orig Wed Apr 7 16:08:05 1993
--- kvm.c Wed Apr 7 17:30:34 1993
***************
*** 74,79 ****
--- 74,81 ----
#define btop(x) (((unsigned)(x)) >> PGSHIFT) /* XXX */
#define ptob(x) ((caddr_t)((x) << PGSHIFT)) /* XXX */
#include <vm/vm.h> /* ??? kinfo_proc currently includes this*/
+ #include <vm/vm_page.h>
+ #include <vm/swap_pager.h>
#include <sys/kinfo_proc.h>
#ifdef hp300
#include <hp300/hp300/pte.h>
***************
*** 108,113 ****
--- 110,122 ----
struct user user;
char upages[UPAGES][NBPG];
} user;
+
+ #ifdef NEWVM
+ struct swapblk {
+ long offset; /* offset in swap device */
+ long size; /* remaining size of block in swap device */
+ };
+ #endif
/*
* random other stuff
*/
***************
*** 120,125 ****
--- 129,135 ----
static int pcbpf;
static int argaddr0; /* XXX */
static int argaddr1;
+ static int swaddr;
static int nswap;
static char *tmp;
#if defined(hp300)
***************
*** 156,176 ****
#define X_DMMIN 3
{ "_dmmax" },
#define X_DMMAX 4
/*
* everything here and down, only if a dead kernel
*/
{ "_Sysmap" },
! #define X_SYSMAP 5
#define X_DEADKERNEL X_SYSMAP
{ "_Syssize" },
! #define X_SYSSIZE 6
{ "_allproc" },
! #define X_ALLPROC 7
{ "_zombproc" },
! #define X_ZOMBPROC 8
{ "_nproc" },
! #define X_NPROC 9
! #define X_LAST 9
#if defined(hp300)
{ "_Sysseg" },
#define X_SYSSEG (X_LAST+1)
--- 166,192 ----
#define X_DMMIN 3
{ "_dmmax" },
#define X_DMMAX 4
+ { "_vm_page_buckets" },
+ #define X_VM_PAGE_BUCKETS 5
+ { "_vm_page_hash_mask" },
+ #define X_VM_PAGE_HASH_MASK 6
+ { "_page_shift" },
+ #define X_PAGE_SHIFT 7
/*
* everything here and down, only if a dead kernel
*/
{ "_Sysmap" },
! #define X_SYSMAP 8
#define X_DEADKERNEL X_SYSMAP
{ "_Syssize" },
! #define X_SYSSIZE 9
{ "_allproc" },
! #define X_ALLPROC 10
{ "_zombproc" },
! #define X_ZOMBPROC 11
{ "_nproc" },
! #define X_NPROC 12
! #define X_LAST 12
#if defined(hp300)
{ "_Sysseg" },
#define X_SYSSEG (X_LAST+1)
***************
*** 187,192 ****
--- 203,212 ----
static off_t Vtophys();
static void klseek(), seterr(), setsyserr(), vstodb();
static int getkvars(), kvm_doprocs(), kvm_init();
+ #ifdef NEWVM
+ static int vatosw();
+ static int findpage();
+ #endif
/*
* returns 0 if files were opened now,
***************
*** 396,401 ****
--- 416,423 ----
kvm_getprocs(what, arg)
int what, arg;
{
+ static int ocopysize = -1;
+
if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
return (NULL);
if (!deadkernel) {
***************
*** 406,416 ****
return (-1);
}
copysize = ret;
! if ((kvmprocbase = (struct kinfo_proc *)malloc(copysize))
! == NULL) {
seterr("out of memory");
return (-1);
}
if ((ret = getkerninfo(what, kvmprocbase, ©size,
arg)) == -1) {
setsyserr("can't get proc list");
--- 428,440 ----
return (-1);
}
copysize = ret;
! if (copysize > ocopysize &&
! (kvmprocbase = (struct kinfo_proc *)malloc(copysize))
! == NULL) {
seterr("out of memory");
return (-1);
}
+ ocopysize = copysize;
if ((ret = getkerninfo(what, kvmprocbase, ©size,
arg)) == -1) {
setsyserr("can't get proc list");
***************
*** 662,667 ****
--- 686,693 ----
register struct kinfo_proc *kp = (struct kinfo_proc *)p;
register int i;
register char *up;
+ u_int vaddr;
+ struct swapblk swb;
if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
return (NULL);
***************
*** 669,680 ****
seterr("zombie process");
return (NULL);
}
/*
- * Reading from swap is too complicated right now.
- */
- if ((p->p_flag & SLOAD) == 0)
- return(NULL);
- /*
* Read u-area one page at a time for the benefit of post-mortems
*/
up = (char *) p->p_addr;
--- 695,744 ----
seterr("zombie process");
return (NULL);
}
+
+ argaddr0 = argaddr1 = swaddr = 0;
+ if ((p->p_flag & SLOAD) == 0) {
+ vm_offset_t maddr;
+
+ if (swap < 0) {
+ seterr("no swap");
+ return (NULL);
+ }
+ /*
+ * Costly operation, better set enable_swap to zero
+ * in vm/vm_glue.c, since paging of user pages isn't
+ * done yet anyway.
+ */
+ if (vatosw(p, USRSTACK + i * NBPG, &maddr, &swb) == 0)
+ return NULL;
+
+ if (maddr == 0 && swb.size < UPAGES * NBPG)
+ return NULL;
+
+ for (i = 0; i < UPAGES; i++) {
+ if (maddr) {
+ (void) lseek(mem, maddr + i * NBPG, 0);
+ if (read(mem,
+ (char *)user.upages[i], NBPG) != NBPG) {
+ seterr(
+ "can't read u for pid %d from %s",
+ p->p_pid, swapf);
+ return NULL;
+ }
+ } else {
+ (void) lseek(swap, swb.offset + i * NBPG, 0);
+ if (read(swap,
+ (char *)user.upages[i], NBPG) != NBPG) {
+ seterr(
+ "can't read u for pid %d from %s",
+ p->p_pid, swapf);
+ return NULL;
+ }
+ }
+ }
+ return(&user.user);
+ }
/*
* Read u-area one page at a time for the benefit of post-mortems
*/
up = (char *) p->p_addr;
***************
*** 691,697 ****
/*
* Conjure up a physical address for the arguments.
*/
- argaddr0 = argaddr1 = 0;
#ifdef hp300
if (kp->kp_eproc.e_vm.vm_pmap.pm_ptab) {
struct pte pte[CLSIZE*2];
--- 755,760 ----
***************
*** 706,746 ****
argaddr1 = ctob(pftoc(pte[CLSIZE*1].pg_pfnum));
}
}
! #endif /* 08 Sep 92*/
kp->kp_eproc.e_vm.vm_rssize =
kp->kp_eproc.e_vm.vm_pmap.pm_stats.resident_count; /* XXX */
#ifdef i386
if (kp->kp_eproc.e_vm.vm_pmap.pm_pdir) {
struct pde pde;
- /* u_int vaddr = USRSTACK-ARGSIZE;*/
- /* 08 Sep 92*/ u_int vaddr = (u_int)kp->kp_eproc.e_vm.vm_maxsaddr + MAXSSIZ - ARGSIZE;
- /* 08 Sep 92 ---------
- 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);
}
#else
--- 769,816 ----
argaddr1 = ctob(pftoc(pte[CLSIZE*1].pg_pfnum));
}
}
! #endif
kp->kp_eproc.e_vm.vm_rssize =
kp->kp_eproc.e_vm.vm_pmap.pm_stats.resident_count; /* XXX */
+ vaddr = (u_int)kp->kp_eproc.e_vm.vm_maxsaddr + MAXSSIZ - ARGSIZE;
+
#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[pdei(vaddr)]), 0);
!
if (read(kmem, (char *)&pde, sizeof pde) == sizeof pde
&& pde.pd_v) {
struct pte pte;
! if (lseek(mem, (long)ctob(pde.pd_pfnum) +
! (ptei(vaddr) * sizeof pte), 0) == -1)
! seterr("kvm_getu: lseek");
! if (read(mem, (char *)&pte, sizeof pte) == sizeof pte) {
! if (pte.pg_v) {
! argaddr1 = (long)ctob(pte.pg_pfnum);
! } else {
! goto hard;
! }
! } else {
! seterr("kvm_getu: read");
}
+ } else {
+ goto hard;
}
}
! #endif /* i386 */
!
! hard:
! if (vatosw(p, vaddr, &argaddr1, &swb)) {
! if (argaddr1 == 0 && swb.size >= ARGSIZE)
! swaddr = swb.offset;
! }
!
return(&user.user);
}
#else
***************
*** 849,856 ****
goto retucomm;
if ((p->p_flag & SLOAD) == 0 || argaddr1 == 0) {
#ifdef NEWVM
! goto retucomm; /* XXX for now */
#else
if (swap < 0 || p->p_ssize == 0)
goto retucomm;
vstodb(0, CLSIZE, &up->u_smap, &db, 1);
--- 919,942 ----
goto retucomm;
if ((p->p_flag & SLOAD) == 0 || argaddr1 == 0) {
#ifdef NEWVM
! if (swaddr == 0)
! goto retucomm; /* XXX for now */
! #ifdef i386
! (void) lseek(swap, swaddr, 0);
! if (read(swap, &argspac.argc[0], ARGSIZE) != ARGSIZE)
! goto bad;
#else
+ if (argaddr0) {
+ lseek(swap, (long)argaddr0, 0);
+ if (read(swap, (char *)&argspac, CLBYTES) != CLBYTES)
+ goto bad;
+ } else
+ bzero(&argspac, CLBYTES);
+ lseek(swap, (long)argaddr1, 0);
+ if (read(swap, &argspac.argc[CLBYTES], CLBYTES) != CLBYTES)
+ goto bad;
+ #endif
+ #else
if (swap < 0 || p->p_ssize == 0)
goto retucomm;
vstodb(0, CLSIZE, &up->u_smap, &db, 1);
***************
*** 882,891 ****
#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)];
--- 968,978 ----
#endif
file = (char *) memf;
}
+
+ nbad = 0;
#ifdef i386
ip = &argspac.argi[(ARGSIZE-ARG_MAX)/sizeof (int)];
for (cp = (char *)ip; cp < &argspac.argc[ARGSIZE-stkoff]; cp++) {
#else
ip = &argspac.argi[CLBYTES*2/sizeof (int)];
***************
*** 897,903 ****
}
*(char *)ip = ' ';
ip++;
- nbad = 0;
for (cp = (char *)ip; cp < &argspac.argc[CLBYTES*2-stkoff]; cp++) {
#endif
--- 984,989 ----
***************
*** 1190,1195 ****
--- 1276,1457 ----
}
#endif
+
+ #ifdef NEWVM
+ /*
+ * locate address of unwired or swapped page
+ */
+
+ #define DEBUG 0
+
+ #define KREAD(off, addr, len) \
+ (kvm_read((void *)(off), (char *)(addr), (len)) == (len))
+
+
+ static int
+ vatosw(p, vaddr, maddr, swb)
+ struct proc *p ;
+ vm_offset_t vaddr;
+ vm_offset_t *maddr;
+ struct swapblk *swb;
+ {
+ register struct kinfo_proc *kp = (struct kinfo_proc *)p;
+ vm_map_t mp = &kp->kp_eproc.e_vm.vm_map;
+ struct vm_object vm_object;
+ struct vm_map_entry vm_entry;
+ struct pager_struct pager;
+ struct swpager swpager;
+ struct swblock swblock;
+ long addr, off;
+ int i;
+
+ if (p->p_pid == 0 || p->p_pid == 2)
+ return 0;
+
+ addr = (long)mp->header.next;
+ for (i = 0; i < mp->nentries; i++) {
+ /* Weed through map entries until vaddr in range */
+ if (!KREAD(addr, &vm_entry, sizeof(vm_entry))) {
+ setsyserr("vatosw: read vm_map_entry");
+ return 0;
+ }
+ if ((vaddr >= vm_entry.start) && (vaddr <= vm_entry.end) &&
+ (vm_entry.object.vm_object != 0))
+ break;
+
+ addr = (long)vm_entry.next;
+ }
+ if (i == mp->nentries) {
+ seterr("%u: map not found\n", p->p_pid);
+ return 0;
+ }
+
+ if (vm_entry.is_a_map || vm_entry.is_sub_map) {
+ seterr("%u: Is a map\n", p->p_pid);
+ return 0;
+ }
+
+ /* Locate memory object */
+ off = (vaddr - vm_entry.start) + vm_entry.offset;
+ addr = (long)vm_entry.object.vm_object;
+ while (1) {
+ if (!KREAD(addr, &vm_object, sizeof vm_object)) {
+ setsyserr("vatosw: read vm_object");
+ return 0;
+ }
+
+ #if DEBUG
+ fprintf(stderr, "%u: find page: object %#x offset %x\n",
+ p->p_pid, addr, off);
+ #endif
+
+ /* Lookup in page queue */
+ if (findpage(addr, off, maddr))
+ return 1;
+
+ if (vm_object.shadow == 0)
+ break;
+
+ #if DEBUG
+ fprintf(stderr, "%u: shadow obj at %x: offset %x+%x\n",
+ p->p_pid, addr, off, vm_object.shadow_offset);
+ #endif
+
+ addr = (long)vm_object.shadow;
+ off += vm_object.shadow_offset;
+ }
+
+ if (!vm_object.pager) {
+ seterr("%u: no pager\n", p->p_pid);
+ return 0;
+ }
+
+ /* Find address in swap space */
+ if (!KREAD(vm_object.pager, &pager, sizeof pager)) {
+ setsyserr("vatosw: read pager");
+ return 0;
+ }
+ if (pager.pg_type != PG_SWAP) {
+ seterr("%u: weird pager\n", p->p_pid);
+ return 0;
+ }
+
+ /* Get swap pager data */
+ if (!KREAD(pager.pg_data, &swpager, sizeof swpager)) {
+ setsyserr("vatosw: read swpager");
+ return 0;
+ }
+
+ off += vm_object.paging_offset;
+
+ /* Read swap block array */
+ if (!KREAD((long)swpager.sw_blocks +
+ (off/dbtob(swpager.sw_bsize)) * sizeof swblock,
+ &swblock, sizeof swblock)) {
+ setsyserr("vatosw: read swblock");
+ return 0;
+ }
+ swb->offset = dbtob(swblock.swb_block)+ (off % dbtob(swpager.sw_bsize));
+ swb->size = dbtob(swpager.sw_bsize) - (off % dbtob(swpager.sw_bsize));
+ return 1;
+ }
+
+
+ #define atop(x) (((unsigned)(x)) >> page_shift)
+ #define vm_page_hash(object, offset) \
+ (((unsigned)object+(unsigned)atop(offset))&vm_page_hash_mask)
+
+ static int
+ findpage(object, offset, maddr)
+ long object;
+ long offset;
+ vm_offset_t *maddr;
+ {
+ static long vm_page_hash_mask;
+ static long vm_page_buckets;
+ static long page_shift;
+ queue_head_t bucket;
+ struct vm_page mem;
+ long addr, baddr;
+
+ if (vm_page_hash_mask == 0 && !KREAD(nl[X_VM_PAGE_HASH_MASK].n_value,
+ &vm_page_hash_mask, sizeof (long))) {
+ seterr("can't read vm_page_hash_mask");
+ return 0;
+ }
+ if (page_shift == 0 && !KREAD(nl[X_PAGE_SHIFT].n_value,
+ &page_shift, sizeof (long))) {
+ seterr("can't read page_shift");
+ return 0;
+ }
+ if (vm_page_buckets == 0 && !KREAD(nl[X_VM_PAGE_BUCKETS].n_value,
+ &vm_page_buckets, sizeof (long))) {
+ seterr("can't read vm_page_buckets");
+ return 0;
+ }
+
+ baddr = vm_page_buckets + vm_page_hash(object,offset) * sizeof(queue_head_t);
+ if (!KREAD(baddr, &bucket, sizeof (bucket))) {
+ seterr("can't read vm_page_bucket");
+ return 0;
+ }
+
+ addr = (long)bucket.next;
+ while (addr != baddr) {
+ if (!KREAD(addr, &mem, sizeof (mem))) {
+ seterr("can't read vm_page");
+ return 0;
+ }
+ if ((long)mem.object == object && mem.offset == offset) {
+ *maddr = (long)mem.phys_addr;
+ return 1;
+ }
+ addr = (long)mem.hashq.next;
+ }
+ return 0;
+ }
+ #endif /* NEWVM */
+
#include <varargs.h>
static char errbuf[_POSIX2_LINE_MAX];
***************
*** 1203,1208 ****
--- 1465,1473 ----
va_start(ap);
fmt = va_arg(ap, char *);
(void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap);
+ #if DEBUG
+ (void) vfprintf(stderr, fmt, ap);
+ #endif
va_end(ap);
}