Re: Crashing on LOOP instruction (ARMV7-A)

  • From: Oleg Volosin <oleg@xxxxxxxxxxxxxx>
  • To: "luajit@xxxxxxxxxxxxx" <luajit@xxxxxxxxxxxxx>
  • Date: Tue, 7 Aug 2018 15:15:34 +0000

I'm starting to think it has something to do with mcode_alloc() and the way it 
is allocating 64K aligned blocks of memory.

I can see it is allocating two 32K blocks of memory before the crash one at 
0x07250000 and the second at 0x08CC0000.

MMAP: hint=07250000, size=32768, prot=00000300
MMAP: ret ptr=07250000
MMAP: hint=08CC0000, size=32768, prot=00000300
MMAP: ret ptr=08CC0000

The crash address is always at 0x8CC8000 which is a) not in the range of 
previously allocated memory and b) is exactly past the end of the second 
allocated region i.e. exactly at 0x08CC0000+32K.

Any ideas please?

Thanks



On 7 Aug 2018, at 14:04, Oleg Volosin 
<oleg@xxxxxxxxxxxxxx<mailto:oleg@xxxxxxxxxxxxxx>> wrote:

Actually it is invoking mcode_alloc_at() at least twice before crashing. Not 
sure why GDB not hitting a breakpoint in there though. Totally puzzled.

Anyways, I added some tracing to mcode_alloc_at() and mcode_setprot() and I can 
see it is allocating at least two 32K blocks with PROT_READ | PROT_WRITE before 
crashing. It doesn't allocate with PROT_EXEC nor calling mcode_setprot() to 
update the executable attribute later. Not sure this is expected behaviour or 
an anomaly.


# luajit -j dump test.lua


---- TRACE 1 start test.lua:4
0009  SUBVN    0   0   0  ; 1
0010  JMP      1 => 0005
0005  KSHORT   1   0
0006  ISGE     1   0
0007  JMP      1 => 0011
0008  LOOP     1 => 0011
MMAP: hint=07250000, size=32768, prot=00000300
MMAP: ret ptr=07250000
MMAP: hint=08CC0000, size=32768, prot=00000300
MMAP: ret ptr=08CC0000
Memory fault




On 7 Aug 2018, at 13:18, Oleg Volosin 
<oleg@xxxxxxxxxxxxxx<mailto:oleg@xxxxxxxxxxxxxx>> wrote:


Bit more on this. I don't think it even gets a chance to emit or run any 
instructions at the point of crash, although I'm not totally sure here. I've 
put a breakpoint at mcode_alloc_at() in lj_mcode.c and it is crashing before 
hitting that.

Goin slowly step by step through the code points at cpcall() function messing 
up the stack or something of a sort.

luajit [864294]
Thread [1] (STOPPED) (Suspended : Step)
cpcall() at lj_api.c:1,059 0x80502e0 <<<<- crashing on return from cpcall()
lj_vm_cpcall() at lj_vm.s:1,266 0x8060d90
lua_cpcall() at lj_api.c:1,074 0x8052f42
main() at luajit.c:566 0x804c0c0

static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud)
{
  GCfunc *fn = lj_func_newC(L, 0, getcurrenv(L));
  fn->c.f = func;
  setfuncV(L, L->top, fn);
  setlightudV(L->top+1, checklightudptr(L, ud));
  cframe_nres(L->cframe) = 1+0;  /* Zero results. */
  L->top += 2;
  return L->top-1;  /* Now call the newly allocated C function. */ <<<<- 
crashing on return
}



Oleg



On 7 Aug 2018, at 12:34, Oleg Volosin 
<oleg@xxxxxxxxxxxxxx<mailto:oleg@xxxxxxxxxxxxxx>> wrote:

Hi Mike

I tried to enable correct memory mapping for POSIX platforms (LUAJIT_OS_POSIX 
macro) and confirmed mmap() in lj_mcode.c is actually invoked as it should. No 
change, still crashing just as before.

I have also compared the LJ_TARGET_POSIX executable memory mapping code in 
lj_mcode.c vs Google's V8 JITed engine which works OK on the platform (here 
https://chromium.googlesource.com/v8/v8/+/3.27.27/src/platform-qnx.cc) and it 
appears to be pretty much identical, i.e. it maps the region with (PROT_READ | 
PROT_WRITE | PROT_EXEC) attributes.

Not totally sure where to move from here. Could you please advice.

I tried to gather some further debug info on this. It appears to crash on TSTEQ 
instruction and I'm totally puzzled as to why:




Lua script:

print(">>>");
local times = 100;
while times > 0 do
    times = times - 1;
end
print("<<<");




Call stack:

luajit [790566]
Thread [1] (STOPPED) (Suspended : Signal : SIGSEGV:Segmentation fault)
0x108d000  <<<<---- crashing on TSTEQ below ------------ <<<<
cache_one() at 0x1072bc4
0x31202020
0x31202020



DASM:

0108cfb8:   andeq r0, r0, r1, lsl r0
0108cfbc:   muleq r1, r8, r9
0108cfc0:   andeq r0, r0, r2, lsl r0
0108cfc4:   muleq r0, r0, pc        ; <UNPREDICTABLE>
0108cfc8:   andeq r0, r0, r3, lsl r0
0108cfcc:   andeq r0, r0, r8
0108cfd0:   svcvs 0x00fffffa
0108cfd4:   andeq r0, r0, r5, asr #5
0108cfd8:   andeq r0, r0, r0
0108cfdc:   andeq r0, r0, r0
0108cfe0:   andeq r0, r0, r0
0108cfe4:   andeq r0, r0, r0
0108cfe8:   andeq r0, r0, r0
0108cfec:   andeq r0, r0, r0
0108cff0:   andeq r0, r0, r0
0108cff4:   andeq r0, r0, r0
0108cff8:   andeq r0, r0, r0
0108cffc:   andeq r0, r0, r0
0108d000:   tsteq r8, r8, ror #30    <<<<---- crashing on TSTEQ ------------ 
<<<<
0108d004:   stmdaeq r10, {r3, r4, r5, r7, r8, r9, r12, lr, pc}
0108d008:   tsteq r1, r4, asr #4
0108d00c:   tsteq r7, r12, lsr #10
0108d010:   tsteq r4, r12, asr r1
0108d014:   stmdavc r1, {r4, r6, r9, lr, pc}
0108d018:   tsteq r4, r8, ror lr
0108d01c:   smlabteq r5, r8, r0, r2
0108d020:   smlabteq r3, r8, r3, sp
0108d024:   stmdavc r1, {r0, r2, r4, r5, r6, r8, r11, r12, lr}
0108d028:   tsteq r2, r12, lsl r11
0108d02c:   tsteq r4, r12, asr #10
0108d030:    ; <UNDEFINED> instruction: 0x0101efbc
0108d034:   tsteq r5, r8, ror r3
0108d038:   smlabteq r4, r4, sp, r5
0108d03c:    ; <UNDEFINED> instruction: 0x01039f90


Regs:

r0 0xffffffff
r1 0x80c0370
r2 0x10a8
r3 0x2
r4 0x0
r5 0x80ae228
r6 0x80b5be8
r7 0x7
r8 0x80e0b58
r9 0x80e0ac8
r10 0x0
r11 0xe58de000
r12 0x108d6c8
sp 0x8047250
lr 0x1072bc4
pc 0x108d000
cpsr 0xa0000010
$




Oleg






On 6 Aug 2018, at 18:44, Mike Pall 
<mikelj-1808@xxxxxxx<mailto:mikelj-1808@xxxxxxx>> wrote:

Oleg Volosin wrote:
Memory fault

Check memory page protections for JIT-compiled code. You're
probably ending up using the dummy allocator in lj_mcode.c, which
WILL fail, if memory is not executable by default.

In other words: Figure out which API your OS supports, e.g. POSIX.
Then compile with e.g. -DLUAJIT_OS=LUAJIT_OS_POSIX . Or contribute
a change to lj_arch.h for your OS (near LUAJIT_OS).

--Mike





Other related posts: