linux/arch/arm/lib/backtrace-clang.S
<<
>>
Prefs
   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
 147                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 */
 1671004:           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                bhi     for_each_frame
 201
 2021006:           adr     r0, .Lbad
 203                mov     r1, loglvl
 204                mov     r2, frame
 205                bl      _printk
 206no_frame:       ldmfd   sp!, {r4 - r9, fp, pc}
 207ENDPROC(c_backtrace)
 208                .pushsection __ex_table,"a"
 209                .align  3
 210                .long   1001b, 1006b
 211                .long   1002b, 1006b
 212                .long   1003b, 1006b
 213                .long   1004b, 1006b
 214                .long   1005b, 1006b
 215                .popsection
 216
 217.Lbad:          .asciz  "%sBacktrace aborted due to bad frame pointer <%p>\n"
 218                .align
 219.Lopcode:       .word   0xe92d4800 >> 11        @ stmfd sp!, {... fp, lr}
 220                .word   0x0b000000              @ bl if these bits are set
 221
 222#endif
 223