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