diff --git a/plugin/src/serialize.rs b/plugin/src/serialize.rs index 0d452ee9c..7d4866764 100644 --- a/plugin/src/serialize.rs +++ b/plugin/src/serialize.rs @@ -251,7 +251,7 @@ pub fn expr_size_of_scale(ty: &syn::Path, value: &TokenTree, size: Size) -> Toke let size = size.as_literal(); delimited(quote_spanned! { span=> - (::std::mem::size_of::<#ty>() as #size) * #value + (::core::mem::size_of::<#ty>() as #size) * #value }) } @@ -303,17 +303,17 @@ pub fn expr_offset_of(path: &syn::Path, attr: &syn::Ident, size: Size) -> TokenT let size = size.as_literal(); delimited(quote_spanned! { span=> - ::std::mem::offset_of!(#path, #attr) as #size + ::core::mem::offset_of!(#path, #attr) as #size }) } -// returns std::mem::size_of() +// returns core::mem::size_of() pub fn expr_size_of(path: &syn::Path) -> TokenTree { // generate a P that returns the size of type at path let span = path.span(); delimited(quote_spanned! { span=> - ::std::mem::size_of::<#path>() + ::core::mem::size_of::<#path>() }) } diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 32d59ed33..b7af82d07 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -15,7 +15,12 @@ license.workspace = true [dependencies] -memmap2 = "0.9.5" -byteorder = "1.5.0" -fnv = "1.0.7" +memmap2 = { version = "0.9.5", optional = true } +byteorder = { version = "1.5.0", default-features = false } +fnv = { version = "1.0.7", default-features = false } dynasm = { version = "=3.0.1", path = "../plugin" } +hashbrown = "0.15.1" + +[features] +default = [] +std = ["fnv/std", "byteorder/std", "memmap2"] \ No newline at end of file diff --git a/runtime/src/aarch64.rs b/runtime/src/aarch64.rs index 6d5141959..103f5964a 100644 --- a/runtime/src/aarch64.rs +++ b/runtime/src/aarch64.rs @@ -25,7 +25,7 @@ use crate::Register; use crate::relocations::{Relocation, RelocationSize, RelocationKind, ImpossibleRelocation, fits_signed_bitfield}; use byteorder::{ByteOrder, LittleEndian}; -use std::convert::TryFrom; +use core::convert::TryFrom; /// Relocation implementation for the aarch64 architecture. #[derive(Debug, Clone)] @@ -188,6 +188,7 @@ impl Relocation for Aarch64Relocation { } /// An aarch64 Assembler. This is aliased here for backwards compatability. +#[cfg(feature = "std")] pub type Assembler = crate::Assembler; /// An aarch64 AssemblyModifier. This is aliased here for backwards compatability. pub type AssemblyModifier<'a> = crate::Modifier<'a, Aarch64Relocation>; diff --git a/runtime/src/cache_control.rs b/runtime/src/cache_control.rs index b227b5e8e..6f55af935 100644 --- a/runtime/src/cache_control.rs +++ b/runtime/src/cache_control.rs @@ -29,7 +29,7 @@ pub fn synchronize_icache(slice: &[u8]) { #[cfg(target_arch="aarch64")] mod aarch64 { - use std::arch::asm; + use core::arch::asm; /// return the cache line sizes as reported by the processor as a tuple of (dcache, icache) fn get_cacheline_sizes() -> (usize, usize) { diff --git a/runtime/src/components.rs b/runtime/src/components.rs index 1d24d9345..a7e7436c2 100644 --- a/runtime/src/components.rs +++ b/runtime/src/components.rs @@ -1,18 +1,37 @@ //! This module provides several reusable compoments for implementing assemblers -use std::io; +#[cfg(feature = "std")] use std::collections::hash_map::Entry; -use std::collections::BTreeMap; -use std::sync::{Arc, RwLock, RwLockWriteGuard}; -use std::mem; +use alloc::collections::BTreeMap; +#[cfg(feature = "std")] +use alloc::sync::Arc; +use alloc::vec::Vec; +#[cfg(feature = "std")] +use core::mem; + +#[cfg(feature = "std")] +use std::io; +#[cfg(feature = "std")] +use std::sync::{RwLock, RwLockWriteGuard}; +#[cfg(feature = "std")] use fnv::FnvHashMap; +#[cfg(not(feature = "std"))] +type FnvHashMap = hashbrown::HashMap; + +#[cfg(not(feature = "std"))] +use hashbrown::hash_map::Entry; + use crate::{DynamicLabel, AssemblyOffset, DynasmError, LabelKind, DynasmLabelApi}; -use crate::mmap::{ExecutableBuffer, MutableBuffer}; use crate::relocations::{Relocation, RelocationKind, RelocationSize, ImpossibleRelocation}; + +#[cfg(feature = "std")] use crate::cache_control; +#[cfg(feature = "std")] +use crate::mmap::{ExecutableBuffer, MutableBuffer}; + /// A static label represents either a local label or a global label reference. /// /// Global labels are unique names, which can be referenced multiple times, but only defined once @@ -79,6 +98,7 @@ impl StaticLabel { /// This struct implements a protection-swapping assembling buffer #[derive(Debug)] +#[cfg(feature = "std")] pub struct MemoryManager { // buffer where the end result is copied into execbuffer: Arc>, @@ -92,6 +112,7 @@ pub struct MemoryManager { execbuffer_addr: usize } +#[cfg(feature = "std")] impl MemoryManager { /// Create a new memory manager, with `initial_mmap_size` data allocated pub fn new(initial_mmap_size: usize) -> io::Result { @@ -333,7 +354,7 @@ impl PatchLoc { /// Returns a range that covers the entire relocation in its assembling buffer /// `buf_offset` is a value that is subtracted from this range when the buffer you want to slice /// with this range is only a part of a bigger buffer. - pub fn range(&self, buf_offset: usize) -> std::ops::Range { + pub fn range(&self, buf_offset: usize) -> core::ops::Range { let field_offset = self.location.0 - buf_offset - self.field_offset as usize; field_offset .. field_offset + self.relocation.size() } @@ -646,7 +667,7 @@ mod tests { } fn test_litpool() { - let mut ops = Assembler::::new().unwrap(); + let mut ops = VecAssembler::::new(0x0); let dynamic1 = ops.new_dynamic_label(); let mut pool = components::LitPool::new(); diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 049b411fd..18317a046 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1,9 +1,21 @@ +#![cfg_attr(not(any(feature = "std", test)), no_std)] #![warn(missing_docs)] +#![warn( + clippy::alloc_instead_of_core, + clippy::std_instead_of_core, + clippy::std_instead_of_alloc +)] //! This crate provides runtime support for dynasm-rs. It contains traits that document the interface used by the dynasm proc_macro to generate code, //! Assemblers that implement these traits, and relocation models for the various supported architectures. Additionally, it also provides the tools //! to write your own Assemblers using these components. +extern crate alloc; + +#[cfg(test)] +extern crate std; + +#[cfg(feature = "std")] pub mod mmap; pub mod components; pub mod relocations; @@ -30,18 +42,28 @@ pub mod x64; pub mod x86; pub mod aarch64; +#[cfg(feature = "std")] pub use crate::mmap::ExecutableBuffer; pub use dynasm::{dynasm, dynasm_backwards}; -use crate::components::{MemoryManager, LabelRegistry, RelocRegistry, ManagedRelocs, PatchLoc, StaticLabel}; +use crate::components::{LabelRegistry, RelocRegistry, ManagedRelocs, PatchLoc, StaticLabel}; +#[cfg(feature = "std")] +use crate::components::MemoryManager; use crate::relocations::Relocation; -use std::hash::Hash; -use std::sync::{Arc, RwLock, RwLockReadGuard}; +use core::hash::Hash; +use core::error; +use core::fmt::{self, Debug}; +#[cfg(feature = "std")] +use core::mem; +#[cfg(feature = "std")] +use alloc::sync::Arc; +use alloc::vec::Vec; + +#[cfg(feature = "std")] +use std::sync::{RwLock, RwLockReadGuard}; +#[cfg(feature = "std")] use std::io; -use std::error; -use std::fmt::{self, Debug}; -use std::mem; /// This macro takes a *const pointer from the source operand, and then casts it to the desired return type. /// this allows it to be used as an easy shorthand for passing pointers as dynasm immediate arguments. @@ -78,12 +100,14 @@ impl DynamicLabel { /// A read-only shared reference to the executable buffer inside an `Assembler`. By /// locking it the internal `ExecutableBuffer` can be accessed and executed. #[derive(Debug, Clone)] +#[cfg(feature = "std")] pub struct Executor { execbuffer: Arc> } /// A read-only lockable reference to the internal `ExecutableBuffer` of an `Assembler`. /// To gain access to this buffer, it must be locked. +#[cfg(feature = "std")] impl Executor { /// Gain read-access to the internal `ExecutableBuffer`. While the returned guard /// is alive, it can be used to read and execute from the `ExecutableBuffer`. @@ -458,7 +482,7 @@ impl VecAssembler { pub fn take(&mut self) -> Result, DynasmError> { self.commit()?; self.labels.clear(); - Ok(std::mem::take(&mut self.ops)) + Ok(core::mem::take(&mut self.ops)) } /// Equivalent of take, but instead of allocating a new vector it simply provides a draining iterator over the internal contents. @@ -560,6 +584,7 @@ impl DynasmLabelApi for VecAssembler { /// incremental compilation and multithreaded execution with simultaneous compilation. /// Its implementation guarantees no memory is executable and writable at the same time. #[derive(Debug)] +#[cfg(feature = "std")] pub struct Assembler { ops: Vec, memory: MemoryManager, @@ -569,6 +594,7 @@ pub struct Assembler { error: Option, } +#[cfg(feature = "std")] impl Assembler { /// Create a new, empty assembler, with initial allocation size `page_size`. pub fn new() -> io::Result { @@ -740,18 +766,21 @@ impl Assembler { } } +#[cfg(feature = "std")] impl Extend for Assembler { fn extend(&mut self, iter: T) where T: IntoIterator { self.ops.extend(iter) } } +#[cfg(feature = "std")] impl<'a, R: Relocation> Extend<&'a u8> for Assembler { fn extend(&mut self, iter: T) where T: IntoIterator { self.ops.extend(iter) } } +#[cfg(feature = "std")] impl DynasmApi for Assembler { fn offset(&self) -> AssemblyOffset { AssemblyOffset(self.memory.committed() + self.ops.len()) @@ -771,6 +800,7 @@ impl DynasmApi for Assembler { } } +#[cfg(feature = "std")] impl DynasmLabelApi for Assembler { type Relocation = R; @@ -881,6 +911,7 @@ impl<'a, R: Relocation> Modifier<'a, R> { } // encode uncommited relocations. also, invalidate the icache + #[allow(unused)] fn encode_relocs(&mut self) -> Result<(), DynasmError> { let buf_addr = self.buffer.as_ptr() as usize; diff --git a/runtime/src/relocations.rs b/runtime/src/relocations.rs index fb6faef9c..0d569ccb8 100644 --- a/runtime/src/relocations.rs +++ b/runtime/src/relocations.rs @@ -2,7 +2,7 @@ use byteorder::{ByteOrder, LittleEndian}; -use std::convert::TryFrom; +use core::convert::TryFrom; /// Error returned when encoding a relocation failed #[derive(Debug)] diff --git a/runtime/src/x64.rs b/runtime/src/x64.rs index 9a0fd73a0..260a765ba 100644 --- a/runtime/src/x64.rs +++ b/runtime/src/x64.rs @@ -22,7 +22,7 @@ use crate::relocations::{Relocation, RelocationSize, RelocationKind, ImpossibleRelocation}; use crate::Register; -use std::hash::Hash; +use core::hash::Hash; /// Relocation implementation for the x64 architecture. @@ -61,6 +61,7 @@ impl Relocation for X64Relocation { } /// An x64 Assembler. This is aliased here for backwards compatability. +#[cfg(feature = "std")] pub type Assembler = crate::Assembler; /// An x64 AssemblyModifier. This is aliased here for backwards compatability. pub type AssemblyModifier<'a> = crate::Modifier<'a, X64Relocation>; diff --git a/runtime/src/x86.rs b/runtime/src/x86.rs index b20e0bae6..879b03380 100644 --- a/runtime/src/x86.rs +++ b/runtime/src/x86.rs @@ -63,6 +63,7 @@ impl Relocation for X86Relocation { /// An x86 Assembler. This is aliased here for backwards compatability. +#[cfg(feature = "std")] pub type Assembler = crate::Assembler; /// An x86 AssemblyModifier. This is aliased here for backwards compatability. pub type AssemblyModifier<'a> = crate::Modifier<'a, X86Relocation>; diff --git a/testing/Cargo.toml b/testing/Cargo.toml index 9dfd61da3..e2ca3d325 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -9,3 +9,4 @@ itertools = "0.13.0" [dependencies.dynasmrt] path = "../runtime" +features = ["std"]