Wed Jun 06 19:35:56 2012: Request 77677 was acted upon.
Transaction: Ticket created by bulk88.
       Queue: Win32-API
     Subject: x64 asm is broken for ::API, >4 param crash
   Broken in: 0.68
    Severity: Normal
       Owner: Nobody
  Requestors: bul...@hotmail.com
      Status: new
 Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=77677 >


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.
________________________

.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.

Reply via email to