{
return 0; // probe is already registered
}
- result = dbi_register_jprobe (&probe->jprobe, 0);
+ result = dbi_register_jprobe (&probe->jprobe);
if (result)
{
EPRINTF ("register_kernel_jprobe(0x%lx) failure %d", probe->addr, result);
((probe == exec_probe) && (us_proc_probes & US_PROC_EXEC_INSTLD))) {
return 0; // probe is necessary for user space instrumentation
}
- dbi_unregister_jprobe (&probe->jprobe, 0);
+ dbi_unregister_jprobe (&probe->jprobe);
return 0;
}
return 0; // probe is already registered
}
- result = dbi_register_kretprobe (&probe->retprobe, 0);
+ result = dbi_register_kretprobe (&probe->retprobe);
if (result)
{
EPRINTF ("register_kernel_retprobe(0x%lx) failure %d", probe->addr, result);
((probe == exec_probe) && (us_proc_probes & US_PROC_EXEC_INSTLD))) {
return 0; // probe is necessary for user space instrumentation
}
- dbi_unregister_kretprobe (&probe->retprobe, 0);
+ dbi_unregister_kretprobe (&probe->retprobe);
return 0;
}
DEFINE_PER_CPU (kernel_probe_t *, gpKernProbe) = NULL;
EXPORT_PER_CPU_SYMBOL_GPL(gpKernProbe);
-DEFINE_PER_CPU(struct pt_regs *, gpKernRegs) = NULL;
-EXPORT_PER_CPU_SYMBOL_GPL(gpKernRegs);
unsigned long
def_jprobe_event_pre_handler (kernel_probe_t * probe, struct pt_regs *regs)
{
__get_cpu_var (gpKernProbe) = probe;
- __get_cpu_var (gpKernRegs) = regs;
return 0;
}
* 2008-2009 Alexey Gerenkov <a.gerenkov@samsung.com> User-Space
* Probes initial implementation; Support x86.
* 2010 Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
- *
* 2010-2011 Alexander Shirshikov <a.shirshikov@samsung.com>: initial implementation for Thumb
- * 2012 Stanislav Andreev <s.andreev@samsung.com>: added time debug profiling support; BUG() message fix
- * 2012 Stanislav Andreev <s.andreev@samsung.com>: redesign of kprobe functionality -
- * kprobe_handler() now called via undefined instruction hooks
- * 2012 Stanislav Andreev <s.andreev@samsung.com>: hash tables search implemented for uprobes
+ * 2012 Stanislav Andreev <s.andreev@samsung.com>: added time debug profiling support; BUG() message fix
+ * 2012 Stanislav Andreev <s.andreev@samsung.com>: redesign of kprobe functionality -
+ * kprobe_handler() now called via undefined instruction hooks
+ * 2012 Stanislav Andreev <s.andreev@samsung.com>: hash tables search implemented for uprobes
*/
#include <linux/module.h>
{
for (i = 0; i < 13; i++)
{
- // DBPRINTF("prep_pc_dep_insn_execbuf: check R%d/%d, changing regs %x in %x",
- // i, ARM_INSN_REG_RN(insn), uregs, insn);
if ((uregs & 0x1) && (ARM_INSN_REG_RN (insn) == i))
continue;
if ((uregs & 0x2) && (ARM_INSN_REG_RD (insn) == i))
ARM_INSN_REG_SET_RD (insns[0], i);
// set register to load address to
ARM_INSN_REG_SET_RD (insns[1], i);
- // set instruction to execute and patch it
+ // set instruction to execute and patch it
if (uregs & 0x10)
{
ARM_INSN_REG_CLEAR_MR (insn, 15);
{
if (((((unsigned char) insn) & 0xff) >> 3) == 15)
reg = (insn & 0xffff) & uregs;
- else
+ else
return 0;
}else{
if (THUMB2_INSN_MATCH (ADR, insn))
int arch_prepare_kprobe (struct kprobe *p)
{
kprobe_opcode_t insns[KPROBES_TRAMP_LEN];
- int uregs, pc_dep;
- int ret = 0;
-
- if (!ret)
- {
- kprobe_opcode_t insn[MAX_INSN_SIZE];
- struct arch_specific_insn ainsn;
- /* insn: must be on special executable page on i386. */
- p->ainsn.insn = get_insn_slot (NULL, 0);
- if (!p->ainsn.insn)
- return -ENOMEM;
- memcpy (insn, p->addr, MAX_INSN_SIZE * sizeof (kprobe_opcode_t));
- ainsn.insn_arm = ainsn.insn = insn;
- ret = arch_check_insn_arm (&ainsn);
- if (!ret)
- {
- p->opcode = *p->addr;
-
- p->ainsn.boostable = 1;
- uregs = pc_dep = 0;
- // Rn, Rm ,Rd
- if (ARM_INSN_MATCH (DPIS, insn[0]) || ARM_INSN_MATCH (LRO, insn[0]) ||
- ARM_INSN_MATCH (SRO, insn[0]))
- {
-
- uregs = 0xb;
- if ((ARM_INSN_REG_RN (insn[0]) == 15) || (ARM_INSN_REG_RM (insn[0]) == 15) ||
- (ARM_INSN_MATCH (SRO, insn[0]) && (ARM_INSN_REG_RD (insn[0]) == 15)))
- {
-
- DBPRINTF ("Unboostable insn %lx, DPIS/LRO/SRO\n", insn[0]);
- pc_dep = 1;
- }
- }
- // Rn ,Rd
- else if (ARM_INSN_MATCH (DPI, insn[0]) || ARM_INSN_MATCH (LIO, insn[0]) ||
- ARM_INSN_MATCH (SIO, insn[0]))
- {
-
- uregs = 0x3;
- if ((ARM_INSN_REG_RN (insn[0]) == 15) || (ARM_INSN_MATCH (SIO, insn[0]) &&
- (ARM_INSN_REG_RD (insn[0]) == 15)))
- {
-
- pc_dep = 1;
- DBPRINTF ("Unboostable insn %lx/%p/%d, DPI/LIO/SIO\n", insn[0], p, p->ainsn.boostable);
- }
- }
- // Rn, Rm, Rs
- else if (ARM_INSN_MATCH (DPRS, insn[0]))
- {
-
- uregs = 0xd;
- if ((ARM_INSN_REG_RN (insn[0]) == 15) || (ARM_INSN_REG_RM (insn[0]) == 15) ||
- (ARM_INSN_REG_RS (insn[0]) == 15))
- {
-
- pc_dep = 1;
- DBPRINTF ("Unboostable insn %lx, DPRS\n", insn[0]);
- }
- }
- // register list
- else if (ARM_INSN_MATCH (SM, insn[0]))
- {
-
- uregs = 0x10;
- if (ARM_INSN_REG_MR (insn[0], 15))
- {
-
- DBPRINTF ("Unboostable insn %lx, SM\n", insn[0]);
- pc_dep = 1;
- }
- }
- // check instructions that can write result to SP andu uses PC
- if (pc_dep && (ARM_INSN_REG_RD (ainsn.insn[0]) == 13))
- {
- static int count;
- count++;
- //printk ("insn writes result to SP and uses PC: %lx/%d\n", ainsn.insn[0], count);
- free_insn_slot (&kprobe_insn_pages, NULL, p->ainsn.insn, 0);
- ret = -EFAULT;
- }
- else {
- if (uregs && pc_dep)
- {
- memcpy (insns, pc_dep_insn_execbuf, sizeof (insns));
- if (prep_pc_dep_insn_execbuf (insns, insn[0], uregs) != 0)
- {
- DBPRINTF ("failed to prepare exec buffer for insn %lx!", insn[0]);
- free_insn_slot (&kprobe_insn_pages, NULL, p->ainsn.insn, 0);
- return -EINVAL;
- }
- //insns[KPROBES_TRAMP_SS_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
- insns[6] = (kprobe_opcode_t) (p->addr + 2);
- }
- else
- {
- memcpy (insns, gen_insn_execbuf, sizeof (insns));
- insns[KPROBES_TRAMP_INSN_IDX] = insn[0];
- }
- //insns[KPROBES_TRAMP_RET_BREAK_IDX] = UNDEF_INSTRUCTION;
- insns[7] = (kprobe_opcode_t) (p->addr + 1);
- DBPRINTF ("arch_prepare_kprobe: insn %lx", insn[0]);
- DBPRINTF ("arch_prepare_kprobe: to %p - %lx %lx %lx %lx %lx %lx %lx %lx %lx",
- p->ainsn.insn, insns[0], insns[1], insns[2], insns[3], insns[4],
- insns[5], insns[6], insns[7], insns[8]);
- memcpy (p->ainsn.insn, insns, sizeof(insns));
- flush_icache_range(p->ainsn.insn, p->ainsn.insn + sizeof(insns));
+ int uregs, pc_dep, ret = 0;
+ kprobe_opcode_t insn[MAX_INSN_SIZE];
+ struct arch_specific_insn ainsn;
+
+ /* insn: must be on special executable page on i386. */
+ p->ainsn.insn = get_insn_slot (NULL, 0);
+ if (!p->ainsn.insn)
+ return -ENOMEM;
+
+ memcpy (insn, p->addr, MAX_INSN_SIZE * sizeof (kprobe_opcode_t));
+ ainsn.insn_arm = ainsn.insn = insn;
+ ret = arch_check_insn_arm (&ainsn);
+ if (!ret)
+ {
+ p->opcode = *p->addr;
+ p->ainsn.boostable = 1;
+ uregs = pc_dep = 0;
+
+ // Rn, Rm ,Rd
+ if(ARM_INSN_MATCH (DPIS, insn[0]) || ARM_INSN_MATCH (LRO, insn[0]) ||
+ ARM_INSN_MATCH (SRO, insn[0]))
+ {
+ uregs = 0xb;
+ if( (ARM_INSN_REG_RN (insn[0]) == 15) || (ARM_INSN_REG_RM (insn[0]) == 15) ||
+ (ARM_INSN_MATCH (SRO, insn[0]) && (ARM_INSN_REG_RD (insn[0]) == 15)) )
+ {
+ DBPRINTF ("Unboostable insn %lx, DPIS/LRO/SRO\n", insn[0]);
+ pc_dep = 1;
+ }
+ }
+ // Rn ,Rd
+ else if(ARM_INSN_MATCH (DPI, insn[0]) || ARM_INSN_MATCH (LIO, insn[0]) ||
+ ARM_INSN_MATCH (SIO, insn[0]))
+ {
+ uregs = 0x3;
+ if ((ARM_INSN_REG_RN (insn[0]) == 15) || (ARM_INSN_MATCH (SIO, insn[0]) &&
+ (ARM_INSN_REG_RD (insn[0]) == 15)))
+ {
+ pc_dep = 1;
+ DBPRINTF ("Unboostable insn %lx/%p/%d, DPI/LIO/SIO\n", insn[0], p, p->ainsn.boostable);
+ }
+ }
+ // Rn, Rm, Rs
+ else if(ARM_INSN_MATCH (DPRS, insn[0]))
+ {
+ uregs = 0xd;
+ if ((ARM_INSN_REG_RN (insn[0]) == 15) || (ARM_INSN_REG_RM (insn[0]) == 15) ||
+ (ARM_INSN_REG_RS (insn[0]) == 15))
+ {
+ pc_dep = 1;
+ DBPRINTF ("Unboostable insn %lx, DPRS\n", insn[0]);
+ }
+ }
+ // register list
+ else if(ARM_INSN_MATCH (SM, insn[0]))
+ {
+ uregs = 0x10;
+ if (ARM_INSN_REG_MR (insn[0], 15))
+ {
+ DBPRINTF ("Unboostable insn %lx, SM\n", insn[0]);
+ pc_dep = 1;
+ }
+ }
+ // check instructions that can write result to SP andu uses PC
+ if (pc_dep && (ARM_INSN_REG_RD (ainsn.insn[0]) == 13))
+ {
+ free_insn_slot (&kprobe_insn_pages, NULL, p->ainsn.insn, 0);
+ ret = -EFAULT;
+ }
+ else
+ {
+ if (uregs && pc_dep)
+ {
+ memcpy (insns, pc_dep_insn_execbuf, sizeof (insns));
+ if (prep_pc_dep_insn_execbuf (insns, insn[0], uregs) != 0)
+ {
+ DBPRINTF ("failed to prepare exec buffer for insn %lx!", insn[0]);
+ free_insn_slot (&kprobe_insn_pages, NULL, p->ainsn.insn, 0);
+ return -EINVAL;
+ }
+ insns[6] = (kprobe_opcode_t) (p->addr + 2);
+ }
+ else
+ {
+ memcpy (insns, gen_insn_execbuf, sizeof (insns));
+ insns[KPROBES_TRAMP_INSN_IDX] = insn[0];
+ }
+ insns[7] = (kprobe_opcode_t) (p->addr + 1);
+ DBPRINTF ("arch_prepare_kprobe: insn %lx", insn[0]);
+ DBPRINTF ("arch_prepare_kprobe: to %p - %lx %lx %lx %lx %lx %lx %lx %lx %lx",
+ p->ainsn.insn, insns[0], insns[1], insns[2], insns[3], insns[4],
+ insns[5], insns[6], insns[7], insns[8]);
+ memcpy (p->ainsn.insn, insns, sizeof(insns));
+ flush_icache_range(p->ainsn.insn, p->ainsn.insn + sizeof(insns));
#ifdef BOARD_tegra
- flush_cache_all();
+ flush_cache_all();
#endif
- }
- }
- else
- {
- free_insn_slot (&kprobe_insn_pages, NULL, p->ainsn.insn, 0);
- }
- }
+ }
+ }
+ else
+ {
+ free_insn_slot (&kprobe_insn_pages, NULL, p->ainsn.insn, 0);
+ }
+
return ret;
}
memcpy (insns, pc_dep_insn_execbuf, sizeof (insns));
if (prep_pc_dep_insn_execbuf (insns, insn[0], uregs) != 0)
{
- printk("Error in %s at %d: failed to prepare exec buffer for insn %lx!",
+ printk("Error in %s at %d: failed to prepare exec buffer for insn %lx!",
insn[0], __FILE__, __LINE__);
p->safe_arm = -1;
// TODO: move free to later phase
THUMB2_INSN_MATCH (LDRHW, insn[0]) || THUMB2_INSN_MATCH (LDRHW1, insn[0]) ||
THUMB2_INSN_MATCH (LDRWL, insn[0])) && THUMB2_INSN_REG_RN(insn[0]) == 15) ||
THUMB2_INSN_MATCH (LDREX, insn[0]) ||
- ((THUMB2_INSN_MATCH (STRW, insn[0]) || THUMB2_INSN_MATCH (STRBW, insn[0]) ||
- THUMB2_INSN_MATCH (STRHW, insn[0]) || THUMB2_INSN_MATCH (STRHW1, insn[0])) &&
+ ((THUMB2_INSN_MATCH (STRW, insn[0]) || THUMB2_INSN_MATCH (STRBW, insn[0]) ||
+ THUMB2_INSN_MATCH (STRHW, insn[0]) || THUMB2_INSN_MATCH (STRHW1, insn[0])) &&
(THUMB2_INSN_REG_RN(insn[0]) == 15 || THUMB2_INSN_REG_RT(insn[0]) == 15)) ||
- ((THUMB2_INSN_MATCH (STRT, insn[0]) || THUMB2_INSN_MATCH (STRHT, insn[0])) &&
+ ((THUMB2_INSN_MATCH (STRT, insn[0]) || THUMB2_INSN_MATCH (STRHT, insn[0])) &&
(THUMB2_INSN_REG_RN(insn[0]) == 15 || THUMB2_INSN_REG_RT(insn[0]) == 15)) )
{
uregs = 0xf000; // Rt 12-15
memcpy (insns, pc_dep_insn_execbuf_thumb, 18 * 2);
if (prep_pc_dep_insn_execbuf_thumb (insns, insn[0], uregs) != 0)
{
- printk("Error in %s at %d: failed to prepare exec buffer for insn %lx!",
+ printk("Error in %s at %d: failed to prepare exec buffer for insn %lx!",
insn[0], __FILE__, __LINE__);
p->safe_thumb = -1;
//free_insn_slot (&uprobe_insn_pages, task, p->ainsn.insn_thumb, 0);
#ifdef OVERHEAD_DEBUG
do_gettimeofday(&swap_tv2);
swap_sum_hit++;
- swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) * USEC_IN_SEC_NUM +
+ swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) * USEC_IN_SEC_NUM +
(swap_tv2.tv_usec - swap_tv1.tv_usec));
#endif
#ifdef SUPRESS_BUG_MESSAGES
}
else
{
- if(pid) { //we can reenter probe upon uretprobe exception
+ if(pid) { //we can reenter probe upon uretprobe exception
DBPRINTF ("check for UNDEF_INSTRUCTION %p\n", addr);
// UNDEF_INSTRUCTION from user space
/*if (p->break_handler && p->break_handler(p, regs)) {
DBPRINTF("kprobe_running !!! goto ss");
goto ss_probe;
- } */
+ } */
DBPRINTF ("unknown uprobe at %p cur at %p/%p\n", addr, p->addr, p->ainsn.insn);
if(pid)
ssaddr = p->ainsn.insn + UPROBES_TRAMP_SS_BREAK_IDX;
#ifdef OVERHEAD_DEBUG
do_gettimeofday(&swap_tv2);
swap_sum_hit++;
- swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) * USEC_IN_SEC_NUM +
+ swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) * USEC_IN_SEC_NUM +
(swap_tv2.tv_usec - swap_tv1.tv_usec));
#endif
#ifdef SUPRESS_BUG_MESSAGES
#ifdef OVERHEAD_DEBUG
do_gettimeofday(&swap_tv2);
swap_sum_hit++;
- swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) * USEC_IN_SEC_NUM +
+ swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) * USEC_IN_SEC_NUM +
(swap_tv2.tv_usec - swap_tv1.tv_usec));
#endif
#ifdef SUPRESS_BUG_MESSAGES
#ifdef OVERHEAD_DEBUG
do_gettimeofday(&swap_tv2);
swap_sum_hit++;
- swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) * USEC_IN_SEC_NUM +
+ swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) * USEC_IN_SEC_NUM +
(swap_tv2.tv_usec - swap_tv1.tv_usec));
#endif
#ifdef SUPRESS_BUG_MESSAGES
//call handler for all kernel probes and user space ones which belong to current tgid
if (!p->tgid || (p->tgid == current->tgid))
- {
+ {
if(!p->tgid && ((unsigned int)p->addr == sched_addr) && sched_rp){
struct task_struct *p, *g;
rcu_read_lock();
/*
* It is possible to have multiple instances associated with a given
* task either because an multiple functions in the call path
- * have a return probe installed on them, and/or more then one
+ * have a return probe installed on them, and/or more then one
* return probe was registered for a target function.
*
* We can handle this because:
do_kpro(&undef_ho_k);
do_kpro(&undef_ho_u);
do_kpro(&undef_ho_u_t);
- if ((ret = dbi_register_kprobe (&trampoline_p, 0)) != 0) {
+ if ((ret = dbi_register_kprobe (&trampoline_p)) != 0) {
//dbi_unregister_jprobe(&do_exit_p, 0);
return ret;
}
// Insert new code
memcpy ((void *) do_bp_handler, arr_traps_template, code_size);
flush_icache_range (do_bp_handler, do_bp_handler + code_size);
- if((ret = dbi_register_kprobe (&trampoline_p, 0)) != 0){
+ if((ret = dbi_register_kprobe (&trampoline_p)) != 0){
//dbi_unregister_jprobe(&do_exit_p, 0);
return ret;
}
* 2006-2007 Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM and MIPS
* 2008-2009 Alexey Gerenkov <a.gerenkov@samsung.com> User-Space
* Probes initial implementation; Support x86/ARM/MIPS for both user and kernel spaces.
- * 2010 Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
+ * 2010 Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
*
-
*/
#include "dbi_kprobes.h"
extern unsigned int *sched_addr;
extern unsigned int *fork_addr;
-
extern struct hlist_head kprobe_insn_pages;
extern unsigned long (*kallsyms_search) (const char *name);
/* We have preemption disabled.. so it is safe to use __ versions */
-static inline
+static inline
void set_kprobe_instance (struct kprobe *kp)
{
__get_cpu_var (kprobe_instance) = kp;
}
-static inline
+static inline
void reset_kprobe_instance (void)
{
__get_cpu_var (kprobe_instance) = NULL;
* Aggregate handlers for multiple kprobes support - these handlers
* take care of invoking the individual kprobe handlers on p->list
*/
-static
+static
int aggr_pre_handler (struct kprobe *p, struct pt_regs *regs)
{
struct kprobe *kp;
return 0;
}
-static
+static
void aggr_post_handler (struct kprobe *p, struct pt_regs *regs, unsigned long flags)
{
struct kprobe *kp;
reset_kprobe_instance ();
}
}
- return;
}
-static
+static
int aggr_fault_handler (struct kprobe *p, struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = __get_cpu_var (kprobe_instance);
return 0;
}
-static
+static
int aggr_break_handler (struct kprobe *p, struct pt_regs *regs)
{
struct kprobe *cur = __get_cpu_var (kprobe_instance);
/*
* Keep all fields in the kprobe consistent
*/
-static inline
+static inline
void copy_kprobe (struct kprobe *old_p, struct kprobe *p)
{
memcpy (&p->opcode, &old_p->opcode, sizeof (kprobe_opcode_t));
* Fill in the required fields of the "manager kprobe". Replace the
* earlier kprobe in the hlist with the manager kprobe
*/
-static inline
+static inline
void add_aggr_kprobe (struct kprobe *ap, struct kprobe *p)
{
copy_kprobe (p, ap);
return ret;
}
-static
-int __dbi_register_kprobe (struct kprobe *p, unsigned long called_from, int atomic)
-{
- struct kprobe *old_p;
- // struct module *probed_mod;
- int ret = 0;
- /*
- * If we have a symbol_name argument look it up,
- * and add it to the address. That way the addr
- * field can either be global or relative to a symbol.
- */
- if (p->symbol_name)
- {
- if (p->addr)
- return -EINVAL;
- p->addr = (unsigned int) kallsyms_search (p->symbol_name);
- }
-
- if (!p->addr)
- return -EINVAL;
- DBPRINTF ("p->addr = 0x%p\n", p->addr);
- p->addr = (kprobe_opcode_t *) (((char *) p->addr) + p->offset);
- DBPRINTF ("p->addr = 0x%p p = 0x%p\n", p->addr, p);
-
- /* if ((!kernel_text_address((unsigned long) p->addr)) ||
- in_kprobes_functions((unsigned long) p->addr))
- return -EINVAL;*/
+int dbi_register_kprobe (struct kprobe *p)
+{
+ struct kprobe *old_p;
+ int ret = 0;
+ /*
+ * If we have a symbol_name argument look it up,
+ * and add it to the address. That way the addr
+ * field can either be global or relative to a symbol.
+ */
+ if (p->symbol_name)
+ {
+ if (p->addr)
+ return -EINVAL;
+ p->addr = (unsigned int) kallsyms_search (p->symbol_name);
+ }
+
+ if (!p->addr)
+ return -EINVAL;
+ DBPRINTF ("p->addr = 0x%p\n", p->addr);
+ p->addr = (kprobe_opcode_t *) (((char *) p->addr) + p->offset);
+ DBPRINTF ("p->addr = 0x%p p = 0x%p\n", p->addr, p);
#ifdef KPROBES_PROFILE
- p->start_tm.tv_sec = p->start_tm.tv_usec = 0;
- p->hnd_tm_sum.tv_sec = p->hnd_tm_sum.tv_usec = 0;
- p->count = 0;
+ p->start_tm.tv_sec = p->start_tm.tv_usec = 0;
+ p->hnd_tm_sum.tv_sec = p->hnd_tm_sum.tv_usec = 0;
+ p->count = 0;
#endif
- p->mod_refcounted = 0;
- //p->proc_prio = 0;
- //p->proc_sched = 0;
- //p->spid = -1;
- //p->irq = 0;
- //p->task_flags = 0;
- /*
- // Check are we probing a module
- if ((probed_mod = module_text_address((unsigned long) p->addr))) {
- struct module *calling_mod = module_text_address(called_from);
- // We must allow modules to probe themself and
- // in this case avoid incrementing the module refcount,
- // so as to allow unloading of self probing modules.
- //
- if (calling_mod && (calling_mod != probed_mod)) {
- if (unlikely(!try_module_get(probed_mod)))
- return -EINVAL;
- p->mod_refcounted = 1;
- } else
- probed_mod = NULL;
- }
- */
- p->nmissed = 0;
- // mutex_lock(&kprobe_mutex);
- old_p = get_kprobe (p->addr, 0, NULL);
- if (old_p)
- {
- ret = register_aggr_kprobe (old_p, p);
- if (!ret)
- atomic_inc (&kprobe_count);
- goto out;
- }
-
- if ((ret = arch_prepare_kprobe (p)) != 0)
- goto out;
-
- DBPRINTF ("before out ret = 0x%x\n", ret);
-
- INIT_HLIST_NODE (&p->hlist);
- hlist_add_head_rcu (&p->hlist, &kprobe_table[hash_ptr (p->addr, KPROBE_HASH_BITS)]);
-
- /* if (atomic_add_return(1, &kprobe_count) == \
- (ARCH_INACTIVE_KPROBE_COUNT + 1))
- register_page_fault_notifier(&kprobe_page_fault_nb);*/
-
- arch_arm_kprobe (p);
+ p->mod_refcounted = 0;
+ p->nmissed = 0;
+
+ old_p = get_kprobe (p->addr, 0, NULL);
+ if (old_p)
+ {
+ ret = register_aggr_kprobe (old_p, p);
+ if (!ret)
+ atomic_inc (&kprobe_count);
+ goto out;
+ }
+
+ if ((ret = arch_prepare_kprobe (p)) != 0)
+ goto out;
+
+ DBPRINTF ("before out ret = 0x%x\n", ret);
+ INIT_HLIST_NODE (&p->hlist);
+ hlist_add_head_rcu (&p->hlist, &kprobe_table[hash_ptr (p->addr, KPROBE_HASH_BITS)]);
+ arch_arm_kprobe (p);
out:
- // mutex_unlock(&kprobe_mutex);
- /*
- if (ret && probed_mod)
- module_put(probed_mod);
- */
- DBPRINTF ("out ret = 0x%x\n", ret);
-
- return ret;
+ DBPRINTF ("out ret = 0x%x\n", ret);
+ return ret;
}
-
-int dbi_register_kprobe (struct kprobe *p, int atomic)
+void dbi_unregister_kprobe (struct kprobe *p, struct task_struct *task)
{
- return __dbi_register_kprobe (p, (unsigned long) __builtin_return_address (0), atomic);
-}
-
-void dbi_unregister_kprobe (struct kprobe *p, struct task_struct *task, int atomic)
-{
- // struct module *mod;
struct kprobe *old_p, *list_p;
- int cleanup_p, pid = 0;
-
- // mutex_lock(&kprobe_mutex);
-
- pid = p->tgid;
+ int cleanup_p, pid = p->tgid;
old_p = get_kprobe (p->addr, pid, NULL);
DBPRINTF ("dbi_unregister_kprobe p=%p old_p=%p", p, old_p);
if (unlikely (!old_p))
- {
- // mutex_unlock(&kprobe_mutex);
return;
- }
+
if (p != old_p)
{
- list_for_each_entry_rcu (list_p, &old_p->list, list)
+ list_for_each_entry_rcu (list_p, &old_p->list, list)
if (list_p == p)
/* kprobe p is a valid probe */
goto valid_p;
- // mutex_unlock(&kprobe_mutex);
return;
}
+
valid_p:
DBPRINTF ("dbi_unregister_kprobe valid_p");
- if ((old_p == p) || ((old_p->pre_handler == aggr_pre_handler) &&
+ if ((old_p == p) || ((old_p->pre_handler == aggr_pre_handler) &&
(p->list.next == &old_p->list) && (p->list.prev == &old_p->list)))
{
/* Only probe on the hash list */
cleanup_p = 0;
}
DBPRINTF ("dbi_unregister_kprobe cleanup_p=%d", cleanup_p);
- // mutex_unlock(&kprobe_mutex);
- // synchronize_sched();
- /*
- if (p->mod_refcounted &&
- (mod = module_text_address((unsigned long)p->addr)))
- module_put(mod);
- */
if (cleanup_p)
{
if (p != old_p)
}
else
{
- /// mutex_lock(&kprobe_mutex);
if (p->break_handler)
old_p->break_handler = NULL;
if (p->post_handler)
if (cleanup_p == 0)
old_p->post_handler = NULL;
}
- // mutex_unlock(&kprobe_mutex);
}
-
- /* Call unregister_page_fault_notifier()
- * if no probes are active
- */
- // mutex_lock(&kprobe_mutex);
- /* if (atomic_add_return(-1, &kprobe_count) == \
- ARCH_INACTIVE_KPROBE_COUNT)
- unregister_page_fault_notifier(&kprobe_page_fault_nb);*/
- // mutex_unlock(&kprobe_mutex);
- return;
}
-int dbi_register_jprobe (struct jprobe *jp, int atomic)
+int dbi_register_jprobe (struct jprobe *jp)
{
/* Todo: Verify probepoint is a function entry point */
jp->kp.pre_handler = setjmp_pre_handler;
jp->kp.break_handler = longjmp_break_handler;
- return __dbi_register_kprobe (&jp->kp, (unsigned long) __builtin_return_address (0), atomic);
+ return dbi_register_kprobe (&jp->kp);
}
-void dbi_unregister_jprobe (struct jprobe *jp, int atomic)
+void dbi_unregister_jprobe (struct jprobe *jp)
{
- dbi_unregister_kprobe (&jp->kp, 0, atomic);
+ dbi_unregister_kprobe (&jp->kp, 0);
}
/*
return 0;
}
-int dbi_register_kretprobe (struct kretprobe *rp, int atomic)
+int dbi_register_kretprobe (struct kretprobe *rp)
{
int ret = 0;
struct kretprobe_instance *inst;
int i;
- int priority = atomic ? GFP_ATOMIC : GFP_KERNEL;
DBPRINTF ("START");
rp->kp.pre_handler = pre_handler_kretprobe;
INIT_HLIST_HEAD (&rp->free_instances);
for (i = 0; i < rp->maxactive; i++)
{
- inst = kmalloc (sizeof (struct kretprobe_instance), priority);
+ inst = kmalloc (sizeof (struct kretprobe_instance), GFP_KERNEL);
if (inst == NULL)
{
free_rp_inst (rp);
DBPRINTF ("addr=%p, *addr=[%lx %lx %lx]", rp->kp.addr, (unsigned long) (*(rp->kp.addr)), (unsigned long) (*(rp->kp.addr + 1)), (unsigned long) (*(rp->kp.addr + 2)));
rp->nmissed = 0;
/* Establish function entry probe point */
- if ((ret = __dbi_register_kprobe (&rp->kp, (unsigned long) __builtin_return_address (0), atomic)) != 0)
+ if ((ret = dbi_register_kprobe (&rp->kp)) != 0)
free_rp_inst (rp);
DBPRINTF ("addr=%p, *addr=[%lx %lx %lx]", rp->kp.addr, (unsigned long) (*(rp->kp.addr)), (unsigned long) (*(rp->kp.addr + 1)), (unsigned long) (*(rp->kp.addr + 2)));
return ret;
}
-void dbi_unregister_kretprobe (struct kretprobe *rp, int atomic)
+void dbi_unregister_kretprobe (struct kretprobe *rp)
{
unsigned long flags;
struct kretprobe_instance *ri;
- dbi_unregister_kprobe (&rp->kp, 0, atomic);
+ dbi_unregister_kprobe (&rp->kp, 0);
if((unsigned int)rp->kp.addr == sched_addr)
sched_rp = NULL;
* 2006-2007 Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM and MIPS
* 2008-2009 Alexey Gerenkov <a.gerenkov@samsung.com> User-Space
* Probes initial implementation; Support x86/ARM/MIPS for both user and kernel spaces.
- * 2010 Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
+ * 2010 Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
*
-
*/
-
#include <linux/version.h> // LINUX_VERSION_CODE, KERNEL_VERSION()
-
-//#include <linux/list.h>
#include <linux/notifier.h>
-//#include <linux/smp.h>
#include <linux/percpu.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
struct hlist_head *kretprobe_inst_table_head (void *hash_key);
-int dbi_register_kprobe (struct kprobe *p, int atomic);
-void dbi_unregister_kprobe (struct kprobe *p, struct task_struct *task, int atomic);
+int dbi_register_kprobe (struct kprobe *p);
+void dbi_unregister_kprobe (struct kprobe *p, struct task_struct *task);
int register_aggr_kprobe (struct kprobe *old_p, struct kprobe *p);
int pre_handler_kretprobe (struct kprobe *p, struct pt_regs *regs);
int setjmp_pre_handler (struct kprobe *, struct pt_regs *);
int longjmp_break_handler (struct kprobe *, struct pt_regs *);
-int dbi_register_jprobe (struct jprobe *p, int atomic);
-void dbi_unregister_jprobe (struct jprobe *p, int atomic);
+int dbi_register_jprobe (struct jprobe *p);
+void dbi_unregister_jprobe (struct jprobe *p);
void dbi_jprobe_return (void);
void dbi_jprobe_return_end (void);
int alloc_nodes_kretprobe(struct kretprobe *rp);
-int dbi_register_kretprobe (struct kretprobe *rp, int atomic);
-void dbi_unregister_kretprobe (struct kretprobe *rp, int atomic);
+int dbi_register_kretprobe (struct kretprobe *rp);
+void dbi_unregister_kretprobe (struct kretprobe *rp);
-void kretprobe_assert (struct kretprobe_instance *ri,
+void kretprobe_assert (struct kretprobe_instance *ri,
unsigned long orig_ret_address, unsigned long trampoline_address);
void unregister_uprobe (struct kprobe *p, struct task_struct *task, int atomic)
{
- dbi_unregister_kprobe (p, task, atomic);
+ dbi_unregister_kprobe (p, task);
}