From: Weinan Liu <[email protected]>

DWARF CFI (Call Frame Information) specifies how to recover the return
address and callee-saved registers at each PC in a given function.
Compilers are able to generate the CFI annotations when they compile
the code to assembly language. For handcrafted assembly, we need to
annotate them by hand.

Annotate minimal CFI to enable stacktracing using SFrame for kernel
exception entries through el1*_64_*() paths and irq entries through
call_on_irq_stack()

Signed-off-by: Weinan Liu <[email protected]>
Suggested-by: Jens Remus <[email protected]>
Reviewed-by: Jens Remus <[email protected]>
Signed-off-by: Dylan Hatch <[email protected]>
---
 arch/arm64/kernel/entry.S | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index f8018b5c1f9a..dc55b0b19cfa 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -30,6 +30,12 @@
 #include <asm/asm-uaccess.h>
 #include <asm/unistd.h>
 
+/*
+ * Do not generate .eh_frame.  Only generate .debug_frame and optionally
+ * .sframe (via assembler option --gsframe[-N]).
+ */
+       .cfi_sections .debug_frame
+
        .macro  clear_gp_regs
        .irp    
n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29
        mov     x\n, xzr
@@ -575,7 +581,16 @@ SYM_CODE_START_LOCAL(el\el\ht\()_\regsize\()_\label)
        .if \el == 0
        b       ret_to_user
        .else
+       /*
+        * Minimal DWARF CFI for unwinding across the call above.
+        * Enable unwinding for el1*_64_*() path only.
+        */
+       .cfi_startproc
+       .cfi_def_cfa_offset PT_REGS_SIZE
+       .cfi_offset 29, S_FP - PT_REGS_SIZE
+       .cfi_offset 30, S_LR - PT_REGS_SIZE
        b       ret_to_kernel
+       .cfi_endproc
        .endif
 SYM_CODE_END(el\el\ht\()_\regsize\()_\label)
        .endm
@@ -872,6 +887,7 @@ NOKPROBE(ret_from_fork)
  * Calls func(regs) using this CPU's irq stack and shadow irq stack.
  */
 SYM_FUNC_START(call_on_irq_stack)
+       .cfi_startproc
        save_and_disable_daif x9
 #ifdef CONFIG_SHADOW_CALL_STACK
        get_current_task x16
@@ -882,6 +898,9 @@ SYM_FUNC_START(call_on_irq_stack)
        /* Create a frame record to save our LR and SP (implicit in FP) */
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
+       .cfi_def_cfa 29, 16
+       .cfi_offset 29, -16
+       .cfi_offset 30, -8
 
        ldr_this_cpu x16, irq_stack_ptr, x17
 
@@ -897,9 +916,13 @@ SYM_FUNC_START(call_on_irq_stack)
         */
        mov     sp, x29
        ldp     x29, x30, [sp], #16
+       .cfi_restore 29
+       .cfi_restore 30
+       .cfi_def_cfa 31, 0
        scs_load_current
        restore_irq x9
        ret
+       .cfi_endproc
 SYM_FUNC_END(call_on_irq_stack)
 NOKPROBE(call_on_irq_stack)
 
-- 
2.54.0.545.g6539524ca2-goog


Reply via email to