1#![warn(missing_docs)]
2
3pub mod mmap;
8pub mod components;
9pub mod relocations;
10pub mod cache_control;
11
12macro_rules! reg_impls {
14 ($r:ty) => {
15 impl $crate::Register for $r {
16 fn code(&self) -> u8 {
17 *self as u8
18 }
19 }
20
21 impl From<$r> for u8 {
22 fn from(rq: $r) -> u8 {
23 rq.code()
24 }
25 }
26 }
27}
28
29pub mod x64;
30pub mod x86;
31pub mod aarch64;
32pub mod riscv;
33
34pub use crate::mmap::ExecutableBuffer;
35pub use dynasm::{dynasm, dynasm_backwards};
36
37use crate::components::{MemoryManager, LabelRegistry, RelocRegistry, ManagedRelocs, PatchLoc, StaticLabel};
38use crate::relocations::Relocation;
39
40use std::hash::Hash;
41use std::sync::{Arc, RwLock, RwLockReadGuard};
42use std::io;
43use std::error;
44use std::fmt::{self, Debug};
45use std::mem;
46
47#[macro_export]
50macro_rules! Pointer {
51 ($e:expr) => {$e as *const _ as _};
52}
53
54#[macro_export]
56macro_rules! MutPointer {
57 ($e:expr) => {$e as *mut _ as _};
58}
59
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
64pub struct AssemblyOffset(pub usize);
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
68pub struct DynamicLabel(usize);
69
70
71impl DynamicLabel {
72 pub fn get_id(self) -> usize {
74 self.0
75 }
76}
77
78
79#[derive(Debug, Clone)]
82pub struct Executor {
83 execbuffer: Arc<RwLock<ExecutableBuffer>>
84}
85
86impl Executor {
89 #[inline]
94 pub fn lock(&self) -> RwLockReadGuard<'_, ExecutableBuffer> {
95 let guard = self.execbuffer.read().unwrap();
96 cache_control::prepare_for_execution(&*guard);
97 guard
98 }
99}
100
101
102#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
104pub enum LabelKind {
105 Local(&'static str),
107 Global(&'static str),
109 Dynamic(DynamicLabel)
111}
112
113impl fmt::Display for LabelKind {
114 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115 match self {
116 Self::Local(s) => write!(f, "label {}", s),
117 Self::Global(s) => write!(f, "label ->{}", s),
118 Self::Dynamic(id) => write!(f, "label =>{}", id.get_id())
119 }
120 }
121}
122
123
124#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
126pub enum TargetKind {
127 Local(&'static str),
129 Global(&'static str),
131 Dynamic(DynamicLabel),
133 Extern(usize),
135 Managed,
137}
138
139impl fmt::Display for TargetKind {
140 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141 match self {
142 Self::Local(s) => write!(f, "target [><]{}", s),
143 Self::Global(s) => write!(f, "target ->{}", s),
144 Self::Dynamic(id) => write!(f, "target =>{}", id.get_id()),
145 Self::Extern(value) => write!(f, "target extern {}", value),
146 Self::Managed => write!(f, "while adjusting managed relocation"),
147 }
148 }
149}
150
151
152#[derive(Debug, Clone, PartialEq, Eq)]
154pub enum DynasmError {
155 CheckFailed,
157 DuplicateLabel(LabelKind),
159 UnknownLabel(LabelKind),
161 ImpossibleRelocation(TargetKind),
163}
164
165impl fmt::Display for DynasmError {
166 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
167 match self {
168 DynasmError::CheckFailed => write!(f, "An assembly modification check failed"),
169 DynasmError::DuplicateLabel(l) => write!(f, "Duplicate label defined: '{}'", l),
170 DynasmError::UnknownLabel(l) => write!(f, "Unknown label: '{}'", l),
171 DynasmError::ImpossibleRelocation(s) => write!(f, "Impossible relocation: '{}'", s),
172 }
173 }
174}
175
176impl error::Error for DynasmError {
177 fn description(&self) -> &str {
178 match self {
179 DynasmError::CheckFailed => "An assembly modification offset check failed",
180 DynasmError::DuplicateLabel(_) => "Duplicate label defined",
181 DynasmError::UnknownLabel(_) => "Unknown label",
182 DynasmError::ImpossibleRelocation(_) => "Impossible relocation",
183 }
184 }
185}
186
187
188pub trait DynasmApi: Extend<u8> + for<'a> Extend<&'a u8> {
191 fn offset(&self) -> AssemblyOffset;
193 fn push(&mut self, byte: u8);
195 fn align(&mut self, alignment: usize, with: u8);
197
198 #[inline]
199 fn push_i8(&mut self, value: i8) {
201 self.push(value as u8);
202 }
203 #[inline]
205 fn push_i16(&mut self, value: i16) {
206 self.extend(&value.to_le_bytes());
207 }
208 #[inline]
210 fn push_i32(&mut self, value: i32) {
211 self.extend(&value.to_le_bytes());
212 }
213 #[inline]
215 fn push_i64(&mut self, value: i64) {
216 self.extend(&value.to_le_bytes());
217 }
218 #[inline]
220 fn push_u16(&mut self, value: u16) {
221 self.extend(&value.to_le_bytes());
222 }
223 #[inline]
225 fn push_u32(&mut self, value: u32) {
226 self.extend(&value.to_le_bytes());
227 }
228 #[inline]
230 fn push_u64(&mut self, value: u64) {
231 self.extend(&value.to_le_bytes());
232 }
233 #[inline]
235 fn runtime_error(&self, msg: &'static str) -> ! {
236 panic!("{}", msg);
237 }
238}
239
240pub trait DynasmLabelApi : DynasmApi {
245 type Relocation: Relocation;
247
248 fn local_label( &mut self, name: &'static str);
250 fn global_label( &mut self, name: &'static str);
252 fn dynamic_label(&mut self, id: DynamicLabel);
254
255 fn forward_reloc( &mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
257 self.forward_relocation(name, target_offset, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
258 }
259 fn backward_reloc(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
261 self.backward_relocation(name, target_offset, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
262 }
263 fn global_reloc( &mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
265 self.global_relocation(name, target_offset, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
266 }
267 fn dynamic_reloc( &mut self, id: DynamicLabel, target_offset: isize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
269 self.dynamic_relocation(id, target_offset, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
270 }
271 fn bare_reloc(&mut self, target: usize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as Relocation>::Encoding) {
273 self.bare_relocation(target, field_offset, ref_offset, Self::Relocation::from_encoding(kind))
274 }
275
276 fn forward_relocation( &mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: Self::Relocation);
278 fn backward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: Self::Relocation);
280 fn global_relocation( &mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: Self::Relocation);
282 fn dynamic_relocation( &mut self, id: DynamicLabel, target_offset: isize, field_offset: u8, ref_offset: u8, kind: Self::Relocation);
284 fn bare_relocation(&mut self, target: usize, field_offset: u8, ref_offset: u8, kind: Self::Relocation);
286}
287
288
289#[derive(Debug, Clone)]
292pub struct SimpleAssembler {
293 pub ops: Vec<u8>
295}
296
297impl SimpleAssembler {
298 pub fn new() -> SimpleAssembler {
300 SimpleAssembler {
301 ops: Vec::new()
302 }
303 }
304
305 pub fn alter(&mut self) -> UncommittedModifier<'_> {
307 UncommittedModifier::new(&mut self.ops, AssemblyOffset(0))
308 }
309
310 pub fn finalize(self) -> Vec<u8> {
312 self.ops
313 }
314}
315
316impl Extend<u8> for SimpleAssembler {
317 fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=u8> {
318 self.ops.extend(iter)
319 }
320}
321
322impl<'a> Extend<&'a u8> for SimpleAssembler {
323 fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
324 self.ops.extend(iter)
325 }
326}
327
328impl DynasmApi for SimpleAssembler {
329 fn offset(&self) -> AssemblyOffset {
330 AssemblyOffset(self.ops.len())
331 }
332 fn push(&mut self, byte: u8) {
333 self.ops.push(byte);
334 }
335 fn align(&mut self, alignment: usize, with: u8) {
336 let offset = self.offset().0 % alignment;
337 if offset != 0 {
338 for _ in offset .. alignment {
339 self.push(with);
340 }
341 }
342 }
343}
344
345
346#[derive(Debug)]
349pub struct VecAssembler<R: Relocation> {
350 ops: Vec<u8>,
351 baseaddr: usize,
352 labels: LabelRegistry,
353 relocs: RelocRegistry<R>,
354 error: Option<DynasmError>,
355}
356
357impl<R: Relocation> VecAssembler<R> {
358 pub fn new(baseaddr: usize) -> VecAssembler<R> {
360 VecAssembler {
361 ops: Vec::new(),
362 baseaddr,
363 labels: LabelRegistry::new(),
364 relocs: RelocRegistry::new(),
365 error: None
366 }
367 }
368
369 pub fn new_with_capacity(baseaddr: usize, ops_capacity: usize,
379 local_labels: usize, global_labels: usize, dynamic_labels: usize,
380 static_references: usize, dynamic_references: usize) -> VecAssembler<R> {
381 VecAssembler {
382 ops: Vec::with_capacity(ops_capacity),
383 baseaddr,
384 labels: LabelRegistry::with_capacity(local_labels, global_labels, dynamic_labels),
385 relocs: RelocRegistry::with_capacity(static_references, dynamic_references),
386 error: None
387 }
388 }
389
390 pub fn reserve_ops(&mut self, additional: usize) {
392 self.ops.reserve(additional);
393 }
394
395 pub fn new_dynamic_label(&mut self) -> DynamicLabel {
397 self.labels.new_dynamic_label()
398 }
399
400 pub fn commit(&mut self) -> Result<(), DynasmError> {
403 if let Some(e) = self.error.take() {
405 return Err(e);
406 }
407
408 for (loc, label) in self.relocs.take_statics() {
410 let target = self.labels.resolve_static(&label)?;
411 let buf = &mut self.ops[loc.range(0)];
412 if loc.patch(buf, self.baseaddr, target.0).is_err() {
413 return Err(DynasmError::ImpossibleRelocation(
414 if label.is_global() {
415 TargetKind::Global(label.get_name())
416 } else {
417 TargetKind::Local(label.get_name())
418 }
419 ));
420 }
421 }
422
423 for (loc, id) in self.relocs.take_dynamics() {
425 let target = self.labels.resolve_dynamic(id)?;
426 let buf = &mut self.ops[loc.range(0)];
427 if loc.patch(buf, self.baseaddr, target.0).is_err() {
428 return Err(DynasmError::ImpossibleRelocation(TargetKind::Dynamic(id)));
429 }
430 }
431
432 Ok(())
433 }
434
435 pub fn alter(&mut self) -> UncommittedModifier<'_> {
438 UncommittedModifier::new(&mut self.ops, AssemblyOffset(0))
439 }
440
441 pub fn labels(&self) -> &LabelRegistry {
443 &self.labels
444 }
445
446 pub fn labels_mut(&mut self) -> &mut LabelRegistry {
448 &mut self.labels
449 }
450
451 pub fn finalize(mut self) -> Result<Vec<u8>, DynasmError> {
454 self.commit()?;
455 Ok(self.ops)
456 }
457
458 pub fn take(&mut self) -> Result<Vec<u8>, DynasmError> {
460 self.commit()?;
461 self.labels.clear();
462 Ok(std::mem::take(&mut self.ops))
463 }
464
465 pub fn drain<'a>(&'a mut self) -> Result<impl Iterator<Item=u8> + 'a, DynasmError> {
467 self.commit()?;
468 self.labels.clear();
469 Ok(self.ops.drain(..))
470 }
471}
472
473impl<R: Relocation> Extend<u8> for VecAssembler<R> {
474 fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=u8> {
475 self.ops.extend(iter)
476 }
477}
478
479impl<'a, R: Relocation> Extend<&'a u8> for VecAssembler<R> {
480 fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
481 self.ops.extend(iter)
482 }
483}
484
485impl<R: Relocation> DynasmApi for VecAssembler<R> {
486 fn offset(&self) -> AssemblyOffset {
487 AssemblyOffset(self.ops.len())
488 }
489 fn push(&mut self, byte: u8) {
490 self.ops.push(byte);
491 }
492 fn align(&mut self, alignment: usize, with: u8) {
493 let offset = self.offset().0 % alignment;
494 if offset != 0 {
495 for _ in offset .. alignment {
496 self.push(with);
497 }
498 }
499 }
500}
501
502impl<R: Relocation> DynasmLabelApi for VecAssembler<R> {
503 type Relocation = R;
504
505 fn local_label(&mut self, name: &'static str) {
506 let offset = self.offset();
507 self.labels.define_local(name, offset);
508 }
509 fn global_label( &mut self, name: &'static str) {
510 let offset = self.offset();
511 if let Err(e) = self.labels.define_global(name, offset) {
512 self.error = Some(e)
513 }
514 }
515 fn dynamic_label(&mut self, id: DynamicLabel) {
516 let offset = self.offset();
517 if let Err(e) = self.labels.define_dynamic(id, offset) {
518 self.error = Some(e)
519 }
520 }
521 fn global_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
522 let location = self.offset();
523 let label = StaticLabel::global(name);
524 self.relocs.add_static(label, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
525 }
526 fn dynamic_relocation(&mut self, id: DynamicLabel, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
527 let location = self.offset();
528 self.relocs.add_dynamic(id, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
529 }
530 fn forward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
531 let location = self.offset();
532 let label = match self.labels.place_local_reference(name) {
533 Some(label) => label.next(),
534 None => StaticLabel::first(name),
535 };
536 self.relocs.add_static(label, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
537 }
538 fn backward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
539 let location = self.offset();
540 let label = match self.labels.place_local_reference(name) {
541 Some(label) => label,
542 None => {
543 self.error = Some(DynasmError::UnknownLabel(LabelKind::Local(name)));
544 return;
545 }
546 };
547 self.relocs.add_static(label, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
548 }
549 fn bare_relocation(&mut self, target: usize, field_offset: u8, ref_offset: u8, kind: R) {
550 let location = self.offset();
551 let loc = PatchLoc::new(location, 0, field_offset, ref_offset, kind);
552 let buf = &mut self.ops[loc.range(0)];
553 if loc.patch(buf, self.baseaddr, target).is_err() {
554 self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Extern(target)))
555 }
556 }
557}
558
559
560#[derive(Debug)]
564pub struct Assembler<R: Relocation> {
565 ops: Vec<u8>,
566 memory: MemoryManager,
567 labels: LabelRegistry,
568 relocs: RelocRegistry<R>,
569 managed: ManagedRelocs<R>,
570 error: Option<DynasmError>,
571}
572
573impl<R: Relocation> Assembler<R> {
574 pub fn new() -> io::Result<Self> {
576 Ok(Self {
577 ops: Vec::new(),
578 memory: MemoryManager::new(R::page_size())?,
579 labels: LabelRegistry::new(),
580 relocs: RelocRegistry::new(),
581 managed: ManagedRelocs::new(),
582 error: None
583 })
584 }
585
586 pub fn new_with_capacity(capacity: usize) -> io::Result<Self> {
589 let memory_size =
591 capacity
592 .checked_next_multiple_of(R::page_size())
593 .ok_or(io::Error::new(
594 io::ErrorKind::InvalidInput,
595 "Capacity is too large",
596 ))?;
597
598 Ok(Self {
599 ops: Vec::with_capacity(capacity),
600 memory: MemoryManager::new(memory_size)?,
601 labels: LabelRegistry::new(),
602 relocs: RelocRegistry::new(),
603 managed: ManagedRelocs::new(),
604 error: None,
605 })
606 }
607
608 pub fn new_dynamic_label(&mut self) -> DynamicLabel {
610 self.labels.new_dynamic_label()
611 }
612
613 pub fn alter_uncommitted(&mut self) -> UncommittedModifier<'_> {
616 let offset = self.memory.committed();
617 UncommittedModifier::new(&mut self.ops, AssemblyOffset(offset))
618 }
619
620 pub fn alter<F, O>(&mut self, f: F) -> Result<O, DynasmError>
624 where F: FnOnce(&mut Modifier<R>) -> O {
625 self.commit()?;
626
627 let mut lock = self.memory.write();
629 let buffer = mem::replace(&mut *lock, ExecutableBuffer::default());
630 let mut buffer = buffer.make_mut().expect("Could not swap buffer protection modes");
631
632 let mut modifier = Modifier {
634 asmoffset: 0,
635 previous_asmoffset: 0,
636 buffer: &mut buffer,
637
638 labels: &mut self.labels,
639 relocs: &mut self.relocs,
640 old_managed: &mut self.managed,
641 new_managed: ManagedRelocs::new(),
642
643 error: None
644 };
645
646 let output = f(&mut modifier);
648
649 modifier.encode_relocs()?;
651
652 let buffer = buffer.make_exec().expect("Could not swap buffer protection modes");
654 *lock = buffer;
655
656 Ok(output)
658 }
659
660 pub fn commit(&mut self) -> Result<(), DynasmError> {
663 self.encode_relocs()?;
664
665 let managed = &self.managed;
666 let error = &mut self.error;
667
668 self.memory.commit(&mut self.ops, |buffer, old_addr, new_addr| {
669 let change = new_addr.wrapping_sub(old_addr) as isize;
670
671 for reloc in managed.iter() {
672 let buf = &mut buffer[reloc.range(0)];
673 if reloc.adjust(buf, change).is_err() {
674 *error = Some(DynasmError::ImpossibleRelocation(TargetKind::Managed))
675 }
676
677 }
680 });
681
682 if let Some(e) = self.error.take() {
683 return Err(e);
684 }
685 Ok(())
686 }
687
688 pub fn finalize(mut self) -> Result<ExecutableBuffer, Self> {
691 self.commit().expect("Errors were encountered when committing before finalization");
692 match self.memory.finalize() {
693 Ok(execbuffer) => {
694 cache_control::prepare_for_execution(&execbuffer);
695 Ok(execbuffer)
696 },
697 Err(memory) => Err(Self {
698 memory,
699 ..self
700 })
701 }
702 }
703
704 pub fn reader(&self) -> Executor {
706 Executor {
707 execbuffer: self.memory.reader()
708 }
709 }
710
711 pub fn labels(&self) -> &LabelRegistry {
713 &self.labels
714 }
715
716 pub fn labels_mut(&mut self) -> &mut LabelRegistry {
718 &mut self.labels
719 }
720
721 fn encode_relocs(&mut self) -> Result<(), DynasmError> {
723 let buf_offset = self.memory.committed();
724 let buf_addr = self.memory.execbuffer_addr();
725 let buf = &mut self.ops;
726
727 if let Some(e) = self.error.take() {
729 return Err(e);
730 }
731
732 for (loc, label) in self.relocs.take_statics() {
734 let target = self.labels.resolve_static(&label)?;
735 let buf = &mut buf[loc.range(buf_offset)];
736 if loc.patch(buf, buf_addr, target.0).is_err() {
737 return Err(DynasmError::ImpossibleRelocation(
738 if label.is_global() {
739 TargetKind::Global(label.get_name())
740 } else {
741 TargetKind::Local(label.get_name())
742 }
743 ));
744 }
745 if loc.needs_adjustment() {
746 self.managed.add(loc)
747 }
748 }
749
750 for (loc, id) in self.relocs.take_dynamics() {
752 let target = self.labels.resolve_dynamic(id)?;
753 let buf = &mut buf[loc.range(buf_offset)];
754 if loc.patch(buf, buf_addr, target.0).is_err() {
755 return Err(DynasmError::ImpossibleRelocation(TargetKind::Dynamic(id)));
756 }
757 if loc.needs_adjustment() {
758 self.managed.add(loc)
759 }
760 }
761
762 Ok(())
763 }
764}
765
766impl<R: Relocation> Extend<u8> for Assembler<R> {
767 fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=u8> {
768 self.ops.extend(iter)
769 }
770}
771
772impl<'a, R: Relocation> Extend<&'a u8> for Assembler<R> {
773 fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'a u8> {
774 self.ops.extend(iter)
775 }
776}
777
778impl<R: Relocation> DynasmApi for Assembler<R> {
779 fn offset(&self) -> AssemblyOffset {
780 AssemblyOffset(self.memory.committed() + self.ops.len())
781 }
782
783 fn push(&mut self, value: u8) {
784 self.ops.push(value);
785 }
786
787 fn align(&mut self, alignment: usize, with: u8) {
788 let misalign = self.offset().0 % alignment;
789 if misalign != 0 {
790 for _ in misalign .. alignment {
791 self.push(with);
792 }
793 }
794 }
795}
796
797impl<R: Relocation> DynasmLabelApi for Assembler<R> {
798 type Relocation = R;
799
800 fn local_label(&mut self, name: &'static str) {
801 let offset = self.offset();
802 self.labels.define_local(name, offset);
803 }
804 fn global_label( &mut self, name: &'static str) {
805 let offset = self.offset();
806 if let Err(e) = self.labels.define_global(name, offset) {
807 self.error = Some(e)
808 }
809 }
810 fn dynamic_label(&mut self, id: DynamicLabel) {
811 let offset = self.offset();
812 if let Err(e) = self.labels.define_dynamic(id, offset) {
813 self.error = Some(e)
814 }
815 }
816 fn global_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
817 let location = self.offset();
818 let label = StaticLabel::global(name);
819 self.relocs.add_static(label, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
820 }
821 fn dynamic_relocation(&mut self, id: DynamicLabel, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
822 let location = self.offset();
823 self.relocs.add_dynamic(id, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
824 }
825 fn forward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
826 let location = self.offset();
827 let label = match self.labels.place_local_reference(name) {
828 Some(label) => label.next(),
829 None => StaticLabel::first(name),
830 };
831 self.relocs.add_static(label, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
832 }
833 fn backward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
834 let location = self.offset();
835 let label = match self.labels.place_local_reference(name) {
836 Some(label) => label,
837 None => {
838 self.error = Some(DynasmError::UnknownLabel(LabelKind::Local(name)));
839 return;
840 }
841 };
842 self.relocs.add_static(label, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
843 }
844 fn bare_relocation(&mut self, target: usize, field_offset: u8, ref_offset: u8, kind: R) {
845 let location = self.offset();
846 let loc = PatchLoc::new(location, 0, field_offset, ref_offset, kind);
847 let buf = &mut self.ops[loc.range(self.memory.committed())];
848 if loc.patch(buf, self.memory.execbuffer_addr(), target).is_err() {
849 self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Extern(target)))
850 } else if loc.needs_adjustment() {
851 self.managed.add(loc)
852 }
853 }
854}
855
856
857#[derive(Debug)]
861pub struct Modifier<'a, R: Relocation> {
862 asmoffset: usize,
863 previous_asmoffset: usize,
864 buffer: &'a mut [u8],
865
866 labels: &'a mut LabelRegistry,
867 relocs: &'a mut RelocRegistry<R>,
868 old_managed: &'a mut ManagedRelocs<R>,
869 new_managed: ManagedRelocs<R>,
870
871 error: Option<DynasmError>
872}
873
874impl<'a, R: Relocation> Modifier<'a, R> {
875 pub fn goto(&mut self, offset: AssemblyOffset) {
877 cache_control::synchronize_icache(&self.buffer[self.previous_asmoffset .. self.asmoffset]);
879
880 self.old_managed.remove_between(self.previous_asmoffset, self.asmoffset);
882
883 self.asmoffset = offset.0;
885 self.previous_asmoffset = offset.0;
886 }
887
888 pub fn check(&self, offset: AssemblyOffset) -> Result<(), DynasmError> {
890 if self.asmoffset > offset.0 {
891 Err(DynasmError::CheckFailed)
892 } else {
893 Ok(())
894 }
895 }
896
897 pub fn check_exact(&self, offset: AssemblyOffset) -> Result<(), DynasmError> {
899 if self.asmoffset != offset.0 {
900 Err(DynasmError::CheckFailed)
901 } else {
902 Ok(())
903 }
904 }
905
906 fn encode_relocs(&mut self) -> Result<(), DynasmError> {
908 let buf_addr = self.buffer.as_ptr() as usize;
909
910 cache_control::synchronize_icache(&self.buffer[self.previous_asmoffset .. self.asmoffset]);
912
913 if let Some(e) = self.error.take() {
915 return Err(e);
916 }
917
918 for (loc, label) in self.relocs.take_statics() {
920 let target = self.labels.resolve_static(&label)?;
921 let buf = &mut self.buffer[loc.range(0)];
922 if loc.patch(buf, buf_addr, target.0).is_err() {
923 return Err(DynasmError::ImpossibleRelocation(
924 if label.is_global() {
925 TargetKind::Global(label.get_name())
926 } else {
927 TargetKind::Local(label.get_name())
928 }
929 ));
930 }
931
932 cache_control::synchronize_icache(buf);
934
935 if loc.needs_adjustment() {
936 self.new_managed.add(loc);
937 }
938 }
939
940 for (loc, id) in self.relocs.take_dynamics() {
942 let target = self.labels.resolve_dynamic(id)?;
943 let buf = &mut self.buffer[loc.range(0)];
944 if loc.patch(buf, buf_addr, target.0).is_err() {
945 return Err(DynasmError::ImpossibleRelocation(TargetKind::Dynamic(id)));
946 }
947
948 cache_control::synchronize_icache(buf);
950
951 if loc.needs_adjustment() {
952 self.new_managed.add(loc);
953 }
954 }
955
956 self.old_managed.remove_between(self.previous_asmoffset, self.asmoffset);
957 self.previous_asmoffset = self.asmoffset;
958
959 self.old_managed.append(&mut self.new_managed);
960
961 Ok(())
962 }
963}
964
965impl<'a, R: Relocation> Extend<u8> for Modifier<'a,R> {
966 fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=u8> {
967 for (src, dst) in iter.into_iter().zip(self.buffer[self.asmoffset ..].iter_mut()) {
968 *dst = src;
969 self.asmoffset += 1;
970 }
971 }
972}
973
974impl<'a, 'b, R: Relocation> Extend<&'b u8> for Modifier<'a, R> {
975 fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'b u8> {
976 for (src, dst) in iter.into_iter().zip(self.buffer[self.asmoffset ..].iter_mut()) {
977 *dst = *src;
978 self.asmoffset += 1;
979 }
980 }
981}
982
983impl<'a, R: Relocation> DynasmApi for Modifier<'a, R> {
984 fn offset(&self) -> AssemblyOffset {
985 AssemblyOffset(self.asmoffset)
986 }
987
988 fn push(&mut self, value: u8) {
989 self.buffer[self.asmoffset] = value;
990 self.asmoffset += 1
991 }
992
993 fn align(&mut self, alignment: usize, with: u8) {
994 let mismatch = self.asmoffset % alignment;
995 if mismatch != 0 {
996 for _ in mismatch .. alignment {
997 self.push(with)
998 }
999 }
1000 }
1001}
1002
1003impl<'a, R: Relocation> DynasmLabelApi for Modifier<'a, R> {
1004 type Relocation = R;
1005
1006 fn local_label(&mut self, name: &'static str) {
1007 let offset = self.offset();
1008 self.labels.define_local(name, offset);
1009 }
1010 fn global_label( &mut self, name: &'static str) {
1011 let offset = self.offset();
1012 if let Err(e) = self.labels.define_global(name, offset) {
1013 self.error = Some(e);
1014 }
1015 }
1016 fn dynamic_label(&mut self, id: DynamicLabel) {
1017 let offset = self.offset();
1018 if let Err(e) = self.labels.define_dynamic(id, offset) {
1019 self.error = Some(e);
1020 }
1021 }
1022 fn global_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
1023 let location = self.offset();
1024 let label = StaticLabel::global(name);
1025 self.relocs.add_static(label, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
1026 }
1027 fn dynamic_relocation(&mut self, id: DynamicLabel, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
1028 let location = self.offset();
1029 self.relocs.add_dynamic(id, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
1030 }
1031 fn forward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
1032 let location = self.offset();
1033 let label = match self.labels.place_local_reference(name) {
1034 Some(label) => label.next(),
1035 None => StaticLabel::first(name),
1036 };
1037 self.relocs.add_static(label, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
1038 }
1039 fn backward_relocation(&mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: R) {
1040 let location = self.offset();
1041 let label = match self.labels.place_local_reference(name) {
1042 Some(label) => label,
1043 None => {
1044 self.error = Some(DynasmError::UnknownLabel(LabelKind::Local(name)));
1045 return;
1046 }
1047 };
1048 self.relocs.add_static(label, PatchLoc::new(location, target_offset, field_offset, ref_offset, kind));
1049 }
1050 fn bare_relocation(&mut self, target: usize, field_offset: u8, ref_offset: u8, kind: R) {
1051 let location = self.offset();
1052 let loc = PatchLoc::new(location, 0, field_offset, ref_offset, kind);
1053 let buf_addr = self.buffer.as_ptr() as usize;
1054 let buf = &mut self.buffer[loc.range(0)];
1055 if loc.patch(buf, buf_addr, target).is_err() {
1056 self.error = Some(DynasmError::ImpossibleRelocation(TargetKind::Extern(target)));
1057 } else if loc.needs_adjustment() {
1058 self.new_managed.add(loc)
1059 }
1060 }
1061}
1062
1063
1064#[derive(Debug)]
1070pub struct UncommittedModifier<'a> {
1071 buffer: &'a mut Vec<u8>,
1072 base_offset: usize,
1073 offset: usize
1074}
1075
1076impl<'a> UncommittedModifier<'a> {
1077 pub fn new(buffer: &mut Vec<u8>, base_offset: AssemblyOffset) -> UncommittedModifier<'_> {
1079 UncommittedModifier {
1080 buffer,
1081 base_offset: base_offset.0,
1082 offset: base_offset.0
1083 }
1084 }
1085
1086 pub fn goto(&mut self, offset: AssemblyOffset) {
1088 self.offset = offset.0;
1089 }
1090
1091 pub fn check(&mut self, offset: AssemblyOffset) -> Result<(), DynasmError> {
1093 if self.offset > offset.0 {
1094 Err(DynasmError::CheckFailed)
1095 } else {
1096 Ok(())
1097 }
1098 }
1099
1100 pub fn check_exact(&mut self, offset: AssemblyOffset) -> Result<(), DynasmError> {
1102 if self.offset != offset.0 {
1103 Err(DynasmError::CheckFailed)
1104 } else {
1105 Ok(())
1106 }
1107 }
1108}
1109
1110impl<'a> DynasmApi for UncommittedModifier<'a> {
1111 fn offset(&self) -> AssemblyOffset {
1112 AssemblyOffset(self.offset)
1113 }
1114
1115 fn push(&mut self, value: u8) {
1116 self.buffer[self.offset - self.base_offset] = value;
1117 self.offset += 1;
1118 }
1119
1120 fn align(&mut self, alignment: usize, with: u8) {
1121 let mismatch = self.offset % alignment;
1122 if mismatch != 0 {
1123 for _ in mismatch .. alignment {
1124 self.push(with)
1125 }
1126 }
1127 }
1128}
1129
1130impl<'a> Extend<u8> for UncommittedModifier<'a> {
1131 fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=u8> {
1132 for i in iter {
1133 self.push(i)
1134 }
1135 }
1136}
1137
1138impl<'a, 'b> Extend<&'b u8> for UncommittedModifier<'a> {
1139 fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=&'b u8> {
1140 self.extend(iter.into_iter().cloned())
1141 }
1142}
1143
1144pub trait Register: Debug + Clone + Copy + PartialEq + Eq + Hash {
1148 fn code(&self) -> u8;
1151}