1/* 2 * linux/arch/arm26/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#include <linux/linkage.h> 11#include <asm/assembler.h> 12 .text 13 14@ fp is 0 or stack frame 15 16#define frame r4 17#define next r5 18#define save r6 19#define mask r7 20#define offset r8 21 22ENTRY(__backtrace) 23 mov r1, #0x10 24 mov r0, fp 25 26ENTRY(c_backtrace) 27 28#ifdef CONFIG_NO_FRAME_POINTER 29 mov pc, lr 30#else 31 32 stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location... 33 mov mask, #0xfc000003 34 tst mask, r0 35 movne r0, #0 36 movs frame, r0 371: moveq r0, #-2 38 LOADREGS(eqfd, sp!, {r4 - r8, pc}) 39 402: stmfd sp!, {pc} @ calculate offset of PC in STMIA instruction 41 ldr r0, [sp], #4 42 adr r1, 2b - 4 43 sub offset, r0, r1 44 453: tst frame, mask @ Check for address exceptions... 46 bne 1b 47 481001: ldr next, [frame, #-12] @ get fp 491002: ldr r2, [frame, #-4] @ get lr 501003: ldr r3, [frame, #0] @ get pc 51 sub save, r3, offset @ Correct PC for prefetching 52 bic save, save, mask 531004: ldr r1, [save, #0] @ get instruction at function 54 mov r1, r1, lsr #10 55 ldr r3, .Ldsi+4 56 teq r1, r3 57 subeq save, save, #4 58 adr r0, .Lfe 59 mov r1, save 60 bic r2, r2, mask 61 bl printk @ print pc and link register 62 63 ldr r0, [frame, #-8] @ get sp 64 sub r0, r0, #4 651005: ldr r1, [save, #4] @ get instruction at function+4 66 mov r3, r1, lsr #10 67 ldr r2, .Ldsi+4 68 teq r3, r2 @ Check for stmia sp!, {args} 69 addeq save, save, #4 @ next instruction 70 bleq .Ldumpstm 71 72 sub r0, frame, #16 731006: ldr r1, [save, #4] @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction 74 mov r3, r1, lsr #10 75 ldr r2, .Ldsi 76 teq r3, r2 77 bleq .Ldumpstm 78 79 teq frame, next 80 movne frame, next 81 teqne frame, #0 82 bne 3b 83 LOADREGS(fd, sp!, {r4 - r8, pc}) 84 85/* 86 * Fixup for LDMDB 87 */ 88 .section .fixup,"ax" 89 .align 0 901007: ldr r0, =.Lbad 91 mov r1, frame 92 bl printk 93 LOADREGS(fd, sp!, {r4 - r8, pc}) 94 .ltorg 95 .previous 96 97 .section __ex_table,"a" 98 .align 3 99 .long 1001b, 1007b 100 .long 1002b, 1007b 101 .long 1003b, 1007b 102 .long 1004b, 1007b 103 .long 1005b, 1007b 104 .long 1006b, 1007b 105 .previous 106 107#define instr r4 108#define reg r5 109#define stack r6 110 111.Ldumpstm: stmfd sp!, {instr, reg, stack, r7, lr} 112 mov stack, r0 113 mov instr, r1 114 mov reg, #9 115 mov r7, #0 1161: mov r3, #1 117 tst instr, r3, lsl reg 118 beq 2f 119 add r7, r7, #1 120 teq r7, #4 121 moveq r7, #0 122 moveq r3, #'\n' 123 movne r3, #' ' 124 ldr r2, [stack], #-4 125 mov r1, reg 126 adr r0, .Lfp 127 bl printk 1282: subs reg, reg, #1 129 bpl 1b 130 teq r7, #0 131 adrne r0, .Lcr 132 blne printk 133 mov r0, stack 134 LOADREGS(fd, sp!, {instr, reg, stack, r7, pc}) 135 136.Lfe: .asciz "Function entered at [<%p>] from [<%p>]\n" 137.Lfp: .asciz " r%d = %08X%c" 138.Lcr: .asciz "\n" 139.Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n" 140 .align 141.Ldsi: .word 0x00e92dd8 >> 2 142 .word 0x00e92d00 >> 2 143 144#endif 145