4
4
5
5
use super :: mystd:: fs:: File ;
6
6
use super :: mystd:: io:: Read ;
7
- use super :: mystd :: str :: FromStr ;
8
- use super :: { OsString , String , Vec } ;
7
+ use super :: OsString ;
8
+ use super :: { String , Vec } ;
9
9
10
10
#[ derive( PartialEq , Eq , Debug ) ]
11
- pub ( super ) struct MapsEntry {
11
+ pub struct MapsEntry {
12
12
/// start (inclusive) and limit (exclusive) of address range.
13
13
address : ( usize , usize ) ,
14
14
/// The perms field are the permissions for the entry
@@ -53,42 +53,6 @@ pub(super) struct MapsEntry {
53
53
pathname : OsString ,
54
54
}
55
55
56
- #[ cfg( not( target_os = "nto" ) ) ]
57
- pub ( super ) fn parse_maps ( ) -> Result < Vec < MapsEntry > , & ' static str > {
58
- let mut v = Vec :: new ( ) ;
59
- let mut proc_self_maps =
60
- File :: open ( "/proc/self/maps" ) . map_err ( |_| "Couldn't open /proc/self/maps" ) ?;
61
- let mut buf = String :: new ( ) ;
62
- let _bytes_read = proc_self_maps
63
- . read_to_string ( & mut buf)
64
- . map_err ( |_| "Couldn't read /proc/self/maps" ) ?;
65
- for line in buf. lines ( ) {
66
- v. push ( line. parse ( ) ?) ;
67
- }
68
-
69
- Ok ( v)
70
- }
71
-
72
- // TODO: This could be merged with the above block but seems to require
73
- // creating a couple of extra strings to pass to map_err(). Is
74
- // there a way to pass it paramenters without adding a bunch of
75
- // lines of code?
76
- #[ cfg( target_os = "nto" ) ]
77
- pub ( super ) fn parse_maps ( ) -> Result < Vec < MapsEntry > , & ' static str > {
78
- let mut v = Vec :: new ( ) ;
79
- let mut proc_self_maps =
80
- File :: open ( "/proc/self/pmap" ) . map_err ( |_| "Couldn't open /proc/self/pmap" ) ?;
81
- let mut buf = String :: new ( ) ;
82
- let _bytes_read = proc_self_maps
83
- . read_to_string ( & mut buf)
84
- . map_err ( |_| "Couldn't read /proc/self/pmap" ) ?;
85
- for line in buf. lines ( ) {
86
- v. push ( line. parse ( ) ?) ;
87
- }
88
-
89
- Ok ( v)
90
- }
91
-
92
56
impl MapsEntry {
93
57
pub ( super ) fn pathname ( & self ) -> & OsString {
94
58
& self . pathname
@@ -99,269 +63,51 @@ impl MapsEntry {
99
63
}
100
64
}
101
65
102
- #[ cfg( not( target_os = "nto" ) ) ]
103
- impl FromStr for MapsEntry {
104
- type Err = & ' static str ;
105
-
106
- // Format: address perms offset dev inode pathname
107
- // e.g.: "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]"
108
- // e.g.: "7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"
109
- // e.g.: "35b1a21000-35b1a22000 rw-p 00000000 00:00 0"
110
- fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
111
- let mut parts = s
112
- . split ( ' ' ) // space-separated fields
113
- . filter ( |s| s. len ( ) > 0 ) ; // multiple spaces implies empty strings that need to be skipped.
114
- let range_str = parts. next ( ) . ok_or ( "Couldn't find address" ) ?;
115
- let perms_str = parts. next ( ) . ok_or ( "Couldn't find permissions" ) ?;
116
- let offset_str = parts. next ( ) . ok_or ( "Couldn't find offset" ) ?;
117
- let dev_str = parts. next ( ) . ok_or ( "Couldn't find dev" ) ?;
118
- let inode_str = parts. next ( ) . ok_or ( "Couldn't find inode" ) ?;
119
- let pathname_str = parts. next ( ) . unwrap_or ( "" ) ; // pathname may be omitted.
120
-
121
- let hex = |s| usize:: from_str_radix ( s, 16 ) . map_err ( |_| "Couldn't parse hex number" ) ;
122
- let address = {
123
- // This could use `range_str.split_once('-')` once the MSRV passes 1.52.
124
- if let Some ( idx) = range_str. find ( '-' ) {
125
- let ( start, rest) = range_str. split_at ( idx) ;
126
- let ( _div, limit) = rest. split_at ( 1 ) ;
127
- ( hex ( start) ?, hex ( limit) ?)
128
- } else {
129
- return Err ( "Couldn't parse address range" ) ;
130
- }
131
- } ;
132
- let perms: [ char ; 4 ] = {
133
- let mut chars = perms_str. chars ( ) ;
134
- let mut c = || chars. next ( ) . ok_or ( "insufficient perms" ) ;
135
- let perms = [ c ( ) ?, c ( ) ?, c ( ) ?, c ( ) ?] ;
136
- if chars. next ( ) . is_some ( ) {
137
- return Err ( "too many perms" ) ;
138
- }
139
- perms
140
- } ;
141
- let offset = hex ( offset_str) ?;
142
- let dev = {
143
- // This could use `dev_str.split_once(':')` once the MSRV passes 1.52.
144
- if let Some ( idx) = dev_str. find ( ':' ) {
145
- let ( major, rest) = dev_str. split_at ( idx) ;
146
- let ( _div, minor) = rest. split_at ( 1 ) ;
147
- ( hex ( major) ?, hex ( minor) ?)
148
- } else {
149
- return Err ( "Couldn't parse dev" ) ?;
150
- }
151
- } ;
152
- let inode = hex ( inode_str) ?;
153
- let pathname = pathname_str. into ( ) ;
154
-
155
- Ok ( MapsEntry {
156
- address,
157
- perms,
158
- offset,
159
- dev,
160
- inode,
161
- pathname,
162
- } )
163
- }
66
+ fn concat_str ( a : & str , b : & str ) -> String {
67
+ let mut e = String :: from ( a) ;
68
+ e += b;
69
+ e
164
70
}
165
71
166
- #[ cfg( target_os = "nto" ) ]
167
- impl FromStr for MapsEntry {
168
- type Err = & ' static str ;
169
-
170
- // Format: vaddr,size,flags,prot,maxprot,dev,ino,offset,rsv,guardsize,refcnt,mapcnt,path
171
- // e.g.: "0x00000022fa36b000,0x0000000000002000,0x00000071,0x05,0x0f,0x0000040b,0x00000000000000dd,
172
- // 0x0000000000000000,0x0000000000000000,0x00000000,0x00000005,0x00000003,/proc/boot/cat"
173
- fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
174
- let mut parts = s. split ( ',' ) ;
175
- let vaddr_str = parts. next ( ) . ok_or ( "Couldn't find virtual address" ) ?;
176
- let size_str = parts. next ( ) . ok_or ( "Couldn't find size" ) ?;
177
- let _flags_str = parts. next ( ) . ok_or ( "Couldn't find flags" ) ?;
178
- let prot_str = parts. next ( ) . ok_or ( "Couldn't find protection" ) ?;
179
- let _maxprot_str = parts. next ( ) . ok_or ( "Couldn't find maximum protection" ) ?;
180
- let dev_str = parts. next ( ) . ok_or ( "Couldn't find device" ) ?;
181
- let ino_str = parts. next ( ) . ok_or ( "Couldn't find inode" ) ?;
182
- let offset_str = parts. next ( ) . ok_or ( "Couldn't find offset" ) ?;
183
- let _rsv_str = parts. next ( ) . ok_or ( "Couldn't find reserved pages" ) ?;
184
- let _guardsize_str = parts. next ( ) . ok_or ( "Couldn't find guard size" ) ?;
185
- let _refcnt_str = parts. next ( ) . ok_or ( "Couldn't find reference count" ) ?;
186
- let _mapcnt_str = parts. next ( ) . ok_or ( "Couldn't find mapped count" ) ?;
187
- let pathname_str = parts. next ( ) . unwrap_or ( "" ) ; // pathname may be omitted.
188
-
189
- let hex = |s : & str | usize:: from_str_radix ( & s[ 2 ..] , 16 ) . map_err ( |_| "Couldn't parse hex number" ) ;
190
- let address = { ( hex ( vaddr_str) ?, hex ( vaddr_str) ? + hex ( size_str) ?) } ;
191
-
192
- // TODO: Probably a rust'ier way of doing this
193
- let mut perms: [ char ; 4 ] = [ '-' , '-' , '-' , '-' ] ;
194
- let perm_str: [ char ; 3 ] = [ 'r' , 'w' , 'x' ] ;
195
- let perm_bits: [ usize ; 3 ] = [ 0x1 , 0x2 , 0x4 ] ;
196
-
197
- for ( pos, val) in perm_bits. iter ( ) . enumerate ( ) {
198
- let prot = hex ( prot_str) ?;
199
- if val & prot != 0 {
200
- perms[ pos] = perm_str[ pos]
201
- }
202
- }
203
-
204
- let offset = hex ( offset_str) ?;
205
- let dev = { ( hex ( dev_str) ?, 0x00000000 ) } ;
206
- let inode = hex ( ino_str) ?;
207
- let pathname = pathname_str. into ( ) ;
208
-
209
- Ok ( MapsEntry {
210
- address,
211
- perms,
212
- offset,
213
- dev,
214
- inode,
215
- pathname,
216
- } )
217
- }
72
+ fn read_file ( file : & str ) -> Result < String , String > {
73
+ let mut proc_self_maps =
74
+ File :: open ( file) . map_err ( |_| concat_str ( "Couldn't open file: " , file) ) ?;
75
+ let mut buf = String :: new ( ) ;
76
+ let _bytes_read = proc_self_maps
77
+ . read_to_string ( & mut buf)
78
+ . map_err ( |_| concat_str ( "Couldn't read file: " , file) ) ?;
79
+ Ok ( buf)
218
80
}
219
81
220
- // Make sure we can parse 64-bit sample output if we're on a 64-bit target.
221
- #[ cfg( target_pointer_width = "64" ) ]
222
- #[ test]
223
- #[ cfg( not( target_os = "nto" ) ) ]
224
- fn check_maps_entry_parsing_64bit ( ) {
225
- assert_eq ! (
226
- "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 \
227
- [vsyscall]"
228
- . parse:: <MapsEntry >( )
229
- . unwrap( ) ,
230
- MapsEntry {
231
- address: ( 0xffffffffff600000 , 0xffffffffff601000 ) ,
232
- perms: [ '-' , '-' , 'x' , 'p' ] ,
233
- offset: 0x00000000 ,
234
- dev: ( 0x00 , 0x00 ) ,
235
- inode: 0x0 ,
236
- pathname: "[vsyscall]" . into( ) ,
237
- }
238
- ) ;
239
-
240
- assert_eq ! (
241
- "7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 \
242
- /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"
243
- . parse:: <MapsEntry >( )
244
- . unwrap( ) ,
245
- MapsEntry {
246
- address: ( 0x7f5985f46000 , 0x7f5985f48000 ) ,
247
- perms: [ 'r' , 'w' , '-' , 'p' ] ,
248
- offset: 0x00039000 ,
249
- dev: ( 0x103 , 0x06 ) ,
250
- inode: 0x76021795 ,
251
- pathname: "/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2" . into( ) ,
252
- }
253
- ) ;
254
- assert_eq ! (
255
- "35b1a21000-35b1a22000 rw-p 00000000 00:00 0"
256
- . parse:: <MapsEntry >( )
257
- . unwrap( ) ,
258
- MapsEntry {
259
- address: ( 0x35b1a21000 , 0x35b1a22000 ) ,
260
- perms: [ 'r' , 'w' , '-' , 'p' ] ,
261
- offset: 0x00000000 ,
262
- dev: ( 0x00 , 0x00 ) ,
263
- inode: 0x0 ,
264
- pathname: Default :: default ( ) ,
265
- }
266
- ) ;
82
+ pub fn parse_maps ( ) -> Result < Vec < MapsEntry > , String > {
83
+ let ( file, skip) = config ( ) ;
84
+ let content = read_file ( file) ?;
85
+ parse_maps_lines ( & content, skip)
267
86
}
268
87
269
- #[ cfg( target_os = "nto" ) ]
270
- fn check_maps_entry_parsing_64bit ( ) {
271
- assert_eq ! (
272
- "0xffffffffff600000,0x0000000000001000,0x00000071,0x04,0x0f,0x00000000,0x0000000000000000,\
273
- 0x0000000000000000,0x0000000000000000,0x00000000,0x00000005,0x00000003,/proc/boot/foo"
274
- . parse:: <MapsEntry >( )
275
- . unwrap( ) ,
276
- MapsEntry {
277
- address: ( 0xffffffffff600000 , 0xffffffffff601000 ) ,
278
- perms: [ '-' , '-' , 'x' , '-' ] ,
279
- offset: 0x00000000 ,
280
- dev: ( 0x00 , 0x00 ) ,
281
- inode: 0x0 ,
282
- pathname: "/proc/boot/foo" . into( ) ,
283
- }
284
- ) ;
285
-
286
- assert_eq ! (
287
- "0x00007f5985f46000,0x0000000000002000,0x00000071,0x03,0x0f,0x00000103,0x0000000076021795,\
288
- 0x0000000000039000,0x0000000000000000,0x00000000,0x00000005,0x00000003,/usr/lib/ldqnx-64.so.2"
289
- . parse:: <MapsEntry >( )
290
- . unwrap( ) ,
291
- MapsEntry {
292
- address: ( 0x7f5985f46000 , 0x7f5985f48000 ) ,
293
- perms: [ 'r' , 'w' , '-' , '-' ] ,
294
- offset: 0x00039000 ,
295
- dev: ( 0x103 , 0x0 ) ,
296
- inode: 0x76021795 ,
297
- pathname: "/usr/lib/ldqnx-64.so.2" . into( ) ,
298
- }
299
- ) ;
300
- assert_eq ! (
301
- "0x00000035b1a21000,0x0000000000001000,0x00000071,0x03,0x0f,0x00000000,0x0000000000000000,\
302
- 0x0000000000000000,0x0000000000000000,0x00000000,0x00000005,0x00000003,"
303
- . parse:: <MapsEntry >( )
304
- . unwrap( ) ,
305
- MapsEntry {
306
- address: ( 0x35b1a21000 , 0x35b1a22000 ) ,
307
- perms: [ 'r' , 'w' , '-' , '-' ] ,
308
- offset: 0x00000000 ,
309
- dev: ( 0x00 , 0x00 ) ,
310
- inode: 0x0 ,
311
- pathname: Default :: default ( ) ,
312
- }
313
- ) ;
88
+ fn parse_maps_lines ( content : & str , skip : usize ) -> Result < Vec < MapsEntry > , String > {
89
+ let mut data = Vec :: new ( ) ;
90
+ for line in content. lines ( ) . skip ( skip) {
91
+ data. push ( line. parse ( ) ?) ;
92
+ }
93
+ Ok ( data)
314
94
}
315
95
316
- // (This output was taken from a 32-bit machine, but will work on any target)
317
- #[ cfg( not( target_os = "nto" ) ) ]
318
- #[ test]
319
- fn check_maps_entry_parsing_32bit ( ) {
320
- /* Example snippet of output:
321
- 08056000-08077000 rw-p 00000000 00:00 0 [heap]
322
- b7c79000-b7e02000 r--p 00000000 08:01 60662705 /usr/lib/locale/locale-archive
323
- b7e02000-b7e03000 rw-p 00000000 00:00 0
324
- */
325
- assert_eq ! (
326
- "08056000-08077000 rw-p 00000000 00:00 0 \
327
- [heap]"
328
- . parse:: <MapsEntry >( )
329
- . unwrap( ) ,
330
- MapsEntry {
331
- address: ( 0x08056000 , 0x08077000 ) ,
332
- perms: [ 'r' , 'w' , '-' , 'p' ] ,
333
- offset: 0x00000000 ,
334
- dev: ( 0x00 , 0x00 ) ,
335
- inode: 0x0 ,
336
- pathname: "[heap]" . into( ) ,
337
- }
338
- ) ;
96
+ cfg_if:: cfg_if! {
97
+ if #[ cfg( target_os = "nto" ) ] {
98
+ mod parse_running_mmaps_unix_nto;
99
+ use parse_running_mmaps_unix_nto:: * ;
100
+ } else {
101
+ mod parse_running_mmaps_unix_default;
102
+ use parse_running_mmaps_unix_default:: * ;
103
+ }
104
+ }
339
105
340
- assert_eq ! (
341
- "b7c79000-b7e02000 r--p 00000000 08:01 60662705 \
342
- /usr/lib/locale/locale-archive"
343
- . parse:: <MapsEntry >( )
344
- . unwrap( ) ,
345
- MapsEntry {
346
- address: ( 0xb7c79000 , 0xb7e02000 ) ,
347
- perms: [ 'r' , '-' , '-' , 'p' ] ,
348
- offset: 0x00000000 ,
349
- dev: ( 0x08 , 0x01 ) ,
350
- inode: 0x60662705 ,
351
- pathname: "/usr/lib/locale/locale-archive" . into( ) ,
352
- }
353
- ) ;
354
- assert_eq ! (
355
- "b7e02000-b7e03000 rw-p 00000000 00:00 0"
356
- . parse:: <MapsEntry >( )
357
- . unwrap( ) ,
358
- MapsEntry {
359
- address: ( 0xb7e02000 , 0xb7e03000 ) ,
360
- perms: [ 'r' , 'w' , '-' , 'p' ] ,
361
- offset: 0x00000000 ,
362
- dev: ( 0x00 , 0x00 ) ,
363
- inode: 0x0 ,
364
- pathname: Default :: default ( ) ,
365
- }
366
- ) ;
106
+ #[ cfg( test) ]
107
+ mod test {
108
+ #[ test]
109
+ fn test_parse_maps ( ) {
110
+ use super :: * ;
111
+ assert ! ( parse_maps( ) . is_ok( ) ) ;
112
+ }
367
113
}
0 commit comments