Skip to content

Commit 75e65e7

Browse files
author
gh-tr
committed
Merged separate OS implementations into the original source file as the automated build system is unhappy about naming conventions on 1.42.0
1 parent 4204530 commit 75e65e7

File tree

3 files changed

+284
-301
lines changed

3 files changed

+284
-301
lines changed

src/symbolize/gimli/parse_running_mmaps_unix.rs

+284-25
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
use super::mystd::fs::File;
66
use super::mystd::io::Read;
7-
use super::OsString;
8-
use super::{String, Vec};
7+
use super::mystd::str::FromStr;
8+
use super::{OsString, String, Vec};
99

1010
#[derive(PartialEq, Eq, Debug)]
1111
pub struct MapsEntry {
@@ -53,16 +53,6 @@ pub struct MapsEntry {
5353
pathname: OsString,
5454
}
5555

56-
impl MapsEntry {
57-
pub(super) fn pathname(&self) -> &OsString {
58-
&self.pathname
59-
}
60-
61-
pub(super) fn ip_matches(&self, ip: usize) -> bool {
62-
self.address.0 <= ip && ip < self.address.1
63-
}
64-
}
65-
6656
fn concat_str(a: &str, b: &str) -> String {
6757
let mut e = String::from(a);
6858
e += b;
@@ -93,21 +83,290 @@ fn parse_maps_lines(content: &str, skip: usize) -> Result<Vec<MapsEntry>, String
9383
Ok(data)
9484
}
9585

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::*;
86+
impl MapsEntry {
87+
pub(super) fn pathname(&self) -> &OsString {
88+
&self.pathname
89+
}
90+
91+
pub(super) fn ip_matches(&self, ip: usize) -> bool {
92+
self.address.0 <= ip && ip < self.address.1
93+
}
94+
}
95+
96+
#[cfg(not(target_os = "nto"))]
97+
pub fn config() -> (&'static str, usize) {
98+
("/proc/self/maps", 0)
99+
}
100+
101+
#[cfg(not(target_os = "nto"))]
102+
impl FromStr for MapsEntry {
103+
type Err = &'static str;
104+
105+
// Format: address perms offset dev inode pathname
106+
// e.g.: "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]"
107+
// e.g.: "7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"
108+
// e.g.: "35b1a21000-35b1a22000 rw-p 00000000 00:00 0"
109+
fn from_str(s: &str) -> Result<Self, Self::Err> {
110+
let mut parts = s
111+
.split(' ') // space-separated fields
112+
.filter(|s| s.len() > 0); // multiple spaces implies empty strings that need to be skipped.
113+
let range_str = parts.next().ok_or("Couldn't find address")?;
114+
let perms_str = parts.next().ok_or("Couldn't find permissions")?;
115+
let offset_str = parts.next().ok_or("Couldn't find offset")?;
116+
let dev_str = parts.next().ok_or("Couldn't find dev")?;
117+
let inode_str = parts.next().ok_or("Couldn't find inode")?;
118+
let pathname_str = parts.next().unwrap_or(""); // pathname may be omitted.
119+
120+
let hex = |s| usize::from_str_radix(s, 16).map_err(|_| "Couldn't parse hex number");
121+
let address = {
122+
// This could use `range_str.split_once('-')` once the MSRV passes 1.52.
123+
if let Some(idx) = range_str.find('-') {
124+
let (start, rest) = range_str.split_at(idx);
125+
let (_div, limit) = rest.split_at(1);
126+
(hex(start)?, hex(limit)?)
127+
} else {
128+
return Err("Couldn't parse address range");
129+
}
130+
};
131+
let perms: [char; 4] = {
132+
let mut chars = perms_str.chars();
133+
let mut c = || chars.next().ok_or("insufficient perms");
134+
let perms = [c()?, c()?, c()?, c()?];
135+
if chars.next().is_some() {
136+
return Err("too many perms");
137+
}
138+
perms
139+
};
140+
let offset = hex(offset_str)?;
141+
let dev = {
142+
// This could use `dev_str.split_once(':')` once the MSRV passes 1.52.
143+
if let Some(idx) = dev_str.find(':') {
144+
let (major, rest) = dev_str.split_at(idx);
145+
let (_div, minor) = rest.split_at(1);
146+
(hex(major)?, hex(minor)?)
147+
} else {
148+
return Err("Couldn't parse dev")?;
149+
}
150+
};
151+
let inode = hex(inode_str)?;
152+
let pathname = pathname_str.into();
153+
154+
Ok(MapsEntry {
155+
address,
156+
perms,
157+
offset,
158+
dev,
159+
inode,
160+
pathname,
161+
})
103162
}
104163
}
105164

106-
#[cfg(test)]
107-
mod test {
108-
#[test]
109-
fn test_parse_maps() {
110-
use super::*;
111-
assert!(parse_maps().is_ok());
165+
#[cfg(target_os = "nto")]
166+
pub fn config() -> (&'static str, usize) {
167+
("/proc/self/pmap", 1)
168+
}
169+
170+
#[cfg(target_os = "nto")]
171+
impl FromStr for MapsEntry {
172+
type Err = &'static str;
173+
174+
// Format: vaddr,size,flags,prot,maxprot,dev,ino,offset,rsv,guardsize,refcnt,mapcnt,path
175+
// e.g.: "0x00000022fa36b000,0x0000000000002000,0x00000071,0x05,0x0f,0x0000040b,0x00000000000000dd,
176+
// 0x0000000000000000,0x0000000000000000,0x00000000,0x00000005,0x00000003,/proc/boot/cat"
177+
fn from_str(s: &str) -> Result<Self, Self::Err> {
178+
let mut parts = s.split(',');
179+
let vaddr_str = parts.next().ok_or("Couldn't find virtual address")?;
180+
let size_str = parts.next().ok_or("Couldn't find size")?;
181+
let _flags_str = parts.next().ok_or("Couldn't find flags")?;
182+
let prot_str = parts.next().ok_or("Couldn't find protection")?;
183+
let _maxprot_str = parts.next().ok_or("Couldn't find maximum protection")?;
184+
let dev_str = parts.next().ok_or("Couldn't find device")?;
185+
let ino_str = parts.next().ok_or("Couldn't find inode")?;
186+
let offset_str = parts.next().ok_or("Couldn't find offset")?;
187+
let _rsv_str = parts.next().ok_or("Couldn't find reserved pages")?;
188+
let _guardsize_str = parts.next().ok_or("Couldn't find guard size")?;
189+
let _refcnt_str = parts.next().ok_or("Couldn't find reference count")?;
190+
let _mapcnt_str = parts.next().ok_or("Couldn't find mapped count")?;
191+
let pathname_str = parts.next().unwrap_or(""); // pathname may be omitted.
192+
193+
let hex =
194+
|s: &str| usize::from_str_radix(&s[2..], 16).map_err(|_| "Couldn't parse hex number");
195+
let address = { (hex(vaddr_str)?, hex(vaddr_str)? + hex(size_str)?) };
196+
197+
// TODO: Probably a rust'ier way of doing this
198+
let mut perms: [char; 4] = ['-', '-', '-', '-'];
199+
let perm_str: [char; 3] = ['r', 'w', 'x'];
200+
let perm_bits: [usize; 3] = [0x1, 0x2, 0x4];
201+
202+
for (pos, val) in perm_bits.iter().enumerate() {
203+
let prot = hex(prot_str)?;
204+
if val & prot != 0 {
205+
perms[pos] = perm_str[pos]
206+
}
207+
}
208+
209+
let offset = hex(offset_str)?;
210+
let dev = { (hex(dev_str)?, 0x00000000) };
211+
let inode = hex(ino_str)?;
212+
let pathname = pathname_str.into();
213+
214+
Ok(MapsEntry {
215+
address,
216+
perms,
217+
offset,
218+
dev,
219+
inode,
220+
pathname,
221+
})
112222
}
113223
}
224+
225+
// Make sure we can parse 64-bit sample output if we're on a 64-bit target.
226+
#[cfg(all(target_pointer_width = "64", not(target_os = "nto")))]
227+
#[test]
228+
fn check_maps_entry_parsing_64bit() {
229+
assert_eq!(
230+
"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 \
231+
[vsyscall]"
232+
.parse::<MapsEntry>()
233+
.unwrap(),
234+
MapsEntry {
235+
address: (0xffffffffff600000, 0xffffffffff601000),
236+
perms: ['-', '-', 'x', 'p'],
237+
offset: 0x00000000,
238+
dev: (0x00, 0x00),
239+
inode: 0x0,
240+
pathname: "[vsyscall]".into(),
241+
}
242+
);
243+
244+
assert_eq!(
245+
"7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 \
246+
/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"
247+
.parse::<MapsEntry>()
248+
.unwrap(),
249+
MapsEntry {
250+
address: (0x7f5985f46000, 0x7f5985f48000),
251+
perms: ['r', 'w', '-', 'p'],
252+
offset: 0x00039000,
253+
dev: (0x103, 0x06),
254+
inode: 0x76021795,
255+
pathname: "/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2".into(),
256+
}
257+
);
258+
assert_eq!(
259+
"35b1a21000-35b1a22000 rw-p 00000000 00:00 0"
260+
.parse::<MapsEntry>()
261+
.unwrap(),
262+
MapsEntry {
263+
address: (0x35b1a21000, 0x35b1a22000),
264+
perms: ['r', 'w', '-', 'p'],
265+
offset: 0x00000000,
266+
dev: (0x00, 0x00),
267+
inode: 0x0,
268+
pathname: Default::default(),
269+
}
270+
);
271+
}
272+
273+
// (This output was taken from a 32-bit machine, but will work on any target)
274+
#[cfg(not(target_os = "nto"))]
275+
#[test]
276+
fn check_maps_entry_parsing_32bit() {
277+
/* Example snippet of output:
278+
08056000-08077000 rw-p 00000000 00:00 0 [heap]
279+
b7c79000-b7e02000 r--p 00000000 08:01 60662705 /usr/lib/locale/locale-archive
280+
b7e02000-b7e03000 rw-p 00000000 00:00 0
281+
*/
282+
assert_eq!(
283+
"08056000-08077000 rw-p 00000000 00:00 0 \
284+
[heap]"
285+
.parse::<MapsEntry>()
286+
.unwrap(),
287+
MapsEntry {
288+
address: (0x08056000, 0x08077000),
289+
perms: ['r', 'w', '-', 'p'],
290+
offset: 0x00000000,
291+
dev: (0x00, 0x00),
292+
inode: 0x0,
293+
pathname: "[heap]".into(),
294+
}
295+
);
296+
297+
assert_eq!(
298+
"b7c79000-b7e02000 r--p 00000000 08:01 60662705 \
299+
/usr/lib/locale/locale-archive"
300+
.parse::<MapsEntry>()
301+
.unwrap(),
302+
MapsEntry {
303+
address: (0xb7c79000, 0xb7e02000),
304+
perms: ['r', '-', '-', 'p'],
305+
offset: 0x00000000,
306+
dev: (0x08, 0x01),
307+
inode: 0x60662705,
308+
pathname: "/usr/lib/locale/locale-archive".into(),
309+
}
310+
);
311+
assert_eq!(
312+
"b7e02000-b7e03000 rw-p 00000000 00:00 0"
313+
.parse::<MapsEntry>()
314+
.unwrap(),
315+
MapsEntry {
316+
address: (0xb7e02000, 0xb7e03000),
317+
perms: ['r', 'w', '-', 'p'],
318+
offset: 0x00000000,
319+
dev: (0x00, 0x00),
320+
inode: 0x0,
321+
pathname: Default::default(),
322+
}
323+
);
324+
}
325+
326+
#[cfg(target_os = "nto")]
327+
#[test]
328+
fn check_maps_entry_parsing_64bit() {
329+
assert_eq!(
330+
"0xffffffffff600000,0x0000000000001000,0x00000071,0x04,0x0f,0x00000000,0x0000000000000000,\
331+
0x0000000000000000,0x0000000000000000,0x00000000,0x00000005,0x00000003,/proc/boot/foo"
332+
.parse::<MapsEntry>()
333+
.unwrap(),
334+
MapsEntry {
335+
address: (0xffffffffff600000, 0xffffffffff601000),
336+
perms: ['-', '-', 'x', '-'],
337+
offset: 0x00000000,
338+
dev: (0x00, 0x00),
339+
inode: 0x0,
340+
pathname: "/proc/boot/foo".into(),
341+
}
342+
);
343+
344+
assert_eq!(
345+
"0x00007f5985f46000,0x0000000000002000,0x00000071,0x03,0x0f,0x00000103,0x0000000076021795,\
346+
0x0000000000039000,0x0000000000000000,0x00000000,0x00000005,0x00000003,/usr/lib/ldqnx-64.so.2"
347+
.parse::<MapsEntry>()
348+
.unwrap(),
349+
MapsEntry {
350+
address: (0x7f5985f46000, 0x7f5985f48000),
351+
perms: ['r', 'w', '-', '-'],
352+
offset: 0x00039000,
353+
dev: (0x103, 0x0),
354+
inode: 0x76021795,
355+
pathname: "/usr/lib/ldqnx-64.so.2".into(),
356+
}
357+
);
358+
assert_eq!(
359+
"0x00000035b1a21000,0x0000000000001000,0x00000071,0x03,0x0f,0x00000000,0x0000000000000000,\
360+
0x0000000000000000,0x0000000000000000,0x00000000,0x00000005,0x00000003,"
361+
.parse::<MapsEntry>()
362+
.unwrap(),
363+
MapsEntry {
364+
address: (0x35b1a21000, 0x35b1a22000),
365+
perms: ['r', 'w', '-', '-'],
366+
offset: 0x00000000,
367+
dev: (0x00, 0x00),
368+
inode: 0x0,
369+
pathname: Default::default(),
370+
}
371+
);
372+
}

0 commit comments

Comments
 (0)