1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * linux/arch/arm/lib/backtrace-clang.S
4 *
5 * Copyright (C) 2019 Nathan Huckleberry
6 *
7 */
8#include <linux/kern_levels.h>
9#include <linux/linkage.h>
10#include <asm/assembler.h>
11 .text
12
13/* fp is 0 or stack frame */
14
15#define frame r4
16#define sv_fp r5
17#define sv_pc r6
18#define mask r7
19#define sv_lr r8
20#define loglvl r9
21
22ENTRY(c_backtrace)
23
24#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
25 ret lr
26ENDPROC(c_backtrace)
27#else
28
29
30/*
31 * Clang does not store pc or sp in function prologues so we don't know exactly
32 * where the function starts.
33 *
34 * We can treat the current frame's lr as the saved pc and the preceding
35 * frame's lr as the current frame's lr, but we can't trace the most recent
36 * call. Inserting a false stack frame allows us to reference the function
37 * called last in the stacktrace.
38 *
39 * If the call instruction was a bl we can look at the callers branch
40 * instruction to calculate the saved pc. We can recover the pc in most cases,
41 * but in cases such as calling function pointers we cannot. In this case,
42 * default to using the lr. This will be some address in the function, but will
43 * not be the function start.
44 *
45 * Unfortunately due to the stack frame layout we can't dump r0 - r3, but these
46 * are less frequently saved.
47 *
48 * Stack frame layout:
49 * <larger addresses>
50 * saved lr
51 * frame=> saved fp
52 * optionally saved caller registers (r4 - r10)
53 * optionally saved arguments (r0 - r3)
54 * <top of stack frame>
55 * <smaller addresses>
56 *
57 * Functions start with the following code sequence:
58 * corrected pc => stmfd sp!, {..., fp, lr}
59 * add fp, sp, #x
60 * stmfd sp!, {r0 - r3} (optional)
61 *
62 *
63 *
64 *
65 *
66 *
67 * The diagram below shows an example stack setup for dump_stack.
68 *
69 * The frame for c_backtrace has pointers to the code of dump_stack. This is
70 * why the frame of c_backtrace is used to for the pc calculation of
71 * dump_stack. This is why we must move back a frame to print dump_stack.
72 *
73 * The stored locals for dump_stack are in dump_stack's frame. This means that
74 * to fully print dump_stack's frame we need both the frame for dump_stack (for
75 * locals) and the frame that was called by dump_stack (for pc).
76 *
77 * To print locals we must know where the function start is. If we read the
78 * function prologue opcodes we can determine which variables are stored in the
79 * stack frame.
80 *
81 * To find the function start of dump_stack we can look at the stored LR of
82 * show_stack. It points at the instruction directly after the bl dump_stack.
83 * We can then read the offset from the bl opcode to determine where the branch
84 * takes us. The address calculated must be the start of dump_stack.
85 *
86 * c_backtrace frame dump_stack:
87 * {[LR] } ============| ...
88 * {[FP] } =======| | bl c_backtrace
89 * | |=> ...
90 * {[R4-R10]} |
91 * {[R0-R3] } | show_stack:
92 * dump_stack frame | ...
93 * {[LR] } =============| bl dump_stack
94 * {[FP] } <=======| |=> ...
95 * {[R4-R10]}
96 * {[R0-R3] }
97 */
98
99 stmfd sp!, {r4 - r9, fp, lr} @ Save an extra register
100 @ to ensure 8 byte alignment
101 movs frame, r0 @ if frame pointer is zero
102 beq no_frame @ we have no stack frames
103 mov loglvl, r2
104 tst r1, #0x10 @ 26 or 32-bit mode?
105 moveq mask, #0xfc000003
106 movne mask, #0 @ mask for 32-bit
107
108/*
109 * Switches the current frame to be the frame for dump_stack.
110 */
111 add frame, sp, #24 @ switch to false frame
112for_each_frame: tst frame, mask @ Check for address exceptions
113 bne no_frame
114
115/*
116 * sv_fp is the stack frame with the locals for the current considered
117 * function.
118 *
119 * sv_pc is the saved lr frame the frame above. This is a pointer to a code
120 * address within the current considered function, but it is not the function
121 * start. This value gets updated to be the function start later if it is
122 * possible.
123 */
1241001: ldr sv_pc, [frame, #4] @ get saved 'pc'
1251002: ldr sv_fp, [frame, #0] @ get saved fp
126
127 teq sv_fp, mask @ make sure next frame exists
128 beq no_frame
129
130/*
131 * sv_lr is the lr from the function that called the current function. This is
132 * a pointer to a code address in the current function's caller. sv_lr-4 is
133 * the instruction used to call the current function.
134 *
135 * This sv_lr can be used to calculate the function start if the function was
136 * called using a bl instruction. If the function start can be recovered sv_pc
137 * is overwritten with the function start.
138 *
139 * If the current function was called using a function pointer we cannot
140 * recover the function start and instead continue with sv_pc as an arbitrary
141 * value within the current function. If this is the case we cannot print
142 * registers for the current function, but the stacktrace is still printed
143 * properly.
144 */
1451003: ldr sv_lr, [sv_fp, #4] @ get saved lr from next frame
146
1471004: ldr r0, [sv_lr, #-4] @ get call instruction
148 ldr r3, .Lopcode+4
149 and r2, r3, r0 @ is this a bl call
150 teq r2, r3
151 bne finished_setup @ give up if it's not
152 and r0, #0xffffff @ get call offset 24-bit int
153 lsl r0, r0, #8 @ sign extend offset
154 asr r0, r0, #8
155 ldr sv_pc, [sv_fp, #4] @ get lr address
156 add sv_pc, sv_pc, #-4 @ get call instruction address
157 add sv_pc, sv_pc, #8 @ take care of prefetch
158 add sv_pc, sv_pc, r0, lsl #2@ find function start
159
160finished_setup:
161
162 bic sv_pc, sv_pc, mask @ mask PC/LR for the mode
163
164/*
165 * Print the function (sv_pc) and where it was called from (sv_lr).
166 */
167 mov r0, sv_pc
168
169 mov r1, sv_lr
170 mov r2, frame
171 bic r1, r1, mask @ mask PC/LR for the mode
172 mov r3, loglvl
173 bl dump_backtrace_entry
174
175/*
176 * Test if the function start is a stmfd instruction to determine which
177 * registers were stored in the function prologue.
178 *
179 * If we could not recover the sv_pc because we were called through a function
180 * pointer the comparison will fail and no registers will print. Unwinding will
181 * continue as if there had been no registers stored in this frame.
182 */
1831005: ldr r1, [sv_pc, #0] @ if stmfd sp!, {..., fp, lr}
184 ldr r3, .Lopcode @ instruction exists,
185 teq r3, r1, lsr #11
186 ldr r0, [frame] @ locals are stored in
187 @ the preceding frame
188 subeq r0, r0, #4
189 mov r2, loglvl
190 bleq dump_backtrace_stm @ dump saved registers
191
192/*
193 * If we are out of frames or if the next frame is invalid.
194 */
195 teq sv_fp, #0 @ zero saved fp means
196 beq no_frame @ no further frames
197
198 cmp sv_fp, frame @ next frame must be
199 mov frame, sv_fp @ above the current frame
200#ifdef CONFIG_IRQSTACKS
201 @
202 @ Kernel stacks may be discontiguous in memory. If the next
203 @ frame is below the previous frame, accept it as long as it
204 @ lives in kernel memory.
205 @
206 cmpls sv_fp, #PAGE_OFFSET
207#endif
208 bhi for_each_frame
209
2101006: adr r0, .Lbad
211 mov r1, loglvl
212 mov r2, frame
213 bl _printk
214no_frame: ldmfd sp!, {r4 - r9, fp, pc}
215ENDPROC(c_backtrace)
216 .pushsection __ex_table,"a"
217 .align 3
218 .long 1001b, 1006b
219 .long 1002b, 1006b
220 .long 1003b, 1006b
221 .long 1004b, finished_setup
222 .long 1005b, 1006b
223 .popsection
224
225.Lbad: .asciz "%sBacktrace aborted due to bad frame pointer <%p>\n"
226 .align
227.Lopcode: .word 0xe92d4800 >> 11 @ stmfd sp!, {... fp, lr}
228 .word 0x0b000000 @ bl if these bits are set
229
230#endif
231

source code of linux/arch/arm/lib/backtrace-clang.S