#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
-#include <sys/ptrace.h>
#include <fcntl.h>
#include <jh.h>
#include <stdbool.h>
#include <string.h>
+#include <sys/uio.h>
+
+ssize_t getmem(pid_t pid, void *dst, void *src, size_t len) {
+ assert(len > 0);
+ struct iovec local = {.iov_base = dst, .iov_len = len};
+ struct iovec remote = {.iov_base = src, .iov_len = len};
+ return process_vm_readv(pid, &local, 1, &remote, 1, 0);
+}
struct range {
void *a, *b;
char *line;
+ char readable;
};
struct range *mappings;
TPRINTF(maps_path, "/proc/%s/maps", argv[1])
char *maps = CHK_PTR(slurp_file(maps_path, NULL, JH_SLURP_NO_STAT), "unable to read /proc/$pid/maps", 1);
-/*
- char argbuf[8192];
- size_t arglen = strlen(argv[2])*4;
- for (int i=0; i<strlen(argv[2]); i++) {
- argbuf[i*4] = argv[2][i];
- argbuf[i*4+1] = 0;
- argbuf[i*4+2] = 0;
- argbuf[i*4+3] = 0;
- }*/
-
- if (ptrace(PTRACE_ATTACH, atoi(argv[1]), NULL, NULL)) {
- fputs("warning: unable to ptrace\n", stderr);
- } else {
- wait(NULL);
- }
-
- TPRINTF(mem_path, "/proc/%s/mem", argv[1])
- int memfd = fail_on_neg(open(mem_path, O_RDONLY), "unable to open /proc/$pid/mem", 1);
+ pid_t target = atoi(argv[1]);
size_t n_mappings = count_char_occurences(maps, '\n');
mappings = CHK_PTR(calloc(n_mappings+1, sizeof(struct range)), "memory allocation failed", 1);
for (char *line = strtok(maps, "\n"); line != NULL; line = strtok(NULL, "\n")) {
struct range *mapping = &mappings[mappings_used++];
mapping->line = CHK_PTR(strdup(line), "memory allocation failed", 1);
- if (sscanf(line, "%p-%p", &mapping->a, &mapping->b) != 2) xperror("sscanf failed", 0);
+ if (sscanf(line, "%p-%p %c", &mapping->a, &mapping->b, &mapping->readable) != 3) xperror("sscanf failed", 0);
+ assert(mapping->readable == 'r' || mapping->readable == '-');
}
FOR_EACH_MAPPING {
+ //fprintf(stderr, "%s\n", mapping->line);
+ if (mapping->readable == '-') continue; /* guard page */
+ if (strchr(mapping->line, '/') == NULL && strstr(mapping->line, "[vvar]") != NULL) continue; /* vvar mapping is weird */
size_t len = mapping->b - mapping->a;
+ //printf("a=0x%llx b=0x%llx len=0x%llx\n", (unsigned long long)mapping->a, (unsigned long long)mapping->b, (unsigned long long)len);
char *copy = CHK_PTR(malloc(len), "malloc failed", 1);
ssize_t read_res;
- size_t read_done = 0;
-read_more:;
- if ((read_res=pread(memfd, copy+read_done, len-read_done, (off_t)mapping->a-read_done)) != (ssize_t)len) {
- if (read_res <= 0) {
+ if ((read_res=getmem(target, copy, mapping->a, len)) != len) {
+ if (read_res == 0) {
fputs("warning: some read failed\n", stderr);
continue;
}
- read_done += read_res;
- goto read_more;
+ if (read_res == -1) {
+ perror("warning: some read failed");
+ continue;
+ }
}
size_t pos = 0;
while (1) {
- char *ptr = memmem(copy + pos, len, argv[2], strlen(argv[2]));
+ char *ptr = memmem(copy + pos, len - pos, argv[2], strlen(argv[2]));
if (ptr == NULL) break;
pos = ptr - copy;
printf("at %p in %s\n", mapping->a + pos, mapping->line);