Skip to content

Commit d528ac4

Browse files
flba-ebgh-tr
authored andcommitted
Split Linux and nto code into separate mods
1 parent 12afb11 commit d528ac4

4 files changed

+300
-296
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ exclude = [
2727
[dependencies]
2828
cfg-if = "1.0"
2929
rustc-demangle = "0.1.4"
30-
libc = { version = "0.2.94", default-features = false }
30+
libc = { version = "0.2.139", default-features = false }
3131

3232
# Optionally enable the ability to serialize a `Backtrace`, controlled through
3333
# the `serialize-*` features below.

src/symbolize/gimli/parse_running_mmaps_unix.rs

+41-295
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
use super::mystd::fs::File;
66
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};
99

1010
#[derive(PartialEq, Eq, Debug)]
11-
pub(super) struct MapsEntry {
11+
pub struct MapsEntry {
1212
/// start (inclusive) and limit (exclusive) of address range.
1313
address: (usize, usize),
1414
/// The perms field are the permissions for the entry
@@ -53,42 +53,6 @@ pub(super) struct MapsEntry {
5353
pathname: OsString,
5454
}
5555

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-
9256
impl MapsEntry {
9357
pub(super) fn pathname(&self) -> &OsString {
9458
&self.pathname
@@ -99,269 +63,51 @@ impl MapsEntry {
9963
}
10064
}
10165

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
16470
}
16571

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)
21880
}
21981

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)
26786
}
26887

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)
31494
}
31595

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+
}
339105

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+
}
367113
}

0 commit comments

Comments
 (0)