-
Notifications
You must be signed in to change notification settings - Fork 248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for QNX Neutrino #507
base: master
Are you sure you want to change the base?
Changes from all commits
5c36819
12afb11
d528ac4
4204530
75e65e7
84fd7c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -53,19 +53,34 @@ pub(super) struct MapsEntry { | |||||||||
pathname: OsString, | ||||||||||
} | ||||||||||
|
||||||||||
pub(super) fn parse_maps() -> Result<Vec<MapsEntry>, &'static str> { | ||||||||||
let mut v = Vec::new(); | ||||||||||
fn concat_str(a: &str, b: &str) -> String { | ||||||||||
let mut e = String::from(a); | ||||||||||
e += b; | ||||||||||
e | ||||||||||
} | ||||||||||
|
||||||||||
fn read_file(file: &str) -> Result<String, String> { | ||||||||||
let mut proc_self_maps = | ||||||||||
File::open("/proc/self/maps").map_err(|_| "Couldn't open /proc/self/maps")?; | ||||||||||
File::open(file).map_err(|_| concat_str("Couldn't open file: ", file))?; | ||||||||||
let mut buf = String::new(); | ||||||||||
let _bytes_read = proc_self_maps | ||||||||||
.read_to_string(&mut buf) | ||||||||||
.map_err(|_| "Couldn't read /proc/self/maps")?; | ||||||||||
for line in buf.lines() { | ||||||||||
v.push(line.parse()?); | ||||||||||
} | ||||||||||
.map_err(|_| concat_str("Couldn't read file: ", file))?; | ||||||||||
Ok(buf) | ||||||||||
} | ||||||||||
|
||||||||||
Ok(v) | ||||||||||
pub(super) fn parse_maps() -> Result<Vec<MapsEntry>, String> { | ||||||||||
let (file, skip) = config(); | ||||||||||
let content = read_file(file)?; | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
parse_maps_lines(&content, skip) | ||||||||||
} | ||||||||||
|
||||||||||
fn parse_maps_lines(content: &str, skip: usize) -> Result<Vec<MapsEntry>, String> { | ||||||||||
Comment on lines
+75
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this is still functionally identical if we simply delete these lines?
Suggested change
|
||||||||||
let mut data = Vec::new(); | ||||||||||
for line in content.lines().skip(skip) { | ||||||||||
data.push(line.parse()?); | ||||||||||
} | ||||||||||
Ok(data) | ||||||||||
} | ||||||||||
|
||||||||||
impl MapsEntry { | ||||||||||
|
@@ -78,6 +93,12 @@ impl MapsEntry { | |||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
#[cfg(not(target_os = "nto"))] | ||||||||||
pub fn config() -> (&'static str, usize) { | ||||||||||
("/proc/self/maps", 0) | ||||||||||
} | ||||||||||
Comment on lines
+96
to
+99
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This moves to runtime what can be known at compile-time. Please describe a |
||||||||||
|
||||||||||
#[cfg(not(target_os = "nto"))] | ||||||||||
impl FromStr for MapsEntry { | ||||||||||
type Err = &'static str; | ||||||||||
|
||||||||||
|
@@ -141,13 +162,73 @@ impl FromStr for MapsEntry { | |||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
#[cfg(target_os = "nto")] | ||||||||||
pub fn config() -> (&'static str, usize) { | ||||||||||
("/proc/self/pmap", 1) | ||||||||||
} | ||||||||||
|
||||||||||
#[cfg(target_os = "nto")] | ||||||||||
impl FromStr for MapsEntry { | ||||||||||
type Err = &'static str; | ||||||||||
|
||||||||||
// Format: vaddr,size,flags,prot,maxprot,dev,ino,offset,rsv,guardsize,refcnt,mapcnt,path | ||||||||||
// e.g.: "0x00000022fa36b000,0x0000000000002000,0x00000071,0x05,0x0f,0x0000040b,0x00000000000000dd, | ||||||||||
// 0x0000000000000000,0x0000000000000000,0x00000000,0x00000005,0x00000003,/proc/boot/cat" | ||||||||||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||||||||||
let mut parts = s.split(','); | ||||||||||
let vaddr_str = parts.next().ok_or("Couldn't find virtual address")?; | ||||||||||
let size_str = parts.next().ok_or("Couldn't find size")?; | ||||||||||
let _flags_str = parts.next().ok_or("Couldn't find flags")?; | ||||||||||
let prot_str = parts.next().ok_or("Couldn't find protection")?; | ||||||||||
let _maxprot_str = parts.next().ok_or("Couldn't find maximum protection")?; | ||||||||||
let dev_str = parts.next().ok_or("Couldn't find device")?; | ||||||||||
let ino_str = parts.next().ok_or("Couldn't find inode")?; | ||||||||||
let offset_str = parts.next().ok_or("Couldn't find offset")?; | ||||||||||
let _rsv_str = parts.next().ok_or("Couldn't find reserved pages")?; | ||||||||||
let _guardsize_str = parts.next().ok_or("Couldn't find guard size")?; | ||||||||||
let _refcnt_str = parts.next().ok_or("Couldn't find reference count")?; | ||||||||||
let _mapcnt_str = parts.next().ok_or("Couldn't find mapped count")?; | ||||||||||
Comment on lines
+179
to
+190
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to be clear, on QNX Neutrino these are all required fields? Is there somewhere this format is documented for Neutrino? It seems to be a superset of the other format described here? |
||||||||||
let pathname_str = parts.next().unwrap_or(""); // pathname may be omitted. | ||||||||||
|
||||||||||
let hex = | ||||||||||
|s: &str| usize::from_str_radix(&s[2..], 16).map_err(|_| "Couldn't parse hex number"); | ||||||||||
let address = { (hex(vaddr_str)?, hex(vaddr_str)? + hex(size_str)?) }; | ||||||||||
|
||||||||||
// TODO: Probably a rust'ier way of doing this | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could probably cook something up using |
||||||||||
let mut perms: [char; 4] = ['-', '-', '-', '-']; | ||||||||||
let perm_str: [char; 3] = ['r', 'w', 'x']; | ||||||||||
let perm_bits: [usize; 3] = [0x1, 0x2, 0x4]; | ||||||||||
|
||||||||||
for (pos, val) in perm_bits.iter().enumerate() { | ||||||||||
let prot = hex(prot_str)?; | ||||||||||
if val & prot != 0 { | ||||||||||
perms[pos] = perm_str[pos] | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
let offset = hex(offset_str)?; | ||||||||||
let dev = { (hex(dev_str)?, 0x00000000) }; | ||||||||||
let inode = hex(ino_str)?; | ||||||||||
let pathname = pathname_str.into(); | ||||||||||
|
||||||||||
Ok(MapsEntry { | ||||||||||
address, | ||||||||||
perms, | ||||||||||
offset, | ||||||||||
dev, | ||||||||||
inode, | ||||||||||
pathname, | ||||||||||
}) | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
// Make sure we can parse 64-bit sample output if we're on a 64-bit target. | ||||||||||
#[cfg(target_pointer_width = "64")] | ||||||||||
#[cfg(all(target_pointer_width = "64", not(target_os = "nto")))] | ||||||||||
#[test] | ||||||||||
fn check_maps_entry_parsing_64bit() { | ||||||||||
assert_eq!( | ||||||||||
"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 \ | ||||||||||
[vsyscall]" | ||||||||||
[vsyscall]" | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason for diffing this line? |
||||||||||
.parse::<MapsEntry>() | ||||||||||
.unwrap(), | ||||||||||
MapsEntry { | ||||||||||
|
@@ -162,7 +243,7 @@ fn check_maps_entry_parsing_64bit() { | |||||||||
|
||||||||||
assert_eq!( | ||||||||||
"7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 \ | ||||||||||
/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2" | ||||||||||
/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2" | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason for diffing this line? |
||||||||||
.parse::<MapsEntry>() | ||||||||||
.unwrap(), | ||||||||||
MapsEntry { | ||||||||||
|
@@ -190,6 +271,7 @@ fn check_maps_entry_parsing_64bit() { | |||||||||
} | ||||||||||
|
||||||||||
// (This output was taken from a 32-bit machine, but will work on any target) | ||||||||||
#[cfg(not(target_os = "nto"))] | ||||||||||
#[test] | ||||||||||
fn check_maps_entry_parsing_32bit() { | ||||||||||
/* Example snippet of output: | ||||||||||
|
@@ -240,3 +322,51 @@ fn check_maps_entry_parsing_32bit() { | |||||||||
} | ||||||||||
); | ||||||||||
} | ||||||||||
|
||||||||||
#[cfg(target_os = "nto")] | ||||||||||
#[test] | ||||||||||
fn check_maps_entry_parsing_64bit() { | ||||||||||
assert_eq!( | ||||||||||
"0xffffffffff600000,0x0000000000001000,0x00000071,0x04,0x0f,0x00000000,0x0000000000000000,\ | ||||||||||
0x0000000000000000,0x0000000000000000,0x00000000,0x00000005,0x00000003,/proc/boot/foo" | ||||||||||
.parse::<MapsEntry>() | ||||||||||
.unwrap(), | ||||||||||
MapsEntry { | ||||||||||
address: (0xffffffffff600000, 0xffffffffff601000), | ||||||||||
perms: ['-', '-', 'x', '-'], | ||||||||||
offset: 0x00000000, | ||||||||||
dev: (0x00, 0x00), | ||||||||||
inode: 0x0, | ||||||||||
pathname: "/proc/boot/foo".into(), | ||||||||||
} | ||||||||||
); | ||||||||||
|
||||||||||
assert_eq!( | ||||||||||
"0x00007f5985f46000,0x0000000000002000,0x00000071,0x03,0x0f,0x00000103,0x0000000076021795,\ | ||||||||||
0x0000000000039000,0x0000000000000000,0x00000000,0x00000005,0x00000003,/usr/lib/ldqnx-64.so.2" | ||||||||||
.parse::<MapsEntry>() | ||||||||||
.unwrap(), | ||||||||||
MapsEntry { | ||||||||||
address: (0x7f5985f46000, 0x7f5985f48000), | ||||||||||
perms: ['r', 'w', '-', '-'], | ||||||||||
offset: 0x00039000, | ||||||||||
dev: (0x103, 0x0), | ||||||||||
inode: 0x76021795, | ||||||||||
pathname: "/usr/lib/ldqnx-64.so.2".into(), | ||||||||||
} | ||||||||||
); | ||||||||||
assert_eq!( | ||||||||||
"0x00000035b1a21000,0x0000000000001000,0x00000071,0x03,0x0f,0x00000000,0x0000000000000000,\ | ||||||||||
0x0000000000000000,0x0000000000000000,0x00000000,0x00000005,0x00000003," | ||||||||||
.parse::<MapsEntry>() | ||||||||||
.unwrap(), | ||||||||||
MapsEntry { | ||||||||||
address: (0x35b1a21000, 0x35b1a22000), | ||||||||||
perms: ['r', 'w', '-', '-'], | ||||||||||
offset: 0x00000000, | ||||||||||
dev: (0x00, 0x00), | ||||||||||
inode: 0x0, | ||||||||||
pathname: Default::default(), | ||||||||||
} | ||||||||||
); | ||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This machinery is a reimplementation of
fs::read_to_string
. You can importfs
by changingIf you must, you can use
map_err
for the Err variant.