9 static struct maps_list *alloc_maplist(void)
11 struct maps_list *map;
13 map = malloc(sizeof *map);
17 memset(map, 0, sizeof(*map));
18 INIT_LIST_HEAD(&map->list);
23 static struct maps *alloc_map(void)
27 map = malloc(sizeof *map);
31 memset(map, 0, sizeof(*map));
32 INIT_LIST_HEAD(&map->list);
37 static struct maps *parse_maps(FILE *file, int pid)
39 struct maps *the_map = NULL;
43 while(fgets(line, sizeof(line), file)) {
44 struct maps *map = alloc_map();
45 unsigned long start, end;
54 ret = sscanf(line, "%lx-%lx %*s %*s %*s %*s %s",
57 printf("%x, start %lx, end %lx, str: %s\n",
58 ret, start, end, ret >= 3 ? name : "");
61 printf("Error reading input: %s\n", line);
67 map->size = end - start;
71 strncpy(map->name, name, sizeof(map->name));
73 list_add_tail(&map->list, &the_map->list);
79 static void clear_pageframe(struct pageframe *pf)
81 memset(pf, 0, sizeof(*pf));
84 static struct pageframe *alloc_pageframe(void)
86 struct pageframe *pageframe;
88 pageframe = malloc(sizeof *pageframe);
89 if (pageframe == NULL)
92 clear_pageframe(pageframe);
97 #define BITRANGE(first, last) (((2ll << (last - first)) - 1) << first)
99 static void pageframe_to_struct(unsigned long long p, struct pageframe *pf)
101 pf->page_present = !!(BITRANGE(63, 63) & p);
102 pf->page_swapped = !!(BITRANGE(62, 62) & p);
103 pf->page_shift = (BITRANGE(55, 60) & p) >> 55;
104 pf->pfn = (BITRANGE(0, 54) & p);
105 pf->swap_type = (BITRANGE(0, 4) & p);
106 pf->swap_offset = (BITRANGE(5, 54) & p) >> 5;
108 printf("pfn: %lx shift: %d present: %d swapped %d\n",
109 pf->pfn, pf->page_shift, pf->page_present, pf->page_swapped);
113 static int compare_pageframe(struct bintree *at, struct bintree *bt)
115 struct pageframe *a, *b;
116 a = tree_to_pageframe(at);
117 b = tree_to_pageframe(bt);
119 return a->pfn - b->pfn;
122 struct bintree_ops pageframe_ops = {
123 .compare = compare_pageframe,
126 /* Read data from the /proc/pid/pagemap file */
127 static int parse_pageframe(FILE *file, struct pageframe *pf_tree,
131 struct maps_list *tmp;
132 struct pageframe *match, *pageframe;
134 unsigned long long pf;
137 /* Go through the list of allocated memory areas */
138 list_for_each_entry(map, &maps->list, list) {
139 start = map->start >> (PAGE_SHIFT - 3);
140 len = map->size >> (PAGE_SHIFT - 3);
142 printf("start: %lx len %lx: name: %s\n",
143 start, len, map->name);
145 ret = fseek(file, start, SEEK_SET);
148 fprintf(stderr, "Error seeking to %lx: %s\n", start,
154 for (i = 0; i < len; i++) {
155 ret = fread(&pf, 1, sizeof(pf), file);
156 if (ret != sizeof(pf)) {
159 "Error reading %ld bytes, got %d: %s\n",
160 sizeof(pf), ret, strerror(errno));
164 pageframe = alloc_pageframe();
165 pageframe_to_struct(pf, pageframe);
166 match = tree_to_pageframe(
167 bintree_add(&pf_tree->tree,
168 &pageframe->tree, &pageframe_ops));
170 if (match != pageframe)
174 * Add a link from the physical page to this
178 match->ml = alloc_maplist();
179 match->ml->map = map;
181 tmp = alloc_maplist();
183 list_add(&match->ml->list, &tmp->list);
191 void read_pageframe(int pid, struct pageframe *pageframe)
198 snprintf(path, sizeof(path), "/proc/%d/maps", pid);
199 file = fopen(path, "rb");
204 maps = parse_maps(file, pid);
206 snprintf(path, sizeof(path), "/proc/%d/pagemap", pid);
207 file = fopen(path, "rb");
212 parse_pageframe(file, pageframe, maps);
217 fprintf(stderr, "Failed to open file %s: %s\n", path, strerror(error));