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>
70 TAILQ_HEAD(object_q
, vm_object
);
73 { "_vm_object_lists" },
84 char pgbuf
[PAGE_SIZE
];
86 static void scan_vmobjs(kvm_t
*kd
, struct object_q
*obj_list
);
87 static void dump_swap(kvm_t
*kd
, struct swblock
*swbp
);
88 static void dump_memq(kvm_t
*kd
, struct vm_page
*pgp
);
89 static void kkread(kvm_t
*kd
, u_long addr
, void *buf
, size_t nbytes
);
90 static off_t
devoffset(long blkno
, int *whichp
);
93 main(int ac
, char **av
)
95 struct object_q obj_list
[VMOBJ_HSIZE
];
100 const char *corefile
= NULL
;
101 const char *sysfile
= NULL
;
103 while ((ch
= getopt(ac
, av
, "M:N:v")) != -1) {
115 fprintf(stderr
, "%s [-M core] [-N system]\n", av
[0]);
119 if ((kd
= kvm_open(sysfile
, corefile
, NULL
, O_RDONLY
, "kvm:")) == NULL
) {
123 if (kvm_nlist(kd
, Nl
) != 0) {
127 kkread(kd
, Nl
[1].n_value
, &nswdev
, sizeof(nswdev
));
128 kkread(kd
, Nl
[2].n_value
, &dmmax
, sizeof(dmmax
));
131 swapfds
= calloc(sizeof(int), nswdev
);
132 for (i
= 0; i
< nswdev
&& i
< ac
- optind
; ++i
) {
133 printf("open %s\n", av
[optind
+ i
]);
134 swapfds
[i
] = open(av
[optind
+ i
], O_RDONLY
);
140 memfds
= open("/dev/mem", O_RDONLY
);
143 kkread(kd
, Nl
[0].n_value
, obj_list
, sizeof(obj_list
));
144 for (i
= 0; i
< VMOBJ_HSIZE
; ++i
)
145 scan_vmobjs(kd
, &obj_list
[i
]);
150 scan_vmobjs(kvm_t
*kd
, struct object_q
*obj_list
)
152 struct vm_object
*op
;
153 struct vm_object obj
;
155 op
= TAILQ_FIRST(obj_list
);
157 kkread(kd
, (long)op
, &obj
, sizeof(obj
));
159 printf("%p type=%d size=%016jx handle=%p swblocks=%d\n",
160 op
, obj
.type
, (intmax_t)obj
.size
, obj
.handle
,
162 printf("\t\t ref_count=%d backing_obj=%p\n",
163 obj
.ref_count
, obj
.backing_object
);
166 dump_swap(kd
, obj
.swblock_root
.rbh_root
);
167 if (obj
.type
== OBJT_DEFAULT
|| obj
.type
== OBJT_SWAP
)
168 dump_memq(kd
, obj
.rb_memq
.rbh_root
);
171 op
= TAILQ_NEXT(&obj
, object_list
);
176 dump_swap(kvm_t
*kd
, struct swblock
*swbp
)
188 kkread(kd
, (long)swbp
, &swb
, sizeof(swb
));
189 dump_swap(kd
, swb
.swb_entry
.rbe_left
);
191 for (i
= 0; i
< SWAP_META_PAGES
; ++i
) {
192 printf(" %016lx: ", (swb
.swb_index
+ i
) * 4096L);
193 if (swb
.swb_pages
[i
] == SWAPBLK_NONE
) {
194 printf(" (unassigned)\n");
197 printf(" %ld\n", swb
.swb_pages
[i
]);
198 off
= devoffset(swb
.swb_pages
[i
], &which
);
199 if (swapfds
[which
] >= 0) {
200 lseek(swapfds
[which
], off
, 0);
201 if (read(swapfds
[which
], pgbuf
, sizeof(pgbuf
)) <= 0)
202 printf("\t(read failed)\n");
204 for (j
= 0; j
< PAGE_SIZE
; j
+= 16) {
205 printf("\t%04x ", j
);
206 for (k
= 0; k
< 16; ++k
) {
207 printf(" %02x", (uint8_t)pgbuf
[j
+k
]);
212 for (k
= 0; k
< 16; ++k
) {
213 if (isprint((uint8_t)pgbuf
[j
+k
]))
214 printf("%c", pgbuf
[j
+k
]);
223 dump_swap(kd
, swb
.swb_entry
.rbe_right
);
227 dump_memq(kvm_t
*kd
, struct vm_page
*pgp
)
235 kkread(kd
, (long)pgp
, &pg
, sizeof(pg
));
236 dump_memq(kd
, pg
.rb_entry
.rbe_left
);
237 printf(" %016lx: %016jx (physical)\n",
238 pg
.pindex
* 4096L, (intmax_t)pg
.phys_addr
);
239 lseek(memfds
, pg
.phys_addr
, 0);
240 if (read(memfds
, pgbuf
, sizeof(pgbuf
)) <= 0) {
241 printf("\t(read failed)\n");
243 for (j
= 0; j
< PAGE_SIZE
; j
+= 16) {
244 printf("\t%04x ", j
);
245 for (k
= 0; k
< 16; ++k
) {
246 printf(" %02x", (uint8_t)pgbuf
[j
+k
]);
251 for (k
= 0; k
< 16; ++k
) {
252 if (isprint((uint8_t)pgbuf
[j
+k
]))
253 printf("%c", pgbuf
[j
+k
]);
261 dump_memq(kd
, pg
.rb_entry
.rbe_right
);
265 kkread(kvm_t
*kd
, u_long addr
, void *buf
, size_t nbytes
)
267 if (kvm_read(kd
, addr
, buf
, nbytes
) != nbytes
) {
274 devoffset(long blkno
, int *whichp
)
282 *whichp
= seg
% nswdev
;
284 off
= (off_t
)(seg
* dmmax
+ off
) << PAGE_SHIFT
;
287 off
= blkno
* PAGE_SIZE
;