1: /* 2: ** kvm.c A set of functions emulating KVM for machines without them. 3: ** 4: ** This code is in the public domain and may be used freely by anyone 5: ** who wants to. 6: ** 7: ** Last update: 12 Dec 1992 8: ** 9: ** Author: Peter Eriksson <pen@lysator.liu.se> 10: */ 11: 12: #ifndef NO_KVM 13: #ifndef HAVE_KVM 14: 15: #ifdef NeXT31 16: # include <libc.h> 17: #endif 18: 19: #include <stdio.h> 20: #include <errno.h> 21: #include <nlist.h> 22: 23: #ifdef IRIX 24: # ifdef IRIX62 25: # if _MIPS_SZPTR == 64 26: # define _K64U64 1 27: # else 28: # define _K32U32 1 29: # endif 30: # endif 31: 32: # include <sys/sbd.h> 33: 34: # ifndef K0_TO_PHYS 35: # define K0_TO_PHYS(x) (x) 36: # endif 37: 38: # if defined(IRIX6) || (defined(IRIX62) && _MIPS_SZPTR == 64) 39: # define nlist nlist64 40: # endif 41: #endif 42: 43: #ifdef BSD43 44: # include <sys/types.h> 45: # include <sys/dir.h> 46: # include <sys/param.h> 47: # include <sys/vmmac.h> 48: #if 0 49: # include <sys/time.h> 50: #else 51: # include <sys/user.h> 52: #endif 53: # ifdef DIRBLKSIZ 54: # undef DIRBLKSIZ 55: # endif 56: #if 0 57: # include <sys/user.h> 58: #endif 59: # include <sys/proc.h> 60: # include <machine/pte.h> 61: # include "paths.h" 62: #endif 63: 64: 65: #include "kernel/kvm.h" 66: #include "paths.h" 67: 68: #if defined(BSD43) || defined(MIPS) 69: extern int errno; 70: #endif 71: 72: extern void *malloc(); 73: 74: 75: kvm_t *kvm_open(namelist, corefile, swapfile, flag, errstr) 76: char *namelist; 77: char *corefile; 78: char *swapfile; 79: int flag; 80: char *errstr; 81: { 82: kvm_t *kd; 83: 84: if (!namelist) 85: namelist = _PATH_UNIX; 86: if (!corefile) 87: corefile = _PATH_KMEM; 88: 89: #ifdef BSD43 90: if (!swapfile) 91: swapfile = _PATH_SWAP; 92: #endif 93: 94: kd = (kvm_t *) malloc(sizeof(kvm_t)); 95: if (!kd) 96: { 97: if (errstr) 98: perror(errstr); 99: return NULL; 100: } 101: 102: kd->namelist = (char *) malloc(strlen(namelist)+1); 103: if (!kd->namelist) 104: { 105: if (errstr) 106: perror(errstr); 107: return NULL; 108: } 109: 110: if ((kd->fd = open(corefile, flag)) < 0) 111: { 112: if (errstr) 113: perror(errstr); 114: free(kd->namelist); 115: free(kd); 116: return NULL; 117: } 118: 119: #ifdef BSD43 120: if ((kd->swap_fd = open(swapfile, flag)) < 0) 121: { 122: if (errstr) 123: perror(errstr); 124: close(kd->fd); 125: free(kd->namelist); 126: free(kd); 127: return NULL; 128: } 129: 130: if ((kd->mem_fd = open(_PATH_MEM, flag)) < 0) 131: { 132: if (errstr) 133: perror(errstr); 134: close(kd->swap_fd); 135: close(kd->fd); 136: free(kd->namelist); 137: free(kd); 138: return NULL; 139: } 140: #endif 141: 142: strcpy(kd->namelist, namelist); 143: return kd; 144: } 145: 146: 147: int kvm_close(kd) 148: kvm_t *kd; 149: { 150: int code; 151: 152: code = close(kd->fd); 153: #ifdef BSD43 154: close(kd->swap_fd); 155: close(kd->mem_fd); 156: if (kd->proctab) 157: free(kd->proctab); 158: #endif 159: free(kd->namelist); 160: free(kd); 161: 162: return code; 163: } 164: 165: 166: /* 167: ** Extract offsets to the symbols in the 'nl' list. Returns 0 if all found, 168: ** or else the number of variables that was not found. 169: */ 170: int kvm_nlist(kd, nl) 171: kvm_t *kd; 172: struct nlist *nl; 173: { 174: int code; 175: int i; 176: 177: code = nlist(kd->namelist, nl); 178: 179: if (code != 0) 180: return code; 181: 182: /* 183: ** Verify that we got all the needed variables. Needed because some 184: ** implementations of nlist() returns 0 although it didn't find all 185: ** variables. 186: */ 187: if (code == 0) 188: { 189: #if defined(__convex__) || defined(NeXT) 190: for (i = 0; nl[i].n_un.n_name && nl[i].n_un.n_name[0]; i++) 191: #else 192: for (i = 0; nl[i].n_name && nl[i].n_name[0]; i++) 193: #endif 194: #if defined(_AUX_SOURCE) || defined(_CRAY) || defined(sco) || defined(_SEQUENT_) 195: /* A/UX sets n_type to 0 if not compiled with -g. n_value will still 196: ** contain the (correct?) value (unless symbol unknown). 197: */ 198: if( nl[i].n_value == 0) 199: code++; 200: #else 201: if (nl[i].n_type == 0) 202: code++; 203: #endif 204: } 205: 206: return code; 207: } 208: 209: 210: /* 211: ** Get a piece of the kernel memory 212: */ 213: static int readbuf(fd, addr, buf, len) 214: int fd; 215: long addr; 216: char *buf; 217: int len; 218: { 219: #ifdef IRIX 220: addr = K0_TO_PHYS(addr); 221: #endif 222: errno = 0; 223: #if defined(__alpha) 224: /* 225: * Let us be paranoid about return values. 226: * It should be like this on all implementations, 227: * but some may have broken lseek or read returns. 228: */ 229: if (lseek(fd, addr, 0) != addr || errno != 0) return -1; 230: if (read(fd, buf, len) != len || errno != 0) return -1; 231: return len; 232: #else 233: if (lseek(fd, addr, 0) == -1 && errno != 0) return -1; 234: return read(fd, buf, len); 235: #endif 236: } 237: 238: int kvm_read(kd, addr, buf, len) 239: kvm_t *kd; 240: long addr; 241: char *buf; 242: int len; 243: { 244: return readbuf(kd->fd, addr, buf, len); 245: } 246: 247: 248: #ifdef BSD43 249: 250: struct user *kvm_getu(kd, procp) 251: kvm_t *kd; 252: struct proc *procp; 253: { 254: static union 255: { 256: struct user user; 257: char upages[UPAGES][NBPG]; 258: } userb; 259: 260: int ncl; 261: struct pte *pteaddr, apte; 262: struct pte arguutl[UPAGES+CLSIZE]; 263: 264: 265: if ((procp->p_flag & SLOAD) == 0) 266: { 267: if(readbuf(kd->swap_fd, 268: dtob(procp->p_swaddr), 269: &userb.user, sizeof(struct user)) < 0) 270: return NULL; 271: } 272: else 273: { 274: /* 275: ** Sigh. I just *love* hard coded variable names in macros... 276: */ 277: { 278: struct pte *usrpt = kd->usrpt; 279: 280: pteaddr = &kd->Usrptma[btokmx(procp->p_p0br) + procp->p_szpt - 1]; 281: if (readbuf(kd->fd, pteaddr, &apte, sizeof(apte)) < 0) 282: return NULL; 283: } 284: 285: if (readbuf(kd->mem_fd, 286: ctob(apte.pg_pfnum+1)-(UPAGES+CLSIZE)*sizeof(struct pte), 287: arguutl, sizeof(arguutl)) < 0) 288: return NULL; 289: 290: ncl = (sizeof(struct user) + NBPG*CLSIZE - 1) / (NBPG*CLSIZE); 291: while (--ncl >= 0) 292: { 293: int i; 294: 295: 296: i = ncl * CLSIZE; 297: if(readbuf(kd->mem_fd, 298: ctob(arguutl[CLSIZE+i].pg_pfnum), 299: userb.upages[i], CLSIZE*NBPG) < 0) 300: return NULL; 301: } 302: } 303: 304: return &userb.user; 305: } 306: 307: 308: 309: struct proc *kvm_nextproc(kd) 310: kvm_t *kd; 311: { 312: if (kd->proctab == NULL) 313: if (kvm_setproc(kd) < 0) 314: return NULL; 315: 316: if (kd->procidx < kd->nproc) 317: return &kd->proctab[kd->procidx++]; 318: 319: return (struct proc *) NULL; 320: } 321: 322: int kvm_setproc(kd) 323: kvm_t *kd; 324: { 325: long procaddr; 326: 327: static struct nlist nl[] = 328: { 329: #define N_PROC 0 330: #define N_USRPTMA 1 331: #define N_NPROC 2 332: #define N_USRPT 3 333: 334: { "_proc" }, 335: { "_Usrptmap" }, 336: { "_nproc" }, 337: { "_usrpt" }, 338: { "" } 339: }; 340: 341: if (kvm_nlist(kd, nl) != 0) 342: return -1; 343: 344: kd->Usrptma = (struct pte *) nl[N_USRPTMA].n_value; 345: kd->usrpt = (struct pte *) nl[N_USRPT].n_value; 346: 347: if (readbuf(kd->fd, nl[N_NPROC].n_value, &kd->nproc, sizeof(kd->nproc)) < 0) 348: return -1; 349: 350: if (readbuf(kd->fd, nl[N_PROC].n_value, &procaddr, sizeof(procaddr)) < 0) 351: return -1; 352: 353: if (kd->proctab) 354: free(kd->proctab); 355: 356: kd->proctab = (struct proc *) calloc(kd->nproc, sizeof(struct proc)); 357: if (!kd->proctab) 358: return -1; 359: 360: if (readbuf(kd->fd, 361: procaddr, 362: kd->proctab, 363: kd->nproc*sizeof(struct proc)) < 0) 364: return -1; 365: 366: kd->procidx = 0; 367: 368: return 0; 369: } 370: 371: 372: struct proc *kvm_getproc(kd, pid) 373: kvm_t *kd; 374: int pid; 375: { 376: struct proc *procp; 377: 378: 379: if (kvm_setproc(kd) < 0) 380: return NULL; 381: 382: while ((procp = kvm_nextproc(kd)) && procp->p_pid != pid) 383: ; 384: 385: return procp; 386: } 387: 388: #endif 389: 390: #else 391: /* Just to make some compilers shut up! */ 392: int kvm_dummy() 393: { 394: return 1; 395: } 396: #endif 397: #endif