From 9300a465016c7474ee61d6cefa97c662c190aeff Mon Sep 17 00:00:00 2001 From: edef Date: Sat, 30 Jul 2022 02:07:13 +0000 Subject: ripple/minitrace: dump early memory mappings These are from right after exec(2), so they are all done by the kernel. Change-Id: Ic76aa9c40acac64462fa6ab5c33cabcee3e096e5 --- ripple/minitrace/src/maps_file.rs | 186 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 ripple/minitrace/src/maps_file.rs (limited to 'ripple/minitrace/src/maps_file.rs') diff --git a/ripple/minitrace/src/maps_file.rs b/ripple/minitrace/src/maps_file.rs new file mode 100644 index 0000000..84fc0fb --- /dev/null +++ b/ripple/minitrace/src/maps_file.rs @@ -0,0 +1,186 @@ +// SPDX-FileCopyrightText: edef +// SPDX-License-Identifier: OSL-3.0 + +use { + anyhow::bail, + nom::{ + branch::alt, + bytes::complete::{tag, take_while}, + combinator::map_res, + sequence::tuple, + IResult, + }, + std::fmt::{self, Debug}, +}; + +fn whitespace(s: &str) -> IResult<&str, &str> { + take_while(|c| c == ' ')(s) +} + +fn hex_u32(s: &str) -> IResult<&str, u32> { + map_res(take_while(|c: char| c.is_ascii_hexdigit()), |src| { + u32::from_str_radix(src, 16) + })(s) +} + +fn hex_u64(s: &str) -> IResult<&str, u64> { + map_res(take_while(|c: char| c.is_ascii_hexdigit()), |src| { + u64::from_str_radix(src, 16) + })(s) +} + +fn dec_u64(s: &str) -> IResult<&str, u64> { + map_res(take_while(|c: char| c.is_ascii_hexdigit()), |src| { + u64::from_str_radix(src, 10) + })(s) +} + +fn perm(c: &'static str) -> impl Fn(&str) -> IResult<&str, bool> { + move |input| { + let (input, tag) = alt((tag(c), tag("-")))(input)?; + Ok((input, tag != "-")) + } +} + +fn shared(input: &str) -> IResult<&str, bool> { + let (input, tag) = alt((tag("p"), tag("s")))(input)?; + Ok((input, tag == "s")) +} + +fn pathname(input: &str) -> IResult<&str, &str> { + take_while(|c| c != '\n')(input) +} + +fn mapping(input: &str) -> IResult<&str, Mapping> { + let ( + input, + ( + start, + _, + end, + _, + perm_read, + perm_write, + perm_exec, + shared, + _, + offset, + _, + dev_maj, + _, + dev_min, + _, + inode, + _, + pathname, + ), + ) = tuple(( + hex_u64, + tag("-"), + hex_u64, + whitespace, + perm("r"), + perm("w"), + perm("x"), + shared, + whitespace, + hex_u64, + whitespace, + hex_u32, + tag(":"), + hex_u32, + whitespace, + dec_u64, + whitespace, + pathname, + ))(input)?; + Ok(( + input, + Mapping { + start, + end, + perm_read, + perm_write, + perm_exec, + shared, + offset, + dev: (dev_maj, dev_min), + inode, + pathname: pathname.to_owned(), + }, + )) +} + +pub(crate) fn parse_mapping_line(line: &str) -> anyhow::Result { + match mapping(line) { + Ok(("", mapping)) => Ok(mapping), + Ok(_) => unreachable!(), + Err(err) => bail!("Cannot parse mapping: {err}"), + } +} + +#[derive(Eq, PartialEq)] +pub(crate) struct Mapping { + start: u64, + end: u64, + perm_read: bool, + perm_write: bool, + perm_exec: bool, + shared: bool, + offset: u64, + dev: (u32, u32), + inode: u64, + pathname: String, +} + +impl Debug for Mapping { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use std::fmt::Write; + + let Mapping { + start, + end, + perm_read, + perm_write, + perm_exec, + shared, + offset, + dev: (dev_maj, dev_min), + inode, + ref pathname, + } = *self; + + write!(f, "{start:016x}-{end:016x} ")?; + + for (c, p) in [('r', perm_read), ('w', perm_write), ('x', perm_exec)] { + f.write_char(if p { c } else { '-' })?; + } + f.write_char(if shared { 's' } else { 'p' })?; + f.write_char(' ')?; + + write!( + f, + "{offset:016x} {dev_maj:04x}:{dev_min:04x} {inode:20} {pathname}" + ) + } +} + +#[test] +fn golden_mapping() { + let line = + "00400000-00407000 r--p 00000000 00:1e 7507895 /nix/store/hgl0ydlkgs6y6hx9h7k209shw3v7z77j-coreutils-9.0/bin/coreutils"; + let golden = Mapping { + start: 0x00400000, + end: 0x00407000, + perm_read: true, + perm_write: false, + perm_exec: false, + shared: false, + offset: 0, + dev: (0x00, 0x1e), + inode: 7507895, + pathname: "/nix/store/hgl0ydlkgs6y6hx9h7k209shw3v7z77j-coreutils-9.0/bin/coreutils" + .to_owned(), + }; + assert_eq!(mapping(line).unwrap().1, golden); +} -- cgit 1.4.1