#include #include #include #include #include #include #include #include #include #include #include #include #if 0 /* XXX */ struct vm_phys_seg { vm_paddr_t start; vm_paddr_t end; vm_page_t first_page; int domain; void *free_queues; }; #endif static inline u_long nsegpages(struct vm_phys_seg *seg) { return (atop(seg->end - seg->start)); } static struct nlist namelist[] = { #define X_VM_PAGE_ARRAY 0 { .n_name = "_vm_page_array" }, #define X_VM_PAGE_ARRAY_SIZE 1 { .n_name = "_vm_page_array_size" }, #define X_VM_PHYS_SEGS 2 { .n_name = "_vm_phys_segs" }, #define X_KERNEL_OBJECT_STORE 3 { .n_name = "_kernel_object_store" }, { .n_name = "" }, }; static kvm_t * kvminit(void) { char errbuf[_POSIX2_LINE_MAX]; kvm_t *kvm; int count; kvm = kvm_openfiles(NULL, NULL, NULL, 0, errbuf); if (kvm == NULL) errx(1, "kvm_openfiles: %s", errbuf); count = kvm_nlist(kvm, namelist); if (count == -1) errx(1, "kvm_nlist: %s", kvm_geterr(kvm)); if (count > 0) errx(1, "kvm_nlist: failed to resolve symbols"); return (kvm); } static int kread(kvm_t *kvm, u_long kaddr, void *addr, size_t size) { ssize_t ret; ret = kvm_read(kvm, kaddr, addr, size); if (ret < 0 || (size_t)ret != size) errx(1, "kread: %#lx: %s", kaddr, kvm_geterr(kvm)); return (0); } static int kread_symbol(kvm_t *kvm, int index, void *addr, size_t size) { ssize_t ret; ret = kvm_read(kvm, namelist[index].n_value, addr, size); if (ret < 0 || (size_t)ret != size) errx(1, "kread_symbol: %s: %s", namelist[index].n_name, kvm_geterr(kvm)); return (0); } int main(void) { struct vm_phys_seg segs[VM_PHYSSEG_MAX]; struct vm_object obj; vm_page_t arrs[VM_PHYSSEG_MAX], m; kvm_t *kvm; size_t size; long j, npages; int i; kvm = kvminit(); kread_symbol(kvm, X_VM_PHYS_SEGS, segs, sizeof(segs)); npages = 0; for (i = 0; i < VM_PHYSSEG_MAX; i++) { npages += nsegpages(&segs[i]); size = nsegpages(&segs[i]) * sizeof(struct vm_page); arrs[i] = malloc(size); if (arrs[i] == NULL) err(1, "malloc"); kread(kvm, (u_long)segs[i].first_page, arrs[i], size); } for (i = 0; i < VM_PHYSSEG_MAX; i++) { for (j = 0; j < nsegpages(&segs[i]); j++) { m = &arrs[i][j]; if (m->order == VM_NFREEORDER) { if (m->object != NULL && (u_long)m->object != namelist[X_KERNEL_OBJECT_STORE].n_value) { kread(kvm, (u_long)m->object, &obj, sizeof(obj)); if (obj.type == OBJT_DEFAULT || obj.type == OBJT_SWAP) { if ((obj.flags & OBJ_ANON) != 0) printf("%#lx: anonymous\n", m->phys_addr); else printf("%#lx: shmem\n", m->phys_addr); } else if (obj.type == OBJT_VNODE) printf("%#lx: vnode\n", m->phys_addr); else printf("%#lx: unknown\n", m->phys_addr); } else { printf("%#lx: kernel-wired\n", m->phys_addr); } } else { printf("%#lx: free\n", m->phys_addr); } } } return (0); }