[Vm-dev] [OpenSmalltalk/opensmalltalk-vm] passing struct by value does not respect x86_64 SysV ABI (#443)

Todd Blanchard tblanchard at mac.com
Fri Nov 8 16:41:12 UTC 2019


I think I ran into this trying to build FFI to libclang.

It passes a lot of structs by value and some calls came back with nothing.  

My message to vm-dev at lists.squeakfoundation.org on Nov 21, 2017 follows;

Apologies if this isn't relevant.  

> 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
> 
> 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;
> }
> 
> 




> On Nov 6, 2019, at 12:57 PM, Nicolas Cellier <notifications at github.com> wrote:
> 
> For passing parameters by value, my understanding is that we can pass up to 8 eigthbytes individually for each struct (either via register if struct fits on two eightbytes, and if we still have available registers, or via stack...). Only for more than 8 eightbytes, we will pass by MEMORY (a pointer to struct).
> 
> Here is a little example:
> 
> double adi(sdi x) { return (double) x.a + (double) x.b ; }
> double adi_2(sdi x,sdi y) { return adi(x) + adi(y); }
> double adi_4(sdi x,sdi y,sdi z,sdi t) { return adi_2(x,y) + adi_2(z,t); }
> 
> double aslf(sslf x) { return (double) x.a + (double) x.b + (double) x.c ; }
> double aslf_2(sslf x,sslf y) { return aslf(x) + aslf(y); }
> double aslf_4(sslf x,sslf y,sslf z,sslf t) { return aslf_2(x,y) + aslf_2(z,t); }
> double-int are passed by registers (by value) because fitting on 2 eightbytes
> short-long-float are passed via stack (by value) because requiring 3 eightbytes
> We should try longer (> 8 eightbytes) and verify that they are passed by pointer...
> 
>> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub <https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/443?email_source=notifications&email_token=AIJPEW3KXWHZHIYSFPN56DDQSMVU3A5CNFSM4JJ3EAU2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEDH6XYY#issuecomment-550497251>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AIJPEW6526SF2E4V5NDITSTQSMVU3ANCNFSM4JJ3EAUQ>.
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20191108/fae15d19/attachment-0003.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: LibCClang-FFI-Binding.st
Type: application/octet-stream
Size: 5652 bytes
Desc: not available
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20191108/fae15d19/attachment-0002.obj>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20191108/fae15d19/attachment-0004.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: microclang.c
Type: application/octet-stream
Size: 1760 bytes
Desc: not available
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20191108/fae15d19/attachment-0003.obj>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20191108/fae15d19/attachment-0005.html>


More information about the Vm-dev mailing list