1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
| /*
| * linux/arch/unicore32/lib/backtrace.S
| *
| * Code specific to PKUnity SoC and UniCore ISA
| *
| * Copyright (C) 2001-2010 GUAN Xue-tao
| *
| * 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.
| */
| #include <linux/linkage.h>
| #include <asm/assembler.h>
| .text
|
| @ fp is 0 or stack frame
|
| #define frame v4
| #define sv_fp v5
| #define sv_pc v6
| #define offset v8
|
| ENTRY(__backtrace)
| mov r0, fp
|
| ENTRY(c_backtrace)
|
| #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
| mov pc, lr
| ENDPROC(__backtrace)
| ENDPROC(c_backtrace)
| #else
| stm.w (v4 - v8, lr), [sp-] @ Save an extra register
| @ so we have a location...
| mov.a frame, r0 @ if frame pointer is zero
| beq no_frame @ we have no stack frames
|
| 1: stm.w (pc), [sp-] @ calculate offset of PC stored
| ldw.w r0, [sp]+, #4 @ by stmfd for this CPU
| adr r1, 1b
| sub offset, r0, r1
|
| /*
| * Stack frame layout:
| * optionally saved caller registers (r4 - r10)
| * saved fp
| * saved sp
| * saved lr
| * frame => saved pc
| * optionally saved arguments (r0 - r3)
| * saved sp => <next word>
| *
| * Functions start with the following code sequence:
| * mov ip, sp
| * stm.w (r0 - r3), [sp-] (optional)
| * corrected pc => stm.w sp, (..., fp, ip, lr, pc)
| */
| for_each_frame:
|
| 1001: ldw sv_pc, [frame+], #0 @ get saved pc
| 1002: ldw sv_fp, [frame+], #-12 @ get saved fp
|
| sub sv_pc, sv_pc, offset @ Correct PC for prefetching
|
| 1003: ldw r2, [sv_pc+], #-4 @ if stmfd sp, {args} exists,
| ldw r3, .Ldsi+4 @ adjust saved 'pc' back one
| cxor.a r3, r2 >> #14 @ instruction
| beq 201f
| sub r0, sv_pc, #4 @ allow for mov
| b 202f
| 201:
| sub r0, sv_pc, #8 @ allow for mov + stmia
| 202:
| ldw r1, [frame+], #-4 @ get saved lr
| mov r2, frame
| b.l dump_backtrace_entry
|
| ldw r1, [sv_pc+], #-4 @ if stmfd sp, {args} exists,
| ldw r3, .Ldsi+4
| cxor.a r3, r1 >> #14
| bne 1004f
| ldw r0, [frame+], #-8 @ get sp
| sub r0, r0, #4 @ point at the last arg
| b.l .Ldumpstm @ dump saved registers
|
| 1004: ldw r1, [sv_pc+], #0 @ if stmfd {, fp, ip, lr, pc}
| ldw r3, .Ldsi @ instruction exists,
| cxor.a r3, r1 >> #14
| bne 201f
| sub r0, frame, #16
| b.l .Ldumpstm @ dump saved registers
| 201:
| cxor.a sv_fp, #0 @ zero saved fp means
| beq no_frame @ no further frames
|
| csub.a sv_fp, frame @ next frame must be
| mov frame, sv_fp @ above the current frame
| bua for_each_frame
|
| 1006: adr r0, .Lbad
| mov r1, frame
| b.l printk
| no_frame: ldm.w (v4 - v8, pc), [sp]+
| ENDPROC(__backtrace)
| ENDPROC(c_backtrace)
|
| .pushsection __ex_table,"a"
| .align 3
| .long 1001b, 1006b
| .long 1002b, 1006b
| .long 1003b, 1006b
| .long 1004b, 1006b
| .popsection
|
| #define instr v4
| #define reg v5
| #define stack v6
|
| .Ldumpstm: stm.w (instr, reg, stack, v7, lr), [sp-]
| mov stack, r0
| mov instr, r1
| mov reg, #14
| mov v7, #0
| 1: mov r3, #1
| csub.a reg, #8
| bne 201f
| sub reg, reg, #3
| 201:
| cand.a instr, r3 << reg
| beq 2f
| add v7, v7, #1
| cxor.a v7, #6
| cmoveq v7, #1
| cmoveq r1, #'\n'
| cmovne r1, #' '
| ldw.w r3, [stack]+, #-4
| mov r2, reg
| csub.a r2, #8
| bsl 201f
| sub r2, r2, #3
| 201:
| cand.a instr, #0x40 @ if H is 1, high 16 regs
| beq 201f
| add r2, r2, #0x10 @ so r2 need add 16
| 201:
| adr r0, .Lfp
| b.l printk
| 2: sub.a reg, reg, #1
| bns 1b
| cxor.a v7, #0
| beq 201f
| adr r0, .Lcr
| b.l printk
| 201: ldm.w (instr, reg, stack, v7, pc), [sp]+
|
| .Lfp: .asciz "%cr%d:%08x"
| .Lcr: .asciz "\n"
| .Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n"
| .align
| .Ldsi: .word 0x92eec000 >> 14 @ stm.w sp, (... fp, ip, lr, pc)
| .word 0x92e10000 >> 14 @ stm.w sp, ()
|
| #endif
|
|