home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / lib / libutil / kvm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-07  |  24.8 KB  |  1,107 lines

  1. /*-
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #if defined(LIBC_SCCS) && !defined(lint)
  35. static char sccsid[] = "@(#)kvm.c    5.18 (Berkeley) 5/7/91";
  36. #endif /* LIBC_SCCS and not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <sys/user.h>
  40. #include <sys/proc.h>
  41. #include <sys/ioctl.h>
  42. #include <sys/kinfo.h>
  43. #include <sys/tty.h>
  44. #include <machine/vmparam.h>
  45. #include <fcntl.h>
  46. #include <nlist.h>
  47. #include <kvm.h>
  48. #include <ndbm.h>
  49. #include <limits.h>
  50. #include <paths.h>
  51. #include <stdio.h>
  52. #include <string.h>
  53.  
  54. #ifdef SPPWAIT
  55. #define NEWVM
  56. #endif
  57.  
  58. #ifdef NEWVM
  59. #define    btop(x)        (((unsigned)(x)) >> PGSHIFT)    /* XXX */
  60. #define    ptob(x)        ((caddr_t)((x) << PGSHIFT))    /* XXX */
  61. #include <vm/vm.h>    /* ??? kinfo_proc currently includes this*/
  62. #include <sys/kinfo_proc.h>
  63. #ifdef hp300
  64. #include <hp300/hp300/pte.h>
  65. #endif
  66. #else /* NEWVM */
  67. #include <machine/pte.h>
  68. #include <sys/vmmac.h>
  69. #include <sys/text.h>
  70. #endif /* NEWVM */
  71.  
  72. /*
  73.  * files
  74.  */
  75. static    const char *unixf, *memf, *kmemf, *swapf;
  76. static    int unixx, mem, kmem, swap;
  77. static    DBM *db;
  78. /*
  79.  * flags
  80.  */
  81. static    int deadkernel;
  82. static    int kvminit = 0;
  83. static    int kvmfilesopen = 0;
  84. /*
  85.  * state
  86.  */
  87. static    struct kinfo_proc *kvmprocbase, *kvmprocptr;
  88. static    int kvmnprocs;
  89. /*
  90.  * u. buffer
  91.  */
  92. static union {
  93.     struct    user user;
  94.     char    upages[UPAGES][NBPG];
  95. } user;
  96. /*
  97.  * random other stuff
  98.  */
  99. #ifndef NEWVM
  100. static    struct pte *Usrptmap, *usrpt;
  101. static    struct    pte *Sysmap;
  102. static    int    Syssize;
  103. #endif
  104. static    int    dmmin, dmmax;
  105. static    int    pcbpf;
  106. static    int    argaddr0;    /* XXX */
  107. static    int    argaddr1;
  108. static    int    nswap;
  109. static    char    *tmp;
  110. #if defined(hp300)
  111. static    int    lowram;
  112. static    struct ste *Sysseg;
  113. #endif
  114.  
  115. #define basename(cp)    ((tmp=rindex((cp), '/')) ? tmp+1 : (cp))
  116. #define    MAXSYMSIZE    256
  117.  
  118. #if defined(hp300)
  119. #define pftoc(f)    ((f) - lowram)
  120. #define iskva(v)    (1)
  121. #endif
  122.  
  123. #ifndef pftoc
  124. #define pftoc(f)    (f)
  125. #endif
  126. #ifndef iskva
  127. #define iskva(v)    ((u_long)(v) & KERNBASE)
  128. #endif
  129.  
  130. static struct nlist nl[] = {
  131.     { "_Usrptmap" },
  132. #define    X_USRPTMAP    0
  133.     { "_usrpt" },
  134. #define    X_USRPT        1
  135.     { "_nswap" },
  136. #define    X_NSWAP        2
  137.     { "_dmmin" },
  138. #define    X_DMMIN        3
  139.     { "_dmmax" },
  140. #define    X_DMMAX        4
  141.     /*
  142.      * everything here and down, only if a dead kernel
  143.      */
  144.     { "_Sysmap" },
  145. #define    X_SYSMAP    5
  146. #define    X_DEADKERNEL    X_SYSMAP
  147.     { "_Syssize" },
  148. #define    X_SYSSIZE    6
  149.     { "_allproc" },
  150. #define X_ALLPROC    7
  151.     { "_zombproc" },
  152. #define X_ZOMBPROC    8
  153.     { "_nproc" },
  154. #define    X_NPROC        9
  155. #define    X_LAST        9
  156. #if defined(hp300)
  157.     { "_Sysseg" },
  158. #define    X_SYSSEG    (X_LAST+1)
  159.     { "_lowram" },
  160. #define    X_LOWRAM    (X_LAST+2)
  161. #endif
  162.     { "" },
  163. };
  164.  
  165. static off_t vtophys();
  166. static void klseek(), seterr(), setsyserr(), vstodb();
  167. static int getkvars(), kvm_doprocs(), kvm_init();
  168.  
  169. /*
  170.  * returns     0 if files were opened now,
  171.  *         1 if files were already opened,
  172.  *        -1 if files could not be opened.
  173.  */
  174. kvm_openfiles(uf, mf, sf)
  175.     const char *uf, *mf, *sf; 
  176. {
  177.     if (kvmfilesopen)
  178.         return (1);
  179.     unixx = mem = kmem = swap = -1;
  180.     unixf = (uf == NULL) ? _PATH_UNIX : uf; 
  181.     memf = (mf == NULL) ? _PATH_MEM : mf;
  182.  
  183.     if ((unixx = open(unixf, O_RDONLY, 0)) == -1) {
  184.         setsyserr("can't open %s", unixf);
  185.         goto failed;
  186.     }
  187.     if ((mem = open(memf, O_RDONLY, 0)) == -1) {
  188.         setsyserr("can't open %s", memf);
  189.         goto failed;
  190.     }
  191.     if (sf != NULL)
  192.         swapf = sf;
  193.     if (mf != NULL) {
  194.         deadkernel++;
  195.         kmemf = mf;
  196.         kmem = mem;
  197.         swap = -1;
  198.     } else {
  199.         kmemf = _PATH_KMEM;
  200.         if ((kmem = open(kmemf, O_RDONLY, 0)) == -1) {
  201.             setsyserr("can't open %s", kmemf);
  202.             goto failed;
  203.         }
  204.         swapf = (sf == NULL) ?  _PATH_DRUM : sf;
  205.         /*
  206.          * live kernel - avoid looking up nlist entries
  207.          * past X_DEADKERNEL.
  208.          */
  209.         nl[X_DEADKERNEL].n_name = "";
  210.     }
  211.     if (swapf != NULL && ((swap = open(swapf, O_RDONLY, 0)) == -1)) {
  212.         seterr("can't open %s", swapf);
  213.         goto failed;
  214.     }
  215.     kvmfilesopen++;
  216.     if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) /*XXX*/
  217.         return (-1);
  218.     return (0);
  219. failed:
  220.     kvm_close();
  221.     return (-1);
  222. }
  223.  
  224. static
  225. kvm_init(uf, mf, sf)
  226.     char *uf, *mf, *sf;
  227. {
  228.     if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
  229.         return (-1);
  230.     if (getkvars() == -1)
  231.         return (-1);
  232.     kvminit = 1;
  233.  
  234.     return (0);
  235. }
  236.  
  237. kvm_close()
  238. {
  239.     if (unixx != -1) {
  240.         close(unixx);
  241.         unixx = -1;
  242.     }
  243.     if (kmem != -1) {
  244.         if (kmem != mem)
  245.             close(kmem);
  246.         /* otherwise kmem is a copy of mem, and will be closed below */
  247.         kmem = -1;
  248.     }
  249.     if (mem != -1) {
  250.         close(mem);
  251.         mem = -1;
  252.     }
  253.     if (swap != -1) {
  254.         close(swap);
  255.         swap = -1;
  256.     }
  257.     if (db != NULL) {
  258.         dbm_close(db);
  259.         db = NULL;
  260.     }
  261.     kvminit = 0;
  262.     kvmfilesopen = 0;
  263.     deadkernel = 0;
  264. #ifndef NEWVM
  265.     if (Sysmap) {
  266.         free(Sysmap);
  267.         Sysmap = NULL;
  268.     }
  269. #endif
  270. }
  271.  
  272. kvm_nlist(nl)
  273.     struct nlist *nl;
  274. {
  275.     datum key, data;
  276.     char dbname[MAXPATHLEN];
  277.     char dbversion[_POSIX2_LINE_MAX];
  278.     char kversion[_POSIX2_LINE_MAX];
  279.     int dbversionlen;
  280.     char symbuf[MAXSYMSIZE];
  281.     struct nlist nbuf, *n;
  282.     int num, did;
  283.  
  284.     if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
  285.         return (-1);
  286.     if (deadkernel)
  287.         goto hard2;
  288.     /*
  289.      * initialize key datum
  290.      */
  291.     key.dptr = symbuf;
  292.  
  293.     if (db != NULL)
  294.         goto win;    /* off to the races */
  295.     /*
  296.      * open database
  297.      */
  298.     sprintf(dbname, "%s/kvm_%s", _PATH_VARRUN, basename(unixf));
  299.     if ((db = dbm_open(dbname, O_RDONLY, 0)) == NULL)
  300.         goto hard2;
  301.     /*
  302.      * read version out of database
  303.      */
  304.     bcopy("VERSION", symbuf, sizeof ("VERSION")-1);
  305.     key.dsize = (sizeof ("VERSION") - 1) + 1;
  306.     data = dbm_fetch(db, key);
  307.     if (data.dptr == NULL)
  308.         goto hard1;
  309.     bcopy(data.dptr, dbversion, data.dsize);
  310.     dbversionlen = data.dsize;
  311.     /*
  312.      * read version string from kernel memory
  313.      */
  314.     bcopy("_version", symbuf, sizeof ("_version")-1);
  315.     key.dsize = (sizeof ("_version")-1) + 1;
  316.     data = dbm_fetch(db, key);
  317.     if (data.dptr == NULL)
  318.         goto hard1;
  319.     if (data.dsize != sizeof (struct nlist))
  320.         goto hard1;
  321.     bcopy(data.dptr, &nbuf, sizeof (struct nlist));
  322.     lseek(kmem, nbuf.n_value, 0);
  323.     if (read(kmem, kversion, dbversionlen) != dbversionlen)
  324.         goto hard1;
  325.     /*
  326.      * if they match, we win - otherwise do it the hard way
  327.      */
  328.     if (bcmp(dbversion, kversion, dbversionlen) != 0)
  329.         goto hard1;
  330.     /*
  331.      * getem from the database.
  332.      */
  333. win:
  334.     num = did = 0;
  335.     for (n = nl; n->n_name && n->n_name[0]; n++, num++) {
  336.         int len;
  337.         /*
  338.          * clear out fields from users buffer
  339.          */
  340.         n->n_type = 0;
  341.         n->n_other = 0;
  342.         n->n_desc = 0;
  343.         n->n_value = 0;
  344.         /*
  345.          * query db
  346.          */
  347.         if ((len = strlen(n->n_name)) > MAXSYMSIZE) {
  348.             seterr("symbol too large");
  349.             return (-1);
  350.         }
  351.         (void)strcpy(symbuf, n->n_name);
  352.         key.dsize = len + 1;
  353.         data = dbm_fetch(db, key);
  354.         if (data.dptr == NULL || data.dsize != sizeof (struct nlist))
  355.             continue;
  356.         bcopy(data.dptr, &nbuf, sizeof (struct nlist));
  357.         n->n_value = nbuf.n_value;
  358.         n->n_type = nbuf.n_type;
  359.         n->n_desc = nbuf.n_desc;
  360.         n->n_other = nbuf.n_other;
  361.         did++;
  362.     }
  363.     return (num - did);
  364. hard1:
  365.     dbm_close(db);
  366.     db = NULL;
  367. hard2:
  368.     num = nlist(unixf, nl);
  369.     if (num == -1)
  370.         seterr("nlist (hard way) failed");
  371.     return (num);
  372. }
  373.  
  374. kvm_getprocs(what, arg)
  375.     int what, arg;
  376. {
  377.     if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
  378.         return (NULL);
  379.     if (!deadkernel) {
  380.         int ret, copysize;
  381.  
  382.         if ((ret = getkerninfo(what, NULL, NULL, arg)) == -1) {
  383.             setsyserr("can't get estimate for kerninfo");
  384.             return (-1);
  385.         }
  386.         copysize = ret;
  387.         if ((kvmprocbase = (struct kinfo_proc *)malloc(copysize)) 
  388.              == NULL) {
  389.             seterr("out of memory");
  390.             return (-1);
  391.         }
  392.         if ((ret = getkerninfo(what, kvmprocbase, ©size, 
  393.              arg)) == -1) {
  394.             setsyserr("can't get proc list");
  395.             return (-1);
  396.         }
  397.         if (copysize % sizeof (struct kinfo_proc)) {
  398.             seterr("proc size mismatch (got %d total, kinfo_proc: %d)",
  399.                 copysize, sizeof (struct kinfo_proc));
  400.             return (-1);
  401.         }
  402.         kvmnprocs = copysize / sizeof (struct kinfo_proc);
  403.     } else {
  404.         int nproc;
  405.  
  406.         if (kvm_read((void *) nl[X_NPROC].n_value, &nproc,
  407.             sizeof (int)) != sizeof (int)) {
  408.             seterr("can't read nproc");
  409.             return (-1);
  410.         }
  411.         if ((kvmprocbase = (struct kinfo_proc *)
  412.              malloc(nproc * sizeof (struct kinfo_proc))) == NULL) {
  413.             seterr("out of memory (addr: %x nproc = %d)",
  414.                 nl[X_NPROC].n_value, nproc);
  415.             return (-1);
  416.         }
  417.         kvmnprocs = kvm_doprocs(what, arg, kvmprocbase);
  418.         realloc(kvmprocbase, kvmnprocs * sizeof (struct kinfo_proc));
  419.     }
  420.     kvmprocptr = kvmprocbase;
  421.  
  422.     return (kvmnprocs);
  423. }
  424.  
  425. /*
  426.  * XXX - should NOT give up so easily - especially since the kernel
  427.  * may be corrupt (it died).  Should gather as much information as possible.
  428.  * Follows proc ptrs instead of reading table since table may go
  429.  * away soon.
  430.  */
  431. static
  432. kvm_doprocs(what, arg, buff)
  433.     int what, arg;
  434.     char *buff;
  435. {
  436.     struct proc *p, proc;
  437.     register char *bp = buff;
  438.     int i = 0;
  439.     int doingzomb = 0;
  440.     struct eproc eproc;
  441.     struct pgrp pgrp;
  442.     struct session sess;
  443.     struct tty tty;
  444. #ifndef NEWVM
  445.     struct text text;
  446. #endif
  447.  
  448.     /* allproc */
  449.     if (kvm_read((void *) nl[X_ALLPROC].n_value, &p, 
  450.         sizeof (struct proc *)) != sizeof (struct proc *)) {
  451.         seterr("can't read allproc");
  452.         return (-1);
  453.     }
  454.  
  455. again:
  456.     for (; p; p = proc.p_nxt) {
  457.         if (kvm_read(p, &proc, sizeof (struct proc)) !=
  458.             sizeof (struct proc)) {
  459.             seterr("can't read proc at %x", p);
  460.             return (-1);
  461.         }
  462. #ifdef NEWVM
  463.         if (kvm_read(proc.p_cred, &eproc.e_pcred,
  464.             sizeof (struct pcred)) == sizeof (struct pcred))
  465.             (void) kvm_read(eproc.e_pcred.pc_ucred, &eproc.e_ucred,
  466.                 sizeof (struct ucred));
  467.         switch(ki_op(what)) {
  468.             
  469.         case KINFO_PROC_PID:
  470.             if (proc.p_pid != (pid_t)arg)
  471.                 continue;
  472.             break;
  473.  
  474.  
  475.         case KINFO_PROC_UID:
  476.             if (eproc.e_ucred.cr_uid != (uid_t)arg)
  477.                 continue;
  478.             break;
  479.  
  480.         case KINFO_PROC_RUID:
  481.             if (eproc.e_pcred.p_ruid != (uid_t)arg)
  482.                 continue;
  483.             break;
  484.         }
  485. #else
  486.         switch(ki_op(what)) {
  487.             
  488.         case KINFO_PROC_PID:
  489.             if (proc.p_pid != (pid_t)arg)
  490.                 continue;
  491.             break;
  492.  
  493.  
  494.         case KINFO_PROC_UID:
  495.             if (proc.p_uid != (uid_t)arg)
  496.                 continue;
  497.             break;
  498.  
  499.         case KINFO_PROC_RUID:
  500.             if (proc.p_ruid != (uid_t)arg)
  501.                 continue;
  502.             break;
  503.         }
  504. #endif
  505.         /*
  506.          * gather eproc
  507.          */
  508.         eproc.e_paddr = p;
  509.         if (kvm_read(proc.p_pgrp, &pgrp, sizeof (struct pgrp)) !=
  510.                 sizeof (struct pgrp)) {
  511.             seterr("can't read pgrp at %x", proc.p_pgrp);
  512.             return (-1);
  513.         }
  514.         eproc.e_sess = pgrp.pg_session;
  515.         eproc.e_pgid = pgrp.pg_id;
  516.         eproc.e_jobc = pgrp.pg_jobc;
  517.         if (kvm_read(pgrp.pg_session, &sess, sizeof (struct session))
  518.            != sizeof (struct session)) {
  519.             seterr("can't read session at %x", pgrp.pg_session);
  520.             return (-1);
  521.         }
  522.         if ((proc.p_flag&SCTTY) && sess.s_ttyp != NULL) {
  523.             if (kvm_read(sess.s_ttyp, &tty, sizeof (struct tty))
  524.                 != sizeof (struct tty)) {
  525.                 seterr("can't read tty at %x", sess.s_ttyp);
  526.                 return (-1);
  527.             }
  528.             eproc.e_tdev = tty.t_dev;
  529.             eproc.e_tsess = tty.t_session;
  530.             if (tty.t_pgrp != NULL) {
  531.                 if (kvm_read(tty.t_pgrp, &pgrp, sizeof (struct
  532.                     pgrp)) != sizeof (struct pgrp)) {
  533.                     seterr("can't read tpgrp at &x", 
  534.                         tty.t_pgrp);
  535.                     return (-1);
  536.                 }
  537.                 eproc.e_tpgid = pgrp.pg_id;
  538.             } else
  539.                 eproc.e_tpgid = -1;
  540.         } else
  541.             eproc.e_tdev = NODEV;
  542.         if (proc.p_wmesg)
  543.             kvm_read(proc.p_wmesg, eproc.e_wmesg, WMESGLEN);
  544. #ifdef NEWVM
  545.         (void) kvm_read(proc.p_vmspace, &eproc.e_vm,
  546.             sizeof (struct vmspace));
  547.         eproc.e_xsize = eproc.e_xrssize =
  548.             eproc.e_xccount = eproc.e_xswrss = 0;
  549. #else
  550.         if (proc.p_textp) {
  551.             kvm_read(proc.p_textp, &text, sizeof (text));
  552.             eproc.e_xsize = text.x_size;
  553.             eproc.e_xrssize = text.x_rssize;
  554.             eproc.e_xccount = text.x_ccount;
  555.             eproc.e_xswrss = text.x_swrss;
  556.         } else {
  557.             eproc.e_xsize = eproc.e_xrssize =
  558.               eproc.e_xccount = eproc.e_xswrss = 0;
  559.         }
  560. #endif
  561.  
  562.         switch(ki_op(what)) {
  563.  
  564.         case KINFO_PROC_PGRP:
  565.             if (eproc.e_pgid != (pid_t)arg)
  566.                 continue;
  567.             break;
  568.  
  569.         case KINFO_PROC_TTY:
  570.             if ((proc.p_flag&SCTTY) == 0 || 
  571.                  eproc.e_tdev != (dev_t)arg)
  572.                 continue;
  573.             break;
  574.         }
  575.  
  576.         i++;
  577.         bcopy(&proc, bp, sizeof (struct proc));
  578.         bp += sizeof (struct proc);
  579.         bcopy(&eproc, bp, sizeof (struct eproc));
  580.         bp+= sizeof (struct eproc);
  581.     }
  582.     if (!doingzomb) {
  583.         /* zombproc */
  584.         if (kvm_read((void *) nl[X_ZOMBPROC].n_value, &p, 
  585.             sizeof (struct proc *)) != sizeof (struct proc *)) {
  586.             seterr("can't read zombproc");
  587.             return (-1);
  588.         }
  589.         doingzomb = 1;
  590.         goto again;
  591.     }
  592.  
  593.     return (i);
  594. }
  595.  
  596. struct proc *
  597. kvm_nextproc()
  598. {
  599.  
  600.     if (!kvmprocbase && kvm_getprocs(0, 0) == -1)
  601.         return (NULL);
  602.     if (kvmprocptr >= (kvmprocbase + kvmnprocs)) {
  603.         seterr("end of proc list");
  604.         return (NULL);
  605.     }
  606.     return((struct proc *)(kvmprocptr++));
  607. }
  608.  
  609. struct eproc *
  610. kvm_geteproc(p)
  611.     const struct proc *p;
  612. {
  613.     return ((struct eproc *)(((char *)p) + sizeof (struct proc)));
  614. }
  615.  
  616. kvm_setproc()
  617. {
  618.     kvmprocptr = kvmprocbase;
  619. }
  620.  
  621. kvm_freeprocs()
  622. {
  623.  
  624.     if (kvmprocbase) {
  625.         free(kvmprocbase);
  626.         kvmprocbase = NULL;
  627.     }
  628. }
  629.  
  630. #ifdef NEWVM
  631. struct user *
  632. kvm_getu(p)
  633.     const struct proc *p;
  634. {
  635.     register struct kinfo_proc *kp = (struct kinfo_proc *)p;
  636.     register int i;
  637.     register char *up;
  638.  
  639.     if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
  640.         return (NULL);
  641.     if (p->p_stat == SZOMB) {
  642.         seterr("zombie process");
  643.         return (NULL);
  644.     }
  645.     /*
  646.      * Reading from swap is too complicated right now.
  647.      */
  648.     if ((p->p_flag & SLOAD) == 0)
  649.         return(NULL);
  650.     /*
  651.      * Read u-area one page at a time for the benefit of post-mortems
  652.      */
  653.     up = (char *) p->p_addr;
  654.     for (i = 0; i < UPAGES; i++) {
  655.         klseek(kmem, (long)up, 0);
  656.         if (read(kmem, user.upages[i], CLBYTES) != CLBYTES) {
  657.             seterr("cant read page %x of u of pid %d from %s",
  658.                 up, p->p_pid, kmemf);
  659.             return(NULL);
  660.         }
  661.         up += CLBYTES;
  662.     }
  663.     pcbpf = (int) btop(p->p_addr);    /* what should this be really? */
  664.     /*
  665.      * Conjure up a physical address for the arguments.
  666.      */
  667.     argaddr0 = argaddr1 = 0;
  668. #ifdef hp300
  669.     if (kp->kp_eproc.e_vm.vm_pmap.pm_ptab) {
  670.         struct pte pte[CLSIZE*2];
  671.  
  672.         klseek(kmem,
  673.             (long)&kp->kp_eproc.e_vm.vm_pmap.pm_ptab
  674.             [btoc(USRSTACK-CLBYTES*2)], 0);
  675.         if (read(kmem, (char *)&pte, sizeof(pte)) == sizeof(pte)) {
  676. #if CLBYTES < 2048
  677.             argaddr0 = ctob(pftoc(pte[CLSIZE*0].pg_pfnum));
  678. #endif
  679.             argaddr1 = ctob(pftoc(pte[CLSIZE*1].pg_pfnum));
  680.         }
  681.     }
  682.     kp->kp_eproc.e_vm.vm_rssize =
  683.         kp->kp_eproc.e_vm.vm_pmap.pm_stats.resident_count; /* XXX */
  684. #endif
  685.     return(&user.user);
  686. }
  687. #else
  688. struct user *
  689. kvm_getu(p)
  690.     const struct proc *p;
  691. {
  692.     struct pte *pteaddr, apte;
  693.     struct pte arguutl[HIGHPAGES+(CLSIZE*2)];
  694.     register int i;
  695.     int ncl;
  696.  
  697.     if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
  698.         return (NULL);
  699.     if (p->p_stat == SZOMB) {
  700.         seterr("zombie process");
  701.         return (NULL);
  702.     }
  703.     if ((p->p_flag & SLOAD) == 0) {
  704.         if (swap < 0) {
  705.             seterr("no swap");
  706.             return (NULL);
  707.         }
  708.         (void) lseek(swap, (long)dtob(p->p_swaddr), 0);
  709.         if (read(swap, (char *)&user.user, sizeof (struct user)) != 
  710.             sizeof (struct user)) {
  711.             seterr("can't read u for pid %d from %s",
  712.                 p->p_pid, swapf);
  713.             return (NULL);
  714.         }
  715.         pcbpf = 0;
  716.         argaddr0 = 0;
  717.         argaddr1 = 0;
  718.         return (&user.user);
  719.     }
  720.     pteaddr = &Usrptmap[btokmx(p->p_p0br) + p->p_szpt - 1];
  721.     klseek(kmem, (long)pteaddr, 0);
  722.     if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
  723.         seterr("can't read indir pte to get u for pid %d from %s",
  724.             p->p_pid, kmemf);
  725.         return (NULL);
  726.     }
  727.     lseek(mem, (long)ctob(pftoc(apte.pg_pfnum+1)) - sizeof(arguutl), 0);
  728.     if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
  729.         seterr("can't read page table for u of pid %d from %s",
  730.             p->p_pid, memf);
  731.         return (NULL);
  732.     }
  733.     if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
  734.         argaddr0 = ctob(pftoc(arguutl[0].pg_pfnum));
  735.     else
  736.         argaddr0 = 0;
  737.     if (arguutl[CLSIZE*1].pg_fod == 0 && arguutl[CLSIZE*1].pg_pfnum)
  738.         argaddr1 = ctob(pftoc(arguutl[CLSIZE*1].pg_pfnum));
  739.     else
  740.         argaddr1 = 0;
  741.     pcbpf = arguutl[CLSIZE*2].pg_pfnum;
  742.     ncl = (sizeof (struct user) + CLBYTES - 1) / CLBYTES;
  743.     while (--ncl >= 0) {
  744.         i = ncl * CLSIZE;
  745.         lseek(mem,
  746.               (long)ctob(pftoc(arguutl[(CLSIZE*2)+i].pg_pfnum)), 0);
  747.         if (read(mem, user.upages[i], CLBYTES) != CLBYTES) {
  748.             seterr("can't read page %d of u of pid %d from %s",
  749.                 arguutl[(CLSIZE*2)+i].pg_pfnum, p->p_pid, memf);
  750.             return(NULL);
  751.         }
  752.     }
  753.     return (&user.user);
  754. }
  755. #endif
  756.  
  757. char *
  758. kvm_getargs(p, up)
  759.     const struct proc *p;
  760.     const struct user *up;
  761. {
  762.     char cmdbuf[CLBYTES*2];
  763.     union {
  764.         char    argc[CLBYTES*2];
  765.         int    argi[CLBYTES*2/sizeof (int)];
  766.     } argspac;
  767.     register char *cp;
  768.     register int *ip;
  769.     char c;
  770.     int nbad;
  771. #ifndef NEWVM
  772.     struct dblock db;
  773. #endif
  774.     const char *file;
  775.     int stkoff = 0;
  776.  
  777. #if defined(NEWVM) && defined(hp300)
  778.     stkoff = 20;            /* XXX for sigcode */
  779. #endif
  780.     if (up == NULL || p->p_pid == 0 || p->p_pid == 2)
  781.         goto retucomm;
  782.     if ((p->p_flag & SLOAD) == 0 || argaddr1 == 0) {
  783. #ifdef NEWVM
  784.         goto retucomm;    /* XXX for now */
  785. #else
  786.         if (swap < 0 || p->p_ssize == 0)
  787.             goto retucomm;
  788.         vstodb(0, CLSIZE, &up->u_smap, &db, 1);
  789.         (void) lseek(swap, (long)dtob(db.db_base), 0);
  790.         if (read(swap, (char *)&argspac.argc[CLBYTES], CLBYTES)
  791.             != CLBYTES)
  792.             goto bad;
  793.         vstodb(1, CLSIZE, &up->u_smap, &db, 1);
  794.         (void) lseek(swap, (long)dtob(db.db_base), 0);
  795.         if (read(swap, (char *)&argspac.argc[0], CLBYTES) != CLBYTES)
  796.             goto bad;
  797.         file = swapf;
  798. #endif
  799.     } else {
  800.         if (argaddr0) {
  801.             lseek(mem, (long)argaddr0, 0);
  802.             if (read(mem, (char *)&argspac, CLBYTES) != CLBYTES)
  803.                 goto bad;
  804.         } else
  805.             bzero(&argspac, CLBYTES);
  806.         lseek(mem, (long)argaddr1, 0);
  807.         if (read(mem, &argspac.argc[CLBYTES], CLBYTES) != CLBYTES)
  808.             goto bad;
  809.         file = (char *) memf;
  810.     }
  811.     ip = &argspac.argi[CLBYTES*2/sizeof (int)];
  812.     ip -= 2;                /* last arg word and .long 0 */
  813.     ip -= stkoff / sizeof (int);
  814.     while (*--ip) {
  815.         if (ip == argspac.argi)
  816.             goto retucomm;
  817.     }
  818.     *(char *)ip = ' ';
  819.     ip++;
  820.     nbad = 0;
  821.     for (cp = (char *)ip; cp < &argspac.argc[CLBYTES*2-stkoff]; cp++) {
  822.         c = *cp & 0177;
  823.         if (c == 0)
  824.             *cp = ' ';
  825.         else if (c < ' ' || c > 0176) {
  826.             if (++nbad >= 5*(0+1)) {    /* eflg -> 0 XXX */
  827.                 *cp++ = ' ';
  828.                 break;
  829.             }
  830.             *cp = '?';
  831.         } else if (0 == 0 && c == '=') {    /* eflg -> 0 XXX */
  832.             while (*--cp != ' ')
  833.                 if (cp <= (char *)ip)
  834.                     break;
  835.             break;
  836.         }
  837.     }
  838.     *cp = 0;
  839.     while (*--cp == ' ')
  840.         *cp = 0;
  841.     cp = (char *)ip;
  842.     (void) strncpy(cmdbuf, cp, &argspac.argc[CLBYTES*2] - cp);
  843.     if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
  844.         (void) strcat(cmdbuf, " (");
  845.         (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm));
  846.         (void) strcat(cmdbuf, ")");
  847.     }
  848.     return (cmdbuf);
  849.  
  850. bad:
  851.     seterr("error locating command name for pid %d from %s",
  852.         p->p_pid, file);
  853. retucomm:
  854.     (void) strcpy(cmdbuf, " (");
  855.     (void) strncat(cmdbuf, p->p_comm, sizeof (p->p_comm));
  856.     (void) strcat(cmdbuf, ")");
  857.     return (cmdbuf);
  858. }
  859.  
  860.  
  861. static
  862. getkvars()
  863. {
  864.     if (kvm_nlist(nl) == -1)
  865.         return (-1);
  866.     if (deadkernel) {
  867.         /* We must do the sys map first because klseek uses it */
  868.         long    addr;
  869.  
  870. #ifndef NEWVM
  871.         Syssize = nl[X_SYSSIZE].n_value;
  872.         Sysmap = (struct pte *)
  873.             calloc((unsigned) Syssize, sizeof (struct pte));
  874.         if (Sysmap == NULL) {
  875.             seterr("out of space for Sysmap");
  876.             return (-1);
  877.         }
  878.         addr = (long) nl[X_SYSMAP].n_value;
  879.         addr &= ~KERNBASE;
  880.         (void) lseek(kmem, addr, 0);
  881.         if (read(kmem, (char *) Sysmap, Syssize * sizeof (struct pte))
  882.             != Syssize * sizeof (struct pte)) {
  883.             seterr("can't read Sysmap");
  884.             return (-1);
  885.         }
  886. #endif
  887. #if defined(hp300)
  888.         addr = (long) nl[X_LOWRAM].n_value;
  889.         (void) lseek(kmem, addr, 0);
  890.         if (read(kmem, (char *) &lowram, sizeof (lowram))
  891.             != sizeof (lowram)) {
  892.             seterr("can't read lowram");
  893.             return (-1);
  894.         }
  895.         lowram = btop(lowram);
  896.         Sysseg = (struct ste *) malloc(NBPG);
  897.         if (Sysseg == NULL) {
  898.             seterr("out of space for Sysseg");
  899.             return (-1);
  900.         }
  901.         addr = (long) nl[X_SYSSEG].n_value;
  902.         (void) lseek(kmem, addr, 0);
  903.         read(kmem, (char *)&addr, sizeof(addr));
  904.         (void) lseek(kmem, (long)addr, 0);
  905.         if (read(kmem, (char *) Sysseg, NBPG) != NBPG) {
  906.             seterr("can't read Sysseg");
  907.             return (-1);
  908.         }
  909. #endif
  910.     }
  911. #ifndef NEWVM
  912.     usrpt = (struct pte *)nl[X_USRPT].n_value;
  913.     Usrptmap = (struct pte *)nl[X_USRPTMAP].n_value;
  914. #endif
  915.     if (kvm_read((void *) nl[X_NSWAP].n_value, &nswap, sizeof (long)) !=
  916.         sizeof (long)) {
  917.         seterr("can't read nswap");
  918.         return (-1);
  919.     }
  920.     if (kvm_read((void *) nl[X_DMMIN].n_value, &dmmin, sizeof (long)) !=
  921.         sizeof (long)) {
  922.         seterr("can't read dmmin");
  923.         return (-1);
  924.     }
  925.     if (kvm_read((void *) nl[X_DMMAX].n_value, &dmmax, sizeof (long)) !=
  926.         sizeof (long)) {
  927.         seterr("can't read dmmax");
  928.         return (-1);
  929.     }
  930.     return (0);
  931. }
  932.  
  933. kvm_read(loc, buf, len)
  934.     void *loc;
  935.     void *buf;
  936. {
  937.     if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
  938.         return (-1);
  939.     if (iskva(loc)) {
  940.         klseek(kmem, (off_t) loc, 0);
  941.         if (read(kmem, buf, len) != len) {
  942.             seterr("error reading kmem at %x", loc);
  943.             return (-1);
  944.         }
  945.     } else {
  946.         lseek(mem, (off_t) loc, 0);
  947.         if (read(mem, buf, len) != len) {
  948.             seterr("error reading mem at %x", loc);
  949.             return (-1);
  950.         }
  951.     }
  952.     return (len);
  953. }
  954.  
  955. static void
  956. klseek(fd, loc, off)
  957.     int fd;
  958.     off_t loc;
  959.     int off;
  960. {
  961.  
  962.     if (deadkernel) {
  963.         if ((loc = vtophys(loc)) == -1)
  964.             return;
  965.     }
  966.     (void) lseek(fd, (off_t)loc, off);
  967. }
  968.  
  969. #ifndef NEWVM
  970. /*
  971.  * Given a base/size pair in virtual swap area,
  972.  * return a physical base/size pair which is the
  973.  * (largest) initial, physically contiguous block.
  974.  */
  975. static void
  976. vstodb(vsbase, vssize, dmp, dbp, rev)
  977.     register int vsbase;
  978.     int vssize;
  979.     struct dmap *dmp;
  980.     register struct dblock *dbp;
  981. {
  982.     register int blk = dmmin;
  983.     register swblk_t *ip = dmp->dm_map;
  984.  
  985.     vsbase = ctod(vsbase);
  986.     vssize = ctod(vssize);
  987.     if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
  988.         /*panic("vstodb")*/;
  989.     while (vsbase >= blk) {
  990.         vsbase -= blk;
  991.         if (blk < dmmax)
  992.             blk *= 2;
  993.         ip++;
  994.     }
  995.     if (*ip <= 0 || *ip + blk > nswap)
  996.         /*panic("vstodb")*/;
  997.     dbp->db_size = MIN(vssize, blk - vsbase);
  998.     dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
  999. }
  1000. #endif
  1001.  
  1002. #ifdef NEWVM
  1003. static off_t
  1004. vtophys(loc)
  1005.     long    loc;
  1006. {
  1007.     off_t newloc = (off_t) -1;
  1008. #ifdef hp300
  1009.     int p, ste, pte;
  1010.  
  1011.     ste = *(int *)&Sysseg[loc >> SG_ISHIFT];
  1012.     if ((ste & SG_V) == 0) {
  1013.         seterr("vtophys: segment not valid");
  1014.         return((off_t) -1);
  1015.     }
  1016.     p = btop(loc & SG_PMASK);
  1017.     newloc = (ste & SG_FRAME) + (p * sizeof(struct pte));
  1018.     (void) lseek(kmem, (long)(newloc-(off_t)ptob(lowram)), 0);
  1019.     if (read(kmem, (char *)&pte, sizeof pte) != sizeof pte) {
  1020.         seterr("vtophys: cannot locate pte");
  1021.         return((off_t) -1);
  1022.     }
  1023.     newloc = pte & PG_FRAME;
  1024.     if (pte == PG_NV || newloc < (off_t)ptob(lowram)) {
  1025.         seterr("vtophys: page not valid");
  1026.         return((off_t) -1);
  1027.     }
  1028.     newloc = (newloc - (off_t)ptob(lowram)) + (loc & PGOFSET);
  1029. #endif
  1030.     return((off_t) newloc);
  1031. }
  1032. #else
  1033. static off_t
  1034. vtophys(loc)
  1035.     long loc;
  1036. {
  1037.     int p;
  1038.     off_t newloc;
  1039.     register struct pte *pte;
  1040.  
  1041.     newloc = loc & ~KERNBASE;
  1042.     p = btop(newloc);
  1043. #if defined(vax) || defined(tahoe)
  1044.     if ((loc & KERNBASE) == 0) {
  1045.         seterr("vtophys: translating non-kernel address");
  1046.         return((off_t) -1);
  1047.     }
  1048. #endif
  1049.     if (p >= Syssize) {
  1050.         seterr("vtophys: page out of bound (%d>=%d)", p, Syssize);
  1051.         return((off_t) -1);
  1052.     }
  1053.     pte = &Sysmap[p];
  1054.     if (pte->pg_v == 0 && (pte->pg_fod || pte->pg_pfnum == 0)) {
  1055.         seterr("vtophys: page not valid");
  1056.         return((off_t) -1);
  1057.     }
  1058. #if defined(hp300)
  1059.     if (pte->pg_pfnum < lowram) {
  1060.         seterr("vtophys: non-RAM page (%d<%d)", pte->pg_pfnum, lowram);
  1061.         return((off_t) -1);
  1062.     }
  1063. #endif
  1064.     loc = (long) (ptob(pftoc(pte->pg_pfnum)) + (loc & PGOFSET));
  1065.     return(loc);
  1066. }
  1067. #endif
  1068.  
  1069. #include <varargs.h>
  1070. static char errbuf[_POSIX2_LINE_MAX];
  1071.  
  1072. static void
  1073. seterr(va_alist)
  1074.     va_dcl
  1075. {
  1076.     char *fmt;
  1077.     va_list ap;
  1078.  
  1079.     va_start(ap);
  1080.     fmt = va_arg(ap, char *);
  1081.     (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap);
  1082.     va_end(ap);
  1083. }
  1084.  
  1085. static void
  1086. setsyserr(va_alist)
  1087.     va_dcl
  1088. {
  1089.     char *fmt, *cp;
  1090.     va_list ap;
  1091.     extern int errno;
  1092.  
  1093.     va_start(ap);
  1094.     fmt = va_arg(ap, char *);
  1095.     (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap);
  1096.     for (cp=errbuf; *cp; cp++)
  1097.         ;
  1098.     snprintf(cp, _POSIX2_LINE_MAX - (cp - errbuf), ": %s", strerror(errno));
  1099.     va_end(ap);
  1100. }
  1101.  
  1102. char *
  1103. kvm_geterr()
  1104. {
  1105.     return (errbuf);
  1106. }
  1107.