#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; }