I've found and fixed the bugs that were stopping gcj from working. Firstly, there was the "libgcc is a symlink instead of a linker script" bug that I've explained before. Then there was the libgcj/sysdep/arm/locks.h problem that broke locking. I already described that. Then I found a locking bug in the boehm garbage collector. GC_clear(), which releases a lock, was simply inline static void GC_clear(volatile unsigned int *addr) { /* Try to discourage gcc from moving anything past this. */ __asm__ __volatile__(" " : : : "memory"); *(addr) = 0; } but it needs a memory barrier instruction. The easiest way to fix this is to use a gcc builtin that generates the correct barrier: inline static void GC_clear(volatile unsigned int *addr) { __sync_lock_release(addr); } I also replaced GC_test_and_set() with a gcc builtin, although this isn't strictly necessary: inline static int GC_test_and_set(volatile unsigned int *addr) { return __sync_lock_test_and_set(addr, 1); } There was also a problem in libffi when generating a closure. The code that generates a trampoline looks like this: #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ unsigned int __fun = (unsigned int)(FUN); \ unsigned int __ctx = (unsigned int)(CTX); \ *(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \ *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \ *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \ *(unsigned int*) &__tramp[12] = __ctx; \ *(unsigned int*) &__tramp[16] = __fun; \ __clear_cache((&__tramp[0]), (&__tramp[19])); \ }) Here, three instructions are laid down in memory, followed by some data fields. Once that has been done, __clear_cache() is called on the block of memory. Unfortunately, due to the requirement to placate SELinux, the same block of memory is mapped twice, once with RW mapping and once with RX mapping. Therefore, there must be two calls to __clear_cache(), one to flush the dcache, and one to flush the icache. Like this: #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ unsigned int __fun = (unsigned int)(FUN); \ unsigned int __ctx = (unsigned int)(CTX); \ unsigned char *insns = (unsigned char *)(CTX); \ *(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \ *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \ *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \ *(unsigned int*) &__tramp[12] = __ctx; \ *(unsigned int*) &__tramp[16] = __fun; \ __clear_cache((&__tramp[0]), (&__tramp[19])); /* Clear data mapping. */ \ __clear_cache(insns, insns + 3 * sizeof (unsigned int)); \ /* Clear instruction \ mapping. */ \ }) Finally, libjava was segfaulting when an array class was finalized. This has apparently always happened, but on other platforms the segfault is caught and turned into a NullPointerException. All finalizers are called from an exception region that traps all exceptions and continues, so we never noticed. Fixed thusly: --- libjava/java/lang/natClass.cc 2010-06-11 05:09:01.000000000 -0400 +++ prev/libjava/java/lang/natClass.cc 2011-06-21 06:09:22.000000000 -0400 @@ -668,6 +668,8 @@ void java::lang::Class::finalize (void) { + // Array classes don't have an engine, and don't need to be finalized. + if (engine) engine->unregister(this); } After all this, gcj now seems to work. I'm now building OpenJDK. Andrew. _______________________________________________ arm mailing list arm@xxxxxxxxxxxxxxxxxxxxxxx https://admin.fedoraproject.org/mailman/listinfo/arm