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/config.h> 14#include <linux/linkage.h> 15#include <asm/assembler.h> 16 .text 17 18@ fp is 0 or stack frame 19 20#define frame r4 21#define next r5 22#define save r6 23#define mask r7 24#define offset r8 25 26ENTRY(__backtrace) 27 mov r1, #0x10 28 mov r0, fp 29 30ENTRY(c_backtrace) 31 32#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK) 33 mov pc, lr 34#else 35 36 stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location... 37 tst r1, #0x10 @ 26 or 32-bit? 38 moveq mask, #0xfc000003 39 movne mask, #0 40 tst mask, r0 41 movne r0, #0 42 movs frame, r0 431: moveq r0, #-2 44 ldmeqfd sp!, {r4 - r8, pc} 45 462: stmfd sp!, {pc} @ calculate offset of PC in STMIA instruction 47 ldr r0, [sp], #4 48 adr r1, 2b - 4 49 sub offset, r0, r1 50 513: tst frame, mask @ Check for address exceptions... 52 bne 1b 53 541001: ldr next, [frame, #-12] @ get fp 551002: ldr r2, [frame, #-4] @ get lr 561003: ldr r3, [frame, #0] @ get pc 57 sub save, r3, offset @ Correct PC for prefetching 58 bic save, save, mask 591004: ldr r1, [save, #0] @ get instruction at function 60 mov r1, r1, lsr #10 61 ldr r3, .Ldsi+4 62 teq r1, r3 63 subeq save, save, #4 64 mov r0, save 65 bic r1, r2, mask 66 bl dump_backtrace_entry 67 68 ldr r0, [frame, #-8] @ get sp 69 sub r0, r0, #4 701005: ldr r1, [save, #4] @ get instruction at function+4 71 mov r3, r1, lsr #10 72 ldr r2, .Ldsi+4 73 teq r3, r2 @ Check for stmia sp!, {args} 74 addeq save, save, #4 @ next instruction 75 bleq .Ldumpstm 76 77 sub r0, frame, #16 781006: ldr r1, [save, #4] @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction 79 mov r3, r1, lsr #10 80 ldr r2, .Ldsi 81 teq r3, r2 82 bleq .Ldumpstm 83 84 /* 85 * A zero next framepointer means we're done. 86 */ 87 teq next, #0 88 ldmeqfd sp!, {r4 - r8, pc} 89 90 /* 91 * The next framepointer must be above the 92 * current framepointer. 93 */ 94 cmp next, frame 95 mov frame, next 96 bhi 3b 97 b 1007f 98 99/* 100 * Fixup for LDMDB. Note that this must not be in the fixup section. 101 */ 1021007: ldr r0, =.Lbad 103 mov r1, frame 104 bl printk 105 ldmfd sp!, {r4 - r8, pc} 106 .ltorg 107 108 .section __ex_table,"a" 109 .align 3 110 .long 1001b, 1007b 111 .long 1002b, 1007b 112 .long 1003b, 1007b 113 .long 1004b, 1007b 114 .long 1005b, 1007b 115 .long 1006b, 1007b 116 .previous 117 118#define instr r4 119#define reg r5 120#define stack r6 121 122.Ldumpstm: stmfd sp!, {instr, reg, stack, r7, r8, lr} 123 mov stack, r0 124 mov instr, r1 125 mov reg, #9 126 mov r7, #0 1271: mov r3, #1 128 tst instr, r3, lsl reg 129 beq 2f 130 add r7, r7, #1 131 teq r7, #4 132 moveq r7, #0 133 moveq r3, #'\n' 134 movne r3, #' ' 135 ldr r2, [stack], #-4 136 mov r1, reg 137 adr r0, .Lfp 138 bl printk 1392: subs reg, reg, #1 140 bpl 1b 141 teq r7, #0 142 adrne r0, .Lcr 143 blne printk 144 mov r0, stack 145 ldmfd sp!, {instr, reg, stack, r7, r8, pc} 146 147.Lfp: .asciz " r%d = %08X%c" 148.Lcr: .asciz "\n" 149.Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n" 150 .align 151.Ldsi: .word 0x00e92dd8 >> 2 152 .word 0x00e92d00 >> 2 153 154#endif 155