Skip to main content

crystal_sdk/
lib.rs

1#![no_std]
2//#![allow(internal_features)]
3//#![feature(core_intrinsics)]
4
5pub mod mem;
6pub use paste::paste;
7
8/*
9    Macro for importing functions using crystal palace conventions
10*/
11#[macro_export]
12macro_rules! import {
13    // MODULE$Func form
14    ($vis:vis $lib:ident!$func:ident ($($arg:ident :$arg_ty:ty ),* $(,)?) -> $ret:ty) => {
15        $crate::import!(
16            @impl $vis,
17            $func,
18            concat!("\x01__imp_", stringify!($lib), "$", stringify!($func)),
19            ( $( $arg : $arg_ty ),* ),
20            $ret
21        );
22    };
23
24    // Bare form
25    ($vis:vis $func:ident ($($arg:ident :$arg_ty:ty ),* $(,)?) -> $ret:ty) => {
26        $crate::import!(
27            @impl $vis,
28            $func,
29            concat!("\x01__imp_", stringify!($func)),
30            ( $( $arg : $arg_ty ),* ),
31            $ret
32        );
33    };
34
35    // Internal implementation
36    (@impl $vis:vis, $func:ident, $link_name:expr, ( $( $arg:ident : $arg_ty:ty ),* ), $ret:ty) => {
37        $crate::paste! {
38            // import slot symbol
39            unsafe extern {
40                #[link_name = $link_name]
41                static [<__ $func>]: u8;     // the type doesnt matter its just to have the symbol referenced
42            }
43            
44            // function definition for structs and pointers
45            #[allow(non_snake_case, non_upper_case_globals, non_camel_case_types)]
46            #[cfg(target_arch = "x86_64")] 
47            $vis type [<$func Fn>] = unsafe extern "C" fn( $( $arg_ty ),* ) -> $ret;
48
49            #[inline(always)]
50            #[allow(non_snake_case, non_upper_case_globals, non_camel_case_types)]
51            unsafe fn [<$func _ptr>]() -> [<$func Fn>] {
52                let f: [<$func Fn>];
53                core::arch::asm!(
54                    "mov rax, [rip + {slot}]",
55                    slot = sym [<__ $func>],
56                    lateout("rax") f,
57                    options(nostack, preserves_flags),
58                );
59                f
60            }
61
62            // call function with compiler generated ABI stuff
63            #[inline(always)]
64            #[allow(non_snake_case, non_upper_case_globals, non_camel_case_types)]
65            $vis unsafe fn $func( $( $arg : $arg_ty ),* ) -> $ret {
66                unsafe {
67                    let f = [<$func _ptr>]();
68                    f( $( $arg ),* )
69                }
70            }
71        }
72    };
73}
74
75#[macro_export]
76macro_rules! append_data {
77    // default section name based on symbol name since we are linking data to the symbol name anyway (rust)
78    ($sym:ident, $fn_name:ident) => {
79        $crate::append_data!(
80            $sym,
81            $fn_name,
82            concat!(".rdata$", stringify!($sym))
83        );
84    };
85
86    ($sym:ident, $fn_name:ident, $section:expr) => {
87        // define symbol
88        #[unsafe(no_mangle)]
89        #[unsafe(link_section = $section)]
90        static $sym: [u8; 0] = [];
91    
92        #[allow(non_snake_case, non_upper_case_globals, non_camel_case_types)]
93        unsafe fn $fn_name() -> *const u8 {
94            let ptr: *const u8;
95            core::arch::asm!(
96                "lea {out}, [rip + {sym}]",
97                sym = sym $sym,
98                out = lateout(reg) ptr,
99                options(readonly, nostack, preserves_flags),
100            );
101            ptr
102        }
103    };
104}
105
106#[macro_export]
107macro_rules! patch {
108    ($type:ty, $name:ident) => {
109
110    };
111}
112
113/* Struct and helper function for retrieving appended resource using crystal palace convention */
114#[repr(C)]
115struct _RESOURCE {
116    length: core::ffi::c_int,
117    value: [u8; 0],
118}
119
120pub unsafe fn get_resource<'a>(ptr: *const u8) -> &'a [u8] {
121    unsafe {
122        let header = &*(ptr as *const _RESOURCE);
123        core::slice::from_raw_parts(header.value.as_ptr(), header.length as _)
124    }
125}
126
127/* for debugging */
128#[inline(always)]
129pub fn brk() { unsafe { core::arch::asm!("int3"); } }