4 * cc -I/usr/src/sys vmobjinfo.c -o ~/bin/vmobjinfo -lkvm
6 * Dump all vm_object's in the system
8 * Copyright (c) 2010 The DragonFly Project. All rights reserved.
10 * This code is derived from software contributed to The DragonFly Project
11 * by Matthew Dillon <dillon@backplane.com>
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in
21 * the documentation and/or other materials provided with the
23 * 3. Neither the name of The DragonFly Project 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.
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
33 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
35 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
37 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 #define _KERNEL_STRUCTURES
42 #include <sys/param.h>
44 #include <sys/malloc.h>
45 #include <sys/signalvar.h>
46 #include <sys/namecache.h>
47 #include <sys/mount.h>
48 #include <sys/vnode.h>
52 #include <vm/vm_page.h>
53 #include <vm/vm_kern.h>
54 #include <vm/vm_object.h>
55 #include <vm/swap_pager.h>
56 #include <vm/vnode_pager.h>
58 #include <vfs/ufs/quota.h>
59 #include <vfs/ufs/inode.h>
69 TAILQ_HEAD(object_q, vm_object);
72 { "_vm_object_lists" },
83 char pgbuf[PAGE_SIZE];
85 static void scan_vmobjs(kvm_t *kd, struct object_q *obj_list);
86 static void dump_swap(kvm_t *kd, struct swblock *swbp);
87 static void dump_memq(kvm_t *kd, struct vm_page *pgp);
88 static void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes);
89 static off_t devoffset(long blkno, int *whichp);
92 main(int ac, char **av)
94 struct object_q obj_list[VMOBJ_HSIZE];
99 const char *corefile = NULL;
100 const char *sysfile = NULL;
102 while ((ch = getopt(ac, av, "M:N:v")) != -1) {
114 fprintf(stderr, "%s [-M core] [-N system]\n", av[0]);
118 if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) {
122 if (kvm_nlist(kd, Nl) != 0) {
126 kkread(kd, Nl[1].n_value, &nswdev, sizeof(nswdev));
127 kkread(kd, Nl[2].n_value, &dmmax, sizeof(dmmax));
130 swapfds = calloc(sizeof(int), nswdev);
131 for (i = 0; i < nswdev && i < ac - optind; ++i) {
132 printf("open %s\n", av[optind + i]);
133 swapfds[i] = open(av[optind + i], O_RDONLY);
139 memfds = open("/dev/mem", O_RDONLY);
142 kkread(kd, Nl[0].n_value, obj_list, sizeof(obj_list));
143 for (i = 0; i < VMOBJ_HSIZE; ++i)
144 scan_vmobjs(kd, &obj_list[i]);
149 scan_vmobjs(kvm_t *kd, struct object_q *obj_list)
151 struct vm_object *op;
152 struct vm_object obj;
154 op = TAILQ_FIRST(obj_list);
156 kkread(kd, (long)op, &obj, sizeof(obj));
158 printf("%p type=%d size=%016jx handle=%p swblocks=%d\n",
159 op, obj.type, (intmax_t)obj.size, obj.handle,
161 printf("\t\t ref_count=%d backing_obj=%p\n",
162 obj.ref_count, obj.backing_object);
165 dump_swap(kd, obj.swblock_root.rbh_root);
166 if (obj.type == OBJT_DEFAULT || obj.type == OBJT_SWAP)
167 dump_memq(kd, obj.rb_memq.rbh_root);
170 op = TAILQ_NEXT(&obj, object_list);
175 dump_swap(kvm_t *kd, struct swblock *swbp)
187 kkread(kd, (long)swbp, &swb, sizeof(swb));
188 dump_swap(kd, swb.swb_entry.rbe_left);
190 for (i = 0; i < SWAP_META_PAGES; ++i) {
191 printf(" %016lx: ", (swb.swb_index + i) * 4096L);
192 if (swb.swb_pages[i] == SWAPBLK_NONE) {
193 printf(" (unassigned)\n");
196 printf(" %ld\n", swb.swb_pages[i]);
197 off = devoffset(swb.swb_pages[i], &which);
198 if (swapfds[which] >= 0) {
199 lseek(swapfds[which], off, 0);
200 if (read(swapfds[which], pgbuf, sizeof(pgbuf)) <= 0)
201 printf("\t(read failed)\n");
203 for (j = 0; j < PAGE_SIZE; j += 16) {
204 printf("\t%04x ", j);
205 for (k = 0; k < 16; ++k) {
206 printf(" %02x", (uint8_t)pgbuf[j+k]);
211 for (k = 0; k < 16; ++k) {
212 if (isprint((uint8_t)pgbuf[j+k]))
213 printf("%c", pgbuf[j+k]);
222 dump_swap(kd, swb.swb_entry.rbe_right);
226 dump_memq(kvm_t *kd, struct vm_page *pgp)
234 kkread(kd, (long)pgp, &pg, sizeof(pg));
235 dump_memq(kd, pg.rb_entry.rbe_left);
236 printf(" %016lx: %016jx (physical)\n",
237 pg.pindex * 4096L, (intmax_t)pg.phys_addr);
238 lseek(memfds, pg.phys_addr, 0);
239 if (read(memfds, pgbuf, sizeof(pgbuf)) <= 0) {
240 printf("\t(read failed)\n");
242 for (j = 0; j < PAGE_SIZE; j += 16) {
243 printf("\t%04x ", j);
244 for (k = 0; k < 16; ++k) {
245 printf(" %02x", (uint8_t)pgbuf[j+k]);
250 for (k = 0; k < 16; ++k) {
251 if (isprint((uint8_t)pgbuf[j+k]))
252 printf("%c", pgbuf[j+k]);
260 dump_memq(kd, pg.rb_entry.rbe_right);
264 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes)
266 if (kvm_read(kd, addr, buf, nbytes) != nbytes) {
273 devoffset(long blkno, int *whichp)
281 *whichp = seg % nswdev;
283 off = (off_t)(seg * dmmax + off) << PAGE_SHIFT;
286 off = blkno * PAGE_SIZE;