Looking carefully at this instruction:
0x499fe5d4: ldr r8, [pc, #12638680] ; 0x499fea44
Lets try this calculation by hand. PC is always 8 bytes ahead of the current instruction, so pc=0x499fe5d4 + 8.
Then we add 12638680, and we read from that memory location.
After asking around a bit I've been told that the number inside the square brackets is not to be taken literally. It includes flags and other things. However, the address in the annotation can be trusted.
And lets also recall that r8 was programmed with this address before we branched. Checking back to the original register dump, r8=0x41d9f3e4 which is the same as cti_op_resolve_global. Things are making some sense.
The offset in the str/ldr lr lines of 3118288 is huge of course. Again I think we have to ignore it. I think the offset being used is 0x40, as shown by the comment.
Now lets think about the value of lr. It got set as 0x499fe5dc because of the "blx r8" that we followed earlier. Now almost immediately inside cti_op_resolve_global we call "bl", which will change the value of lr. However, lr does *not* reflect the return location for the "bl 0x41cf4aac" call. This means either:
1. We crashed before executing the bl inside cti_op_resolve_global (seems impossible), or
2. We executed the bl inside cti_op_resolve_global, and then restored lr, and returned. (seems likely)
So lets go back to the code pasted at the top of this comment (around 0x499fe5dc), since thats where we're returning to.
This code looks odd.
Seems to set r7 to a fixed value and then compare its value against 1?
Looking at register values and memory I'm having trouble convincing myself that this code has run, but it might have.
Anyway, out of time for today unfortunately.
I tried the test webpage that you provided. It doesn't trigger the crash.
Also after a few runs I haven't managed to reproduce the problem where the stub offset is off by 8. Maybe that one was a bad dump.
Working from home today, with a different laptop.
So not using the same trace as earlier. Lets start over with a new crash.
(gdb) bt
#0 0x000013e4 in ?? ()
#1 0x499fe5dc in ?? ()
#2 0x499fe5dc in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) info registers
r0 0x4996e240 1234625088
r1 0xfffffffb 4294967291
r2 0x4996e240 1234625088
r3 0xfffffffb 4294967291
r4 0x47626688 1197631112
r5 0x1d2 466
r6 0x47626588 1197630856
r7 0x5357c57c 1398261116
r8 0x41d9f3e4 1104802788
r9 0x47626570 1197630832
r10 0x45a67400 1168536576
r11 0x41f55058 1106595928
r12 0x4c1d0ab0 1276971696
sp 0xbe8aed78 0xbe8aed78
lr 0x499fe5dc 1235215836
pc 0x13e4 0x13e4
cpsr 0x600f0010 1611595792
Check around the LR area again:
(gdb) x/12i $lr-32
0x499fe5bc: mov r0, sp
0x499fe5c0: str r4, [sp, #3118288] ; 0x60
0x499fe5c4: mov r8, #408 ; 0x198
0x499fe5c8: str r8, [r4, #-3118288] ; 0x2c
0x499fe5cc: ldr r3, [pc, #12638680] ; 0x499fea40
0x499fe5d0: str r4, [r3]
0x499fe5d4: ldr r8, [pc, #12638680] ; 0x499fea44
0x499fe5d8: blx r8
0x499fe5dc: str r0, [r4, #3118288] ; 0x70
0x499fe5e0: str r1, [r4, #3118288] ; 0x74
0x499fe5e4: b 0x499fc264
0x499fe5e8: b 0x499fe618
Looking carefully at this instruction:
0x499fe5d4: ldr r8, [pc, #12638680] ; 0x499fea44
Lets try this calculation by hand. PC is always 8 bytes ahead of the current instruction, so pc=0x499fe5d4 + 8.
Then we add 12638680, and we read from that memory location.
0x499fe5d4 + 8 + 12638680 = 0x4a60bfb4 so:
(gdb) x/x 0x4a60bfb4
0x4a60bfb4: 0x00000000
Hmm, unlikely.
But gdb's annotation said 0x499fea44.
After asking around a bit I've been told that the number inside the square brackets is not to be taken literally. It includes flags and other things. However, the address in the annotation can be trusted.
So, lets check the memory at that address.
(gdb) x/x 0x499fea44 resolve_ global> : str lr, [sp, #3118288] ; 0x40 resolve_ global+ 4>: bl 0x41cf4aac resolve_ global+ 8>: resolve_ global+ 12>: mov pc, lr
0x499fea44: 0x41d9f3e4
(gdb) x/4i 0x41d9f3e4
0x41d9f3e4 <cti_op_
0x41d9f3e8 <cti_op_
0x41d9f3ec <cti_op_
ldr lr, [sp, #3118288] ; 0x40
0x41d9f3f0 <cti_op_
And lets also recall that r8 was programmed with this address before we branched. Checking back to the original register dump, r8=0x41d9f3e4 which is the same as cti_op_ resolve_ global. Things are making some sense.
The offset in the str/ldr lr lines of 3118288 is huge of course. Again I think we have to ignore it. I think the offset being used is 0x40, as shown by the comment.
Now lets think about the value of lr. It got set as 0x499fe5dc because of the "blx r8" that we followed earlier. Now almost immediately inside cti_op_ resolve_ global we call "bl", which will change the value of lr. However, lr does *not* reflect the return location for the "bl 0x41cf4aac" call. This means either: resolve_ global (seems impossible), or resolve_ global, and then restored lr, and returned. (seems likely)
1. We crashed before executing the bl inside cti_op_
2. We executed the bl inside cti_op_
So lets go back to the code pasted at the top of this comment (around 0x499fe5dc), since thats where we're returning to.
0x499fe5dc: str r0, [r4, #3118288] ; 0x70
0x499fe5e0: str r1, [r4, #3118288] ; 0x74
Lets see if we executed those instructions:
r4=0x47626688
r4 + 0x70 = 0x476266f8
(gdb) x/x 0x476266f8
0x476266f8: 0x4996e240
That matches the value of r0.
Looking at the "str r1":
(gdb) x/x 0x476266fc
0x476266fc: 0xfffffffb
That matches the value of r1.
So it seems like we have returned and executed these 2 instructions at least. Next is:
0x499fe5e4: b 0x499fc264
Lets look:
(gdb) x/12i 0x499fc264
0x499fc264: mov r2, #1
0x499fc268: mvn r7, #0
0x499fc26c: ldr r0, [r4, #3118288] ; 0x50
0x499fc270: ldr r1, [r4, #3118288] ; 0x54
0x499fc274: cmn r7, #1
0x499fc278: bne 0x499fe5e8
0x499fc27c: cmn r1, #5
0x499fc280: bne 0x499fe5e8
0x499fc284: ldr r8, [r0]
0x499fc288: ldr r3, [pc, #28956432] ; 0x499fca44
0x499fc28c: cmp r8, r3
0x499fc290: bne 0x499fe5ec
This code looks odd.
Seems to set r7 to a fixed value and then compare its value against 1?
Looking at register values and memory I'm having trouble convincing myself that this code has run, but it might have.
Anyway, out of time for today unfortunately.
I tried the test webpage that you provided. It doesn't trigger the crash.
Also after a few runs I haven't managed to reproduce the problem where the stub offset is off by 8. Maybe that one was a bad dump.