162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/arch/arm/lib/backtrace-clang.S 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2019 Nathan Huckleberry 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#include <linux/kern_levels.h> 962306a36Sopenharmony_ci#include <linux/linkage.h> 1062306a36Sopenharmony_ci#include <asm/assembler.h> 1162306a36Sopenharmony_ci .text 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* fp is 0 or stack frame */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define frame r4 1662306a36Sopenharmony_ci#define sv_fp r5 1762306a36Sopenharmony_ci#define sv_pc r6 1862306a36Sopenharmony_ci#define mask r7 1962306a36Sopenharmony_ci#define sv_lr r8 2062306a36Sopenharmony_ci#define loglvl r9 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ciENTRY(c_backtrace) 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK) 2562306a36Sopenharmony_ci ret lr 2662306a36Sopenharmony_ciENDPROC(c_backtrace) 2762306a36Sopenharmony_ci#else 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* 3162306a36Sopenharmony_ci * Clang does not store pc or sp in function prologues so we don't know exactly 3262306a36Sopenharmony_ci * where the function starts. 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci * We can treat the current frame's lr as the saved pc and the preceding 3562306a36Sopenharmony_ci * frame's lr as the current frame's lr, but we can't trace the most recent 3662306a36Sopenharmony_ci * call. Inserting a false stack frame allows us to reference the function 3762306a36Sopenharmony_ci * called last in the stacktrace. 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci * If the call instruction was a bl we can look at the callers branch 4062306a36Sopenharmony_ci * instruction to calculate the saved pc. We can recover the pc in most cases, 4162306a36Sopenharmony_ci * but in cases such as calling function pointers we cannot. In this case, 4262306a36Sopenharmony_ci * default to using the lr. This will be some address in the function, but will 4362306a36Sopenharmony_ci * not be the function start. 4462306a36Sopenharmony_ci * 4562306a36Sopenharmony_ci * Unfortunately due to the stack frame layout we can't dump r0 - r3, but these 4662306a36Sopenharmony_ci * are less frequently saved. 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * Stack frame layout: 4962306a36Sopenharmony_ci * <larger addresses> 5062306a36Sopenharmony_ci * saved lr 5162306a36Sopenharmony_ci * frame=> saved fp 5262306a36Sopenharmony_ci * optionally saved caller registers (r4 - r10) 5362306a36Sopenharmony_ci * optionally saved arguments (r0 - r3) 5462306a36Sopenharmony_ci * <top of stack frame> 5562306a36Sopenharmony_ci * <smaller addresses> 5662306a36Sopenharmony_ci * 5762306a36Sopenharmony_ci * Functions start with the following code sequence: 5862306a36Sopenharmony_ci * corrected pc => stmfd sp!, {..., fp, lr} 5962306a36Sopenharmony_ci * add fp, sp, #x 6062306a36Sopenharmony_ci * stmfd sp!, {r0 - r3} (optional) 6162306a36Sopenharmony_ci * 6262306a36Sopenharmony_ci * 6362306a36Sopenharmony_ci * 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci * 6662306a36Sopenharmony_ci * 6762306a36Sopenharmony_ci * The diagram below shows an example stack setup for dump_stack. 6862306a36Sopenharmony_ci * 6962306a36Sopenharmony_ci * The frame for c_backtrace has pointers to the code of dump_stack. This is 7062306a36Sopenharmony_ci * why the frame of c_backtrace is used to for the pc calculation of 7162306a36Sopenharmony_ci * dump_stack. This is why we must move back a frame to print dump_stack. 7262306a36Sopenharmony_ci * 7362306a36Sopenharmony_ci * The stored locals for dump_stack are in dump_stack's frame. This means that 7462306a36Sopenharmony_ci * to fully print dump_stack's frame we need both the frame for dump_stack (for 7562306a36Sopenharmony_ci * locals) and the frame that was called by dump_stack (for pc). 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci * To print locals we must know where the function start is. If we read the 7862306a36Sopenharmony_ci * function prologue opcodes we can determine which variables are stored in the 7962306a36Sopenharmony_ci * stack frame. 8062306a36Sopenharmony_ci * 8162306a36Sopenharmony_ci * To find the function start of dump_stack we can look at the stored LR of 8262306a36Sopenharmony_ci * show_stack. It points at the instruction directly after the bl dump_stack. 8362306a36Sopenharmony_ci * We can then read the offset from the bl opcode to determine where the branch 8462306a36Sopenharmony_ci * takes us. The address calculated must be the start of dump_stack. 8562306a36Sopenharmony_ci * 8662306a36Sopenharmony_ci * c_backtrace frame dump_stack: 8762306a36Sopenharmony_ci * {[LR] } ============| ... 8862306a36Sopenharmony_ci * {[FP] } =======| | bl c_backtrace 8962306a36Sopenharmony_ci * | |=> ... 9062306a36Sopenharmony_ci * {[R4-R10]} | 9162306a36Sopenharmony_ci * {[R0-R3] } | show_stack: 9262306a36Sopenharmony_ci * dump_stack frame | ... 9362306a36Sopenharmony_ci * {[LR] } =============| bl dump_stack 9462306a36Sopenharmony_ci * {[FP] } <=======| |=> ... 9562306a36Sopenharmony_ci * {[R4-R10]} 9662306a36Sopenharmony_ci * {[R0-R3] } 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci stmfd sp!, {r4 - r9, fp, lr} @ Save an extra register 10062306a36Sopenharmony_ci @ to ensure 8 byte alignment 10162306a36Sopenharmony_ci movs frame, r0 @ if frame pointer is zero 10262306a36Sopenharmony_ci beq no_frame @ we have no stack frames 10362306a36Sopenharmony_ci mov loglvl, r2 10462306a36Sopenharmony_ci tst r1, #0x10 @ 26 or 32-bit mode? 10562306a36Sopenharmony_ci moveq mask, #0xfc000003 10662306a36Sopenharmony_ci movne mask, #0 @ mask for 32-bit 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/* 10962306a36Sopenharmony_ci * Switches the current frame to be the frame for dump_stack. 11062306a36Sopenharmony_ci */ 11162306a36Sopenharmony_ci add frame, sp, #24 @ switch to false frame 11262306a36Sopenharmony_cifor_each_frame: tst frame, mask @ Check for address exceptions 11362306a36Sopenharmony_ci bne no_frame 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/* 11662306a36Sopenharmony_ci * sv_fp is the stack frame with the locals for the current considered 11762306a36Sopenharmony_ci * function. 11862306a36Sopenharmony_ci * 11962306a36Sopenharmony_ci * sv_pc is the saved lr frame the frame above. This is a pointer to a code 12062306a36Sopenharmony_ci * address within the current considered function, but it is not the function 12162306a36Sopenharmony_ci * start. This value gets updated to be the function start later if it is 12262306a36Sopenharmony_ci * possible. 12362306a36Sopenharmony_ci */ 12462306a36Sopenharmony_ci1001: ldr sv_pc, [frame, #4] @ get saved 'pc' 12562306a36Sopenharmony_ci1002: ldr sv_fp, [frame, #0] @ get saved fp 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci teq sv_fp, mask @ make sure next frame exists 12862306a36Sopenharmony_ci beq no_frame 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci/* 13162306a36Sopenharmony_ci * sv_lr is the lr from the function that called the current function. This is 13262306a36Sopenharmony_ci * a pointer to a code address in the current function's caller. sv_lr-4 is 13362306a36Sopenharmony_ci * the instruction used to call the current function. 13462306a36Sopenharmony_ci * 13562306a36Sopenharmony_ci * This sv_lr can be used to calculate the function start if the function was 13662306a36Sopenharmony_ci * called using a bl instruction. If the function start can be recovered sv_pc 13762306a36Sopenharmony_ci * is overwritten with the function start. 13862306a36Sopenharmony_ci * 13962306a36Sopenharmony_ci * If the current function was called using a function pointer we cannot 14062306a36Sopenharmony_ci * recover the function start and instead continue with sv_pc as an arbitrary 14162306a36Sopenharmony_ci * value within the current function. If this is the case we cannot print 14262306a36Sopenharmony_ci * registers for the current function, but the stacktrace is still printed 14362306a36Sopenharmony_ci * properly. 14462306a36Sopenharmony_ci */ 14562306a36Sopenharmony_ci1003: ldr sv_lr, [sv_fp, #4] @ get saved lr from next frame 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci1004: ldr r0, [sv_lr, #-4] @ get call instruction 14862306a36Sopenharmony_ci ldr r3, .Lopcode+4 14962306a36Sopenharmony_ci and r2, r3, r0 @ is this a bl call 15062306a36Sopenharmony_ci teq r2, r3 15162306a36Sopenharmony_ci bne finished_setup @ give up if it's not 15262306a36Sopenharmony_ci and r0, #0xffffff @ get call offset 24-bit int 15362306a36Sopenharmony_ci lsl r0, r0, #8 @ sign extend offset 15462306a36Sopenharmony_ci asr r0, r0, #8 15562306a36Sopenharmony_ci ldr sv_pc, [sv_fp, #4] @ get lr address 15662306a36Sopenharmony_ci add sv_pc, sv_pc, #-4 @ get call instruction address 15762306a36Sopenharmony_ci add sv_pc, sv_pc, #8 @ take care of prefetch 15862306a36Sopenharmony_ci add sv_pc, sv_pc, r0, lsl #2@ find function start 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cifinished_setup: 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci bic sv_pc, sv_pc, mask @ mask PC/LR for the mode 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci/* 16562306a36Sopenharmony_ci * Print the function (sv_pc) and where it was called from (sv_lr). 16662306a36Sopenharmony_ci */ 16762306a36Sopenharmony_ci mov r0, sv_pc 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci mov r1, sv_lr 17062306a36Sopenharmony_ci mov r2, frame 17162306a36Sopenharmony_ci bic r1, r1, mask @ mask PC/LR for the mode 17262306a36Sopenharmony_ci mov r3, loglvl 17362306a36Sopenharmony_ci bl dump_backtrace_entry 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/* 17662306a36Sopenharmony_ci * Test if the function start is a stmfd instruction to determine which 17762306a36Sopenharmony_ci * registers were stored in the function prologue. 17862306a36Sopenharmony_ci * 17962306a36Sopenharmony_ci * If we could not recover the sv_pc because we were called through a function 18062306a36Sopenharmony_ci * pointer the comparison will fail and no registers will print. Unwinding will 18162306a36Sopenharmony_ci * continue as if there had been no registers stored in this frame. 18262306a36Sopenharmony_ci */ 18362306a36Sopenharmony_ci1005: ldr r1, [sv_pc, #0] @ if stmfd sp!, {..., fp, lr} 18462306a36Sopenharmony_ci ldr r3, .Lopcode @ instruction exists, 18562306a36Sopenharmony_ci teq r3, r1, lsr #11 18662306a36Sopenharmony_ci ldr r0, [frame] @ locals are stored in 18762306a36Sopenharmony_ci @ the preceding frame 18862306a36Sopenharmony_ci subeq r0, r0, #4 18962306a36Sopenharmony_ci mov r2, loglvl 19062306a36Sopenharmony_ci bleq dump_backtrace_stm @ dump saved registers 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci/* 19362306a36Sopenharmony_ci * If we are out of frames or if the next frame is invalid. 19462306a36Sopenharmony_ci */ 19562306a36Sopenharmony_ci teq sv_fp, #0 @ zero saved fp means 19662306a36Sopenharmony_ci beq no_frame @ no further frames 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci cmp sv_fp, frame @ next frame must be 19962306a36Sopenharmony_ci mov frame, sv_fp @ above the current frame 20062306a36Sopenharmony_ci#ifdef CONFIG_IRQSTACKS 20162306a36Sopenharmony_ci @ 20262306a36Sopenharmony_ci @ Kernel stacks may be discontiguous in memory. If the next 20362306a36Sopenharmony_ci @ frame is below the previous frame, accept it as long as it 20462306a36Sopenharmony_ci @ lives in kernel memory. 20562306a36Sopenharmony_ci @ 20662306a36Sopenharmony_ci cmpls sv_fp, #PAGE_OFFSET 20762306a36Sopenharmony_ci#endif 20862306a36Sopenharmony_ci bhi for_each_frame 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci1006: adr r0, .Lbad 21162306a36Sopenharmony_ci mov r1, loglvl 21262306a36Sopenharmony_ci mov r2, frame 21362306a36Sopenharmony_ci bl _printk 21462306a36Sopenharmony_cino_frame: ldmfd sp!, {r4 - r9, fp, pc} 21562306a36Sopenharmony_ciENDPROC(c_backtrace) 21662306a36Sopenharmony_ci .pushsection __ex_table,"a" 21762306a36Sopenharmony_ci .align 3 21862306a36Sopenharmony_ci .long 1001b, 1006b 21962306a36Sopenharmony_ci .long 1002b, 1006b 22062306a36Sopenharmony_ci .long 1003b, 1006b 22162306a36Sopenharmony_ci .long 1004b, finished_setup 22262306a36Sopenharmony_ci .long 1005b, 1006b 22362306a36Sopenharmony_ci .popsection 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci.Lbad: .asciz "%sBacktrace aborted due to bad frame pointer <%p>\n" 22662306a36Sopenharmony_ci .align 22762306a36Sopenharmony_ci.Lopcode: .word 0xe92d4800 >> 11 @ stmfd sp!, {... fp, lr} 22862306a36Sopenharmony_ci .word 0x0b000000 @ bl if these bits are set 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci#endif 231