Last active
September 17, 2021 08:21
-
-
Save kostikbel/1f0de166c34d822b6aa7a05110ede8be to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* $Id: shadow_show.c,v 1.4 2021/05/04 14:55:03 kostik Exp kostik $ */ | |
/* /usr/local/opt/gcc-11.1.0/bin/gcc -Wall -Wextra -g -O -o shadow_show shadow_show.c -lutil */ | |
#include <sys/param.h> | |
#include <sys/sysctl.h> | |
#include <sys/user.h> | |
#include <err.h> | |
#include <libutil.h> | |
#include <stdbool.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
static struct swinfo { | |
struct kinfo_vmobject sw_vmo; | |
pid_t sw_pid; | |
} *swobj; | |
static int nswobj; | |
static int | |
swobj_search(const void *a, const void *b) | |
{ | |
const uint64_t *aa = a; | |
const struct swinfo *bb = b; | |
if (*aa == bb->sw_vmo.kvo_me) | |
return (0); | |
return (*aa > bb->sw_vmo.kvo_me ? -1 : 1); | |
} | |
static int | |
swobj_sort(const void *a, const void *b) | |
{ | |
return (((const struct swinfo *)a)->sw_vmo.kvo_me > | |
((const struct swinfo *)b)->sw_vmo.kvo_me ? -1 : 1); | |
} | |
static bool | |
get_swap_vmobjects(void) | |
{ | |
struct kinfo_vmobject *kvo; | |
struct swinfo *swi; | |
int cnt, i, next_i, last_nswobj, max; | |
max = next_i = nswobj = 0; | |
kvo = kinfo_getvmobject(&cnt); | |
if (kvo == NULL) { | |
err(1, "kinfo_getvmobject()"); | |
return (false); | |
} | |
do { | |
for (i = next_i; i < cnt; i++) { | |
if (kvo[i].kvo_type != KVME_TYPE_DEFAULT && | |
kvo[i].kvo_type != KVME_TYPE_SWAP) | |
continue; | |
if (nswobj < max) { | |
swi = &swobj[nswobj]; | |
memcpy(&swi->sw_vmo, &kvo[i], | |
sizeof(struct kinfo_vmobject)); | |
swi->sw_pid = 0; | |
next_i = i + 1; | |
} | |
nswobj++; | |
} | |
if (nswobj <= max) | |
break; | |
/* allocate memory and fill skipped elements */ | |
last_nswobj = max; | |
max = nswobj; | |
nswobj = last_nswobj; | |
/* allocate more memory and fill missed ones */ | |
swobj = realloc(swobj, max * sizeof(struct swinfo)); | |
if (swobj == NULL) | |
err(1, "Out of memory"); | |
} while (i <= cnt); /* extra safety guard */ | |
free(kvo); | |
if (nswobj > 1) | |
qsort(swobj, nswobj, sizeof (swobj[0]), swobj_sort); | |
return (nswobj > 0); | |
} | |
static void | |
handle_proc(pid_t pid) | |
{ | |
struct kinfo_vmentry *kvm, *kve; | |
struct swinfo *swi; | |
uint64_t vmobj_handle; | |
uint64_t resident_pages, swapped_pages; | |
int cnt, i, j, tab_level; | |
kvm = kinfo_getvmmap(pid, &cnt); | |
if (kvm == NULL) { | |
warnx("Cannot get vm map for pid %d", pid); | |
return; | |
} | |
printf("pid %d\n", pid); | |
resident_pages = swapped_pages = 0; | |
for (i = 0; i < cnt; i++) { | |
kve = &kvm[i]; | |
if (kve->kve_type != KVME_TYPE_DEFAULT && | |
kve->kve_type != KVME_TYPE_SWAP) | |
continue; | |
printf("%#019jx-%#019jx\n", (uintmax_t)kve->kve_start, | |
(uintmax_t)kve->kve_end); | |
vmobj_handle = kve->kve_obj; | |
for (tab_level = 1;; tab_level += 1) { | |
if (vmobj_handle == 0) | |
break; | |
for (j = 0; j < tab_level; j++) | |
printf(" "); | |
printf("%#019jx ", vmobj_handle); | |
swi = bsearch(&vmobj_handle, swobj, nswobj, | |
sizeof(swobj[0]), swobj_search); | |
if (swi == NULL) { | |
printf("\n"); | |
break; | |
} | |
printf("%ju %ju\n", (uintmax_t)swi->sw_vmo.kvo_resident, | |
(uintmax_t)swi->sw_vmo.kvo_swapped); | |
if (swi->sw_pid != pid) { | |
resident_pages += swi->sw_vmo.kvo_resident; | |
swapped_pages += swi->sw_vmo.kvo_swapped; | |
swi->sw_pid = pid; | |
} | |
vmobj_handle = swi->sw_vmo.kvo_backing_obj; | |
} | |
} | |
printf("Total %ju %ju\n", (uintmax_t)resident_pages, | |
(uintmax_t)swapped_pages); | |
} | |
int | |
main(int argc, char *argv[]) | |
{ | |
pid_t pid; | |
int i; | |
if (!get_swap_vmobjects()) | |
exit(1); | |
for (i = 1; i < argc; i++) { | |
pid = atoi(argv[i]); | |
handle_proc(pid); | |
} | |
exit(0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* $Id: shadow_show.c,v 1.3 2021/05/04 14:20:58 kostik Exp kostik $ */ | |
/* /usr/local/opt/gcc-11.1.0/bin/gcc -Wall -Wextra -g -O -o shadow_show shadow_show.c -lutil */ | |
#include <sys/param.h> | |
#include <sys/sysctl.h> | |
#include <sys/user.h> | |
#include <err.h> | |
#include <libutil.h> | |
#include <stdbool.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
static struct swapvm { | |
uint64_t kvo_me; | |
uint32_t swapped_pages; | |
uint64_t next; | |
} *swobj = NULL; | |
static int nswobj = 0; | |
static int | |
swobj_search(const void *a, const void *b) | |
{ | |
const uint64_t *aa = a; | |
const struct swapvm *bb = b; | |
if (*aa == bb->kvo_me) | |
return (0); | |
return (*aa > bb->kvo_me ? -1 : 1); | |
} | |
static int | |
swobj_sort(const void *a, const void *b) | |
{ | |
return (((const struct swapvm *)a)->kvo_me > | |
((const struct swapvm *)b)->kvo_me ? -1: 1); | |
} | |
static bool | |
get_swap_vmobjects(void) | |
{ | |
struct kinfo_vmobject *kvo; | |
int cnt, i, next_i, last_nswobj, max; | |
max = next_i = nswobj = 0; | |
kvo = kinfo_getvmobject(&cnt); | |
if (kvo == NULL) { | |
err(1, "kinfo_getvmobject()"); | |
return (false); | |
} | |
do { | |
for (i = next_i; i < cnt; i++) { | |
if (kvo[i].kvo_type != KVME_TYPE_DEFAULT && | |
kvo[i].kvo_type != KVME_TYPE_SWAP) | |
continue; | |
if (nswobj < max) { | |
swobj[nswobj].kvo_me = kvo[i].kvo_me; | |
swobj[nswobj].swapped_pages = | |
kvo[i].kvo_swapped; | |
swobj[nswobj].next = kvo[i].kvo_backing_obj; | |
next_i = i + 1; | |
} | |
nswobj++; | |
} | |
if (nswobj <= max) | |
break; | |
/* allocate memory and fill skipped elements */ | |
last_nswobj = max; | |
max = nswobj; | |
nswobj = last_nswobj; | |
/* allocate more memory and fill missed ones */ | |
if ((swobj = realloc(swobj, max * sizeof(*swobj))) == NULL) | |
err(1, "Out of memory"); | |
} while (i <= cnt); /* extra safety guard */ | |
free(kvo); | |
if (nswobj > 1) | |
qsort(swobj, nswobj, sizeof (swobj[0]), swobj_sort); | |
return (nswobj > 0); | |
} | |
static void | |
handle_proc(pid_t pid) | |
{ | |
struct kinfo_vmentry *kvm, *kve; | |
struct swapvm *svm; | |
uint64_t vmobj_handle; | |
uint64_t swapped_pages; | |
int cnt, i, j, tab_level; | |
kvm = kinfo_getvmmap(pid, &cnt); | |
if (kvm == NULL) { | |
warnx("Cannot get vm map for pid %d", pid); | |
return; | |
} | |
printf("pid %d\n", pid); | |
swapped_pages = 0; | |
for (i = 0; i < cnt; i++) { | |
kve = &kvm[i]; | |
if (kve->kve_type != KVME_TYPE_DEFAULT && | |
kve->kve_type != KVME_TYPE_SWAP) | |
continue; | |
printf("%#019jx-%#019jx\n", (uintmax_t)kve->kve_start, | |
(uintmax_t)kve->kve_end); | |
vmobj_handle = kve->kve_obj; | |
for (tab_level = 1;; tab_level += 1) { | |
if (vmobj_handle == 0) | |
break; | |
for (j = 0; j < tab_level; j++) | |
printf(" "); | |
printf("%#019jx ", vmobj_handle); | |
svm = bsearch(&vmobj_handle, swobj, nswobj, | |
sizeof(swobj[0]), swobj_search); | |
if (svm == NULL) { | |
printf("\n"); | |
break; | |
} | |
printf("%ju\n", (uintmax_t)svm->swapped_pages); | |
swapped_pages += svm->swapped_pages; | |
vmobj_handle = svm->next; | |
} | |
} | |
printf("Total %ju\n", swapped_pages); | |
} | |
int | |
main(int argc, char *argv[]) | |
{ | |
pid_t pid; | |
int i; | |
if (!get_swap_vmobjects()) | |
exit(1); | |
for (i = 1; i < argc; i++) { | |
pid = atoi(argv[i]); | |
handle_proc(pid); | |
} | |
exit(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Yes, I am using 13.0 release. Thank you for your time, I will try stable/13 or HEAD :)