Skip to content

Commit 12afb11

Browse files
author
gh-tr
committed
Initial attempt at adding process map parsing
1 parent 5c36819 commit 12afb11

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

src/symbolize/gimli/parse_running_mmaps_unix.rs

+125
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub(super) struct MapsEntry {
5353
pathname: OsString,
5454
}
5555

56+
#[cfg(not(target_os = "nto"))]
5657
pub(super) fn parse_maps() -> Result<Vec<MapsEntry>, &'static str> {
5758
let mut v = Vec::new();
5859
let mut proc_self_maps =
@@ -68,6 +69,26 @@ pub(super) fn parse_maps() -> Result<Vec<MapsEntry>, &'static str> {
6869
Ok(v)
6970
}
7071

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+
7192
impl MapsEntry {
7293
pub(super) fn pathname(&self) -> &OsString {
7394
&self.pathname
@@ -78,6 +99,7 @@ impl MapsEntry {
7899
}
79100
}
80101

102+
#[cfg(not(target_os = "nto"))]
81103
impl FromStr for MapsEntry {
82104
type Err = &'static str;
83105

@@ -141,9 +163,64 @@ impl FromStr for MapsEntry {
141163
}
142164
}
143165

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+
}
218+
}
219+
144220
// Make sure we can parse 64-bit sample output if we're on a 64-bit target.
145221
#[cfg(target_pointer_width = "64")]
146222
#[test]
223+
#[cfg(not(target_os = "nto"))]
147224
fn check_maps_entry_parsing_64bit() {
148225
assert_eq!(
149226
"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 \
@@ -189,7 +266,55 @@ fn check_maps_entry_parsing_64bit() {
189266
);
190267
}
191268

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+
);
314+
}
315+
192316
// (This output was taken from a 32-bit machine, but will work on any target)
317+
#[cfg(not(target_os = "nto"))]
193318
#[test]
194319
fn check_maps_entry_parsing_32bit() {
195320
/* Example snippet of output:

0 commit comments

Comments
 (0)