Thanks for the help! Using these techniques plus poring over GDB, I have tracked down the exact location of the ReadOnlyMemoryError()
in my code, but I still don’t know what is causing it. It appears to be a bug either in the Julia run-time system or the LLVM run-time system.
My code (0.6.2) looks like this:
if whichderiv == -1
[snip]
elseif whichderiv == 0
[snip]
elseif whichderiv == 1
[snip]
elseif whichderiv == 2
[snip]
elseif whichderiv == 3
[snip]
else
@assert false
end
This compiles into a switch
statement in LLVM:
switch i64 %1053, label %L888 [
i64 -1, label %if202
i64 0, label %if313
i64 1, label %if314
i64 2, label %if315
i64 3, label %if338
]
This compiles to the following native code, which has a jump-table in it:
movq -48(%rbp), %rax
leaq 1(%rax,%r15), %rax
cmpq $4, %rax
ja L16870
movabsq $140732104772572, %rcx # imm = 0x7FFEBF1D0BDC
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
movq -360(%rbp), %r15
jmpq *%rax
And the problem is that the jump-table entries are corrupted, so that the jmpq
statement lands in never-never land. It is already corrupted as soon as the routine starts for the first time post-compilation, so apparently my code is not to blame. The offsets in the table look reasonable relative to one another, but they are offsets with respect to the wrong base address. This problem is inconsistent; it is in Linux but not Windows, and seemingly trivial changes to how I run my code fix the problem (but there are other suspicious errors later).