/
region_list.c
133 lines (123 loc) · 3.87 KB
/
region_list.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/***********************************************************************
* region_list.c *
* *
* Implementation of the region_list structure *
* *
**********************************************************************/
/* Includes */
#include<errno.h>
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
#include "region_list.h"
/***********************************************************************
* new_region_list - initialize a new region_list *
* *
* Given a pid, new_region_list crawls through /proc/<pid>/maps and *
* produces a linked list called region_list which contains the *
* addresses for all the memory regions in the pid's address space. *
* *
* The flag RL_FLAG_ANON specifies whether it should include all the *
* segments it can read in this list or just the interesting ones. *
***********************************************************************/
struct region_list * new_region_list(pid_t pid, int flags)
{
/* Variables */
char * path = NULL;
int maps_fd = -1;
int maps_len;
char * maps = NULL;
int i = 0;
off_t offset = 0;
char i_hate_proc;
struct region_list * head;
struct region_list * cur;
char * tok/*en_of_my_appreciation*/;
int chk;
/* Initialize */
path = calloc(1, 25);
err_chk(path == NULL);
head = calloc(sizeof(struct region_list), 1);
err_chk(head == NULL);
cur = head;
/* Open maps */
snprintf(path, 24, "%s%d%s", "/proc/", (int) pid, "/maps");
maps_fd = open(path, O_RDONLY);
err_chk(maps_fd == -1);
/* read maps into memory */
for(maps_len = 0; (chk = read(maps_fd, &i_hate_proc, 1)) == 1; maps_len++); /* find length because files in proc are silly */
err_chk(chk == -1 || maps_len == 0);
lseek(maps_fd, 0, SEEK_SET);
maps = calloc(maps_len + 1, 1);
err_chk(maps == NULL);
while(offset != maps_len)
{
chk = read(maps_fd, maps + offset, maps_len - offset);
err_chk(chk == -1);
offset += chk;
}
/* parse */
while(1)
{
cur->next = calloc(sizeof(struct region_list), 1);
err_chk(cur->next == NULL);
cur->next->begin = (void *) strtol(maps + i, &tok, 16);
cur->next->end = (void *) strtol(tok + 1, &tok, 16);
for(;maps[i] != '\n';i++);
if(flags & RL_FLAG_RWANON)
{
if(tok[1] != 'r' || tok[2] != 'w' || tok[21] != '0' || tok[22] != ' ')
{
free(cur->next);
cur->next = NULL;
i++;
if(i == maps_len)
break;
else
continue;
}
}
else
{
if(tok[1] != 'r')
{
free(cur->next);
cur->next = NULL;
i++;
if(i == maps_len)
break;
else
continue;
}
}
if(i+1 == maps_len)
break;
else
i++;
cur = cur->next;
}
/* clean up */
cur = head->next;
free(head);
free(path);
free(maps);
close(maps_fd);
return cur;
err: /* Error handling */
/* perror("new_region_list"); */
if(path)
free(path);
if(maps)
free(maps);
if(maps_fd != -1)
close(maps_fd);
return NULL;
}
/* Free a region_list */
struct region_list * free_region_list(struct region_list * rl)
{
if(rl->next != NULL)
free_region_list(rl->next);
free(rl);
return NULL;
}