Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Studio 2013 /GH /Gh _penter/_pexit 64bit how to save registers?

I'm using the following compiler options in VS2013:

/Gh (Enable _penter Hook Function)

http://msdn.microsoft.com/en-us/library/c63a9b7h.aspx

/GH (Enable _pexit Hook Function) http://msdn.microsoft.com/en-us/library/xc11y76y.aspx

As I'm trying to implement some basic profiling for my code. However with the 64-bit compiler its not possible to use the naked attribute:

http://msdn.microsoft.com/en-us/library/h5w10wxs.aspx

I don't think this is really a problem, however what is a problem is that I can't find a way to save the registers as inline assembly is not supported in this compiler. So if change any registers then their value is trashed. For example:

; int __cdecl DllMain(void *hModule, unsigned int ulReason, _CONTEXT *pContext)
push    rbx
sub     rsp, 20h
call    _penter

Here we must make sure that _penter will not trash the value of rsp:

; int __cdecl penter(LARGE_INTEGER PerformanceCount)
PerformanceCount= LARGE_INTEGER ptr  8

sub     rsp, 28h
xor     eax, eax
lea     rcx, [rsp+28h+PerformanceCount] ; lpPerformanceCount
mov     qword ptr [rsp+28h+PerformanceCount], rax
call    cs:__imp_QueryPerformanceCounter
add     rsp, 28h
retn
_penter endp

In this case its ok as _penter is fixing up rsp - however the values of eax and rcx are being overwritten. In x86 compiler I can simply add inline asm to push and pop these registers. How can I do this in the x64 compiler?

like image 778
paulm Avatar asked Jan 30 '26 03:01

paulm


1 Answers

This is in fact an issue with MSVC x64 that doesn't respect non-naked (absent in x64) declaration of _penter/_pexit functions.

Below goes an example of how I worked around this issue (not only you have to save volatile registers contents of which are considered to be destroyed by the call, but the flags register as well, as _penter/_pexit may get inserted in-between assembly commands having dependency on flags; this can only be done in a separate assembly file since MSVC does not provide inline assembly in x64):

PUSHREGS    macro
    push    rax
    lahf
    push    rax
    push    rcx
    push    rdx
    push    r8
    push    r9
    push    r10
    push    r11
endm

POPREGS macro
    pop r11
    pop r10
    pop r9
    pop r8
    pop rdx
    pop rcx
    pop rax
    sahf
    pop rax
endm

...

profile_enter   proc
    PUSHREGS
    ; > your code goes here. Be aware that it must preserve any non-volatile registers used and align the stack pointer for any calls made.
    POPREGS
    ret
profile_enter   endp

You can also take a look at the working code here: https://github.com/tyoma/micro-profiler/blob/master/micro-profiler/collector/hooks.asm

like image 96
Arty Avatar answered Feb 02 '26 09:02

Arty



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!