[PATCH] ARM: Implement functions for HAVE_FUNCTION_ARG_ACCESS_API
From: Andrew Jeffery
Date: Tue May 19 2020 - 10:32:11 EST
This allows extraction of kernel function arguments via kprobes on ARM.
Based on the arm64 implementation and adapted for the 32-bit AAPCS.
Signed-off-by: Andrew Jeffery <andrew@xxxxxxxx>
---
The description for HAVE_FUNCTION_ARG_ACCESS_API was pretty vague on what was
required. I've implemented enough to enable argument extraction for kprobes; is
there anything else needed to satisfy HAVE_FUNCTION_ARG_ACCESS_API?
arch/arm/Kconfig | 1 +
arch/arm/include/asm/ptrace.h | 24 ++++++++++++++++++++++++
2 files changed, 25 insertions(+)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c77c93c485a0..d82f80845e03 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -82,6 +82,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_ARG_ACCESS_API
select HAVE_FUNCTION_GRAPH_TRACER if !THUMB2_KERNEL && !CC_IS_CLANG
select HAVE_FUNCTION_TRACER if !XIP_KERNEL && (CC_IS_GCC || CLANG_VERSION >= 100000)
select HAVE_GCC_PLUGINS
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 91d6b7856be4..71e7649deac9 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -149,6 +149,30 @@ static inline unsigned long regs_get_register(struct pt_regs *regs,
return *(unsigned long *)((unsigned long)regs + offset);
}
+/*
+ * Read a register given an architectural register index r.
+ */
+static inline unsigned long pt_regs_read_reg(const struct pt_regs *regs, int r)
+{
+ return regs->uregs[r];
+}
+
+/**
+ * regs_get_kernel_argument() - get Nth function argument in kernel
+ * @regs: pt_regs of that context
+ * @n: function argument number (start from 0)
+ *
+ * regs_get_argument() returns @n th argument of the function call.
+ */
+static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs,
+ unsigned int n)
+{
+#define NR_REG_ARGUMENTS 4
+ if (n < NR_REG_ARGUMENTS)
+ return pt_regs_read_reg(regs, n);
+ return 0;
+}
+
/* Valid only for Kernel mode traps. */
static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
{
--
2.25.1