CRASH: code_api|api.drdecode SEGFAULT/SIGILLs intermittently on aarch64 armv8.0
Created by: joshua-warburton
When run on certain v8.0 hardware, the api.decode test will segfault or SIGILL intermittently. The test harness eats the error message but when the binary is run independently, the fault will appear. Digging into this it appears that the following line in the test triggers the crash
uint written = ((uint(*)(void))generated_code)();
This is running assembly created by the lines above:
instrlist_t *ilist = instrlist_create(GD);
instr_t *callee = INSTR_CREATE_label(GD);
instrlist_append(
ilist,
XINST_CREATE_move(GD, opnd_create_reg(DR_REG_X1), opnd_create_reg(DR_REG_LR)));
instrlist_insert_mov_instr_addr(GD, callee, (byte *)ilist, opnd_create_reg(DR_REG_X0),
ilist, NULL, NULL, NULL);
instrlist_append(ilist, INSTR_CREATE_blr(GD, opnd_create_reg(DR_REG_X0)));
instrlist_append(ilist, INSTR_CREATE_ret(GD, opnd_create_reg(DR_REG_X1)));
instrlist_append(ilist, callee);
instrlist_insert_mov_immed_ptrsz(GD, 0xdeadbeef, opnd_create_reg(DR_REG_X0), ilist,
NULL, NULL, NULL);
instrlist_append(ilist, XINST_CREATE_return(GD));
I modified the test to print out the instructions that are being generated, which seem to be fine
orr %xzr %x30 lsl $0x0000000000000000 -> %x1
movz @0x0000aaab256572c0[2byte] lsl $0x00 -> %x0
movk %x0 @0x0000aaab256572c0[2byte] lsl $0x10 -> %x0
movk %x0 @0x0000aaab256572c0[2byte] lsl $0x20 -> %x0
blr %x0 -> %x30
ret %x1
<label>
movz $0xbeef lsl $0x00 -> %x0
movk %x0 $0xdead lsl $0x10 -> %x0
ret %x30
Oddly enough, if the binary is moved to an arm v8.2 machine, it runs just fine.
Looking at the dump, it appears the SIGILL comes from
Program terminated with signal SIGILL, Illegal instruction.
#0 0x0000ffff885d3000 in ?? ()
0xffff885d3000 mov x1, x30
To Reproduce
- Build the unit tests in debug mode
- Run
./suite/tests/bin/api.drdecode
until you hit a segfault/sigill on an arm v8.0 machine
Expected behaviour Unit test passes
Versions
- most recent version of upstream/master
- Ubuntu 18.04.5 LTS
- 64-bit