C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Interceptor Function (preserve stack and all registers)

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Tue, 30 Jul 2024 16:19:11 +0100
On Tue, Jul 30, 2024 at 11:45 AM Frederick Virchanza Gotham wrote:
>
> Here's the GodBolt for a recursive interceptor function running on
> MS-Windows x86_32 with the VC++ compiler, preserving every single
> register except for EAX:
>
> https://godbolt.org/z/z1cdMovjv


The latest version of the Microsoft compiler doesn't allow inline
assembler inside a C++ source file when compiling for a 64-Bit target,
so I couldn't implement the 64-Bit version on GodBolt.

The above GodBolt code can be ported from x86_32 to x86_64 by
replacing the assembler with the following:

EnumResourceTypesA:
        pushfq
        mov rax, [rsp+8] ; save original return address
        push rbx
        push rcx
        push rdi
        push rdx
        push rsi
        push rbp
        push r8
        push r9
        push r10
        push r11
        push r12
        push r13
        push r14
        push r15
        sub rsp, 512 ; allocate space for the floating points
        fxsave [rsp] ; save the floating points

        mov rcx, rax ; set 1st arg = original return address
        call Inwards

        fxrstor [rsp] ; restore the floating points
        add rsp, 512 ; deallocate space for the floating points
        pop r15
        pop r14
        pop r13
        pop r12
        pop r11
        pop r10
        pop r9
        pop r8
        pop rbp
        pop rsi
        pop rdx
        pop rdi
        pop rcx
        pop rbx
        popfq

        push r10 ; Put r10's value on the stack...
        add rsp, 8 ; ...still there but hidden

        add rsp, 8 ; Remove return address from stack
        lea r10, [come_back_here] ; Prepare the new return address
        push r10 ; Set new return address on stack

        sub rsp, 8 ; Navigate to the hidden r10 value
        pop r10 ; Retrieve hidden r10 value and
restore stack
        jmp rax ; Jump to original function

    come_back_here:
        pushfq
        push rax ; Must preserve return value
        push rbx
        push rcx
        push rdi
        push rdx
        push rsi
        push rbp
        push r8
        push r9
        push r10
        push r11
        push r12
        push r13
        push r14
        push r15
        sub rsp, 512
        fxsave [rsp]

        call Outwards

        push rax ; Put the original return address on the stack...
        add rsp, 8 ; ...but hide it there without overwriting it

        fxrstor [rsp]
        add rsp, 512
        pop r15
        pop r14
        pop r13
        pop r12
        pop r11
        pop r10
        pop r9
        pop r8
        pop rbp
        pop rsi
        pop rdx
        pop rdi
        pop rcx
        pop rbx
        pop rax ; Restore return value
        popfq

        jmp qword ptr[rsp - (512 + 17*8)] ; Jump back to caller

Received on 2024-07-30 15:19:26