On 22 November 2017 at 13:38, Todd Blanchard tblanchard@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; }