1 /* $NetBSD: pmap.c,v 1.29 2005/12/15 01:53:30 reinoud 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: pmap.c,v 1.29 2005/12/15 01:53:30 reinoud Exp $"); 42 #endif 43 44 #include <string.h> 45 46 #ifndef LOCKDEBUG 47 #define VERSION regular 48 #else /* LOCKDEBUG */ 49 #define VERSION lockdebug 50 #endif /* LOCKDEBUG */ 51 52 #include "pmap.h" 53 #include "main.h" 54 55 static void dump_vm_anon(kvm_t *, struct vm_anon **, int); 56 static char *findname(kvm_t *, struct kbit *, struct kbit *, struct kbit *, 57 struct kbit *, struct kbit *); 58 static int search_cache(kvm_t *, struct kbit *, char **, char *, size_t); 59 60 /* when recursing, output is indented */ 61 #define indent(n) ((n) * (recurse > 1 ? recurse - 1 : 0)) 62 #define rwx (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE) 63 64 int heapfound; 65 66 void 67 PMAPFUNC(process_map,VERSION)(kvm_t *kd, struct kinfo_proc2 *proc, 68 struct kbit *vmspace, const char *thing) 69 { 70 struct kbit kbit, *vm_map = &kbit; 71 72 if (proc) { 73 heapfound = 0; 74 A(vmspace) = (u_long)proc->p_vmspace; 75 S(vmspace) = sizeof(struct vmspace); 76 thing = "proc->p_vmspace.vm_map"; 77 } else if (S(vmspace) == (size_t)-1) { 78 heapfound = 0; 79 /* A(vmspace) set by caller */ 80 S(vmspace) = sizeof(struct vmspace); 81 /* object identified by caller */ 82 } else { 83 heapfound = 1; /* but really, do kernels have a heap? */ 84 A(vmspace) = 0; 85 S(vmspace) = 0; 86 thing = "kernel_map"; 87 } 88 89 S(vm_map) = sizeof(struct vm_map); 90 91 if (S(vmspace) != 0) { 92 KDEREF(kd, vmspace); 93 A(vm_map) = A(vmspace) + offsetof(struct vmspace, vm_map); 94 memcpy(D(vm_map, vm_map), &D(vmspace, vmspace)->vm_map, 95 S(vm_map)); 96 } else { 97 memset(vmspace, 0, sizeof(*vmspace)); 98 A(vm_map) = kernel_map_addr; 99 KDEREF(kd, vm_map); 100 } 101 102 PMAPFUNC(dump_vm_map,VERSION)(kd, proc, vmspace, vm_map, thing); 103 } 104 105 void 106 PMAPFUNC(dump_vm_map,VERSION)(kvm_t *kd, struct kinfo_proc2 *proc, 107 struct kbit *vmspace, struct kbit *vm_map, const char *mname) 108 { 109 struct kbit kbit[2], *header, *vm_map_entry; 110 struct vm_map_entry *last, *next; 111 size_t total; 112 u_long addr, end; 113 114 if (S(vm_map) == (size_t)-1) { 115 heapfound = 1; 116 S(vm_map) = sizeof(struct vm_map); 117 KDEREF(kd, vm_map); 118 } 119 120 header = &kbit[0]; 121 vm_map_entry = &kbit[1]; 122 A(header) = 0; 123 A(vm_map_entry) = 0; 124 125 A(header) = A(vm_map) + offsetof(struct vm_map, header); 126 S(header) = sizeof(struct vm_map_entry); 127 memcpy(D(header, vm_map_entry), &D(vm_map, vm_map)->header, S(header)); 128 129 if (S(vmspace) != 0 && (debug & PRINT_VMSPACE)) { 130 printf("proc->p_vmspace %p = {", P(vmspace)); 131 printf(" vm_refcnt = %d,", D(vmspace, vmspace)->vm_refcnt); 132 printf(" vm_shm = %p,\n", D(vmspace, vmspace)->vm_shm); 133 printf(" vm_rssize = %d,", D(vmspace, vmspace)->vm_rssize); 134 printf(" vm_swrss = %d,", D(vmspace, vmspace)->vm_swrss); 135 printf(" vm_tsize = %d,", D(vmspace, vmspace)->vm_tsize); 136 printf(" vm_dsize = %d,\n", D(vmspace, vmspace)->vm_dsize); 137 printf(" vm_ssize = %d,", D(vmspace, vmspace)->vm_ssize); 138 printf(" vm_taddr = %p,", D(vmspace, vmspace)->vm_taddr); 139 printf(" vm_daddr = %p,\n", D(vmspace, vmspace)->vm_daddr); 140 printf(" vm_maxsaddr = %p,", 141 D(vmspace, vmspace)->vm_maxsaddr); 142 printf(" vm_minsaddr = %p }\n", 143 D(vmspace, vmspace)->vm_minsaddr); 144 } 145 146 if (debug & PRINT_VM_MAP) { 147 printf("%*s%s %p = {", indent(2), "", mname, P(vm_map)); 148 printf(" pmap = %p,\n", D(vm_map, vm_map)->pmap); 149 printf("%*s lock = <struct lock>,", indent(2), ""); 150 printf(" header = <struct vm_map_entry>,"); 151 printf(" nentries = %d,\n", D(vm_map, vm_map)->nentries); 152 printf("%*s size = %lx,", indent(2), "", 153 D(vm_map, vm_map)->size); 154 printf(" ref_count = %d,", D(vm_map, vm_map)->ref_count); 155 printf(" ref_lock = <struct simplelock>,\n"); 156 printf("%*s hint = %p,", indent(2), "", 157 D(vm_map, vm_map)->hint); 158 printf(" hint_lock = <struct simplelock>,\n"); 159 printf("%*s first_free = %p,", indent(2), "", 160 D(vm_map, vm_map)->first_free); 161 printf(" flags = %x <%s%s%s%s%s%s%s >,\n", D(vm_map, vm_map)->flags, 162 D(vm_map, vm_map)->flags & VM_MAP_PAGEABLE ? " PAGEABLE" : "", 163 D(vm_map, vm_map)->flags & VM_MAP_INTRSAFE ? " INTRSAFE" : "", 164 D(vm_map, vm_map)->flags & VM_MAP_WIREFUTURE ? " WIREFUTURE" : "", 165 D(vm_map, vm_map)->flags & VM_MAP_BUSY ? " BUSY" : "", 166 D(vm_map, vm_map)->flags & VM_MAP_WANTLOCK ? " WANTLOCK" : "", 167 #ifdef VM_MAP_DYING 168 D(vm_map, vm_map)->flags & VM_MAP_DYING ? " DYING" : 169 #endif 170 "", 171 #ifdef VM_MAP_TOPDOWN 172 D(vm_map, vm_map)->flags & VM_MAP_TOPDOWN ? " TOPDOWN" : 173 #endif 174 ""); 175 printf("%*s flags_lock = <struct simplelock>,", indent(2), ""); 176 printf(" timestamp = %u }\n", D(vm_map, vm_map)->timestamp); 177 } 178 if (print_ddb) { 179 const char *name = mapname(P(vm_map)); 180 181 printf("%*s%s %p: [0x%lx->0x%lx]\n", indent(2), "", 182 recurse < 2 ? "MAP" : "SUBMAP", P(vm_map), 183 vm_map_min(D(vm_map, vm_map)), 184 vm_map_max(D(vm_map, vm_map))); 185 printf("\t%*s#ent=%d, sz=%ld, ref=%d, version=%d, flags=0x%x\n", 186 indent(2), "", D(vm_map, vm_map)->nentries, 187 D(vm_map, vm_map)->size, D(vm_map, vm_map)->ref_count, 188 D(vm_map, vm_map)->timestamp, D(vm_map, vm_map)->flags); 189 printf("\t%*spmap=%p(resident=<unknown>)\n", indent(2), "", 190 D(vm_map, vm_map)->pmap); 191 if (verbose && name != NULL) 192 printf("\t%*s([ %s ])\n", indent(2), "", name); 193 } 194 195 PMAPFUNC(dump_vm_map_entry,VERSION)(kd, proc, vmspace, header, 1); 196 197 /* 198 * we're not recursing into a submap, so print headers 199 */ 200 if (recurse < 2) { 201 /* headers */ 202 #ifdef DISABLED_HEADERS 203 if (print_map) 204 printf("%-*s %-*s rwx RWX CPY NCP I W A\n", 205 (int)sizeof(long) * 2 + 2, "Start", 206 (int)sizeof(long) * 2 + 2, "End"); 207 if (print_maps) 208 printf("%-*s %-*s rwxp %-*s Dev Inode File\n", 209 (int)sizeof(long) * 2 + 0, "Start", 210 (int)sizeof(long) * 2 + 0, "End", 211 (int)sizeof(long) * 2 + 0, "Offset"); 212 if (print_solaris) 213 printf("%-*s %*s Protection File\n", 214 (int)sizeof(long) * 2 + 0, "Start", 215 (int)sizeof(int) * 2 - 1, "Size "); 216 #endif 217 if (print_all) 218 printf("%-*s %-*s %*s %-*s rwxpc RWX I/W/A Dev %*s" 219 " - File\n", 220 (int)sizeof(long) * 2, "Start", 221 (int)sizeof(long) * 2, "End", 222 (int)sizeof(int) * 2, "Size ", 223 (int)sizeof(long) * 2, "Offset", 224 (int)sizeof(int) * 2, "Inode"); 225 } 226 227 /* these are the "sub entries" */ 228 total = 0; 229 next = D(header, vm_map_entry)->next; 230 last = P(header); 231 end = 0; 232 233 while (next != 0 && next != last) { 234 addr = (u_long)next; 235 A(vm_map_entry) = addr; 236 S(vm_map_entry) = sizeof(struct vm_map_entry); 237 KDEREF(kd, vm_map_entry); 238 next = D(vm_map_entry, vm_map_entry)->next; 239 240 if (end == 0) 241 end = D(vm_map_entry, vm_map_entry)->start; 242 else if (verbose > 1 && 243 end != D(vm_map_entry, vm_map_entry)->start) 244 printf("%*s[%lu pages / %luK]\n", indent(2), "", 245 (D(vm_map_entry, vm_map_entry)->start - end) / 246 page_size, 247 (D(vm_map_entry, vm_map_entry)->start - end) / 248 1024); 249 total += PMAPFUNC(dump_vm_map_entry,VERSION)(kd, proc, 250 vmspace, vm_map_entry, 0); 251 252 end = D(vm_map_entry, vm_map_entry)->end; 253 } 254 255 /* 256 * we're not recursing into a submap, so print totals 257 */ 258 if (recurse < 2) { 259 if (print_solaris) 260 printf("%-*s %8luK\n", 261 (int)sizeof(void *) * 2 - 2, " total", 262 (unsigned long)total); 263 if (print_all) 264 printf("%-*s %9luk\n", 265 (int)sizeof(void *) * 4 - 1, " total", 266 (unsigned long)total); 267 } 268 } 269 270 size_t 271 PMAPFUNC(dump_vm_map_entry,VERSION)(kvm_t *kd, 272 struct kinfo_proc2 *proc, struct kbit *vmspace, 273 struct kbit *vm_map_entry, int ishead) 274 { 275 struct kbit kbit[3]; 276 struct kbit *uvm_obj, *vp, *vfs; 277 struct vm_map_entry *vme; 278 size_t sz; 279 char *name; 280 dev_t dev; 281 ino_t inode; 282 283 if (S(vm_map_entry) == (size_t)-1) { 284 heapfound = 1; 285 S(vm_map_entry) = sizeof(struct vm_map_entry); 286 KDEREF(kd, vm_map_entry); 287 } 288 289 uvm_obj = &kbit[0]; 290 vp = &kbit[1]; 291 vfs = &kbit[2]; 292 293 A(uvm_obj) = 0; 294 A(vp) = 0; 295 A(vfs) = 0; 296 297 vme = D(vm_map_entry, vm_map_entry); 298 299 if ((ishead && (debug & PRINT_VM_MAP_HEADER)) || 300 (!ishead && (debug & PRINT_VM_MAP_ENTRY))) { 301 printf("%*s%s %p = {", indent(2), "", 302 ishead ? "vm_map.header" : "vm_map_entry", 303 P(vm_map_entry)); 304 printf(" prev = %p,", vme->prev); 305 printf(" next = %p,\n", vme->next); 306 printf("%*s start = %lx,", indent(2), "", vme->start); 307 printf(" end = %lx,", vme->end); 308 printf(" object.uvm_obj/sub_map = %p,\n", vme->object.uvm_obj); 309 printf("%*s offset = %" PRIx64 ",", indent(2), "", 310 vme->offset); 311 printf(" etype = %x <%s%s%s%s >,", vme->etype, 312 UVM_ET_ISOBJ(vme) ? " OBJ" : "", 313 UVM_ET_ISSUBMAP(vme) ? " SUBMAP" : "", 314 UVM_ET_ISCOPYONWRITE(vme) ? " COW" : "", 315 UVM_ET_ISNEEDSCOPY(vme) ? " NEEDSCOPY" : ""); 316 printf(" protection = %x,\n", vme->protection); 317 printf("%*s max_protection = %x,", indent(2), "", 318 vme->max_protection); 319 printf(" inheritance = %d,", vme->inheritance); 320 printf(" wired_count = %d,\n", vme->wired_count); 321 printf("%*s aref = { ar_pageoff = %x, ar_amap = %p },", 322 indent(2), "", vme->aref.ar_pageoff, vme->aref.ar_amap); 323 printf(" advice = %d,\n", vme->advice); 324 printf("%*s flags = %x <%s%s%s%s%s > }\n", indent(2), "", 325 vme->flags, 326 vme->flags & UVM_MAP_KERNEL ? " KERNEL" : "", 327 vme->flags & UVM_MAP_KMAPENT ? " KMAPENT" : "", 328 vme->flags & UVM_MAP_FIRST ? " FIRST" : "", 329 vme->flags & UVM_MAP_QUANTUM ? " QUANTUM" : "", 330 vme->flags & UVM_MAP_NOMERGE ? " NOMERGE" : ""); 331 } 332 333 if ((debug & PRINT_VM_AMAP) && (vme->aref.ar_amap != NULL)) { 334 struct kbit akbit, *amap; 335 336 amap = &akbit; 337 P(amap) = vme->aref.ar_amap; 338 S(amap) = sizeof(struct vm_amap); 339 KDEREF(kd, amap); 340 PMAPFUNC(dump_amap,VERSION)(kd, amap); 341 } 342 343 if (ishead) 344 return (0); 345 346 A(vp) = 0; 347 A(uvm_obj) = 0; 348 349 if (vme->object.uvm_obj != NULL) { 350 P(uvm_obj) = vme->object.uvm_obj; 351 S(uvm_obj) = sizeof(struct uvm_object); 352 KDEREF(kd, uvm_obj); 353 if (UVM_ET_ISOBJ(vme) && 354 UVM_OBJ_IS_VNODE(D(uvm_obj, uvm_object))) { 355 P(vp) = P(uvm_obj); 356 S(vp) = sizeof(struct vnode); 357 KDEREF(kd, vp); 358 } 359 } 360 361 A(vfs) = 0; 362 363 if (P(vp) != NULL && D(vp, vnode)->v_mount != NULL) { 364 P(vfs) = D(vp, vnode)->v_mount; 365 S(vfs) = sizeof(struct mount); 366 KDEREF(kd, vfs); 367 D(vp, vnode)->v_mount = D(vfs, mount); 368 } 369 370 /* 371 * dig out the device number and inode number from certain 372 * file system types. 373 */ 374 #define V_DATA_IS(vp, type, d, i) do { \ 375 struct kbit data; \ 376 P(&data) = D(vp, vnode)->v_data; \ 377 S(&data) = sizeof(*D(&data, type)); \ 378 KDEREF(kd, &data); \ 379 dev = D(&data, type)->d; \ 380 inode = D(&data, type)->i; \ 381 } while (0/*CONSTCOND*/) 382 383 dev = 0; 384 inode = 0; 385 386 if (A(vp) && 387 D(vp, vnode)->v_type == VREG && 388 D(vp, vnode)->v_data != NULL) { 389 switch (D(vp, vnode)->v_tag) { 390 case VT_UFS: 391 case VT_LFS: 392 case VT_EXT2FS: 393 V_DATA_IS(vp, inode, i_dev, i_number); 394 break; 395 case VT_ISOFS: 396 V_DATA_IS(vp, iso_node, i_dev, i_number); 397 break; 398 case VT_NON: 399 case VT_NFS: 400 case VT_MFS: 401 case VT_MSDOSFS: 402 case VT_LOFS: 403 case VT_FDESC: 404 case VT_PORTAL: 405 case VT_NULL: 406 case VT_UMAP: 407 case VT_KERNFS: 408 case VT_PROCFS: 409 case VT_AFS: 410 case VT_UNION: 411 case VT_ADOSFS: 412 case VT_CODA: 413 case VT_FILECORE: 414 case VT_NTFS: 415 case VT_VFS: 416 case VT_OVERLAY: 417 case VT_SMBFS: 418 case VT_PTYFS: 419 case VT_TMPFS: 420 case VT_UDF: 421 break; 422 } 423 } 424 425 name = findname(kd, vmspace, vm_map_entry, vp, vfs, uvm_obj); 426 427 if (print_map) { 428 printf("%*s0x%lx 0x%lx %c%c%c %c%c%c %s %s %d %d %d", 429 indent(2), "", 430 vme->start, vme->end, 431 (vme->protection & VM_PROT_READ) ? 'r' : '-', 432 (vme->protection & VM_PROT_WRITE) ? 'w' : '-', 433 (vme->protection & VM_PROT_EXECUTE) ? 'x' : '-', 434 (vme->max_protection & VM_PROT_READ) ? 'r' : '-', 435 (vme->max_protection & VM_PROT_WRITE) ? 'w' : '-', 436 (vme->max_protection & VM_PROT_EXECUTE) ? 'x' : '-', 437 UVM_ET_ISCOPYONWRITE(vme) ? "COW" : "NCOW", 438 UVM_ET_ISNEEDSCOPY(vme) ? "NC" : "NNC", 439 vme->inheritance, vme->wired_count, 440 vme->advice); 441 if (verbose) { 442 if (inode) 443 printf(" %u,%u %llu", major(dev), minor(dev), 444 (unsigned long long)inode); 445 if (name[0]) 446 printf(" %s", name); 447 } 448 printf("\n"); 449 } 450 451 if (print_maps) { 452 printf("%*s%0*lx-%0*lx %c%c%c%c %0*" PRIx64 " %02x:%02x %llu %s\n", 453 indent(2), "", 454 (int)sizeof(void *) * 2, vme->start, 455 (int)sizeof(void *) * 2, vme->end, 456 (vme->protection & VM_PROT_READ) ? 'r' : '-', 457 (vme->protection & VM_PROT_WRITE) ? 'w' : '-', 458 (vme->protection & VM_PROT_EXECUTE) ? 'x' : '-', 459 UVM_ET_ISCOPYONWRITE(vme) ? 'p' : 's', 460 (int)sizeof(void *) * 2, 461 vme->offset, 462 major(dev), minor(dev), (unsigned long long)inode, 463 (name[0] != ' ') || verbose ? name : ""); 464 } 465 466 if (print_ddb) { 467 printf("%*s - %p: 0x%lx->0x%lx: obj=%p/0x%" PRIx64 ", amap=%p/%d\n", 468 indent(2), "", 469 P(vm_map_entry), vme->start, vme->end, 470 vme->object.uvm_obj, vme->offset, 471 vme->aref.ar_amap, vme->aref.ar_pageoff); 472 printf("\t%*ssubmap=%c, cow=%c, nc=%c, prot(max)=%d/%d, inh=%d, " 473 "wc=%d, adv=%d\n", 474 indent(2), "", 475 UVM_ET_ISSUBMAP(vme) ? 'T' : 'F', 476 UVM_ET_ISCOPYONWRITE(vme) ? 'T' : 'F', 477 UVM_ET_ISNEEDSCOPY(vme) ? 'T' : 'F', 478 vme->protection, vme->max_protection, 479 vme->inheritance, vme->wired_count, vme->advice); 480 if (verbose) { 481 printf("\t%*s", indent(2), ""); 482 if (inode) 483 printf("(dev=%u,%u ino=%llu [%s] [%p])\n", 484 major(dev), minor(dev), 485 (unsigned long long)inode, name, P(vp)); 486 else if (name[0] == ' ') 487 printf("(%s)\n", &name[2]); 488 else 489 printf("(%s)\n", name); 490 } 491 } 492 493 sz = 0; 494 if (print_solaris) { 495 char prot[30]; 496 497 prot[0] = '\0'; 498 prot[1] = '\0'; 499 if (vme->protection & VM_PROT_READ) 500 strlcat(prot, "/read", sizeof(prot)); 501 if (vme->protection & VM_PROT_WRITE) 502 strlcat(prot, "/write", sizeof(prot)); 503 if (vme->protection & VM_PROT_EXECUTE) 504 strlcat(prot, "/exec", sizeof(prot)); 505 506 sz = (size_t)((vme->end - vme->start) / 1024); 507 printf("%*s%0*lX %6luK %-15s %s\n", 508 indent(2), "", 509 (int)sizeof(void *) * 2, 510 (unsigned long)vme->start, 511 (unsigned long)sz, 512 &prot[1], 513 name); 514 } 515 516 if (print_all) { 517 sz = (size_t)((vme->end - vme->start) / 1024); 518 printf(A(vp) ? 519 "%*s%0*lx-%0*lx %7luk %0*" PRIx64 " %c%c%c%c%c (%c%c%c) %d/%d/%d %02u:%02u %7llu - %s [%p]\n" : 520 "%*s%0*lx-%0*lx %7luk %0*" PRIx64 " %c%c%c%c%c (%c%c%c) %d/%d/%d %02u:%02u %7llu - %s\n", 521 indent(2), "", 522 (int)sizeof(void *) * 2, 523 vme->start, 524 (int)sizeof(void *) * 2, 525 vme->end - (vme->start != vme->end ? 1 : 0), 526 (unsigned long)sz, 527 (int)sizeof(void *) * 2, 528 vme->offset, 529 (vme->protection & VM_PROT_READ) ? 'r' : '-', 530 (vme->protection & VM_PROT_WRITE) ? 'w' : '-', 531 (vme->protection & VM_PROT_EXECUTE) ? 'x' : '-', 532 UVM_ET_ISCOPYONWRITE(vme) ? 'p' : 's', 533 UVM_ET_ISNEEDSCOPY(vme) ? '+' : '-', 534 (vme->max_protection & VM_PROT_READ) ? 'r' : '-', 535 (vme->max_protection & VM_PROT_WRITE) ? 'w' : '-', 536 (vme->max_protection & VM_PROT_EXECUTE) ? 'x' : '-', 537 vme->inheritance, 538 vme->wired_count, 539 vme->advice, 540 major(dev), minor(dev), (unsigned long long)inode, 541 name, P(vp)); 542 } 543 544 /* no access allowed, don't count space */ 545 if ((vme->protection & rwx) == 0) 546 sz = 0; 547 548 if (recurse && UVM_ET_ISSUBMAP(vme)) { 549 struct kbit mkbit, *submap; 550 551 recurse++; 552 submap = &mkbit; 553 P(submap) = vme->object.sub_map; 554 S(submap) = sizeof(*vme->object.sub_map); 555 KDEREF(kd, submap); 556 PMAPFUNC(dump_vm_map,VERSION)(kd, proc, vmspace, submap, "submap"); 557 recurse--; 558 } 559 560 return (sz); 561 } 562 563 void 564 PMAPFUNC(dump_amap,VERSION)(kvm_t *kd, struct kbit *amap) 565 { 566 struct vm_anon **am_anon; 567 int *am_slots; 568 int *am_bckptr; 569 int *am_ppref; 570 size_t i, r, l, e; 571 572 if (S(amap) == (size_t)-1) { 573 heapfound = 1; 574 S(amap) = sizeof(struct vm_amap); 575 KDEREF(kd, amap); 576 } 577 578 printf("%*s amap %p = { am_l = <struct simplelock>, am_ref = %d, " 579 "am_flags = %x,\n" 580 "%*s am_maxslot = %d, am_nslot = %d, am_nused = %d, " 581 "am_slots = %p,\n" 582 "%*s am_bckptr = %p, am_anon = %p, am_ppref = %p }\n", 583 indent(2), "", 584 P(amap), 585 D(amap, amap)->am_ref, 586 D(amap, amap)->am_flags, 587 indent(2), "", 588 D(amap, amap)->am_maxslot, 589 D(amap, amap)->am_nslot, 590 D(amap, amap)->am_nused, 591 D(amap, amap)->am_slots, 592 indent(2), "", 593 D(amap, amap)->am_bckptr, 594 D(amap, amap)->am_anon, 595 D(amap, amap)->am_ppref); 596 597 if (!(debug & DUMP_VM_AMAP_DATA)) 598 return; 599 600 /* 601 * Assume that sizeof(struct vm_anon *) >= sizeof(size_t) and 602 * allocate that amount of space. 603 */ 604 l = sizeof(struct vm_anon *) * D(amap, amap)->am_maxslot; 605 am_anon = malloc(l); 606 _KDEREF(kd, (u_long)D(amap, amap)->am_anon, am_anon, l); 607 608 l = sizeof(int) * D(amap, amap)->am_maxslot; 609 am_bckptr = malloc(l); 610 _KDEREF(kd, (u_long)D(amap, amap)->am_bckptr, am_bckptr, l); 611 612 l = sizeof(int) * D(amap, amap)->am_maxslot; 613 am_slots = malloc(l); 614 _KDEREF(kd, (u_long)D(amap, amap)->am_slots, am_slots, l); 615 616 if (D(amap, amap)->am_ppref != NULL && 617 D(amap, amap)->am_ppref != PPREF_NONE) { 618 l = sizeof(int) * D(amap, amap)->am_maxslot; 619 am_ppref = malloc(l); 620 _KDEREF(kd, (u_long)D(amap, amap)->am_ppref, am_ppref, l); 621 } else { 622 am_ppref = NULL; 623 } 624 625 printf(" page# %9s %8s", "am_bckptr", "am_slots"); 626 if (am_ppref) 627 printf(" %8s ", "am_ppref"); 628 printf(" %10s\n", "am_anon"); 629 630 l = r = 0; 631 e = verbose > 1 ? D(amap, amap)->am_maxslot : D(amap, amap)->am_nslot; 632 for (i = 0; i < e; i++) { 633 printf(" %4lx", (unsigned long)i); 634 635 if (am_anon[i] || verbose > 1) 636 printf(" %8x", am_bckptr[i]); 637 else 638 printf(" %8s", "-"); 639 640 if (i < D(amap, amap)->am_nused || verbose > 1) 641 printf(" %8x", am_slots[i]); 642 else 643 printf(" %8s", "-"); 644 645 if (am_ppref) { 646 if (l == 0 || r || verbose > 1) 647 printf(" %8d", am_ppref[i]); 648 else 649 printf(" %8s", "-"); 650 r = 0; 651 if (l == 0) { 652 if (am_ppref[i] > 0) { 653 r = am_ppref[i] - 1; 654 l = 1; 655 } else { 656 r = -am_ppref[i] - 1; 657 l = am_ppref[i + 1]; 658 } 659 printf(" (%4ld @ %4ld)", (long)l, (long)r); 660 r = (l > 1) ? 1 : 0; 661 } 662 else 663 printf(" "); 664 l--; 665 } 666 667 dump_vm_anon(kd, am_anon, (int)i); 668 } 669 670 free(am_anon); 671 free(am_bckptr); 672 free(am_slots); 673 if (am_ppref) 674 free(am_ppref); 675 } 676 677 static void 678 dump_vm_anon(kvm_t *kd, struct vm_anon **alist, int i) 679 { 680 681 printf(" %10p", alist[i]); 682 683 if (debug & PRINT_VM_ANON) { 684 struct kbit kbit, *anon = &kbit; 685 686 A(anon) = (u_long)alist[i]; 687 S(anon) = sizeof(struct vm_anon); 688 if (A(anon) == 0) { 689 printf(" = { }\n"); 690 return; 691 } 692 else 693 KDEREF(kd, anon); 694 695 printf(" = { an_ref = %d, an_lock = <struct simplelock>, an_page = %p, an_swslot = %d }", 696 D(anon, anon)->an_ref, D(anon, anon)->an_page, D(anon, anon)->an_swslot); 697 } 698 699 printf("\n"); 700 } 701 702 static char* 703 findname(kvm_t *kd, struct kbit *vmspace, 704 struct kbit *vm_map_entry, struct kbit *vp, 705 struct kbit *vfs, struct kbit *uvm_obj) 706 { 707 static char buf[1024], *name; 708 struct vm_map_entry *vme; 709 size_t l; 710 711 vme = D(vm_map_entry, vm_map_entry); 712 713 if (UVM_ET_ISOBJ(vme)) { 714 if (A(vfs)) { 715 l = (unsigned)strlen(D(vfs, mount)->mnt_stat.f_mntonname); 716 switch (search_cache(kd, vp, &name, buf, sizeof(buf))) { 717 case 0: /* found something */ 718 name--; 719 *name = '/'; 720 /*FALLTHROUGH*/ 721 case 2: /* found nothing */ 722 name -= 5; 723 memcpy(name, " -?- ", (size_t)5); 724 name -= l; 725 memcpy(name, 726 D(vfs, mount)->mnt_stat.f_mntonname, l); 727 break; 728 case 1: /* all is well */ 729 name--; 730 *name = '/'; 731 if (l != 1) { 732 name -= l; 733 memcpy(name, 734 D(vfs, mount)->mnt_stat.f_mntonname, l); 735 } 736 break; 737 } 738 } 739 else if (UVM_OBJ_IS_DEVICE(D(uvm_obj, uvm_object))) { 740 struct kbit kdev; 741 dev_t dev; 742 743 P(&kdev) = P(uvm_obj); 744 S(&kdev) = sizeof(struct uvm_device); 745 KDEREF(kd, &kdev); 746 dev = D(&kdev, uvm_device)->u_device; 747 name = devname(dev, S_IFCHR); 748 if (name != NULL) 749 snprintf(buf, sizeof(buf), "/dev/%s", name); 750 else 751 snprintf(buf, sizeof(buf), " [ device %d,%d ]", 752 major(dev), minor(dev)); 753 name = buf; 754 } 755 else if (UVM_OBJ_IS_AOBJ(D(uvm_obj, uvm_object))) 756 name = " [ uvm_aobj ]"; 757 else if (UVM_OBJ_IS_UBCPAGER(D(uvm_obj, uvm_object))) 758 name = " [ ubc_pager ]"; 759 else if (UVM_OBJ_IS_VNODE(D(uvm_obj, uvm_object))) 760 name = " [ ?VNODE? ]"; 761 else { 762 snprintf(buf, sizeof(buf), " [ ?? %p ?? ]", 763 D(uvm_obj, uvm_object)->pgops); 764 name = buf; 765 } 766 } 767 768 else if (D(vmspace, vmspace)->vm_maxsaddr <= 769 (caddr_t)vme->start && 770 (D(vmspace, vmspace)->vm_maxsaddr + (size_t)maxssiz) >= 771 (caddr_t)vme->end) 772 name = " [ stack ]"; 773 774 else if (!heapfound && 775 (vme->protection & rwx) == rwx && 776 vme->start >= (u_long)D(vmspace, vmspace)->vm_daddr) { 777 heapfound = 1; 778 name = " [ heap ]"; 779 } 780 781 else if (UVM_ET_ISSUBMAP(vme)) { 782 const char *sub = mapname(vme->object.sub_map); 783 snprintf(buf, sizeof(buf), " [ %s ]", sub ? sub : "(submap)"); 784 name = buf; 785 } 786 787 else 788 name = " [ anon ]"; 789 790 return (name); 791 } 792 793 static int 794 search_cache(kvm_t *kd, struct kbit *vp, char **name, char *buf, size_t blen) 795 { 796 char *o, *e; 797 struct cache_entry *ce; 798 struct kbit svp; 799 800 if (nchashtbl == NULL) 801 load_name_cache(kd); 802 803 P(&svp) = P(vp); 804 S(&svp) = sizeof(struct vnode); 805 806 e = &buf[blen - 1]; 807 o = e; 808 do { 809 LIST_FOREACH(ce, &lcache, ce_next) 810 if (ce->ce_vp == P(&svp)) 811 break; 812 if (ce && ce->ce_vp == P(&svp)) { 813 if (o != e) 814 *(--o) = '/'; 815 o -= ce->ce_nlen; 816 memcpy(o, ce->ce_name, (unsigned)ce->ce_nlen); 817 P(&svp) = ce->ce_pvp; 818 } 819 else 820 break; 821 } while (1/*CONSTCOND*/); 822 *e = '\0'; 823 *name = o; 824 825 if (e == o) 826 return (2); 827 828 KDEREF(kd, &svp); 829 return (D(&svp, vnode)->v_flag & VROOT); 830 } 831