I got pulled off to do some $ work and haven't got back to this but I would 
like to get back to it.

Has there been any progress on this in the publicly available 64bit VM?

I see there is a completely separate FFI plugin for 32 vs 64 and worry 64 is 
still not quite ready for real work.

> On Dec 3, 2017, at 7:18 AM, Ben Coman <b...@openinworld.com> wrote:
> 
> 
> 
> On 27 November 2017 at 00:24, Todd Blanchard <tblanch...@mac.com 
> <mailto:tblanch...@mac.com>> wrote:
>  
> i'm getting the idea that we should probably write a test suite/library for 
> FFI
> 
> I noticed these...
> * 
> https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/Cog/platforms/unix/plugins/SqueakFFIPrims/ffi-test-main.c
>  
> <https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/Cog/platforms/unix/plugins/SqueakFFIPrims/ffi-test-main.c>
> * 
> https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/Cog/platforms/Cross/plugins/SqueakFFIPrims/sqFFITestFuncs.c
>  
> <https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/Cog/platforms/Cross/plugins/SqueakFFIPrims/sqFFITestFuncs.c>
> * 
> https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/Cog/platforms/Cross/plugins/IA32ABI/AlienSUnitTestProcedures.c
>  
> <https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/Cog/platforms/Cross/plugins/IA32ABI/AlienSUnitTestProcedures.c>
> 
> These look like c-code test frames for FFI.  Could these be built by the 
> OpenSmalltalk CI to be normally shipped with the VM so that Image-side CI can 
> test against them?
> 
> And also some general info...
> * 
> https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/Cog/platforms/unix/plugins/SqueakFFIPrims/00README
>  
> <https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/Cog/platforms/unix/plugins/SqueakFFIPrims/00README>
> 
>  
> 
>> On Nov 24, 2017, at 12:54 AM, Ben Coman <b...@openinworld.com 
>> <mailto:b...@openinworld.com>> wrote:
>> 
>> 
>> On 24 November 2017 at 13:16, Ben Coman <b...@openinworld.com 
>> <mailto:b...@openinworld.com>> wrote:
>> 
>> 
>> On 22 November 2017 at 21:59, Ben Coman <b...@openinworld.com 
>> <mailto:b...@openinworld.com>> wrote:
>> 
>> 
>> On 22 November 2017 at 13:38, Todd Blanchard <tblanch...@mac.com 
>> <mailto:tblanch...@mac.com>> wrote:
>>  
>> I've been trying to track this down for a couple weeks now.
> 
>> 
>> I have concluded that structs passed by value to functions on the 64 bit VM 
>> are not properly populated.  The struct's memory is all zero'd.
>> 
>> I found this while trying to work with LibClang and found that functions 
>> that fetched code locations from code ranges always returned invalid zero'd 
>> locations.  After spending some time with lldb I have traced the problem 
>> into the native code and found that the argument is not correct.
>> 
>> I've carved out the wee bit of clang to reproduce this in a tiny library.
>> 
>> The gist of it is below and the entire file is included.  Basically the 
>> struct passed to the function clang_getRangeStart is zero'd memory 
>> regardless of the data I send from the image side.
> 
> 
> My last analysis discovered something interesting about strings defined 
> inside shared libraries being handled differently, but only later realised I 
> had chased the wrong rabbit down the hole.  
>  
> I've now investigated the premise you actually poses, and I agree, that 
> structs being zero is some cases.  
> The attached zipfile containing  libstruct.c  a few comparison cases - three 
> "good" layouts that work fine and one "bad" that mostly gets zeros but 
> sometimes other weird numbers.  There is a Makefile with three main targets:
> 1. make layout - statically compiles  libstruct.c  and runs produced  a.out  
> to display structure layouts 
> 
> 2. make run - downloads Pharo, starts it loading  LibStruct.st 
> <http://libstruct.st/>  , then you manually run 
> LibStruct>>>LibStructTest>>#testStructs and observe structure values on 
> console
> 
> 3. make debug - starts LLDB to run Pharo with breakpoints pre-configured for 
> when you run #testStructs.  
>    Note Pharo will freeze and you need to move to LLDB.  Try these 
> commands... 
>       frame variable
>       call print_struct(&GoodStruct1_fmt, &aStruct)
>       continue
> 
> That works on Ubuntu 16.04 64 bit. 
> You will need to tune it for OSX.
> clang and lldb are required.
> 
> ================================
> The offsets configured in the class variables of all ExternalStructs 
> correctly matches that reported by the C code test frame results here...
> 
> $ make layout        
> clang -g libstruct.c
> ./a.out
> 
> GoodStruct1:
>       uint32_t:int1:          01 4 
>       uint32_t:int2:          05 4 
> GoodStruct2:
>       uint32_t:int1:          01 4 
>       uint32_t:int2:          05 4 
>       void*:ptr_data:         09 8 
> GoodStruct3:
>       void*:ptr_data:         01 8 
>       uint32_t:int1:          09 4 
>       uint32_t:int2:          13 4 
> BadStruct:
>       void*:ptr_data1:        01 8 
>       void*:ptr_data2:        09 8 
>       uint32_t:int1:          17 4 
>       uint32_t:int2:          21 4 
> 
> ================================
> 
> $ make run   
> clang -g -o libstruct.so -shared -fPIC libstruct.c
> getpharo/pharo-vm/lib/pharo/5.0-201707201942/pharo getpharo/Pharo.image 
> ../LibStruct.st <http://libstruct.st/>
> 
> Now manually browse to and run  LibStruct>>>LibStructTest>>#testStructs
> LibStructTest>>testStructs
>       |good1Struct good2Struct good3Struct badStruct |
>       
>       good1Struct    := GoodStruct1    new int1: 2; int2: 3.
>       good2Struct    := GoodStruct2    new int1: 2; int2: 3; ptr_force_int: 4.
>       good3Struct    := GoodStruct3    new int1: 2; int2: 3; ptr_force_int: 4.
>       badStruct      := BadStruct      new int1: 2; int2: 3; ptr_force_int1: 
> 4; ptr_force_int1: 5.
>       
>       self assert: (LibStruct tryGood1: good1Struct)       equals: 6. 
>       self assert: (LibStruct tryGood2: good2Struct)       equals: 6.
>       self assert: (LibStruct tryGood3: good3Struct)       equals: 6.
>       "Problem exposed in next line"
>       self assert: (LibStruct tryBad: badStruct)           equals: 6.
> 
> which on console produces...
> 
> GoodStruct1:
>       uint32_t:int1:          01 4 = 02 00 00 00
>       uint32_t:int2:          05 4 = 03 00 00 00
> GoodStruct2:
>       uint32_t:int1:          01 4 = 02 00 00 00
>       uint32_t:int2:          05 4 = 03 00 00 00
>       void*:ptr_data:         09 8 = 04 00 00 00 00 00 00 00
> GoodStruct3:
>       void*:ptr_data:         01 8 = 04 00 00 00 00 00 00 00
>       uint32_t:int1:          09 4 = 02 00 00 00
>       uint32_t:int2:          13 4 = 03 00 00 00
> BadStruct:
>       void*:ptr_data1:        01 8 = 00 00 00 00 00 00 00 00
>       void*:ptr_data2:        09 8 = 00 00 00 00 00 00 00 00
>       uint32_t:int1:          17 4 = 29 03 03 00
>       uint32_t:int2:          21 4 = 00 00 00 00
> 
> Comparing GoodStruct3 and BadStruct, it seems one pointer is handled fine, 
> but not two.
> The first time this is run after Image boots seems like BadStruct gets some 
> random data.
> 
> ================================
> In same image, subsequent runs of  LibStruct>>>LibStructTest>>testStructs     
> give only all zeros for BadStruct, as Todd observed.
> 
> GoodStruct1:
>       uint32_t:int1:          01 4 = 02 00 00 00
>       uint32_t:int2:          05 4 = 03 00 00 00
> GoodStruct2:
>       uint32_t:int1:          01 4 = 02 00 00 00
>       uint32_t:int2:          05 4 = 03 00 00 00
>       void*:ptr_data:         09 8 = 00 00 00 00 00 00 00 00
> GoodStruct3:
>       void*:ptr_data:         01 8 = 00 00 00 00 00 00 00 00
>       uint32_t:int1:          09 4 = 02 00 00 00
>       uint32_t:int2:          13 4 = 03 00 00 00
> BadStruct:
>       void*:ptr_data1:        01 8 = 00 00 00 00 00 00 00 00
>       void*:ptr_data2:        09 8 = 00 00 00 00 00 00 00 00
>       uint32_t:int1:          17 4 = 00 00 00 00
>       uint32_t:int2:          21 4 = 00 00 00 00
> 
> 
> cheers -ben
> 
> <FFI64StructTest.zip>

Reply via email to