Skip Menu |

This queue is for tickets about the Win32-API CPAN distribution.

Report information
The Basics
Id: 77677
Status: resolved
Priority: 0/
Queue: Win32-API

People
Owner: BULKDD [...] cpan.org
Requestors: bulk88 [...] hotmail.com
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.68
Fixed in: 0.70_01



Subject: x64 asm is broken for ::API, >4 param crash
If there are over 4 parameters on x64 with GCC, there is a crash. Remember every function on x64 has 4 parameters without exception. RSI and R10 is filled with garbage with the 2 POPs at the end. The stack pusher loop is broken. RSI in Call_asm is the retval struct pointer on -O2 (strawberry perl's default). On -O0 it doesn't crash, IDK and don't care why. Show quoted text
________________________ .globl Call_x64_real Call_x64_real: pushq %rbp movq %rsp,%rbp subq $32,%rsp # keep space for 4 64bit params ADD 32 to RSP A FIXED AMOUNT # Store register parameters movq %rcx,16(%rbp) # ApiFunction movq %rdx,24(%rbp) # int_registers movq %r8,32(%rbp) # float_registers movq %r9,40(%rbp) # stack # Save regs we are gonna use pushq %rsi ADD 8 to RSP A FIXED AMOUNT pushq %r10 ADD 8 to RSP A FIXED AMOUNT # Load up integer registers first... movq 24(%rbp),%rax # rax = int_registers movq (%rax),%rcx movq 8(%rax),%rdx movq 16(%rax),%r8 movq 24(%rax),%r9 # Now floating-point registers movq 32(%rbp),%rax # rax = float_registers movsd (%rax),%xmm0 movsd 8(%rax),%xmm1 movsd 16(%rax),%xmm2 movsd 24(%rax),%xmm3 # Now the stack movq 40(%rbp),%rsi # rsi = stack movq 48(%rbp),%rax # rax = nstack NSTACK IS NUMBER OF STACK PARAMS FROM Call_asm required_stack = nparams > 4 ? nparams - 4 : 0; NSTACK IS required_stack IN THE CALLER Call_asm END COMMENT # Except not if there isn't any testq %rax,%rax je docall copystack: subq $1,%rax movq (%rsi,%rax,8),%r10 pushq %r10 ADD MANY 8s TO RSP THIS IS A LOOP VARIABLE AMOUNT testq %rax,%rax jne copystack docall: # And call movq 16(%rbp),%r10 # r10 = ApiFunction subq $32,%rsp # Microsoft x64 calling convention - allocate 32 bytes of "shadow space" on the stack ADD 32 TO RSP, A FIXED AMOUNT callq *%r10 addq $32,%rsp # restore stack REMOVE 32 FROM RSP, A FIXED AMOUNT # Store return value movq 56(%rbp),%r10 # r10 = iret movq %rax,(%r10) movq 64(%rbp),%r10 # r10 = dret movsd %xmm0,(%r10) # Restore regs popq %r10 REMOVE 8 FROM RSP, A FIXED AMOUNT popq %rsi REMOVE 8 FROM RSP, A FIXED AMOUNT movq %rbp,%rsp popq %rbp retq
____________________________________________ This bug is in the public 0.68, and my personal API versions (0.69/0.70). Its only on x64 and on GCC Perl. I'll investigate whether the same bug is in MSVC x64 side.
From: bulk88(1) [...] hotmail.com
Show quoted text
____________________________________ void Call_asm(FARPROC ApiFunction, APIPARAM *params, int nparams, APIPARAM *retval, BOOL c_call) { struct _CONTEXT cxt; struct _CONTEXT cxt2; size_t nRegisters = 0, nStack = 0; size_t required_registers = 0, required_stack = 0;
_____________________________________ RtlCaptureContext(&cxt); Call_x64_real(ApiFunction, int_registers, float_registers, stack, required_stack, &iret, &dret); RtlCaptureContext(&cxt2); if(cxt.Rsi != cxt2.Rsi) {printf("bad RSI\n"); printf("%d \n", *(int*)0);}
_____________________________________ I got a "bad RSI" on Strawberry and VC Perl. Both are broken over 4 params.
From: bulk88(1) [...] hotmail.com
There are 2 separate problems here. MSVC doesn't save RSI, but it causes no ill effects since MSVC (atleast my 2008) will not use nonvolatile registers (and therefore use more stack memory) no matter what the -O flag or LTCG setting. Ask MS about that one. The GCC code saves RSI and restores it, and GCC uses RSI alot unlike MSVC, but if the stack prototype has more than 4 args, the copystack loop runs and "corrupts" RSP and then later when the POPs happen they POP garbage into RSI and R10 (why R10 is saved, its volatile, and not a fastcall register, IDK), RSP isn't the same when the PUSHes were done. Since MSVC code doesn't ever call POP and uses 100% RBP addressing, the RSP position is irrelevant but RSI is still not restored.