From 18a86e1038b20cb6f8922beead08dcc24ba2a4d3 Mon Sep 17 00:00:00 2001 From: raven Date: Wed, 8 Apr 2026 22:51:39 -0500 Subject: rewrite and port to SDL3 --- src/procfs.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 src/procfs.c (limited to 'src/procfs.c') diff --git a/src/procfs.c b/src/procfs.c new file mode 100644 index 0000000..d377e02 --- /dev/null +++ b/src/procfs.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "procfs.h" + +int procfs_open(pid_t pid) { + char path[2048]; + sprintf(path, "/proc/%d/mem", pid); + return open(path, O_RDWR); +} + +ssize_t procfs_maps(pid_t pid, struct procfs_map **maps) { + char path[2048]; + sprintf(path, "/proc/%d/maps", pid); + FILE *f = fopen(path, "r"); + if (!f) return -1; + + int n = 0; + int capacity = 2; + if (*maps) { + free(*maps); + } + *maps = calloc(capacity, sizeof(**maps)); + if (!*maps) return -1; + while (1) { + void *base, *max; + char prot_str[4]; + char name[4096] = {0}; + void *unused; + int matches = fscanf( + f, "%p-%p %4c %p %p:%p %d", + &base, &max, &prot_str, &unused, &unused, &unused, &unused + ); + if (matches == EOF) goto eof; + if (matches < 7) goto err; + + int c = ' '; + while (c == ' ') { + c = fgetc(f); + } + if (c == EOF) goto err; + ungetc(c, f); + if (fgets(name, 4096, f) == NULL) goto err; + name[strlen(name) - 1] = '\0'; // remove newline + + int prot = 0; + for (int i = 0; i < 4; i++) { + switch (prot_str[i]) { + case 'r': + prot |= PROT_READ; + break; + case 'w': + prot |= PROT_WRITE; + break; + case 'x': + prot |= PROT_EXEC; + break; + default: + break; + } + } + if (prot == 0) prot = PROT_NONE; + + if (n > 0) { + procfs_map *prev = *maps + (n - 1); + if ((strlen(name) == 0 || strncmp(prev->name, name, 1024) == 0) && + prev->max == (uintptr_t)base) { + prev->max = (uintptr_t)max; + continue; + } + } + + n++; + if (n > capacity) { + capacity <<= 1; + struct procfs_map *r = reallocarray(*maps, capacity, sizeof(*r)); + if (!r) goto err; + *maps = r; + } + procfs_map *new = *maps + (n - 1); + new->base = (uintptr_t)base; + new->max = (uintptr_t)max; + new->prot = prot; + strncpy(new->name, name, sizeof(new->name) - 1); + } +eof: + if (ferror(f)) goto err; + fclose(f); + if (n == 0) { + free(*maps); + *maps = NULL; + } + return n; +err: + fclose(f); + free(*maps); + *maps = NULL; + return -1; +} + +// mmap does not work on /proc/pid/mem, so we issue reads/writes instead +int read_mem(int fd, uintptr_t addr, uint8_t *data, size_t size) { + if (lseek(fd, addr, SEEK_SET) == -1) return -1; + size_t n = 0; + while (n < size) { + ssize_t result = read(fd, data + n, size - n); + if (result <= 0) return -1; + n += result; + } + return 0; +} + +int write_mem(int fd, uintptr_t addr, uint8_t *data, size_t size) { + if (lseek(fd, addr, SEEK_SET) == -1) return -1; + size_t n = 0; + while (n < size) { + ssize_t result = write(fd, data + n, size - n); + if (result <= 0) return -1; + n += result; + } + return 0; +} -- cgit v1.2.3