123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- /*
- * linux/arch/arm/lib/backtrace.S
- *
- * Copyright (C) 1995, 1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 27/03/03 Ian Molton Clean up CONFIG_CPU
- *
- */
- #include <linux/config.h>
- #include <linux/linkage.h>
- #include <asm/assembler.h>
- .text
- @ fp is 0 or stack frame
- #define frame r4
- #define next r5
- #define save r6
- #define mask r7
- #define offset r8
- ENTRY(__backtrace)
- mov r1, #0x10
- mov r0, fp
- ENTRY(c_backtrace)
- #ifndef CONFIG_FRAME_POINTER
- mov pc, lr
- #else
- stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location...
- tst r1, #0x10 @ 26 or 32-bit?
- moveq mask, #0xfc000003
- movne mask, #0
- tst mask, r0
- movne r0, #0
- movs frame, r0
- 1: moveq r0, #-2
- LOADREGS(eqfd, sp!, {r4 - r8, pc})
- 2: stmfd sp!, {pc} @ calculate offset of PC in STMIA instruction
- ldr r0, [sp], #4
- adr r1, 2b - 4
- sub offset, r0, r1
- 3: tst frame, mask @ Check for address exceptions...
- bne 1b
- 1001: ldr next, [frame, #-12] @ get fp
- 1002: ldr r2, [frame, #-4] @ get lr
- 1003: ldr r3, [frame, #0] @ get pc
- sub save, r3, offset @ Correct PC for prefetching
- bic save, save, mask
- 1004: ldr r1, [save, #0] @ get instruction at function
- mov r1, r1, lsr #10
- ldr r3, .Ldsi+4
- teq r1, r3
- subeq save, save, #4
- mov r0, save
- bic r1, r2, mask
- bl dump_backtrace_entry
- ldr r0, [frame, #-8] @ get sp
- sub r0, r0, #4
- 1005: ldr r1, [save, #4] @ get instruction at function+4
- mov r3, r1, lsr #10
- ldr r2, .Ldsi+4
- teq r3, r2 @ Check for stmia sp!, {args}
- addeq save, save, #4 @ next instruction
- bleq .Ldumpstm
- sub r0, frame, #16
- 1006: ldr r1, [save, #4] @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction
- mov r3, r1, lsr #10
- ldr r2, .Ldsi
- teq r3, r2
- bleq .Ldumpstm
- /*
- * A zero next framepointer means we're done.
- */
- teq next, #0
- LOADREGS(eqfd, sp!, {r4 - r8, pc})
- /*
- * The next framepointer must be above the
- * current framepointer.
- */
- cmp next, frame
- mov frame, next
- bhi 3b
- b 1007f
- /*
- * Fixup for LDMDB
- */
- .section .fixup,"ax"
- .align 0
- 1007: ldr r0, =.Lbad
- mov r1, frame
- bl printk
- LOADREGS(fd, sp!, {r4 - r8, pc})
- .ltorg
- .previous
-
- .section __ex_table,"a"
- .align 3
- .long 1001b, 1007b
- .long 1002b, 1007b
- .long 1003b, 1007b
- .long 1004b, 1007b
- .long 1005b, 1007b
- .long 1006b, 1007b
- .previous
- #define instr r4
- #define reg r5
- #define stack r6
- .Ldumpstm: stmfd sp!, {instr, reg, stack, r7, lr}
- mov stack, r0
- mov instr, r1
- mov reg, #9
- mov r7, #0
- 1: mov r3, #1
- tst instr, r3, lsl reg
- beq 2f
- add r7, r7, #1
- teq r7, #4
- moveq r7, #0
- moveq r3, #'\n'
- movne r3, #' '
- ldr r2, [stack], #-4
- mov r1, reg
- adr r0, .Lfp
- bl printk
- 2: subs reg, reg, #1
- bpl 1b
- teq r7, #0
- adrne r0, .Lcr
- blne printk
- mov r0, stack
- LOADREGS(fd, sp!, {instr, reg, stack, r7, pc})
- .Lfp: .asciz " r%d = %08X%c"
- .Lcr: .asciz "\n"
- .Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n"
- .align
- .Ldsi: .word 0x00e92dd8 >> 2
- .word 0x00e92d00 >> 2
- #endif
|