Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/dynasmrt-1.2.3/src/mmap.rs
Line
Count
Source (jump to first uncovered line)
1
//! This module implements some wrappers around Mmap/MmapMut to also support a cheap "empty" variant.
2
// Unfortunately Memmap itself doesn't support a cheap zero-length variant
3
4
use std::ops::{Deref, DerefMut};
5
use std::io;
6
7
use memmap2::{Mmap, MmapMut};
8
9
use crate::AssemblyOffset;
10
11
/// A structure holding a buffer of executable memory. It also derefs to a `&[u8]`.
12
/// This structure does not allocate when its size is 0.
13
#[derive(Debug)]
14
pub struct ExecutableBuffer {
15
    // length of the buffer that has actually been written to
16
    length: usize,
17
    // backing buffer
18
    buffer: Option<Mmap>
19
}
20
21
/// ExecutableBuffer equivalent that holds a buffer of mutable memory instead of executable memory. It also derefs to a `&mut [u8]`.
22
/// This structure does not allocate when its size is 0.
23
#[derive(Debug)]
24
pub struct MutableBuffer {
25
    // length of the buffer that has actually been written to
26
    length: usize,
27
    // backing buffer
28
    buffer: Option<MmapMut>
29
}
30
31
impl ExecutableBuffer {
32
    /// Obtain a pointer into the executable memory from an offset into it.
33
    /// When an offset returned from `DynasmLabelApi::offset` is used, the resulting pointer
34
    /// will point to the start of the first instruction after the offset call,
35
    /// which can then be jumped or called to divert control flow into the executable
36
    /// buffer. Note that if this buffer is accessed through an Executor, these pointers
37
    /// will only be valid as long as its lock is held. When no locks are held,
38
    /// The assembler is free to relocate the executable buffer when it requires
39
    /// more memory than available.
40
0
    pub fn ptr(&self, offset: AssemblyOffset) -> *const u8 {
41
0
        &self[offset.0] as *const u8
42
0
    }
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer>::ptr
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer>::ptr
43
44
    /// Create a new executable buffer, backed by a buffer of size `size`.
45
    /// It will start with an initialized length of 0.
46
0
    pub fn new(size: usize) -> io::Result<ExecutableBuffer> {
47
0
        let buffer = if size == 0 {
48
0
            None
49
        } else {
50
0
            Some(MmapMut::map_anon(size)?.make_exec()?)
51
        };
52
53
0
        Ok(ExecutableBuffer {
54
0
            length: 0,
55
0
            buffer
56
0
        })
57
0
    }
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer>::new
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer>::new
58
59
    /// Query the backing size of this executable buffer
60
0
    pub fn size(&self) -> usize {
61
0
        self.buffer.as_ref().map(|b| b.len()).unwrap_or(0) as usize
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer>::size::{closure#0}
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer>::size::{closure#0}
62
0
    }
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer>::size
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer>::size
63
64
    /// Change this executable buffer into a mutable buffer.
65
0
    pub fn make_mut(self) -> io::Result<MutableBuffer> {
66
0
        let buffer = if let Some(map) = self.buffer {
67
0
            Some(map.make_mut()?)
68
        } else {
69
0
            None
70
        };
71
72
0
        Ok(MutableBuffer {
73
0
            length: self.length,
74
0
            buffer
75
0
        })
76
0
    }
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer>::make_mut
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer>::make_mut
77
}
78
79
impl MutableBuffer {
80
    /// Create a new mutable buffer, backed by a buffer of size `size`.
81
    /// It will start with an initialized length of 0.
82
0
    pub fn new(size: usize) -> io::Result<MutableBuffer> {
83
0
        let buffer = if size == 0 {
84
0
            None
85
        } else {
86
0
            Some(MmapMut::map_anon(size)?)
87
        };
88
89
0
        Ok(MutableBuffer {
90
0
            length: 0,
91
0
            buffer
92
0
        })
93
0
    }
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer>::new
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer>::new
94
95
    /// Query the backing size of this mutable buffer
96
0
    pub fn size(&self) -> usize {
97
0
        self.buffer.as_ref().map(|b| b.len()).unwrap_or(0) as usize
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer>::size::{closure#0}
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer>::size::{closure#0}
98
0
    }
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer>::size
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer>::size
99
100
    /// Set the length of the usable part of this mutable buffer. The length
101
    /// should not be set larger than the allocated size, otherwise methods can panic.
102
0
    pub fn set_len(&mut self, length: usize) {
103
0
        self.length = length
104
0
    }
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer>::set_len
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer>::set_len
105
106
    /// Change this mutable buffer into an executable buffer.
107
0
    pub fn make_exec(self) -> io::Result<ExecutableBuffer> {
108
0
        let buffer = if let Some(map) = self.buffer {
109
0
            Some(map.make_exec()?)
110
        } else {
111
0
            None
112
        };
113
114
0
        Ok(ExecutableBuffer {
115
0
            length: self.length,
116
0
            buffer
117
0
        })
118
0
    }
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer>::make_exec
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer>::make_exec
119
}
120
121
impl Default for ExecutableBuffer {
122
0
    fn default() -> ExecutableBuffer {
123
0
        ExecutableBuffer {
124
0
            length: 0,
125
0
            buffer: None
126
0
        }
127
0
    }
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer as core::default::Default>::default
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer as core::default::Default>::default
128
}
129
130
impl Default for MutableBuffer {
131
0
    fn default() -> MutableBuffer {
132
0
        MutableBuffer {
133
0
            length: 0,
134
0
            buffer: None
135
0
        }
136
0
    }
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer as core::default::Default>::default
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer as core::default::Default>::default
137
}
138
139
impl Deref for ExecutableBuffer {
140
    type Target = [u8];
141
0
    fn deref(&self) -> &[u8] {
142
0
        if let Some(map) = &self.buffer {
143
0
            &map[..self.length]
144
        } else {
145
0
            &[]
146
        }
147
0
    }
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer as core::ops::deref::Deref>::deref
Unexecuted instantiation: <dynasmrt::mmap::ExecutableBuffer as core::ops::deref::Deref>::deref
148
}
149
150
impl Deref for MutableBuffer {
151
    type Target = [u8];
152
0
    fn deref(&self) -> &[u8] {
153
0
        if let Some(map) = &self.buffer {
154
0
            &map[..self.length]
155
        } else {
156
0
            &[]
157
        }
158
0
    }
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer as core::ops::deref::Deref>::deref
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer as core::ops::deref::Deref>::deref
159
}
160
161
impl DerefMut for MutableBuffer {
162
0
    fn deref_mut(&mut self) -> &mut [u8] {
163
0
        if let Some(map) = &mut self.buffer {
164
0
            &mut map[..self.length]
165
        } else {
166
0
            &mut []
167
        }
168
0
    }
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <dynasmrt::mmap::MutableBuffer as core::ops::deref::DerefMut>::deref_mut
169
}