1 /* $NetBSD: main.c,v 1.16 2004/01/31 20:53:55 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.16 2004/01/31 20:53:55 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, *buf_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 { "_buf_map" }, 136 #define NL_buf_map 8 137 { NULL } 138 }; 139 140 #define VMSPACE_ADDRESS 1 141 #define VM_MAP_ADDRESS 2 142 #define VM_MAP_ENTRY_ADDRESS 3 143 #define AMAP_ADDRESS 4 144 145 void check_fd(int); 146 int not_using_lockdebug(kvm_t *); 147 void load_symbols(kvm_t *); 148 void cache_enter(int, struct namecache *); 149 150 int 151 main(int argc, char *argv[]) 152 { 153 kvm_t *kd; 154 pid_t pid; 155 int which, many, ch, rc; 156 char errbuf[_POSIX2_LINE_MAX + 1]; 157 struct kinfo_proc2 *kproc; 158 char *kmem, *kernel, *t; 159 gid_t egid; 160 struct kbit kbit, *vmspace; 161 u_long address; 162 163 egid = getegid(); 164 if (setegid(getgid()) == -1) 165 err(1, "failed to reset privileges"); 166 167 check_fd(STDIN_FILENO); 168 check_fd(STDOUT_FILENO); 169 check_fd(STDERR_FILENO); 170 171 pid = -1; 172 which = verbose = debug = 0; 173 print_all = print_map = print_maps = print_solaris = print_ddb = 0; 174 recurse = 0; 175 kmem = kernel = NULL; 176 address = 0; 177 vmspace = &kbit; 178 179 while ((ch = getopt(argc, argv, "A:aD:dE:lM:mN:Pp:RrS:sV:vx")) != -1) { 180 switch (ch) { 181 case 'A': 182 case 'E': 183 case 'S': 184 case 'V': 185 if (which != 0) 186 errx(1, "use only one of -A, -E, -S, or -V"); 187 errno = 0; 188 address = strtoul(optarg, &t, 0); 189 if (*t != '\0') 190 errx(1, "%s is not a valid address", optarg); 191 if (errno != 0) 192 err(1, "%s is not a valid address", optarg); 193 switch (ch) { 194 case 'A': which = AMAP_ADDRESS; break; 195 case 'E': which = VM_MAP_ENTRY_ADDRESS; break; 196 case 'S': which = VMSPACE_ADDRESS; break; 197 case 'V': which = VM_MAP_ADDRESS; break; 198 } 199 break; 200 case 'a': 201 print_all = 1; 202 break; 203 case 'd': 204 print_ddb = 1; 205 break; 206 case 'D': 207 errno = 0; 208 debug = strtoul(optarg, &t, 0); 209 if (*t != '\0') 210 errx(1, "%s is not a valid number", optarg); 211 if (errno != 0) 212 err(1, "%s is not a valid number", optarg); 213 break; 214 case 'l': 215 print_maps = 1; 216 break; 217 case 'm': 218 print_map = 1; 219 break; 220 case 'M': 221 kmem = optarg; 222 break; 223 case 'N': 224 kernel = optarg; 225 break; 226 case 'p': 227 errno = 0; 228 pid = strtol(optarg, &t, 0); 229 if (pid < 0) 230 errno = EINVAL; 231 if (*t != '\0') 232 errx(1, "%s is not a valid pid", optarg); 233 if (errno != 0) 234 err(1, "%s is not a valid pid", optarg); 235 break; 236 case 'P': 237 pid = getpid(); 238 break; 239 case 'R': 240 recurse = 1; 241 break; 242 case 's': 243 print_solaris = 1; 244 break; 245 case 'v': 246 verbose++; 247 break; 248 case 'r': 249 case 'x': 250 errx(1, "-%c option not implemented, sorry", optopt); 251 /*NOTREACHED*/ 252 case '?': 253 default: 254 fprintf(stderr, "usage: %s [-adlmPRsv] [-A address] " 255 "[-D number] [-E address] [-M core]\n" 256 "\t[-N system] [-p pid] [-S address] " 257 "[-V address] [pid ...]\n", 258 getprogname()); 259 exit(1); 260 } 261 } 262 argc -= optind; 263 argv += optind; 264 265 /* more than one "process" to dump? */ 266 many = (argc > 1 - (pid == -1 ? 0 : 1)) ? 1 : 0; 267 268 /* apply default */ 269 if (print_all + print_map + print_maps + print_solaris + 270 print_ddb == 0) 271 print_solaris = 1; 272 273 /* get privs back if it appears to be safe, otherwise toss them */ 274 if (kernel == NULL && kmem == NULL && address == 0) 275 rc = setegid(egid); 276 else 277 rc = setgid(getgid()); 278 if (rc == -1) 279 err(1, "failed to reset privileges"); 280 281 /* start by opening libkvm */ 282 kd = kvm_openfiles(kernel, kmem, NULL, O_RDONLY, errbuf); 283 284 /* we're completely done with privileges now */ 285 rc = setgid(getgid()); 286 if (rc == -1) 287 err(1, "failed to reset privileges"); 288 289 /* print the kvm_open error, if any */ 290 errbuf[_POSIX2_LINE_MAX] = '\0'; 291 if (kd == NULL) 292 errx(1, "%s", errbuf); 293 294 /* get "bootstrap" addresses from kernel */ 295 load_symbols(kd); 296 297 if (not_using_lockdebug(kd)) { 298 process_map = PMAPFUNC(process_map,regular); 299 dump_vm_map = PMAPFUNC(dump_vm_map,regular); 300 dump_vm_map_entry = PMAPFUNC(dump_vm_map_entry,regular); 301 dump_amap = PMAPFUNC(dump_amap,regular); 302 } 303 else { 304 process_map = PMAPFUNC(process_map,lockdebug); 305 dump_vm_map = PMAPFUNC(dump_vm_map,lockdebug); 306 dump_vm_map_entry = PMAPFUNC(dump_vm_map_entry,lockdebug); 307 dump_amap = PMAPFUNC(dump_amap,lockdebug); 308 } 309 310 if (address) { 311 struct kbit kbit2, *at = &kbit2; 312 313 memset(vmspace, 0, sizeof(*vmspace)); 314 A(at) = address; 315 S(at) = (size_t)-1; 316 317 switch (which) { 318 case VMSPACE_ADDRESS: 319 /* (kd, kproc, vmspace, thing) */ 320 (*process_map)(kd, NULL, at, "vm_map"); 321 break; 322 case VM_MAP_ADDRESS: 323 /* (kd, proc, vmspace, vm_map, thing) */ 324 (*dump_vm_map)(kd, NULL, vmspace, at, "vm_map"); 325 break; 326 case VM_MAP_ENTRY_ADDRESS: 327 /* (kd, proc, vmspace, vm_map_entry, 0) */ 328 (*dump_vm_map_entry)(kd, NULL, vmspace, at, 0); 329 break; 330 case AMAP_ADDRESS: 331 /* (kd, amap) */ 332 (*dump_amap)(kd, at); 333 break; 334 } 335 exit(0); 336 } 337 338 do { 339 if (pid == -1) { 340 if (argc == 0) 341 pid = getppid(); 342 else { 343 errno = 0; 344 pid = strtol(argv[0], &t, 0); 345 if (pid < 0) 346 errno = EINVAL; 347 if (*t != '\0') 348 errx(1, "%s is not a valid pid", 349 argv[0]); 350 if (errno != 0) 351 err(1, "%s is not a valid pid", 352 argv[0]); 353 argv++; 354 argc--; 355 } 356 } 357 358 /* find the process id */ 359 if (pid == 0) 360 kproc = NULL; 361 else { 362 kproc = kvm_getproc2(kd, KERN_PROC_PID, pid, 363 sizeof(struct kinfo_proc2), &rc); 364 if (kproc == NULL || rc == 0) { 365 errno = ESRCH; 366 warn("%d", pid); 367 pid = -1; 368 continue; 369 } 370 } 371 372 /* dump it */ 373 if (many) { 374 if (kproc) 375 printf("process %d:\n", kproc->p_pid); 376 else 377 printf("kernel:\n"); 378 } 379 380 (*process_map)(kd, kproc, vmspace, NULL); 381 pid = -1; 382 } while (argc > 0); 383 384 /* done. go away. */ 385 rc = kvm_close(kd); 386 if (rc == -1) 387 err(1, "kvm_close"); 388 389 return (0); 390 } 391 392 void 393 check_fd(int fd) 394 { 395 struct stat st; 396 int n; 397 398 if (fstat(fd, &st) == -1) { 399 (void)close(fd); 400 n = open("/dev/null", O_RDWR); 401 if (n == fd || n == -1) 402 /* we're either done or we can do no more */ 403 return; 404 /* if either of these fail, there's not much we can do */ 405 (void)dup2(n, fd); 406 (void)close(n); 407 /* XXX should we exit if it fails? */ 408 } 409 } 410 411 int 412 not_using_lockdebug(kvm_t *kd) 413 { 414 struct kbit kbit[3]; 415 struct kbit *vm_map, *header, *vm_map_entry; 416 417 vm_map = &kbit[0]; 418 header = &kbit[1]; 419 vm_map_entry = &kbit[2]; 420 421 A(vm_map) = kernel_map_addr; 422 S(vm_map) = sizeof(struct vm_map); 423 KDEREF(kd, vm_map); 424 425 A(header) = A(vm_map) + offsetof(struct vm_map, header); 426 S(header) = sizeof(struct vm_map_entry); 427 memcpy(D(header, vm_map_entry), &D(vm_map, vm_map)->header, S(header)); 428 429 /* 430 * the kernel *always* has map entries, but we might see a 431 * zero if we're using a lockdebug kernel and haven't noticed 432 * yet. 433 */ 434 if (D(vm_map, vm_map)->nentries == 0) { 435 436 /* no entries -> all pointers must point to the header */ 437 if (P(header) == D(header, vm_map_entry)->next && 438 P(header) == D(header, vm_map_entry)->prev && 439 P(header) == D(vm_map, vm_map)->hint && 440 P(header) == D(vm_map, vm_map)->first_free) 441 return (0); 442 } 443 else { 444 445 P(vm_map_entry) = D(header, vm_map_entry)->next; 446 S(vm_map_entry) = sizeof(struct vm_map_entry); 447 if (!KDEREFOK(kd, vm_map_entry)) 448 return (1); 449 450 /* we have entries, so there must be referential integrity */ 451 if (D(vm_map_entry, vm_map_entry)->prev == P(header) && 452 vm_map_min(D(vm_map, vm_map)) <= 453 D(vm_map_entry, vm_map_entry)->start && 454 D(vm_map_entry, vm_map_entry)->end <= 455 vm_map_max(D(vm_map, vm_map))) 456 return (0); 457 } 458 459 return (1); 460 } 461 462 void 463 load_symbols(kvm_t *kd) 464 { 465 int rc, i, mib[2]; 466 size_t sz; 467 468 rc = kvm_nlist(kd, &ksyms[0]); 469 if (rc != 0) { 470 for (i = 0; ksyms[i].n_name != NULL; i++) 471 if (ksyms[i].n_value == 0) 472 warnx("symbol %s: not found", ksyms[i].n_name); 473 exit(1); 474 } 475 476 uvm_vnodeops = (void*)ksyms[NL_UVM_VNODEOPS].n_value; 477 uvm_deviceops = (void*)ksyms[NL_UVM_DEVICEOPS].n_value; 478 aobj_pager = (void*)ksyms[NL_AOBJ_PAGER].n_value; 479 ubc_pager = (void*)ksyms[NL_UBC_PAGER].n_value; 480 481 kernel_floor = (void*)ksyms[NL_KENTER].n_value; 482 nchash_addr = ksyms[NL_NCHASH].n_value; 483 484 _KDEREF(kd, ksyms[NL_MAXSSIZ].n_value, &maxssiz, 485 sizeof(maxssiz)); 486 _KDEREF(kd, ksyms[NL_NCHASHTBL].n_value, &nchashtbl_addr, 487 sizeof(nchashtbl_addr)); 488 _KDEREF(kd, ksyms[NL_KERNEL_MAP].n_value, &kernel_map_addr, 489 sizeof(kernel_map_addr)); 490 491 /* 492 * Some of these may be missing from some platforms, for 493 * example sparc, sh3, and most powerpc platforms don't 494 * have a "phys_map", etc. 495 */ 496 (void)kvm_nlist(kd, &kmaps[0]); 497 498 #define get_map_address(m) do {\ 499 if (kmaps[CONCAT(NL_,m)].n_value != 0) \ 500 _KDEREF(kd, kmaps[CONCAT(NL_,m)].n_value, &m, sizeof(m)); \ 501 } while (0/*CONSTCOND*/) 502 503 get_map_address(kmem_map); 504 get_map_address(mb_map); 505 get_map_address(phys_map); 506 get_map_address(exec_map); 507 get_map_address(pager_map); 508 get_map_address(st_map); 509 get_map_address(pt_map); 510 get_map_address(lkm_map); 511 get_map_address(buf_map); 512 513 mib[0] = CTL_HW; 514 mib[1] = HW_PAGESIZE; 515 sz = sizeof(page_size); 516 if (sysctl(&mib[0], 2, &page_size, &sz, NULL, 0) == -1) 517 err(1, "sysctl: hw.pagesize"); 518 } 519 520 const char * 521 mapname(void *addr) 522 { 523 524 if (addr == (void*)kernel_map_addr) 525 return ("kernel_map"); 526 else if (addr == kmem_map) 527 return ("kmem_map"); 528 else if (addr == mb_map) 529 return ("mb_map"); 530 else if (addr == phys_map) 531 return ("phys_map"); 532 else if (addr == exec_map) 533 return ("exec_map"); 534 else if (addr == pager_map) 535 return ("pager_map"); 536 else if (addr == st_map) 537 return ("st_map"); 538 else if (addr == pt_map) 539 return ("pt_map"); 540 else if (addr == lkm_map) 541 return ("lkm_map"); 542 else if (addr == buf_map) 543 return ("buf_map"); 544 else 545 return (NULL); 546 } 547 548 void 549 load_name_cache(kvm_t *kd) 550 { 551 struct namecache _ncp, *ncp, *oncp; 552 struct nchashhead _ncpp, *ncpp; 553 u_long nchash; 554 int i; 555 556 LIST_INIT(&lcache); 557 558 _KDEREF(kd, nchash_addr, &nchash, sizeof(nchash)); 559 nchashtbl = malloc(sizeof(nchashtbl) * (int)(nchash + 1)); 560 _KDEREF(kd, nchashtbl_addr, nchashtbl, 561 sizeof(nchashtbl) * (int)(nchash + 1)); 562 563 ncpp = &_ncpp; 564 565 for (i = 0; i <= nchash; i++) { 566 ncpp = &nchashtbl[i]; 567 oncp = NULL; 568 LIST_FOREACH(ncp, ncpp, nc_hash) { 569 if (ncp == oncp || 570 (void*)ncp < kernel_floor || 571 ncp == (void*)0xdeadbeef) 572 break; 573 oncp = ncp; 574 _KDEREF(kd, (u_long)ncp, &_ncp, sizeof(*ncp)); 575 ncp = &_ncp; 576 if ((void*)ncp->nc_vp > kernel_floor && 577 ncp->nc_nlen > 0) { 578 if (ncp->nc_nlen > 2 || 579 ncp->nc_name[0] != '.' || 580 (ncp->nc_name[1] != '.' && 581 ncp->nc_nlen != 1)) 582 cache_enter(i, ncp); 583 } 584 } 585 } 586 } 587 588 void 589 cache_enter(int i, struct namecache *ncp) 590 { 591 struct cache_entry *ce; 592 593 if (debug & DUMP_NAMEI_CACHE) 594 printf("[%d] ncp->nc_vp %10p, ncp->nc_dvp %10p, " 595 "ncp->nc_nlen %3d [%.*s]\n", 596 i, ncp->nc_vp, ncp->nc_dvp, 597 ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name); 598 599 ce = malloc(sizeof(struct cache_entry)); 600 601 ce->ce_vp = ncp->nc_vp; 602 ce->ce_pvp = ncp->nc_dvp; 603 ce->ce_nlen = ncp->nc_nlen; 604 strncpy(ce->ce_name, ncp->nc_name, sizeof(ce->ce_name)); 605 ce->ce_name[MIN(ce->ce_nlen, sizeof(ce->ce_name) - 1)] = '\0'; 606 607 LIST_INSERT_HEAD(&lcache, ce, ce_next); 608 } 609