Commit 41918ec8 authored by Ard Biesheuvel's avatar Ard Biesheuvel
Browse files

ARM: ftrace: enable the graph tracer with the EABI unwinder



Enable the function graph tracer in combination with the EABI unwinder,
so that Thumb2 builds or Clang ARM builds can make use of it.

This involves using the unwinder to locate the return address of an
instrumented function on the stack, so that it can be overridden and
made to refer to the ftrace handling routines that need to be called at
function return.

Given that for these builds, it is not guaranteed that the value of the
link register is stored on the stack, fall back to the stack slot that
will be used by the ftrace exit code to restore LR in the instrumented
function's execution context.

Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
Reviewed-by: default avatarSteven Rostedt (Google) <rostedt@goodmis.org>
parent 538b9265
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ config ARM
	select HAVE_EXIT_THREAD
	select HAVE_FAST_GUP if ARM_LPAE
	select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL
	select HAVE_FUNCTION_GRAPH_TRACER if !THUMB2_KERNEL && !CC_IS_CLANG
	select HAVE_FUNCTION_GRAPH_TRACER
	select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !(THUMB2_KERNEL && CC_IS_CLANG)
	select HAVE_FUTEX_CMPXCHG if FUTEX
	select HAVE_GCC_PLUGINS
+1 −1
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ config UNWINDER_FRAME_POINTER

config UNWINDER_ARM
	bool "ARM EABI stack unwinder"
	depends on AEABI && !FUNCTION_GRAPH_TRACER
	depends on AEABI
	# https://github.com/ClangBuiltLinux/linux/issues/732
	depends on !LD_IS_LLD || LLD_VERSION >= 110000
	select ARM_UNWIND
+0 −18
Original line number Diff line number Diff line
@@ -35,26 +35,8 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)

#ifndef __ASSEMBLY__

#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
/*
 * return_address uses walk_stackframe to do it's work.  If both
 * CONFIG_FRAME_POINTER=y and CONFIG_ARM_UNWIND=y walk_stackframe uses unwind
 * information.  For this to work in the function tracer many functions would
 * have to be marked with __notrace.  So for now just depend on
 * !CONFIG_ARM_UNWIND.
 */

void *return_address(unsigned int);

#else

static inline void *return_address(unsigned int level)
{
	return NULL;
}

#endif

#define ftrace_return_address(n) return_address(n)

#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
+1 −4
Original line number Diff line number Diff line
@@ -25,10 +25,7 @@ obj-y := elf.o entry-common.o irq.o opcodes.o \
KASAN_SANITIZE_stacktrace.o := n
KASAN_SANITIZE_traps.o := n

ifneq ($(CONFIG_ARM_UNWIND),y)
obj-$(CONFIG_FRAME_POINTER)	+= return_address.o
endif

obj-y				+= return_address.o
obj-$(CONFIG_ATAGS)		+= atags_parse.o
obj-$(CONFIG_ATAGS_PROC)	+= atags_proc.o
obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += atags_compat.o
+20 −8
Original line number Diff line number Diff line
@@ -100,7 +100,8 @@ ftrace_regs_call:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	.globl ftrace_graph_regs_call
ftrace_graph_regs_call:
	mov	r0, r0
ARM(	mov	r0, r0	)
THUMB(	nop.w		)
#endif

	@ pop saved regs
@@ -112,13 +113,18 @@ ftrace_graph_regs_call:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
.macro __ftrace_graph_regs_caller

#ifdef CONFIG_UNWINDER_FRAME_POINTER
	sub	r0, fp, #4		@ lr of instrumented routine (parent)
#else
	add	r0, sp, #S_LR
#endif

	@ called from __ftrace_regs_caller
	ldr	r1, [sp, #S_PC]		@ instrumented routine (func)
	mcount_adjust_addr	r1, r1

	mov	r2, fp			@ frame pointer
	mov	r2, fpreg		@ frame pointer
	add	r3, sp, #PT_REGS_SIZE
	bl	prepare_ftrace_return

	@ pop registers saved in ftrace_regs_caller
@@ -149,14 +155,19 @@ ftrace_call\suffix:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	.globl ftrace_graph_call\suffix
ftrace_graph_call\suffix:
	mov	r0, r0
ARM(	mov	r0, r0	)
THUMB(	nop.w		)
#endif

	mcount_exit
.endm

.macro __ftrace_graph_caller
#ifdef CONFIG_UNWINDER_FRAME_POINTER
	sub	r0, fp, #4		@ &lr of instrumented routine (&parent)
#else
	add	r0, sp, #20
#endif
#ifdef CONFIG_DYNAMIC_FTRACE
	@ called from __ftrace_caller, saved in mcount_enter
	ldr	r1, [sp, #16]		@ instrumented routine (func)
@@ -165,7 +176,8 @@ ftrace_graph_call\suffix:
	@ called from __mcount, untouched in lr
	mcount_adjust_addr	r1, lr	@ instrumented routine (func)
#endif
	mov	r2, fp			@ frame pointer
	mov	r2, fpreg		@ frame pointer
	add	r3, sp, #24
	bl	prepare_ftrace_return
	mcount_exit
.endm
@@ -244,14 +256,14 @@ ENDPROC(ftrace_graph_regs_caller)
.purgem mcount_exit

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	.globl return_to_handler
return_to_handler:
ENTRY(return_to_handler)
	stmdb	sp!, {r0-r3}
	add	r0, sp, #16		@ sp at exit of instrumented routine
	bl	ftrace_return_to_handler
	mov	lr, r0			@ r0 has real ret addr
	ldmia	sp!, {r0-r3}
	ret	lr
ENDPROC(return_to_handler)
#endif

ENTRY(ftrace_stub)
Loading