Created
July 29, 2018 01:33
-
-
Save thejh/92b66c44cd3ecc381deed9815b72310c to your computer and use it in GitHub Desktop.
unused stack memory experiment
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
// small stack memory usage experiment | |
// written by Jann Horn | |
#include <stdint.h> | |
#include <sys/ptrace.h> | |
#include <sys/user.h> | |
#include <fcntl.h> | |
#include <err.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <sys/types.h> | |
#include <sys/wait.h> | |
#include <assert.h> | |
#include <stdio.h> | |
int main(void) { | |
int pid_max; | |
{ | |
char pid_max_str[30]; | |
int fd = open("/proc/sys/kernel/pid_max", O_RDONLY); | |
if (fd == -1) err(1, "open pid_max"); | |
int res = read(fd, pid_max_str, sizeof(pid_max_str)-1); | |
if (res == -1) err(1, "read pid_max"); | |
close(fd); | |
pid_max_str[res] = 0; | |
pid_max = atoi(pid_max_str); | |
if (pid_max < 100) | |
errx(1, "read pid_max"); | |
printf("got pid_max: %d\n", pid_max); | |
} | |
int procs_seen = 0; | |
long present_pages_sum = 0, swapped_pages_sum = 0; | |
for (int pid = 1; pid < pid_max; pid++) { | |
int r; | |
r = ptrace(PTRACE_ATTACH, pid, 0, 0); | |
if (r == -1) continue; | |
// wait for SIGSTOP, but reinject everything else | |
while (1) { | |
int status; | |
if (waitpid(pid, &status, 0) != pid) | |
err(1, "waitpid"); | |
if (WIFEXITED(status) || WIFSIGNALED(status)) { | |
// oops, we raced, it's dead | |
goto next_pid; | |
} | |
assert(WIFSTOPPED(status)); | |
int sig = WSTOPSIG(status); | |
if (sig == SIGSTOP) { | |
// wheee, it's stopped now! | |
break; | |
} else { | |
// bleh. reinject and loop back. | |
if (ptrace(PTRACE_CONT, pid, NULL, sig)) | |
err(1, "reinject signal"); | |
} | |
} | |
// we're attached, grab the register state | |
printf("pid %d\n", pid); | |
struct user_regs_struct regs = {0}; | |
if (ptrace(PTRACE_GETREGS, pid, NULL, ®s)) | |
err(1, "PTRACE_GETREGS"); | |
printf(" rsp: 0x%016llx\n", regs.rsp); | |
printf(" rip: 0x%016llx\n", regs.rip); | |
unsigned long redzone_bottom = regs.rsp - 128; | |
unsigned long redzone_bottom_page = redzone_bottom & ~0xfffUL; | |
char maps_name[100]; | |
sprintf(maps_name, "/proc/%d/maps", pid); | |
FILE *maps_file = fopen(maps_name, "r"); | |
if (!maps_file) { | |
perror("open maps"); | |
goto detach; | |
} | |
char line[1000]; | |
unsigned long stack_start; | |
while (fgets(line, sizeof(line), maps_file) == line) { | |
unsigned long start, end; | |
if (sscanf(line, "%lx-%lx", &start, &end) != 2) | |
continue; | |
if (start <= regs.rsp && regs.rsp < end) { | |
printf(" found stack: 0x%lx-0x%lx\n", start, end); | |
printf(" stack usage: %lu bytes\n", end-redzone_bottom); | |
stack_start = start; | |
break; | |
} | |
} | |
fclose(maps_file); | |
char pagemap_name[100]; | |
sprintf(pagemap_name, "/proc/%d/pagemap", pid); | |
int pagemap_fd = open(pagemap_name, O_RDONLY); | |
int present_pages = 0, swapped_pages = 0; | |
if (pagemap_fd == -1) { | |
perror("open pagemap"); | |
goto detach; | |
} | |
for (unsigned long page = stack_start; page < redzone_bottom_page; page += 0x1000) { | |
unsigned long off = page / 0x1000 * sizeof(uint64_t); | |
uint64_t val; | |
if (pread(pagemap_fd, &val, sizeof(uint64_t), off) != sizeof(uint64_t)) { | |
perror("bad pagemap read"); | |
goto detach; | |
} | |
if (val & (1UL<<63)) { | |
present_pages++; | |
} else if (val & (1UL<<62)) { | |
swapped_pages++; | |
} | |
} | |
close(pagemap_fd); | |
printf(" present: %d kB\n", present_pages*4); | |
printf(" swapped: %d kB\n", swapped_pages*4); | |
present_pages_sum += present_pages; | |
swapped_pages_sum += swapped_pages; | |
// get out of here! | |
procs_seen++; | |
detach: | |
if (ptrace(PTRACE_DETACH, pid, 0, 0)) | |
err(1, "PTRACE_DETACH"); | |
next_pid:; | |
} | |
printf("\nTOTAL:\n"); | |
printf("tasks: %d\n", procs_seen); | |
printf("present: %ld kB\n", present_pages_sum*4); | |
printf("swapped: %ld kB\n", swapped_pages_sum*4); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment