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#ifndef CONFIG_FRAME_POINTER 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 LOADREGS(eqfd, 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 LOADREGS(eqfd, 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 101 */ 102 .section .fixup,"ax" 103 .align 0 1041007: ldr r0, =.Lbad 105 mov r1, frame 106 bl printk 107 LOADREGS(fd, sp!, {r4 - r8, pc}) 108 .ltorg 109 .previous 110 111 .section __ex_table,"a" 112 .align 3 113 .long 1001b, 1007b 114 .long 1002b, 1007b 115 .long 1003b, 1007b 116 .long 1004b, 1007b 117 .long 1005b, 1007b 118 .long 1006b, 1007b 119 .previous 120 121#define instr r4 122#define reg r5 123#define stack r6 124 125.Ldumpstm: stmfd sp!, {instr, reg, stack, r7, lr} 126 mov stack, r0 127 mov instr, r1 128 mov reg, #9 129 mov r7, #0 1301: mov r3, #1 131 tst instr, r3, lsl reg 132 beq 2f 133 add r7, r7, #1 134 teq r7, #4 135 moveq r7, #0 136 moveq r3, #'\n' 137 movne r3, #' ' 138 ldr r2, [stack], #-4 139 mov r1, reg 140 adr r0, .Lfp 141 bl printk 1422: subs reg, reg, #1 143 bpl 1b 144 teq r7, #0 145 adrne r0, .Lcr 146 blne printk 147 mov r0, stack 148 LOADREGS(fd, sp!, {instr, reg, stack, r7, pc}) 149 150.Lfp: .asciz " r%d = %08X%c" 151.Lcr: .asciz "\n" 152.Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n" 153 .align 154.Ldsi: .word 0x00e92dd8 >> 2 155 .word 0x00e92d00 >> 2 156 157#endif 158