xref: /openbsd-src/usr.sbin/procmap/procmap.c (revision caaedbb7b282bf724632db46a6c2ee74073d4e1d)
1 /*	$OpenBSD: procmap.c,v 1.5 2004/02/18 03:27:22 tedu Exp $ */
2 /*	$NetBSD: pmap.c,v 1.1 2002/09/01 20:32:44 atatat Exp $ */
3 
4 /*
5  * Copyright (c) 2002 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Andrew Brown.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *      This product includes software developed by the NetBSD
22  *      Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/time.h>
43 #include <sys/exec.h>
44 #include <sys/proc.h>
45 #include <sys/vnode.h>
46 #include <sys/mount.h>
47 #include <sys/uio.h>
48 #include <sys/namei.h>
49 #include <sys/sysctl.h>
50 
51 #include <uvm/uvm.h>
52 #include <uvm/uvm_device.h>
53 
54 #include <ufs/ufs/quota.h>
55 #include <ufs/ufs/inode.h>
56 #undef doff_t
57 #undef IN_ACCESS
58 #undef i_size
59 #undef i_devvp
60 #include <isofs/cd9660/iso.h>
61 #include <isofs/cd9660/cd9660_node.h>
62 
63 #include <kvm.h>
64 #include <fcntl.h>
65 #include <errno.h>
66 #include <err.h>
67 #include <stdlib.h>
68 #include <stddef.h>
69 #include <unistd.h>
70 #include <stdio.h>
71 #include <limits.h>
72 #include <string.h>
73 
74 /*
75  * stolen (and munged) from #include <uvm/uvm_object.h>
76  */
77 #define UVM_OBJ_IS_VNODE(uobj)    ((uobj)->pgops == uvm_vnodeops)
78 #define UVM_OBJ_IS_AOBJ(uobj)     ((uobj)->pgops == aobj_pager)
79 #define UVM_OBJ_IS_DEVICE(uobj)   ((uobj)->pgops == uvm_deviceops)
80 #if 0
81 #define UVM_OBJ_IS_UBCPAGER(uobj) ((uobj)->pgops == ubc_pager)
82 #endif
83 
84 #define PRINT_VMSPACE		0x00000001
85 #define PRINT_VM_MAP		0x00000002
86 #define PRINT_VM_MAP_HEADER	0x00000004
87 #define PRINT_VM_MAP_ENTRY	0x00000008
88 #define DUMP_NAMEI_CACHE	0x00000010
89 
90 struct cache_entry {
91 	LIST_ENTRY(cache_entry) ce_next;
92 	struct vnode *ce_vp, *ce_pvp;
93 	u_long ce_cid, ce_pcid;
94 	int ce_nlen;
95 	char ce_name[256];
96 };
97 
98 LIST_HEAD(cache_head, cache_entry) lcache;
99 LIST_HEAD(nchashhead, namecache) *nchashtbl = NULL;
100 void *uvm_vnodeops, *uvm_deviceops, *aobj_pager;
101 #if 0
102 void *ubc_pager;
103 #endif
104 void *kernel_floor;
105 u_long nchash_addr, nchashtbl_addr, kernel_map_addr;
106 int debug, verbose;
107 int print_all, print_map, print_maps, print_solaris, print_ddb;
108 int rwx = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE, heapfound;
109 rlim_t maxssiz;
110 
111 struct kbit {
112 	/*
113 	 * size of data chunk
114 	 */
115 	size_t k_size;
116 
117 	/*
118 	 * something for printf() and something for kvm_read()
119 	 */
120 	union {
121 		void *k_addr_p;
122 		u_long k_addr_ul;
123 	} k_addr;
124 
125 	/*
126 	 * where we actually put the "stuff"
127 	 */
128 	union {
129 		char data[1];
130 		struct vmspace vmspace;
131 		struct vm_map vm_map;
132 		struct vm_map_entry vm_map_entry;
133 		struct vnode vnode;
134 		struct uvm_object uvm_object;
135 		struct mount mount;
136 		struct namecache namecache;
137 		struct inode inode;
138 		struct iso_node iso_node;
139 		struct uvm_device uvm_device;
140 	} k_data;
141 };
142 
143 /* the size of the object in the kernel */
144 #define S(x)	((x)->k_size)
145 /* the address of the object in kernel, two forms */
146 #define A(x)	((x)->k_addr.k_addr_ul)
147 #define P(x)	((x)->k_addr.k_addr_p)
148 /* the data from the kernel */
149 #define D(x,d)	(&((x)->k_data.d))
150 
151 /* suck the data from the kernel */
152 #define _KDEREF(kd, addr, dst, sz) do { \
153 	ssize_t len; \
154 	len = kvm_read((kd), (addr), (dst), (sz)); \
155 	if (len != (sz)) \
156 		errx(1, "%s == %ld vs. %lu @ %lx", \
157 		    kvm_geterr(kd), (long)len, (unsigned long)(sz), (addr)); \
158 } while (0/*CONSTCOND*/)
159 
160 /* suck the data using the structure */
161 #define KDEREF(kd, item) _KDEREF((kd), A(item), D(item, data), S(item))
162 
163 struct nlist nl[] = {
164 	{ "_maxsmap" },
165 #define NL_MAXSSIZ		0
166 	{ "_uvm_vnodeops" },
167 #define NL_UVM_VNODEOPS		1
168 	{ "_uvm_deviceops" },
169 #define NL_UVM_DEVICEOPS	2
170 	{ "_aobj_pager" },
171 #define NL_AOBJ_PAGER		3
172 	{ "_kernel_map" },
173 #define NL_KERNEL_MAP		4
174 	{ "_nchashtbl" },
175 #define NL_NCHASHTBL		5
176 	{ "_nchash" },
177 #define NL_NCHASH		6
178 	{ "_kernel_text" },
179 #define NL_KENTER		7
180 #if 0
181 	{ "_ubc_pager" },
182 #define NL_UBC_PAGER		8
183 #endif
184 	{ NULL }
185 };
186 
187 void load_symbols(kvm_t *);
188 void process_map(kvm_t *, pid_t, struct kinfo_proc *);
189 size_t dump_vm_map_entry(kvm_t *, struct kbit *, struct kbit *, int);
190 char *findname(kvm_t *, struct kbit *, struct kbit *, struct kbit *,
191 	       struct kbit *, struct kbit *);
192 int search_cache(kvm_t *, struct kbit *, char **, char *, size_t);
193 void load_name_cache(kvm_t *);
194 void cache_enter(struct namecache *);
195 static void __dead usage(void);
196 
197 int
198 main(int argc, char *argv[])
199 {
200 	kvm_t *kd;
201 	pid_t pid;
202 	int many, ch, rc;
203 	char errbuf[_POSIX2_LINE_MAX + 1];
204 	/* u_long addr, next; */
205 	struct kinfo_proc *kproc;
206 	/* struct proc proc; */
207 	char *kmem, *kernel;
208 
209 	pid = -1;
210 	verbose = debug = 0;
211 	print_all = print_map = print_maps = print_solaris = print_ddb = 0;
212 	kmem = kernel = NULL;
213 
214 	while ((ch = getopt(argc, argv, "aD:dlmM:N:p:Prsvx")) != -1) {
215 		switch (ch) {
216 		case 'a':
217 			print_all = 1;
218 			break;
219 		case 'd':
220 			print_ddb = 1;
221 			break;
222 		case 'D':
223 			debug = atoi(optarg);
224 			break;
225 		case 'l':
226 			print_maps = 1;
227 			break;
228 		case 'm':
229 			print_map = 1;
230 			break;
231 		case 'M':
232 			kmem = optarg;
233 			break;
234 		case 'N':
235 			kernel = optarg;
236 			break;
237 		case 'p':
238 			if (!isdigit(optarg[0]))
239 				usage();
240 			pid = atoi(optarg);
241 			break;
242 		case 'P':
243 			pid = getpid();
244 			break;
245 		case 's':
246 			print_solaris = 1;
247 			break;
248 		case 'v':
249 			verbose = 1;
250 			break;
251 		case 'r':
252 		case 'x':
253 			errx(1, "-%c option not implemented, sorry", optopt);
254 			/*NOTREACHED*/
255 		case '?':
256 		default:
257 			usage();
258 		}
259 	}
260 	argc -= optind;
261 	argv += optind;
262 
263 	/* more than one "process" to dump? */
264 	many = (argc > 1 - (pid == -1 ? 0 : 1)) ? 1 : 0;
265 
266 	/* apply default */
267 	if (print_all + print_map + print_maps + print_solaris +
268 	    print_ddb == 0)
269 		print_solaris = 1;
270 
271 	/* start by opening libkvm */
272 	kd = kvm_openfiles(kernel, kmem, NULL, O_RDONLY, errbuf);
273 	errbuf[_POSIX2_LINE_MAX] = '\0';
274 	if (kd == NULL)
275 		errx(1, "%s", errbuf);
276 
277 	/* get "bootstrap" addresses from kernel */
278 	load_symbols(kd);
279 
280 	do {
281 		if (pid == -1) {
282 			if (argc == 0)
283 				pid = getppid();
284 			else {
285 				if (!isdigit(argv[0][0]))
286 					usage();
287 				pid = atoi(argv[0]);
288 				argv++;
289 				argc--;
290 			}
291 		}
292 
293 		/* find the process id */
294 		if (pid == 0)
295 			kproc = NULL;
296 		else {
297 			kproc = kvm_getprocs(kd, KERN_PROC_PID, pid, &rc);
298 			if (kproc == NULL || rc == 0) {
299 				errno = ESRCH;
300 				warn("%d", pid);
301 				pid = -1;
302 				continue;
303 			}
304 		}
305 
306 		/* dump it */
307 		if (many) {
308 			if (kproc)
309 				printf("process %d:\n", pid);
310 			else
311 				printf("kernel:\n");
312 		}
313 
314 		process_map(kd, pid, kproc);
315 		pid = -1;
316 	} while (argc > 0);
317 
318 	/* done.  go away. */
319 	rc = kvm_close(kd);
320 	if (rc == -1)
321 		err(1, "kvm_close");
322 
323 	return (0);
324 }
325 
326 void
327 process_map(kvm_t *kd, pid_t pid, struct kinfo_proc *proc)
328 {
329 	struct kbit kbit[4];
330 	struct kbit *vmspace, *vm_map, *header, *vm_map_entry;
331 	struct vm_map_entry *last;
332 	size_t total;
333 	u_long addr, next;
334 	char *thing;
335 
336 	vmspace = &kbit[0];
337 	vm_map = &kbit[1];
338 	header = &kbit[2];
339 	vm_map_entry = &kbit[3];
340 
341 	A(vmspace) = 0;
342 	A(vm_map) = 0;
343 	A(header) = 0;
344 	A(vm_map_entry) = 0;
345 
346 	if (pid > 0) {
347 		heapfound = 0;
348 		A(vmspace) = (u_long)proc->kp_proc.p_vmspace;
349 		S(vmspace) = sizeof(struct vmspace);
350 		KDEREF(kd, vmspace);
351 		thing = "proc->p_vmspace.vm_map";
352 	} else {
353 		heapfound = 1; /* but really, do kernels have a heap? */
354 		A(vmspace) = 0;
355 		S(vmspace) = 0;
356 		thing = "kernel_map";
357 	}
358 
359 	if (pid > 0 && (debug & PRINT_VMSPACE)) {
360 		printf("proc->p_vmspace %p = {", P(vmspace));
361 		printf(" vm_refcnt = %d,", D(vmspace, vmspace)->vm_refcnt);
362 		printf(" vm_shm = %p,\n", D(vmspace, vmspace)->vm_shm);
363 		printf("    vm_rssize = %d,", D(vmspace, vmspace)->vm_rssize);
364 		printf(" vm_swrss = %d,", D(vmspace, vmspace)->vm_swrss);
365 		printf(" vm_tsize = %d,", D(vmspace, vmspace)->vm_tsize);
366 		printf(" vm_dsize = %d,\n", D(vmspace, vmspace)->vm_dsize);
367 		printf("    vm_ssize = %d,", D(vmspace, vmspace)->vm_ssize);
368 		printf(" vm_taddr = %p,", D(vmspace, vmspace)->vm_taddr);
369 		printf(" vm_daddr = %p,\n", D(vmspace, vmspace)->vm_daddr);
370 		printf("    vm_maxsaddr = %p,",
371 		       D(vmspace, vmspace)->vm_maxsaddr);
372 		printf(" vm_minsaddr = %p }\n",
373 		       D(vmspace, vmspace)->vm_minsaddr);
374 	}
375 
376 	S(vm_map) = sizeof(struct vm_map);
377 	if (pid > 0) {
378 		A(vm_map) = A(vmspace);
379 		memcpy(D(vm_map, vm_map), &D(vmspace, vmspace)->vm_map,
380 		       S(vm_map));
381 	} else {
382 		A(vm_map) = kernel_map_addr;
383 		KDEREF(kd, vm_map);
384 	}
385 	if (debug & PRINT_VM_MAP) {
386 		printf("%s %p = {", thing, P(vm_map));
387 
388 		printf(" pmap = %p,\n", D(vm_map, vm_map)->pmap);
389 		printf("    lock = <struct lock>,");
390 		printf(" header = <struct vm_map_entry>,");
391 		printf(" nentries = %d,\n", D(vm_map, vm_map)->nentries);
392 		printf("    size = %lx,", D(vm_map, vm_map)->size);
393 		printf(" ref_count = %d,", D(vm_map, vm_map)->ref_count);
394 		printf(" ref_lock = <struct simplelock>,\n");
395 		printf("    hint = %p,", D(vm_map, vm_map)->hint);
396 		printf(" hint_lock = <struct simplelock>,\n");
397 		printf("    first_free = %p,", D(vm_map, vm_map)->first_free);
398 		printf(" flags = %x <%s%s%s%s%s%s >,\n", D(vm_map, vm_map)->flags,
399 		       D(vm_map, vm_map)->flags & VM_MAP_PAGEABLE ? " PAGEABLE" : "",
400 		       D(vm_map, vm_map)->flags & VM_MAP_INTRSAFE ? " INTRSAFE" : "",
401 		       D(vm_map, vm_map)->flags & VM_MAP_WIREFUTURE ? " WIREFUTURE" : "",
402 		       D(vm_map, vm_map)->flags & VM_MAP_BUSY ? " BUSY" : "",
403 		       D(vm_map, vm_map)->flags & VM_MAP_WANTLOCK ? " WANTLOCK" : "",
404 #if VM_MAP_TOPDOWN > 0
405 		       D(vm_map, vm_map)->flags & VM_MAP_TOPDOWN ? " TOPDOWN" :
406 #endif
407 		       "");
408 		printf("    flags_lock = <struct simplelock>,");
409 		printf(" timestamp = %u }\n", D(vm_map, vm_map)->timestamp);
410 	}
411 	if (print_ddb) {
412 		printf("MAP %p: [0x%lx->0x%lx]\n", P(vm_map),
413 		       D(vm_map, vm_map)->min_offset, D(vm_map, vm_map)->max_offset);
414 		printf("\t#ent=%d, sz=%ld, ref=%d, version=%d, flags=0x%x\n",
415 		       D(vm_map, vm_map)->nentries, D(vm_map, vm_map)->size,
416 		       D(vm_map, vm_map)->ref_count, D(vm_map, vm_map)->timestamp,
417 		       D(vm_map, vm_map)->flags);
418 		printf("\tpmap=%p(resident=<unknown>)\n", D(vm_map, vm_map)->pmap);
419 	}
420 
421 	A(header) = A(vm_map) + offsetof(struct vm_map, header);
422 	S(header) = sizeof(struct vm_map_entry);
423 	memcpy(D(header, vm_map_entry), &D(vm_map, vm_map)->header, S(header));
424 	dump_vm_map_entry(kd, vmspace, header, 1);
425 
426 	/* headers */
427 #ifdef DISABLED_HEADERS
428 	if (print_map)
429 		printf("%-*s %-*s rwx RWX CPY NCP I W A\n",
430 		       (int)sizeof(long) * 2 + 2, "Start",
431 		       (int)sizeof(long) * 2 + 2, "End");
432 	if (print_maps)
433 		printf("%-*s %-*s rwxp %-*s Dev   Inode      File\n",
434 		       (int)sizeof(long) * 2 + 0, "Start",
435 		       (int)sizeof(long) * 2 + 0, "End",
436 		       (int)sizeof(long) * 2 + 0, "Offset");
437 	if (print_solaris)
438 		printf("%-*s %*s Protection        File\n",
439 		       (int)sizeof(long) * 2 + 0, "Start",
440 		       (int)sizeof(int) * 2 - 1,  "Size ");
441 #endif
442 	if (print_all)
443 		printf("%-*s %-*s %*s %-*s rwxpc  RWX  I/W/A Dev  %*s - File\n",
444 		       (int)sizeof(long) * 2, "Start",
445 		       (int)sizeof(long) * 2, "End",
446 		       (int)sizeof(int)  * 2, "Size ",
447 		       (int)sizeof(long) * 2, "Offset",
448 		       (int)sizeof(int)  * 2, "Inode");
449 
450 	/* these are the "sub entries" */
451 	total = 0;
452 	next = (u_long)D(header, vm_map_entry)->next;
453 	D(vm_map_entry, vm_map_entry)->next =
454 		D(header, vm_map_entry)->next + 1;
455 	last = P(header);
456 
457 	while (next != 0 && D(vm_map_entry, vm_map_entry)->next != last) {
458 		addr = next;
459 		A(vm_map_entry) = addr;
460 		S(vm_map_entry) = sizeof(struct vm_map_entry);
461 		KDEREF(kd, vm_map_entry);
462 		total += dump_vm_map_entry(kd, vmspace, vm_map_entry, 0);
463 		next = (u_long)D(vm_map_entry, vm_map_entry)->next;
464 	}
465 	if (print_solaris)
466 		printf("%-*s %8luK\n",
467 		       (int)sizeof(void *) * 2 - 2, " total",
468 		       (unsigned long)total);
469 	if (print_all)
470 		printf("%-*s %9luk\n",
471 		       (int)sizeof(void *) * 4 - 1, " total",
472 		       (unsigned long)total);
473 }
474 
475 void
476 load_symbols(kvm_t *kd)
477 {
478 	int rc;
479 	int i;
480 
481 	rc = kvm_nlist(kd, &nl[0]);
482 	if (rc == -1)
483 		errx(1, "%s == %d", kvm_geterr(kd), rc);
484 	for (i = 0; i < sizeof(nl)/sizeof(nl[0]); i++)
485 		if (nl[i].n_value == 0 && nl[i].n_name)
486 			printf("%s not found\n", nl[i].n_name);
487 
488 	uvm_vnodeops =	(void*)nl[NL_UVM_VNODEOPS].n_value;
489 	uvm_deviceops =	(void*)nl[NL_UVM_DEVICEOPS].n_value;
490 	aobj_pager =	(void*)nl[NL_AOBJ_PAGER].n_value;
491 #if 0
492 	ubc_pager =	(void*)nl[NL_UBC_PAGER].n_value;
493 #endif
494 
495 	kernel_floor =	(void*)nl[NL_KENTER].n_value;
496 	nchash_addr =	nl[NL_NCHASH].n_value;
497 
498 	_KDEREF(kd, nl[NL_MAXSSIZ].n_value, &maxssiz,
499 		sizeof(maxssiz));
500 	_KDEREF(kd, nl[NL_NCHASHTBL].n_value, &nchashtbl_addr,
501 	       sizeof(nchashtbl_addr));
502 	_KDEREF(kd, nl[NL_KERNEL_MAP].n_value, &kernel_map_addr,
503 		sizeof(kernel_map_addr));
504 }
505 
506 size_t
507 dump_vm_map_entry(kvm_t *kd, struct kbit *vmspace,
508 		  struct kbit *vm_map_entry,
509 		  int ishead)
510 {
511 	struct kbit kbit[3];
512 	struct kbit *uvm_obj, *vp, *vfs;
513 	struct vm_map_entry *vme;
514 	size_t sz;
515 	char *name;
516 	dev_t dev;
517 	ino_t inode;
518 
519 	uvm_obj = &kbit[0];
520 	vp = &kbit[1];
521 	vfs = &kbit[2];
522 
523 	A(uvm_obj) = 0;
524 	A(vp) = 0;
525 	A(vfs) = 0;
526 
527 	vme = D(vm_map_entry, vm_map_entry);
528 
529 	if ((ishead && (debug & PRINT_VM_MAP_HEADER)) ||
530 	    (!ishead && (debug & PRINT_VM_MAP_ENTRY))) {
531 		printf("%s %p = {", ishead ? "vm_map.header" : "vm_map_entry",
532 		       P(vm_map_entry));
533 		printf(" prev = %p,", vme->prev);
534 		printf(" next = %p,\n", vme->next);
535 		printf("    start = %lx,", vme->start);
536 		printf(" end = %lx,", vme->end);
537 		printf(" object.uvm_obj/sub_map = %p,\n", vme->object.uvm_obj);
538 		printf("    offset = %lx,", (unsigned long)vme->offset);
539 		printf(" etype = %x <%s%s%s%s >,", vme->etype,
540 		       vme->etype & UVM_ET_OBJ ? " OBJ" : "",
541 		       vme->etype & UVM_ET_SUBMAP ? " SUBMAP" : "",
542 		       vme->etype & UVM_ET_COPYONWRITE ? " COW" : "",
543 		       vme->etype & UVM_ET_NEEDSCOPY ? " NEEDSCOPY" : "");
544 		printf(" protection = %x,\n", vme->protection);
545 		printf("    max_protection = %x,", vme->max_protection);
546 		printf(" inheritance = %d,", vme->inheritance);
547 		printf(" wired_count = %d,\n", vme->wired_count);
548 		printf("    aref = <struct vm_aref>,");
549 		printf(" advice = %d,", vme->advice);
550 		printf(" flags = %x <%s%s > }\n", vme->flags,
551 		       vme->flags & UVM_MAP_STATIC ? " STATIC" : "",
552 		       vme->flags & UVM_MAP_KMEM ? " KMEM" : "");
553 	}
554 
555 	if (ishead)
556 		return (0);
557 
558 	A(vp) = 0;
559 	A(uvm_obj) = 0;
560 
561 	if (vme->object.uvm_obj != NULL) {
562 		P(uvm_obj) = vme->object.uvm_obj;
563 		S(uvm_obj) = sizeof(struct uvm_object);
564 		KDEREF(kd, uvm_obj);
565 		if (UVM_ET_ISOBJ(vme) &&
566 		    UVM_OBJ_IS_VNODE(D(uvm_obj, uvm_object))) {
567 			P(vp) = P(uvm_obj);
568 			S(vp) = sizeof(struct vnode);
569 			KDEREF(kd, vp);
570 		}
571 	}
572 
573 	A(vfs) = NULL;
574 
575 	if (P(vp) != NULL && D(vp, vnode)->v_mount != NULL) {
576 		P(vfs) = D(vp, vnode)->v_mount;
577 		S(vfs) = sizeof(struct mount);
578 		KDEREF(kd, vfs);
579 		D(vp, vnode)->v_mount = D(vfs, mount);
580 	}
581 
582 	/*
583 	 * dig out the device number and inode number from certain
584 	 * file system types.
585 	 */
586 #define V_DATA_IS(vp, type, d, i) do { \
587 	struct kbit data; \
588 	P(&data) = D(vp, vnode)->v_data; \
589 	S(&data) = sizeof(*D(&data, type)); \
590 	KDEREF(kd, &data); \
591 	dev = D(&data, type)->d; \
592 	inode = D(&data, type)->i; \
593 } while (0/*CONSTCOND*/)
594 
595 	dev = 0;
596 	inode = 0;
597 
598 	if (A(vp) &&
599 	    D(vp, vnode)->v_type == VREG &&
600 	    D(vp, vnode)->v_data != NULL) {
601 		switch (D(vp, vnode)->v_tag) {
602 		case VT_UFS:
603 		case VT_LFS:
604 		case VT_EXT2FS:
605 			V_DATA_IS(vp, inode, i_dev, i_number);
606 			break;
607 		case VT_ISOFS:
608 			V_DATA_IS(vp, iso_node, i_dev, i_number);
609 			break;
610 		case VT_NON:
611 		case VT_NFS:
612 		case VT_MFS:
613 		case VT_MSDOSFS:
614 		case VT_LOFS:
615 		case VT_FDESC:
616 		case VT_PORTAL:
617 		case VT_NULL:
618 		case VT_UMAP:
619 		case VT_KERNFS:
620 		case VT_PROCFS:
621 		case VT_AFS:
622 		case VT_UNION:
623 		case VT_ADOSFS:
624 		default:
625 			break;
626 		}
627 	}
628 
629 	name = findname(kd, vmspace, vm_map_entry, vp, vfs, uvm_obj);
630 
631 	if (print_map) {
632 		printf("0x%lx 0x%lx %c%c%c %c%c%c %s %s %d %d %d",
633 		       vme->start, vme->end,
634 		       (vme->protection & VM_PROT_READ) ? 'r' : '-',
635 		       (vme->protection & VM_PROT_WRITE) ? 'w' : '-',
636 		       (vme->protection & VM_PROT_EXECUTE) ? 'x' : '-',
637 		       (vme->max_protection & VM_PROT_READ) ? 'r' : '-',
638 		       (vme->max_protection & VM_PROT_WRITE) ? 'w' : '-',
639 		       (vme->max_protection & VM_PROT_EXECUTE) ? 'x' : '-',
640 		       (vme->etype & UVM_ET_COPYONWRITE) ? "COW" : "NCOW",
641 		       (vme->etype & UVM_ET_NEEDSCOPY) ? "NC" : "NNC",
642 		       vme->inheritance, vme->wired_count,
643 		       vme->advice);
644 		if (verbose) {
645 			if (inode)
646 				printf(" %d,%d %d",
647 				       major(dev), minor(dev), inode);
648 			if (name[0])
649 				printf(" %s", name);
650 		}
651 		printf("\n");
652 	}
653 
654 	if (print_maps)
655 		printf("%0*lx-%0*lx %c%c%c%c %0*lx %02x:%02x %d     %s\n",
656 		       (int)sizeof(void *) * 2, vme->start,
657 		       (int)sizeof(void *) * 2, vme->end,
658 		       (vme->protection & VM_PROT_READ) ? 'r' : '-',
659 		       (vme->protection & VM_PROT_WRITE) ? 'w' : '-',
660 		       (vme->protection & VM_PROT_EXECUTE) ? 'x' : '-',
661 		       (vme->etype & UVM_ET_COPYONWRITE) ? 'p' : 's',
662 		       (int)sizeof(void *) * 2,
663 		       (unsigned long)vme->offset,
664 		       major(dev), minor(dev), inode, inode ? name : "");
665 
666 	if (print_ddb) {
667 		printf(" - %p: 0x%lx->0x%lx: obj=%p/0x%lx, amap=%p/%d\n",
668 		       P(vm_map_entry), vme->start, vme->end,
669 		       vme->object.uvm_obj, (unsigned long)vme->offset,
670 		       vme->aref.ar_amap, vme->aref.ar_pageoff);
671 		printf("\tsubmap=%c, cow=%c, nc=%c, prot(max)=%d/%d, inh=%d, "
672 		       "wc=%d, adv=%d\n",
673 		       (vme->etype & UVM_ET_SUBMAP) ? 'T' : 'F',
674 		       (vme->etype & UVM_ET_COPYONWRITE) ? 'T' : 'F',
675 		       (vme->etype & UVM_ET_NEEDSCOPY) ? 'T' : 'F',
676 		       vme->protection, vme->max_protection,
677 		       vme->inheritance, vme->wired_count, vme->advice);
678 		if (inode && verbose)
679 			printf("\t(dev=%d,%d ino=%d [%s] [%p])\n",
680 			       major(dev), minor(dev), inode,
681 			       inode ? name : "", P(vp));
682 		else if (name[0] == ' ' && verbose)
683 			printf("\t(%s)\n", &name[2]);
684 	}
685 
686 	sz = 0;
687 	if (print_solaris) {
688 		char prot[30];
689 
690 		prot[0] = '\0';
691 		prot[1] = '\0';
692 		if (vme->protection & VM_PROT_READ)
693 			strlcat(prot, "/read", sizeof(prot));
694 		if (vme->protection & VM_PROT_WRITE)
695 			strlcat(prot, "/write", sizeof(prot));
696 		if (vme->protection & VM_PROT_EXECUTE)
697 			strlcat(prot, "/exec", sizeof(prot));
698 
699 		sz = (size_t)((vme->end - vme->start) / 1024);
700 		printf("%0*lX %6luK %-15s   %s\n",
701 		       (int)sizeof(void *) * 2,
702 		       (unsigned long)vme->start,
703 		       (unsigned long)sz,
704 		       &prot[1],
705 		       name);
706 	}
707 
708 	if (print_all) {
709 		sz = (size_t)((vme->end - vme->start) / 1024);
710 		printf(A(vp) ?
711 		       "%0*lx-%0*lx %7luk %0*lx %c%c%c%c%c (%c%c%c) %d/%d/%d %02d:%02d %7d - %s [%p]\n" :
712 		       "%0*lx-%0*lx %7luk %0*lx %c%c%c%c%c (%c%c%c) %d/%d/%d %02d:%02d %7d - %s\n",
713 		       (int)sizeof(void *) * 2,
714 		       vme->start,
715 		       (int)sizeof(void *) * 2,
716 		       vme->end - (vme->start != vme->end ? 1 : 0),
717 		       (unsigned long)sz,
718 		       (int)sizeof(void *) * 2,
719 		       (unsigned long)vme->offset,
720 		       (vme->protection & VM_PROT_READ) ? 'r' : '-',
721 		       (vme->protection & VM_PROT_WRITE) ? 'w' : '-',
722 		       (vme->protection & VM_PROT_EXECUTE) ? 'x' : '-',
723 		       (vme->etype & UVM_ET_COPYONWRITE) ? 'p' : 's',
724 		       (vme->etype & UVM_ET_NEEDSCOPY) ? '+' : '-',
725 		       (vme->max_protection & VM_PROT_READ) ? 'r' : '-',
726 		       (vme->max_protection & VM_PROT_WRITE) ? 'w' : '-',
727 		       (vme->max_protection & VM_PROT_EXECUTE) ? 'x' : '-',
728 		       vme->inheritance,
729 		       vme->wired_count,
730 		       vme->advice,
731 		       major(dev), minor(dev), inode,
732 		       name, P(vp));
733 	}
734 
735 	/* no access allowed, don't count space */
736 	if ((vme->protection & rwx) == 0)
737 		sz = 0;
738 
739 	return (sz);
740 }
741 
742 char*
743 findname(kvm_t *kd, struct kbit *vmspace,
744 	 struct kbit *vm_map_entry, struct kbit *vp,
745 	 struct kbit *vfs, struct kbit *uvm_obj)
746 {
747 	static char buf[1024], *name;
748 	struct vm_map_entry *vme;
749 	size_t l;
750 
751 	vme = D(vm_map_entry, vm_map_entry);
752 
753 	if (UVM_ET_ISOBJ(vme)) {
754 		if (A(vfs)) {
755 			l = (unsigned)strlen(D(vfs, mount)->mnt_stat.f_mntonname);
756 			switch (search_cache(kd, vp, &name, buf, sizeof(buf))) {
757 			    case 0: /* found something */
758                                 name--;
759                                 *name = '/';
760 				/*FALLTHROUGH*/
761 			    case 2: /* found nothing */
762 				name -= 6;
763 				memcpy(name, " -??- ", (size_t)6);
764 				name -= l;
765 				memcpy(name,
766 				       D(vfs, mount)->mnt_stat.f_mntonname, l);
767 				break;
768 			    case 1: /* all is well */
769 				name--;
770 				*name = '/';
771 				if (l != 1) {
772 					name -= l;
773 					memcpy(name,
774 					       D(vfs, mount)->mnt_stat.f_mntonname, l);
775 				}
776 				break;
777 			}
778 		}
779 		else if (UVM_OBJ_IS_DEVICE(D(uvm_obj, uvm_object))) {
780 			struct kbit kdev;
781 			dev_t dev;
782 
783 			P(&kdev) = P(uvm_obj);
784 			S(&kdev) = sizeof(struct uvm_device);
785 			KDEREF(kd, &kdev);
786 			dev = D(&kdev, uvm_device)->u_device;
787 			name = devname(dev, S_IFCHR);
788 			if (name != NULL)
789 				snprintf(buf, sizeof(buf), "/dev/%s", name);
790 			else
791 				snprintf(buf, sizeof(buf), "  [ device %d,%d ]",
792 					 major(dev), minor(dev));
793 			name = buf;
794 		}
795 		else if (UVM_OBJ_IS_AOBJ(D(uvm_obj, uvm_object)))
796 			name = "  [ uvm_aobj ]";
797 #if 0
798 		else if (UVM_OBJ_IS_UBCPAGER(D(uvm_obj, uvm_object)))
799 			name = "  [ ubc_pager ]";
800 #endif
801 		else if (UVM_OBJ_IS_VNODE(D(uvm_obj, uvm_object)))
802 			name = "  [ ?VNODE? ]";
803 		else {
804 			snprintf(buf, sizeof(buf), "  [ ?? %p ?? ]",
805 				 D(uvm_obj, uvm_object)->pgops);
806 			name = buf;
807 		}
808 	}
809 
810 	else if (D(vmspace, vmspace)->vm_maxsaddr <=
811 		 (caddr_t)vme->start &&
812 		 (D(vmspace, vmspace)->vm_maxsaddr + (size_t)maxssiz) >=
813 		 (caddr_t)vme->end)
814 		name = "  [ stack ]";
815 
816 	else if ((vme->protection & rwx) == rwx && !heapfound) {
817 		/* XXX this could probably be done better */
818 		heapfound = 1;
819 		name = "  [ heap ]";
820 	}
821 
822 	else
823 		name = "  [ anon ]";
824 
825 	return (name);
826 }
827 
828 int
829 search_cache(kvm_t *kd, struct kbit *vp, char **name, char *buf, size_t blen)
830 {
831 	char *o, *e;
832 	struct cache_entry *ce;
833 	struct kbit svp;
834 	u_long cid;
835 
836 	if (nchashtbl == NULL)
837 		load_name_cache(kd);
838 
839 	P(&svp) = P(vp);
840 	S(&svp) = sizeof(struct vnode);
841 	cid = D(vp, vnode)->v_id;
842 
843 	e = &buf[blen - 1];
844 	o = e;
845 	do {
846 		LIST_FOREACH(ce, &lcache, ce_next)
847 			if (ce->ce_vp == P(&svp) && ce->ce_cid == cid)
848 				break;
849 		if (ce && ce->ce_vp == P(&svp) && ce->ce_cid == cid) {
850 			if (o != e)
851 				*(--o) = '/';
852 			o -= ce->ce_nlen;
853 			memcpy(o, ce->ce_name, (unsigned)ce->ce_nlen);
854 			P(&svp) = ce->ce_pvp;
855 			cid = ce->ce_pcid;
856 		}
857 		else
858 			break;
859 	} while (1/*CONSTCOND*/);
860 	*e = '\0';
861 	*name = o;
862 
863 	if (e == o)
864 		return (2);
865 
866 	KDEREF(kd, &svp);
867 	return (D(&svp, vnode)->v_flag & VROOT);
868 }
869 
870 void
871 load_name_cache(kvm_t *kd)
872 {
873 	struct namecache _ncp, *ncp, *oncp;
874 	struct nchashhead _ncpp, *ncpp;
875 	u_long nchash;
876 	int i;
877 
878 	LIST_INIT(&lcache);
879 
880 	_KDEREF(kd, nchash_addr, &nchash, sizeof(nchash));
881 	nchashtbl = malloc(sizeof(nchashtbl) * (int)nchash);
882 	if (nchashtbl == NULL)
883 		err(1, "load_name_cache");
884 	_KDEREF(kd, nchashtbl_addr, nchashtbl,
885 	    sizeof(nchashtbl) * (int)nchash);
886 
887 	ncpp = &_ncpp;
888 
889 	for (i = 0; i <= nchash; i++) {
890 		ncpp = &nchashtbl[i];
891 		oncp = NULL;
892 		LIST_FOREACH(ncp, ncpp, nc_hash) {
893 			if (ncp == oncp ||
894 			    (void*)ncp < kernel_floor ||
895 			    ncp == (void*)0xdeadbeef)
896 				break;
897 			oncp = ncp;
898 			_KDEREF(kd, (u_long)ncp, &_ncp, sizeof(*ncp));
899 			ncp = &_ncp;
900 			if ((void*)ncp->nc_vp > kernel_floor &&
901 			    ncp->nc_nlen > 0) {
902 				if (ncp->nc_nlen > 2 ||
903 				    ncp->nc_name[0] != '.' ||
904 				    (ncp->nc_name[1] != '.' &&
905 				     ncp->nc_nlen != 1))
906 					cache_enter(ncp);
907 			}
908 		}
909 	}
910 }
911 
912 void
913 cache_enter(struct namecache *ncp)
914 {
915 	struct cache_entry *ce;
916 
917 	if (debug & DUMP_NAMEI_CACHE)
918 		printf("ncp->nc_vp %10p, ncp->nc_dvp %10p, ncp->nc_nlen "
919 		       "%3d [%.*s] (nc_dvpid=%lu, nc_vpid=%lu)\n",
920 		       ncp->nc_vp, ncp->nc_dvp,
921 		       ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name,
922 		       ncp->nc_dvpid, ncp->nc_vpid);
923 
924 	ce = malloc(sizeof(struct cache_entry));
925 	if (ce == NULL)
926 		err(1, "cache_enter");
927 
928 	ce->ce_vp = ncp->nc_vp;
929 	ce->ce_pvp = ncp->nc_dvp;
930 	ce->ce_cid = ncp->nc_vpid;
931 	ce->ce_pcid = ncp->nc_dvpid;
932 	ce->ce_nlen = ncp->nc_nlen;
933 	strlcpy(ce->ce_name, ncp->nc_name, sizeof(ce->ce_name));
934 
935 	LIST_INSERT_HEAD(&lcache, ce, ce_next);
936 }
937 
938 static void __dead
939 usage(void)
940 {
941 	extern char *__progname;
942 	fprintf(stderr, "usage: %s [-adlmPsv] [-D number] "
943 	    "[-M core] [-N system] [-p pid] [pid ...]\n",
944 	    __progname);
945 	exit(1);
946 }
947