Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 75 additions & 31 deletions proxygen-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ impl From<syn::Meta> for ProxySignatureType {
// Note: You may not have any instructions in the function body when forwarding function calls
#[proc_macro_attribute]
pub fn forward(_attr_input: TokenStream, item: TokenStream) -> TokenStream {
unsafe{
let input: ItemFn = syn::parse(item).expect("You may only proxy a function");
let func_name = input.sig.clone().ident;
let func_body = input.block.stmts.clone();
Expand Down Expand Up @@ -112,7 +113,7 @@ pub fn forward(_attr_input: TokenStream, item: TokenStream) -> TokenStream {
pub unsafe extern "C" fn #func_name() {
#[cfg(target_arch = "x86_64")]
{
std::arch::asm!(
std::arch::naked_asm!(
"call {wait_dll_proxy_init}",
"mov rax, qword ptr [rip + {ORIG_FUNCS_PTR}]",
"add rax, {orig_index} * 8",
Expand All @@ -122,13 +123,12 @@ pub fn forward(_attr_input: TokenStream, item: TokenStream) -> TokenStream {
wait_dll_proxy_init = sym crate::wait_dll_proxy_init,
ORIG_FUNCS_PTR = sym crate::ORIG_FUNCS_PTR,
orig_index = const #orig_index_ident,
options(noreturn)
)
}

#[cfg(target_arch = "x86")]
{
std::arch::asm!(
std::arch::naked_asm!(
"call {wait_dll_proxy_init}",
"mov eax, dword ptr [{ORIG_FUNCS_PTR}]",
"add eax, {orig_index} * 4",
Expand All @@ -138,11 +138,11 @@ pub fn forward(_attr_input: TokenStream, item: TokenStream) -> TokenStream {
wait_dll_proxy_init = sym crate::wait_dll_proxy_init,
ORIG_FUNCS_PTR = sym crate::ORIG_FUNCS_PTR,
orig_index = const #orig_index_ident,
options(noreturn)
)
}
}
))
}
}

// Proc macro to bring the original function into the scope of an interceptor function as `orig_func`
Expand Down Expand Up @@ -241,8 +241,6 @@ pub fn pre_hook(attr_input: TokenStream, item: TokenStream) -> TokenStream {
let hook_func_name =
syn::parse_str::<syn::Ident>(&format!("Proxygen_PreHook_{}", &func_name)).unwrap();
TokenStream::from(quote!(
#[cfg(not(target_arch = "x86_64"))]
compile_error!("Pre-hooks aren't yet implemented for non x86-64");

#[no_mangle]
// TODO: Use the same safety/unsafety modifier as the original here
Expand All @@ -254,47 +252,93 @@ pub fn pre_hook(attr_input: TokenStream, item: TokenStream) -> TokenStream {
#[naked]
#(#attrs)*
pub unsafe extern "C" fn #func_name() {
std::arch::asm!(
// Wait for dll proxy to initialize
"call {wait_dll_proxy_init}",
"mov rax, qword ptr [rip + {ORIG_FUNCS_PTR}]",
"add rax, {orig_index} * 8",
"mov rax, qword ptr [rax]",
#[cfg(target_arch = "x86")]
{
std::arch::naked_asm!(
"call {wait_dll_proxy_init}",
"mov eax, dword ptr [{ORIG_FUNCS_PTR}]",
"add eax, {orig_index} * 4", // 4 bytes per pointer in 32-bit
"mov eax, dword ptr [eax]",

// Push the original function onto the stack
"push rax",
"push eax",

// Save the general purpose registers
"push rdi; push rsi; push rcx; push rdx; push r8; push r9",
// Note: i686 doesn't have r8, r9, etc.
"push edi; push esi; push ecx; push edx; push ebx",

// Save the 128-bit floating point registers
"sub rsp, 64",
"movaps [rsp], xmm0",
"movaps [rsp + 16], xmm1",
"movaps [rsp + 32], xmm2",
"movaps [rsp + 48], xmm3",
// Note: XMM registers are available in i686 with SSE support
"sub esp, 64",
"movaps [esp], xmm0",
"movaps [esp + 16], xmm1",
"movaps [esp + 32], xmm2",
"movaps [esp + 48], xmm3",

// Call our hook code here
"call {proxygen_pre_hook_func}",

// Restore the 128-bit floating point registers
"movaps xmm3, [rsp + 48]",
"movaps xmm2, [rsp + 32]",
"movaps xmm1, [rsp + 16]",
"movaps xmm0, [rsp]",
"add rsp, 64",
"movaps xmm3, [esp + 48]",
"movaps xmm2, [esp + 32]",
"movaps xmm1, [esp + 16]",
"movaps xmm0, [esp]",
"add esp, 64",

// Restore the general purpose registers
"pop r9; pop r8; pop rdx; pop rcx; pop rsi; pop rdi",
"pop ebx; pop edx; pop ecx; pop esi; pop edi",

// Return to the original function
"ret",
wait_dll_proxy_init = sym crate::wait_dll_proxy_init,
ORIG_FUNCS_PTR = sym crate::ORIG_FUNCS_PTR,
orig_index = const #orig_index_ident,
proxygen_pre_hook_func = sym #hook_func_name,
options(noreturn)
);
wait_dll_proxy_init = sym crate::wait_dll_proxy_init,
ORIG_FUNCS_PTR = sym crate::ORIG_FUNCS_PTR,
orig_index = const #orig_index_ident,
proxygen_pre_hook_func = sym #hook_func_name,
);
}
#[cfg(target_arch = "x86_64")]
{
std::arch::naked_asm!(
// Wait for dll proxy to initialize
"call {wait_dll_proxy_init}",
"mov rax, qword ptr [rip + {ORIG_FUNCS_PTR}]",
"add rax, {orig_index} * 8",
"mov rax, qword ptr [rax]",

// Push the original function onto the stack
"push rax",

// Save the general purpose registers
"push rdi; push rsi; push rcx; push rdx; push r8; push r9",

// Save the 128-bit floating point registers
"sub rsp, 64",
"movaps [rsp], xmm0",
"movaps [rsp + 16], xmm1",
"movaps [rsp + 32], xmm2",
"movaps [rsp + 48], xmm3",

// Call our hook code here
"call {proxygen_pre_hook_func}",

// Restore the 128-bit floating point registers
"movaps xmm3, [rsp + 48]",
"movaps xmm2, [rsp + 32]",
"movaps xmm1, [rsp + 16]",
"movaps xmm0, [rsp]",
"add rsp, 64",

// Restore the general purpose registers
"pop r9; pop r8; pop rdx; pop rcx; pop rsi; pop rdi",

// Return to the original function
"ret",
wait_dll_proxy_init = sym crate::wait_dll_proxy_init,
ORIG_FUNCS_PTR = sym crate::ORIG_FUNCS_PTR,
orig_index = const #orig_index_ident,
proxygen_pre_hook_func = sym #hook_func_name,
);
}
}
))
}
Expand Down