9 static struct maps *alloc_map(void)
13 map = malloc(sizeof *map);
17 memset(map, 0, sizeof(*map));
18 INIT_LIST_HEAD(&map->list);
23 static struct maps *parse_maps(FILE *file, int pid)
25 struct maps *the_map = NULL;
29 while(fgets(line, sizeof(line), file)) {
30 struct maps *map = alloc_map();
31 unsigned long start, end;
40 ret = sscanf(line, "%lx-%lx %*s %*s %*s %*s %s",
43 printf("%x, start %lx, end %lx, str: %s\n",
44 ret, start, end, ret >= 3 ? name : "");
47 printf("Error reading input: %s\n", line);
53 map->size = end - start;
57 strncpy(map->name, name, sizeof(map->name));
59 list_add_tail(&map->list, &the_map->list);
65 static void clear_pageframe(struct pageframe *pf)
67 memset(pf, 0, sizeof(*pf));
70 static struct pageframe *alloc_pageframe(void)
72 struct pageframe *pageframe;
74 pageframe = malloc(sizeof *pageframe);
75 if (pageframe == NULL)
78 clear_pageframe(pageframe);
83 #define BITRANGE(first, last) (((2ll << (last - first)) - 1) << first)
85 static void pageframe_to_struct(unsigned long long p, struct pageframe *pf)
87 pf->page_present = !!(BITRANGE(63, 63) & p);
88 pf->page_swapped = !!(BITRANGE(62, 62) & p);
89 pf->page_shift = (BITRANGE(55, 60) & p) >> 55;
90 pf->pfn = (BITRANGE(0, 54) & p);
91 pf->swap_type = (BITRANGE(0, 4) & p);
92 pf->swap_offset = (BITRANGE(5, 54) & p) >> 5;
94 printf("pfn: %lx shift: %d present: %d swapped %d\n",
95 pf->pfn, pf->page_shift, pf->page_present, pf->page_swapped);
99 static int compare_pageframe(struct bintree *at, struct bintree *bt)
101 struct pageframe *a, *b;
102 a = tree_to_pageframe(at);
103 b = tree_to_pageframe(bt);
105 return a->pfn - b->pfn;
108 struct bintree_ops pageframe_ops = {
109 .compare = compare_pageframe,
112 /* Read data from the /proc/pid/pagemap file */
113 static int parse_pageframe(FILE *file, struct pageframe **pageframe_tree,
116 struct maps *map, *tmp;
117 struct pageframe *match, *pageframe = alloc_pageframe();
119 unsigned long long pf;
122 /* Go through the list of allocated memory areas */
123 list_for_each_entry(map, &maps->list, list) {
124 start = map->start >> (PAGE_SHIFT - 3);
125 len = map->size >> (PAGE_SHIFT - 3);
127 printf("start: %lx len %lx: name: %s\n",
128 start, len, map->name);
130 ret = fseek(file, start, SEEK_SET);
133 fprintf(stderr, "Error seeking to %lx: %s\n", start,
139 for (i = 0; i < len; i++) {
140 ret = fread(&pf, 1, sizeof(pf), file);
141 if (ret != sizeof(pf)) {
144 "Error reading %ld bytes, got %d: %s\n",
145 sizeof(pf), ret, strerror(errno));
150 pageframe_to_struct(pf, pageframe);
151 match = tree_to_pageframe(
152 bintree_add(&(*pageframe_tree)->tree,
153 &pageframe->tree, &pageframe_ops));
155 if (*pageframe_tree == NULL)
156 *pageframe_tree = match;
159 * Add a link from the physical page to this
163 match->maps = alloc_map();
165 INIT_LIST_HEAD(&match->maps->list);
169 list_add(&match->maps->list, &tmp->list);
177 struct pageframe *read_pageframe(int pid, struct pageframe *pageframe)
184 snprintf(path, sizeof(path), "/proc/%d/maps", pid);
185 file = fopen(path, "rb");
190 maps = parse_maps(file, pid);
192 snprintf(path, sizeof(path), "/proc/%d/pagemap", pid);
193 file = fopen(path, "rb");
198 parse_pageframe(file, &pageframe, maps);
203 fprintf(stderr, "Failed to open file %s: %s\n", path, strerror(error));