xref: /dflybsd-src/test/debug/vmobjinfo.c (revision 8835adf8d6f12ed2e2bc71c55e928e81ae0339c0)
137ab3e78SMatthew Dillon /*
237ab3e78SMatthew Dillon  * VMOBJINFO.C
337ab3e78SMatthew Dillon  *
4fe18a9daSMatthew Dillon  * cc -I/usr/src/sys vmobjinfo.c -o ~/bin/vmobjinfo -lkvm
537ab3e78SMatthew Dillon  *
637ab3e78SMatthew Dillon  * Dump all vm_object's in the system
737ab3e78SMatthew Dillon  *
837ab3e78SMatthew Dillon  * Copyright (c) 2010 The DragonFly Project.  All rights reserved.
937ab3e78SMatthew Dillon  *
1037ab3e78SMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
1137ab3e78SMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
1237ab3e78SMatthew Dillon  *
1337ab3e78SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
1437ab3e78SMatthew Dillon  * modification, are permitted provided that the following conditions
1537ab3e78SMatthew Dillon  * are met:
1637ab3e78SMatthew Dillon  *
1737ab3e78SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
1837ab3e78SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
1937ab3e78SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
2037ab3e78SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
2137ab3e78SMatthew Dillon  *    the documentation and/or other materials provided with the
2237ab3e78SMatthew Dillon  *    distribution.
2337ab3e78SMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
2437ab3e78SMatthew Dillon  *    contributors may be used to endorse or promote products derived
2537ab3e78SMatthew Dillon  *    from this software without specific, prior written permission.
2637ab3e78SMatthew Dillon  *
2737ab3e78SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2837ab3e78SMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2937ab3e78SMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
3037ab3e78SMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
3137ab3e78SMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
3237ab3e78SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
3337ab3e78SMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
3437ab3e78SMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
3537ab3e78SMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3637ab3e78SMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3737ab3e78SMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3837ab3e78SMatthew Dillon  * SUCH DAMAGE.
3937ab3e78SMatthew Dillon  */
4037ab3e78SMatthew Dillon 
4137ab3e78SMatthew Dillon #define _KERNEL_STRUCTURES
4237ab3e78SMatthew Dillon #include <sys/param.h>
4337ab3e78SMatthew Dillon #include <sys/user.h>
4437ab3e78SMatthew Dillon #include <sys/malloc.h>
4537ab3e78SMatthew Dillon #include <sys/signalvar.h>
4637ab3e78SMatthew Dillon #include <sys/namecache.h>
4737ab3e78SMatthew Dillon #include <sys/mount.h>
4837ab3e78SMatthew Dillon #include <sys/vnode.h>
4937ab3e78SMatthew Dillon #include <sys/buf.h>
5037ab3e78SMatthew Dillon 
5137ab3e78SMatthew Dillon #include <vm/vm.h>
5237ab3e78SMatthew Dillon #include <vm/vm_page.h>
5337ab3e78SMatthew Dillon #include <vm/vm_kern.h>
5437ab3e78SMatthew Dillon #include <vm/vm_object.h>
5537ab3e78SMatthew Dillon #include <vm/swap_pager.h>
5637ab3e78SMatthew Dillon #include <vm/vnode_pager.h>
5737ab3e78SMatthew Dillon 
5837ab3e78SMatthew Dillon #include <vfs/ufs/quota.h>
5937ab3e78SMatthew Dillon #include <vfs/ufs/inode.h>
6037ab3e78SMatthew Dillon 
6137ab3e78SMatthew Dillon #include <stdio.h>
6237ab3e78SMatthew Dillon #include <stdlib.h>
6337ab3e78SMatthew Dillon #include <string.h>
6437ab3e78SMatthew Dillon #include <fcntl.h>
6537ab3e78SMatthew Dillon #include <kvm.h>
6637ab3e78SMatthew Dillon #include <nlist.h>
6737ab3e78SMatthew Dillon #include <getopt.h>
68*8835adf8SMatthew Dillon #include <ctype.h>
6937ab3e78SMatthew Dillon 
7037ab3e78SMatthew Dillon TAILQ_HEAD(object_q, vm_object);
7137ab3e78SMatthew Dillon 
7237ab3e78SMatthew Dillon struct nlist Nl[] = {
73fe18a9daSMatthew Dillon     { "_vm_object_lists" },
74fe18a9daSMatthew Dillon     { "_nswdev" },
75fe18a9daSMatthew Dillon     { "_dmmax" },
7637ab3e78SMatthew Dillon     { NULL }
7737ab3e78SMatthew Dillon };
7837ab3e78SMatthew Dillon 
79fe18a9daSMatthew Dillon int VerboseOpt;
80fe18a9daSMatthew Dillon int nswdev;
81fe18a9daSMatthew Dillon int dmmax;
82fe18a9daSMatthew Dillon int memfds = -1;
83fe18a9daSMatthew Dillon int *swapfds;
84fe18a9daSMatthew Dillon char pgbuf[PAGE_SIZE];
85fe18a9daSMatthew Dillon 
8637ab3e78SMatthew Dillon static void scan_vmobjs(kvm_t *kd, struct object_q *obj_list);
87fe18a9daSMatthew Dillon static void dump_swap(kvm_t *kd, struct swblock *swbp);
88fe18a9daSMatthew Dillon static void dump_memq(kvm_t *kd, struct vm_page *pgp);
8937ab3e78SMatthew Dillon static void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes);
90fe18a9daSMatthew Dillon static off_t devoffset(long blkno, int *whichp);
9137ab3e78SMatthew Dillon 
9237ab3e78SMatthew Dillon int
main(int ac,char ** av)9337ab3e78SMatthew Dillon main(int ac, char **av)
9437ab3e78SMatthew Dillon {
95fe18a9daSMatthew Dillon     struct object_q obj_list[VMOBJ_HSIZE];
9637ab3e78SMatthew Dillon     kvm_t *kd;
9737ab3e78SMatthew Dillon     int i;
98fe18a9daSMatthew Dillon     int nswap;
9937ab3e78SMatthew Dillon     int ch;
10037ab3e78SMatthew Dillon     const char *corefile = NULL;
10137ab3e78SMatthew Dillon     const char *sysfile = NULL;
10237ab3e78SMatthew Dillon 
103fe18a9daSMatthew Dillon     while ((ch = getopt(ac, av, "M:N:v")) != -1) {
10437ab3e78SMatthew Dillon 	switch(ch) {
10537ab3e78SMatthew Dillon 	case 'M':
10637ab3e78SMatthew Dillon 	    corefile = optarg;
10737ab3e78SMatthew Dillon 	    break;
10837ab3e78SMatthew Dillon 	case 'N':
10937ab3e78SMatthew Dillon 	    sysfile = optarg;
11037ab3e78SMatthew Dillon 	    break;
111fe18a9daSMatthew Dillon 	case 'v':
112fe18a9daSMatthew Dillon 	    ++VerboseOpt;
113fe18a9daSMatthew Dillon 	    break;
11437ab3e78SMatthew Dillon 	default:
11537ab3e78SMatthew Dillon 	    fprintf(stderr, "%s [-M core] [-N system]\n", av[0]);
11637ab3e78SMatthew Dillon 	    exit(1);
11737ab3e78SMatthew Dillon 	}
11837ab3e78SMatthew Dillon     }
11937ab3e78SMatthew Dillon     if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) {
12037ab3e78SMatthew Dillon 	perror("kvm_open");
12137ab3e78SMatthew Dillon 	exit(1);
12237ab3e78SMatthew Dillon     }
12337ab3e78SMatthew Dillon     if (kvm_nlist(kd, Nl) != 0) {
12437ab3e78SMatthew Dillon 	perror("kvm_nlist");
12537ab3e78SMatthew Dillon 	exit(1);
12637ab3e78SMatthew Dillon     }
127fe18a9daSMatthew Dillon     kkread(kd, Nl[1].n_value, &nswdev, sizeof(nswdev));
128fe18a9daSMatthew Dillon     kkread(kd, Nl[2].n_value, &dmmax, sizeof(dmmax));
129fe18a9daSMatthew Dillon 
130fe18a9daSMatthew Dillon     if (VerboseOpt) {
131fe18a9daSMatthew Dillon 	swapfds = calloc(sizeof(int), nswdev);
132fe18a9daSMatthew Dillon 	for (i = 0; i < nswdev && i < ac - optind; ++i) {
133fe18a9daSMatthew Dillon 		printf("open %s\n", av[optind + i]);
134fe18a9daSMatthew Dillon 		swapfds[i] = open(av[optind + i], O_RDONLY);
135fe18a9daSMatthew Dillon 	}
136fe18a9daSMatthew Dillon 	while (i < nswdev) {
137fe18a9daSMatthew Dillon 		swapfds[i] = -1;
138fe18a9daSMatthew Dillon 		++i;
139fe18a9daSMatthew Dillon 	}
140fe18a9daSMatthew Dillon 	memfds = open("/dev/mem", O_RDONLY);
141fe18a9daSMatthew Dillon     }
142fe18a9daSMatthew Dillon 
143fe18a9daSMatthew Dillon     kkread(kd, Nl[0].n_value, obj_list, sizeof(obj_list));
144fe18a9daSMatthew Dillon     for (i = 0; i < VMOBJ_HSIZE; ++i)
145fe18a9daSMatthew Dillon 	    scan_vmobjs(kd, &obj_list[i]);
14637ab3e78SMatthew Dillon     return(0);
14737ab3e78SMatthew Dillon }
14837ab3e78SMatthew Dillon 
14937ab3e78SMatthew Dillon static void
scan_vmobjs(kvm_t * kd,struct object_q * obj_list)15037ab3e78SMatthew Dillon scan_vmobjs(kvm_t *kd, struct object_q *obj_list)
15137ab3e78SMatthew Dillon {
15237ab3e78SMatthew Dillon     struct vm_object *op;
15337ab3e78SMatthew Dillon     struct vm_object obj;
15437ab3e78SMatthew Dillon 
15537ab3e78SMatthew Dillon     op = TAILQ_FIRST(obj_list);
15637ab3e78SMatthew Dillon     while (op) {
15737ab3e78SMatthew Dillon 	kkread(kd, (long)op, &obj, sizeof(obj));
15837ab3e78SMatthew Dillon 
15937ab3e78SMatthew Dillon 	printf("%p type=%d size=%016jx handle=%p swblocks=%d\n",
16037ab3e78SMatthew Dillon 		op, obj.type, (intmax_t)obj.size, obj.handle,
16137ab3e78SMatthew Dillon 		obj.swblock_count);
162fe18a9daSMatthew Dillon 	printf("\t\t   ref_count=%d backing_obj=%p\n",
163fe18a9daSMatthew Dillon 		obj.ref_count, obj.backing_object);
164fe18a9daSMatthew Dillon 
165fe18a9daSMatthew Dillon 	if (VerboseOpt) {
166fe18a9daSMatthew Dillon 		dump_swap(kd, obj.swblock_root.rbh_root);
167fe18a9daSMatthew Dillon 		if (obj.type == OBJT_DEFAULT || obj.type == OBJT_SWAP)
168fe18a9daSMatthew Dillon 			dump_memq(kd, obj.rb_memq.rbh_root);
169fe18a9daSMatthew Dillon 	}
17037ab3e78SMatthew Dillon 
17137ab3e78SMatthew Dillon 	op = TAILQ_NEXT(&obj, object_list);
17237ab3e78SMatthew Dillon     }
17337ab3e78SMatthew Dillon }
17437ab3e78SMatthew Dillon 
17537ab3e78SMatthew Dillon static void
dump_swap(kvm_t * kd,struct swblock * swbp)176fe18a9daSMatthew Dillon dump_swap(kvm_t *kd, struct swblock *swbp)
177fe18a9daSMatthew Dillon {
178fe18a9daSMatthew Dillon 	struct swblock swb;
179fe18a9daSMatthew Dillon 	int which;
180fe18a9daSMatthew Dillon 	int i;
181fe18a9daSMatthew Dillon 	int j;
182fe18a9daSMatthew Dillon 	int k;
183fe18a9daSMatthew Dillon 	int fd;
184fe18a9daSMatthew Dillon 	off_t off;
185fe18a9daSMatthew Dillon 
186fe18a9daSMatthew Dillon 	if (swbp == NULL)
187fe18a9daSMatthew Dillon 		return;
188fe18a9daSMatthew Dillon 	kkread(kd, (long)swbp, &swb, sizeof(swb));
189fe18a9daSMatthew Dillon 	dump_swap(kd, swb.swb_entry.rbe_left);
190fe18a9daSMatthew Dillon 
191fe18a9daSMatthew Dillon 	for (i = 0; i < SWAP_META_PAGES; ++i) {
192fe18a9daSMatthew Dillon 		printf("    %016lx: ", (swb.swb_index + i) * 4096L);
193fe18a9daSMatthew Dillon 		if (swb.swb_pages[i] == SWAPBLK_NONE) {
194fe18a9daSMatthew Dillon 			printf(" (unassigned)\n");
195fe18a9daSMatthew Dillon 			continue;
196fe18a9daSMatthew Dillon 		}
197fe18a9daSMatthew Dillon 		printf(" %ld\n", swb.swb_pages[i]);
198fe18a9daSMatthew Dillon 		off = devoffset(swb.swb_pages[i], &which);
199fe18a9daSMatthew Dillon 		if (swapfds[which] >= 0) {
200fe18a9daSMatthew Dillon 			lseek(swapfds[which], off, 0);
201fe18a9daSMatthew Dillon 			if (read(swapfds[which], pgbuf, sizeof(pgbuf)) <= 0)
202fe18a9daSMatthew Dillon 				printf("\t(read failed)\n");
203fe18a9daSMatthew Dillon 			else
204fe18a9daSMatthew Dillon 			for (j = 0; j < PAGE_SIZE; j += 16) {
205fe18a9daSMatthew Dillon 				printf("\t%04x ", j);
206fe18a9daSMatthew Dillon 				for (k = 0; k < 16; ++k) {
207fe18a9daSMatthew Dillon 					printf(" %02x", (uint8_t)pgbuf[j+k]);
208fe18a9daSMatthew Dillon 					if (k == 7)
209fe18a9daSMatthew Dillon 						printf(" ");
210fe18a9daSMatthew Dillon 				}
211fe18a9daSMatthew Dillon 				printf("  ");
212fe18a9daSMatthew Dillon 				for (k = 0; k < 16; ++k) {
213fe18a9daSMatthew Dillon 					if (isprint((uint8_t)pgbuf[j+k]))
214fe18a9daSMatthew Dillon 						printf("%c", pgbuf[j+k]);
215fe18a9daSMatthew Dillon 					else
216fe18a9daSMatthew Dillon 						printf(".");
217fe18a9daSMatthew Dillon 				}
218fe18a9daSMatthew Dillon 				printf("\n");
219fe18a9daSMatthew Dillon 			}
220fe18a9daSMatthew Dillon 		}
221fe18a9daSMatthew Dillon 	}
222fe18a9daSMatthew Dillon 
223fe18a9daSMatthew Dillon 	dump_swap(kd, swb.swb_entry.rbe_right);
224fe18a9daSMatthew Dillon }
225fe18a9daSMatthew Dillon 
226fe18a9daSMatthew Dillon static void
dump_memq(kvm_t * kd,struct vm_page * pgp)227fe18a9daSMatthew Dillon dump_memq(kvm_t *kd, struct vm_page *pgp)
228fe18a9daSMatthew Dillon {
229fe18a9daSMatthew Dillon 	struct vm_page pg;
230fe18a9daSMatthew Dillon 	int j;
231fe18a9daSMatthew Dillon 	int k;
232fe18a9daSMatthew Dillon 
233fe18a9daSMatthew Dillon 	if (pgp == NULL)
234fe18a9daSMatthew Dillon 		return;
235fe18a9daSMatthew Dillon 	kkread(kd, (long)pgp, &pg, sizeof(pg));
236fe18a9daSMatthew Dillon 	dump_memq(kd, pg.rb_entry.rbe_left);
237fe18a9daSMatthew Dillon 	printf("    %016lx: %016jx (physical)\n",
238fe18a9daSMatthew Dillon 	       pg.pindex * 4096L, (intmax_t)pg.phys_addr);
239fe18a9daSMatthew Dillon 	lseek(memfds, pg.phys_addr, 0);
240fe18a9daSMatthew Dillon 	if (read(memfds, pgbuf, sizeof(pgbuf)) <= 0) {
241fe18a9daSMatthew Dillon 		printf("\t(read failed)\n");
242fe18a9daSMatthew Dillon 	} else {
243fe18a9daSMatthew Dillon 		for (j = 0; j < PAGE_SIZE; j += 16) {
244fe18a9daSMatthew Dillon 			printf("\t%04x ", j);
245fe18a9daSMatthew Dillon 			for (k = 0; k < 16; ++k) {
246fe18a9daSMatthew Dillon 				printf(" %02x", (uint8_t)pgbuf[j+k]);
247fe18a9daSMatthew Dillon 				if (k == 7)
248fe18a9daSMatthew Dillon 					printf(" ");
249fe18a9daSMatthew Dillon 			}
250fe18a9daSMatthew Dillon 			printf("  ");
251fe18a9daSMatthew Dillon 			for (k = 0; k < 16; ++k) {
252fe18a9daSMatthew Dillon 				if (isprint((uint8_t)pgbuf[j+k]))
253fe18a9daSMatthew Dillon 					printf("%c", pgbuf[j+k]);
254fe18a9daSMatthew Dillon 				else
255fe18a9daSMatthew Dillon 					printf(".");
256fe18a9daSMatthew Dillon 			}
257fe18a9daSMatthew Dillon 			printf("\n");
258fe18a9daSMatthew Dillon 		}
259fe18a9daSMatthew Dillon 	}
260fe18a9daSMatthew Dillon 
261fe18a9daSMatthew Dillon 	dump_memq(kd, pg.rb_entry.rbe_right);
262fe18a9daSMatthew Dillon }
263fe18a9daSMatthew Dillon 
264fe18a9daSMatthew Dillon static void
kkread(kvm_t * kd,u_long addr,void * buf,size_t nbytes)26537ab3e78SMatthew Dillon kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes)
26637ab3e78SMatthew Dillon {
26737ab3e78SMatthew Dillon     if (kvm_read(kd, addr, buf, nbytes) != nbytes) {
26837ab3e78SMatthew Dillon         perror("kvm_read");
26937ab3e78SMatthew Dillon         exit(1);
27037ab3e78SMatthew Dillon     }
27137ab3e78SMatthew Dillon }
272fe18a9daSMatthew Dillon 
273fe18a9daSMatthew Dillon static off_t
devoffset(long blkno,int * whichp)274fe18a9daSMatthew Dillon devoffset(long blkno, int *whichp)
275fe18a9daSMatthew Dillon {
276fe18a9daSMatthew Dillon 	off_t off;
277fe18a9daSMatthew Dillon 	long seg;
278fe18a9daSMatthew Dillon 
279fe18a9daSMatthew Dillon 	if (nswdev > 1) {
280fe18a9daSMatthew Dillon 		off = blkno % dmmax;
281fe18a9daSMatthew Dillon 		seg = blkno / dmmax;
282fe18a9daSMatthew Dillon 		*whichp = seg % nswdev;
283fe18a9daSMatthew Dillon 		seg /= nswdev;
284fe18a9daSMatthew Dillon 		off = (off_t)(seg * dmmax + off) << PAGE_SHIFT;
285fe18a9daSMatthew Dillon 	} else {
286fe18a9daSMatthew Dillon 		*whichp = 0;
287fe18a9daSMatthew Dillon 		off = blkno * PAGE_SIZE;
288fe18a9daSMatthew Dillon 	}
289fe18a9daSMatthew Dillon }
290