root/procselfmaps.cpp
/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- fd
- isValidData
- readDec
- readHex
- getNextArea
1 /****************************************************************************
2 * Copyright (C) 2006-2013 by Jason Ansel, Kapil Arya, and Gene Cooperman *
3 * jansel@csail.mit.edu, kapil@ccs.neu.edu, gene@ccs.neu.edu *
4 * *
5 * This file is part of DMTCP. *
6 * *
7 * DMTCP is free software: you can redistribute it and/or *
8 * modify it under the terms of the GNU Lesser General Public License as *
9 * published by the Free Software Foundation, either version 3 of the *
10 * License, or (at your option) any later version. *
11 * *
12 * DMTCP is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU Lesser General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License along with DMTCP:dmtcp/src. If not, see *
19 * <http://www.gnu.org/licenses/>. *
20 ****************************************************************************/
21
22 #include <fcntl.h>
23 #include "util.h"
24 #include "procselfmaps.h"
25 #include "syscallwrappers.h"
26 #include "jassert.h"
27
28 using namespace dmtcp;
29
30
31 ProcSelfMaps::ProcSelfMaps()
32 : dataIdx(0),
33 numAreas(0),
34 numBytes(0),
35 fd(-1)
36 {
37 char buf[4096];
38 fd = _real_open("/proc/self/maps", O_RDONLY);
39 JASSERT(fd != -1) (JASSERT_ERRNO);
40 ssize_t numRead = 0;
41
42 // Get an approximation of the required buffer size.
43 do {
44 numRead = Util::readAll(fd, buf, sizeof(buf));
45 if (numRead > 0) {
46 numBytes += numRead;
47 }
48 } while (numRead > 0);
49
50 // Now allocate a buffer. Note that this will most likely change the layout
51 // of /proc/self/maps, so we need to recalculate numBytes.
52 size_t size = numBytes + 4096; // Add a one page buffer.
53 data = (char*) JALLOC_HELPER_MALLOC(size);
54 JASSERT(lseek(fd, 0, SEEK_SET) == 0);
55
56 numBytes = Util::readAll(fd, data, size);
57 JASSERT(numBytes > 0) (numBytes);
58
59 // TODO(kapil): Replace this assert with more robust code that would
60 // reallocate the buffer with an extended size.
61 JASSERT(numBytes < size) (numBytes) (size);
62
63 // TODO(kapil): Validate the read data.
64 JASSERT(isValidData());
65
66 _real_close(fd);
67
68 for (size_t i = 0; i < numBytes; i++) {
69 if (data[i] == '\n') {
70 numAreas++;
71 }
72 }
73 }
74
75 ProcSelfMaps::~ProcSelfMaps()
76 {
77 JALLOC_HELPER_FREE(data);
78 fd = -1;
79 dataIdx = 0;
80 numAreas = 0;
81 numBytes = 0;
82 }
83
84 bool ProcSelfMaps::isValidData()
85 {
86 // TODO(kapil): Add validation check.
87 return true;
88 }
89
90 unsigned long int ProcSelfMaps::readDec()
91 {
92 unsigned long int v = 0;
93
94 while (1) {
95 char c = data[dataIdx];
96 if ((c >= '0') && (c <= '9')) {
97 c -= '0';
98 } else {
99 break;
100 }
101 v = v * 10 + c;
102 dataIdx++;
103 }
104 return v;
105 }
106
107 unsigned long int ProcSelfMaps::readHex()
108 {
109 unsigned long int v = 0;
110
111 while (1) {
112 char c = data[dataIdx];
113 if ((c >= '0') && (c <= '9')) {
114 c -= '0';
115 } else if ((c >= 'a') && (c <= 'f')) {
116 c -= 'a' - 10;
117 } else if ((c >= 'A') && (c <= 'F')) {
118 c -= 'A' - 10;
119 } else {
120 break;
121 }
122 v = v * 16 + c;
123 dataIdx++;
124 }
125 return v;
126 }
127
128 int ProcSelfMaps::getNextArea(ProcMapsArea* area)
129 {
130 char rflag, sflag, wflag, xflag;
131
132 if (dataIdx >= numBytes || data[dataIdx] == 0) {
133 return 0;
134 }
135
136 area->addr = (VA) readHex();
137 JASSERT(area->addr != NULL);
138
139 JASSERT(data[dataIdx++] == '-');
140
141 area->endAddr = (VA) readHex();
142 JASSERT(area->endAddr != NULL);
143
144 JASSERT(data[dataIdx++] == ' ');
145
146 JASSERT(area->endAddr >= area->addr);
147 area->size = area->endAddr - area->addr;
148
149 rflag = data[dataIdx++];
150 JASSERT((rflag == 'r') || (rflag == '-'));
151
152 wflag = data[dataIdx++];
153 JASSERT((wflag == 'w') || (wflag == '-'));
154
155 xflag = data[dataIdx++];
156 JASSERT((xflag == 'x') || (xflag == '-'));
157
158 sflag = data[dataIdx++];
159 JASSERT((sflag == 's') || (sflag == 'p'));
160
161 JASSERT(data[dataIdx++] == ' ');
162
163 area->offset = readHex();
164 JASSERT(data[dataIdx++] == ' ');
165
166 area->devmajor = readHex();
167 JASSERT(data[dataIdx++] == ':');
168
169 area->devminor = readHex();
170 JASSERT(data[dataIdx++] == ' ');
171
172 area->inodenum = readDec();
173
174 while (data[dataIdx] == ' ') {
175 dataIdx++;
176 }
177
178 area -> name[0] = '\0';
179 if (data[dataIdx] == '/' || data[dataIdx] == '[' || data[dataIdx] == '(') {
180 // absolute pathname, or [stack], [vdso], etc.
181 // On some machines, deleted files have a " (deleted)" prefix to the
182 // filename.
183 size_t i = 0;
184 while (data[dataIdx] != '\n') {
185 area->name[i++] = data[dataIdx++];
186 JASSERT(i < sizeof(area->name));
187 }
188 area -> name[i] = '\0';
189 }
190
191 JASSERT(data[dataIdx++] == '\n');
192
193 area -> prot = 0;
194 if (rflag == 'r') {
195 area -> prot |= PROT_READ;
196 }
197 if (wflag == 'w') {
198 area -> prot |= PROT_WRITE;
199 }
200 if (xflag == 'x') {
201 area -> prot |= PROT_EXEC;
202 }
203
204 area -> flags = MAP_FIXED;
205 if (sflag == 's') {
206 area -> flags |= MAP_SHARED;
207 }
208 if (sflag == 'p') {
209 area -> flags |= MAP_PRIVATE;
210 }
211 if (area -> name[0] == '\0') {
212 area -> flags |= MAP_ANONYMOUS;
213 }
214
215 return 1;
216 }