1 /* $NetBSD: main.c,v 1.9 2003/05/04 15:09:46 atatat Exp $ */ 2 3 /* 4 * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Brown. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 #ifndef lint 41 __RCSID("$NetBSD: main.c,v 1.9 2003/05/04 15:09:46 atatat Exp $"); 42 #endif 43 44 #include <sys/param.h> 45 46 #ifndef __NetBSD_Version__ 47 #error go away, you fool 48 #elif (__NetBSD_Version__ < 105000000) 49 #error only works with uvm 50 #endif 51 52 #include <fcntl.h> 53 #include <errno.h> 54 #include <unistd.h> 55 #include <limits.h> 56 #include <string.h> 57 58 /* 59 * define LOCKDEBUG here so that we get the LOCKDEBUG sized version of 60 * struct kbit from pmap.h 61 */ 62 #define LOCKDEBUG 63 64 #include "pmap.h" 65 #include "main.h" 66 67 /* 68 * strange gyrations to get the prototype for the regular version of 69 * the vm printing functions 70 */ 71 #undef VERSION 72 #define VERSION regular 73 #include "pmap.h" 74 #undef VERSION 75 #define VERSION lockdebug 76 77 struct cache_head lcache; 78 struct nchashhead *nchashtbl; 79 void *uvm_vnodeops, *uvm_deviceops, *aobj_pager, *ubc_pager; 80 void *kernel_floor; 81 struct vm_map *kmem_map, *mb_map, *phys_map, *exec_map, *pager_map; 82 struct vm_map *st_map, *pt_map, *lkm_map; 83 u_long nchash_addr, nchashtbl_addr, kernel_map_addr; 84 int debug, verbose, recurse, page_size; 85 int print_all, print_map, print_maps, print_solaris, print_ddb; 86 rlim_t maxssiz; 87 88 void (*process_map)(kvm_t *, struct kinfo_proc2 *, 89 struct kbit *, const char *); 90 void (*dump_vm_map)(kvm_t *, struct kinfo_proc2 *, 91 struct kbit *, struct kbit *, const char *); 92 size_t (*dump_vm_map_entry)(kvm_t *, struct kinfo_proc2 *, 93 struct kbit *, struct kbit *, int); 94 void (*dump_amap)(kvm_t *, struct kbit *); 95 96 struct nlist ksyms[] = { 97 { "_maxsmap" }, 98 #define NL_MAXSSIZ 0 99 { "_uvm_vnodeops" }, 100 #define NL_UVM_VNODEOPS 1 101 { "_uvm_deviceops" }, 102 #define NL_UVM_DEVICEOPS 2 103 { "_aobj_pager" }, 104 #define NL_AOBJ_PAGER 3 105 { "_ubc_pager" }, 106 #define NL_UBC_PAGER 4 107 { "_kernel_map" }, 108 #define NL_KERNEL_MAP 5 109 { "_nchashtbl" }, 110 #define NL_NCHASHTBL 6 111 { "_nchash" }, 112 #define NL_NCHASH 7 113 { "_kernel_text" }, 114 #define NL_KENTER 8 115 { NULL } 116 }; 117 118 struct nlist kmaps[] = { 119 { "_kmem_map" }, 120 #define NL_kmem_map 0 121 { "_mb_map" }, 122 #define NL_mb_map 1 123 { "_phys_map" }, 124 #define NL_phys_map 2 125 { "_exec_map" }, 126 #define NL_exec_map 3 127 { "_pager_map" }, 128 #define NL_pager_map 4 129 { "_st_map" }, 130 #define NL_st_map 5 131 { "_pt_map" }, 132 #define NL_pt_map 6 133 { "_lkm_map" }, 134 #define NL_lkm_map 7 135 { NULL } 136 }; 137 138 #define VMSPACE_ADDRESS 1 139 #define VM_MAP_ADDRESS 2 140 #define VM_MAP_ENTRY_ADDRESS 3 141 #define AMAP_ADDRESS 4 142 143 void check_fd(int); 144 int not_using_lockdebug(kvm_t *); 145 void load_symbols(kvm_t *); 146 void cache_enter(int, struct namecache *); 147 148 int 149 main(int argc, char *argv[]) 150 { 151 kvm_t *kd; 152 pid_t pid; 153 int which, many, ch, rc; 154 char errbuf[_POSIX2_LINE_MAX + 1]; 155 struct kinfo_proc2 *kproc; 156 char *kmem, *kernel, *t; 157 gid_t egid; 158 struct kbit kbit, *vmspace; 159 u_long address; 160 161 egid = getegid(); 162 if (setegid(getgid()) == -1) 163 err(1, "failed to reset privileges"); 164 165 check_fd(STDIN_FILENO); 166 check_fd(STDOUT_FILENO); 167 check_fd(STDERR_FILENO); 168 169 pid = -1; 170 which = verbose = debug = 0; 171 print_all = print_map = print_maps = print_solaris = print_ddb = 0; 172 recurse = 0; 173 kmem = kernel = NULL; 174 address = 0; 175 vmspace = &kbit; 176 177 while ((ch = getopt(argc, argv, "A:aD:dE:lM:mN:Pp:RrS:sV:vx")) != -1) { 178 switch (ch) { 179 case 'A': 180 case 'E': 181 case 'S': 182 case 'V': 183 if (which != 0) 184 errx(1, "use only one of -A, -E, -S, or -V"); 185 errno = 0; 186 address = strtoul(optarg, &t, 0); 187 if (*t != '\0') 188 errx(1, "%s is not a valid address", optarg); 189 if (errno != 0) 190 err(1, "%s is not a valid address", optarg); 191 switch (ch) { 192 case 'A': which = AMAP_ADDRESS; break; 193 case 'E': which = VM_MAP_ENTRY_ADDRESS; break; 194 case 'S': which = VMSPACE_ADDRESS; break; 195 case 'V': which = VM_MAP_ADDRESS; break; 196 } 197 break; 198 case 'a': 199 print_all = 1; 200 break; 201 case 'd': 202 print_ddb = 1; 203 break; 204 case 'D': 205 errno = 0; 206 debug = strtoul(optarg, &t, 0); 207 if (*t != '\0') 208 errx(1, "%s is not a valid number", optarg); 209 if (errno != 0) 210 err(1, "%s is not a valid number", optarg); 211 break; 212 case 'l': 213 print_maps = 1; 214 break; 215 case 'm': 216 print_map = 1; 217 break; 218 case 'M': 219 kmem = optarg; 220 break; 221 case 'N': 222 kernel = optarg; 223 break; 224 case 'p': 225 errno = 0; 226 pid = strtol(optarg, &t, 0); 227 if (pid < 0) 228 errno = EINVAL; 229 if (*t != '\0') 230 errx(1, "%s is not a valid pid", optarg); 231 if (errno != 0) 232 err(1, "%s is not a valid pid", optarg); 233 break; 234 case 'P': 235 pid = getpid(); 236 break; 237 case 'R': 238 recurse = 1; 239 break; 240 case 's': 241 print_solaris = 1; 242 break; 243 case 'v': 244 verbose++; 245 break; 246 case 'r': 247 case 'x': 248 errx(1, "-%c option not implemented, sorry", optopt); 249 /*NOTREACHED*/ 250 case '?': 251 default: 252 fprintf(stderr, "usage: %s [-adlmPRsv] [-A address] " 253 "[-D number] [-E address] [-M core]\n" 254 "\t[-N system] [-p pid] [-S address] " 255 "[-V address] [pid ...]\n", 256 getprogname()); 257 exit(1); 258 } 259 } 260 argc -= optind; 261 argv += optind; 262 263 /* more than one "process" to dump? */ 264 many = (argc > 1 - (pid == -1 ? 0 : 1)) ? 1 : 0; 265 266 /* apply default */ 267 if (print_all + print_map + print_maps + print_solaris + 268 print_ddb == 0) 269 print_solaris = 1; 270 271 /* get privs back if it appears to be safe, otherwise toss them */ 272 if (kernel == NULL && kmem == NULL && address == 0) 273 rc = setegid(egid); 274 else 275 rc = setgid(getgid()); 276 if (rc == -1) 277 err(1, "failed to reset privileges"); 278 279 /* start by opening libkvm */ 280 kd = kvm_openfiles(kernel, kmem, NULL, O_RDONLY, errbuf); 281 282 /* we're completely done with privileges now */ 283 rc = setgid(getgid()); 284 if (rc == -1) 285 err(1, "failed to reset privileges"); 286 287 /* print the kvm_open error, if any */ 288 errbuf[_POSIX2_LINE_MAX] = '\0'; 289 if (kd == NULL) 290 errx(1, "%s", errbuf); 291 292 /* get "bootstrap" addresses from kernel */ 293 load_symbols(kd); 294 295 if (not_using_lockdebug(kd)) { 296 process_map = PMAPFUNC(process_map,regular); 297 dump_vm_map = PMAPFUNC(dump_vm_map,regular); 298 dump_vm_map_entry = PMAPFUNC(dump_vm_map_entry,regular); 299 dump_amap = PMAPFUNC(dump_amap,regular); 300 } 301 else { 302 process_map = PMAPFUNC(process_map,lockdebug); 303 dump_vm_map = PMAPFUNC(dump_vm_map,lockdebug); 304 dump_vm_map_entry = PMAPFUNC(dump_vm_map_entry,lockdebug); 305 dump_amap = PMAPFUNC(dump_amap,lockdebug); 306 } 307 308 if (address) { 309 struct kbit kbit2, *at = &kbit2; 310 311 memset(vmspace, 0, sizeof(*vmspace)); 312 A(at) = address; 313 S(at) = -1; 314 315 switch (which) { 316 case VMSPACE_ADDRESS: 317 /* (kd, kproc, vmspace, thing) */ 318 (*process_map)(kd, NULL, at, "vm_map"); 319 break; 320 case VM_MAP_ADDRESS: 321 /* (kd, proc, vmspace, vm_map, thing) */ 322 (*dump_vm_map)(kd, NULL, vmspace, at, "vm_map"); 323 break; 324 case VM_MAP_ENTRY_ADDRESS: 325 /* (kd, proc, vmspace, vm_map_entry, 0) */ 326 (*dump_vm_map_entry)(kd, NULL, vmspace, at, 0); 327 break; 328 case AMAP_ADDRESS: 329 /* (kd, amap) */ 330 (*dump_amap)(kd, at); 331 break; 332 } 333 exit(0); 334 } 335 336 do { 337 if (pid == -1) { 338 if (argc == 0) 339 pid = getppid(); 340 else { 341 errno = 0; 342 pid = strtol(argv[0], &t, 0); 343 if (pid < 0) 344 errno = EINVAL; 345 if (*t != '\0') 346 errx(1, "%s is not a valid pid", 347 argv[0]); 348 if (errno != 0) 349 err(1, "%s is not a valid pid", 350 argv[0]); 351 argv++; 352 argc--; 353 } 354 } 355 356 /* find the process id */ 357 if (pid == 0) 358 kproc = NULL; 359 else { 360 kproc = kvm_getproc2(kd, KERN_PROC_PID, pid, 361 sizeof(struct kinfo_proc2), &rc); 362 if (kproc == NULL || rc == 0) { 363 errno = ESRCH; 364 warn("%d", pid); 365 pid = -1; 366 continue; 367 } 368 } 369 370 /* dump it */ 371 if (many) { 372 if (kproc) 373 printf("process %d:\n", kproc->p_pid); 374 else 375 printf("kernel:\n"); 376 } 377 378 (*process_map)(kd, kproc, vmspace, NULL); 379 pid = -1; 380 } while (argc > 0); 381 382 /* done. go away. */ 383 rc = kvm_close(kd); 384 if (rc == -1) 385 err(1, "kvm_close"); 386 387 return (0); 388 } 389 390 void 391 check_fd(int fd) 392 { 393 struct stat st; 394 int n; 395 396 if (fstat(fd, &st) == -1) { 397 (void)close(fd); 398 n = open("/dev/null", O_RDWR); 399 if (n == fd || n == -1) 400 /* we're either done or we can do no more */ 401 return; 402 /* if either of these fail, there's not much we can do */ 403 (void)dup2(n, fd); 404 (void)close(n); 405 /* XXX should we exit if it fails? */ 406 } 407 } 408 409 int 410 not_using_lockdebug(kvm_t *kd) 411 { 412 struct kbit kbit[3]; 413 struct kbit *vm_map, *header, *vm_map_entry; 414 415 vm_map = &kbit[0]; 416 header = &kbit[1]; 417 vm_map_entry = &kbit[2]; 418 419 A(vm_map) = kernel_map_addr; 420 S(vm_map) = sizeof(struct vm_map); 421 KDEREF(kd, vm_map); 422 423 A(header) = A(vm_map) + offsetof(struct vm_map, header); 424 S(header) = sizeof(struct vm_map_entry); 425 memcpy(D(header, vm_map_entry), &D(vm_map, vm_map)->header, S(header)); 426 427 /* 428 * the kernel *always* has map entries, but we might see a 429 * zero if we're using a lockdebug kernel and haven't noticed 430 * yet. 431 */ 432 if (D(vm_map, vm_map)->nentries == 0) { 433 434 /* no entries -> all pointers must point to the header */ 435 if (P(header) == D(header, vm_map_entry)->next && 436 P(header) == D(header, vm_map_entry)->prev && 437 P(header) == D(vm_map, vm_map)->hint && 438 P(header) == D(vm_map, vm_map)->first_free) 439 return (0); 440 } 441 else { 442 443 P(vm_map_entry) = D(header, vm_map_entry)->next; 444 S(vm_map_entry) = sizeof(struct vm_map_entry); 445 KDEREF(kd, vm_map_entry); 446 447 /* we have entries, so there must be referential integrity */ 448 if (D(vm_map_entry, vm_map_entry)->prev == P(header) && 449 D(header, vm_map_entry)->start <= 450 D(vm_map_entry, vm_map_entry)->start && 451 D(vm_map_entry, vm_map_entry)->end <= 452 D(header, vm_map_entry)->end) 453 return (0); 454 } 455 456 return (1); 457 } 458 459 void 460 load_symbols(kvm_t *kd) 461 { 462 int rc, i, mib[2]; 463 size_t sz; 464 465 rc = kvm_nlist(kd, &ksyms[0]); 466 if (rc != 0) { 467 for (i = 0; ksyms[i].n_name != NULL; i++) 468 if (ksyms[i].n_value == 0) 469 warnx("symbol %s: not found", ksyms[i].n_name); 470 exit(1); 471 } 472 473 uvm_vnodeops = (void*)ksyms[NL_UVM_VNODEOPS].n_value; 474 uvm_deviceops = (void*)ksyms[NL_UVM_DEVICEOPS].n_value; 475 aobj_pager = (void*)ksyms[NL_AOBJ_PAGER].n_value; 476 ubc_pager = (void*)ksyms[NL_UBC_PAGER].n_value; 477 478 kernel_floor = (void*)ksyms[NL_KENTER].n_value; 479 nchash_addr = ksyms[NL_NCHASH].n_value; 480 481 _KDEREF(kd, ksyms[NL_MAXSSIZ].n_value, &maxssiz, 482 sizeof(maxssiz)); 483 _KDEREF(kd, ksyms[NL_NCHASHTBL].n_value, &nchashtbl_addr, 484 sizeof(nchashtbl_addr)); 485 _KDEREF(kd, ksyms[NL_KERNEL_MAP].n_value, &kernel_map_addr, 486 sizeof(kernel_map_addr)); 487 488 /* 489 * Some of these may be missing from some platforms, for 490 * example sparc, sh3, and most powerpc platforms don't 491 * have a "phys_map", etc. 492 */ 493 (void)kvm_nlist(kd, &kmaps[0]); 494 495 #define get_map_address(m) \ 496 if (kmaps[CONCAT(NL_,m)].n_value != 0) \ 497 _KDEREF(kd, kmaps[CONCAT(NL_,m)].n_value, &m, sizeof(m)) 498 499 get_map_address(kmem_map); 500 get_map_address(mb_map); 501 get_map_address(phys_map); 502 get_map_address(exec_map); 503 get_map_address(pager_map); 504 get_map_address(st_map); 505 get_map_address(pt_map); 506 get_map_address(lkm_map); 507 508 mib[0] = CTL_HW; 509 mib[1] = HW_PAGESIZE; 510 sz = sizeof(page_size); 511 if (sysctl(&mib[0], 2, &page_size, &sz, NULL, 0) == -1) 512 err(1, "sysctl: hw.pagesize"); 513 } 514 515 const char * 516 mapname(void *addr) 517 { 518 519 if (addr == (void*)kernel_map_addr) 520 return ("kernel_map"); 521 else if (addr == kmem_map) 522 return ("kmem_map"); 523 else if (addr == mb_map) 524 return ("mb_map"); 525 else if (addr == phys_map) 526 return ("phys_map"); 527 else if (addr == exec_map) 528 return ("exec_map"); 529 else if (addr == pager_map) 530 return ("pager_map"); 531 else if (addr == st_map) 532 return ("st_map"); 533 else if (addr == pt_map) 534 return ("pt_map"); 535 else if (addr == lkm_map) 536 return ("lkm_map"); 537 else 538 return (NULL); 539 } 540 541 void 542 load_name_cache(kvm_t *kd) 543 { 544 struct namecache _ncp, *ncp, *oncp; 545 struct nchashhead _ncpp, *ncpp; 546 u_long nchash; 547 int i; 548 549 LIST_INIT(&lcache); 550 551 _KDEREF(kd, nchash_addr, &nchash, sizeof(nchash)); 552 nchashtbl = malloc(sizeof(nchashtbl) * (int)nchash); 553 _KDEREF(kd, nchashtbl_addr, nchashtbl, 554 sizeof(nchashtbl) * (int)nchash); 555 556 ncpp = &_ncpp; 557 558 for (i = 0; i <= nchash; i++) { 559 ncpp = &nchashtbl[i]; 560 oncp = NULL; 561 LIST_FOREACH(ncp, ncpp, nc_hash) { 562 if (ncp == oncp || 563 (void*)ncp < kernel_floor || 564 ncp == (void*)0xdeadbeef) 565 break; 566 oncp = ncp; 567 _KDEREF(kd, (u_long)ncp, &_ncp, sizeof(*ncp)); 568 ncp = &_ncp; 569 if ((void*)ncp->nc_vp > kernel_floor && 570 ncp->nc_nlen > 0) { 571 if (ncp->nc_nlen > 2 || 572 ncp->nc_name[0] != '.' || 573 (ncp->nc_name[1] != '.' && 574 ncp->nc_nlen != 1)) 575 cache_enter(i, ncp); 576 } 577 } 578 } 579 } 580 581 void 582 cache_enter(int i, struct namecache *ncp) 583 { 584 struct cache_entry *ce; 585 586 if (debug & DUMP_NAMEI_CACHE) 587 printf("[%d] ncp->nc_vp %10p, ncp->nc_dvp %10p, " 588 "ncp->nc_nlen %3d [%.*s] (nc_dvpid=%lu, nc_vpid=%lu)\n", 589 i, ncp->nc_vp, ncp->nc_dvp, 590 ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name, 591 ncp->nc_dvpid, ncp->nc_vpid); 592 593 ce = malloc(sizeof(struct cache_entry)); 594 595 ce->ce_vp = ncp->nc_vp; 596 ce->ce_pvp = ncp->nc_dvp; 597 ce->ce_cid = ncp->nc_vpid; 598 ce->ce_pcid = ncp->nc_dvpid; 599 ce->ce_nlen = ncp->nc_nlen; 600 strncpy(ce->ce_name, ncp->nc_name, sizeof(ce->ce_name)); 601 ce->ce_name[MIN(ce->ce_nlen, sizeof(ce->ce_name) - 1)] = '\0'; 602 603 LIST_INSERT_HEAD(&lcache, ce, ce_next); 604 } 605