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); | |
} |
This feature requires stable/13 or HEAD. I suspect you use 13.0 release.
Yes, I am using 13.0 release. Thank you for your time, I will try stable/13 or HEAD :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This code looks awesome, I am trying to compile this in freebsd 13 and getting this error:
**[freebsd13.0]# /usr/local/opt/bin/gcc -Wall -Wextra -g -O -o shadow_show shadow_show.c -lutil
shadow_show.c: In function âget_swap_vmobjectsâ:
shadow_show.c:57:63: error: âstruct kinfo_vmobjectâ has no member named âkvo_meâ; did you mean âkvo_typeâ?
57 | swobj[nswobj].kvo_me = kvo[i].kvo_me;
| ^~~~~~
| kvo_type
shadow_show.c:59:43: error: âstruct kinfo_vmobjectâ has no member named âkvo_swappedâ
59 | kvo[i].kvo_swapped;
| ^
shadow_show.c:60:60: error: âstruct kinfo_vmobjectâ has no member named âkvo_backing_objâ
60 | swobj[nswobj].next = kvo[i].kvo_backing_obj;
| ^
shadow_show.c: In function âhandle_procâ:
shadow_show.c:104:35: error: âstruct kinfo_vmentryâ has no member named âkve_objâ
104 | vmobj_handle = kve->kve_obj;
| ^~
[freebsd13.0]#/usr/local/opt/bin/gcc --version
gcc (GCC) 11.1.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[freebsd13.0]#**
Could you please help fix this compilation issue.