1 /* $NetBSD: pmap.c,v 1.7 2002/10/17 17:18:34 atatat Exp $ */ 2 3 /* 4 * Copyright (c) 2002 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: pmap.c,v 1.7 2002/10/17 17:18:34 atatat Exp $"); 42 #endif 43 44 #include <sys/types.h> 45 #include <sys/param.h> 46 #include <sys/time.h> 47 #include <sys/exec.h> 48 #include <sys/proc.h> 49 #include <sys/vnode.h> 50 #include <sys/mount.h> 51 #include <sys/uio.h> 52 #include <sys/namei.h> 53 #include <sys/sysctl.h> 54 55 #include <uvm/uvm.h> 56 #include <uvm/uvm_device.h> 57 58 #include <ufs/ufs/inode.h> 59 #undef doff_t 60 #undef IN_ACCESS 61 #include <isofs/cd9660/iso.h> 62 #include <isofs/cd9660/cd9660_node.h> 63 64 #include <kvm.h> 65 #include <fcntl.h> 66 #include <errno.h> 67 #include <err.h> 68 #include <stdlib.h> 69 #include <stddef.h> 70 #include <unistd.h> 71 #include <stdio.h> 72 #include <limits.h> 73 #include <string.h> 74 75 #ifndef __NetBSD_Version__ 76 #error go away, you fool 77 #elif (__NetBSD_Version__ < 105000000) 78 #error only works with uvm 79 #endif 80 81 /* 82 * stolen (and munged) from #include <uvm/uvm_object.h> 83 */ 84 #define UVM_OBJ_IS_VNODE(uobj) ((uobj)->pgops == uvm_vnodeops) 85 #define UVM_OBJ_IS_AOBJ(uobj) ((uobj)->pgops == aobj_pager) 86 #define UVM_OBJ_IS_DEVICE(uobj) ((uobj)->pgops == uvm_deviceops) 87 #define UVM_OBJ_IS_UBCPAGER(uobj) ((uobj)->pgops == ubc_pager) 88 89 #define PRINT_VMSPACE 0x00000001 90 #define PRINT_VM_MAP 0x00000002 91 #define PRINT_VM_MAP_HEADER 0x00000004 92 #define PRINT_VM_MAP_ENTRY 0x00000008 93 #define DUMP_NAMEI_CACHE 0x00000010 94 95 struct cache_entry { 96 LIST_ENTRY(cache_entry) ce_next; 97 struct vnode *ce_vp, *ce_pvp; 98 u_long ce_cid, ce_pcid; 99 int ce_nlen; 100 char ce_name[256]; 101 }; 102 103 LIST_HEAD(cache_head, cache_entry) lcache; 104 LIST_HEAD(nchashhead, namecache) *nchashtbl = NULL; 105 void *uvm_vnodeops, *uvm_deviceops, *aobj_pager, *ubc_pager; 106 void *kernel_floor; 107 struct vm_map *kmem_map, *mb_map, *phys_map, *exec_map, *pager_map; 108 u_long nchash_addr, nchashtbl_addr, kernel_map_addr; 109 int debug, verbose, recurse; 110 int print_all, print_map, print_maps, print_solaris, print_ddb; 111 int rwx = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE, heapfound; 112 rlim_t maxssiz; 113 114 struct kbit { 115 /* 116 * size of data chunk 117 */ 118 size_t k_size; 119 120 /* 121 * something for printf() and something for kvm_read() 122 */ 123 union { 124 void *k_addr_p; 125 u_long k_addr_ul; 126 } k_addr; 127 128 /* 129 * where we actually put the "stuff" 130 */ 131 union { 132 char data[1]; 133 struct vmspace vmspace; 134 struct vm_map vm_map; 135 struct vm_map_entry vm_map_entry; 136 struct vnode vnode; 137 struct uvm_object uvm_object; 138 struct mount mount; 139 struct namecache namecache; 140 struct inode inode; 141 struct iso_node iso_node; 142 struct uvm_device uvm_device; 143 } k_data; 144 }; 145 146 /* the size of the object in the kernel */ 147 #define S(x) ((x)->k_size) 148 /* the address of the object in kernel, two forms */ 149 #define A(x) ((x)->k_addr.k_addr_ul) 150 #define P(x) ((x)->k_addr.k_addr_p) 151 /* the data from the kernel */ 152 #define D(x,d) (&((x)->k_data.d)) 153 154 /* suck the data from the kernel */ 155 #define _KDEREF(kd, addr, dst, sz) do { \ 156 ssize_t len; \ 157 len = kvm_read((kd), (addr), (dst), (sz)); \ 158 if (len != (sz)) \ 159 errx(1, "trying to read %lu bytes from %lx: %s", \ 160 (unsigned long)(sz), (addr), kvm_geterr(kd)); \ 161 } while (0/*CONSTCOND*/) 162 163 /* suck the data using the structure */ 164 #define KDEREF(kd, item) _KDEREF((kd), A(item), D(item, data), S(item)) 165 166 /* when recursing, output is indented */ 167 #define indent(n) ((n) * (recurse > 1 ? recurse - 1 : 0)) 168 169 struct nlist ksyms[] = { 170 { "_maxsmap" }, 171 #define NL_MAXSSIZ 0 172 { "_uvm_vnodeops" }, 173 #define NL_UVM_VNODEOPS 1 174 { "_uvm_deviceops" }, 175 #define NL_UVM_DEVICEOPS 2 176 { "_aobj_pager" }, 177 #define NL_AOBJ_PAGER 3 178 { "_ubc_pager" }, 179 #define NL_UBC_PAGER 4 180 { "_kernel_map" }, 181 #define NL_KERNEL_MAP 5 182 { "_nchashtbl" }, 183 #define NL_NCHASHTBL 6 184 { "_nchash" }, 185 #define NL_NCHASH 7 186 { "_kernel_text" }, 187 #define NL_KENTER 8 188 { NULL } 189 }; 190 191 struct nlist kmaps[] = { 192 { "_kmem_map" }, 193 #define NL_KMEM_MAP 0 194 { "_mb_map" }, 195 #define NL_MB_MAP 1 196 { "_phys_map" }, 197 #define NL_PHYS_MAP 2 198 { "_exec_map" }, 199 #define NL_EXEC_MAP 3 200 { "_pager_map" }, 201 #define NL_PAGER_MAP 4 202 { NULL } 203 }; 204 205 void check(int); 206 void load_symbols(kvm_t *); 207 void process_map(kvm_t *, pid_t, struct kinfo_proc2 *); 208 void dump_vm_map(kvm_t *, struct kbit *, struct kbit *, char *); 209 size_t dump_vm_map_entry(kvm_t *, struct kbit *, struct kbit *, int); 210 char *findname(kvm_t *, struct kbit *, struct kbit *, struct kbit *, 211 struct kbit *, struct kbit *); 212 int search_cache(kvm_t *, struct kbit *, char **, char *, size_t); 213 void load_name_cache(kvm_t *); 214 void cache_enter(int, struct namecache *); 215 216 int 217 main(int argc, char *argv[]) 218 { 219 kvm_t *kd; 220 pid_t pid; 221 int many, ch, rc; 222 char errbuf[_POSIX2_LINE_MAX + 1]; 223 struct kinfo_proc2 *kproc; 224 char *kmem, *kernel; 225 226 check(STDIN_FILENO); 227 check(STDOUT_FILENO); 228 check(STDERR_FILENO); 229 230 pid = -1; 231 verbose = debug = 0; 232 print_all = print_map = print_maps = print_solaris = print_ddb = 0; 233 recurse = 0; 234 kmem = kernel = NULL; 235 236 while ((ch = getopt(argc, argv, "aD:dlmM:N:p:PRrsvx")) != -1) { 237 switch (ch) { 238 case 'a': 239 print_all = 1; 240 break; 241 case 'd': 242 print_ddb = 1; 243 break; 244 case 'D': 245 debug = atoi(optarg); 246 break; 247 case 'l': 248 print_maps = 1; 249 break; 250 case 'm': 251 print_map = 1; 252 break; 253 case 'M': 254 kmem = optarg; 255 break; 256 case 'N': 257 kernel = optarg; 258 break; 259 case 'p': 260 pid = atoi(optarg); 261 break; 262 case 'P': 263 pid = getpid(); 264 break; 265 case 'R': 266 recurse = 1; 267 break; 268 case 's': 269 print_solaris = 1; 270 break; 271 case 'v': 272 verbose = 1; 273 break; 274 case 'r': 275 case 'x': 276 errx(1, "-%c option not implemented, sorry", optopt); 277 /*NOTREACHED*/ 278 case '?': 279 default: 280 fprintf(stderr, "usage: %s [-adlmPsv] [-D number] " 281 "[-M core] [-N system] [-p pid] [pid ...]\n", 282 getprogname()); 283 exit(1); 284 } 285 } 286 argc -= optind; 287 argv += optind; 288 289 /* more than one "process" to dump? */ 290 many = (argc > 1 - (pid == -1 ? 0 : 1)) ? 1 : 0; 291 292 /* apply default */ 293 if (print_all + print_map + print_maps + print_solaris + 294 print_ddb == 0) 295 print_solaris = 1; 296 297 /* start by opening libkvm */ 298 kd = kvm_openfiles(kernel, kmem, NULL, O_RDONLY, errbuf); 299 errbuf[_POSIX2_LINE_MAX] = '\0'; 300 if (kd == NULL) 301 errx(1, "%s", errbuf); 302 303 /* get "bootstrap" addresses from kernel */ 304 load_symbols(kd); 305 306 do { 307 if (pid == -1) { 308 if (argc == 0) 309 pid = getppid(); 310 else { 311 pid = atoi(argv[0]); 312 argv++; 313 argc--; 314 } 315 } 316 317 /* find the process id */ 318 if (pid == 0) 319 kproc = NULL; 320 else { 321 kproc = kvm_getproc2(kd, KERN_PROC_PID, pid, 322 sizeof(struct kinfo_proc2), &rc); 323 if (kproc == NULL || rc == 0) { 324 errno = ESRCH; 325 warn("%d", pid); 326 pid = -1; 327 continue; 328 } 329 } 330 331 /* dump it */ 332 if (many) { 333 if (kproc) 334 printf("process %d:\n", kproc->p_pid); 335 else 336 printf("kernel:\n"); 337 } 338 339 process_map(kd, pid, kproc); 340 pid = -1; 341 } while (argc > 0); 342 343 /* done. go away. */ 344 rc = kvm_close(kd); 345 if (rc == -1) 346 err(1, "kvm_close"); 347 348 return (0); 349 } 350 351 void 352 check(int fd) 353 { 354 struct stat st; 355 int n; 356 357 if (fstat(fd, &st) == -1) { 358 (void)close(fd); 359 n = open("/dev/null", O_RDWR); 360 if (n == fd || n == -1) 361 /* we're either done or we can do no more */ 362 return; 363 /* if either of these fail, there's not much we can do */ 364 (void)dup2(n, fd); 365 (void)close(n); 366 /* XXX should we exit if it fails? */ 367 } 368 } 369 370 void 371 process_map(kvm_t *kd, pid_t pid, struct kinfo_proc2 *proc) 372 { 373 struct kbit kbit[2], *vmspace, *vm_map; 374 char *thing; 375 376 vmspace = &kbit[0]; 377 vm_map = &kbit[1]; 378 379 A(vmspace) = 0; 380 A(vm_map) = 0; 381 382 if (pid > 0) { 383 heapfound = 0; 384 A(vmspace) = (u_long)proc->p_vmspace; 385 S(vmspace) = sizeof(struct vmspace); 386 KDEREF(kd, vmspace); 387 thing = "proc->p_vmspace.vm_map"; 388 } else { 389 heapfound = 1; /* but really, do kernels have a heap? */ 390 A(vmspace) = 0; 391 S(vmspace) = 0; 392 thing = "kernel_map"; 393 } 394 395 if (pid > 0 && (debug & PRINT_VMSPACE)) { 396 printf("proc->p_vmspace %p = {", P(vmspace)); 397 printf(" vm_refcnt = %d,", D(vmspace, vmspace)->vm_refcnt); 398 printf(" vm_shm = %p,\n", D(vmspace, vmspace)->vm_shm); 399 printf(" vm_rssize = %d,", D(vmspace, vmspace)->vm_rssize); 400 printf(" vm_swrss = %d,", D(vmspace, vmspace)->vm_swrss); 401 printf(" vm_tsize = %d,", D(vmspace, vmspace)->vm_tsize); 402 printf(" vm_dsize = %d,\n", D(vmspace, vmspace)->vm_dsize); 403 printf(" vm_ssize = %d,", D(vmspace, vmspace)->vm_ssize); 404 printf(" vm_taddr = %p,", D(vmspace, vmspace)->vm_taddr); 405 printf(" vm_daddr = %p,\n", D(vmspace, vmspace)->vm_daddr); 406 printf(" vm_maxsaddr = %p,", 407 D(vmspace, vmspace)->vm_maxsaddr); 408 printf(" vm_minsaddr = %p }\n", 409 D(vmspace, vmspace)->vm_minsaddr); 410 } 411 412 S(vm_map) = sizeof(struct vm_map); 413 if (pid > 0) { 414 A(vm_map) = A(vmspace); 415 memcpy(D(vm_map, vm_map), &D(vmspace, vmspace)->vm_map, 416 S(vm_map)); 417 } else { 418 A(vm_map) = kernel_map_addr; 419 KDEREF(kd, vm_map); 420 } 421 422 dump_vm_map(kd, vmspace, vm_map, thing); 423 } 424 425 void 426 load_symbols(kvm_t *kd) 427 { 428 int rc, i; 429 430 rc = kvm_nlist(kd, &ksyms[0]); 431 if (rc != 0) { 432 for (i = 0; ksyms[i].n_name != NULL; i++) 433 if (ksyms[i].n_value == 0) 434 warnx("symbol %s: not found", ksyms[i].n_name); 435 exit(1); 436 } 437 438 uvm_vnodeops = (void*)ksyms[NL_UVM_VNODEOPS].n_value; 439 uvm_deviceops = (void*)ksyms[NL_UVM_DEVICEOPS].n_value; 440 aobj_pager = (void*)ksyms[NL_AOBJ_PAGER].n_value; 441 ubc_pager = (void*)ksyms[NL_UBC_PAGER].n_value; 442 443 kernel_floor = (void*)ksyms[NL_KENTER].n_value; 444 nchash_addr = ksyms[NL_NCHASH].n_value; 445 446 _KDEREF(kd, ksyms[NL_MAXSSIZ].n_value, &maxssiz, 447 sizeof(maxssiz)); 448 _KDEREF(kd, ksyms[NL_NCHASHTBL].n_value, &nchashtbl_addr, 449 sizeof(nchashtbl_addr)); 450 _KDEREF(kd, ksyms[NL_KERNEL_MAP].n_value, &kernel_map_addr, 451 sizeof(kernel_map_addr)); 452 453 /* 454 * Some of these may be missing from some platforms, for 455 * example sparc, sh3, and most powerpc platforms don't 456 * have a "phys_map". 457 */ 458 (void)kvm_nlist(kd, &kmaps[0]); 459 if (kmaps[NL_KMEM_MAP].n_value != 0) 460 _KDEREF(kd, kmaps[NL_KMEM_MAP].n_value, &kmem_map, 461 sizeof(kmem_map)); 462 if (kmaps[NL_MB_MAP].n_value != 0) 463 _KDEREF(kd, kmaps[NL_MB_MAP].n_value, &mb_map, 464 sizeof(mb_map)); 465 if (kmaps[NL_PHYS_MAP].n_value != 0) 466 _KDEREF(kd, kmaps[NL_PHYS_MAP].n_value, &phys_map, 467 sizeof(phys_map)); 468 if (kmaps[NL_EXEC_MAP].n_value != 0) 469 _KDEREF(kd, kmaps[NL_EXEC_MAP].n_value, &exec_map, 470 sizeof(exec_map)); 471 if (kmaps[NL_PAGER_MAP].n_value != 0) 472 _KDEREF(kd, kmaps[NL_PAGER_MAP].n_value, &pager_map, 473 sizeof(pager_map)); 474 } 475 476 void 477 dump_vm_map(kvm_t *kd, struct kbit *vmspace, struct kbit *vm_map, 478 char *mname) 479 { 480 struct kbit kbit[2], *header, *vm_map_entry; 481 struct vm_map_entry *last, *next; 482 size_t total; 483 u_long addr; 484 485 header = &kbit[0]; 486 vm_map_entry = &kbit[1]; 487 A(header) = 0; 488 A(vm_map_entry) = 0; 489 490 if (debug & PRINT_VM_MAP) { 491 printf("%*s%s %p = {", indent(2), "", mname, P(vm_map)); 492 printf(" pmap = %p,\n", D(vm_map, vm_map)->pmap); 493 printf("%*s lock = <struct lock>,", indent(2), ""); 494 printf(" header = <struct vm_map_entry>,"); 495 printf(" nentries = %d,\n", D(vm_map, vm_map)->nentries); 496 printf("%*s size = %lx,", indent(2), "", 497 D(vm_map, vm_map)->size); 498 printf(" ref_count = %d,", D(vm_map, vm_map)->ref_count); 499 printf(" ref_lock = <struct simplelock>,\n"); 500 printf("%*s hint = %p,", indent(2), "", 501 D(vm_map, vm_map)->hint); 502 printf(" hint_lock = <struct simplelock>,\n"); 503 printf("%*s first_free = %p,", indent(2), "", 504 D(vm_map, vm_map)->first_free); 505 printf(" flags = %x <%s%s%s%s%s%s >,\n", D(vm_map, vm_map)->flags, 506 D(vm_map, vm_map)->flags & VM_MAP_PAGEABLE ? " PAGEABLE" : "", 507 D(vm_map, vm_map)->flags & VM_MAP_INTRSAFE ? " INTRSAFE" : "", 508 D(vm_map, vm_map)->flags & VM_MAP_WIREFUTURE ? " WIREFUTURE" : "", 509 D(vm_map, vm_map)->flags & VM_MAP_BUSY ? " BUSY" : "", 510 D(vm_map, vm_map)->flags & VM_MAP_WANTLOCK ? " WANTLOCK" : "", 511 #ifdef VM_MAP_DYING 512 D(vm_map, vm_map)->flags & VM_MAP_DYING ? " DYING" : "", 513 #endif 514 #ifdef VM_MAP_TOPDOWN 515 D(vm_map, vm_map)->flags & VM_MAP_TOPDOWN ? " TOPDOWN" : 516 #endif 517 ""); 518 printf("%*s flags_lock = <struct simplelock>,", indent(2), ""); 519 printf(" timestamp = %u }\n", D(vm_map, vm_map)->timestamp); 520 } 521 if (print_ddb) { 522 char *name; 523 524 if (A(vm_map) == kernel_map_addr) 525 name = "kernel_map"; 526 else if (P(vm_map) == kmem_map) 527 name = "kmem_map"; 528 else if (P(vm_map) == mb_map) 529 name = "mb_map"; 530 else if (P(vm_map) == phys_map) 531 name = "phys_map"; 532 else if (P(vm_map) == exec_map) 533 name = "exec_map"; 534 else if (P(vm_map) == pager_map) 535 name = "pager_map"; 536 else 537 name = NULL; 538 539 printf("%*s%s %p: [0x%lx->0x%lx]\n", indent(2), "", 540 recurse < 2 ? "MAP" : "SUBMAP", P(vm_map), 541 D(vm_map, vm_map)->min_offset, 542 D(vm_map, vm_map)->max_offset); 543 printf("\t%*s#ent=%d, sz=%ld, ref=%d, version=%d, flags=0x%x\n", 544 indent(2), "", D(vm_map, vm_map)->nentries, 545 D(vm_map, vm_map)->size, D(vm_map, vm_map)->ref_count, 546 D(vm_map, vm_map)->timestamp, D(vm_map, vm_map)->flags); 547 printf("\t%*spmap=%p(resident=<unknown>)\n", indent(2), "", 548 D(vm_map, vm_map)->pmap); 549 if (verbose && name != NULL) 550 printf("\t%*s([ %s ])\n", indent(2), "", name); 551 } 552 553 A(header) = A(vm_map) + offsetof(struct vm_map, header); 554 S(header) = sizeof(struct vm_map_entry); 555 memcpy(D(header, vm_map_entry), &D(vm_map, vm_map)->header, S(header)); 556 dump_vm_map_entry(kd, vmspace, header, 1); 557 558 /* 559 * we're not recursing into a submap, so print headers 560 */ 561 if (recurse < 2) { 562 /* headers */ 563 #ifdef DISABLED_HEADERS 564 if (print_map) 565 printf("%-*s %-*s rwx RWX CPY NCP I W A\n", 566 (int)sizeof(long) * 2 + 2, "Start", 567 (int)sizeof(long) * 2 + 2, "End"); 568 if (print_maps) 569 printf("%-*s %-*s rwxp %-*s Dev Inode File\n", 570 (int)sizeof(long) * 2 + 0, "Start", 571 (int)sizeof(long) * 2 + 0, "End", 572 (int)sizeof(long) * 2 + 0, "Offset"); 573 if (print_solaris) 574 printf("%-*s %*s Protection File\n", 575 (int)sizeof(long) * 2 + 0, "Start", 576 (int)sizeof(int) * 2 - 1, "Size "); 577 #endif 578 if (print_all) 579 printf("%-*s %-*s %*s %-*s rwxpc RWX I/W/A Dev %*s" 580 " - File\n", 581 (int)sizeof(long) * 2, "Start", 582 (int)sizeof(long) * 2, "End", 583 (int)sizeof(int) * 2, "Size ", 584 (int)sizeof(long) * 2, "Offset", 585 (int)sizeof(int) * 2, "Inode"); 586 } 587 588 /* these are the "sub entries" */ 589 total = 0; 590 next = D(header, vm_map_entry)->next; 591 last = P(header); 592 593 while (next != 0 && next != last) { 594 addr = (u_long)next; 595 A(vm_map_entry) = addr; 596 S(vm_map_entry) = sizeof(struct vm_map_entry); 597 KDEREF(kd, vm_map_entry); 598 next = D(vm_map_entry, vm_map_entry)->next; 599 total += dump_vm_map_entry(kd, vmspace, vm_map_entry, 0); 600 } 601 602 /* 603 * we're not recursing into a submap, so print totals 604 */ 605 if (recurse < 2) { 606 if (print_solaris) 607 printf("%-*s %8luK\n", 608 (int)sizeof(void *) * 2 - 2, " total", 609 (unsigned long)total); 610 if (print_all) 611 printf("%-*s %9luk\n", 612 (int)sizeof(void *) * 4 - 1, " total", 613 (unsigned long)total); 614 } 615 } 616 617 size_t 618 dump_vm_map_entry(kvm_t *kd, struct kbit *vmspace, 619 struct kbit *vm_map_entry, 620 int ishead) 621 { 622 struct kbit kbit[3]; 623 struct kbit *uvm_obj, *vp, *vfs; 624 struct vm_map_entry *vme; 625 size_t sz; 626 char *name; 627 dev_t dev; 628 ino_t inode; 629 630 uvm_obj = &kbit[0]; 631 vp = &kbit[1]; 632 vfs = &kbit[2]; 633 634 A(uvm_obj) = 0; 635 A(vp) = 0; 636 A(vfs) = 0; 637 638 vme = D(vm_map_entry, vm_map_entry); 639 640 if ((ishead && (debug & PRINT_VM_MAP_HEADER)) || 641 (!ishead && (debug & PRINT_VM_MAP_ENTRY))) { 642 printf("%*s%s %p = {", indent(2), "", 643 ishead ? "vm_map.header" : "vm_map_entry", 644 P(vm_map_entry)); 645 printf(" prev = %p,", vme->prev); 646 printf(" next = %p,\n", vme->next); 647 printf("%*s start = %lx,", indent(2), "", vme->start); 648 printf(" end = %lx,", vme->end); 649 printf(" object.uvm_obj/sub_map = %p,\n", vme->object.uvm_obj); 650 printf("%*s offset = %lx,", indent(2), "", 651 (unsigned long)vme->offset); 652 printf(" etype = %x <%s%s%s%s >,", vme->etype, 653 vme->etype & UVM_ET_OBJ ? " OBJ" : "", 654 vme->etype & UVM_ET_SUBMAP ? " SUBMAP" : "", 655 vme->etype & UVM_ET_COPYONWRITE ? " COW" : "", 656 vme->etype & UVM_ET_NEEDSCOPY ? " NEEDSCOPY" : ""); 657 printf(" protection = %x,\n", vme->protection); 658 printf("%*s max_protection = %x,", indent(2), "", 659 vme->max_protection); 660 printf(" inheritance = %d,", vme->inheritance); 661 printf(" wired_count = %d,\n", vme->wired_count); 662 printf("%*s aref = { ar_pageoff = %x, ar_amap = %p },", 663 indent(2), "", vme->aref.ar_pageoff, vme->aref.ar_amap); 664 printf(" advice = %d,\n", vme->advice); 665 printf("%*s flags = %x <%s%s > }\n", indent(2), "", 666 vme->flags, 667 vme->flags & UVM_MAP_STATIC ? " STATIC" : "", 668 vme->flags & UVM_MAP_KMEM ? " KMEM" : ""); 669 } 670 671 if (ishead) 672 return (0); 673 674 A(vp) = 0; 675 A(uvm_obj) = 0; 676 677 if (vme->object.uvm_obj != NULL) { 678 P(uvm_obj) = vme->object.uvm_obj; 679 S(uvm_obj) = sizeof(struct uvm_object); 680 KDEREF(kd, uvm_obj); 681 if (UVM_ET_ISOBJ(vme) && 682 UVM_OBJ_IS_VNODE(D(uvm_obj, uvm_object))) { 683 P(vp) = P(uvm_obj); 684 S(vp) = sizeof(struct vnode); 685 KDEREF(kd, vp); 686 } 687 } 688 689 A(vfs) = NULL; 690 691 if (P(vp) != NULL && D(vp, vnode)->v_mount != NULL) { 692 P(vfs) = D(vp, vnode)->v_mount; 693 S(vfs) = sizeof(struct mount); 694 KDEREF(kd, vfs); 695 D(vp, vnode)->v_mount = D(vfs, mount); 696 } 697 698 /* 699 * dig out the device number and inode number from certain 700 * file system types. 701 */ 702 #define V_DATA_IS(vp, type, d, i) do { \ 703 struct kbit data; \ 704 P(&data) = D(vp, vnode)->v_data; \ 705 S(&data) = sizeof(*D(&data, type)); \ 706 KDEREF(kd, &data); \ 707 dev = D(&data, type)->d; \ 708 inode = D(&data, type)->i; \ 709 } while (0/*CONSTCOND*/) 710 711 dev = 0; 712 inode = 0; 713 714 if (A(vp) && 715 D(vp, vnode)->v_type == VREG && 716 D(vp, vnode)->v_data != NULL) { 717 switch (D(vp, vnode)->v_tag) { 718 case VT_UFS: 719 case VT_LFS: 720 case VT_EXT2FS: 721 V_DATA_IS(vp, inode, i_dev, i_number); 722 break; 723 case VT_ISOFS: 724 V_DATA_IS(vp, iso_node, i_dev, i_number); 725 break; 726 case VT_NON: 727 case VT_NFS: 728 case VT_MFS: 729 case VT_MSDOSFS: 730 case VT_LOFS: 731 case VT_FDESC: 732 case VT_PORTAL: 733 case VT_NULL: 734 case VT_UMAP: 735 case VT_KERNFS: 736 case VT_PROCFS: 737 case VT_AFS: 738 case VT_UNION: 739 case VT_ADOSFS: 740 case VT_CODA: 741 case VT_FILECORE: 742 case VT_NTFS: 743 case VT_VFS: 744 case VT_OVERLAY: 745 case VT_SMBFS: 746 break; 747 } 748 } 749 750 name = findname(kd, vmspace, vm_map_entry, vp, vfs, uvm_obj); 751 752 if (print_map) { 753 printf("%*s0x%lx 0x%lx %c%c%c %c%c%c %s %s %d %d %d", 754 indent(2), "", 755 vme->start, vme->end, 756 (vme->protection & VM_PROT_READ) ? 'r' : '-', 757 (vme->protection & VM_PROT_WRITE) ? 'w' : '-', 758 (vme->protection & VM_PROT_EXECUTE) ? 'x' : '-', 759 (vme->max_protection & VM_PROT_READ) ? 'r' : '-', 760 (vme->max_protection & VM_PROT_WRITE) ? 'w' : '-', 761 (vme->max_protection & VM_PROT_EXECUTE) ? 'x' : '-', 762 (vme->etype & UVM_ET_COPYONWRITE) ? "COW" : "NCOW", 763 (vme->etype & UVM_ET_NEEDSCOPY) ? "NC" : "NNC", 764 vme->inheritance, vme->wired_count, 765 vme->advice); 766 if (verbose) { 767 if (inode) 768 printf(" %d,%d %d", 769 major(dev), minor(dev), inode); 770 if (name[0]) 771 printf(" %s", name); 772 } 773 printf("\n"); 774 } 775 776 if (print_maps) { 777 printf("%*s%0*lx-%0*lx %c%c%c%c %0*lx %02x:%02x %d %s\n", 778 indent(2), "", 779 (int)sizeof(void *) * 2, vme->start, 780 (int)sizeof(void *) * 2, vme->end, 781 (vme->protection & VM_PROT_READ) ? 'r' : '-', 782 (vme->protection & VM_PROT_WRITE) ? 'w' : '-', 783 (vme->protection & VM_PROT_EXECUTE) ? 'x' : '-', 784 (vme->etype & UVM_ET_COPYONWRITE) ? 'p' : 's', 785 (int)sizeof(void *) * 2, 786 (unsigned long)vme->offset, 787 major(dev), minor(dev), inode, 788 (name[0] != ' ') || verbose ? name : ""); 789 } 790 791 if (print_ddb) { 792 printf("%*s - %p: 0x%lx->0x%lx: obj=%p/0x%lx, amap=%p/%d\n", 793 indent(2), "", 794 P(vm_map_entry), vme->start, vme->end, 795 vme->object.uvm_obj, (unsigned long)vme->offset, 796 vme->aref.ar_amap, vme->aref.ar_pageoff); 797 printf("\t%*ssubmap=%c, cow=%c, nc=%c, prot(max)=%d/%d, inh=%d, " 798 "wc=%d, adv=%d\n", 799 indent(2), "", 800 (vme->etype & UVM_ET_SUBMAP) ? 'T' : 'F', 801 (vme->etype & UVM_ET_COPYONWRITE) ? 'T' : 'F', 802 (vme->etype & UVM_ET_NEEDSCOPY) ? 'T' : 'F', 803 vme->protection, vme->max_protection, 804 vme->inheritance, vme->wired_count, vme->advice); 805 if (verbose) { 806 printf("\t%*s", indent(2), ""); 807 if (inode) 808 printf("(dev=%d,%d ino=%d [%s] [%p])\n", 809 major(dev), minor(dev), inode, 810 name, P(vp)); 811 else if (name[0] == ' ') 812 printf("(%s)\n", &name[2]); 813 else 814 printf("(%s)\n", name); 815 } 816 } 817 818 sz = 0; 819 if (print_solaris) { 820 char prot[30]; 821 822 prot[0] = '\0'; 823 prot[1] = '\0'; 824 if (vme->protection & VM_PROT_READ) 825 strcat(prot, "/read"); 826 if (vme->protection & VM_PROT_WRITE) 827 strcat(prot, "/write"); 828 if (vme->protection & VM_PROT_EXECUTE) 829 strcat(prot, "/exec"); 830 831 sz = (size_t)((vme->end - vme->start) / 1024); 832 printf("%*s%0*lX %6luK %-15s %s\n", 833 indent(2), "", 834 (int)sizeof(void *) * 2, 835 (unsigned long)vme->start, 836 (unsigned long)sz, 837 &prot[1], 838 name); 839 } 840 841 if (print_all) { 842 sz = (size_t)((vme->end - vme->start) / 1024); 843 printf(A(vp) ? 844 "%*s%0*lx-%0*lx %7luk %0*lx %c%c%c%c%c (%c%c%c) %d/%d/%d %02d:%02d %7d - %s [%p]\n" : 845 "%*s%0*lx-%0*lx %7luk %0*lx %c%c%c%c%c (%c%c%c) %d/%d/%d %02d:%02d %7d - %s\n", 846 indent(2), "", 847 (int)sizeof(void *) * 2, 848 vme->start, 849 (int)sizeof(void *) * 2, 850 vme->end - (vme->start != vme->end ? 1 : 0), 851 (unsigned long)sz, 852 (int)sizeof(void *) * 2, 853 (unsigned long)vme->offset, 854 (vme->protection & VM_PROT_READ) ? 'r' : '-', 855 (vme->protection & VM_PROT_WRITE) ? 'w' : '-', 856 (vme->protection & VM_PROT_EXECUTE) ? 'x' : '-', 857 (vme->etype & UVM_ET_COPYONWRITE) ? 'p' : 's', 858 (vme->etype & UVM_ET_NEEDSCOPY) ? '+' : '-', 859 (vme->max_protection & VM_PROT_READ) ? 'r' : '-', 860 (vme->max_protection & VM_PROT_WRITE) ? 'w' : '-', 861 (vme->max_protection & VM_PROT_EXECUTE) ? 'x' : '-', 862 vme->inheritance, 863 vme->wired_count, 864 vme->advice, 865 major(dev), minor(dev), inode, 866 name, P(vp)); 867 } 868 869 /* no access allowed, don't count space */ 870 if ((vme->protection & rwx) == 0) 871 sz = 0; 872 873 if (recurse && (vme->etype & UVM_ET_SUBMAP)) { 874 struct kbit mkbit, *submap; 875 876 recurse++; 877 submap = &mkbit; 878 P(submap) = vme->object.sub_map; 879 S(submap) = sizeof(*vme->object.sub_map); 880 KDEREF(kd, submap); 881 dump_vm_map(kd, vmspace, submap, "submap"); 882 recurse--; 883 } 884 885 return (sz); 886 } 887 888 char* 889 findname(kvm_t *kd, struct kbit *vmspace, 890 struct kbit *vm_map_entry, struct kbit *vp, 891 struct kbit *vfs, struct kbit *uvm_obj) 892 { 893 static char buf[1024], *name; 894 struct vm_map_entry *vme; 895 size_t l; 896 897 vme = D(vm_map_entry, vm_map_entry); 898 899 if (UVM_ET_ISOBJ(vme)) { 900 if (A(vfs)) { 901 l = (unsigned)strlen(D(vfs, mount)->mnt_stat.f_mntonname); 902 switch (search_cache(kd, vp, &name, buf, sizeof(buf))) { 903 case 0: /* found something */ 904 name--; 905 *name = '/'; 906 /*FALLTHROUGH*/ 907 case 2: /* found nothing */ 908 name -= 6; 909 memcpy(name, " -??- ", (size_t)6); 910 name -= l; 911 memcpy(name, 912 D(vfs, mount)->mnt_stat.f_mntonname, l); 913 break; 914 case 1: /* all is well */ 915 name--; 916 *name = '/'; 917 if (l != 1) { 918 name -= l; 919 memcpy(name, 920 D(vfs, mount)->mnt_stat.f_mntonname, l); 921 } 922 break; 923 } 924 } 925 else if (UVM_OBJ_IS_DEVICE(D(uvm_obj, uvm_object))) { 926 struct kbit kdev; 927 dev_t dev; 928 929 P(&kdev) = P(uvm_obj); 930 S(&kdev) = sizeof(struct uvm_device); 931 KDEREF(kd, &kdev); 932 dev = D(&kdev, uvm_device)->u_device; 933 name = devname(dev, S_IFCHR); 934 if (name != NULL) 935 snprintf(buf, sizeof(buf), "/dev/%s", name); 936 else 937 snprintf(buf, sizeof(buf), " [ device %d,%d ]", 938 major(dev), minor(dev)); 939 name = buf; 940 } 941 else if (UVM_OBJ_IS_AOBJ(D(uvm_obj, uvm_object))) 942 name = " [ uvm_aobj ]"; 943 else if (UVM_OBJ_IS_UBCPAGER(D(uvm_obj, uvm_object))) 944 name = " [ ubc_pager ]"; 945 else if (UVM_OBJ_IS_VNODE(D(uvm_obj, uvm_object))) 946 name = " [ ?VNODE? ]"; 947 else { 948 snprintf(buf, sizeof(buf), " [ ?? %p ?? ]", 949 D(uvm_obj, uvm_object)->pgops); 950 name = buf; 951 } 952 } 953 954 else if (D(vmspace, vmspace)->vm_maxsaddr <= 955 (caddr_t)vme->start && 956 (D(vmspace, vmspace)->vm_maxsaddr + (size_t)maxssiz) >= 957 (caddr_t)vme->end) 958 name = " [ stack ]"; 959 960 else if ((vme->protection & rwx) == rwx && !heapfound) { 961 /* XXX this could probably be done better */ 962 heapfound = 1; 963 name = " [ heap ]"; 964 } 965 966 else 967 name = " [ anon ]"; 968 969 return (name); 970 } 971 972 int 973 search_cache(kvm_t *kd, struct kbit *vp, char **name, char *buf, size_t blen) 974 { 975 char *o, *e; 976 struct cache_entry *ce; 977 struct kbit svp; 978 u_long cid; 979 980 if (nchashtbl == NULL) 981 load_name_cache(kd); 982 983 P(&svp) = P(vp); 984 S(&svp) = sizeof(struct vnode); 985 cid = D(vp, vnode)->v_id; 986 987 e = &buf[blen - 1]; 988 o = e; 989 do { 990 LIST_FOREACH(ce, &lcache, ce_next) 991 if (ce->ce_vp == P(&svp) && ce->ce_cid == cid) 992 break; 993 if (ce && ce->ce_vp == P(&svp) && ce->ce_cid == cid) { 994 if (o != e) 995 *(--o) = '/'; 996 o -= ce->ce_nlen; 997 memcpy(o, ce->ce_name, (unsigned)ce->ce_nlen); 998 P(&svp) = ce->ce_pvp; 999 cid = ce->ce_pcid; 1000 } 1001 else 1002 break; 1003 } while (1/*CONSTCOND*/); 1004 *e = '\0'; 1005 *name = o; 1006 1007 if (e == o) 1008 return (2); 1009 1010 KDEREF(kd, &svp); 1011 return (D(&svp, vnode)->v_flag & VROOT); 1012 } 1013 1014 void 1015 load_name_cache(kvm_t *kd) 1016 { 1017 struct namecache _ncp, *ncp, *oncp; 1018 struct nchashhead _ncpp, *ncpp; 1019 u_long nchash; 1020 int i; 1021 1022 LIST_INIT(&lcache); 1023 1024 _KDEREF(kd, nchash_addr, &nchash, sizeof(nchash)); 1025 nchashtbl = malloc(sizeof(nchashtbl) * (int)nchash); 1026 _KDEREF(kd, nchashtbl_addr, nchashtbl, 1027 sizeof(nchashtbl) * (int)nchash); 1028 1029 ncpp = &_ncpp; 1030 1031 for (i = 0; i <= nchash; i++) { 1032 ncpp = &nchashtbl[i]; 1033 oncp = NULL; 1034 LIST_FOREACH(ncp, ncpp, nc_hash) { 1035 if (ncp == oncp || 1036 (void*)ncp < kernel_floor || 1037 ncp == (void*)0xdeadbeef) 1038 break; 1039 oncp = ncp; 1040 _KDEREF(kd, (u_long)ncp, &_ncp, sizeof(*ncp)); 1041 ncp = &_ncp; 1042 if ((void*)ncp->nc_vp > kernel_floor && 1043 ncp->nc_nlen > 0) { 1044 if (ncp->nc_nlen > 2 || 1045 ncp->nc_name[0] != '.' || 1046 (ncp->nc_name[1] != '.' && 1047 ncp->nc_nlen != 1)) 1048 cache_enter(i, ncp); 1049 } 1050 } 1051 } 1052 } 1053 1054 void 1055 cache_enter(int i, struct namecache *ncp) 1056 { 1057 struct cache_entry *ce; 1058 1059 if (debug & DUMP_NAMEI_CACHE) 1060 printf("[%d] ncp->nc_vp %10p, ncp->nc_dvp %10p, " 1061 "ncp->nc_nlen %3d [%.*s] (nc_dvpid=%lu, nc_vpid=%lu)\n", 1062 i, ncp->nc_vp, ncp->nc_dvp, 1063 ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name, 1064 ncp->nc_dvpid, ncp->nc_vpid); 1065 1066 ce = malloc(sizeof(struct cache_entry)); 1067 1068 ce->ce_vp = ncp->nc_vp; 1069 ce->ce_pvp = ncp->nc_dvp; 1070 ce->ce_cid = ncp->nc_vpid; 1071 ce->ce_pcid = ncp->nc_dvpid; 1072 ce->ce_nlen = ncp->nc_nlen; 1073 strncpy(ce->ce_name, ncp->nc_name, sizeof(ce->ce_name)); 1074 ce->ce_name[MIN(ce->ce_nlen, sizeof(ce->ce_name) - 1)] = '\0'; 1075 1076 LIST_INSERT_HEAD(&lcache, ce, ce_next); 1077 } 1078