Linux 5.7.7
[linux/fpc-iii.git] / arch / arm / lib / backtrace-clang.S
blob2ff375144b55b0347240441205f476aae1a837cc
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
13 /* fp is 0 or stack frame */
15 #define frame   r4
16 #define sv_fp   r5
17 #define sv_pc   r6
18 #define mask    r7
19 #define sv_lr   r8
21 ENTRY(c_backtrace)
23 #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
24                 ret     lr
25 ENDPROC(c_backtrace)
26 #else
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  */
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
107  * Switches the current frame to be the frame for dump_stack.
108  */
109                 add     frame, sp, #24          @ switch to false frame
110 for_each_frame: tst     frame, mask             @ Check for address exceptions
111                 bne     no_frame
114  * sv_fp is the stack frame with the locals for the current considered
115  * function.
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  */
122 1001:           ldr     sv_pc, [frame, #4]      @ get saved 'pc'
123 1002:           ldr     sv_fp, [frame, #0]      @ get saved fp
125                 teq     sv_fp, mask             @ make sure next frame exists
126                 beq     no_frame
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.
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.
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  */
143 1003:           ldr     sv_lr, [sv_fp, #4]      @ get saved lr from next frame
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
158 finished_setup:
160                 bic     sv_pc, sv_pc, mask      @ mask PC/LR for the mode
163  * Print the function (sv_pc) and where it was called from (sv_lr).
164  */
165 1004:           mov     r0, sv_pc
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
173  * Test if the function start is a stmfd instruction to determine which
174  * registers were stored in the function prologue.
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  */
180 1005:           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
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
194                 cmp     sv_fp, frame            @ next frame must be
195                 mov     frame, sv_fp            @ above the current frame
196                 bhi     for_each_frame
198 1006:           adr     r0, .Lbad
199                 mov     r1, frame
200                 bl      printk
201 no_frame:       ldmfd   sp!, {r4 - r9, fp, pc}
202 ENDPROC(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
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
217 #endif