Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/dynasmrt-1.2.3/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
#![warn(missing_docs)]
2
3
//! This crate provides runtime support for dynasm-rs. It contains traits that document the interface used by the dynasm proc_macro to generate code,
4
//! Assemblers that implement these traits, and relocation models for the various supported architectures. Additionally, it also provides the tools
5
//! to write your own Assemblers using these components.
6
7
pub mod mmap;
8
pub mod components;
9
pub mod relocations;
10
11
/// Helper to implement common traits on register enums.
12
macro_rules! reg_impls {
13
    ($r:ty) => {
14
        impl $crate::Register for $r {
15
0
            fn code(&self) -> u8 {
16
0
                *self as u8
17
0
            }
Unexecuted instantiation: <dynasmrt::x64::Rq as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x64::Rx as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x64::RC as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::Rd as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::Rh as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::Rf as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::Rm as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::Rx as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::Rs as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::RC as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::RD as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::RB as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::aarch64::RX as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::aarch64::RXSP as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::aarch64::RV as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x64::Rq as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x64::Rx as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x64::RC as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::Rd as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::Rh as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::Rf as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::Rm as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::Rx as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::Rs as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::RC as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::RD as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::x86::RB as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::aarch64::RX as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::aarch64::RXSP as dynasmrt::Register>::code
Unexecuted instantiation: <dynasmrt::aarch64::RV as dynasmrt::Register>::code
18
        }
19
20
        impl From<$r> for u8 {
21
0
            fn from(rq: $r) -> u8 {
22
0
                rq.code()
23
0
            }
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x64::Rq>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x64::Rx>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x64::RC>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::Rd>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::Rh>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::Rf>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::Rm>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::Rx>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::Rs>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::RC>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::RD>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::RB>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::aarch64::RX>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::aarch64::RXSP>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::aarch64::RV>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x64::Rq>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x64::Rx>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x64::RC>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::Rd>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::Rh>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::Rf>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::Rm>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::Rx>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::Rs>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::RC>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::RD>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::x86::RB>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::aarch64::RX>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::aarch64::RXSP>>::from
Unexecuted instantiation: <u8 as core::convert::From<dynasmrt::aarch64::RV>>::from
24
        }
25
    }
26
}
27
28
pub mod x64;
29
pub mod x86;
30
pub mod aarch64;
31
32
pub use crate::mmap::ExecutableBuffer;
33
pub use dynasm::{dynasm, dynasm_backwards};
34
35
use crate::components::{MemoryManager, LabelRegistry, RelocRegistry, ManagedRelocs, PatchLoc};
36
use crate::relocations::Relocation;
37
38
use std::hash::Hash;
39
use std::iter::Extend;
40
use std::sync::{Arc, RwLock, RwLockReadGuard};
41
use std::io;
42
use std::error;
43
use std::fmt::{self, Debug};
44
use std::mem;
45
46
/// This macro takes a *const pointer from the source operand, and then casts it to the desired return type.
47
/// this allows it to be used as an easy shorthand for passing pointers as dynasm immediate arguments.
48
#[macro_export]
49
macro_rules! Pointer {
50
    ($e:expr) => {$e as *const _ as _};
51
}
52
53
/// Preforms the same action as the `Pointer!` macro, but casts to a *mut pointer.
54
#[macro_export]
55
macro_rules! MutPointer {
56
    ($e:expr) => {$e as *mut _ as _};
57
}
58
59
60
/// A struct representing an offset into the assembling buffer of a `DynasmLabelApi` struct.
61
/// The wrapped `usize` is the offset from the start of the assembling buffer in bytes.
62
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
63
pub struct AssemblyOffset(pub usize);
64
65
/// A dynamic label
66
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
67
pub struct DynamicLabel(usize);
68
69
70
impl DynamicLabel {
71
    /// Get the internal ID of this dynamic label. This is only useful for debugging purposes.
72
0
    pub fn get_id(self) -> usize {
73
0
        self.0
74
0
    }
Unexecuted instantiation: <dynasmrt::DynamicLabel>::get_id
Unexecuted instantiation: <dynasmrt::DynamicLabel>::get_id
75
}
76
77
78
/// A read-only shared reference to the executable buffer inside an Assembler. By
79
/// locking it the internal `ExecutableBuffer` can be accessed and executed.
80
#[derive(Debug, Clone)]
81
pub struct Executor {
82
    execbuffer: Arc<RwLock<ExecutableBuffer>>
83
}
84
85
/// A read-only lockable reference to the internal `ExecutableBuffer` of an Assembler.
86
/// To gain access to this buffer, it must be locked.
87
impl Executor {
88
    /// Gain read-access to the internal `ExecutableBuffer`. While the returned guard
89
    /// is alive, it can be used to read and execute from the `ExecutableBuffer`.
90
    /// Any pointers created to the `Executablebuffer` should no longer be used when
91
    /// the guard is dropped.
92
    #[inline]
93
0
    pub fn lock(&self) -> RwLockReadGuard<ExecutableBuffer> {
94
0
        self.execbuffer.read().unwrap()
95
0
    }
Unexecuted instantiation: <dynasmrt::Executor>::lock
Unexecuted instantiation: <dynasmrt::Executor>::lock
96
}
97
98
99
/// A description of a label. Used for error reporting.
100
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
101
pub enum LabelKind {
102
    /// A local label, like `label:`
103
    Local(&'static str),
104
    /// A global label, like `->label:`
105
    Global(&'static str),
106
    /// A dynamic label, like `=>value:`
107
    Dynamic(DynamicLabel)
108
}
109
110
impl fmt::Display for LabelKind {
111
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112
0
        match self {
113
0
            Self::Local(s) => write!(f, "label {}", s),
114
0
            Self::Global(s) => write!(f, "label ->{}", s),
115
0
            Self::Dynamic(id) => write!(f, "label =>{}", id.get_id())
116
        }
117
0
    }
Unexecuted instantiation: <dynasmrt::LabelKind as core::fmt::Display>::fmt
Unexecuted instantiation: <dynasmrt::LabelKind as core::fmt::Display>::fmt
118
}
119
120
121
/// A description of a relocation target. Used for error reporting.
122
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
123
pub enum TargetKind {
124
    /// This targets a local label with the specified name that still has to be defined.
125
    Forward(&'static str),
126
    /// This targets a local label with the specified name that was already previously defined.
127
    Backward(&'static str),
128
    /// This targets a global label with the specified name.
129
    Global(&'static str),
130
    /// This targets the specified dynamic label.
131
    Dynamic(DynamicLabel),
132
    /// This targets the specified address.
133
    Extern(usize),
134
    /// An already resolved relocation that needs to be adjusted when the buffer moves in memory.
135
    Managed,
136
}
137
138
impl fmt::Display for TargetKind {
139
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140
0
        match self {
141
0
            Self::Forward(s) => write!(f, "target >{}", s),
142
0
            Self::Backward(s) => write!(f, "target <{}", s),
143
0
            Self::Global(s) => write!(f, "target ->{}", s),
144
0
            Self::Dynamic(id) => write!(f, "target =>{}", id.get_id()),
145
0
            Self::Extern(value) => write!(f, "target extern {}", value),
146
0
            Self::Managed => write!(f, "while adjusting managed relocation"),
147
        }
148
0
    }
Unexecuted instantiation: <dynasmrt::TargetKind as core::fmt::Display>::fmt
Unexecuted instantiation: <dynasmrt::TargetKind as core::fmt::Display>::fmt
149
}
150
151
152
/// The various error types generated by dynasm functions.
153
#[derive(Debug, Clone, PartialEq, Eq)]
154
pub enum DynasmError {
155
    /// A check (like `Modifier::check` or `Modifier::check_exact`) that failed
156
    CheckFailed,
157
    /// A duplicate label dynamic/global label was defined
158
    DuplicateLabel(LabelKind),
159
    /// An unknown label
160
    UnknownLabel(LabelKind),
161
    /// The user tried to declare a relocation too far away from the label it targets
162
    ImpossibleRelocation(TargetKind),
163
}
164
165
impl fmt::Display for DynasmError {
166
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
167
0
        match self {
168
0
            DynasmError::CheckFailed => write!(f, "An assembly modification check failed"),
169
0
            DynasmError::DuplicateLabel(l) => write!(f, "Duplicate label defined: '{}'", l),
170
0
            DynasmError::UnknownLabel(l) => write!(f, "Unknown label: '{}'", l),
171
0
            DynasmError::ImpossibleRelocation(s) => write!(f, "Impossible relocation: '{}'", s),
172
        }
173
0
    }
Unexecuted instantiation: <dynasmrt::DynasmError as core::fmt::Display>::fmt
Unexecuted instantiation: <dynasmrt::DynasmError as core::fmt::Display>::fmt
174
}
175
176
impl error::Error for DynasmError {
177
0
    fn description(&self) -> &str {
178
0
        match self {
179
0
            DynasmError::CheckFailed => "An assembly modification offset check failed",
180
0
            DynasmError::DuplicateLabel(_) => "Duplicate label defined",
181
0
            DynasmError::UnknownLabel(_) => "Unknown label",
182
0
            DynasmError::ImpossibleRelocation(_) => "Impossible relocation",
183
        }
184
0
    }
Unexecuted instantiation: <dynasmrt::DynasmError as core::error::Error>::description
Unexecuted instantiation: <dynasmrt::DynasmError as core::error::Error>::description
185
}
186
187
188
/// This trait represents the interface that must be implemented to allow
189
/// the dynasm preprocessor to assemble into a datastructure.
190
pub trait DynasmApi: Extend<u8> + for<'a> Extend<&'a u8> {
191
    /// Report the current offset into the assembling target
192
    fn offset(&self) -> AssemblyOffset;
193
    /// Push a byte into the assembling target
194
    fn push(&mut self, byte: u8);
195
    /// Push filler until the assembling target end is aligned to the given alignment.
196
    fn align(&mut self, alignment: usize, with: u8);
197
198
    #[inline]
199
    /// Push a signed byte into the assembling target
200
688k
    fn push_i8(&mut self, value: i8) {
201
688k
        self.push(value as u8);
202
688k
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::push_i8
Line
Count
Source
200
519k
    fn push_i8(&mut self, value: i8) {
201
519k
        self.push(value as u8);
202
519k
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_i8
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_i8
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::push_i8
Line
Count
Source
200
169k
    fn push_i8(&mut self, value: i8) {
201
169k
        self.push(value as u8);
202
169k
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_i8
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_i8
203
    /// Push a signed word into the assembling target
204
    #[inline]
205
725
    fn push_i16(&mut self, value: i16) {
206
725
        self.extend(&value.to_le_bytes());
207
725
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmApi>::push_i16
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::push_i16
Line
Count
Source
205
687
    fn push_i16(&mut self, value: i16) {
206
687
        self.extend(&value.to_le_bytes());
207
687
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_i16
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_i16
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmApi>::push_i16
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::push_i16
Line
Count
Source
205
38
    fn push_i16(&mut self, value: i16) {
206
38
        self.extend(&value.to_le_bytes());
207
38
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_i16
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_i16
208
    /// Push a signed doubleword into the assembling target
209
    #[inline]
210
12.3M
    fn push_i32(&mut self, value: i32) {
211
12.3M
        self.extend(&value.to_le_bytes());
212
12.3M
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::push_i32
Line
Count
Source
210
10.1M
    fn push_i32(&mut self, value: i32) {
211
10.1M
        self.extend(&value.to_le_bytes());
212
10.1M
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_i32
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_i32
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::push_i32
Line
Count
Source
210
2.15M
    fn push_i32(&mut self, value: i32) {
211
2.15M
        self.extend(&value.to_le_bytes());
212
2.15M
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_i32
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_i32
213
    /// Push a signed quadword into the assembling target
214
    #[inline]
215
923k
    fn push_i64(&mut self, value: i64) {
216
923k
        self.extend(&value.to_le_bytes());
217
923k
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::push_i64
Line
Count
Source
215
734k
    fn push_i64(&mut self, value: i64) {
216
734k
        self.extend(&value.to_le_bytes());
217
734k
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_i64
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_i64
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::push_i64
Line
Count
Source
215
188k
    fn push_i64(&mut self, value: i64) {
216
188k
        self.extend(&value.to_le_bytes());
217
188k
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_i64
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_i64
218
    /// Push an usigned word into the assembling target
219
    #[inline]
220
0
    fn push_u16(&mut self, value: u16) {
221
0
        self.extend(&value.to_le_bytes());
222
0
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_u16
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_u16
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_u16
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_u16
223
    /// Push an usigned doubleword into the assembling target
224
    #[inline]
225
0
    fn push_u32(&mut self, value: u32) {
226
0
        self.extend(&value.to_le_bytes());
227
0
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmApi>::push_u32
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_u32
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_u32
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmApi>::push_u32
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_u32
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_u32
228
    /// Push an usigned quadword into the assembling target
229
    #[inline]
230
0
    fn push_u64(&mut self, value: u64) {
231
0
        self.extend(&value.to_le_bytes());
232
0
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::push_u64
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_u64
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_u64
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::push_u64
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push_u64
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push_u64
233
    /// This function is called in when a runtime error has to be generated. It panics.
234
    #[inline]
235
0
    fn runtime_error(&self, msg: &'static str) -> ! {
236
0
        panic!("{}", msg);
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::runtime_error
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::runtime_error
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::runtime_error
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::runtime_error
237
    }
238
}
239
240
/// This trait extends DynasmApi to not only allow assembling, but also labels and various directives
241
pub trait DynasmLabelApi : DynasmApi {
242
    /// The relocation info type this assembler uses. 
243
    type Relocation: Relocation;
244
245
    /// Record the definition of a local label
246
    fn local_label(  &mut self, name: &'static str);
247
    /// Record the definition of a global label
248
    fn global_label( &mut self, name: &'static str);
249
    /// Record the definition of a dynamic label
250
    fn dynamic_label(&mut self, id: DynamicLabel);
251
252
    /// Record a relocation spot for a forward reference to a local label
253
39.4k
    fn forward_reloc( &mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
254
39.4k
        self.forward_relocation(name, target_offset, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
255
39.4k
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmLabelApi>::forward_reloc
Line
Count
Source
253
38.0k
    fn forward_reloc( &mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
254
38.0k
        self.forward_relocation(name, target_offset, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
255
38.0k
    }
Unexecuted instantiation: <_ as dynasmrt::DynasmLabelApi>::forward_reloc
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmLabelApi>::forward_reloc
Line
Count
Source
253
1.43k
    fn forward_reloc( &mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
254
1.43k
        self.forward_relocation(name, target_offset, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
255
1.43k
    }
Unexecuted instantiation: <_ as dynasmrt::DynasmLabelApi>::forward_reloc
256
    /// Record a relocation spot for a backward reference to a local label
257
0
    fn backward_reloc(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
258
0
        self.backward_relocation(name, target_offset, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
259
0
    }
Unexecuted instantiation: <_ as dynasmrt::DynasmLabelApi>::backward_reloc
Unexecuted instantiation: <_ as dynasmrt::DynasmLabelApi>::backward_reloc
260
    /// Record a relocation spot for a reference to a global label
261
0
    fn global_reloc(  &mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
262
0
        self.global_relocation(name, target_offset, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
263
0
    }
Unexecuted instantiation: <_ as dynasmrt::DynasmLabelApi>::global_reloc
Unexecuted instantiation: <_ as dynasmrt::DynasmLabelApi>::global_reloc
264
    /// Record a relocation spot for a reference to a dynamic label
265
2.23M
    fn dynamic_reloc( &mut self, id: DynamicLabel,   target_offset: isize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
266
2.23M
        self.dynamic_relocation(id, target_offset, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
267
2.23M
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmLabelApi>::dynamic_reloc
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmLabelApi>::dynamic_reloc
Line
Count
Source
265
1.84M
    fn dynamic_reloc( &mut self, id: DynamicLabel,   target_offset: isize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
266
1.84M
        self.dynamic_relocation(id, target_offset, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
267
1.84M
    }
Unexecuted instantiation: <_ as dynasmrt::DynasmLabelApi>::dynamic_reloc
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmLabelApi>::dynamic_reloc
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmLabelApi>::dynamic_reloc
Line
Count
Source
265
381k
    fn dynamic_reloc( &mut self, id: DynamicLabel,   target_offset: isize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
266
381k
        self.dynamic_relocation(id, target_offset, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
267
381k
    }
Unexecuted instantiation: <_ as dynasmrt::DynasmLabelApi>::dynamic_reloc
268
    /// Record a relocation spot to an arbitrary target.
269
0
    fn bare_reloc(&mut self, target: usize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
270
0
        self.bare_relocation(target, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
271
0
    }
Unexecuted instantiation: <_ as dynasmrt::DynasmLabelApi>::bare_reloc
Unexecuted instantiation: <_ as dynasmrt::DynasmLabelApi>::bare_reloc
272
273
    /// Equivalent of forward_reloc, but takes a non-encoded relocation
274
    fn forward_relocation( &mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: Self::Relocation);
275
    /// Equivalent of backward_reloc, but takes a non-encoded relocation
276
    fn backward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: Self::Relocation);
277
    /// Equivalent of global_reloc, but takes a non-encoded relocation
278
    fn global_relocation(  &mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: Self::Relocation);
279
    /// Equivalent of dynamic_reloc, but takes a non-encoded relocation
280
    fn dynamic_relocation( &mut self, id: DynamicLabel,   target_offset: isize, field_offset: u8, ref_offset: u8, kind: Self::Relocation);
281
    /// Equivalent of bare_reloc, but takes a non-encoded relocation
282
    fn bare_relocation(&mut self, target: usize, field_offset: u8, ref_offset: u8, kind: Self::Relocation);
283
}
284
285
286
/// An assembler that is purely a `Vec<u8>`. It doesn't support labels or architecture-specific directives,
287
/// but can be used to easily inspect generated code. It is intended to be used in testcases.
288
#[derive(Debug, Clone)]
289
pub struct SimpleAssembler {
290
    /// The assembling buffer.
291
    pub ops: Vec<u8>
292
}
293
294
impl SimpleAssembler {
295
    /// Creates a new `SimpleAssembler`, containing an empty `Vec`.
296
0
    pub fn new() -> SimpleAssembler {
297
0
        SimpleAssembler {
298
0
            ops: Vec::new()
299
0
        }
300
0
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler>::new
Unexecuted instantiation: <dynasmrt::SimpleAssembler>::new
301
302
    /// Use an `UncommittedModifier` to alter uncommitted code.
303
0
    pub fn alter(&mut self) -> UncommittedModifier {
304
0
        UncommittedModifier::new(&mut self.ops, AssemblyOffset(0))
305
0
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler>::alter
Unexecuted instantiation: <dynasmrt::SimpleAssembler>::alter
306
307
    /// Destroys this assembler, returning the `Vec<u8>` contained within
308
0
    pub fn finalize(self) -> Vec<u8> {
309
0
        self.ops
310
0
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler>::finalize
Unexecuted instantiation: <dynasmrt::SimpleAssembler>::finalize
311
}
312
313
impl Extend<u8> for SimpleAssembler {
314
0
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=u8> {
315
0
        self.ops.extend(iter)
316
0
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as core::iter::traits::collect::Extend<u8>>::extend::<core::option::Option<u8>>
Unexecuted instantiation: <dynasmrt::SimpleAssembler as core::iter::traits::collect::Extend<u8>>::extend::<core::option::Option<u8>>
317
}
318
319
impl<'a> Extend<&'a u8> for SimpleAssembler {
320
0
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
321
0
        self.ops.extend(iter)
322
0
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as core::iter::traits::collect::Extend<&u8>>::extend::<core::option::Option<&u8>>
Unexecuted instantiation: <dynasmrt::SimpleAssembler as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 2]>
Unexecuted instantiation: <dynasmrt::SimpleAssembler as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 4]>
Unexecuted instantiation: <dynasmrt::SimpleAssembler as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 8]>
Unexecuted instantiation: <dynasmrt::SimpleAssembler as core::iter::traits::collect::Extend<&u8>>::extend::<core::option::Option<&u8>>
Unexecuted instantiation: <dynasmrt::SimpleAssembler as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 2]>
Unexecuted instantiation: <dynasmrt::SimpleAssembler as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 4]>
Unexecuted instantiation: <dynasmrt::SimpleAssembler as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 8]>
323
}
324
325
impl DynasmApi for SimpleAssembler {
326
0
    fn offset(&self) -> AssemblyOffset {
327
0
        AssemblyOffset(self.ops.len())
328
0
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::offset
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::offset
329
0
    fn push(&mut self, byte: u8) {
330
0
        self.ops.push(byte);
331
0
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::push
332
0
    fn align(&mut self, alignment: usize, with: u8) {
333
0
        let offset = self.offset().0 % alignment;
334
0
        if offset != 0 {
335
0
            for _ in offset .. alignment {
336
0
                self.push(with);
337
0
            }
338
0
        }
339
0
    }
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::align
Unexecuted instantiation: <dynasmrt::SimpleAssembler as dynasmrt::DynasmApi>::align
340
}
341
342
343
/// An assembler that assembles into a `Vec<u8>`, while supporting labels. To support the different types of relocations
344
/// it requires a base address of the to be assembled code to be specified.
345
#[derive(Debug)]
346
pub struct VecAssembler<R: Relocation> {
347
    ops: Vec<u8>,
348
    baseaddr: usize,
349
    labels: LabelRegistry,
350
    relocs: RelocRegistry<R>,
351
    error: Option<DynasmError>,
352
}
353
354
impl<R: Relocation> VecAssembler<R> {
355
    /// Creates a new VecAssembler, with the specified base address.
356
422k
    pub fn new(baseaddr: usize) -> VecAssembler<R> {
357
422k
        VecAssembler {
358
422k
            ops: Vec::new(),
359
422k
            baseaddr,
360
422k
            labels: LabelRegistry::new(),
361
422k
            relocs: RelocRegistry::new(),
362
422k
            error: None
363
422k
        }
364
422k
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation>>::new
Line
Count
Source
356
231k
    pub fn new(baseaddr: usize) -> VecAssembler<R> {
357
231k
        VecAssembler {
358
231k
            ops: Vec::new(),
359
231k
            baseaddr,
360
231k
            labels: LabelRegistry::new(),
361
231k
            relocs: RelocRegistry::new(),
362
231k
            error: None
363
231k
        }
364
231k
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation>>::new
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::new
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation>>::new
Line
Count
Source
356
191k
    pub fn new(baseaddr: usize) -> VecAssembler<R> {
357
191k
        VecAssembler {
358
191k
            ops: Vec::new(),
359
191k
            baseaddr,
360
191k
            labels: LabelRegistry::new(),
361
191k
            relocs: RelocRegistry::new(),
362
191k
            error: None
363
191k
        }
364
191k
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation>>::new
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::new
365
366
    /// Create a new dynamic label ID
367
3.85M
    pub fn new_dynamic_label(&mut self) -> DynamicLabel {
368
3.85M
        self.labels.new_dynamic_label()
369
3.85M
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation>>::new_dynamic_label
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation>>::new_dynamic_label
Line
Count
Source
367
2.77M
    pub fn new_dynamic_label(&mut self) -> DynamicLabel {
368
2.77M
        self.labels.new_dynamic_label()
369
2.77M
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::new_dynamic_label
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation>>::new_dynamic_label
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation>>::new_dynamic_label
Line
Count
Source
367
1.08M
    pub fn new_dynamic_label(&mut self) -> DynamicLabel {
368
1.08M
        self.labels.new_dynamic_label()
369
1.08M
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::new_dynamic_label
370
371
    /// Resolves any relocations emitted to the assembler before this point.
372
    /// If an impossible relocation was specified before this point, returns them here.
373
352k
    pub fn commit(&mut self) -> Result<(), DynasmError> {
374
        // If we accrued any errors while assembling before, emit them now.
375
352k
        if let Some(e) = self.error.take() {
376
0
            return Err(e);
377
352k
        }
378
379
        // Resolve globals
380
352k
        for (loc, name) in self.relocs.take_globals() {
381
0
            let target = self.labels.resolve_global(name)?;
382
0
            let buf = &mut self.ops[loc.range(0)];
383
0
            if loc.patch(buf, self.baseaddr, target.0).is_err() {
384
0
                return Err(DynasmError::ImpossibleRelocation(TargetKind::Global(name)));
385
0
            }
386
        }
387
388
        // Resolve dynamics
389
2.23M
        for (loc, id) in self.relocs.take_dynamics() {
390
2.23M
            let target = self.labels.resolve_dynamic(id)?;
391
2.23M
            let buf = &mut self.ops[loc.range(0)];
392
2.23M
            if loc.patch(buf, self.baseaddr, target.0).is_err() {
393
0
                return Err(DynasmError::ImpossibleRelocation(TargetKind::Dynamic(id)));
394
2.23M
            }
395
        }
396
397
        // Check that there are no unknown local labels
398
352k
        for (_, name) in self.relocs.take_locals() {
399
0
            return Err(DynasmError::UnknownLabel(LabelKind::Local(name)));
400
        }
401
402
352k
        Ok(())
403
352k
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation>>::commit
Line
Count
Source
373
212k
    pub fn commit(&mut self) -> Result<(), DynasmError> {
374
        // If we accrued any errors while assembling before, emit them now.
375
212k
        if let Some(e) = self.error.take() {
376
0
            return Err(e);
377
212k
        }
378
379
        // Resolve globals
380
212k
        for (loc, name) in self.relocs.take_globals() {
381
0
            let target = self.labels.resolve_global(name)?;
382
0
            let buf = &mut self.ops[loc.range(0)];
383
0
            if loc.patch(buf, self.baseaddr, target.0).is_err() {
384
0
                return Err(DynasmError::ImpossibleRelocation(TargetKind::Global(name)));
385
0
            }
386
        }
387
388
        // Resolve dynamics
389
1.84M
        for (loc, id) in self.relocs.take_dynamics() {
390
1.84M
            let target = self.labels.resolve_dynamic(id)?;
391
1.84M
            let buf = &mut self.ops[loc.range(0)];
392
1.84M
            if loc.patch(buf, self.baseaddr, target.0).is_err() {
393
0
                return Err(DynasmError::ImpossibleRelocation(TargetKind::Dynamic(id)));
394
1.84M
            }
395
        }
396
397
        // Check that there are no unknown local labels
398
212k
        for (_, name) in self.relocs.take_locals() {
399
0
            return Err(DynasmError::UnknownLabel(LabelKind::Local(name)));
400
        }
401
402
212k
        Ok(())
403
212k
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation>>::commit
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::commit
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation>>::commit
Line
Count
Source
373
139k
    pub fn commit(&mut self) -> Result<(), DynasmError> {
374
        // If we accrued any errors while assembling before, emit them now.
375
139k
        if let Some(e) = self.error.take() {
376
0
            return Err(e);
377
139k
        }
378
379
        // Resolve globals
380
139k
        for (loc, name) in self.relocs.take_globals() {
381
0
            let target = self.labels.resolve_global(name)?;
382
0
            let buf = &mut self.ops[loc.range(0)];
383
0
            if loc.patch(buf, self.baseaddr, target.0).is_err() {
384
0
                return Err(DynasmError::ImpossibleRelocation(TargetKind::Global(name)));
385
0
            }
386
        }
387
388
        // Resolve dynamics
389
381k
        for (loc, id) in self.relocs.take_dynamics() {
390
381k
            let target = self.labels.resolve_dynamic(id)?;
391
381k
            let buf = &mut self.ops[loc.range(0)];
392
381k
            if loc.patch(buf, self.baseaddr, target.0).is_err() {
393
0
                return Err(DynasmError::ImpossibleRelocation(TargetKind::Dynamic(id)));
394
381k
            }
395
        }
396
397
        // Check that there are no unknown local labels
398
139k
        for (_, name) in self.relocs.take_locals() {
399
0
            return Err(DynasmError::UnknownLabel(LabelKind::Local(name)));
400
        }
401
402
139k
        Ok(())
403
139k
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation>>::commit
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::commit
404
405
    /// Use an `UncommittedModifier` to alter uncommitted code.
406
    /// This does not allow the user to change labels/relocations.
407
0
    pub fn alter(&mut self) -> UncommittedModifier {
408
0
        UncommittedModifier::new(&mut self.ops, AssemblyOffset(0))
409
0
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::alter
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::alter
410
411
    /// Provides access to the assemblers internal labels registry
412
0
    pub fn labels(&self) -> &LabelRegistry {
413
0
        &self.labels
414
0
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::labels
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::labels
415
416
    /// Provides mutable access to the assemblers internal labels registry
417
0
    pub fn labels_mut(&mut self) -> &mut LabelRegistry {
418
0
        &mut self.labels
419
0
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::labels_mut
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::labels_mut
420
421
    /// Finalizes the `VecAssembler`, returning the resulting `Vec<u8>` containing all assembled data.
422
    /// this implicitly commits any relocations beforehand and returns an error if required.
423
352k
    pub fn finalize(mut self) -> Result<Vec<u8>, DynasmError> {
424
352k
        self.commit()?;
425
352k
        Ok(self.ops)
426
352k
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation>>::finalize
Line
Count
Source
423
212k
    pub fn finalize(mut self) -> Result<Vec<u8>, DynasmError> {
424
212k
        self.commit()?;
425
212k
        Ok(self.ops)
426
212k
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation>>::finalize
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::finalize
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation>>::finalize
Line
Count
Source
423
139k
    pub fn finalize(mut self) -> Result<Vec<u8>, DynasmError> {
424
139k
        self.commit()?;
425
139k
        Ok(self.ops)
426
139k
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation>>::finalize
Unexecuted instantiation: <dynasmrt::VecAssembler<_>>::finalize
427
}
428
429
impl<R: Relocation> Extend<u8> for VecAssembler<R> {
430
0
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=u8> {
431
0
        self.ops.extend(iter)
432
0
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as core::iter::traits::collect::Extend<u8>>::extend::<_>
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as core::iter::traits::collect::Extend<u8>>::extend::<_>
433
}
434
435
impl<'a, R: Relocation> Extend<&'a u8> for VecAssembler<R> {
436
47.9M
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
47.9M
        self.ops.extend(iter)
438
47.9M
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 1]>
Line
Count
Source
436
18.3M
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
18.3M
        self.ops.extend(iter)
438
18.3M
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 2]>
Line
Count
Source
436
7.45M
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
7.45M
        self.ops.extend(iter)
438
7.45M
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 3]>
Line
Count
Source
436
23.8k
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
23.8k
        self.ops.extend(iter)
438
23.8k
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 4]>
Line
Count
Source
436
10.1M
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
10.1M
        self.ops.extend(iter)
438
10.1M
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 5]>
Line
Count
Source
436
705k
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
705k
        self.ops.extend(iter)
438
705k
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 6]>
Line
Count
Source
436
1.17M
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
1.17M
        self.ops.extend(iter)
438
1.17M
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 8]>
Line
Count
Source
436
734k
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
734k
        self.ops.extend(iter)
438
734k
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 2]>
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 4]>
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 8]>
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as core::iter::traits::collect::Extend<&u8>>::extend::<_>
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 1]>
Line
Count
Source
436
4.57M
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
4.57M
        self.ops.extend(iter)
438
4.57M
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 2]>
Line
Count
Source
436
2.00M
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
2.00M
        self.ops.extend(iter)
438
2.00M
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 3]>
Line
Count
Source
436
12.5k
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
12.5k
        self.ops.extend(iter)
438
12.5k
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 4]>
Line
Count
Source
436
2.15M
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
2.15M
        self.ops.extend(iter)
438
2.15M
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 5]>
Line
Count
Source
436
156k
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
156k
        self.ops.extend(iter)
438
156k
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 6]>
Line
Count
Source
436
226k
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
226k
        self.ops.extend(iter)
438
226k
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 8]>
Line
Count
Source
436
188k
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
437
188k
        self.ops.extend(iter)
438
188k
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 2]>
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 4]>
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 8]>
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as core::iter::traits::collect::Extend<&u8>>::extend::<_>
439
}
440
441
impl<R: Relocation> DynasmApi for VecAssembler<R> {
442
15.8M
    fn offset(&self) -> AssemblyOffset {
443
15.8M
        AssemblyOffset(self.ops.len())
444
15.8M
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::offset
Line
Count
Source
442
11.4M
    fn offset(&self) -> AssemblyOffset {
443
11.4M
        AssemblyOffset(self.ops.len())
444
11.4M
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmApi>::offset
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmApi>::offset
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::offset
Line
Count
Source
442
4.38M
    fn offset(&self) -> AssemblyOffset {
443
4.38M
        AssemblyOffset(self.ops.len())
444
4.38M
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmApi>::offset
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmApi>::offset
445
64.9M
    fn push(&mut self, byte: u8) {
446
64.9M
        self.ops.push(byte);
447
64.9M
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::push
Line
Count
Source
445
51.2M
    fn push(&mut self, byte: u8) {
446
51.2M
        self.ops.push(byte);
447
51.2M
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmApi>::push
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmApi>::push
Line
Count
Source
445
13.6M
    fn push(&mut self, byte: u8) {
446
13.6M
        self.ops.push(byte);
447
13.6M
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmApi>::push
448
0
    fn align(&mut self, alignment: usize, with: u8) {
449
0
        let offset = self.offset().0 % alignment;
450
0
        if offset != 0 {
451
0
            for _ in offset .. alignment {
452
0
                self.push(with);
453
0
            }
454
0
        }
455
0
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmApi>::align
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmApi>::align
456
}
457
458
impl<R: Relocation> DynasmLabelApi for VecAssembler<R> {
459
    type Relocation = R;
460
461
845k
    fn local_label(&mut self, name: &'static str) {
462
845k
        let offset = self.offset();
463
845k
        for loc in self.relocs.take_locals_named(name) {
464
39.4k
            let buf = &mut self.ops[loc.range(0)];
465
39.4k
            if loc.patch(buf, self.baseaddr, offset.0).is_err() {
466
0
                self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Forward(name)))
467
39.4k
            }
468
        }
469
845k
        self.labels.define_local(name, offset);
470
845k
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmLabelApi>::local_label
Line
Count
Source
461
581k
    fn local_label(&mut self, name: &'static str) {
462
581k
        let offset = self.offset();
463
581k
        for loc in self.relocs.take_locals_named(name) {
464
38.0k
            let buf = &mut self.ops[loc.range(0)];
465
38.0k
            if loc.patch(buf, self.baseaddr, offset.0).is_err() {
466
0
                self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Forward(name)))
467
38.0k
            }
468
        }
469
581k
        self.labels.define_local(name, offset);
470
581k
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmLabelApi>::local_label
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::local_label
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmLabelApi>::local_label
Line
Count
Source
461
263k
    fn local_label(&mut self, name: &'static str) {
462
263k
        let offset = self.offset();
463
263k
        for loc in self.relocs.take_locals_named(name) {
464
1.43k
            let buf = &mut self.ops[loc.range(0)];
465
1.43k
            if loc.patch(buf, self.baseaddr, offset.0).is_err() {
466
0
                self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Forward(name)))
467
1.43k
            }
468
        }
469
263k
        self.labels.define_local(name, offset);
470
263k
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmLabelApi>::local_label
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::local_label
471
0
    fn global_label( &mut self, name: &'static str) {
472
0
        let offset = self.offset();
473
0
        if let Err(e) = self.labels.define_global(name, offset) {
474
0
            self.error = Some(e)
475
0
        }
476
0
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::global_label
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::global_label
477
3.85M
    fn dynamic_label(&mut self, id: DynamicLabel) {
478
3.85M
        let offset = self.offset();
479
3.85M
        if let Err(e) = self.labels.define_dynamic(id, offset) {
480
0
            self.error = Some(e)
481
3.85M
        }
482
3.85M
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmLabelApi>::dynamic_label
Line
Count
Source
477
2.77M
    fn dynamic_label(&mut self, id: DynamicLabel) {
478
2.77M
        let offset = self.offset();
479
2.77M
        if let Err(e) = self.labels.define_dynamic(id, offset) {
480
0
            self.error = Some(e)
481
2.77M
        }
482
2.77M
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmLabelApi>::dynamic_label
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::dynamic_label
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmLabelApi>::dynamic_label
Line
Count
Source
477
1.08M
    fn dynamic_label(&mut self, id: DynamicLabel) {
478
1.08M
        let offset = self.offset();
479
1.08M
        if let Err(e) = self.labels.define_dynamic(id, offset) {
480
0
            self.error = Some(e)
481
1.08M
        }
482
1.08M
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmLabelApi>::dynamic_label
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::dynamic_label
483
0
    fn global_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
484
0
        let location = self.offset();
485
0
        self.relocs.add_global(name, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
486
0
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::global_relocation
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::global_relocation
487
2.23M
    fn dynamic_relocation(&mut self, id: DynamicLabel, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
488
2.23M
        let location = self.offset();
489
2.23M
        self.relocs.add_dynamic(id, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
490
2.23M
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmLabelApi>::dynamic_relocation
Line
Count
Source
487
1.84M
    fn dynamic_relocation(&mut self, id: DynamicLabel, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
488
1.84M
        let location = self.offset();
489
1.84M
        self.relocs.add_dynamic(id, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
490
1.84M
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmLabelApi>::dynamic_relocation
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::dynamic_relocation
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmLabelApi>::dynamic_relocation
Line
Count
Source
487
381k
    fn dynamic_relocation(&mut self, id: DynamicLabel, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
488
381k
        let location = self.offset();
489
381k
        self.relocs.add_dynamic(id, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
490
381k
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<dynasmrt::aarch64::Aarch64Relocation> as dynasmrt::DynasmLabelApi>::dynamic_relocation
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::dynamic_relocation
491
39.4k
    fn forward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
492
39.4k
        let location = self.offset();
493
39.4k
        self.relocs.add_local(name, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
494
39.4k
    }
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmLabelApi>::forward_relocation
Line
Count
Source
491
38.0k
    fn forward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
492
38.0k
        let location = self.offset();
493
38.0k
        self.relocs.add_local(name, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
494
38.0k
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::forward_relocation
<dynasmrt::VecAssembler<dynasmrt::x64::X64Relocation> as dynasmrt::DynasmLabelApi>::forward_relocation
Line
Count
Source
491
1.43k
    fn forward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
492
1.43k
        let location = self.offset();
493
1.43k
        self.relocs.add_local(name, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
494
1.43k
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::forward_relocation
495
0
    fn backward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
496
0
        let target = match self.labels.resolve_local(name) {
497
0
            Ok(target) => target.0,
498
0
            Err(e) => {
499
0
                self.error = Some(e);
500
0
                return;
501
            }
502
        };
503
0
        let location = self.offset();
504
0
        let loc = PatchLoc::new(location, target_offset, field_offset, ref_offset, kind);
505
0
        let buf = &mut self.ops[loc.range(0)];
506
0
        if loc.patch(buf, self.baseaddr, target).is_err() {
507
0
            self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Backward(name)))
508
0
        }
509
0
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::backward_relocation
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::backward_relocation
510
0
    fn bare_relocation(&mut self, target: usize, field_offset: u8, ref_offset: u8, kind: R) {
511
0
        let location = self.offset();
512
0
        let loc = PatchLoc::new(location, 0, field_offset, ref_offset, kind);
513
0
        let buf = &mut self.ops[loc.range(0)];
514
0
        if loc.patch(buf, self.baseaddr, target).is_err() {
515
0
            self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Extern(target)))
516
0
        }
517
0
    }
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::bare_relocation
Unexecuted instantiation: <dynasmrt::VecAssembler<_> as dynasmrt::DynasmLabelApi>::bare_relocation
518
}
519
520
521
/// A full assembler implementation. Supports labels, all types of relocations,
522
/// incremental compilation and multithreaded execution with simultaneous compiltion.
523
/// Its implementation guarantees no memory is executable and writable at the same time.
524
#[derive(Debug)]
525
pub struct Assembler<R: Relocation> {
526
    ops: Vec<u8>,
527
    memory: MemoryManager,
528
    labels: LabelRegistry,
529
    relocs: RelocRegistry<R>,
530
    managed: ManagedRelocs<R>,
531
    error: Option<DynasmError>,
532
}
533
534
impl<R: Relocation> Assembler<R> {
535
    /// Create a new, empty assembler, with initial allocation size `page_size`.
536
0
    pub fn new() -> io::Result<Self> {
537
0
        Ok(Self {
538
0
            ops: Vec::new(),
539
0
            memory: MemoryManager::new(R::page_size())?,
540
0
            labels: LabelRegistry::new(),
541
0
            relocs: RelocRegistry::new(),
542
0
            managed: ManagedRelocs::new(),
543
0
            error: None
544
        })
545
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_>>::new
Unexecuted instantiation: <dynasmrt::Assembler<_>>::new
546
547
    /// Create a new dynamic label ID
548
0
    pub fn new_dynamic_label(&mut self) -> DynamicLabel {
549
0
        self.labels.new_dynamic_label()
550
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_>>::new_dynamic_label
Unexecuted instantiation: <dynasmrt::Assembler<_>>::new_dynamic_label
551
552
    /// Use an `UncommittedModifier` to alter uncommitted code.
553
    /// This does not allow the user to change labels/relocations.
554
0
    pub fn alter_uncommitted(&mut self) -> UncommittedModifier {
555
0
        let offset = self.memory.committed();
556
0
        UncommittedModifier::new(&mut self.ops, AssemblyOffset(offset))
557
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_>>::alter_uncommitted
Unexecuted instantiation: <dynasmrt::Assembler<_>>::alter_uncommitted
558
559
    /// Use a `Modifier` to alter committed code directly. While this is happening
560
    /// no code can be executed as the relevant pages are remapped as writable.
561
    /// This API supports defining new labels/relocations, and overwriting previously defined relocations.
562
0
    pub fn alter<F, O>(&mut self, f: F) -> Result<O, DynasmError>
563
0
    where F: FnOnce(&mut Modifier<R>) -> O {
564
0
        self.commit()?;
565
566
        // swap out a buffer from base
567
0
        let mut lock = self.memory.write();
568
0
        let buffer = mem::replace(&mut *lock, ExecutableBuffer::default());
569
0
        let mut buffer = buffer.make_mut().expect("Could not swap buffer protection modes");
570
0
571
0
        // construct the modifier
572
0
        let mut modifier = Modifier {
573
0
            asmoffset: 0,
574
0
            previous_asmoffset: 0,
575
0
            buffer: &mut *buffer,
576
0
577
0
            labels: &mut self.labels,
578
0
            relocs: &mut self.relocs,
579
0
            old_managed: &mut self.managed,
580
0
            new_managed: ManagedRelocs::new(),
581
0
582
0
            error: None
583
0
        };
584
0
585
0
        // execute the user code
586
0
        let output = f(&mut modifier);
587
0
588
0
        // flush any changes made by the user code to the buffer
589
0
        modifier.encode_relocs()?;
590
591
        // repack the buffer
592
0
        let buffer = buffer.make_exec().expect("Could not swap buffer protection modes");
593
0
        *lock = buffer;
594
0
595
0
        // call it a day
596
0
        Ok(output)
597
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_>>::alter::<_, _>
Unexecuted instantiation: <dynasmrt::Assembler<_>>::alter::<_, _>
598
599
    /// Commit code, flushing the temporary internal assembling buffer to the mapped executable memory.
600
    /// This makes assembled code available for execution.
601
0
    pub fn commit(&mut self) -> Result<(), DynasmError> {
602
0
        self.encode_relocs()?;
603
604
0
        let managed = &self.managed;
605
0
        let error = &mut self.error;
606
0
607
0
        self.memory.commit(&mut self.ops, |buffer, old_addr, new_addr| {
608
0
            let change = new_addr.wrapping_sub(old_addr) as isize;
609
610
0
            for reloc in managed.iter() {
611
0
                let buf = &mut buffer[reloc.range(0)];
612
0
                if reloc.adjust(buf, change).is_err() {
613
0
                    *error = Some(DynasmError::ImpossibleRelocation(TargetKind::Managed))
614
0
                }
615
            }
616
0
        });
Unexecuted instantiation: <dynasmrt::Assembler<_>>::commit::{closure#0}
Unexecuted instantiation: <dynasmrt::Assembler<_>>::commit::{closure#0}
617
618
0
        if let Some(e) = self.error.take() {
619
0
            return Err(e);
620
0
        }
621
0
        Ok(())
622
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_>>::commit
Unexecuted instantiation: <dynasmrt::Assembler<_>>::commit
623
624
    /// Finalize this assembler, returning the internal executablebuffer if no Executor instances exist.
625
    /// This panics if any uncommitted changes caused errors near the end. To handle these, call `commit()` explicitly beforehand.
626
0
    pub fn finalize(mut self) -> Result<ExecutableBuffer, Self> {
627
0
        self.commit().expect("Errors were encountered when committing before finalization");
628
0
        match self.memory.finalize() {
629
0
            Ok(execbuffer) => Ok(execbuffer),
630
0
            Err(memory) => Err(Self {
631
0
                memory,
632
0
                ..self
633
0
            })
634
        }
635
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_>>::finalize
Unexecuted instantiation: <dynasmrt::Assembler<_>>::finalize
636
637
    /// Create an executor which can be used to execute code while still assembling code
638
0
    pub fn reader(&self) -> Executor {
639
0
        Executor {
640
0
            execbuffer: self.memory.reader()
641
0
        }
642
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_>>::reader
Unexecuted instantiation: <dynasmrt::Assembler<_>>::reader
643
644
    /// Provides access to the assemblers internal labels registry
645
0
    pub fn labels(&self) -> &LabelRegistry {
646
0
        &self.labels
647
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_>>::labels
Unexecuted instantiation: <dynasmrt::Assembler<_>>::labels
648
649
    /// Provides mutable access to the assemblers internal labels registry
650
0
    pub fn labels_mut(&mut self) -> &mut LabelRegistry {
651
0
        &mut self.labels
652
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_>>::labels_mut
Unexecuted instantiation: <dynasmrt::Assembler<_>>::labels_mut
653
654
    // encode uncommited relocations
655
0
    fn encode_relocs(&mut self) -> Result<(), DynasmError> {
656
0
        let buf_offset = self.memory.committed();
657
0
        let buf_addr = self.memory.execbuffer_addr();
658
0
        let buf = &mut self.ops;
659
660
        // If we accrued any errors while assembling before, emit them now.
661
0
        if let Some(e) = self.error.take() {
662
0
            return Err(e);
663
0
        }
664
665
        // Resolve globals
666
0
        for (loc, name) in self.relocs.take_globals() {
667
0
            let target = self.labels.resolve_global(name)?;
668
0
            let buf = &mut buf[loc.range(buf_offset)];
669
0
            if loc.patch(buf, buf_addr, target.0).is_err() {
670
0
                return Err(DynasmError::ImpossibleRelocation(TargetKind::Global(name)));
671
0
            }
672
0
            if loc.needs_adjustment() {
673
0
                self.managed.add(loc)
674
0
            }
675
        }
676
677
        // Resolve dynamics
678
0
        for (loc, id) in self.relocs.take_dynamics() {
679
0
            let target = self.labels.resolve_dynamic(id)?;
680
0
            let buf = &mut buf[loc.range(buf_offset)];
681
0
            if loc.patch(buf, buf_addr, target.0).is_err() {
682
0
                return Err(DynasmError::ImpossibleRelocation(TargetKind::Dynamic(id)));
683
0
            }
684
0
            if loc.needs_adjustment() {
685
0
                self.managed.add(loc)
686
0
            }
687
        }
688
689
        // Check that there are no unknown local labels
690
0
        for (_, name) in self.relocs.take_locals() {
691
0
            return Err(DynasmError::UnknownLabel(LabelKind::Local(name)));
692
        }
693
694
0
        Ok(())
695
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_>>::encode_relocs
Unexecuted instantiation: <dynasmrt::Assembler<_>>::encode_relocs
696
}
697
698
impl<R: Relocation> Extend<u8> for Assembler<R> {
699
0
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=u8> {
700
0
        self.ops.extend(iter)
701
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_> as core::iter::traits::collect::Extend<u8>>::extend::<_>
Unexecuted instantiation: <dynasmrt::Assembler<_> as core::iter::traits::collect::Extend<u8>>::extend::<_>
702
}
703
704
impl<'a, R: Relocation> Extend<&'a u8> for Assembler<R> {
705
0
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
706
0
        self.ops.extend(iter)
707
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_> as core::iter::traits::collect::Extend<&u8>>::extend::<_>
Unexecuted instantiation: <dynasmrt::Assembler<_> as core::iter::traits::collect::Extend<&u8>>::extend::<_>
708
}
709
710
impl<R: Relocation> DynasmApi for Assembler<R> {
711
0
    fn offset(&self) -> AssemblyOffset {
712
0
        AssemblyOffset(self.memory.committed() + self.ops.len())
713
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmApi>::offset
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmApi>::offset
714
715
0
    fn push(&mut self, value: u8) {
716
0
        self.ops.push(value);
717
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmApi>::push
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmApi>::push
718
719
0
    fn align(&mut self, alignment: usize, with: u8) {
720
0
        let misalign = self.offset().0 % alignment;
721
0
        if misalign != 0 {
722
0
            for _ in misalign .. alignment {
723
0
                self.push(with);
724
0
            }
725
0
        }
726
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmApi>::align
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmApi>::align
727
}
728
729
impl<R: Relocation> DynasmLabelApi for Assembler<R> {
730
    type Relocation = R;
731
732
0
    fn local_label(&mut self, name: &'static str) {
733
0
        let offset = self.offset();
734
0
        for loc in self.relocs.take_locals_named(name) {
735
0
            let buf = &mut self.ops[loc.range(self.memory.committed())];
736
0
            if loc.patch(buf, self.memory.execbuffer_addr(), offset.0).is_err() {
737
0
                self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Forward(name)))
738
0
            } else if loc.needs_adjustment() {
739
0
                self.managed.add(loc)
740
0
            }
741
        }
742
0
        self.labels.define_local(name, offset);
743
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::local_label
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::local_label
744
0
    fn global_label( &mut self, name: &'static str) {
745
0
        let offset = self.offset();
746
0
        if let Err(e) = self.labels.define_global(name, offset) {
747
0
            self.error = Some(e)
748
0
        }
749
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::global_label
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::global_label
750
0
    fn dynamic_label(&mut self, id: DynamicLabel) {
751
0
        let offset = self.offset();
752
0
        if let Err(e) = self.labels.define_dynamic(id, offset) {
753
0
            self.error = Some(e)
754
0
        }
755
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::dynamic_label
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::dynamic_label
756
0
    fn global_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
757
0
        let location = self.offset();
758
0
        self.relocs.add_global(name, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
759
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::global_relocation
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::global_relocation
760
0
    fn dynamic_relocation(&mut self, id: DynamicLabel, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
761
0
        let location = self.offset();
762
0
        self.relocs.add_dynamic(id, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
763
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::dynamic_relocation
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::dynamic_relocation
764
0
    fn forward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
765
0
        let location = self.offset();
766
0
        self.relocs.add_local(name, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
767
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::forward_relocation
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::forward_relocation
768
0
    fn backward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
769
0
        let target = match self.labels.resolve_local(name) {
770
0
            Ok(target) => target.0,
771
0
            Err(e) => {
772
0
                self.error = Some(e);
773
0
                return;
774
            }
775
        };
776
0
        let location = self.offset();
777
0
        let loc = PatchLoc::new(location, target_offset, field_offset, ref_offset, kind);
778
0
        let buf = &mut self.ops[loc.range(self.memory.committed())];
779
0
        if loc.patch(buf, self.memory.execbuffer_addr(), target).is_err() {
780
0
            self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Backward(name)))
781
0
        } else if loc.needs_adjustment() {
782
0
            self.managed.add(loc)
783
0
        }
784
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::backward_relocation
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::backward_relocation
785
0
    fn bare_relocation(&mut self, target: usize, field_offset: u8, ref_offset: u8, kind: R) {
786
0
        let location = self.offset();
787
0
        let loc = PatchLoc::new(location, 0, field_offset, ref_offset, kind);
788
0
        let buf = &mut self.ops[loc.range(self.memory.committed())];
789
0
        if loc.patch(buf, self.memory.execbuffer_addr(), target).is_err() {
790
0
            self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Extern(target)))
791
0
        } else if loc.needs_adjustment() {
792
0
            self.managed.add(loc)
793
0
        }
794
0
    }
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::bare_relocation
Unexecuted instantiation: <dynasmrt::Assembler<_> as dynasmrt::DynasmLabelApi>::bare_relocation
795
}
796
797
798
/// Allows modification of already committed assembly code. Contains an internal cursor
799
/// into the emitted assembly, initialized to the start, that can be moved around either with the
800
/// `goto` function, or just by assembling new code into this `Modifier`.
801
#[derive(Debug)]
802
pub struct Modifier<'a, R: Relocation> {
803
    asmoffset: usize,
804
    previous_asmoffset: usize,
805
    buffer: &'a mut [u8],
806
807
    labels: &'a mut LabelRegistry,
808
    relocs: &'a mut RelocRegistry<R>,
809
    old_managed: &'a mut ManagedRelocs<R>,
810
    new_managed: ManagedRelocs<R>,
811
812
    error: Option<DynasmError>
813
}
814
815
impl<'a, R: Relocation> Modifier<'a, R> {
816
    /// Move the modifier cursor to the selected location.
817
0
    pub fn goto(&mut self, offset: AssemblyOffset) {
818
0
        self.old_managed.remove_between(self.previous_asmoffset, self.asmoffset);
819
0
        self.asmoffset = offset.0;
820
0
        self.previous_asmoffset = offset.0;
821
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_>>::goto
Unexecuted instantiation: <dynasmrt::Modifier<_>>::goto
822
823
    /// Check that the modifier cursor has not moved past the specified location.
824
0
    pub fn check(&self, offset: AssemblyOffset) -> Result<(), DynasmError> {
825
0
        if self.asmoffset > offset.0 {
826
0
            Err(DynasmError::CheckFailed)
827
        } else {
828
0
            Ok(())
829
        }
830
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_>>::check
Unexecuted instantiation: <dynasmrt::Modifier<_>>::check
831
832
    /// Check that the modifier cursor is exactly at the specified location.
833
0
    pub fn check_exact(&self, offset: AssemblyOffset) -> Result<(), DynasmError> {
834
0
        if self.asmoffset != offset.0 {
835
0
            Err(DynasmError::CheckFailed)
836
        } else {
837
0
            Ok(())
838
        }
839
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_>>::check_exact
Unexecuted instantiation: <dynasmrt::Modifier<_>>::check_exact
840
841
    // encode uncommited relocations
842
0
    fn encode_relocs(&mut self) -> Result<(), DynasmError> {
843
0
        let buf_addr = self.buffer.as_ptr() as usize;
844
845
        // If we accrued any errors while assembling before, emit them now.
846
0
        if let Some(e) = self.error.take() {
847
0
            return Err(e);
848
0
        }
849
850
        // Resolve globals
851
0
        for (loc, name) in self.relocs.take_globals() {
852
0
            let target = self.labels.resolve_global(name)?;
853
0
            let buf = &mut self.buffer[loc.range(0)];
854
0
            if loc.patch(buf, buf_addr, target.0).is_err() {
855
0
                return Err(DynasmError::ImpossibleRelocation(TargetKind::Global(name)));
856
0
            }
857
0
            if loc.needs_adjustment() {
858
0
                self.new_managed.add(loc);
859
0
            }
860
        }
861
862
        // Resolve dynamics
863
0
        for (loc, id) in self.relocs.take_dynamics() {
864
0
            let target = self.labels.resolve_dynamic(id)?;
865
0
            let buf = &mut self.buffer[loc.range(0)];
866
0
            if loc.patch(buf, buf_addr, target.0).is_err() {
867
0
                return Err(DynasmError::ImpossibleRelocation(TargetKind::Dynamic(id)));
868
0
            }
869
0
            if loc.needs_adjustment() {
870
0
                self.new_managed.add(loc);
871
0
            }
872
        }
873
874
        // Check for unknown locals
875
0
        for (_, name) in self.relocs.take_locals() {
876
0
            return Err(DynasmError::UnknownLabel(LabelKind::Local(name)));
877
        }
878
879
0
        self.old_managed.remove_between(self.previous_asmoffset, self.asmoffset);
880
0
        self.previous_asmoffset = self.asmoffset;
881
0
882
0
        self.old_managed.append(&mut self.new_managed);
883
0
884
0
        Ok(())
885
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_>>::encode_relocs
Unexecuted instantiation: <dynasmrt::Modifier<_>>::encode_relocs
886
}
887
888
impl<'a, R: Relocation> Extend<u8> for Modifier<'a,R> {
889
0
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=u8> {
890
0
        for (src, dst) in iter.into_iter().zip(self.buffer[self.asmoffset ..].iter_mut()) {
891
0
            *dst = src;
892
0
            self.asmoffset += 1;
893
0
        }
894
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_> as core::iter::traits::collect::Extend<u8>>::extend::<_>
Unexecuted instantiation: <dynasmrt::Modifier<_> as core::iter::traits::collect::Extend<u8>>::extend::<_>
895
}
896
897
impl<'a, 'b, R: Relocation> Extend<&'b u8> for Modifier<'a, R> {
898
0
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'b u8> {
899
0
        for (src, dst) in iter.into_iter().zip(self.buffer[self.asmoffset ..].iter_mut()) {
900
0
            *dst = *src;
901
0
            self.asmoffset += 1;
902
0
        }
903
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_> as core::iter::traits::collect::Extend<&u8>>::extend::<_>
Unexecuted instantiation: <dynasmrt::Modifier<_> as core::iter::traits::collect::Extend<&u8>>::extend::<_>
904
}
905
906
impl<'a, R: Relocation> DynasmApi for Modifier<'a, R> {
907
0
    fn offset(&self) -> AssemblyOffset {
908
0
        AssemblyOffset(self.asmoffset)
909
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmApi>::offset
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmApi>::offset
910
911
0
    fn push(&mut self, value: u8) {
912
0
        self.buffer[self.asmoffset] = value;
913
0
        self.asmoffset += 1
914
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmApi>::push
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmApi>::push
915
916
0
    fn align(&mut self, alignment: usize, with: u8) {
917
0
        let mismatch = self.asmoffset % alignment;
918
0
        if mismatch != 0 {
919
0
            for _ in mismatch .. alignment {
920
0
                self.push(with)
921
            }
922
0
        }
923
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmApi>::align
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmApi>::align
924
}
925
926
impl<'a, R: Relocation> DynasmLabelApi for Modifier<'a, R> {
927
    type Relocation = R;
928
929
0
    fn local_label(&mut self, name: &'static str) {
930
0
        let offset = self.offset();
931
0
        for loc in self.relocs.take_locals_named(name) {
932
0
            let buf_addr = self.buffer.as_ptr() as usize;
933
0
            let buf = &mut self.buffer[loc.range(0)];
934
0
            if loc.patch(buf, buf_addr, offset.0).is_err()  {
935
0
                self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Forward(name)));
936
0
            } else if loc.needs_adjustment() {
937
0
                self.new_managed.add(loc);
938
0
            }
939
        }
940
0
        self.labels.define_local(name, offset);
941
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::local_label
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::local_label
942
0
    fn global_label( &mut self, name: &'static str) {
943
0
        let offset = self.offset();
944
0
        if let Err(e) = self.labels.define_global(name, offset) {
945
0
            self.error = Some(e);
946
0
        }
947
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::global_label
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::global_label
948
0
    fn dynamic_label(&mut self, id: DynamicLabel) {
949
0
        let offset = self.offset();
950
0
        if let Err(e) = self.labels.define_dynamic(id, offset) {
951
0
            self.error = Some(e);
952
0
        }
953
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::dynamic_label
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::dynamic_label
954
0
    fn global_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
955
0
        let location = self.offset();
956
0
        self.relocs.add_global(name, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
957
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::global_relocation
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::global_relocation
958
0
    fn dynamic_relocation(&mut self, id: DynamicLabel, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
959
0
        let location = self.offset();
960
0
        self.relocs.add_dynamic(id, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
961
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::dynamic_relocation
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::dynamic_relocation
962
0
    fn forward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
963
0
        let location = self.offset();
964
0
        self.relocs.add_local(name, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
965
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::forward_relocation
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::forward_relocation
966
0
    fn backward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
967
0
        let target = match self.labels.resolve_local(name) {
968
0
            Ok(target) => target.0,
969
0
            Err(e) => {
970
0
                self.error = Some(e);
971
0
                return;
972
            }
973
        };
974
0
        let location = self.offset();
975
0
        let loc = PatchLoc::new(location, target_offset, field_offset, ref_offset, kind);
976
0
            let buf_addr = self.buffer.as_ptr() as usize;
977
0
        let buf = &mut self.buffer[loc.range(0)];
978
0
        if loc.patch(buf, buf_addr, target).is_err() {
979
0
            self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Backward(name)));
980
0
        } else if loc.needs_adjustment() {
981
0
            self.new_managed.add(loc)
982
0
        }
983
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::backward_relocation
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::backward_relocation
984
0
    fn bare_relocation(&mut self, target: usize, field_offset: u8, ref_offset: u8, kind: R) {
985
0
        let location = self.offset();
986
0
        let loc = PatchLoc::new(location, 0, field_offset, ref_offset, kind);
987
0
            let buf_addr = self.buffer.as_ptr() as usize;
988
0
        let buf = &mut self.buffer[loc.range(0)];
989
0
        if loc.patch(buf, buf_addr, target).is_err() {
990
0
            self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Extern(target)));
991
0
        } else if loc.needs_adjustment() {
992
0
            self.new_managed.add(loc)
993
0
        }
994
0
    }
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::bare_relocation
Unexecuted instantiation: <dynasmrt::Modifier<_> as dynasmrt::DynasmLabelApi>::bare_relocation
995
}
996
997
998
/// This struct is a wrapper around an `Assembler` normally created using the
999
/// `Assembler.alter_uncommitted` method. It allows the user to edit parts
1000
/// of the assembling buffer that cannot be determined easily or efficiently
1001
/// in advance. Due to limitations of the label resolution algorithms, this
1002
/// assembler does not allow labels to be used.
1003
#[derive(Debug)]
1004
pub struct UncommittedModifier<'a> {
1005
    buffer: &'a mut Vec<u8>,
1006
    base_offset: usize,
1007
    offset: usize
1008
}
1009
1010
impl<'a> UncommittedModifier<'a> {
1011
    /// create a new uncommittedmodifier
1012
0
    pub fn new(buffer: &mut Vec<u8>, base_offset: AssemblyOffset) -> UncommittedModifier {
1013
0
        UncommittedModifier {
1014
0
            buffer,
1015
0
            base_offset: base_offset.0,
1016
0
            offset: base_offset.0
1017
0
        }
1018
0
    }
Unexecuted instantiation: <dynasmrt::UncommittedModifier>::new
Unexecuted instantiation: <dynasmrt::UncommittedModifier>::new
1019
1020
    /// Sets the current modification offset to the given value
1021
0
    pub fn goto(&mut self, offset: AssemblyOffset) {
1022
0
        self.offset = offset.0;
1023
0
    }
Unexecuted instantiation: <dynasmrt::UncommittedModifier>::goto
Unexecuted instantiation: <dynasmrt::UncommittedModifier>::goto
1024
1025
    /// Checks that the current modification offset is not larger than the specified offset.
1026
0
    pub fn check(&mut self, offset: AssemblyOffset) -> Result<(), DynasmError> {
1027
0
        if self.offset > offset.0 {
1028
0
            Err(DynasmError::CheckFailed)
1029
        } else {
1030
0
            Ok(())
1031
        }
1032
0
    }
Unexecuted instantiation: <dynasmrt::UncommittedModifier>::check
Unexecuted instantiation: <dynasmrt::UncommittedModifier>::check
1033
1034
    /// Checks that the current modification offset is exactly the specified offset.
1035
0
    pub fn check_exact(&mut self, offset: AssemblyOffset) -> Result<(), DynasmError> {
1036
0
        if self.offset != offset.0 {
1037
0
            Err(DynasmError::CheckFailed)
1038
        } else {
1039
0
            Ok(())
1040
        }
1041
0
    }
Unexecuted instantiation: <dynasmrt::UncommittedModifier>::check_exact
Unexecuted instantiation: <dynasmrt::UncommittedModifier>::check_exact
1042
}
1043
1044
impl<'a> DynasmApi for UncommittedModifier<'a> {
1045
0
    fn offset(&self) -> AssemblyOffset {
1046
0
        AssemblyOffset(self.offset)
1047
0
    }
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::offset
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::offset
1048
1049
0
    fn push(&mut self, value: u8) {
1050
0
        self.buffer[self.offset - self.base_offset] = value;
1051
0
        self.offset += 1;
1052
0
    }
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::push
1053
1054
0
    fn align(&mut self, alignment: usize, with: u8) {
1055
0
        let mismatch = self.offset % alignment;
1056
0
        if mismatch != 0 {
1057
0
            for _ in mismatch .. alignment {
1058
0
                self.push(with)
1059
            }
1060
0
        }
1061
0
    }
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::align
Unexecuted instantiation: <dynasmrt::UncommittedModifier as dynasmrt::DynasmApi>::align
1062
}
1063
1064
impl<'a> Extend<u8> for UncommittedModifier<'a> {
1065
0
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=u8> {
1066
0
        for i in iter {
1067
0
            self.push(i)
1068
        }
1069
0
    }
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<u8>>::extend::<core::option::Option<u8>>
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<u8>>::extend::<core::iter::adapters::cloned::Cloned<core::option::IntoIter<&u8>>>
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<u8>>::extend::<core::iter::adapters::cloned::Cloned<core::slice::iter::Iter<u8>>>
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<u8>>::extend::<core::option::Option<u8>>
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<u8>>::extend::<core::iter::adapters::cloned::Cloned<core::option::IntoIter<&u8>>>
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<u8>>::extend::<core::iter::adapters::cloned::Cloned<core::slice::iter::Iter<u8>>>
1070
}
1071
1072
impl<'a, 'b> Extend<&'b u8> for UncommittedModifier<'a> {
1073
0
    fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'b u8> {
1074
0
        self.extend(iter.into_iter().cloned())
1075
0
    }
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<&u8>>::extend::<core::option::Option<&u8>>
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 2]>
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 4]>
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 8]>
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<&u8>>::extend::<core::option::Option<&u8>>
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 2]>
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 4]>
Unexecuted instantiation: <dynasmrt::UncommittedModifier as core::iter::traits::collect::Extend<&u8>>::extend::<&[u8; 8]>
1076
}
1077
1078
/// A trait abstracting over architectural register families. This is usually implemented
1079
/// over an enum of all available registers in each family. This allows for code that is generic
1080
/// over register families.
1081
pub trait Register: Debug + Clone + Copy + PartialEq + Eq + Hash {
1082
    /// Returns the integer ID of the register. Usually equivalent to casting
1083
    /// the enum to an u8, but allows you to be generic over the register family.
1084
    fn code(&self) -> u8;
1085
}