On 22 November 2017 at 21:59, Ben Coman <btc@openinworld.com> wrote: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.cOn 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.outThat failedSo I'm not sure how to proceed.����I was expecting that would work while Pharo failed.Now interestingly...$ clang test.c microlang.c$ ./a.outThat workedSo it seems a similar problem exists outside our FFI.��cheers -benP.S. I refactored you code to extract a header file (attached)The issue is still beyond my ken, but I've made some progress towards isolating/understanding the issue.Attached zip exploded here for easy reference...___microlang.h___typedef unsigned�� uintptr_t;typedef struct {�� const void *ptr_data[2];} CXSourceRange_;CXSourceRange_ clang_getArbitraryRange_();int clang_getRangeEnd_(CXSourceRange_ range); ___microclang.c___#include "microclang.h"const char* libraryString = "library_pointer";CXSourceRange_ clang_getArbitraryRange_(){�� �� �� ��CXSourceRange_ range = {0};�� �� �� �� range.ptr_data[0] = (void*)libraryString;�� �� �� �� return range;}int clang_getRangeEnd_(CXSourceRange_ range) {�� �� �� ��// Special decoding for CXSourceLocations for CXLoadedDiagnostics.�� �� �� �� if ((uintptr_t)range.ptr_data[0] & 0x1)�� �� �� �� {�� �� �� ��return 0;�� �� �� ��}�� �� �� �� else�� �� �� �� {�� �� �� ��return 1;�� �� �� ��}}___test.c___#include <stdio.h>#include "microclang.h"const char* localString =�� "local_pointer";void test( CXSourceRange_ range, char *note ){�� �� �� ��int result = clang_getRangeEnd_(range);�� �� �� �� if(result == 0)�� �� �� �� {�� �� �� ��printf("That failed (%s)\n", note); }�� �� �� �� else�� �� �� �� {�� �� �� ��printf("That worked (%s)\n", note); }}int main(){�� �� �� ��CXSourceRange_ range1 = clang_getArbitraryRange_();�� �� �� �� test(range1, "library string");�� �� �� �� CXSourceRange_ range2 = {0};�� �� �� �� range2.ptr_data[0] = (void*)localString;�� �� �� �� test(range2, "local string");}___Makefile___default: clean static sharedclean:�� �� �� �� rm -f *so *App�� �� �� �� @echoshared:�� �� �� �� clang -g -o libmicroclang.so -shared -fPIC microclang.c�� �� �� �� clang -g -o sharedApp test.c -L. -lmicroclang�� �� �� �� LD_LIBRARY_PATH=. ./sharedApp�� �� �� �� @echostatic:�� �� �� �� clang -g -o staticApp test.c microclang.c�� �� �� �� ./staticApp�� �� �� �� @echoNow running...$ make > reportgives...___report___rm -f *so *Appclang -g -o staticApp test.c microclang.c./staticAppThat worked (library string)That worked (local string)clang -g -o libmicroclang.so -shared -fPIC microclang.cclang -g -o sharedApp test.c -L. -lmicroclangLD_LIBRARY_PATH=. ./sharedAppThat failed (library string)That worked (local string)