1/* 2 * linux/arch/arm/lib/backtrace.S 3 * 4 * Copyright (C) 1995, 1996 Russell King 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * 27/03/03 Ian Molton Clean up CONFIG_CPU 11 * 12 */ 13#include <linux/linkage.h> 14#include <asm/assembler.h> 15 .text 16 17@ fp is 0 or stack frame 18 19#define frame r4 20#define next r5 21#define save r6 22#define mask r7 23#define offset r8 24 25ENTRY(__backtrace) 26 mov r1, #0x10 27 mov r0, fp 28 29ENTRY(c_backtrace) 30 31#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK) 32 mov pc, lr 33#else 34 35 stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location... 36 tst r1, #0x10 @ 26 or 32-bit? 37 moveq mask, #0xfc000003 38 movne mask, #0 39 tst mask, r0 40 movne r0, #0 41 movs frame, r0 421: moveq r0, #-2 43 ldmeqfd sp!, {r4 - r8, pc} 44 452: stmfd sp!, {pc} @ calculate offset of PC in STMIA instruction 46 ldr r0, [sp], #4 47 adr r1, 2b - 4 48 sub offset, r0, r1 49 503: tst frame, mask @ Check for address exceptions... 51 bne 1b 52 531001: ldr next, [frame, #-12] @ get fp 541002: ldr r2, [frame, #-4] @ get lr 551003: ldr r3, [frame, #0] @ get pc 56 sub save, r3, offset @ Correct PC for prefetching 57 bic save, save, mask 581004: ldr r1, [save, #0] @ get instruction at function 59 mov r1, r1, lsr #10 60 ldr r3, .Ldsi+4 61 teq r1, r3 62 subeq save, save, #4 63 mov r0, save 64 bic r1, r2, mask 65 bl dump_backtrace_entry 66 67 ldr r0, [frame, #-8] @ get sp 68 sub r0, r0, #4 691005: ldr r1, [save, #4] @ get instruction at function+4 70 mov r3, r1, lsr #10 71 ldr r2, .Ldsi+4 72 teq r3, r2 @ Check for stmia sp!, {args} 73 addeq save, save, #4 @ next instruction 74 bleq .Ldumpstm 75 76 sub r0, frame, #16 771006: ldr r1, [save, #4] @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction 78 mov r3, r1, lsr #10 79 ldr r2, .Ldsi 80 teq r3, r2 81 bleq .Ldumpstm 82 83 /* 84 * A zero next framepointer means we're done. 85 */ 86 teq next, #0 87 ldmeqfd sp!, {r4 - r8, pc} 88 89 /* 90 * The next framepointer must be above the 91 * current framepointer. 92 */ 93 cmp next, frame 94 mov frame, next 95 bhi 3b 96 b 1007f 97 98/* 99 * Fixup for LDMDB. Note that this must not be in the fixup section. 100 */ 1011007: ldr r0, =.Lbad 102 mov r1, frame 103 bl printk 104 ldmfd sp!, {r4 - r8, pc} 105 .ltorg 106 107 .section __ex_table,"a" 108 .align 3 109 .long 1001b, 1007b 110 .long 1002b, 1007b 111 .long 1003b, 1007b 112 .long 1004b, 1007b 113 .long 1005b, 1007b 114 .long 1006b, 1007b 115 .previous 116 117#define instr r4 118#define reg r5 119#define stack r6 120 121.Ldumpstm: stmfd sp!, {instr, reg, stack, r7, r8, lr} 122 mov stack, r0 123 mov instr, r1 124 mov reg, #9 125 mov r7, #0 1261: mov r3, #1 127 tst instr, r3, lsl reg 128 beq 2f 129 add r7, r7, #1 130 teq r7, #4 131 moveq r7, #0 132 moveq r3, #'\n' 133 movne r3, #' ' 134 ldr r2, [stack], #-4 135 mov r1, reg 136 adr r0, .Lfp 137 bl printk 1382: subs reg, reg, #1 139 bpl 1b 140 teq r7, #0 141 adrne r0, .Lcr 142 blne printk 143 mov r0, stack 144 ldmfd sp!, {instr, reg, stack, r7, r8, pc} 145 146.Lfp: .asciz " r%d = %08X%c" 147.Lcr: .asciz "\n" 148.Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n" 149 .align 150.Ldsi: .word 0x00e92dd8 >> 2 151 .word 0x00e92d00 >> 2 152 153#endif 154