.text
@ fp is 0 or stack frame
ENTRY(__backtrace)
mov r1,
mov r0, fp
ENTRY(c_backtrace)
mov pc, lr
ENDPROC(__backtrace)
ENDPROC(c_backtrace)
stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location...
movs frame, r0 @ if frame pointer is zero
beq no_frame @ we have no stack frames
tst r1,
ARM( moveq mask,
THUMB( moveq mask,
THUMB( orreq mask,
movne mask,
1: stmfd sp!, {pc} @ calculate offset of PC stored
ldr r0, [sp],
adr r1, 1b
sub offset, r0, r1
for_each_frame: tst frame, mask @ Check for address exceptions
bne no_frame
1001: ldr sv_pc, [frame,
1002: ldr sv_fp, [frame,
sub sv_pc, sv_pc, offset @ Correct PC for prefetching
bic sv_pc, sv_pc, mask @ mask PC/LR for the mode
1003: ldr r2, [sv_pc,
ldr r3, .Ldsi+4 @ adjust saved 'pc' back one
teq r3, r2, lsr
subne r0, sv_pc,
subeq r0, sv_pc,
ldr r1, [frame,
mov r2, frame
bic r1, r1, mask @ mask PC/LR for the mode
bl dump_backtrace_entry
ldr r1, [sv_pc,
ldr r3, .Ldsi+4
teq r3, r1, lsr
ldreq r0, [frame,
subeq r0, r0,
bleq .Ldumpstm @ dump saved registers
1004: ldr r1, [sv_pc,
ldr r3, .Ldsi @ instruction exists,
teq r3, r1, lsr
subeq r0, frame,
bleq .Ldumpstm @ dump saved registers
teq sv_fp,
beq no_frame @ no further frames
cmp sv_fp, frame @ next frame must be
mov frame, sv_fp @ above the current frame
bhi for_each_frame
1006: adr r0, .Lbad
mov r1, frame
bl printk
no_frame: ldmfd sp!, {r4 - r8, pc}
ENDPROC(__backtrace)
ENDPROC(c_backtrace)
.pushsection __ex_table,"a"
.align 3
.long 1001b, 1006b
.long 1002b, 1006b
.long 1003b, 1006b
.long 1004b, 1006b
.popsection
.Ldumpstm: stmfd sp!, {instr, reg, stack, r7, lr}
mov stack, r0
mov instr, r1
mov reg,
mov r7,
1: mov r3,
ARM( tst instr, r3, lsl reg )
THUMB( lsl r3, reg )
THUMB( tst instr, r3 )
beq 2f
add r7, r7,
teq r7,
moveq r7,
moveq r1,
movne r1,
ldr r3, [stack],
mov r2, reg
adr r0, .Lfp
bl printk
2: subs reg, reg,
bpl 1b
teq r7,
adrne r0, .Lcr
blne printk
ldmfd sp!, {instr, reg, stack, r7, pc}
.Lfp: .asciz "%cr%d:%08x"
.Lcr: .asciz "\n"
.Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n"
.align
.Ldsi: .word 0xe92dd800 >> 10 @ stmfd sp!, {... fp, ip, lr, pc}
.word 0xe92d0000 >> 10 @ stmfd sp!, {}