Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  *  linux/arch/arm/lib/backtrace-clang.S
0004  *
0005  *  Copyright (C) 2019 Nathan Huckleberry
0006  *
0007  */
0008 #include <linux/kern_levels.h>
0009 #include <linux/linkage.h>
0010 #include <asm/assembler.h>
0011         .text
0012 
0013 /* fp is 0 or stack frame */
0014 
0015 #define frame   r4
0016 #define sv_fp   r5
0017 #define sv_pc   r6
0018 #define mask    r7
0019 #define sv_lr   r8
0020 #define loglvl  r9
0021 
0022 ENTRY(c_backtrace)
0023 
0024 #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
0025         ret lr
0026 ENDPROC(c_backtrace)
0027 #else
0028 
0029 
0030 /*
0031  * Clang does not store pc or sp in function prologues so we don't know exactly
0032  * where the function starts.
0033  *
0034  * We can treat the current frame's lr as the saved pc and the preceding
0035  * frame's lr as the current frame's lr, but we can't trace the most recent
0036  * call.  Inserting a false stack frame allows us to reference the function
0037  * called last in the stacktrace.
0038  *
0039  * If the call instruction was a bl we can look at the callers branch
0040  * instruction to calculate the saved pc.  We can recover the pc in most cases,
0041  * but in cases such as calling function pointers we cannot. In this case,
0042  * default to using the lr. This will be some address in the function, but will
0043  * not be the function start.
0044  *
0045  * Unfortunately due to the stack frame layout we can't dump r0 - r3, but these
0046  * are less frequently saved.
0047  *
0048  * Stack frame layout:
0049  *      <larger addresses>
0050  *      saved lr
0051  *  frame=> saved fp
0052  *      optionally saved caller registers (r4 - r10)
0053  *      optionally saved arguments (r0 - r3)
0054  *      <top of stack frame>
0055  *      <smaller addresses>
0056  *
0057  * Functions start with the following code sequence:
0058  * corrected pc =>  stmfd sp!, {..., fp, lr}
0059  *      add fp, sp, #x
0060  *      stmfd sp!, {r0 - r3} (optional)
0061  *
0062  *
0063  *
0064  *
0065  *
0066  *
0067  * The diagram below shows an example stack setup for dump_stack.
0068  *
0069  * The frame for c_backtrace has pointers to the code of dump_stack. This is
0070  * why the frame of c_backtrace is used to for the pc calculation of
0071  * dump_stack. This is why we must move back a frame to print dump_stack.
0072  *
0073  * The stored locals for dump_stack are in dump_stack's frame. This means that
0074  * to fully print dump_stack's frame we need both the frame for dump_stack (for
0075  * locals) and the frame that was called by dump_stack (for pc).
0076  *
0077  * To print locals we must know where the function start is. If we read the
0078  * function prologue opcodes we can determine which variables are stored in the
0079  * stack frame.
0080  *
0081  * To find the function start of dump_stack we can look at the stored LR of
0082  * show_stack. It points at the instruction directly after the bl dump_stack.
0083  * We can then read the offset from the bl opcode to determine where the branch
0084  * takes us.  The address calculated must be the start of dump_stack.
0085  *
0086  * c_backtrace frame           dump_stack:
0087  * {[LR]    }  ============|   ...
0088  * {[FP]    }  =======|    |   bl c_backtrace
0089  *                    |    |=> ...
0090  * {[R4-R10]}         |
0091  * {[R0-R3] }         |        show_stack:
0092  * dump_stack frame   |        ...
0093  * {[LR]    } =============|   bl dump_stack
0094  * {[FP]    } <=======|    |=> ...
0095  * {[R4-R10]}
0096  * {[R0-R3] }
0097  */
0098 
0099         stmfd   sp!, {r4 - r9, fp, lr}  @ Save an extra register
0100                         @ to ensure 8 byte alignment
0101         movs    frame, r0       @ if frame pointer is zero
0102         beq no_frame        @ we have no stack frames
0103         mov loglvl, r2
0104         tst r1, #0x10       @ 26 or 32-bit mode?
0105         moveq   mask, #0xfc000003
0106         movne   mask, #0        @ mask for 32-bit
0107 
0108 /*
0109  * Switches the current frame to be the frame for dump_stack.
0110  */
0111         add frame, sp, #24      @ switch to false frame
0112 for_each_frame: tst frame, mask     @ Check for address exceptions
0113         bne no_frame
0114 
0115 /*
0116  * sv_fp is the stack frame with the locals for the current considered
0117  * function.
0118  *
0119  * sv_pc is the saved lr frame the frame above. This is a pointer to a code
0120  * address within the current considered function, but it is not the function
0121  * start. This value gets updated to be the function start later if it is
0122  * possible.
0123  */
0124 1001:       ldr sv_pc, [frame, #4]  @ get saved 'pc'
0125 1002:       ldr sv_fp, [frame, #0]  @ get saved fp
0126 
0127         teq sv_fp, mask     @ make sure next frame exists
0128         beq no_frame
0129 
0130 /*
0131  * sv_lr is the lr from the function that called the current function. This is
0132  * a pointer to a code address in the current function's caller.  sv_lr-4 is
0133  * the instruction used to call the current function.
0134  *
0135  * This sv_lr can be used to calculate the function start if the function was
0136  * called using a bl instruction. If the function start can be recovered sv_pc
0137  * is overwritten with the function start.
0138  *
0139  * If the current function was called using a function pointer we cannot
0140  * recover the function start and instead continue with sv_pc as an arbitrary
0141  * value within the current function. If this is the case we cannot print
0142  * registers for the current function, but the stacktrace is still printed
0143  * properly.
0144  */
0145 1003:       ldr sv_lr, [sv_fp, #4]  @ get saved lr from next frame
0146 
0147 1004:       ldr r0, [sv_lr, #-4]    @ get call instruction
0148         ldr r3, .Lopcode+4
0149         and r2, r3, r0      @ is this a bl call
0150         teq r2, r3
0151         bne finished_setup      @ give up if it's not
0152         and r0, #0xffffff       @ get call offset 24-bit int
0153         lsl r0, r0, #8      @ sign extend offset
0154         asr r0, r0, #8
0155         ldr sv_pc, [sv_fp, #4]  @ get lr address
0156         add sv_pc, sv_pc, #-4   @ get call instruction address
0157         add sv_pc, sv_pc, #8    @ take care of prefetch
0158         add sv_pc, sv_pc, r0, lsl #2@ find function start
0159 
0160 finished_setup:
0161 
0162         bic sv_pc, sv_pc, mask  @ mask PC/LR for the mode
0163 
0164 /*
0165  * Print the function (sv_pc) and where it was called from (sv_lr).
0166  */
0167         mov r0, sv_pc
0168 
0169         mov r1, sv_lr
0170         mov r2, frame
0171         bic r1, r1, mask        @ mask PC/LR for the mode
0172         mov r3, loglvl
0173         bl  dump_backtrace_entry
0174 
0175 /*
0176  * Test if the function start is a stmfd instruction to determine which
0177  * registers were stored in the function prologue.
0178  *
0179  * If we could not recover the sv_pc because we were called through a function
0180  * pointer the comparison will fail and no registers will print. Unwinding will
0181  * continue as if there had been no registers stored in this frame.
0182  */
0183 1005:       ldr r1, [sv_pc, #0]     @ if stmfd sp!, {..., fp, lr}
0184         ldr r3, .Lopcode        @ instruction exists,
0185         teq r3, r1, lsr #11
0186         ldr r0, [frame]     @ locals are stored in
0187                         @ the preceding frame
0188         subeq   r0, r0, #4
0189         mov r2, loglvl
0190         bleq    dump_backtrace_stm  @ dump saved registers
0191 
0192 /*
0193  * If we are out of frames or if the next frame is invalid.
0194  */
0195         teq sv_fp, #0       @ zero saved fp means
0196         beq no_frame        @ no further frames
0197 
0198         cmp sv_fp, frame        @ next frame must be
0199         mov frame, sv_fp        @ above the current frame
0200 #ifdef CONFIG_IRQSTACKS
0201         @
0202         @ Kernel stacks may be discontiguous in memory. If the next
0203         @ frame is below the previous frame, accept it as long as it
0204         @ lives in kernel memory.
0205         @
0206         cmpls   sv_fp, #PAGE_OFFSET
0207 #endif
0208         bhi for_each_frame
0209 
0210 1006:       adr r0, .Lbad
0211         mov r1, loglvl
0212         mov r2, frame
0213         bl  _printk
0214 no_frame:   ldmfd   sp!, {r4 - r9, fp, pc}
0215 ENDPROC(c_backtrace)
0216         .pushsection __ex_table,"a"
0217         .align  3
0218         .long   1001b, 1006b
0219         .long   1002b, 1006b
0220         .long   1003b, 1006b
0221         .long   1004b, finished_setup
0222         .long   1005b, 1006b
0223         .popsection
0224 
0225 .Lbad:      .asciz  "%sBacktrace aborted due to bad frame pointer <%p>\n"
0226         .align
0227 .Lopcode:   .word   0xe92d4800 >> 11    @ stmfd sp!, {... fp, lr}
0228         .word   0x0b000000      @ bl if these bits are set
0229 
0230 #endif