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