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}