|
@@ -256,6 +256,44 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * 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.
|
|
|
+ * Note that this chooses most probably assignment, in some case
|
|
|
+ * it can be incorrect.
|
|
|
+ * This is expected to be called from kprobes or ftrace with regs
|
|
|
+ * where the top of stack is the return address.
|
|
|
+ */
|
|
|
+static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs,
|
|
|
+ unsigned int n)
|
|
|
+{
|
|
|
+ static const unsigned int argument_offs[] = {
|
|
|
+#ifdef __i386__
|
|
|
+ offsetof(struct pt_regs, ax),
|
|
|
+ offsetof(struct pt_regs, cx),
|
|
|
+ offsetof(struct pt_regs, dx),
|
|
|
+#define NR_REG_ARGUMENTS 3
|
|
|
+#else
|
|
|
+ offsetof(struct pt_regs, di),
|
|
|
+ offsetof(struct pt_regs, si),
|
|
|
+ offsetof(struct pt_regs, dx),
|
|
|
+ offsetof(struct pt_regs, cx),
|
|
|
+ offsetof(struct pt_regs, r8),
|
|
|
+ offsetof(struct pt_regs, r9),
|
|
|
+#define NR_REG_ARGUMENTS 6
|
|
|
+#endif
|
|
|
+ };
|
|
|
+
|
|
|
+ if (n >= NR_REG_ARGUMENTS) {
|
|
|
+ n -= NR_REG_ARGUMENTS - 1;
|
|
|
+ return regs_get_kernel_stack_nth(regs, n);
|
|
|
+ } else
|
|
|
+ return regs_get_register(regs, argument_offs[n]);
|
|
|
+}
|
|
|
+
|
|
|
#define arch_has_single_step() (1)
|
|
|
#ifdef CONFIG_X86_DEBUGCTLMSR
|
|
|
#define arch_has_block_step() (1)
|