avian
avian copied to clipboard
invokedynamic leads to accessing null dynamicTable in addDynamic.
I'm hitting a null pointer crash in Avian, somewhere in the guts of handling an invokedynamic
instruction. This is with avian in "compile mode". It doesn't matter if Avian is compiled with the JDK image/source or with Avian's classpath.
This was compiled and run on x64 Ubuntu 16.04.5 LTS and another Linux-based ARM platform.
The crash details from debugger:
CLICK ME: Backtrace from lldb
Process 14395 stopped
* thread #3: tid = 14399, 0x00007ffff7af5564 libjvm.so`(anonymous namespace)::local::addDynamic(t=0x0000555555971c58, invocation=0x00007fffe401e758)::local::MyThread *, vm::GcInvocation *) + 1482 at compile.cpp:1373, name = 'avian-dynamic', stop reason = signal SIGSEGV: invalid address (fault address: 0x8)
frame #0: 0x00007ffff7af5564 libjvm.so`(anonymous namespace)::local::addDynamic(t=0x0000555555971c58, invocation=0x00007fffe401e758)::local::MyThread *, vm::GcInvocation *) + 1482 at compile.cpp:1373
1370 compileRoots(t)->dynamicThunks()->body()[index * 2] = thunk;
1371 compileRoots(t)->dynamicThunks()->body()[(index * 2) + 1] = size;
1372
-> 1373 t->dynamicTable[index] = reinterpret_cast<void*>(thunk);
1374
1375 roots(t)->invocations()->setBodyElement(t, index, invocation);
1376 }
(lldb) thread backtrace
* thread #3: tid = 14399, 0x00007ffff7af5564 libjvm.so`(anonymous namespace)::local::addDynamic(t=0x0000555555971c58, invocation=0x00007fffe401e758)::local::MyThread *, vm::GcInvocation *) + 1482 at compile.cpp:1373, name = 'avian-dynamic', stop reason = signal SIGSEGV: invalid address (fault address: 0x8)
* frame #0: 0x00007ffff7af5564 libjvm.so`(anonymous namespace)::local::addDynamic(t=0x0000555555971c58, invocation=0x00007fffe401e758)::local::MyThread *, vm::GcInvocation *) + 1482 at compile.cpp:1373
frame #1: 0x00007ffff7b0638f libjvm.so`(anonymous namespace)::local::compile(t=0x0000555555971c58, initialFrame=0x00007ffff0de8ed0, initialIp=0, exceptionHandlerStart=-1)::local::MyThread *, (anonymous namespace)::local::Frame *, unsigned int, int) + 21271 at compile.cpp:5289
frame #2: 0x00007ffff7b0e96e libjvm.so`(anonymous namespace)::local::compile(t=0x0000555555971c58, context=0x00007ffff0de9040)::local::MyThread *, (anonymous namespace)::local::Context *) + 1242 at compile.cpp:7378
frame #3: 0x00007ffff7b2375e libjvm.so`(anonymous namespace)::local::compile(t=0x0000555555971c58, allocator=0x000055555575d290, bootContext=0x0000000000000000, method=0x00007fffe401f5a0)::local::MyThread *, avian::util::FixedAllocator *, (anonymous namespace)::local::BootContext *, vm::GcMethod *) + 488 at compile.cpp:10664
frame #4: 0x00007ffff7b15bd5 libjvm.so`(anonymous namespace)::local::MyProcessor::invokeList(this=0x000055555575d1e8, t=0x0000555555971c58, method=0x00007fffe401f5a0, this_=0x0000000000000000, indirectObjects=false, arguments=0x00007ffff0de9320) const + 757 at compile.cpp:9187
frame #5: 0x00007ffff7ad110b libjvm.so`vm::Processor::invoke(this=0x000055555575d1e8, t=0x0000555555971c58, method=0x00007fffe401f5a0, this_=0x0000000000000000) + 215 at processor.h:207
frame #6: 0x00007ffff7ab54f8 libjvm.so`vm::initClass(t=0x0000555555971c58, c=0x00007fffe401f6a0) + 312 at machine.cpp:5267
frame #7: 0x00007ffff7b2362b libjvm.so`(anonymous namespace)::local::compile(t=0x0000555555971c58, allocator=0x000055555575d290, bootContext=0x0000000000000000, method=0x00007fffe401f458)::local::MyThread *, avian::util::FixedAllocator *, (anonymous namespace)::local::BootContext *, vm::GcMethod *) + 181 at compile.cpp:10633
frame #8: 0x00007ffff7b1780c libjvm.so`(anonymous namespace)::local::compileMethod2(t=0x0000555555971c58, ip=0x000000004005b08c)::local::MyThread *, void *) + 248 at compile.cpp:9645
frame #9: 0x00007ffff7b0f02d libjvm.so`(anonymous namespace)::local::compileMethod(t=0x0000555555971c58)::local::MyThread *) + 110 at compile.cpp:7472
frame #10: 0x000000004000001b
frame #11: 0x00007ffff7b13337 libjvm.so`(anonymous namespace)::local::invoke(thread=0x0000555555971c58, method=0x00007ffff10def78, arguments=0x00007ffff0de9b70)::local::ArgumentList *) + 597 at compile.cpp:8555
frame #12: 0x00007ffff7b15bf2 libjvm.so`(anonymous namespace)::local::MyProcessor::invokeList(this=0x000055555575d1e8, t=0x0000555555971c58, method=0x00007ffff10def78, this_=0x0000555555897460, indirectObjects=false, arguments=0x00007ffff0de9c20) const + 786 at compile.cpp:9189
frame #13: 0x00007ffff7ad110b libjvm.so`vm::Processor::invoke(this=0x000055555575d1e8, t=0x0000555555971c58, method=0x00007ffff10def78, this_=0x0000555555897460) + 215 at processor.h:207
frame #14: 0x00007ffff7b2fda7 libjvm.so`(anonymous namespace)::local::MyClasspath::runThread(this=0x0000555555758538, t=0x0000555555971c58) const + 179 at classpath-openjdk.cpp:622
frame #15: 0x00007ffff7ae0c50 libjvm.so`vm::runJavaThread(t=0x0000555555971c58) + 73 at machine.h:1806
frame #16: 0x00007ffff7ae0cff libjvm.so`vm::runThread(t=0x0000555555971c58, (null)=0x0000000000000000) + 152 at machine.h:1820
frame #17: 0x00007ffff7b7efe6 libjvm.so`vmRun + 47
frame #18: 0x00007ffff7ae0b5a libjvm.so`vm::runRaw(t=0x0000555555971c58, function=(libjvm.so`vm::runThread(vm::Thread*, unsigned long*) at machine.h:1812), arguments=0x0000000000000000)(vm::Thread*, unsigned long*), unsigned long*) + 78 at machine.h:1793
frame #19: 0x00007ffff7ae0bda libjvm.so`vm::run(t=0x0000555555971c58, function=(libjvm.so`vm::runThread(vm::Thread*, unsigned long*) at machine.h:1812), arguments=0x0000000000000000)(vm::Thread*, unsigned long*), unsigned long*) + 83 at machine.h:1801
frame #20: 0x00007ffff7ae096c libjvm.so`vm::Thread::Runnable::run(this=0x0000555555971ce0) + 72 at machine.h:1769
frame #21: 0x00007ffff7a94c01 libjvm.so`(anonymous namespace)::run(r=0x0000555555971ce0) + 50 at posix.cpp:101
frame #22: 0x00007ffff6f846ba libpthread.so.0`start_thread + 202
frame #23: 0x00007ffff77c441d libc.so.6`__clone + 109 at clone.S:109
Probing some variables a bit further:
CLICK ME: print of the Thread variable in debugger
(lldb) frame variable *t
error: libjvm.so 0x000002a5: DW_TAG_member '__size' refers to type 0x000002bc which extends beyond the bounds of 0x00000221
error: libjvm.so 0x00000357: DW_TAG_member '__size' refers to type 0x00000375 which extends beyond the bounds of 0x000002d7
((anonymous namespace)::local::MyThread) *t = {
vm::Thread = {
vtable = 0x000055555575d9f8
m = 0x000055555575d898
parent = 0x00005555557628d8
peer = 0x00005555558d0558
child = 0x0000000000000000
waitNext = 0x0000000000000000
state = ActiveState
criticalLevel = 0
systemThread = 0x0000555555972630
lock = 0x00005555559725d0
javaThread = 0x0000555555897460
exception = 0x0000000000000000
heapIndex = 7303
heapOffset = 8190
protector = 0x00007ffff0de8ce0
classInitStack = 0x00007ffff0de9480
libraryLoadStack = 0x0000000000000000
resource = 0x00007ffff0de8640
checkpoint = 0x00007ffff0de99f0
runnable = {
t = 0x0000555555971c58
}
defaultHeap = 0x0000555555a91cd8
heap = 0x00007fffe4011968
backupHeap = {
[0] = 0
[1] = 0
[2] = 0
[3] = 0
[4] = 0
[5] = 0
[6] = 0
[7] = 0
[8] = 0
[9] = 0
[10] = 0
[11] = 0
[12] = 0
[13] = 0
[14] = 0
[15] = 0
[16] = 0
[17] = 0
[18] = 0
[19] = 0
[20] = 0
[21] = 0
[22] = 0
[23] = 0
[24] = 0
[25] = 0
[26] = 0
[27] = 0
[28] = 0
[29] = 0
[30] = 0
[31] = 0
[32] = 0
[33] = 0
[34] = 0
[35] = 0
[36] = 0
[37] = 0
[38] = 0
[39] = 0
[40] = 0
[41] = 0
[42] = 0
[43] = 0
[44] = 0
[45] = 0
[46] = 0
[47] = 0
[48] = 0
[49] = 0
[50] = 0
[51] = 0
[52] = 0
[53] = 0
[54] = 0
[55] = 0
[56] = 0
[57] = 0
[58] = 0
[59] = 0
[60] = 0
[61] = 0
[62] = 0
[63] = 0
[64] = 0
[65] = 0
[66] = 0
[67] = 0
[68] = 0
[69] = 0
[70] = 0
[71] = 0
[72] = 0
[73] = 0
[74] = 0
[75] = 0
[76] = 0
[77] = 0
[78] = 0
[79] = 0
[80] = 0
[81] = 0
[82] = 0
[83] = 0
[84] = 0
[85] = 0
[86] = 0
[87] = 0
[88] = 0
[89] = 0
[90] = 0
[91] = 0
[92] = 0
[93] = 0
[94] = 0
[95] = 0
[96] = 0
[97] = 0
[98] = 0
[99] = 0
[100] = 0
[101] = 0
[102] = 0
[103] = 0
[104] = 0
[105] = 0
[106] = 0
[107] = 0
[108] = 0
[109] = 0
[110] = 0
[111] = 0
[112] = 0
[113] = 0
[114] = 0
[115] = 0
[116] = 0
[117] = 0
[118] = 0
[119] = 0
[120] = 0
[121] = 0
[122] = 0
[123] = 0
[124] = 0
[125] = 0
[126] = 0
[127] = 0
[128] = 0
[129] = 0
[130] = 0
[131] = 0
[132] = 0
[133] = 0
[134] = 0
[135] = 0
[136] = 0
[137] = 0
[138] = 0
[139] = 0
[140] = 0
[141] = 0
[142] = 0
[143] = 0
[144] = 0
[145] = 0
[146] = 0
[147] = 0
[148] = 0
[149] = 0
[150] = 0
[151] = 0
[152] = 0
[153] = 0
[154] = 0
[155] = 0
[156] = 0
[157] = 0
[158] = 0
[159] = 0
[160] = 0
[161] = 0
[162] = 0
[163] = 0
[164] = 0
[165] = 0
[166] = 0
[167] = 0
[168] = 0
[169] = 0
[170] = 0
[171] = 0
[172] = 0
[173] = 0
[174] = 0
[175] = 0
[176] = 0
[177] = 0
[178] = 0
[179] = 0
[180] = 0
[181] = 0
[182] = 0
[183] = 0
[184] = 0
[185] = 0
[186] = 0
[187] = 0
[188] = 0
[189] = 0
[190] = 0
[191] = 0
[192] = 0
[193] = 0
[194] = 0
[195] = 0
[196] = 0
[197] = 0
[198] = 0
[199] = 0
[200] = 0
[201] = 0
[202] = 0
[203] = 0
[204] = 0
[205] = 0
[206] = 0
[207] = 0
[208] = 0
[209] = 0
[210] = 0
[211] = 0
[212] = 0
[213] = 0
[214] = 0
[215] = 0
[216] = 0
[217] = 0
[218] = 0
[219] = 0
[220] = 0
[221] = 0
[222] = 0
[223] = 0
[224] = 0
[225] = 0
[226] = 0
[227] = 0
[228] = 0
[229] = 0
[230] = 0
[231] = 0
[232] = 0
[233] = 0
[234] = 0
[235] = 0
[236] = 0
[237] = 0
[238] = 0
[239] = 0
[240] = 0
[241] = 0
[242] = 0
[243] = 0
[244] = 0
[245] = 0
[246] = 0
[247] = 0
[248] = 0
[249] = 0
[250] = 0
[251] = 0
[252] = 0
[253] = 0
[254] = 0
[255] = 0
}
backupHeapIndex = 0
flags = 160
}
ip = 0x00000000400520c1
stack = 0x00007ffff0de9818
newStack = 0x00007ffff0de95d0
scratch = 0x00007ffff0de9928
continuation = 0x0000000000000000
exceptionStackAdjustment = 0
exceptionOffset = 0
exceptionHandler = 0x0000000000000000
tailAddress = 0x0000000000000000
virtualCallTarget = 0x0000000000000000
virtualCallIndex = 0
heapImage = 0x0000000000000000
codeImage = 0x0000000000000000
thunkTable = 0x000055555575d3a8
dynamicTable = 0x0000000000000000
trace = 0x00007ffff0de9a20
reference = 0x0000000000000000
arch = 0x0000555555763250
transition = 0x0000000000000000
traceContext = 0x0000000000000000
stackLimit = 140737234377120
referenceFrame = 0x0000000000000000
methodLockIsClean = true
}
(lldb) frame variable *t->m->processor->dynamicTable
(void *) *t->m->processor->dynamicTable = 0x000000004005adf0
.
From that we can see that dynamicTable
was set by the rest of the code in addDynamic
for the t->m->processor
, but this doesn't appear to have been copied over to the t->dynamicTable
field? I think it might be a simple case of a missing call to updateDynamicTable(t, t);
or something like that?? That might be understating the problem, however.
Example application that results in this crash: https://github.com/Poddster/avian_null_dynamicTable
That app is the smallest I can make it, though smaller examples might exist. Changing practically anything in this example app makes the problem disappear. (Infact using that information I've managed to make my original app not crash by working around the issue and accessing a class earlier than it normally would. This seems to "fix" the problem for me, though the underlying issue is obviously still present.)