• Madhavan T. Venkataraman's avatar
    arm64: Make dump_backtrace() use arch_stack_walk() · 2dad6dc1
    Madhavan T. Venkataraman authored
    To enable RELIABLE_STACKTRACE and LIVEPATCH on arm64, we need to
    substantially rework arm64's unwinding code. As part of this, we want to
    minimize the set of unwind interfaces we expose, and avoid open-coding
    of unwind logic.
    
    Currently, dump_backtrace() walks the stack of the current task or a
    blocked task by calling stact_backtrace() and iterating unwind steps
    using unwind_frame(). This can be written more simply in terms of
    arch_stack_walk(), considering three distinct cases:
    
    1) When unwinding a blocked task, start_backtrace() is called with the
       blocked task's saved PC and FP, and the unwind proceeds immediately
       from this point without skipping any entries. This is functionally
       equivalent to calling arch_stack_walk() with the blocked task, which
       will start with the task's saved PC and FP.
    
       There is no functional change to this case.
    
    2) When unwinding the current task without regs, start_backtrace() is
       called with dump_backtrace() as the PC and __builtin_frame_address(0)
       as the next frame, and the unwind proceeds immediately without
       skipping. This is *almost* functionally equivalent to calling
       arch_stack_walk() for the current task, which will start with its
       caller (i.e. an offset into dump_backtrace()) as the PC, and the
       callers frame record as the next frame.
    
       The only difference being that dump_backtrace() will be reported with
       an offset (which is strictly more correct than currently). Otherwise
       there is no functional cahnge to this case.
    
    3) When unwinding the current task with regs, start_backtrace() is
       called with dump_backtrace() as the PC and __builtin_frame_address(0)
       as the next frame, and the unwind is performed silently until the
       next frame is the frame pointed to by regs->fp. Reporting starts
       from regs->pc and continues from the frame in regs->fp.
    
       Historically, this pre-unwind was necessary to correctly record
       return addresses rewritten by the ftrace graph calller, but this is
       no longer necessary as these are now recovered using the FP since
       commit:
    
       c6d3cd32 ("arm64: ftrace: use HAVE_FUNCTION_GRAPH_RET_ADDR_PTR")
    
       This pre-unwind is not necessary to recover return addresses
       rewritten by kretprobes, which historically were not recovered, and
       are now recovered using the FP since commit:
    
       cd9bc2c9 ("arm64: Recover kretprobe modified return address in stacktrace")
    
       Thus, this is functionally equivalent to calling arch_stack_walk()
       with the current task and regs, which will start with regs->pc as the
       PC and regs->fp as the next frame, without a pre-unwind.
    
    This patch makes dump_backtrace() use arch_stack_walk(). This simplifies
    dump_backtrace() and will permit subsequent changes to the unwind code.
    
    Aside from the improved reporting when unwinding current without regs,
    there should be no functional change as a result of this patch.
    Signed-off-by: default avatarMadhavan T. Venkataraman <madvenka@linux.microsoft.com>
    [Mark: elaborate commit message]
    Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
    Reviewed-by: default avatarMark Brown <broonie@kernel.org>
    Link: https://lore.kernel.org/r/20211129142849.3056714-9-mark.rutland@arm.comSigned-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    2dad6dc1
stacktrace.c 5.2 KB