-/*
- * Dynamic Binary Instrumentation Module based on KProbes
- * modules/kprobe/arch/asm-arm/swap_kprobes.c
+/**
+ * kprobe/arch/asm-arm/swap_kprobes.c
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM/MIPS
+ * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial implementation; Support x86.
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
+ * @author Alexander Shirshikov <a.shirshikov@samsung.com>: initial implementation for Thumb
+ * @author Stanislav Andreev <s.andreev@samsung.com>: added time debug profiling support; BUG() message fix
+ * @author Stanislav Andreev <s.andreev@samsung.com>: redesign of kprobe functionality -
+ * kprobe_handler() now called via undefined instruction hooks
+ * @author Stanislav Andreev <s.andreev@samsung.com>: hash tables search implemented for uprobes
+ *
+ * @section LICENSE
*
* 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
* 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, 2006-2010
- *
- * 2006-2007 Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM/MIPS
- * 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
+ * @section COPYRIGHT
+ *
+ * Copyright (C) Samsung Electronics, 2006-2014
+ *
+ * @section DESCRIPTION
+ *
+ * SWAP kprobe implementation for ARM architecture.
*/
#include <linux/module.h>
#include <linux/list.h>
#include <linux/hash.h>
-#define SUPRESS_BUG_MESSAGES
+#define SUPRESS_BUG_MESSAGES /**< Debug-off definition */
#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
return ok;
}
+/**
+ * @brief Creates ARM trampoline.
+ *
+ * @param addr Probe address.
+ * @param insn Instuction at this address.
+ * @param tramp Pointer to memory for trampoline.
+ * @return 0 on success, error code on error.
+ */
int arch_make_trampoline_arm(unsigned long addr, unsigned long insn,
unsigned long *tramp)
{
}
EXPORT_SYMBOL_GPL(arch_make_trampoline_arm);
+/**
+ * @brief Creates trampoline for kprobe.
+ *
+ * @param p Pointer to kprobe.
+ * @param sm Pointer to slot manager
+ * @return 0 on success, error code on error.
+ */
int swap_arch_prepare_kprobe(struct kprobe *p, struct slot_manager *sm)
{
unsigned long addr = (unsigned long)p->addr;
return 0;
}
+/**
+ * @brief Prepares singlestep for current CPU.
+ *
+ * @param p Pointer to kprobe.
+ * @param regs Pointer to CPU registers data.
+ * @return Void.
+ */
void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
int cpu = smp_processor_id();
}
EXPORT_SYMBOL_GPL(prepare_singlestep);
+/**
+ * @brief Saves previous kprobe.
+ *
+ * @param kcb Pointer to kprobe_ctlblk struct whereto save current kprobe.
+ * @param p_run Pointer to kprobe.
+ * @return Void.
+ */
void save_previous_kprobe(struct kprobe_ctlblk *kcb, struct kprobe *p_run)
{
kcb->prev_kprobe.kp = swap_kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status;
}
+/**
+ * @brief Restores previous kprobe.
+ *
+ * @param kcb Pointer to kprobe_ctlblk which contains previous kprobe.
+ * @return Void.
+ */
void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
__get_cpu_var(swap_current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status;
}
+/**
+ * @brief Sets currently running kprobe.
+ *
+ * @param p Pointer to currently running kprobe.
+ * @param regs Pointer to CPU registers data.
+ * @param kcb Pointer to kprobe_ctlblk.
+ * @return Void.
+ */
void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
{
__get_cpu_var(swap_current_kprobe) = p;
return 1;
}
+/**
+ * @brief Trap handler.
+ *
+ * @param regs Pointer to CPU register data.
+ * @param instr Instruction.
+ * @return kprobe_handler result.
+ */
int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
{
int ret;
return ret;
}
+/**
+ * @brief Probe pre handler.
+ *
+ * @param p Pointer to fired kprobe.
+ * @param regs Pointer to CPU registers data.
+ * @return 0.
+ */
int swap_setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
return 0;
}
+/**
+ * @brief Jprobe return stub.
+ *
+ * @return Void.
+ */
void swap_jprobe_return(void)
{
}
EXPORT_SYMBOL_GPL(swap_jprobe_return);
+/**
+ * @brief Break handler stub.
+ *
+ * @param p Pointer to fired kprobe.
+ * @param regs Pointer to CPU registers data.
+ * @return 0.
+ */
int swap_longjmp_break_handler (struct kprobe *p, struct pt_regs *regs)
{
return 0;
extern void mem_text_write_kernel_word(unsigned long *addr, unsigned long word);
#endif
+/**
+ * @brief Arms kprobe.
+ *
+ * @param p Pointer to target kprobe.
+ * @return Void.
+ */
void swap_arch_arm_kprobe(struct kprobe *p)
{
#ifdef CONFIG_STRICT_MEMORY_RWX
#endif
}
+/**
+ * @brief Disarms kprobe.
+ *
+ * @param p Pointer to target kprobe.
+ * @return Void.
+ */
void swap_arch_disarm_kprobe(struct kprobe *p)
{
#ifdef CONFIG_STRICT_MEMORY_RWX
#endif
}
+/**
+ * @brief Kretprobe trampoline. Provides jumping to probe handler.
+ *
+ * @return Void.
+ */
void __naked swap_kretprobe_trampoline(void)
{
__asm__ __volatile__ (
: : : "memory");
}
+/**
+ * @brief Prepares kretprobes, saves ret address, makes function return to
+ * trampoline.
+ *
+ * @param ri Pointer to kretprobe_instance.
+ * @param regs Pointer to CPU registers data.
+ * @return Void.
+ */
void swap_arch_prepare_kretprobe(struct kretprobe_instance *ri,
struct pt_regs *regs)
{
return data;
}
+/**
+ * @brief Trampoline for kjump kprobes.
+ *
+ * @return Void.
+ */
void kjump_trampoline(void);
__asm(
"kjump_trampoline: \n"
"nop \n" /* for kjump_kprobe */
);
+/**
+ * @brief Gets kjump address.
+ *
+ * @return Kjump address.
+ */
unsigned long get_kjump_addr(void)
{
return (unsigned long)&kjump_trampoline;
}
EXPORT_SYMBOL_GPL(get_kjump_addr);
+/**
+ * @brief Registers callback for kjump probes.
+ *
+ * @param ret_addr Kjump probe return address.
+ * @param regs Pointer to CPU registers data.
+ * @param cb Kjump probe callback of jumper_cb_t type.
+ * @param data Pointer to data that should be saved in kj_cb_data.
+ * @param size Size of the data.
+ * @return 0.
+ */
int set_kjump_cb(unsigned long ret_addr, struct pt_regs *regs,
jumper_cb_t cb, void *data, size_t size)
{
}
/* FIXME: restore condition flags */
+
+/**
+ * @brief Jumper trampoline.
+ *
+ * @return Void.
+ */
void jump_trampoline(void);
__asm(
"jump_trampoline: \n"
"bx lr \n"
);
+/**
+ * @brief Get jumper address.
+ *
+ * @return Jumper address.
+ */
unsigned long get_jump_addr(void)
{
return (unsigned long)&jump_trampoline;
}
EXPORT_SYMBOL_GPL(get_jump_addr);
+/**
+ * @brief Set jumper probe callback.
+ *
+ * @param ret_addr Jumper probe return address.
+ * @param regs Pointer to CPU registers data.
+ * @param cb Jumper callback of jumper_cb_t type.
+ * @param data Data that should be stored in cb_data.
+ * @param size Size of the data.
+ * @return 0.
+ */
int set_jump_cb(unsigned long ret_addr, struct pt_regs *regs,
jumper_cb_t cb, void *data, size_t size)
{
-
+/**
+ * @brief Registers hook on specified instruction.
+ *
+ * @param hook Pointer to struct undef_hook.
+ * @return Void.
+ */
void swap_register_undef_hook(struct undef_hook *hook)
{
__swap_register_undef_hook(hook);
}
EXPORT_SYMBOL_GPL(swap_register_undef_hook);
+/**
+ * @brief Unregisters hook.
+ *
+ * @param hook Pointer to struct undef_hook.
+ * @return Void.
+ */
void swap_unregister_undef_hook(struct undef_hook *hook)
{
__swap_unregister_undef_hook(hook);
.fn = kprobe_trap_handler
};
+/**
+ * @brief Initializes kprobes module for ARM arch.
+ *
+ * @return 0 on success, error code on error.
+ */
int swap_arch_init_kprobes(void)
{
int ret;
return 0;
}
+/**
+ * @brief Uninitializes kprobe module.
+ *
+ * @return Void.
+ */
void swap_arch_exit_kprobes(void)
{
kjump_exit();
-#ifndef _SWAP_ASM_ARM_KPROBES_H
-#define _SWAP_ASM_ARM_KPROBES_H
-
-/*
- * Dynamic Binary Instrumentation Module based on KProbes
- * modules/kprobe/arch/asm-arm/swap_kprobes.h
+/**
+ * @file kprobe/arch/asm-arm/swap_kprobes.h
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM/MIPS
+ * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial implementation; Support x86/ARM/MIPS for both user and kernel spaces.
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
+ * @author Alexander Shirshikov <a.shirshikov@samsung.com>: initial implementation for Thumb
+ *
+ * @section LICENSE
*
* 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
+ * @section COPYRIGHT
+ *
* Copyright (C) Samsung Electronics, 2006-2010
*
- * 2006-2007 Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM/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
+ * @section DESCRIPTION
*
- * 2010-2011 Alexander Shirshikov <a.shirshikov@samsung.com>: initial implementation for Thumb
+ * ARM arch-dependent kprobes interface declaration.
*/
+
+#ifndef _SWAP_ASM_ARM_KPROBES_H
+#define _SWAP_ASM_ARM_KPROBES_H
+
#include <linux/sched.h>
#include <linux/compiler.h>
typedef unsigned long kprobe_opcode_t;
#ifdef CONFIG_CPU_S3C2443
+/** Breakpoint instruction */
#define BREAKPOINT_INSTRUCTION 0xe1200070
#else
+/** Breakpoint instruction */
#define BREAKPOINT_INSTRUCTION 0xffffdeff
#endif /* CONFIG_CPU_S3C2443 */
#ifndef KPROBES_RET_PROBE_TRAMP
#ifdef CONFIG_CPU_S3C2443
+/** Undefined instruction */
#define UNDEF_INSTRUCTION 0xe1200071
#else
+/** Undefined instruction */
#define UNDEF_INSTRUCTION 0xfffffffe
#endif /* CONFIG_CPU_S3C2443 */
#endif /* KPROBES_RET_PROBE_TRAMP */
+/** Maximum insn size */
#define MAX_INSN_SIZE 1
+/** Uprobes trampoline length */
#define UPROBES_TRAMP_LEN 9 * 4
-# define UPROBES_TRAMP_INSN_IDX 2
-# define UPROBES_TRAMP_SS_BREAK_IDX 4
-# define UPROBES_TRAMP_RET_BREAK_IDX 5
+/** Uprobes trampoline insn idx */
+#define UPROBES_TRAMP_INSN_IDX 2
+/** Uprobes trampoline ss break idx */
+#define UPROBES_TRAMP_SS_BREAK_IDX 4
+/** Uprobes trampoline ret break idx */
+#define UPROBES_TRAMP_RET_BREAK_IDX 5
+/** Kprobes trampoline length */
#define KPROBES_TRAMP_LEN 9 * 4
+/** Kprobes trampoline insn idx */
# define KPROBES_TRAMP_INSN_IDX UPROBES_TRAMP_INSN_IDX
+/** Kprobes trampoline ss break idx */
# define KPROBES_TRAMP_SS_BREAK_IDX UPROBES_TRAMP_SS_BREAK_IDX
/* TODO: remove (not needed for kprobe) */
# define KPROBES_TRAMP_RET_BREAK_IDX UPROBES_TRAMP_RET_BREAK_IDX
+/** User register offset */
#define UREGS_OFFSET 8
+/**
+ * @struct prev_kprobe
+ * @brief Stores previous kprobe.
+ * @var prev_kprobe::kp
+ * Pointer to kprobe struct.
+ * @var prev_kprobe::status
+ * Kprobe status.
+ */
struct prev_kprobe {
struct kprobe *kp;
unsigned long status;
};
+/**
+ * @brief Gets task pc.
+ *
+ * @param p Pointer to task_struct
+ * @return Value in pc.
+ */
static inline unsigned long arch_get_task_pc(struct task_struct *p)
{
return task_thread_info(p)->cpu_context.pc;
}
+/**
+ * @brief Sets task pc.
+ *
+ * @param p Pointer to task_struct.
+ * @param val Value that should be set.
+ * @return Void.
+ */
static inline void arch_set_task_pc(struct task_struct *p, unsigned long val)
{
task_thread_info(p)->cpu_context.pc = val;
}
+/**
+ * @brief Gets syscall registers.
+ *
+ * @param sp Pointer to stack.
+ * @return Pointer to CPU regs data.
+ */
static inline struct pt_regs *swap_get_syscall_uregs(unsigned long sp)
{
return (struct pt_regs *)(sp + UREGS_OFFSET);
}
+/**
+ * @brief Gets stack pointer.
+ *
+ * @param regs Pointer to CPU registers data.
+ * @return Stack address.
+ */
static inline unsigned long swap_get_stack_ptr(struct pt_regs *regs)
{
return regs->ARM_sp;
}
+/**
+ * @brief Gets instruction pointer.
+ *
+ * @param regs Pointer to CPU registers data.
+ * @return Pointer to pc.
+ */
static inline unsigned long swap_get_instr_ptr(struct pt_regs *regs)
{
return regs->ARM_pc;
}
+/**
+ * @brief Sets instruction pointer.
+ *
+ * @param regs Pointer to CPU registers data.
+ * @param val Address that should be stored in pc.
+ * @return Void.
+ */
static inline void swap_set_instr_ptr(struct pt_regs *regs, unsigned long val)
{
regs->ARM_pc = val;
}
+/**
+ * @brief Gets return address.
+ *
+ * @param regs Pointer to CPU registers data.
+ * @return Return address.
+ */
static inline unsigned long swap_get_ret_addr(struct pt_regs *regs)
{
return regs->ARM_lr;
}
+/**
+ * @brief Sets return address.
+ *
+ * @param regs Pointer to CPU registers data.
+ * @param val New return address.
+ * @return Void.
+ */
static inline void swap_set_ret_addr(struct pt_regs *regs, unsigned long val)
{
regs->ARM_lr = val;
}
+/**
+ * @brief Gets specified argument.
+ *
+ * @param regs Pointer to CPU registers data.
+ * @param num Number of the argument.
+ * @return Argument value.
+ */
static inline unsigned long swap_get_arg(struct pt_regs *regs, int num)
{
return regs->uregs[num];
}
+/**
+ * @brief Sets specified argument.
+ *
+ * @param regs Pointer to CPU registers data.
+ * @param num Number of the argument.
+ * @param val New argument value.
+ * @return Void.
+ */
static inline void swap_set_arg(struct pt_regs *regs, int num,
unsigned long val)
{
# define THUMB2_INSN_REG_RM(insn) ((insn & 0x000f0000) >> 16)
-/* per-cpu kprobe control block */
+
+
+/**
+ * @struct kprobe_ctlblk
+ * @brief Per-cpu kprobe control block.
+ * @var kprobe_ctlblk::kprobe_status
+ * Kprobe status.
+ * @var kprobe_ctlblk::prev_kprobe
+ * Previous kprobe.
+ */
struct kprobe_ctlblk {
unsigned long kprobe_status;
struct prev_kprobe prev_kprobe;
};
-/* Architecture specific copy of original instruction */
+/**
+ * @struct arch_specific_insn
+ * @brief Architecture specific copy of original instruction.
+ * @var arch_specific_insn::insn
+ * Copy of the original instruction.
+ */
struct arch_specific_insn {
- /* copy of the original instruction */
kprobe_opcode_t *insn;
};
void swap_register_undef_hook(struct undef_hook *hook);
void swap_unregister_undef_hook(struct undef_hook *hook);
+/**
+ * @brief Arch-dependend module deps initialization stub.
+ *
+ * @return 0.
+ */
static inline int arch_init_module_deps(void)
{
return 0;
void __naked swap_kretprobe_trampoline(void);
+/**
+ * @brief Gets arguments of kernel functions.
+ *
+ * @param regs Pointer to CPU registers data.
+ * @param n Number of the argument.
+ * @return Argument value.
+ */
static inline unsigned long swap_get_karg(struct pt_regs *regs, unsigned long n)
{
switch (n) {
return *((unsigned long *)regs->ARM_sp + n - 4);
}
+/**
+ * @brief swap_get_karg wrapper.
+ *
+ * @param regs Pointer to CPU registers data.
+ * @param n Number of the argument.
+ * @return Argument value.
+ */
static inline unsigned long swap_get_sarg(struct pt_regs *regs, unsigned long n)
{
return swap_get_karg(regs, n);
-/*
- * Dynamic Binary Instrumentation Module based on KProbes
- * modules/kprobe/arch/asm-arm/trampoline_arm.h
+/**
+ * @file kprobe/arch/asm-arm/trampoline_arm.h
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM/MIPS
+ * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space
+ * Probes initial implementation; Support x86/ARM/MIPS for both user and kernel spaces.
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
+ * @author Alexander Shirshikov <a.shirshikov@samsung.com>: initial implementation for Thumb
+ *
+ * @section LICENSE
*
* 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
+ * @section COPYRIGHT
+ *
* Copyright (C) Samsung Electronics, 2006-2010
*
- * 2006-2007 Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM/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
+ * @section DESCRIPTION
*
- * 2010-2011 Alexander Shirshikov <a.shirshikov@samsung.com>: initial implementation for Thumb
+ * Provides intefrace for trampoline_arm.S
*/
#ifndef __ASM_ARM_TRAMPOLINE_ARM_H
-/*
- * Kernel Probes (KProbes)
- * arch/x86/kernel/kprobes.c
+/**
+ * arch/asm-x86/swap_kprobes.c
+ * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial implementation;
+ * Support x86/ARM/MIPS for both user and kernel spaces.
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
+ * @author Stanislav Andreev <s.andreev@samsung.com>: added time debug profiling support; BUG() message fix
+ *
+ * @section LICENSE
*
* 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
* 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) IBM Corporation, 2002, 2004
- */
-
-/*
- * Dynamic Binary Instrumentation Module based on KProbes
- * modules/kprobe/arch/asm-x86/swap_kprobes.c
- *
- * 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.
+ * @section COPYRIGHT
*
- * 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) IBM Corporation, 2002, 2004
*
- * Copyright (C) Samsung Electronics, 2006-2010
+ * @section DESCRIPTION
*
- * 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
- * 2012 Stanislav Andreev <s.andreev@samsung.com>: added time debug profiling support; BUG() message fix
+ * SWAP krpobes arch-dependend part for x86.
*/
#include<linux/module.h>
#include <kprobe/swap_kdebug.h>
#include <kprobe/swap_slots.h>
#include <kprobe/swap_kprobes_deps.h>
-#define SUPRESS_BUG_MESSAGES
+#define SUPRESS_BUG_MESSAGES /**< Debug-off definition. */
extern struct kprobe * per_cpu__current_kprobe;
extern struct kprobe * per_cpu__current_kprobe;
static void (*swap_show_registers)(struct pt_regs * regs);
+/** Stack address. */
#define stack_addr(regs) ((unsigned long *)kernel_stack_pointer(regs))
/*
jop->op = RELATIVEJUMP_INSTRUCTION;
}
-/*
- * returns non-zero if opcodes can be boosted.
+/**
+ * @brief Check if opcode can be boosted.
+ *
+ * @param opcodes Opcode to check.
+ * @return Non-zero if opcode can be boosted.
*/
int swap_can_boost(kprobe_opcode_t *opcodes)
{
return 0;
}
+/**
+ * @brief Creates trampoline for kprobe.
+ *
+ * @param p Pointer to kprobe.
+ * @param sm Pointer to slot manager
+ * @return 0 on success, error code on error.
+ */
int swap_arch_prepare_kprobe(struct kprobe *p, struct slot_manager *sm)
{
/* insn: must be on special executable page on i386. */
return 0;
}
+/**
+ * @brief Prepares singlestep for current CPU.
+ *
+ * @param p Pointer to kprobe.
+ * @param regs Pointer to CPU registers data.
+ * @return Void.
+ */
void prepare_singlestep (struct kprobe *p, struct pt_regs *regs)
{
int cpu = smp_processor_id();
}
EXPORT_SYMBOL_GPL(prepare_singlestep);
+/**
+ * @brief Saves previous kprobe.
+ *
+ * @param kcb Pointer to kprobe_ctlblk struct whereto save current kprobe.
+ * @param p_run Pointer to kprobe.
+ * @return Void.
+ */
void save_previous_kprobe (struct kprobe_ctlblk *kcb, struct kprobe *cur_p)
{
if (kcb->prev_kprobe.kp != NULL)
}
+/**
+ * @brief Restores previous kprobe.
+ *
+ * @param kcb Pointer to kprobe_ctlblk which contains previous kprobe.
+ * @return Void.
+ */
void restore_previous_kprobe (struct kprobe_ctlblk *kcb)
{
__get_cpu_var(swap_current_kprobe) = kcb->prev_kprobe.kp;
kcb->prev_kprobe.status = 0;
}
+/**
+ * @brief Sets currently running kprobe.
+ *
+ * @param p Pointer to currently running kprobe.
+ * @param regs Pointer to CPU registers data.
+ * @param kcb Pointer to kprobe_ctlblk.
+ * @return Void.
+ */
void set_current_kprobe (struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
{
__get_cpu_var(swap_current_kprobe) = p;
kcb->kprobe_saved_eflags &= ~IF_MASK;
}
+/**
+ * @brief Kprobe handler.
+ *
+ * @param regs Pointer to CPU register data.
+ * @return 1 on success.
+ */
int kprobe_handler (struct pt_regs *regs)
{
struct kprobe *p = 0;
return ret;
}
+/**
+ * @brief Probe pre handler.
+ *
+ * @param p Pointer to fired kprobe.
+ * @param regs Pointer to CPU registers data.
+ * @return 0.
+ */
int swap_setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of (p, struct jprobe, kp);
return 1;
}
+/**
+ * @brief Jprobe return end.
+ *
+ * @return Void.
+ */
void swap_jprobe_return_end(void);
+/**
+ * @brief Jprobe return code.
+ *
+ * @return Void.
+ */
void swap_jprobe_return(void)
{
struct kprobe_ctlblk *kcb = swap_get_kprobe_ctlblk();
.priority = INT_MAX
};
+/**
+ * @brief Longjump break handler.
+ *
+ * @param p Pointer to fired kprobe.
+ * @param regs Pointer to CPU registers data.
+ * @return 0 on success.
+ */
int swap_longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kprobe_ctlblk *kcb = swap_get_kprobe_ctlblk();
return 0;
}
+/**
+ * @brief Arms kprobe.
+ *
+ * @param p Pointer to target kprobe.
+ * @return Void.
+ */
void swap_arch_arm_kprobe(struct kprobe *p)
{
swap_text_poke(p->addr,
((unsigned char[]){BREAKPOINT_INSTRUCTION}), 1);
}
+/**
+ * @brief Disarms kprobe.
+ *
+ * @param p Pointer to target kprobe.
+ * @return Void.
+ */
void swap_arch_disarm_kprobe(struct kprobe *p)
{
swap_text_poke(p->addr, &p->opcode, 1);
return (void *)trampoline_probe_handler(NULL, regs);
}
+/**
+ * @brief Prepares kretprobes, saves ret address, makes function return to
+ * trampoline.
+ *
+ * @param ri Pointer to kretprobe_instance.
+ * @param regs Pointer to CPU registers data.
+ * @return Void.
+ */
void swap_arch_prepare_kretprobe(struct kretprobe_instance *ri,
struct pt_regs *regs)
{
*ptr_ret_addr = (unsigned long)&swap_kretprobe_trampoline;
}
+/**
+ * @brief Initializes x86 module deps.
+ *
+ * @return 0 on success, negative error code on error.
+ */
int arch_init_module_deps()
{
const char *sym;
return -ESRCH;
}
+/**
+ * @brief Initializes kprobes module for ARM arch.
+ *
+ * @return 0 on success, error code on error.
+ */
int swap_arch_init_kprobes(void)
{
return register_die_notifier (&kprobe_exceptions_nb);
}
+/**
+ * @brief Uninitializes kprobe module.
+ *
+ * @return Void.
+ */
void swap_arch_exit_kprobes(void)
{
unregister_die_notifier (&kprobe_exceptions_nb);
-#ifndef _SWAP_ASM_X86_KPROBES_H
-#define _SWAP_ASM_X86_KPROBES_H
-
-/*
- * Kernel Probes (KProbes)
- * include/linux/kprobes.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.
+/**
+ * @file kprobe/arch/asm-x86/swap_kprobes.h
+ * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial implementation;
+ * Support x86/ARM/MIPS for both user and kernel spaces.
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
*
- * Copyright (C) IBM Corporation, 2002, 2004
- */
-
-/*
- * Dynamic Binary Instrumentation Module based on KProbes
- * modules/kprobe/arch/asm-x86/swap_kprobes.c
+ * @section LICENSE
*
* 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
+ * @section COPYRIGHT
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
* Copyright (C) Samsung Electronics, 2006-2010
*
- * 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
+ * @section DESCRIPTION
*
-
+ * Arch-dependent kprobes interface for x86 arch.
*/
+#ifndef _SWAP_ASM_X86_KPROBES_H
+#define _SWAP_ASM_X86_KPROBES_H
+
+
#include <linux/version.h>
#include <kprobe/swap_kprobes_deps.h>
+/**
+ * @brief Opcode type.
+ */
typedef u8 kprobe_opcode_t;
#define BREAKPOINT_INSTRUCTION 0xcc
return i;
}
+/**
+ * @struct prev_kprobe
+ * @brief Stores previous kprobe.
+ * @var prev_kprobe::kp
+ * Pointer to kprobe struct.
+ * @var prev_kprobe::status
+ * Kprobe status.
+ */
struct prev_kprobe {
struct kprobe *kp;
unsigned long status;
};
-/* per-cpu kprobe control block */
+/**
+ * @struct kprobe_ctlblk
+ * @brief Per-cpu kprobe control block.
+ * @var kprobe_ctlblk::kprobe_status
+ * Kprobe status.
+ * @var kprobe_ctlblk::prev_kprobe
+ * Previous kprobe.
+ */
struct kprobe_ctlblk {
unsigned long kprobe_status;
struct prev_kprobe prev_kprobe;
};
-/* Architecture specific copy of original instruction */
+/**
+ * @struct arch_specific_insn
+ * @brief Architecture specific copy of original instruction.
+ * @var arch_specific_insn::insn
+ * Copy of the original instruction.
+ * @var arch_specific_insn::boostable
+ * If this flag is not 0, this kprobe can be boost when its
+ * post_handler and break_handler is not set.
+ */
struct arch_specific_insn {
- /* copy of the original instruction */
kprobe_opcode_t *insn;
- /*
- * If this flag is not 0, this kprobe can be boost when its
- * post_handler and break_handler is not set.
- */
int boostable;
};
+/**
+ * @brief Entry point.
+ */
typedef kprobe_opcode_t (*entry_point_t) (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
int arch_init_module_deps(void);
-#ifndef _SWAP_KPROBE_DEBUG_H
-#define _SWAP_KPROBE_DEBUG_H
-
-/*
- * Dynamic Binary Instrumentation Module based on KProbes
- * modules/kprobe/swap_kdebug.h
+/**
+ * @file kprobe/swap_kdebug.h
+ * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial implementation;
+ * Support x86/ARM/MIPS for both user and kernel spaces.
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
+ *
+ * @section LICENSE
*
* 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
+ * @section COPYRIGHT
+ *
* Copyright (C) Samsung Electronics, 2006-2010
*
- * 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
+ * @section DESCRIPTION
*
-*/
+ * Header for debug purposes.
+ */
+
+
+#ifndef _SWAP_KPROBE_DEBUG_H
+#define _SWAP_KPROBE_DEBUG_H
//#define _DEBUG
-/*
- * Kernel Probes (KProbes)
- * kernel/kprobes.c
- *
- * 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.
+/**
+ * kprobe/swap_kprobes.c
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM and MIPS
+ * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial implementation;
+ * Support x86/ARM/MIPS for both user and kernel spaces.
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
*
- * Copyright (C) IBM Corporation, 2002, 2004
- */
-
-/*
- * Dynamic Binary Instrumentation Module based on KProbes
- * modules/kprobe/swap_kprobes.h
+ * @section LICENSE
*
* 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
+ * @section COPYRIGHT
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
* Copyright (C) Samsung Electronics, 2006-2010
*
- * 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
+ * @section DESCRIPTION
*
+ * SWAP kprobe implementation. Dynamic kernel functions instrumentation.
*/
-
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
#include <linux/config.h>
#include "swap_kprobes.h"
#include "swap_kprobes_deps.h"
-
+/**
+ * @var sched_addr
+ * @brief Scheduler address.
+ */
unsigned long sched_addr;
static unsigned long exit_addr;
static unsigned long do_group_exit_addr;
static unsigned long sys_exit_group_addr;
static unsigned long sys_exit_addr;
+/**
+ * @var sm
+ * @brief Current slot manager. Slots are the places where trampolines are
+ * located.
+ */
struct slot_manager sm;
DEFINE_PER_CPU(struct kprobe *, swap_current_kprobe) = NULL;
struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
+/**
+ * @var kprobe_count
+ * @brief Count of kprobes.
+ */
atomic_t kprobe_count;
EXPORT_SYMBOL_GPL(kprobe_count);
__get_cpu_var(kprobe_instance) = NULL;
}
-/* swap_kprobe_running() will just return the current_kprobe on this CPU */
+/**
+ * @brief Gets the current kprobe on this CPU.
+ *
+ * @return Pointer to the current kprobe.
+ */
struct kprobe *swap_kprobe_running(void)
{
return __get_cpu_var(swap_current_kprobe);
}
+/**
+ * @brief Sets the current kprobe to NULL.
+ *
+ * @return Void.
+ */
void swap_reset_current_kprobe(void)
{
__get_cpu_var(swap_current_kprobe) = NULL;
}
+/**
+ * @brief Gets kprobe_ctlblk for the current CPU.
+ *
+ * @return Current CPU struct kprobe_ctlblk.
+ */
struct kprobe_ctlblk *swap_get_kprobe_ctlblk(void)
{
return &__get_cpu_var(kprobe_ctlblk);
* OR
* - with preemption disabled - from arch/xxx/kernel/kprobes.c
*/
+
+/**
+ * @brief Gets kprobe.
+ *
+ * @param addr Probe address.
+ * @return Kprobe for addr.
+ */
struct kprobe *swap_get_kprobe(void *addr)
{
struct hlist_head *head;
return ret;
}
-/* Walks the list and increments nmissed count for multiprobe case */
+/**
+ * @brief Walks the list and increments nmissed count for multiprobe case.
+ *
+ * @param p Pointer to the missed kprobe.
+ * @return Void.
+ */
void swap_kprobes_inc_nmissed_count(struct kprobe *p)
{
struct kprobe *kp;
swap_slot_free(&sm, p->ainsn.insn);
}
+/**
+ * @brief Registers kprobe.
+ *
+ * @param p Pointer to the target kprobe.
+ * @return 0 on success, error code on error.
+ */
int swap_register_kprobe(struct kprobe *p)
{
struct kprobe *old_p;
p->addr = NULL;
}
+/**
+ * @brief Unregistes kprobe.
+ *
+ * @param kp Pointer to the target kprobe.
+ * @return Void.
+ */
void swap_unregister_kprobe(struct kprobe *kp)
{
struct kprobe *old_p, *list_p;
}
EXPORT_SYMBOL_GPL(swap_unregister_kprobe);
+/**
+ * @brief Registers jprobe.
+ *
+ * @param jp Pointer to the target jprobe.
+ * @return swap_register_kprobe result.
+ */
int swap_register_jprobe(struct jprobe *jp)
{
/* Todo: Verify probepoint is a function entry point */
}
EXPORT_SYMBOL_GPL(swap_register_jprobe);
+/**
+ * @brief Unregisters jprobe.
+ *
+ * @param jp Pointer to the target jprobe.
+ * @return Void.
+ */
void swap_unregister_jprobe(struct jprobe *jp)
{
swap_unregister_kprobe(&jp->kp);
return 0;
}
+/**
+ * @brief Trampoline probe handler.
+ *
+ * @param p Pointer to the fired kprobe.
+ * @param regs Pointer to CPU registers data.
+ * @return orig_ret_address
+ */
int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kretprobe_instance *ri = NULL;
return 0;
}
+/**
+ * @brief Registers kretprobes.
+ *
+ * @param rp Pointer to the target kretprobe.
+ * @return 0 on success, error code on error.
+ */
int swap_register_kretprobe(struct kretprobe *rp)
{
int ret = 0;
}
}
+/**
+ * @brief Kretprobes unregister top. Unregisters kprobes.
+ *
+ * @param rps Pointer to the array of pointers to the target kretprobes.
+ * @param size Size of rps array.
+ * @param rp_disarm Disarm flag. If set kretprobe is disarmed.
+ * @return Void.
+ */
void swap_unregister_kretprobes_top(struct kretprobe **rps, size_t size,
int rp_disarm)
{
}
EXPORT_SYMBOL_GPL(swap_unregister_kretprobes_top);
+/**
+ * @brief swap_unregister_kretprobes_top wrapper for a single kretprobe.
+ *
+ * @param rp Pointer to the target kretprobe.
+ * @param rp_disarm Disarm flag.
+ * @return Void.
+ */
void swap_unregister_kretprobe_top(struct kretprobe *rp, int rp_disarm)
{
swap_unregister_kretprobes_top(&rp, 1, rp_disarm);
}
EXPORT_SYMBOL_GPL(swap_unregister_kretprobe_top);
+/**
+ * @brief Kretprobe unregister bottom. Here is kretprobe memory is released.
+ *
+ * @param rp Pointer to the target kretprobe.
+ * @return Void.
+ */
void swap_unregister_kretprobe_bottom(struct kretprobe *rp)
{
unsigned long flags;
}
EXPORT_SYMBOL_GPL(swap_unregister_kretprobe_bottom);
+/**
+ * @brief swap_unregister_kretprobe_bottom wrapper for several kretprobes.
+ *
+ * @param rps Pointer to the array of the target kretprobes pointers.
+ * @param size Size of rps array.
+ * @return Void.
+ */
void swap_unregister_kretprobes_bottom(struct kretprobe **rps, size_t size)
{
const size_t end = ((size_t) 0) - 1;
}
EXPORT_SYMBOL_GPL(swap_unregister_kretprobes_bottom);
+/**
+ * @brief Unregisters kretprobes.
+ *
+ * @param rpp Pointer to the array of the target kretprobes pointers.
+ * @param size Size of rpp array.
+ * @return Void.
+ */
void swap_unregister_kretprobes(struct kretprobe **rpp, size_t size)
{
swap_unregister_kretprobes_top(rpp, size, 1);
}
EXPORT_SYMBOL_GPL(swap_unregister_kretprobes);
+/**
+ * @brief swap_unregister_kretprobes wrapper for a single kretprobe.
+ *
+ * @param rp Pointer to the target kretprobe.
+ * @return Void.
+ */
void swap_unregister_kretprobe(struct kretprobe *rp)
{
swap_unregister_kretprobes(&rp, 1);
-#ifndef _SWAP_KPROBES_H
-#define _SWAP_KPROBES_H
-
-/*
- * Kernel Probes (KProbes)
- * include/linux/kprobes.h
+/**
+ * @file kprobe/swap_kprobes.h
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM and MIPS
+ * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial implementation;
+ * Support x86/ARM/MIPS for both user and kernel spaces.
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
*
- * 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) IBM Corporation, 2002, 2004
- */
-
-/*
- * Dynamic Binary Instrumentation Module based on KProbes
- * modules/kprobe/swap_kprobes.h
+ * @section LICENSE
*
* 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
+ * @section COPYRIGHT
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
* Copyright (C) Samsung Electronics, 2006-2010
*
- * 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
+ * @section DESCRIPTION
*
+ * SWAP kprobe interface definition.
*/
+#ifndef _SWAP_KPROBES_H
+#define _SWAP_KPROBES_H
+
#include <linux/version.h> // LINUX_VERSION_CODE, KERNEL_VERSION()
#include <linux/notifier.h>
#include <linux/percpu.h>
/* kprobe_status settings */
+/** Kprobe hit active */
#define KPROBE_HIT_ACTIVE 0x00000001
+/** Kprobe hit ss */
#define KPROBE_HIT_SS 0x00000002
+/** Kprobe reenter */
#define KPROBE_REENTER 0x00000004
+/** Kprobe hit ss done */
#define KPROBE_HIT_SSDONE 0x00000008
+/** High word */
#define HIWORD(x) (((x) & 0xFFFF0000) >> 16)
+/** Low word */
#define LOWORD(x) ((x) & 0x0000FFFF)
+/** Invalid value */
#define INVALID_VALUE 0xFFFFFFFF
+/** Invalid pointer */
#define INVALID_POINTER (void*)INVALID_VALUE
+/** Jprobe entry */
#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
+/** Retprobe stack depth */
#define RETPROBE_STACK_DEPTH 64
struct kprobe;
struct pt_regs;
struct kretprobe;
struct kretprobe_instance;
+
+/**
+ * @brief Kprobe pre-handler pointer.
+ */
typedef int (*kprobe_pre_handler_t) (struct kprobe *, struct pt_regs *);
+
+/**
+ * @brief Kprobe break handler pointer.
+ */
typedef int (*kprobe_break_handler_t) (struct kprobe *, struct pt_regs *);
+
+/**
+ * @brief Kprobe post handler pointer.
+ */
typedef void (*kprobe_post_handler_t) (struct kprobe *, struct pt_regs *, unsigned long flags);
+
+/**
+ * @brief Kprobe fault handler pointer.
+ */
typedef int (*kprobe_fault_handler_t) (struct kprobe *, struct pt_regs *, int trapnr);
+
+/**
+ * @brief Kretprobe handler pointer.
+ */
typedef int (*kretprobe_handler_t) (struct kretprobe_instance *, struct pt_regs *);
+/**
+ * @struct kprobe
+ * @brief Main kprobe struct.
+ */
struct kprobe
{
- struct hlist_node hlist;
- /*list of probes to search by instruction slot*/
+ struct hlist_node hlist; /**< Hash list.*/
+ /** List of probes to search by instruction slot.*/
struct hlist_node is_hlist;
- /* list of kprobes for multi-handler support */
+ /** List of kprobes for multi-handler support.*/
struct list_head list;
- /* Indicates that the corresponding module has been ref counted */
+ /** Indicates that the corresponding module has been ref counted.*/
unsigned int mod_refcounted;
- /*count the number of times this probe was temporarily disarmed */
+ /** Count the number of times this probe was temporarily disarmed.*/
unsigned long nmissed;
- /* location of the probe point */
+ /** Location of the probe point. */
kprobe_opcode_t *addr;
- /* Allow user to indicate symbol name of the probe point */
+ /** Allow user to indicate symbol name of the probe point.*/
char *symbol_name;
- /* Offset into the symbol */
+ /** Offset into the symbol.*/
unsigned int offset;
- /* Called before addr is executed. */
+ /** Called before addr is executed.*/
kprobe_pre_handler_t pre_handler;
- /* Called after addr is executed, unless... */
+ /** Called after addr is executed, unless...*/
kprobe_post_handler_t post_handler;
- /* ... called if executing addr causes a fault (eg. page fault).
- * Return 1 if it handled fault, otherwise kernel will see it. */
+ /** ... called if executing addr causes a fault (eg. page fault).*/
kprobe_fault_handler_t fault_handler;
- /* ... called if breakpoint trap occurs in probe handler.
- * Return 1 if it handled break, otherwise kernel will see it. */
+ /** Return 1 if it handled fault, otherwise kernel will see it.*/
kprobe_break_handler_t break_handler;
- /* Saved opcode (which has been replaced with breakpoint) */
+ /** Saved opcode (which has been replaced with breakpoint).*/
kprobe_opcode_t opcode;
- /* copy of the original instruction */
+ /** Copy of the original instruction.*/
struct arch_specific_insn ainsn;
- // override single-step target address,
- // may be used to redirect control-flow to arbitrary address after probe point
- // without invocation of original instruction;
- // useful for functions replacement
- // if jprobe.entry should return address of function or NULL
- // if original function should be called
- // not supported for X86, not tested for MIPS
+ /** Override single-step target address, may be used to redirect
+ * control-flow to arbitrary address after probe point without
+ * invocation of original instruction; useful for functions
+ * replacement. If jprobe.entry should return address of function or
+ * NULL if original function should be called.
+ * Not supported for X86, not tested for MIPS. */
kprobe_opcode_t *ss_addr[NR_CPUS];
- // safe/unsafe to use probe
#ifdef CONFIG_ARM
+ /** Safe/unsafe to use probe on ARM.*/
unsigned safe_arm:1;
+ /** Safe/unsafe to use probe on Thumb.*/
unsigned safe_thumb:1;
#endif
};
+/**
+ * @brief Kprobe pre-entry handler pointer.
+ */
typedef unsigned long (*kprobe_pre_entry_handler_t) (void *priv_arg, struct pt_regs * regs);
-/*
- * Special probe type that uses setjmp-longjmp type tricks to resume
+
+/**
+ * @struct jprobe
+ * @brief Special probe type that uses setjmp-longjmp type tricks to resume
* execution at a specified entry with a matching prototype corresponding
* to the probed function - a trick to enable arguments to become
* accessible seamlessly by probe handling logic.
* Because of the way compilers allocate stack space for local variables
* etc upfront, regardless of sub-scopes within a function, this mirroring
* principle currently works only for probes placed on function entry points.
- */
+ */
struct jprobe
{
- struct kprobe kp;
- // probe handling code to jump to
- kprobe_opcode_t *entry;
- // handler whichw willb bec called before 'entry'
+ struct kprobe kp; /**< This probes kprobe.*/
+ kprobe_opcode_t *entry; /**< Probe handling code to jump to.*/
+ /** Handler which will be called before 'entry'. */
kprobe_pre_entry_handler_t pre_entry;
- void *priv_arg;
+ void *priv_arg; /**< Private args.*/
};
+
+/**
+ * @struct jprobe_instance
+ * @brief Jprobe instance struct.
+ */
struct jprobe_instance
{
// either on free list or used list
- struct hlist_node uflist;
- struct hlist_node hlist;
- struct jprobe *jp;
+ struct hlist_node uflist; /**< Jprobes hash list. */
+ struct hlist_node hlist; /**< Jprobes hash list. */
+ struct jprobe *jp; /**< Pointer to the target jprobe. */
+ /** Pointer to the target task_struct. */
struct task_struct *task;
};
-/*
- * Function-return probe -
- * Note:
- * User needs to provide a handler function, and initialize maxactive.
- * maxactive - The maximum number of instances of the probed function that
- * can be active concurrently.
- * nmissed - tracks the number of times the probed function's return was
- * ignored, due to maxactive being too low.
- *
+/**
+ * @struct kretprobe
+ * @brief Function-return probe
+ * Note: User needs to provide a handler function, and initialize maxactive.
*/
struct kretprobe
{
- struct kprobe kp;
- kretprobe_handler_t handler;
- kretprobe_handler_t entry_handler;
+ struct kprobe kp; /**< Kprobe of this kretprobe.*/
+ kretprobe_handler_t handler; /**< Handler of this kretprobe.*/
+ kretprobe_handler_t entry_handler; /**< Entry handler of this kretprobe.*/
+ /** The maximum number of instances of the probed function that can be
+ * active concurrently. */
int maxactive;
+ /** Tracks the number of times the probed function's return was ignored,
+ * due to maxactive being too low. */
int nmissed;
- size_t data_size;
+ size_t data_size; /**< Size of the data. */
+ /** List of this probe's free_instances. */
struct hlist_head free_instances;
+ /** List of this probe's used_instances. */
struct hlist_head used_instances;
#ifdef CONFIG_ARM
- // probe with noreturn (bl,blx)
- unsigned arm_noret:1;
- unsigned thumb_noret:1;
+ unsigned arm_noret:1; /**< No-return flag for ARM.*/
+ unsigned thumb_noret:1; /**< No-return flag for Thumb.*/
#endif
};
+/**
+ * @struct kretprobe_instance
+ * @brief Instance of kretprobe.
+ */
struct kretprobe_instance
{
// either on free list or used list
- struct hlist_node uflist;
- struct hlist_node hlist;
- struct kretprobe *rp;
- unsigned long *ret_addr;
- unsigned long *sp;
- struct task_struct *task;
- char data[0];
+ struct hlist_node uflist; /**< Kretprobe hash list.*/
+ struct hlist_node hlist; /**< Kretprobe hash list.*/
+ struct kretprobe *rp; /**< Pointer to this instance's kretprobe.*/
+ unsigned long *ret_addr; /**< Return address.*/
+ unsigned long *sp; /**< Stack pointer.*/
+ struct task_struct *task; /**< Pointer to the target task_struct.*/
+ char data[0]; /**< Pointer to data.*/
};
-/*
- * Dynamic Binary Instrumentation Module based on KProbes
- * modules/kprobe/swap_kprobes_deps.h
+/**
+ * kprobe/swap_kprobes_deps.c
+ * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial implementation;
+ * Support x86/ARM/MIPS for both user and kernel spaces.
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
+ *
+ * @section LICENSE
*
* 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
+ * @section COPYRIGHT
+ *
* Copyright (C) Samsung Electronics, 2006-2010
*
- * 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
+ * @section DESCRIPTION
*
+ * SWAP kprobe kernel-dependent dependencies.
*/
#include <linux/module.h>
-
+/**
+ * @brief Initializes module dependencies.
+ *
+ * @return 0.
+ */
int init_module_dependencies(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+/**
+ * @brief Gets user pages uprobe.
+ *
+ * @param tsk Pointer to the task_struct.
+ * @param mm Pointer to the mm_struct.
+ * @param start Starting address.
+ * @param nr_pages Pages number.
+ * @param gup_flags Flags.
+ * @param pages Pointer to the array of pointers to the target page structs.
+ * @param vmas Pointer to the array of pointers to the target vm_area_struct.
+ * @param nonblocking Pointer to int.
+ * @return negative error code on error, positive result otherwise.
+ */
long __get_user_pages_uprobe(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, unsigned long nr_pages,
unsigned int gup_flags, struct page **pages,
#endif
#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
+/**
+ * @brief Gets user pages uprobe.
+ *
+ * @param tsk Pointer to the task_struct.
+ * @param mm Pointer to the mm_struct.
+ * @param start Starting address.
+ * @param len Length.
+ * @param write Write flag.
+ * @param force Force flag.
+ * @param pages Pointer to the array of pointers to the target page structs.
+ * @param vmas Pointer to the array of pointers to the target vm_area_struct.
+ * @return negative error code on error, positive result otherwise.
+ */
int get_user_pages_uprobe(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, int len, int write, int force,
struct page **pages, struct vm_area_struct **vmas)
}
#endif
+/**
+ * @brief Read-write task memory.
+ *
+ * @param tsk Pointer to the target task task_struct.
+ * @param addr Address to read-write.
+ * @param buf Pointer to buffer where to put-get data.
+ * @param len Buffer length.
+ * @param write Write flag. If 0 - reading, if 1 - writing.
+ * @return Read-write size, error code on error.
+ */
int access_process_vm_atomic(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
{
struct mm_struct *mm;
return buf - old_buf;
}
+/**
+ * @brief Page present.
+ *
+ * @param mm Pointer to the target mm_struct.
+ * @param address Address.
+ */
int page_present (struct mm_struct *mm, unsigned long address)
{
pgd_t *pgd;
-#ifndef _SWAP_KPROBES_DEPS_H
-#define _SWAP_KPROBES_DEPS_H
-
-/*
- * Dynamic Binary Instrumentation Module based on KProbes
- * modules/kprobe/swap_kprobes_deps.h
+/**
+ * @file kprobe/swap_kprobes_deps.h
+ * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial implementation;
+ * Support x86/ARM/MIPS for both user and kernel spaces.
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
+ *
+ * @section LICENSE
*
* 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
+ * @section COPYRIGHT
+ *
* Copyright (C) Samsung Electronics, 2006-2010
*
- * 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
+ * @section DESCRIPTION
*
+ * SWAP kprobe kernel-dependent dependencies.
*/
+#ifndef _SWAP_KPROBES_DEPS_H
+#define _SWAP_KPROBES_DEPS_H
+
#include <linux/version.h> // LINUX_VERSION_CODE, KERNEL_VERSION()
#include <linux/hugetlb.h>
#include <linux/mempolicy.h>
-/*
- * Kernel Probes (KProbes)
- * kernel/kprobes.c
+/**
+ * kprobe/swap_slots.c
+ * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial implementation;
+ * Support x86/ARM/MIPS for both user and kernel spaces.
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com> new memory allocator for slots
*
- * 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) IBM Corporation, 2002, 2004
- */
-
-/*
- * Dynamic Binary Instrumentation Module based on KProbes
- * modules/kprobe/swap_slots.c
+ * @section LICENSE
*
* 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
+ * @section COPYRIGHT
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
* Copyright (C) Samsung Electronics, 2006-2012
*
- * 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
- * 2012-2013 Vyacheslav Cherkashin <v.cherkashin@samsung.com> new memory allocator for slots
+ * @section DESCRIPTION
+ *
+ * SWAP slots implementation.
*/
#include "swap_kprobes_deps.h"
+/**
+ * @struct chunk
+ * @brief Chunk of memory for trampolines.
+ * @var chunk::data
+ * Chunk data.
+ * @var chunk::first_available
+ * Index of the first available block.
+ * @var chunk::count_available
+ * Count of the blocks.
+ * @var chunk::lock
+ * Chunk's lock.
+ * @var chunk::size
+ * Count of the blocks in chunk.
+ * @var chunk::index
+ * Pointer to allocated memory.
+ */
struct chunk {
unsigned long *data;
unsigned long first_available;
unsigned long *index;
};
+/**
+ * @struct fixed_alloc
+ * @brief Item of fixed allocs list.
+ * @var fixed_alloc::hlist
+ * Fixed alloc hash list node.
+ * @var fixed_alloc::chunk
+ * Chunk.
+ */
struct fixed_alloc
{
struct hlist_node hlist;
}
+/**
+ * @brief Allocates slot for slot manager.
+ *
+ * @param[in,out] sm Slot manager that should be filled.
+ * @return Pointer to allocated slot.
+ */
void *swap_slot_alloc(struct slot_manager *sm)
{
void *free_slot;
}
EXPORT_SYMBOL_GPL(swap_slot_alloc);
+/**
+ * @brief Releases allocated slot.
+ *
+ * @param sm Pointer to the target slot manager.
+ * @param slot Pointer to the target slot.
+ * @return Void.
+ */
void swap_slot_free(struct slot_manager *sm, void *slot)
{
struct fixed_alloc *fa;
-#ifndef _SWAP_SLOTS_H
-#define _SWAP_SLOTS_H
-
-/*
- * Kernel Probes (KProbes)
- * include/linux/kprobes.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.
+/**
+ * @file kprobe/swap_slots.h
+ * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial implementation;
+ * Support x86/ARM/MIPS for both user and kernel spaces.
+ * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com> new memory allocator for slots
*
- * 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) IBM Corporation, 2002, 2004
- */
-
-/*
- * Dynamic Binary Instrumentation Module based on KProbes
- * modules/kprobe/swap_slots.h
+ * @section LICENSE
*
* 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
+ * @section COPYRIGHT
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
* Copyright (C) Samsung Electronics, 2006-2010
*
- * 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
- * 2012-2013 Vyacheslav Cherkashin <v.cherkashin@samsung.com> new memory allocator for slots
+ * @section DESCRIPTION
+ *
+ * SWAP slots interface declaration.
*/
+#ifndef _SWAP_SLOTS_H
+#define _SWAP_SLOTS_H
+
#include <linux/types.h>
+/**
+ * @struct slot_manager
+ * @brief Manage slots.
+ * @var slot_manager::slot_size
+ * Size of the slot.
+ * @var slot_manager::alloc
+ * Memory allocation callback.
+ * @var slot_manager::free
+ * Memory release callback.
+ * @var slot_manager::page_list
+ * List of pages.
+ * @var slot_manager::data
+ * Slot manager data. task_struct pointer usually stored here.
+ */
struct slot_manager {
unsigned long slot_size; /* FIXME: allocated in long (4 byte) */
void *(*alloc)(struct slot_manager *sm);