-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compiling and running jffi for powerpc64-AIX gives illegal instructions errors #53
Comments
Doing some good old printf debugging, I'm seeing some interesting behavior. I've changed Library.c so that dlsym will also immediately invoke the function like so: addr = dl_sym(j2p(handle), sym);
printf("dlsym addr: %p\n", addr);
printf("dlsym test: %s\n", (((const char *(*)(void))addr)())); And as a test to see if the issue was happening in libffi, I changed the invoke in Invoke.c to also manually invoke in the same way: puts("manual call test");
printf("long: %p\n", function);
printf("ptr: %p\n", j2p(function));
printf("test: %s\n", (((const char *(*)(void))j2p(function))()));
FAULTPROT_CTX(env, ctx, ffi_call(&ctx->cif, FFI_FN(j2p(function)), retval, ffiArgs), ); The run looks like this:
The address is the same and doesn't get invalidated, but it only works in the first location. My knowledge on the specifics of how AIX handles its dynamic loading and memory mapping are limited, but perhaps the opened library is becoming invalidated before the invocation, or maybe the address is only valid from particular memory pages, just as a guess in the dark. There are some notes about dlopen's behavior with "inter-module references" and "intra-module references" when the runtime linker is or isn't invoked, so that might be related. This might just need the -brtl linker option. I'll run some more tests around the rtl option and see if that might be a necessary prerequisite. |
I found out what's happening, but I'm not completely sure why. I added output to the dlclose: JNIEXPORT void JNICALL
Java_com_kenai_jffi_Foreign_dlclose(JNIEnv* env, jclass cls, jlong handle)
{
puts("closing module");
dl_close(j2p(handle));
} This is the relevant Java code, just as a reminder: System.out.println("make function");
Function func = new Function(func_address, Type.POINTER);
System.out.println("make buffer");
HeapInvocationBuffer buf = new HeapInvocationBuffer(func);
System.out.println("get memory instance");
MemoryIO mem = MemoryIO.getInstance();
System.out.println("put pointers");
Invoker invoker = Invoker.getInstance();
System.out.println("invoke function");
long address = invoker.invokeAddress(func, buf);
System.out.println(new String(mem.getZeroTerminatedByteArray(address))); And the output looks like this:
For some reason, creating the HeapInvocationBuffer causes JNI to close the library handle. I'm not sure if this happens on other platforms and just doesn't die due to different dlclose semantics or if it's a JVM difference that changes when things like these are invoked (this is the IBM J9 JVM). |
I think I found one source of that issue. J9's garbage collector appears to collect objects that are detected to be unused. The Library is collected (and finalized) almost as soon as it isn't used or referenced anymore, and jffi communicates addresses and relationships in a raw form. Because functions don't keep a reference to the library, it is assumed unused and cleaned up early, before the function is even called. Adding a simple reference to the library afterward (like printing out a string representation) actually gets it called successfully in the invoke function, which completes, though I run into another issue in trying to retrieve the value from memory. I haven't figured out what this issue is coming from (it's a segfault), but I think it might be another early-free. |
Segfault wasn't from an early free. For some reason, the java program isn't getting the full address back in its long:
Looks like it's getting truncated somewhere along the line. |
It was these lines in Invoker: public final long invokeAddress(CallContext ctx, long function, HeapInvocationBuffer buffer) {
return ((long)invokeInt(ctx, function, buffer)) & ADDRESS_MASK;
} For some reason, |
With some modifications, I get a successful program running:
There's a pretty good chance that this means that AIX64 can be built and run just like the other platforms, but this doesn't fix the issues with J9's aggressive GC. Either way, this problem is largely fixed, and the other issues with the GC early free isn't directly related. I'll make a pull request for the AIX changes. |
System Details
Running on powerpc64-AIX 7.1, with gcc 4.9.4, build vars as follows:
Problems Description
Compiling and running a test program with jffi throws errors and crashes. Trying an unmodified
ant jar
gives the following error:Modifying the GNUmakefile with the following change allows compilation, though:
Compiling and running this C program with the library works (both static and dynamic):
However, a simple Java example using jffi, when compiled with this in the archive, fails:
On Linux:
On AIX:
I'm not quite sure what's going wrong here, and my JNI knowledge is limited at best, but I can probably move from here and isolate what the issue is. I'm pretty sure it's not in libffi, but somewhere in the JNI C code, based on the backtrace, but I'm not sure why, or how to avoid it. I'm not sure if it's in my invocation of the JNI build. I can go a few places from here to experiment, but I'm mostly poking around in the dark here.
The text was updated successfully, but these errors were encountered: