Somehow changing how I log things made us go back to 9 valid "allocation rounds" and the tenth blowing up...
--- crash at 2024/02/06 00:25:31---
build:9c92a2f1-2.2.0-release.163717-buildbot
r0:90300d00 r1:00000000 r2:90300d00 r3: 00004000
r12:90300d00 lr:9001aa15 pc:00000000 psr: 200f0000
cfsr:00000001 hfsr:00000000 mmfar:00000000 bfar: 00000000
rcccsr:00000000
heap allocated: 16465792
Lua totalbytes=0 GCdebt=0 GCestimate=0 stacksize=0
It looks like the same thing as before. Initially I didn't realize this so I looked for some docs.
docs: Documentation – Arm Developer
cfsr is 00000001, so here's what the last bit does:
IACCVIOL
Instruction access violation flag:
0
No instruction access violation fault.
1
The processor attempted an instruction fetch from a location that does not permit execution.
This fault occurs on any access to an XN region, even when the MPU is disabled or not present.
When this bit is 1, the PC value stacked for the exception return points to the faulting instruction. The processor has not written a fault address to the MMAR.
so that checks out. Feels good to finally find some hints in the documentation and not in trial-and-error...
Now here's lr
:
Link Register
The Link Register (LR) is register R14. It stores the return information for subroutines, function calls, and exceptions. On reset, the processor sets the LR value to 0xFFFFFFFF.
And that'd be our calling code. Here' it's 9001aa15, which I'll infer to be 1aa15 in my compiled code. gdb doesn't know much:
No line number information available for address 0x1aa15 <_SM12scala.Array$D4filliL15scala.Function0L22scala.reflect.ClassTagL16java.lang.ObjectEO+76>
but if we desugar this... it's the method my Scala is calling: Array.fill
. I have it in my objdump:
0001a9c8 <_SM12scala.Array$D4filliL15scala.Function0L22scala.reflect.ClassTagL16java.lang.ObjectEO>:
1a9c8: 2d e9 f0 43 push.w {r4, r5, r6, r7, r8, r9, lr}
1a9cc: 81 b0 sub sp, #4
1a9ce: 00 28 cmp r0, #0
1a9d0: 3d d0 beq 0x1aa4e <_SM12scala.Array$D4filliL15scala.Function0L22scala.reflect.ClassTagL16java.lang.ObjectEO+0x86> @ imm = #122
1a9d2: 18 46 mov r0, r3
1a9d4: 88 46 mov r8, r1
1a9d6: 00 29 cmp r1, #0
1a9d8: 29 dd ble 0x1aa2e <_SM12scala.Array$D4filliL15scala.Function0L22scala.reflect.ClassTagL16java.lang.ObjectEO+0x66> @ imm = #82
1a9da: c0 b3 cbz r0, 0x1aa4e <_SM12scala.Array$D4filliL15scala.Function0L22scala.reflect.ClassTagL16java.lang.ObjectEO+0x86> @ imm = #112
1a9dc: 14 46 mov r4, r2
1a9de: 01 68 ldr r1, [r0]
1a9e0: 1d 4a ldr r2, [pc, #116] @ 0x1aa58 <$d.5+0x4>
1a9e2: 7a 44 add r2, pc
1a9e4: 89 68 ldr r1, [r1, #8]
1a9e6: d2 f8 00 90 ldr.w r9, [r2]
1a9ea: 43 f6 6c 22 movw r2, #14956
1a9ee: 09 eb 81 01 add.w r1, r9, r1, lsl #2
1a9f2: 8a 58 ldr r2, [r1, r2]
1a9f4: 41 46 mov r1, r8
1a9f6: 90 47 blx r2
1a9f8: 4c b3 cbz r4, 0x1aa4e <_SM12scala.Array$D4filliL15scala.Function0L22scala.reflect.ClassTagL16java.lang.ObjectEO+0x86> @ imm = #82
1a9fa: 06 46 mov r6, r0
1a9fc: 17 48 ldr r0, [pc, #92] @ 0x1aa5c <$d.5+0x8>
1a9fe: 78 44 add r0, pc
1aa00: 00 27 movs r7, #0
1aa02: 05 68 ldr r5, [r0]
1aa04: 20 68 ldr r0, [r4]
1aa06: 80 68 ldr r0, [r0, #8]
1aa08: 09 eb 80 00 add.w r0, r9, r0, lsl #2
1aa0c: d0 f8 2c 1b ldr.w r1, [r0, #2860]
1aa10: 20 46 mov r0, r4
1aa12: 88 47 blx r1
1aa14: 03 46 mov r3, r0
1aa16: 28 46 mov r0, r5
1aa18: 31 46 mov r1, r6
1aa1a: 3a 46 mov r2, r7
1aa1c: e7 f7 a2 ff bl 0x2964 <_SM27scala.runtime.ScalaRunTime$D12array_updateL16java.lang.ObjectiL16java.lang.ObjectuEO> @ imm = #-98492
1aa20: 01 37 adds r7, #1
1aa22: b8 45 cmp r8, r7
1aa24: ee d1 bne 0x1aa04 <_SM12scala.Array$D4filliL15scala.Function0L22scala.reflect.ClassTagL16java.lang.ObjectEO+0x3c> @ imm = #-36
1aa26: 30 46 mov r0, r6
1aa28: 01 b0 add sp, #4
1aa2a: bd e8 f0 83 pop.w {r4, r5, r6, r7, r8, r9, pc}
1aa2e: 70 b1 cbz r0, 0x1aa4e <_SM12scala.Array$D4filliL15scala.Function0L22scala.reflect.ClassTagL16java.lang.ObjectEO+0x86> @ imm = #28
1aa30: 01 68 ldr r1, [r0]
1aa32: 08 4a ldr r2, [pc, #32] @ 0x1aa54 <$d.5>
1aa34: 7a 44 add r2, pc
1aa36: 89 68 ldr r1, [r1, #8]
1aa38: 12 68 ldr r2, [r2]
1aa3a: 02 eb 81 01 add.w r1, r2, r1, lsl #2
1aa3e: 43 f6 6c 22 movw r2, #14956
1aa42: 8a 58 ldr r2, [r1, r2]
1aa44: 00 21 movs r1, #0
1aa46: 01 b0 add sp, #4
1aa48: bd e8 f0 43 pop.w {r4, r5, r6, r7, r8, r9, lr}
1aa4c: 10 47 bx r2
1aa4e: 00 20 movs r0, #0
1aa50: f6 f7 84 fb bl 0x1115c <_SM34scala.scalanative.runtime.package$D16throwNullPointernEO> @ imm = #-39160
quick zoom at the area around 1aa15
:
1aa10: 20 46 mov r0, r4
1aa12: 88 47 blx r1
1aa14: 03 46 mov r3, r0
1aa16: 28 46 mov r0, r5
1aa18: 31 46 mov r1, r6
1aa1a: 3a 46 mov r2, r7
1aa1c: e7 f7 a2 ff bl 0x2964 <_SM27scala.runtime.ScalaRunTime$D12array_updateL16java.lang.ObjectiL16java.lang.ObjectuEO> @ imm = #-98492
Thing is, 1aa15
is in the middle of an instruction: the byte 46
. If I understand anything, you can't just split an instruction like that because 03 46
is just the code for a copy between these particular registers. And how is that even performing a jump to 0x00
?