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