Coverage Report

Created: 2024-12-17 06:15

/rust/registry/src/index.crates.io-6f17d22bba15001f/procfs-0.17.0/src/process/pagemap.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{FileWrapper, ProcResult};
2
use procfs_core::process::PageInfo;
3
use std::{
4
    io::{BufReader, Read, Seek, SeekFrom},
5
    mem::size_of,
6
    ops::{Bound, RangeBounds},
7
};
8
9
impl super::Process {
10
    /// Returns a struct that can be used to access information in the `/proc/pid/pagemap` file.
11
0
    pub fn pagemap(&self) -> ProcResult<PageMap> {
12
0
        let path = self.root.join("pagemap");
13
0
        let file = FileWrapper::open(&path)?;
14
0
        Ok(PageMap::from_file_wrapper(file))
15
0
    }
16
}
17
18
/// Parses page table entries accessing `/proc/<pid>/pagemap`.
19
pub struct PageMap {
20
    reader: BufReader<FileWrapper>,
21
}
22
23
impl PageMap {
24
0
    pub(crate) fn from_file_wrapper(file: FileWrapper) -> Self {
25
0
        Self {
26
0
            reader: BufReader::new(file),
27
0
        }
28
0
    }
29
30
    /// Retrieves information in the page table entry for the page at index `page_index`.
31
    ///
32
    /// Some mappings are not accessible, and will return an Err: `vsyscall`
33
0
    pub fn get_info(&mut self, page_index: usize) -> ProcResult<PageInfo> {
34
0
        self.get_range_info(page_index..page_index + 1)
35
0
            .map(|mut vec| vec.pop().unwrap())
36
0
    }
37
38
    /// Retrieves information in the page table entry for the pages with index in range `page_range`.
39
0
    pub fn get_range_info(&mut self, page_range: impl RangeBounds<usize>) -> ProcResult<Vec<PageInfo>> {
40
        // `start` is always included
41
0
        let start = match page_range.start_bound() {
42
0
            Bound::Included(v) => *v,
43
0
            Bound::Excluded(v) => *v + 1,
44
0
            Bound::Unbounded => 0,
45
        };
46
47
        // `end` is always excluded
48
0
        let end = match page_range.end_bound() {
49
0
            Bound::Included(v) => *v + 1,
50
0
            Bound::Excluded(v) => *v,
51
0
            Bound::Unbounded => std::usize::MAX / crate::page_size() as usize,
52
        };
53
54
0
        let start_position = (start * size_of::<u64>()) as u64;
55
0
        self.reader.seek(SeekFrom::Start(start_position))?;
56
57
0
        let mut page_infos = Vec::with_capacity((end - start) as usize);
58
0
        for _ in start..end {
59
0
            let mut info_bytes = [0; size_of::<u64>()];
60
0
            self.reader.read_exact(&mut info_bytes)?;
61
0
            page_infos.push(PageInfo::parse_info(u64::from_ne_bytes(info_bytes)));
62
        }
63
64
0
        Ok(page_infos)
65
0
    }
66
}