ARM64: implement brk hook 98/111098/3
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Thu, 20 Feb 2014 13:21:49 +0000 (17:21 +0400)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Mon, 30 Jan 2017 16:36:02 +0000 (19:36 +0300)
Create interface for using software breakpoint

Change-Id: Ic080dc6f79746c9cadacd336facdef49557aaa01
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
kprobe/Kbuild
kprobe/arch/arm64/swap-asm/dbg_interface.c [new file with mode: 0644]
kprobe/arch/arm64/swap-asm/dbg_interface.h [new file with mode: 0644]

index 489db75..2501018 100644 (file)
@@ -16,7 +16,8 @@ endif #ifeq ($(CONFIG_STRICT_MEMORY_RWX), y)
 
 
 ### ARM64
-swap_kprobe-$(CONFIG_ARM64) += arch/arm64/swap-asm/swap_kprobes.o
+swap_kprobe-$(CONFIG_ARM64) += arch/arm64/swap-asm/swap_kprobes.o \
+                               arch/arm64/swap-asm/dbg_interface.o
 
 
 ### X86
diff --git a/kprobe/arch/arm64/swap-asm/dbg_interface.c b/kprobe/arch/arm64/swap-asm/dbg_interface.c
new file mode 100644 (file)
index 0000000..438b7b8
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2014
+ *
+ * 2014         Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/rwlock.h>
+#include <asm/debug-monitors.h>
+#include <ksyms/ksyms.h>
+#include "dbg_interface.h"
+
+
+
+
+/* ============================================================================
+ * =                               BRK IMPLEMENT                              =
+ * ============================================================================
+ */
+static LIST_HEAD(brk_list);
+static DEFINE_RWLOCK(brk_list_lock);
+
+void dbg_brk_hook_reg(struct brk_hook *hook)
+{
+       write_lock(&brk_list_lock);
+       list_add(&hook->list, &brk_list);
+       write_unlock(&brk_list_lock);
+}
+EXPORT_SYMBOL_GPL(dbg_brk_hook_reg);
+
+void dbg_brk_hook_unreg(struct brk_hook *hook)
+{
+       write_lock(&brk_list_lock);
+       list_del(&hook->list);
+       write_unlock(&brk_list_lock);
+}
+EXPORT_SYMBOL_GPL(dbg_brk_hook_unreg);
+
+static enum dbg_code call_brk_hook(struct pt_regs *regs, unsigned int esr)
+{
+       struct brk_hook *hook;
+       enum dbg_code (*fn)(struct pt_regs *regs, unsigned int esr) = NULL;
+
+       read_lock(&brk_list_lock);
+       list_for_each_entry(hook, &brk_list, list)
+               if (((esr & hook->esr_mask) == hook->esr_val) &&
+                   ((regs->pstate & hook->spsr_mask) == hook->spsr_val))
+                       fn = hook->fn;
+       read_unlock(&brk_list_lock);
+
+       return fn ? fn(regs, esr) : DBG_ERROR;
+}
+
+
+typedef int (*dbg_fn_t)(unsigned long addr, unsigned int esr,
+                       struct pt_regs *regs);
+
+static dbg_fn_t *brk_handler_ptr;
+static dbg_fn_t orig_brk_handler;
+
+static int brk_handler(unsigned long addr, unsigned int esr,
+                      struct pt_regs *regs)
+{
+       /* call the registered breakpoint handler */
+       if (call_brk_hook(regs, esr) == DBG_HANDLED)
+               return 0;
+
+       return orig_brk_handler(addr, esr, regs);
+}
+
+static void init_brk(dbg_fn_t *fn)
+{
+       brk_handler_ptr = fn;
+       orig_brk_handler = *brk_handler_ptr;
+       *brk_handler_ptr = brk_handler;
+}
+
+static void uninit_brk(void)
+{
+       *brk_handler_ptr = orig_brk_handler;
+}
+
+
+
+
+
+
+/* ============================================================================
+ * =                                INIT / EXIT                               =
+ * ============================================================================
+ */
+int dbg_iface_init(void)
+{
+       struct fault_info {
+               int (*fn)(unsigned long addr, unsigned int esr,
+                         struct pt_regs *regs);
+               int sig;
+               int code;
+               const char *name;
+       };
+
+       struct fault_info *debug_finfo;
+       struct fault_info *finfo_brk;
+
+       debug_finfo = (struct fault_info *)swap_ksyms("debug_fault_info");
+       if (debug_finfo == NULL) {
+               pr_err("cannot found 'debug_fault_info'\n");
+               return -EINVAL;
+       }
+
+       finfo_brk = &debug_finfo[DBG_ESR_EVT_BRK];
+
+       init_brk(&finfo_brk->fn);
+
+       return 0;
+}
+
+void dbg_iface_uninit(void)
+{
+       uninit_brk();
+}
diff --git a/kprobe/arch/arm64/swap-asm/dbg_interface.h b/kprobe/arch/arm64/swap-asm/dbg_interface.h
new file mode 100644 (file)
index 0000000..185d5ae
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef _ASM_DBG_INTERFACE_H
+#define _ASM_DBG_INTERFACE_H
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2014
+ *
+ * 2014         Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#include <linux/list.h>
+#include <linux/types.h>
+
+
+#define ESR_ELx_IL       (1 << 25)
+#define ESR_ELx_EC_BRK   0xf0000000
+#define ESR_ELx_EC_MASK  0xfc000000
+#define BRK_COMM_MASK    0x0000ffff
+
+#define DBG_BRK_ESR_MASK (ESR_ELx_EC_MASK | ESR_ELx_IL | BRK_COMM_MASK)
+#define DBG_BRK_ESR(x)   (ESR_ELx_EC_BRK | ESR_ELx_IL | (BRK_COMM_MASK & (x)))
+
+#define MAKE_BRK(v)      ((((v) & 0xffff) << 5) | 0xd4200000)
+
+
+enum dbg_code {
+       DBG_HANDLED,
+       DBG_ERROR,
+};
+
+
+struct brk_hook {
+       struct list_head list;
+       u32 spsr_mask;
+       u32 spsr_val;
+       u32 esr_mask;
+       u32 esr_val;
+       enum dbg_code (*fn)(struct pt_regs *regs, unsigned int esr);
+};
+
+
+void dbg_brk_hook_reg(struct brk_hook *hook);
+void dbg_brk_hook_unreg(struct brk_hook *hook);
+
+int dbg_iface_init(void);
+void dbg_iface_uninit(void);
+
+
+#endif /* _ASM_DBG_INTERFACE_H */