blob: b0733539f7916341b57d8353f0571e969913f811 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- A simple parser for /proc/self/maps on Linux 2.4.X ---*/
4/*--- vg_procselfmaps.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
13 Julian_Seward@muraroa.demon.co.uk
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file LICENSE.
31*/
32
33
34#include "vg_include.h"
35
36
37/* static ... to keep it out of the stack frame. */
38
39static Char procmap_buf[M_PROCMAP_BUF];
40
41
42/* Helper fns. */
43
44static Int hexdigit ( Char c )
45{
46 if (c >= '0' && c <= '9') return (Int)(c - '0');
47 if (c >= 'a' && c <= 'f') return 10 + (Int)(c - 'a');
48 if (c >= 'A' && c <= 'F') return 10 + (Int)(c - 'A');
49 return -1;
50}
51
52static Int readchar ( Char* buf, Char* ch )
53{
54 if (*buf == 0) return 0;
55 *ch = *buf;
56 return 1;
57}
58
59static Int readhex ( Char* buf, UInt* val )
60{
61 Int n = 0;
62 *val = 0;
63 while (hexdigit(*buf) >= 0) {
64 *val = (*val << 4) + hexdigit(*buf);
65 n++; buf++;
66 }
67 return n;
68}
69
70
71
72/* Read /proc/self/maps. For each map entry, call
73 record_mapping, passing it, in this order:
74
75 start address in memory
76 length
77 r permissions char; either - or r
78 w permissions char; either - or w
79 x permissions char; either - or x
80 offset in file, or zero if no file
81 filename, zero terminated, or NULL if no file
82
83 So the sig of the called fn might be
84
85 void (*record_mapping)( Addr start, UInt size,
86 Char r, Char w, Char x,
87 UInt foffset, UChar* filename )
88
89 Note that the supplied filename is transiently stored; record_mapping
90 should make a copy if it wants to keep it.
91
92 If there's a syntax error or other failure, just abort.
93*/
94
95void VG_(read_procselfmaps) (
96 void (*record_mapping)( Addr, UInt, Char, Char, Char, UInt, UChar* )
97)
98{
99 Int i, j, n_tot, n_chunk, fd, i_eol;
100 Addr start, endPlusOne;
101 UChar* filename;
102 UInt foffset;
103 UChar rr, ww, xx, pp, ch;
104
105 /* Read the initial memory mapping from the /proc filesystem. */
106 fd = VG_(open_read) ( "/proc/self/maps" );
107 if (fd == -1) {
108 VG_(message)(Vg_UserMsg, "FATAL: can't open /proc/self/maps");
109 VG_(exit)(1);
110 }
111 n_tot = 0;
112 do {
113 n_chunk = VG_(read) ( fd, &procmap_buf[n_tot], M_PROCMAP_BUF - n_tot );
114 n_tot += n_chunk;
115 } while ( n_chunk > 0 && n_tot < M_PROCMAP_BUF );
116 VG_(close)(fd);
117 if (n_tot >= M_PROCMAP_BUF-5) {
118 VG_(message)(Vg_UserMsg, "FATAL: M_PROCMAP_BUF is too small; "
119 "increase it and recompile");
120 VG_(exit)(1);
121 }
122 if (n_tot == 0) {
123 VG_(message)(Vg_UserMsg, "FATAL: I/O error on /proc/self/maps" );
124 VG_(exit)(1);
125 }
126 procmap_buf[n_tot] = 0;
127 if (0)
128 VG_(message)(Vg_DebugMsg, "raw:\n%s", procmap_buf );
129
130 /* Ok, it's safely aboard. Parse the entries. */
131
132 i = 0;
133 while (True) {
134 if (i >= n_tot) break;
135
136 /* Read (without fscanf :) the pattern %8x-%8x %c%c%c%c %8x */
137 j = readhex(&procmap_buf[i], &start);
138 if (j > 0) i += j; else goto syntaxerror;
139 j = readchar(&procmap_buf[i], &ch);
140 if (j == 1 && ch == '-') i += j; else goto syntaxerror;
141 j = readhex(&procmap_buf[i], &endPlusOne);
142 if (j > 0) i += j; else goto syntaxerror;
143
144 j = readchar(&procmap_buf[i], &ch);
145 if (j == 1 && ch == ' ') i += j; else goto syntaxerror;
146
147 j = readchar(&procmap_buf[i], &rr);
148 if (j == 1 && (rr == 'r' || rr == '-')) i += j; else goto syntaxerror;
149 j = readchar(&procmap_buf[i], &ww);
150 if (j == 1 && (ww == 'w' || ww == '-')) i += j; else goto syntaxerror;
151 j = readchar(&procmap_buf[i], &xx);
152 if (j == 1 && (xx == 'x' || xx == '-')) i += j; else goto syntaxerror;
153 /* I haven't a clue what this last field means. */
154 j = readchar(&procmap_buf[i], &pp);
155 if (j == 1 && (pp == 'p' || pp == '-' || pp == 's'))
156 i += j; else goto syntaxerror;
157
158 j = readchar(&procmap_buf[i], &ch);
159 if (j == 1 && ch == ' ') i += j; else goto syntaxerror;
160
161 j = readhex(&procmap_buf[i], &foffset);
162 if (j > 0) i += j; else goto syntaxerror;
163
164 goto read_line_ok;
165
166 syntaxerror:
167 VG_(message)(Vg_UserMsg, "FATAL: syntax error reading /proc/self/maps");
168 { Int k;
169 VG_(printf)("last 50 chars: `");
170 for (k = i-50; k <= i; k++) VG_(printf)("%c", procmap_buf[k]);
171 VG_(printf)("'\n");
172 }
173 VG_(exit)(1);
174
175 read_line_ok:
176 /* Try and find the name of the file mapped to this segment, if
177 it exists. */
178 while (procmap_buf[i] != '\n' && i < M_PROCMAP_BUF-1) i++;
179 i_eol = i;
180 i--;
181 while (!VG_(isspace)(procmap_buf[i]) && i >= 0) i--;
182 i++;
183 if (i < i_eol-1 && procmap_buf[i] == '/') {
184 filename = &procmap_buf[i];
185 filename[i_eol - i] = '\0';
186 } else {
187 filename = NULL;
188 foffset = 0;
189 }
190
191 (*record_mapping) ( start, endPlusOne-start,
192 rr, ww, xx,
193 foffset, filename );
194
195 i = i_eol + 1;
196 }
197}
198
199/*--------------------------------------------------------------------*/
200/*--- end vg_procselfmaps.c ---*/
201/*--------------------------------------------------------------------*/