add strscan
[tools.git] / tools / strscan.c
1 // scans process memory for a given string, prints offsets of occurences
2 // will ignore matches where the match is split over a mapping boundary
3 #define _GNU_SOURCE
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <assert.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <jh.h>
11 #include <stdbool.h>
12 #include <string.h>
13
14 struct range {
15   void *a, *b;
16   char *line;
17 };
18
19 struct range *mappings;
20 size_t mappings_used = 0;
21 #define FOR_EACH_MAPPING FOR_EACH_IN_ARRAY(mappings, mappings_used, mapping)
22
23 bool is_mapped(void *addr) {
24   FOR_EACH_MAPPING
25     if (mapping->a <= addr && mapping->b > addr) return true;
26   return false;
27 }
28
29 int main(int argc, char **argv) {
30   // init
31   if (argc != 3) xperror("invocation: anondump <pid> <searchstr>", 0);
32   TPRINTF(maps_path, "/proc/%s/maps", argv[1])
33   char *maps = CHK_PTR(slurp_file(maps_path, NULL, JH_SLURP_NO_STAT), "unable to read /proc/$pid/maps", 1);
34   TPRINTF(mem_path, "/proc/%s/mem", argv[1])
35   int memfd = fail_on_neg(open(mem_path, O_RDONLY), "unable to open /proc/$pid/mem", 1);
36
37   size_t n_mappings = count_char_occurences(maps, '\n');
38   mappings = CHK_PTR(calloc(n_mappings, sizeof(struct range)), "memory allocation failed", 1);
39
40   // do magic
41   for (char *line = strtok(maps, "\n"); line != NULL; line = strtok(NULL, "\n")) {
42     struct range *mapping = &mappings[mappings_used++];
43     mapping->line = CHK_PTR(strdup(line), "memory allocation failed", 1);
44     if (sscanf(line, "%p-%p", &mapping->a, &mapping->b) != 2) xperror("sscanf failed", 0);
45   }
46
47   FOR_EACH_MAPPING {
48     size_t len = mapping->b - mapping->a;
49     char *copy = CHK_PTR(malloc(len), "malloc failed", 1);
50     if (pread(memfd, copy, len, (off_t)mapping->a) != (ssize_t)len) xperror("pread failed", 0);
51     size_t pos = 0;
52     while (1) {
53       char *ptr = memmem(copy + pos, len, argv[2], strlen(argv[2]));
54       if (ptr == NULL) break;
55       pos = ptr - copy;
56       printf("at %p in %s\n", mapping->a + pos, mapping->line);
57       pos++;
58     }
59     free(copy);
60   }
61
62   return 0;
63 }