[Vm-dev] Debugging Win64 Cog Spur

Eliot Miranda eliot.miranda at gmail.com
Mon May 29 18:00:04 UTC 2017


Hi Nicolas,

    these commits fix start up:

[Vm-dev] VM Maker: VMMaker.oscog-eem.2225.mcz
0364ee: CogVM source as per VMMaker.oscog-eem.2227

The main issue was that there was a code generation error for JumpR that
caused jmp %r8 to be generated as jmp %rax, which broke open PIC dispatch.
This didn't affect SysV because the reg assignments for ClassReg are
different.

So now we have a working Cogit for Win64.  I still need to run full tests,
but at least it starts up.  It would be good to check whether the change to
compileInterpreterPrimitive:flags: is actually needed.  It seems like the
right thing to do, but with the change to the C stack it might be
irrelevant.

On Sat, May 27, 2017 at 8:21 AM, Eliot Miranda <eliot.miranda at gmail.com>
wrote:

> Hi Nicolas,
>
>     as far as I can see in https://msdn.microsoft.com/
> en-us/library/ms235286.aspx we do not simulate the shadow space
> convention so any bugs will not show up in the simulator.  I will modify
> the simulator to smash the shadow space on the stack and see how far we
> get.  That should break things and hence make it possible to debug and fix
> the issue.  The convention is pretty simple:
>
> "The caller is responsible for allocating space for parameters to the
> callee, and must always allocate sufficient space to store four register
> parameters, even if the callee doesn’t take that many parameters. This
> simplifies support for unprototyped C-language functions, and vararg C/C++
> functions. For vararg or unprototyped functions, any floating point values
> must be duplicated in the corresponding general-purpose register. Any
> parameters beyond the first four must be stored on the stack, above the
> shadow store for the first four, prior to the call. Vararg function details
> can be found in Varargs. Unprototyped function information is detailed in
> Unprototyped Functions."
>
> There may be places where we simply call directly into the run-time and
> forget to make the shadow space available.
>
> On Fri, May 26, 2017 at 5:55 AM, Nicolas Cellier <
> nicolas.cellier.aka.nice at gmail.com> wrote:
>
>>
>>
>> 2017-05-26 9:24 GMT+02:00 Nicolas Cellier <nicolas.cellier.aka.nice at gmai
>> l.com>:
>>
>>>
>>>
>>> 2017-05-25 17:49 GMT+02:00 Eliot Miranda <eliot.miranda at gmail.com>:
>>>
>>>> Hi Nicolas,
>>>>
>>>> On Wed, May 24, 2017 at 11:28 PM, Nicolas Cellier <
>>>> nicolas.cellier.aka.nice at gmail.com> wrote:
>>>>
>>>>> Great, you reproduced exact same behavior.
>>>>> The problem I have is effectively where to put the breakpoint.
>>>>> I think we can believe the output of (gdb) call printCallStack()
>>>>>
>>>>
>>>> here's one issue; the computation to see if the frame pointer is in use
>>>> fails.  I'm executing this at the compilation break point for FilePath
>>>> class>pathName:isEncoded:
>>>>
>>>> (gdb) print /x CStackPointer
>>>> $7 = 0xef91d0
>>>> (gdb) print /x CFramePointer
>>>> $8 = 0x0
>>>> (gdb) print cFramePointerInUse
>>>> $9 = 0
>>>> (gdb) info registers
>>>> rax            0x68588f 6838415
>>>> rbx            0xffffffff       4294967295
>>>> rcx            0x68588f 6838415
>>>> rdx            0xabababab003a643a       -6076574521274768326
>>>> rsi            0xfde9   65001
>>>> rdi            0x0      0
>>>> rbp            0xef5db0 0xef5db0
>>>> rsp            0xef5c50 0xef5c50
>>>> r8             0x0      0
>>>> r9             0xfffffffffbefbc48       -68174776
>>>> r10            0xe36e626d44726839       -2058599758222432199
>>>> r11            0x8101010101010100       -9151031864016699136
>>>> r12            0xffffffff       4294967295
>>>> r13            0x20     32
>>>> r14            0x7ffc202018f0   140720847460592
>>>> r15            0xf2faf0 15923952
>>>> rip            0x4015d9 0x4015d9 <warning+9>
>>>> eflags         0x206    [ PF IF ]
>>>> cs             0x33     51
>>>> ss             0x2b     43
>>>> ds             0x2b     43
>>>> es             0x2b     43
>>>> fs             0x53     83
>>>> gs             0x2b     43
>>>> (gdb)
>>>>
>>>>
>>>
>>> So ceCaptureStackPointers() must get the value of SP and eventually FP
>>> in the caller.
>>> For getting caller SP, it must unstack the push RBX, and the return
>>> address.
>>>
>>> But on Win64 ABI it's not enough, because stack space is reserved for
>>> the 4 register arguments even if there is less than 4...
>>> So we must add 32 bytes more to callee SP in order to retrieve caller
>>> SP...
>>>
>>>
>> Hmmm wrong guess from my side.
>> Some calls do explicitely reserve the stack space for saving the 4
>> register parameters like:
>>
>>    0x518d06 <generateCaptureCStackPointers+150>:        sub    $0x20,%rsp
>>    0x518d0a <generateCaptureCStackPointers+154>:        callq  0x506220
>> <zeroOpcodeIndexForNewOpcodes>
>>    0x518d0f <generateCaptureCStackPointers+159>:        add    $0x20,%rsp
>>
>> but some do not:
>>
>>    0x4ed822 <generateStackPointerCapture+178>:  mov
>> 0x2071f7(%rip),%rdx        # 0x6f4a20 <methodZoneBase>
>>    0x4ed829 <generateStackPointerCapture+185>:  mov    %rdx,0x70(%rsp)
>>    0x4ed82e <generateStackPointerCapture+190>:  mov
>> 0x207203(%rip),%rdx        # 0x6f4a38 <trampolineTableIndex>
>>    0x4ed835 <generateStackPointerCapture+197>:  mov    %rdx,0x68(%rsp)
>>    0x4ed83a <generateStackPointerCapture+202>:  callq  0x518c70
>> <generateCaptureCStackPointers>
>>    0x4ed83f <generateStackPointerCapture+207>:  callq
>> *0x2b199b(%rip)        # 0x79f1e0 <ceCaptureCStackPointers>
>>    0x4ed845 <generateStackPointerCapture+213>:  callq  0x543650
>> <isCFramePointerInUse>
>>    0x4ed84a <generateStackPointerCapture+218>:  movslq %eax,%rcx
>>    0x4ed84d <generateStackPointerCapture+221>:  mov
>> %rcx,0x2b1844(%rip)        # 0x79f098 <cFramePointerInUse>
>>
>> If I put a breakpoint:
>> (gdb) break generateStackPointerCapture
>>
>> then I see that the frame pointer is not in use in this function:
>>
>> (gdb) print $rbp
>> $6 = (void *) 0x0
>>
>> then:
>>
>> (gdb) print $rsp
>> $7 = (void *) 0xf2f250
>>
>> if I step over ceCaptureCStackPointers()
>> => 0x4e00010:   push   %rbx
>>    0x4e00011:   mov    $0x6dc018,%rbx
>>    0x4e00018:   mov    %rbp,0xc3158(%rbx)
>>    0x4e0001f:   mov    %rsp,%rax
>>    0x4e00022:   add    $0x30,%rax
>>    0x4e00026:   mov    %rax,0xc3140(%rbx)
>>    0x4e0002d:   pop    %rbx
>>
>> i find:
>>
>> (gdb) print CFramePointer
>> $10 = (void *) 0x0
>> (gdb) print CStackPointer
>> $9 = (void *) 0xf2f270
>>
>> 0x20 too much...
>>
>> The other sender of ceCaptureCStackPointers does not use sub
>> $0x20,%rsp either
>>
>>    0x428310 <enterSmalltalkExecutiveImplementation+144>:        xor
>> %eax,%eax
>>    0x428312 <enterSmalltalkExecutiveImplementation+146>:        mov
>> %al,%dl
>>    0x428314 <enterSmalltalkExecutiveImplementation+148>:        mov
>> %dl,0x4d(%rsp)
>>    0x428318 <enterSmalltalkExecutiveImplementation+152>:        mov
>> 0x4d(%rsp),%al
>>    0x42831c <enterSmalltalkExecutiveImplementation+156>:        mov
>> %al,0x4c(%rsp)
>>    0x428320 <enterSmalltalkExecutiveImplementation+160>:        callq
>> *0x376eba(%rip)        # 0x79f1e0 <ceCaptureCStackPointers>
>>    0x428326 <enterSmalltalkExecutiveImplementation+166>:        lea
>> 0x376c33(%rip),%rcx        # 0x79ef60 <reenterInterpreter>
>>
>> So I will have to revert last VMMaker change...
>>
>>
>>>
>>>>
>>>>> I've tried other means:
>>>>> - analyze direct usage of registers RCX & co from VMMaker
>>>>>   if ever it could conflicts with WIN64 logical register assignment
>>>>>   But I did not find anything
>>>>> - compile with MSVC 2017
>>>>>   if ever the compiler could spit different warnings and give a clue
>>>>>   alas it fails very early in readImageFromFileHeapSizeStartingAt
>>>>> (during checkAssumedCompactClasses)
>>>>>  the failure is incomprehensible, because the debugger shows identical
>>>>> contents if I print:
>>>>>
>>>>>         *((sqInt *)(classTableFirstPage+8+(51<<3)))
>>>>> 140697255509608    __int64
>>>>>         *((sqInt *)(specialObjectsOop+8+(7<<3)))
>>>>> 140697255509608    __int64
>>>>>
>>>>> nonetheless, the debugger enters into the if and execute
>>>>>         invalidCompactClassError("Array");
>>>>>
>>>>> I'll have to debug it at assembler level, but it's driving me away
>>>>> from the original problem...
>>>>>
>>>>
>>>> Hmmm.  I doubt this is a problem because the assert and debug VMs would
>>>> print a warning if this were wrong and they seem to be doing fine (I'm
>>>> using the clang build).
>>>>
>>>>
>>>>>
>>>>>
>>> This is a MSVC code generation bug.
>>>
>>>
>>>>
>>>>
>>>>
>>>> --
>>>> _,,,^..^,,,_
>>>> best, Eliot
>>>>
>>>
>>>
>>
>
>
> --
> _,,,^..^,,,_
> best, Eliot
>



-- 
_,,,^..^,,,_
best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20170529/a51adae7/attachment-0001.html>


More information about the Vm-dev mailing list