From: pk@cs.few.eur.nl (Paul Kranenburg)
patch which allows ps(1) and w(1) to lay their hands on process command line arguments.
This commit is contained in:
parent
a3a1e40463
commit
ea0119db71
335
lib/libkvm/kvm.c
335
lib/libkvm/kvm.c
@ -74,6 +74,8 @@ static char sccsid[] = "@(#)kvm.c 5.18 (Berkeley) 5/7/91";
|
||||
#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,6 +110,13 @@ static union {
|
||||
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,6 +129,7 @@ static int dmmin, dmmax;
|
||||
static int pcbpf;
|
||||
static int argaddr0; /* XXX */
|
||||
static int argaddr1;
|
||||
static int swaddr;
|
||||
static int nswap;
|
||||
static char *tmp;
|
||||
#if defined(hp300)
|
||||
@ -156,21 +166,27 @@ static struct nlist nl[] = {
|
||||
#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 5
|
||||
#define X_SYSMAP 8
|
||||
#define X_DEADKERNEL X_SYSMAP
|
||||
{ "_Syssize" },
|
||||
#define X_SYSSIZE 6
|
||||
#define X_SYSSIZE 9
|
||||
{ "_allproc" },
|
||||
#define X_ALLPROC 7
|
||||
#define X_ALLPROC 10
|
||||
{ "_zombproc" },
|
||||
#define X_ZOMBPROC 8
|
||||
#define X_ZOMBPROC 11
|
||||
{ "_nproc" },
|
||||
#define X_NPROC 9
|
||||
#define X_LAST 9
|
||||
#define X_NPROC 12
|
||||
#define X_LAST 12
|
||||
#if defined(hp300)
|
||||
{ "_Sysseg" },
|
||||
#define X_SYSSEG (X_LAST+1)
|
||||
@ -187,6 +203,10 @@ static struct nlist nl[] = {
|
||||
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,6 +416,8 @@ hard2:
|
||||
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,11 +428,13 @@ kvm_getprocs(what, arg)
|
||||
return (-1);
|
||||
}
|
||||
copysize = ret;
|
||||
if ((kvmprocbase = (struct kinfo_proc *)malloc(copysize))
|
||||
== NULL) {
|
||||
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,6 +686,8 @@ kvm_getu(p)
|
||||
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,11 +695,49 @@ kvm_getu(p)
|
||||
seterr("zombie process");
|
||||
return (NULL);
|
||||
}
|
||||
/*
|
||||
* Reading from swap is too complicated right now.
|
||||
*/
|
||||
if ((p->p_flag & SLOAD) == 0)
|
||||
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
|
||||
*/
|
||||
@ -691,7 +755,6 @@ kvm_getu(p)
|
||||
/*
|
||||
* 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];
|
||||
@ -706,41 +769,48 @@ kvm_getu(p)
|
||||
argaddr1 = ctob(pftoc(pte[CLSIZE*1].pg_pfnum));
|
||||
}
|
||||
}
|
||||
#endif /* 08 Sep 92*/
|
||||
#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;
|
||||
/* 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);
|
||||
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
|
||||
#endif /* i386 */
|
||||
|
||||
hard:
|
||||
if (vatosw(p, vaddr, &argaddr1, &swb)) {
|
||||
if (argaddr1 == 0 && swb.size >= ARGSIZE)
|
||||
swaddr = swb.offset;
|
||||
}
|
||||
|
||||
return(&user.user);
|
||||
}
|
||||
#else
|
||||
@ -849,7 +919,23 @@ kvm_getargs(p, up)
|
||||
goto retucomm;
|
||||
if ((p->p_flag & SLOAD) == 0 || argaddr1 == 0) {
|
||||
#ifdef NEWVM
|
||||
goto retucomm; /* XXX for now */
|
||||
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;
|
||||
@ -882,10 +968,11 @@ kvm_getargs(p, up)
|
||||
#endif
|
||||
file = (char *) memf;
|
||||
}
|
||||
|
||||
nbad = 0;
|
||||
#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)];
|
||||
@ -897,7 +984,6 @@ kvm_getargs(p, up)
|
||||
}
|
||||
*(char *)ip = ' ';
|
||||
ip++;
|
||||
nbad = 0;
|
||||
|
||||
for (cp = (char *)ip; cp < &argspac.argc[CLBYTES*2-stkoff]; cp++) {
|
||||
#endif
|
||||
@ -1190,6 +1276,182 @@ vtophys(loc)
|
||||
}
|
||||
#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,6 +1465,9 @@ seterr(va_alist)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,8 @@ static char sccsid[] = "@(#)kvm.c 5.18 (Berkeley) 5/7/91";
|
||||
#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,6 +110,13 @@ static union {
|
||||
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,6 +129,7 @@ static int dmmin, dmmax;
|
||||
static int pcbpf;
|
||||
static int argaddr0; /* XXX */
|
||||
static int argaddr1;
|
||||
static int swaddr;
|
||||
static int nswap;
|
||||
static char *tmp;
|
||||
#if defined(hp300)
|
||||
@ -156,21 +166,27 @@ static struct nlist nl[] = {
|
||||
#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 5
|
||||
#define X_SYSMAP 8
|
||||
#define X_DEADKERNEL X_SYSMAP
|
||||
{ "_Syssize" },
|
||||
#define X_SYSSIZE 6
|
||||
#define X_SYSSIZE 9
|
||||
{ "_allproc" },
|
||||
#define X_ALLPROC 7
|
||||
#define X_ALLPROC 10
|
||||
{ "_zombproc" },
|
||||
#define X_ZOMBPROC 8
|
||||
#define X_ZOMBPROC 11
|
||||
{ "_nproc" },
|
||||
#define X_NPROC 9
|
||||
#define X_LAST 9
|
||||
#define X_NPROC 12
|
||||
#define X_LAST 12
|
||||
#if defined(hp300)
|
||||
{ "_Sysseg" },
|
||||
#define X_SYSSEG (X_LAST+1)
|
||||
@ -187,6 +203,10 @@ static struct nlist nl[] = {
|
||||
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,6 +416,8 @@ hard2:
|
||||
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,11 +428,13 @@ kvm_getprocs(what, arg)
|
||||
return (-1);
|
||||
}
|
||||
copysize = ret;
|
||||
if ((kvmprocbase = (struct kinfo_proc *)malloc(copysize))
|
||||
== NULL) {
|
||||
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,6 +686,8 @@ kvm_getu(p)
|
||||
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,11 +695,49 @@ kvm_getu(p)
|
||||
seterr("zombie process");
|
||||
return (NULL);
|
||||
}
|
||||
/*
|
||||
* Reading from swap is too complicated right now.
|
||||
*/
|
||||
if ((p->p_flag & SLOAD) == 0)
|
||||
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
|
||||
*/
|
||||
@ -691,7 +755,6 @@ kvm_getu(p)
|
||||
/*
|
||||
* 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];
|
||||
@ -706,41 +769,48 @@ kvm_getu(p)
|
||||
argaddr1 = ctob(pftoc(pte[CLSIZE*1].pg_pfnum));
|
||||
}
|
||||
}
|
||||
#endif /* 08 Sep 92*/
|
||||
#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;
|
||||
/* 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);
|
||||
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
|
||||
#endif /* i386 */
|
||||
|
||||
hard:
|
||||
if (vatosw(p, vaddr, &argaddr1, &swb)) {
|
||||
if (argaddr1 == 0 && swb.size >= ARGSIZE)
|
||||
swaddr = swb.offset;
|
||||
}
|
||||
|
||||
return(&user.user);
|
||||
}
|
||||
#else
|
||||
@ -849,7 +919,23 @@ kvm_getargs(p, up)
|
||||
goto retucomm;
|
||||
if ((p->p_flag & SLOAD) == 0 || argaddr1 == 0) {
|
||||
#ifdef NEWVM
|
||||
goto retucomm; /* XXX for now */
|
||||
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;
|
||||
@ -882,10 +968,11 @@ kvm_getargs(p, up)
|
||||
#endif
|
||||
file = (char *) memf;
|
||||
}
|
||||
|
||||
nbad = 0;
|
||||
#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)];
|
||||
@ -897,7 +984,6 @@ kvm_getargs(p, up)
|
||||
}
|
||||
*(char *)ip = ' ';
|
||||
ip++;
|
||||
nbad = 0;
|
||||
|
||||
for (cp = (char *)ip; cp < &argspac.argc[CLBYTES*2-stkoff]; cp++) {
|
||||
#endif
|
||||
@ -1190,6 +1276,182 @@ vtophys(loc)
|
||||
}
|
||||
#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,6 +1465,9 @@ seterr(va_alist)
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user