1/*	$NetBSD: pmap.c,v 1.47 2011/10/11 12:25:56 tsutsui 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 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33#ifndef lint
34__RCSID("$NetBSD: pmap.c,v 1.47 2011/10/11 12:25:56 tsutsui Exp $");
35#endif
36
37#include <string.h>
38
39#include "pmap.h"
40#include "main.h"
41
42static void dump_vm_anon(kvm_t *, struct vm_anon **, int);
43static char *findname(kvm_t *, struct kbit *, struct kbit *, struct kbit *,
44	struct kbit *, struct kbit *);
45static int search_cache(kvm_t *, struct kbit *, char **, char *, size_t);
46
47/* when recursing, output is indented */
48#define indent(n) ((n) * (recurse > 1 ? recurse - 1 : 0))
49#define rwx (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
50
51int heapfound;
52
53void
54process_map(kvm_t *kd, struct kinfo_proc2 *proc,
55			      struct kbit *vmspace, const char *thing)
56{
57	struct kbit kbit, *vm_map = &kbit;
58
59	if (proc) {
60		heapfound = 0;
61		A(vmspace) = (u_long)proc->p_vmspace;
62		S(vmspace) = sizeof(struct vmspace);
63		thing = "proc->p_vmspace.vm_map";
64	} else if (S(vmspace) == (size_t)-1) {
65		heapfound = 0;
66		/* A(vmspace) set by caller */
67		S(vmspace) = sizeof(struct vmspace);
68		/* object identified by caller */
69	} else {
70		heapfound = 1; /* but really, do kernels have a heap? */
71		A(vmspace) = 0;
72		S(vmspace) = 0;
73		thing = "kernel_map";
74	}
75
76	S(vm_map) = sizeof(struct vm_map);
77
78	if (S(vmspace) != 0) {
79		KDEREF(kd, vmspace);
80		A(vm_map) = A(vmspace) + offsetof(struct vmspace, vm_map);
81		memcpy(D(vm_map, vm_map), &D(vmspace, vmspace)->vm_map,
82		       S(vm_map));
83	} else {
84		memset(vmspace, 0, sizeof(*vmspace));
85		A(vm_map) = kernel_map_addr;
86		KDEREF(kd, vm_map);
87	}
88
89	dump_vm_map(kd, proc, vmspace, vm_map, thing);
90}
91
92void
93dump_vm_map(kvm_t *kd, struct kinfo_proc2 *proc,
94	struct kbit *vmspace, struct kbit *vm_map, const char *mname)
95{
96	struct kbit kbit[2], *header, *vm_map_entry;
97	struct vm_map_entry *last, *next;
98	size_t total;
99	u_long addr, end;
100
101	if (S(vm_map) == (size_t)-1) {
102		heapfound = 1;
103		S(vm_map) = sizeof(struct vm_map);
104		KDEREF(kd, vm_map);
105	}
106
107	header = &kbit[0];
108	vm_map_entry = &kbit[1];
109	A(header) = 0;
110	A(vm_map_entry) = 0;
111
112	A(header) = A(vm_map) + offsetof(struct vm_map, header);
113	S(header) = sizeof(struct vm_map_entry);
114	memcpy(D(header, vm_map_entry), &D(vm_map, vm_map)->header, S(header));
115
116	if (S(vmspace) != 0 && (debug & PRINT_VMSPACE)) {
117		printf("proc->p_vmspace %p = {", P(vmspace));
118		printf(" vm_refcnt = %d,", D(vmspace, vmspace)->vm_refcnt);
119		printf(" vm_shm = %p,\n", D(vmspace, vmspace)->vm_shm);
120		printf("    vm_rssize = %d,", D(vmspace, vmspace)->vm_rssize);
121		printf(" vm_swrss = %d,", D(vmspace, vmspace)->vm_swrss);
122		printf(" vm_tsize = %d,", D(vmspace, vmspace)->vm_tsize);
123		printf(" vm_dsize = %d,\n", D(vmspace, vmspace)->vm_dsize);
124		printf("    vm_ssize = %d,", D(vmspace, vmspace)->vm_ssize);
125		printf(" vm_taddr = %p,", D(vmspace, vmspace)->vm_taddr);
126		printf(" vm_daddr = %p,\n", D(vmspace, vmspace)->vm_daddr);
127		printf("    vm_maxsaddr = %p,",
128		       D(vmspace, vmspace)->vm_maxsaddr);
129		printf(" vm_minsaddr = %p }\n",
130		       D(vmspace, vmspace)->vm_minsaddr);
131	}
132
133	if (debug & PRINT_VM_MAP) {
134		printf("%*s%s %p = {", indent(2), "", mname, P(vm_map));
135		printf(" pmap = %p,\n", D(vm_map, vm_map)->pmap);
136		printf("%*s    lock = <struct lock>,", indent(2), "");
137		printf(" header = <struct vm_map_entry>,");
138		printf(" nentries = %d,\n", D(vm_map, vm_map)->nentries);
139		printf("%*s    size = %#"PRIxVSIZE",", indent(2), "",
140		       D(vm_map, vm_map)->size);
141		printf(" ref_count = %d,", D(vm_map, vm_map)->ref_count);
142		printf("%*s    hint = %p,", indent(2), "",
143		       D(vm_map, vm_map)->hint);
144		printf("%*s    first_free = %p,", indent(2), "",
145		       D(vm_map, vm_map)->first_free);
146		printf(" flags = %x <%s%s%s%s%s >,\n", D(vm_map, vm_map)->flags,
147		       D(vm_map, vm_map)->flags & VM_MAP_PAGEABLE ? " PAGEABLE" : "",
148		       D(vm_map, vm_map)->flags & VM_MAP_INTRSAFE ? " INTRSAFE" : "",
149		       D(vm_map, vm_map)->flags & VM_MAP_WIREFUTURE ? " WIREFUTURE" : "",
150#ifdef VM_MAP_DYING
151		       D(vm_map, vm_map)->flags & VM_MAP_DYING ? " DYING" :
152#endif
153		       "",
154#ifdef VM_MAP_TOPDOWN
155		       D(vm_map, vm_map)->flags & VM_MAP_TOPDOWN ? " TOPDOWN" :
156#endif
157		       "");
158		printf("%*s    timestamp = %u }\n", indent(2), "",
159		     D(vm_map, vm_map)->timestamp);
160	}
161	if (print_ddb) {
162		const char *name = mapname(P(vm_map));
163
164		printf("%*s%s %p: [%#"PRIxVADDR"->%#"PRIxVADDR"]\n", indent(2), "",
165		       recurse < 2 ? "MAP" : "SUBMAP", P(vm_map),
166		       vm_map_min(D(vm_map, vm_map)),
167		       vm_map_max(D(vm_map, vm_map)));
168		printf("\t%*s#ent=%d, sz=%"PRIxVSIZE", ref=%d, version=%d, flags=0x%x\n",
169		       indent(2), "", D(vm_map, vm_map)->nentries,
170		       D(vm_map, vm_map)->size, D(vm_map, vm_map)->ref_count,
171		       D(vm_map, vm_map)->timestamp, D(vm_map, vm_map)->flags);
172		printf("\t%*spmap=%p(resident=<unknown>)\n", indent(2), "",
173		       D(vm_map, vm_map)->pmap);
174		if (verbose && name != NULL)
175			printf("\t%*s([ %s ])\n", indent(2), "", name);
176	}
177
178	dump_vm_map_entry(kd, proc, vmspace, header, 1);
179
180	/*
181	 * we're not recursing into a submap, so print headers
182	 */
183	if (recurse < 2) {
184		/* headers */
185#ifdef DISABLED_HEADERS
186		if (print_map)
187			printf("%-*s %-*s rwx RWX CPY NCP I W A\n",
188			       (int)sizeof(long) * 2 + 2, "Start",
189			       (int)sizeof(long) * 2 + 2, "End");
190		if (print_maps)
191			printf("%-*s %-*s rwxp %-*s Dev   Inode      File\n",
192			       (int)sizeof(long) * 2 + 0, "Start",
193			       (int)sizeof(long) * 2 + 0, "End",
194			       (int)sizeof(long) * 2 + 0, "Offset");
195		if (print_solaris)
196			printf("%-*s %*s Protection        File\n",
197			       (int)sizeof(long) * 2 + 0, "Start",
198			       (int)sizeof(int) * 2 - 1,  "Size ");
199#endif
200		if (print_all)
201			printf("%-*s %-*s %*s %-*s rwxpc  RWX  I/W/A Dev  %*s"
202			       " - File\n",
203			       (int)sizeof(long) * 2, "Start",
204			       (int)sizeof(long) * 2, "End",
205			       (int)sizeof(int)  * 2, "Size ",
206			       (int)sizeof(long) * 2, "Offset",
207			       (int)sizeof(int)  * 2, "Inode");
208	}
209
210	/* these are the "sub entries" */
211	total = 0;
212	next = D(header, vm_map_entry)->next;
213	last = P(header);
214	end = 0;
215
216	while (next != 0 && next != last) {
217		addr = (u_long)next;
218		A(vm_map_entry) = addr;
219		S(vm_map_entry) = sizeof(struct vm_map_entry);
220		KDEREF(kd, vm_map_entry);
221		next = D(vm_map_entry, vm_map_entry)->next;
222
223		if (end == 0)
224			end = D(vm_map_entry, vm_map_entry)->start;
225		else if (verbose > 1 &&
226		    end != D(vm_map_entry, vm_map_entry)->start)
227			printf("%*s[%lu pages / %luK]\n", indent(2), "",
228			       (D(vm_map_entry, vm_map_entry)->start - end) /
229			       page_size,
230			       (D(vm_map_entry, vm_map_entry)->start - end) /
231			       1024);
232		total += dump_vm_map_entry(kd, proc, vmspace, vm_map_entry, 0);
233
234		end = D(vm_map_entry, vm_map_entry)->end;
235	}
236
237	/*
238	 * we're not recursing into a submap, so print totals
239	 */
240	if (recurse < 2) {
241		if (print_solaris)
242			printf("%-*s %8luK\n",
243			       (int)sizeof(void *) * 2 - 2, " total",
244			       (unsigned long)total);
245		if (print_all)
246			printf("%-*s %9luk\n",
247			       (int)sizeof(void *) * 4 - 1, " total",
248			       (unsigned long)total);
249	}
250}
251
252size_t
253dump_vm_map_entry(kvm_t *kd, struct kinfo_proc2 *proc, struct kbit *vmspace,
254	struct kbit *vm_map_entry, int ishead)
255{
256	struct kbit kbit[3];
257	struct kbit *uvm_obj, *vp, *vfs;
258	struct vm_map_entry *vme;
259	size_t sz;
260	char *name;
261	dev_t dev;
262	ino_t inode;
263
264	if (S(vm_map_entry) == (size_t)-1) {
265		heapfound = 1;
266		S(vm_map_entry) = sizeof(struct vm_map_entry);
267		KDEREF(kd, vm_map_entry);
268	}
269
270	uvm_obj = &kbit[0];
271	vp = &kbit[1];
272	vfs = &kbit[2];
273
274	A(uvm_obj) = 0;
275	A(vp) = 0;
276	A(vfs) = 0;
277
278	vme = D(vm_map_entry, vm_map_entry);
279
280	if ((ishead && (debug & PRINT_VM_MAP_HEADER)) ||
281	    (!ishead && (debug & PRINT_VM_MAP_ENTRY))) {
282		printf("%*s%s %p = {", indent(2), "",
283		       ishead ? "vm_map.header" : "vm_map_entry",
284		       P(vm_map_entry));
285		printf(" prev = %p,", vme->prev);
286		printf(" next = %p,\n", vme->next);
287		printf("%*s    start = %#"PRIxVADDR",", indent(2), "", vme->start);
288		printf(" end = %#"PRIxVADDR",", vme->end);
289		printf(" object.uvm_obj/sub_map = %p,\n", vme->object.uvm_obj);
290		printf("%*s    offset = %" PRIx64 ",", indent(2), "",
291		       vme->offset);
292		printf(" etype = %x <%s%s%s%s >,", vme->etype,
293		       UVM_ET_ISOBJ(vme) ? " OBJ" : "",
294		       UVM_ET_ISSUBMAP(vme) ? " SUBMAP" : "",
295		       UVM_ET_ISCOPYONWRITE(vme) ? " COW" : "",
296		       UVM_ET_ISNEEDSCOPY(vme) ? " NEEDSCOPY" : "");
297		printf(" protection = %x,\n", vme->protection);
298		printf("%*s    max_protection = %x,", indent(2), "",
299		       vme->max_protection);
300		printf(" inheritance = %d,", vme->inheritance);
301		printf(" wired_count = %d,\n", vme->wired_count);
302		printf("%*s    aref = { ar_pageoff = %x, ar_amap = %p },",
303		       indent(2), "", vme->aref.ar_pageoff, vme->aref.ar_amap);
304		printf(" advice = %d,\n", vme->advice);
305		printf("%*s    flags = %x <%s%s%s%s > }\n", indent(2), "",
306		       vme->flags,
307		       vme->flags & UVM_MAP_KERNEL ? " KERNEL" : "",
308		       vme->flags & UVM_MAP_KMAPENT ? " KMAPENT" : "",
309		       vme->flags & UVM_MAP_STATIC ? " STATIC" : "",
310		       vme->flags & UVM_MAP_NOMERGE ? " NOMERGE" : "");
311	}
312
313	if ((debug & PRINT_VM_AMAP) && (vme->aref.ar_amap != NULL)) {
314		struct kbit akbit, *amap;
315
316		amap = &akbit;
317		P(amap) = vme->aref.ar_amap;
318		S(amap) = sizeof(struct vm_amap);
319		KDEREF(kd, amap);
320		dump_amap(kd, amap);
321	}
322
323	if (ishead)
324		return (0);
325
326	A(vp) = 0;
327	A(uvm_obj) = 0;
328
329	if (vme->object.uvm_obj != NULL) {
330		P(uvm_obj) = vme->object.uvm_obj;
331		S(uvm_obj) = sizeof(struct uvm_object);
332		KDEREF(kd, uvm_obj);
333		if (UVM_ET_ISOBJ(vme) &&
334		    UVM_OBJ_IS_VNODE(D(uvm_obj, uvm_object))) {
335			P(vp) = P(uvm_obj);
336			S(vp) = sizeof(struct vnode);
337			KDEREF(kd, vp);
338		}
339	}
340
341	A(vfs) = 0;
342
343	if (P(vp) != NULL && D(vp, vnode)->v_mount != NULL) {
344		P(vfs) = D(vp, vnode)->v_mount;
345		S(vfs) = sizeof(struct mount);
346		KDEREF(kd, vfs);
347		D(vp, vnode)->v_mount = D(vfs, mount);
348	}
349
350	/*
351	 * dig out the device number and inode number from certain
352	 * file system types.
353	 */
354#define V_DATA_IS(vp, type, d, i) do { \
355	struct kbit data; \
356	P(&data) = D(vp, vnode)->v_data; \
357	S(&data) = sizeof(*D(&data, type)); \
358	KDEREF(kd, &data); \
359	dev = D(&data, type)->d; \
360	inode = D(&data, type)->i; \
361} while (0/*CONSTCOND*/)
362
363	dev = 0;
364	inode = 0;
365
366	if (A(vp) &&
367	    D(vp, vnode)->v_type == VREG &&
368	    D(vp, vnode)->v_data != NULL) {
369		switch (D(vp, vnode)->v_tag) {
370		case VT_UFS:
371		case VT_LFS:
372		case VT_EXT2FS:
373			V_DATA_IS(vp, inode, i_dev, i_number);
374			break;
375		case VT_ISOFS:
376			V_DATA_IS(vp, iso_node, i_dev, i_number);
377			break;
378		default:
379			break;
380		}
381	}
382
383	name = findname(kd, vmspace, vm_map_entry, vp, vfs, uvm_obj);
384
385	if (print_map) {
386		printf("%*s%#"PRIxVADDR" %#"PRIxVADDR" %c%c%c %c%c%c %s %s %d %d %d",
387		       indent(2), "",
388		       vme->start, vme->end,
389		       (vme->protection & VM_PROT_READ) ? 'r' : '-',
390		       (vme->protection & VM_PROT_WRITE) ? 'w' : '-',
391		       (vme->protection & VM_PROT_EXECUTE) ? 'x' : '-',
392		       (vme->max_protection & VM_PROT_READ) ? 'r' : '-',
393		       (vme->max_protection & VM_PROT_WRITE) ? 'w' : '-',
394		       (vme->max_protection & VM_PROT_EXECUTE) ? 'x' : '-',
395		       UVM_ET_ISCOPYONWRITE(vme) ? "COW" : "NCOW",
396		       UVM_ET_ISNEEDSCOPY(vme) ? "NC" : "NNC",
397		       vme->inheritance, vme->wired_count,
398		       vme->advice);
399		if (verbose) {
400			if (inode)
401				printf(" %llu,%llu %llu",
402				    (unsigned long long)major(dev),
403				    (unsigned long long)minor(dev),
404				    (unsigned long long)inode);
405			if (name[0])
406				printf(" %s", name);
407		}
408		printf("\n");
409	}
410
411	if (print_maps) {
412		printf("%*s%0*"PRIxVADDR"-%0*"PRIxVADDR" %c%c%c%c %0*" PRIx64 " %02llx:%02llx %llu     %s\n",
413		       indent(2), "",
414		       (int)sizeof(void *) * 2, vme->start,
415		       (int)sizeof(void *) * 2, vme->end,
416		       (vme->protection & VM_PROT_READ) ? 'r' : '-',
417		       (vme->protection & VM_PROT_WRITE) ? 'w' : '-',
418		       (vme->protection & VM_PROT_EXECUTE) ? 'x' : '-',
419		       UVM_ET_ISCOPYONWRITE(vme) ? 'p' : 's',
420		       (int)sizeof(void *) * 2,
421		       vme->offset,
422		       (unsigned long long)major(dev),
423		       (unsigned long long)minor(dev),
424		       (unsigned long long)inode,
425		       (name[0] != ' ') || verbose ? name : "");
426	}
427
428	if (print_ddb) {
429		printf("%*s - %p: %#"PRIxVADDR"->%#"PRIxVADDR": obj=%p/0x%" PRIx64 ", amap=%p/%d\n",
430		       indent(2), "",
431		       P(vm_map_entry), vme->start, vme->end,
432		       vme->object.uvm_obj, vme->offset,
433		       vme->aref.ar_amap, vme->aref.ar_pageoff);
434		printf("\t%*ssubmap=%c, cow=%c, nc=%c, prot(max)=%d/%d, inh=%d, "
435		       "wc=%d, adv=%d\n",
436		       indent(2), "",
437		       UVM_ET_ISSUBMAP(vme) ? 'T' : 'F',
438		       UVM_ET_ISCOPYONWRITE(vme) ? 'T' : 'F',
439		       UVM_ET_ISNEEDSCOPY(vme) ? 'T' : 'F',
440		       vme->protection, vme->max_protection,
441		       vme->inheritance, vme->wired_count, vme->advice);
442		if (verbose) {
443			printf("\t%*s", indent(2), "");
444			if (inode)
445				printf("(dev=%llu,%llu ino=%llu [%s] [%p])\n",
446				    (unsigned long long)major(dev),
447				    (unsigned long long)minor(dev),
448				    (unsigned long long)inode, name, P(vp));
449			else if (name[0] == ' ')
450				printf("(%s)\n", &name[2]);
451			else
452				printf("(%s)\n", name);
453		}
454	}
455
456	sz = 0;
457	if (print_solaris) {
458		char prot[30];
459
460		prot[0] = '\0';
461		prot[1] = '\0';
462		if (vme->protection & VM_PROT_READ)
463			strlcat(prot, "/read", sizeof(prot));
464		if (vme->protection & VM_PROT_WRITE)
465			strlcat(prot, "/write", sizeof(prot));
466		if (vme->protection & VM_PROT_EXECUTE)
467			strlcat(prot, "/exec", sizeof(prot));
468
469		sz = (size_t)((vme->end - vme->start) / 1024);
470		printf("%*s%0*lX %6luK %-15s   %s\n",
471		       indent(2), "",
472		       (int)sizeof(void *) * 2,
473		       (unsigned long)vme->start,
474		       (unsigned long)sz,
475		       &prot[1],
476		       name);
477	}
478
479	if (print_all) {
480		sz = (size_t)((vme->end - vme->start) / 1024);
481		printf(A(vp) ?
482		       "%*s%0*"PRIxVADDR"-%0*"PRIxVADDR" %7luk %0*" PRIx64 " %c%c%c%c%c (%c%c%c) %d/%d/%d %02llu:%02llu %7llu - %s [%p]\n" :
483		       "%*s%0*"PRIxVADDR"-%0*"PRIxVADDR" %7luk %0*" PRIx64 " %c%c%c%c%c (%c%c%c) %d/%d/%d %02llu:%02llu %7llu - %s\n",
484		       indent(2), "",
485		       (int)sizeof(void *) * 2,
486		       vme->start,
487		       (int)sizeof(void *) * 2,
488		       vme->end - (vme->start != vme->end ? 1 : 0),
489		       (unsigned long)sz,
490		       (int)sizeof(void *) * 2,
491		       vme->offset,
492		       (vme->protection & VM_PROT_READ) ? 'r' : '-',
493		       (vme->protection & VM_PROT_WRITE) ? 'w' : '-',
494		       (vme->protection & VM_PROT_EXECUTE) ? 'x' : '-',
495		       UVM_ET_ISCOPYONWRITE(vme) ? 'p' : 's',
496		       UVM_ET_ISNEEDSCOPY(vme) ? '+' : '-',
497		       (vme->max_protection & VM_PROT_READ) ? 'r' : '-',
498		       (vme->max_protection & VM_PROT_WRITE) ? 'w' : '-',
499		       (vme->max_protection & VM_PROT_EXECUTE) ? 'x' : '-',
500		       vme->inheritance,
501		       vme->wired_count,
502		       vme->advice,
503		       (unsigned long long)major(dev),
504		       (unsigned long long)minor(dev),
505		       (unsigned long long)inode,
506		       name, P(vp));
507	}
508
509	/* no access allowed, don't count space */
510	if ((vme->protection & rwx) == 0)
511		sz = 0;
512
513	if (recurse && UVM_ET_ISSUBMAP(vme)) {
514		struct kbit mkbit, *submap;
515
516		recurse++;
517		submap = &mkbit;
518		P(submap) = vme->object.sub_map;
519		S(submap) = sizeof(*vme->object.sub_map);
520		KDEREF(kd, submap);
521		dump_vm_map(kd, proc, vmspace, submap, "submap");
522		recurse--;
523	}
524
525	return (sz);
526}
527
528void
529dump_amap(kvm_t *kd, struct kbit *amap)
530{
531	struct vm_anon **am_anon;
532	int *am_slots;
533	int *am_bckptr;
534	int *am_ppref;
535	size_t l;
536	int i, r, 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, 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
643static void
644dump_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 = %"PRIuPTR", 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
669static char*
670findname(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 %llu,%llu ]",
719				     (unsigned long long)major(dev),
720				     (unsigned long long)minor(dev));
721			name = buf;
722		}
723		else if (UVM_OBJ_IS_AOBJ(D(uvm_obj, uvm_object))) {
724			snprintf(buf, sizeof(buf), "  [ uvm_aobj ]");
725			name = buf;
726		}
727		else if (UVM_OBJ_IS_UBCPAGER(D(uvm_obj, uvm_object))) {
728			snprintf(buf, sizeof(buf), "  [ ubc_pager ]");
729			name = buf;
730		}
731		else if (UVM_OBJ_IS_VNODE(D(uvm_obj, uvm_object))) {
732			snprintf(buf, sizeof(buf), "  [ ?VNODE? ]");
733			name = buf;
734		}
735		else {
736			snprintf(buf, sizeof(buf), "  [ ?? %p ?? ]",
737				 D(uvm_obj, uvm_object)->pgops);
738			name = buf;
739		}
740	}
741
742	else if ((char *)D(vmspace, vmspace)->vm_maxsaddr <=
743		 (char *)vme->start &&
744		 ((char *)D(vmspace, vmspace)->vm_maxsaddr + (size_t)maxssiz) >=
745		 (char *)vme->end) {
746		snprintf(buf, sizeof(buf), "  [ stack ]");
747		name = buf;
748	}
749
750	else if (!heapfound &&
751		 (vme->protection & rwx) == rwx &&
752		 vme->start >= (u_long)D(vmspace, vmspace)->vm_daddr) {
753		heapfound = 1;
754		snprintf(buf, sizeof(buf), "  [ heap ]");
755		name = buf;
756	}
757
758	else if (UVM_ET_ISSUBMAP(vme)) {
759		const char *sub = mapname(vme->object.sub_map);
760		snprintf(buf, sizeof(buf), "  [ %s ]", sub ? sub : "(submap)");
761		name = buf;
762	}
763
764	else {
765		snprintf(buf, sizeof(buf), "  [ anon ]");
766		name = buf;
767	}
768
769	return (name);
770}
771
772static int
773search_cache(kvm_t *kd, struct kbit *vp, char **name, char *buf, size_t blen)
774{
775	char *o, *e;
776	struct cache_entry *ce;
777	struct kbit svp;
778
779	if (nchashtbl == NULL)
780		load_name_cache(kd);
781
782	P(&svp) = P(vp);
783	S(&svp) = sizeof(struct vnode);
784
785	e = &buf[blen - 1];
786	o = e;
787	do {
788		LIST_FOREACH(ce, &lcache, ce_next)
789			if (ce->ce_vp == P(&svp))
790				break;
791		if (ce && ce->ce_vp == P(&svp)) {
792			if (o != e)
793				*(--o) = '/';
794			o -= ce->ce_nlen;
795			memcpy(o, ce->ce_name, (unsigned)ce->ce_nlen);
796			P(&svp) = ce->ce_pvp;
797		}
798		else
799			break;
800	} while (1/*CONSTCOND*/);
801	*e = '\0';
802	*name = o;
803
804	if (e == o)
805		return (2);
806
807	KDEREF(kd, &svp);
808	return (D(&svp, vnode)->v_vflag & VV_ROOT);
809}
810