[Vm-dev] FFI Struct Argument Pass By Value Fails on Mac 64 bit

Ben Coman btc at openinworld.com
Wed Nov 22 13:59:41 UTC 2017


On 22 November 2017 at 13:38, Todd Blanchard <tblanchard at 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.
>
> The build command I used on sierra is clang -shared -undefined
> dynamic_lookup -o microclang.dylib microclang.c
>

On Ubuntu 16.04 I used...
$ clang -shared -fPIC -o libmicroclang.so microclang.c

$ clang test.c -L. -l microclang
   test.c:6:53: error: no member named 'begin_int_data' in
'CXSourceLocation'
   if(clang_getRangeStart(clang_getArbitraryRange()).begin_int_data == 0)

I presume you meant...
    if(clang_getRangeStart(clang_getArbitraryRange()).int_data == 0)
so correcting and continuing...

$ clang test.c -L. -l microclang
$ LD_LIBRARY_PATH=. ./a.out
That failed

So I'm not sure how to proceed.
I was expecting that would work while Pharo failed.

Now interestingly...
$ clang test.c microlang.c
$ ./a.out
That worked


So it seems a similar problem exists outside our FFI.

cheers -ben

P.S. I refactored you code to extract a header file (attached)



> I'm stuck.  The FFI64 plugin is way beyond my comprehension.
>
> // microclang.c
>
> typedef struct {
>   const void *ptr_data[2];
>   unsigned int_data;
> } CXSourceLocation;
>
> /**
>  * \brief Identifies a half-open character range in the source code.
>  *
>  * Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
>  * starting and end locations from a source range, respectively.
>  */
> typedef struct {
>   const void *ptr_data[2];
>   unsigned begin_int_data;
>   unsigned end_int_data;
> } CXSourceRange;
>
> const char* first = "first_pointer";
> const char* second = "second_pointer";
>
> // return a fake range with non zero data
> CXSourceRange clang_getArbitraryRange()
> {
>   CXSourceRange range = {0};
>   range.ptr_data[0] = (void*)first;
>   range.ptr_data[1] = (void*)second;
>   range.begin_int_data = 17;
>   range.end_int_data = 24;
>   return range;
> }
>
> // Actual clang function - range is always zero'd here despite having
> values in the image
> CXSourceLocation clang_getRangeStart(CXSourceRange range) {
>   // Special decoding for CXSourceLocations for CXLoadedDiagnostics.
>   if ((uintptr_t)range.ptr_data[0] & 0x1) {
>     CXSourceLocation Result = { { range.ptr_data[0], nullptr }, 0 };
>     return Result;
>   }
>
>
>   CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
>     range.begin_int_data };
>   return Result;
> }
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20171122/e65a4bef/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: clang_ffi_struct_test.zip
Type: application/zip
Size: 1684 bytes
Desc: not available
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20171122/e65a4bef/attachment.zip>


More information about the Vm-dev mailing list