diff --git a/src/uu/pmap/src/maps_format_parser.rs b/src/uu/pmap/src/maps_format_parser.rs index 65163634..0e077609 100644 --- a/src/uu/pmap/src/maps_format_parser.rs +++ b/src/uu/pmap/src/maps_format_parser.rs @@ -10,15 +10,37 @@ use std::io::{Error, ErrorKind}; // Represents a parsed single line from /proc//maps. #[derive(Debug, Clone, Default, PartialEq)] pub struct MapLine { - pub address: String, + pub address: Address, pub size_in_kb: u64, pub perms: Perms, pub offset: String, - pub device: String, + pub device: Device, pub inode: u64, pub mapping: String, } +#[derive(Debug, Clone, Default, PartialEq)] +pub struct Address { + pub start: String, + pub low: u64, + pub high: u64, +} + +impl fmt::Display for Address { + // By default, pads with white spaces. + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{: >16}", self.start) + } +} + +impl Address { + // Format for default, extended option, and device option. + // Pads the start address with zero. + pub fn zero_pad(&self) -> String { + format!("{:0>16}", self.start) + } +} + // Represents a set of permissions from the "perms" column of /proc//maps. #[derive(Clone, Copy, Debug, Default, PartialEq)] pub struct Perms { @@ -69,6 +91,28 @@ impl Perms { } } +#[derive(Debug, Clone, Default, PartialEq)] +pub struct Device { + pub major: String, + pub minor: String, + pub width: usize, +} + +impl fmt::Display for Device { + // By default, does not pad. + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}:{}", self.major, self.minor) + } +} + +impl Device { + // Format for device option. + // Pads the device info from /proc//maps with zeros and turns AB:CD into 0AB:000CD. + pub fn device(&self) -> String { + format!("{:0>3}:{:0>5}", self.major, self.minor) + } +} + // Parses a single line from /proc//maps. See // https://www.kernel.org/doc/html/latest/filesystems/proc.html for details about the expected // format. @@ -90,7 +134,7 @@ pub fn parse_map_line(line: &str) -> Result { let (offset, rest) = rest .split_once(' ') .ok_or_else(|| Error::from(ErrorKind::InvalidData))?; - let offset = format!("{offset:0>16}"); + let offset = format!("{offset:0>8}"); let (device, rest) = rest .split_once(' ') @@ -116,9 +160,8 @@ pub fn parse_map_line(line: &str) -> Result { }) } -// Returns the start address and the size of the provided memory range. The start address is always -// 16-digits and padded with 0, if necessary. The size is in KB. -fn parse_address(memory_range: &str) -> Result<(String, u64), Error> { +// Returns Address instance and the size of the provided memory range. The size is in KB. +fn parse_address(memory_range: &str) -> Result<(Address, u64), Error> { let (start, end) = memory_range .split_once('-') .ok_or_else(|| Error::from(ErrorKind::InvalidData))?; @@ -127,15 +170,26 @@ fn parse_address(memory_range: &str) -> Result<(String, u64), Error> { let high = u64::from_str_radix(end, 16).map_err(|_| Error::from(ErrorKind::InvalidData))?; let size_in_kb = (high - low) / 1024; - Ok((format!("{start:0>16}"), size_in_kb)) + Ok(( + Address { + start: start.to_string(), + low, + high, + }, + size_in_kb, + )) } -// Pads the device info from /proc//maps with zeros and turns AB:CD into 0AB:000CD. -fn parse_device(device: &str) -> Result { +// Returns Device instance. +fn parse_device(device: &str) -> Result { let (major, minor) = device .split_once(':') .ok_or_else(|| Error::from(ErrorKind::InvalidData))?; - Ok(format!("{major:0>3}:{minor:0>5}")) + Ok(Device { + major: major.to_string(), + minor: minor.to_string(), + width: device.len(), + }) } impl MapLine { @@ -174,19 +228,31 @@ mod test { fn create_map_line( address: &str, + low: u64, + high: u64, size_in_kb: u64, perms: Perms, offset: &str, - device: &str, + major: &str, + minor: &str, + width: usize, inode: u64, mapping: &str, ) -> MapLine { MapLine { - address: address.to_string(), + address: Address { + start: address.to_string(), + low, + high, + }, size_in_kb, perms, offset: offset.to_string(), - device: device.to_string(), + device: Device { + major: major.to_string(), + minor: minor.to_string(), + width, + }, inode, mapping: mapping.to_string(), } @@ -210,31 +276,31 @@ mod test { fn test_parse_map_line() { let data = [ ( - create_map_line("000062442eb9e000", 16, Perms::from("r--p"), "0000000000000000", "008:00008", 10813151, "/usr/bin/konsole"), + create_map_line("62442eb9e000", 0x62442eb9e000, 0x62442eba2000, 16, Perms::from("r--p"), "00000000", "08", "08", 5, 10813151, "/usr/bin/konsole"), "62442eb9e000-62442eba2000 r--p 00000000 08:08 10813151 /usr/bin/konsole" ), ( - create_map_line("000071af50000000", 132, Perms::from("rw-p"), "0000000000000000", "000:00000", 0, ""), + create_map_line("71af50000000", 0x71af50000000, 0x71af50021000, 132, Perms::from("rw-p"), "00000000", "00", "00", 5, 0, ""), "71af50000000-71af50021000 rw-p 00000000 00:00 0 " ), ( - create_map_line("00007ffc3f8df000", 132, Perms::from("rw-p"), "0000000000000000", "000:00000", 0, "[stack]"), + create_map_line("7ffc3f8df000", 0x7ffc3f8df000, 0x7ffc3f900000, 132, Perms::from("rw-p"), "00000000", "00", "00", 5, 0, "[stack]"), "7ffc3f8df000-7ffc3f900000 rw-p 00000000 00:00 0 [stack]" ), ( - create_map_line("000071af8c9e6000", 16, Perms::from("rw-s"), "0000000105830000", "000:00010", 1075, "anon_inode:i915.gem"), + create_map_line("71af8c9e6000", 0x71af8c9e6000, 0x71af8c9ea000, 16, Perms::from("rw-s"), "105830000", "00", "10", 5, 1075, "anon_inode:i915.gem"), "71af8c9e6000-71af8c9ea000 rw-s 105830000 00:10 1075 anon_inode:i915.gem" ), ( - create_map_line("000071af6cf0c000", 3560, Perms::from("rw-s"), "0000000000000000", "000:00001", 256481, "/memfd:wayland-shm (deleted)"), + create_map_line("71af6cf0c000", 0x71af6cf0c000, 0x71af6d286000, 3560, Perms::from("rw-s"), "00000000", "00", "01", 5, 256481, "/memfd:wayland-shm (deleted)"), "71af6cf0c000-71af6d286000 rw-s 00000000 00:01 256481 /memfd:wayland-shm (deleted)" ), ( - create_map_line("ffffffffff600000", 4, Perms::from("--xp"), "0000000000000000", "000:00000", 0, "[vsyscall]"), + create_map_line("ffffffffff600000", 0xffffffffff600000, 0xffffffffff601000, 4, Perms::from("--xp"), "00000000", "00", "00", 5, 0, "[vsyscall]"), "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]" ), ( - create_map_line("00005e8187da8000", 24, Perms::from("r--p"), "0000000000000000", "008:00008", 9524160, "/usr/bin/hello world"), + create_map_line("5e8187da8000", 0x5e8187da8000, 0x5e8187dae000, 24, Perms::from("r--p"), "00000000", "08", "08", 5, 9524160, "/usr/bin/hello world"), "5e8187da8000-5e8187dae000 r--p 00000000 08:08 9524160 /usr/bin/hello world" ), ]; @@ -251,12 +317,16 @@ mod test { #[test] fn test_parse_address() { - let (start, size) = parse_address("ffffffffff600000-ffffffffff601000").unwrap(); - assert_eq!(start, "ffffffffff600000"); + let (address, size) = parse_address("ffffffffff600000-ffffffffff601000").unwrap(); + assert_eq!(address.start, "ffffffffff600000"); + assert_eq!(address.low, 0xffffffffff600000); + assert_eq!(address.high, 0xffffffffff601000); assert_eq!(size, 4); - let (start, size) = parse_address("7ffc4f0c2000-7ffc4f0e3000").unwrap(); - assert_eq!(start, "00007ffc4f0c2000"); + let (address, size) = parse_address("7ffc4f0c2000-7ffc4f0e3000").unwrap(); + assert_eq!(address.start, "7ffc4f0c2000"); + assert_eq!(address.low, 0x7ffc4f0c2000); + assert_eq!(address.high, 0x7ffc4f0e3000); assert_eq!(size, 132); } @@ -273,8 +343,15 @@ mod test { #[test] fn test_parse_device() { - assert_eq!("012:00034", parse_device("12:34").unwrap()); - assert_eq!("000:00000", parse_device("00:00").unwrap()); + assert_eq!("12:34", parse_device("12:34").unwrap().to_string()); + assert_eq!("00:00", parse_device("00:00").unwrap().to_string()); + assert_eq!("fe:01", parse_device("fe:01").unwrap().to_string()); + assert_eq!("103:100", parse_device("103:100").unwrap().to_string()); + + assert_eq!("012:00034", parse_device("12:34").unwrap().device()); + assert_eq!("000:00000", parse_device("00:00").unwrap().device()); + assert_eq!("0fe:00001", parse_device("fe:01").unwrap().device()); + assert_eq!("103:00100", parse_device("103:100").unwrap().device()); } #[test] diff --git a/src/uu/pmap/src/pmap.rs b/src/uu/pmap/src/pmap.rs index bc05802a..aa5bb943 100644 --- a/src/uu/pmap/src/pmap.rs +++ b/src/uu/pmap/src/pmap.rs @@ -184,7 +184,7 @@ fn output_default_format(pid: &str, pmap_config: &PmapConfig) -> Result<(), Erro process_maps(pid, None, |map_line| { println!( "{} {:>6}K {} {}", - map_line.address, + map_line.address.zero_pad(), map_line.size_in_kb, map_line.perms.mode(), map_line.parse_mapping(pmap_config) @@ -209,7 +209,7 @@ fn output_extended_format(pid: &str, pmap_config: &PmapConfig) -> Result<(), Err for smap_entry in smap_table.entries { println!( "{} {:>7} {:>7} {:>7} {} {}", - smap_entry.map_line.address, + smap_entry.map_line.address.zero_pad(), smap_entry.map_line.size_in_kb, smap_entry.rss_in_kb, smap_entry.shared_dirty_in_kb + smap_entry.private_dirty_in_kb, @@ -361,12 +361,12 @@ fn output_device_format(pid: &str, pmap_config: &PmapConfig) -> Result<(), Error }, |map_line| { println!( - "{} {:>7} {} {} {} {}", - map_line.address, + "{} {:>7} {} {:0>16} {} {}", + map_line.address.zero_pad(), map_line.size_in_kb, map_line.perms.mode(), map_line.offset, - map_line.device, + map_line.device.device(), map_line.parse_mapping(pmap_config) ); total_mapped += map_line.size_in_kb; diff --git a/src/uu/pmap/src/smaps_format_parser.rs b/src/uu/pmap/src/smaps_format_parser.rs index 779a2b8e..f4789165 100644 --- a/src/uu/pmap/src/smaps_format_parser.rs +++ b/src/uu/pmap/src/smaps_format_parser.rs @@ -40,10 +40,10 @@ pub struct SmapEntry { impl SmapEntry { pub fn get_field(&self, field_name: &str) -> String { match field_name { - pmap_field_name::ADDRESS => self.map_line.address.clone(), + pmap_field_name::ADDRESS => self.map_line.address.to_string(), pmap_field_name::PERM => self.map_line.perms.to_string(), pmap_field_name::OFFSET => self.map_line.offset.clone(), - pmap_field_name::DEVICE => self.map_line.device.clone(), + pmap_field_name::DEVICE => self.map_line.device.to_string(), pmap_field_name::INODE => self.map_line.inode.to_string(), pmap_field_name::SIZE => self.map_line.size_in_kb.to_string(), pmap_field_name::KERNEL_PAGE_SIZE => self.kernel_page_size_in_kb.to_string(), @@ -107,6 +107,9 @@ pub struct SmapTableInfo { pub total_thp_eligible: u64, pub total_protection_key: u64, // Width + pub offset_width: usize, + pub device_width: usize, + pub inode_width: usize, pub size_in_kb_width: usize, pub kernel_page_size_in_kb_width: usize, pub mmu_page_size_in_kb_width: usize, @@ -165,6 +168,9 @@ impl Default for SmapTableInfo { total_thp_eligible: 0, total_protection_key: 0, + device_width: pmap_field_name::DEVICE.len(), + offset_width: pmap_field_name::OFFSET.len(), + inode_width: pmap_field_name::INODE.len(), size_in_kb_width: pmap_field_name::SIZE.len(), kernel_page_size_in_kb_width: pmap_field_name::KERNEL_PAGE_SIZE.len(), mmu_page_size_in_kb_width: pmap_field_name::MMU_PAGE_SIZE.len(), @@ -200,9 +206,9 @@ impl SmapTableInfo { match field_name { pmap_field_name::ADDRESS => 16, // See maps_format_parser.rs pmap_field_name::PERM => 4, // See maps_format_parser.rs - pmap_field_name::OFFSET => 16, // See maps_format_parser.rs - pmap_field_name::DEVICE => 9, // See maps_format_parser.rs - pmap_field_name::INODE => 10, // See maps_format_parser.rs + pmap_field_name::OFFSET => self.offset_width, + pmap_field_name::DEVICE => self.device_width, + pmap_field_name::INODE => self.inode_width, pmap_field_name::SIZE => self.size_in_kb_width, pmap_field_name::KERNEL_PAGE_SIZE => self.kernel_page_size_in_kb_width, pmap_field_name::MMU_PAGE_SIZE => self.mmu_page_size_in_kb_width, @@ -289,6 +295,12 @@ pub fn parse_smaps(contents: &str) -> Result { smap_entry = SmapEntry::default(); } smap_table.info.total_size_in_kb += map_line.size_in_kb; + smap_table.info.offset_width = smap_table.info.offset_width.max(map_line.offset.len()); + smap_table.info.device_width = smap_table.info.device_width.max(map_line.device.width); + smap_table.info.inode_width = smap_table + .info + .inode_width + .max(map_line.inode.to_string().len()); smap_entry.map_line = map_line; } else { let (key, val) = line @@ -544,9 +556,13 @@ mod test { #[allow(clippy::too_many_arguments)] fn create_smap_entry( address: &str, + low: u64, + high: u64, perms: Perms, offset: &str, - device: &str, + major: &str, + minor: &str, + width: usize, inode: u64, mapping: &str, size_in_kb: u64, @@ -577,11 +593,19 @@ mod test { ) -> SmapEntry { SmapEntry { map_line: MapLine { - address: address.to_string(), + address: crate::maps_format_parser::Address { + start: address.to_string(), + low, + high, + }, size_in_kb, perms, offset: offset.to_string(), - device: device.to_string(), + device: crate::maps_format_parser::Device { + major: major.to_string(), + minor: minor.to_string(), + width, + }, inode, mapping: mapping.to_string(), }, @@ -617,7 +641,7 @@ mod test { let data = [ ( vec![create_smap_entry( - "0000560880413000", Perms::from("r--p"), "0000000000000000", "008:00008", 10813151, "/usr/bin/konsole", + "560880413000", 0x560880413000, 0x560880440000, Perms::from("r--p"), "00000000", "08", "08", 5, 10813151, "/usr/bin/konsole", 180, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, "rd mr mw me dw sd")], concat!( @@ -651,7 +675,7 @@ mod test { ), ( vec![create_smap_entry( - "000071af50000000", Perms::from("rw-p"), "0000000000000000", "000:00000", 0, "", + "71af50000000", 0x71af50000000, 0x71af50021000, Perms::from("rw-p"), "00000000", "00", "00", 5, 0, "", 132, 4, 4, 128, 9, 9, 128, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, "rd mr mw me sd")], concat!( @@ -684,7 +708,7 @@ mod test { ), ( vec![create_smap_entry( - "00007ffc3f8df000", Perms::from("rw-p"), "0000000000000000", "000:00000", 0, "[stack]", + "7ffc3f8df000", 0x7ffc3f8df000, 0x7ffc3f900000, Perms::from("rw-p"), "00000000", "00", "00", 5, 0, "[stack]", 132, 4, 4, 108, 108, 108, 0, 0, 0, 108, 108, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, "rd wr mr mw me gd ac")], concat!( @@ -717,7 +741,7 @@ mod test { ), ( vec![create_smap_entry( - "000071af8c9e6000", Perms::from("rw-s"), "0000000105830000", "000:00010", 1075, "anon_inode:i915.gem", + "71af8c9e6000", 0x71af8c9e6000, 0x71af8c9ea000, Perms::from("rw-s"), "105830000", "00", "10", 5, 1075, "anon_inode:i915.gem", 16, 4, 4, 16, 16, 16, 0, 0, 0, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "rd wr mr mw me ac sd")], concat!( @@ -749,7 +773,7 @@ mod test { ), ( vec![create_smap_entry( - "000071af6cf0c000", Perms::from("rw-s"), "0000000000000000", "000:00001", 256481, "/memfd:wayland-shm (deleted)", + "71af6cf0c000", 0x71af6cf0c000, 0x71af6d286000, Perms::from("rw-s"), "00000000", "00", "01", 5, 256481, "/memfd:wayland-shm (deleted)", 3560, 4, 4, 532, 108, 0, 524, 0, 8, 0, 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "rd mr mw me sd")], concat!( @@ -781,7 +805,7 @@ mod test { ), ( vec![create_smap_entry( - "ffffffffff600000", Perms::from("--xp"), "0000000000000000", "000:00000", 0, "[vsyscall]", + "ffffffffff600000", 0xffffffffff600000, 0xffffffffff601000, Perms::from("--xp"), "00000000", "00", "00", 5, 0, "[vsyscall]", 4, 4, 4, 4, 4, 4, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "rd wr mr mw me ac sd")], concat!( @@ -813,7 +837,7 @@ mod test { ), ( vec![create_smap_entry( - "00005e8187da8000", Perms::from("r--p"), "0000000000000000", "008:00008", 9524160, "/usr/bin/hello world", + "5e8187da8000", 0x5e8187da8000, 0x5e8187dae000, Perms::from("r--p"), "00000000", "08", "08", 5, 9524160, "/usr/bin/hello world", 24, 4, 4, 24, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "rd ex mr mw me sd")], concat!( @@ -846,11 +870,11 @@ mod test { ( vec![ create_smap_entry( - "000071af8c9e6000", Perms::from("rw-s"), "0000000105830000", "000:00010", 1075, "anon_inode:i915.gem", + "71af8c9e6000", 0x71af8c9e6000, 0x71af8c9ea000, Perms::from("rw-s"), "105830000", "00", "10", 5, 1075, "anon_inode:i915.gem", 16, 4, 4, 16, 16, 16, 0, 0, 0, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "rd wr mr mw me ac sd"), create_smap_entry( - "000071af6cf0c000", Perms::from("rw-s"), "0000000000000000", "000:00001", 256481, "/memfd:wayland-shm (deleted)", + "71af6cf0c000", 0x71af6cf0c000, 0x71af6d286000, Perms::from("rw-s"), "00000000", "00", "01", 5, 256481, "/memfd:wayland-shm (deleted)", 3560, 4, 4, 532, 108, 0, 524, 0, 8, 0, 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "rd mr mw me sd"), ], @@ -909,15 +933,15 @@ mod test { ( vec![ create_smap_entry( - "000071af8c9e6000", Perms::from("rw-s"), "0000000105830000", "000:00010", 1075, "anon_inode:i915.gem", + "71af8c9e6000", 0x71af8c9e6000, 0x71af8c9ea000, Perms::from("rw-s"), "105830000", "00", "10", 5, 1075, "anon_inode:i915.gem", 16, 4, 4, 16, 16, 16, 0, 0, 0, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, "rd wr mr mw me ac sd"), create_smap_entry( - "0000560880413000", Perms::from("r--p"), "0000000000000000", "008:00008", 10813151, "/usr/bin/konsole", + "560880413000", 0x560880413000, 0x560880440000, Perms::from("r--p"), "00000000", "08", "08", 5, 10813151, "/usr/bin/konsole", 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ""), create_smap_entry( - "000071af6cf0c000", Perms::from("rw-s"), "0000000000000000", "000:00001", 256481, "/memfd:wayland-shm (deleted)", + "71af6cf0c000", 0x71af6cf0c000, 0x71af6d286000, Perms::from("rw-s"), "00000000", "00", "01", 5, 256481, "/memfd:wayland-shm (deleted)", 3560, 4, 4, 532, 108, 0, 524, 0, 8, 0, 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "rd mr mw me sd"), ], diff --git a/tests/by-util/test_pmap.rs b/tests/by-util/test_pmap.rs index e289f066..e4b9f8ce 100644 --- a/tests/by-util/test_pmap.rs +++ b/tests/by-util/test_pmap.rs @@ -450,13 +450,13 @@ fn assert_extended_format(pid: u32, s: &str, quiet: bool, show_path: bool) { // Ensure `s` has the following more extended format (-X): // // 1234: /some/path -// Address Perm Offset Device Inode Size Rss Pss Pss_Dirty Referenced Anonymous LazyFree ShmemPmdMapped FilePmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked THPeligible Mapping -// 000073eb5f4c7000 r-xp 0000000000036000 008:00008 2274176 1284 1148 1148 0 1148 0 0 0 0 0 0 0 0 0 0 ld-linux-x86-64.so.2 -// 00007ffd588fc000 r--p 0000000000000000 000:00000 2274176 20 20 20 20 20 20 0 0 0 0 0 0 0 0 0 [stack] -// ffffffffff600000 rw-p 0000000000000000 000:00000 2274176 36 36 36 36 36 36 0 0 0 0 0 0 0 0 0 (one intentional trailing space) +// Address Perm Offset Device Inode Size Rss Pss Pss_Dirty Referenced Anonymous LazyFree ShmemPmdMapped FilePmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked THPeligible Mapping +// 73eb5f4c7000 r-xp 00036000 08:08 2274176 1284 1148 1148 0 1148 0 0 0 0 0 0 0 0 0 0 ld-linux-x86-64.so.2 +// 7ffd588fc000 r--p 00000000 00:00 2274176 20 20 20 20 20 20 0 0 0 0 0 0 0 0 0 [stack] +// ffffffffff600000 rw-p 00000000 00:00 2274176 36 36 36 36 36 36 0 0 0 0 0 0 0 0 0 (one intentional trailing space) // ... -// ==== ==== ==== ========= ========== ========= ======== ============== ============= ============== =============== ==== ======= ====== =========== (one intentional trailing space) -// 4164 3448 2826 552 3448 552 0 0 0 0 0 0 0 0 0 KB (one intentional trailing space) +// ==== ==== ==== ========= ========== ========= ======== ============== ============= ============== =============== ==== ======= ====== =========== (one intentional trailing space) +// 4164 3448 2826 552 3448 552 0 0 0 0 0 0 0 0 0 KB (one intentional trailing space) #[cfg(target_os = "linux")] fn assert_more_extended_format(pid: u32, s: &str, quiet: bool, show_path: bool) { let lines: Vec<_> = s.lines().collect(); @@ -466,11 +466,11 @@ fn assert_more_extended_format(pid: u32, s: &str, quiet: bool, show_path: bool) assert!(re.is_match(lines[0])); if !quiet { - let re = Regex::new(r"^ Address Perm Offset Device Inode +Size +Rss +Pss +Pss_Dirty +Referenced +Anonymous( +KSM)? +LazyFree +ShmemPmdMapped +FilePmdMapped +Shared_Hugetlb +Private_Hugetlb +Swap +SwapPss +Locked +THPeligible( +ProtectionKey)? +Mapping$").unwrap(); + let re = Regex::new(r"^ Address Perm Offset +Device +Inode +Size +Rss +Pss +Pss_Dirty +Referenced +Anonymous( +KSM)? +LazyFree +ShmemPmdMapped +FilePmdMapped +Shared_Hugetlb +Private_Hugetlb +Swap +SwapPss +Locked +THPeligible( +ProtectionKey)? +Mapping$").unwrap(); assert!(re.is_match(lines[1]), "failing line: '{}'", lines[1]); } - let base_pattern = r"^[0-9a-f]{16} (-|r)(-|w)(-|x)(p|s) [0-9a-f]{16} [0-9a-f]{3}:[0-9a-f]{5} +\d+ +[1-9][0-9]* +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)?"; + let base_pattern = r"^[ 0-9a-f]{16} (-|r)(-|w)(-|x)(p|s) [0-9a-f]{8} +[0-9a-f]+:[0-9a-f]+ +\d+ +[1-9][0-9]* +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)?"; let mapping_pattern = if show_path { r" (|\[[a-zA-Z_ ]+\]|/[/a-zA-Z0-9._-]+)$" } else { @@ -487,14 +487,14 @@ fn assert_more_extended_format(pid: u32, s: &str, quiet: bool, show_path: bool) assert!(re.is_match(line), "failing line: '{line}'"); } - let re = Regex::new(r"^ +=+ =+ =+ =+ =+ =+( =+)? =+ =+ =+ =+ =+ =+ =+ =+ =+( =+)? $").unwrap(); + let re = Regex::new(r"^ +=+ =+ =+ =+ =+ =+( =+)? =+ =+ =+ =+ =+ =+ =+ =+ =+( =+)? $").unwrap(); assert!( re.is_match(lines[line_count - 2]), "failing line: '{}'", lines[line_count - 2] ); - let re = Regex::new(r"^ +[1-9][0-9]* +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? KB $").unwrap(); + let re = Regex::new(r"^ +[1-9][0-9]* +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? KB $").unwrap(); assert!( re.is_match(lines[line_count - 1]), "failing line: '{}'", @@ -506,13 +506,13 @@ fn assert_more_extended_format(pid: u32, s: &str, quiet: bool, show_path: bool) // Ensure `s` has the following most extended format (--XX): // // 1234: /some/path -// Address Perm Offset Device Inode Size KernelPageSize MMUPageSize Rss Pss Pss_Dirty Shared_Clean Shared_Dirty Private_Clean Private_Dirty Referenced Anonymous LazyFree AnonHugePages ShmemPmdMapped FilePmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked THPeligible VmFlags Mapping -// 000073eb5f4c7000 r-xp 0000000000036000 008:00008 2274176 1284 4 4 1148 1148 0 0 0 1148 0 1148 0 0 0 0 0 0 0 0 0 0 0 rd ex mr mw me ld-linux-x86-64.so.2 -// 00007ffd588fc000 r--p 0000000000000000 000:00000 2274176 20 4 4 20 20 20 0 0 0 20 20 20 0 0 0 0 0 0 0 0 0 0 rd mr mw me ac [stack] -// ffffffffff600000 rw-p 0000000000000000 000:00000 2274176 36 4 4 36 36 36 0 0 0 36 36 36 0 0 0 0 0 0 0 0 0 0 rd wr mr mw me ac (one intentional trailing space) +// Address Perm Offset Device Inode Size KernelPageSize MMUPageSize Rss Pss Pss_Dirty Shared_Clean Shared_Dirty Private_Clean Private_Dirty Referenced Anonymous LazyFree AnonHugePages ShmemPmdMapped FilePmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked THPeligible VmFlags Mapping +// 73eb5f4c7000 r-xp 00036000 08:08 2274176 1284 4 4 1148 1148 0 0 0 1148 0 1148 0 0 0 0 0 0 0 0 0 0 0 rd ex mr mw me ld-linux-x86-64.so.2 +// 7ffd588fc000 r--p 00000000 00:00 2274176 20 4 4 20 20 20 0 0 0 20 20 20 0 0 0 0 0 0 0 0 0 0 rd mr mw me ac [stack] +// ffffffffff600000 rw-p 00000000 00:00 2274176 36 4 4 36 36 36 0 0 0 36 36 36 0 0 0 0 0 0 0 0 0 0 rd wr mr mw me ac (one intentional trailing space) // ... -// ==== ============== =========== ==== ==== ========= ============ ============ ============= ============= ========== ========= ======== ============= ============== ============= ============== =============== ==== ======= ====== =========== (one intentional trailing space) -// 4164 92 92 3448 2880 552 1132 0 1764 552 3448 552 0 0 0 0 0 0 0 0 0 0 KB (one intentional trailing space) +// ==== ============== =========== ==== ==== ========= ============ ============ ============= ============= ========== ========= ======== ============= ============== ============= ============== =============== ==== ======= ====== =========== (one intentional trailing space) +// 4164 92 92 3448 2880 552 1132 0 1764 552 3448 552 0 0 0 0 0 0 0 0 0 0 KB (one intentional trailing space) #[cfg(target_os = "linux")] fn assert_most_extended_format(pid: u32, s: &str, quiet: bool, show_path: bool) { let lines: Vec<_> = s.lines().collect(); @@ -522,11 +522,11 @@ fn assert_most_extended_format(pid: u32, s: &str, quiet: bool, show_path: bool) assert!(re.is_match(lines[0])); if !quiet { - let re = Regex::new(r"^ Address Perm Offset Device Inode +Size +KernelPageSize +MMUPageSize +Rss +Pss +Pss_Dirty +Shared_Clean +Shared_Dirty +Private_Clean +Private_Dirty +Referenced +Anonymous( +KSM)? +LazyFree +AnonHugePages +ShmemPmdMapped +FilePmdMapped +Shared_Hugetlb +Private_Hugetlb +Swap +SwapPss +Locked +THPeligible( +ProtectionKey)? +VmFlags +Mapping$").unwrap(); + let re = Regex::new(r"^ Address Perm Offset +Device +Inode +Size +KernelPageSize +MMUPageSize +Rss +Pss +Pss_Dirty +Shared_Clean +Shared_Dirty +Private_Clean +Private_Dirty +Referenced +Anonymous( +KSM)? +LazyFree +AnonHugePages +ShmemPmdMapped +FilePmdMapped +Shared_Hugetlb +Private_Hugetlb +Swap +SwapPss +Locked +THPeligible( +ProtectionKey)? +VmFlags +Mapping$").unwrap(); assert!(re.is_match(lines[1]), "failing line: '{}'", lines[1]); } - let base_pattern = r"^[0-9a-f]{16} (-|r)(-|w)(-|x)(p|s) [0-9a-f]{16} [0-9a-f]{3}:[0-9a-f]{5} +\d+ +[1-9][0-9]* +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +([a-z][a-z] )*"; + let base_pattern = r"^[ 0-9a-f]{16} (-|r)(-|w)(-|x)(p|s) [0-9a-f]{8} +[0-9a-f]+:[0-9a-f]+ +\d+ +[1-9][0-9]* +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +([a-z][a-z] )*"; let mapping_pattern = if show_path { r"(|\[[a-zA-Z_ ]+\]|/[/a-zA-Z0-9._-]+)$" } else { @@ -543,14 +543,14 @@ fn assert_most_extended_format(pid: u32, s: &str, quiet: bool, show_path: bool) assert!(re.is_match(line), "failing line: '{line}'"); } - let re = Regex::new(r"^ +=+ =+ =+ =+ =+ =+ =+ =+ =+ =+ =+ =+( =+)? =+ =+ =+ =+ =+ =+ =+ =+ =+ =+( =+)? $").unwrap(); + let re = Regex::new(r"^ +=+ =+ =+ =+ =+ =+ =+ =+ =+ =+ =+ =+( =+)? =+ =+ =+ =+ =+ =+ =+ =+ =+ =+( =+)? $").unwrap(); assert!( re.is_match(lines[line_count - 2]), "failing line: '{}'", lines[line_count - 2] ); - let re = Regex::new(r"^ +[1-9][0-9]* +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? KB $").unwrap(); + let re = Regex::new(r"^ +[1-9][0-9]* +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? KB $").unwrap(); assert!( re.is_match(lines[line_count - 1]), "failing line: '{}'",