-EXTRA_CFLAGS := -I$(src)/../../common -I$(src)/../../profile -DEC_ARCH_$(ARCH) -D__DEBUG $(memchecker) $(debug_opt) $(android_opt) $(slp_opt) $(android_app_opt) $(board_opt)
+EXTRA_CFLAGS := $(extra_cflags)
obj-m := swap_driver.o
swap_driver-y := device_driver.o ec.o legacy.o module.o probes.o probes_manager.o storage.o us_proc_inst.o
module_name = swap_driver
cross_compiler = $(subst gcc,,$(CC))
+inlude_opt = -I$(top_srcdir)/src/modules/ksyms -I$(top_srcdir)/src/common -I$(top_srcdir)/src/profile
+extra_cflags = "$(inlude_opt) -DEC_ARCH_$(ARCH) -D__DEBUG $(memchecker) $(debug_opt) $(android_opt) $(slp_opt) $(android_app_opt) $(board_opt)"
+
#bin_SCRIPTS = patchko.sh insmod.sh
all-local:
cp $(top_srcdir)/src/modules/kprobe/Module.symvers $(driver_module_dir)
- $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) memchecker=$(memchecker) android_opt=$(android_opt) slp_opt=$(slp_opt) android_app_opt=$(android_app_opt) board_opt=$(board_opt) debug_opt=$(debug_opt) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(driver_module_dir) modules
+ $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) extra_cflags=$(extra_cflags) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(driver_module_dir) modules
echo "generate data for version patching <$(OBJDUMP)><$(READELF)>"
$(top_srcdir)/src/modules/driver/patchko.sh -g $(driver_module_dir)/$(module_name).ko $(OBJDUMP) $(READELF)
void * dbi_module_callback_stop;
int dbi_module_priority_start;
int dbi_module_priority_stop;
+ void * (*get_uprobes)(void);
};
extern int dbi_register_handlers_module(struct dbi_modules_handlers_info *dbi_mhi);
// SEE ALSO: module.h
// AUTHOR: L.Komkov, A.Gerenkov
// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
+// DEPT NAME: Advanced Software Group
// CREATED: 2008.02.15
// VERSION: 1.0
// REVISION DATE: 2008.12.03
static int __init InitializeModule(void)
{
- if(lookup_name == NULL) {
- EPRINTF("fp_kallsyms_lookup_name parameter undefined!");
- return -1;
- }
if(device_name == NULL) {
EPRINTF("Using default device name!");
device_name = gl_szDefaultDeviceName;
device_major = DEFAULT_DEVICE_MAJOR;
}
- __real_put_task_struct = (void *) lookup_name (SWAPDRV_PUT_TASK_STRUCT);
+ __real_put_task_struct = (void *)swap_ksyms(SWAPDRV_PUT_TASK_STRUCT);
if (!__real_put_task_struct)
{
EPRINTF (SWAPDRV_PUT_TASK_STRUCT " is not found! Oops. Where is it?");
}
#if defined(CONFIG_MIPS)
- flush_cache_page = (void *) lookup_name ("r4k_flush_cache_page");
+ flush_cache_page = (void *)swap_ksyms("r4k_flush_cache_page");
if (!flush_cache_page)
{
EPRINTF ("failed to resolve 'flush_cache_page'!\n");
// SEE ALSO: module.c
// AUTHOR: L.Komkov, A.Gerenkov
// COMPANY NAME: Samsung Research Center in Moscow
-// DEPT NAME: Advanced Software Group
+// DEPT NAME: Advanced Software Group
// CREATED: 2008.02.15
// VERSION: 1.0
// REVISION DATE: 2008.12.03
extern char *device_name;
extern unsigned int device_major;
-typedef unsigned long (*fp_kallsyms_lookup_name_t) (const char *name);
-
-//export by swap_kprobes.ko
-extern fp_kallsyms_lookup_name_t lookup_name;
-
struct handler_map {
unsigned long func_addr;
unsigned long jp_handler_addr;
////////////////////////////////////////////////////////////////////////////////////
#include <linux/percpu.h>
+#include <ksyms.h>
#include "module.h"
#include "probes_manager.h"
spin_lock_init(&ec_spinlock);
spin_lock_init(&ec_probe_spinlock);
#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-#ifdef CONFIG_X86
- //pf_addr = lookup_name("handle_mm_fault");
- pf_addr = lookup_name("do_page_fault");
-#else
- pf_addr = lookup_name("do_page_fault");
-#endif
+ pf_addr = swap_ksyms("do_page_fault");
if (pf_addr == 0) {
EPRINTF("Cannot find address for page fault function!");
return -EINVAL;
}
- cp_addr = lookup_name("copy_process");
+ cp_addr = swap_ksyms("copy_process");
if (cp_addr == 0) {
EPRINTF("Cannot find address for copy_process function!");
return -EINVAL;
}
- mr_addr = lookup_name("mm_release");
+ mr_addr = swap_ksyms("mm_release");
if (mr_addr == 0) {
EPRINTF("Cannot find address for mm_release function!");
return -EINVAL;
}
- exit_addr = lookup_name("do_exit");
+ exit_addr = swap_ksyms("do_exit");
if (exit_addr == 0) {
EPRINTF("Cannot find address for do_exit function!");
return -EINVAL;
}
- unmap_addr = lookup_name("do_munmap");
+ unmap_addr = swap_ksyms("do_munmap");
if (unmap_addr == 0) {
EPRINTF("Cannot find address for do_munmap function!");
return -EINVAL;
struct hlist_node *node;
unsigned long pre_handler_addr, jp_handler_addr, rp_handler_addr;
+ // FIXME: functions 'find_jp_handler', 'find_rp_handler', 'find_pre_handler' - not found
/* We must perform this lookup whenever this function is called
* because the addresses of find_*_handler functions may differ. */
// swap_handlers removed
unsigned long (*find_jp_handler)(unsigned long) =
// swap_handlers removed
- (unsigned long (*)(unsigned long))lookup_name("find_jp_handler");
+ (unsigned long (*)(unsigned long))swap_ksyms("find_jp_handler");
unsigned long (*find_rp_handler)(unsigned long) =
- (unsigned long (*)(unsigned long))lookup_name("find_rp_handler");
+ (unsigned long (*)(unsigned long))swap_ksyms("find_rp_handler");
unsigned long (*find_pre_handler)(unsigned long) =
- (unsigned long (*)(unsigned long))lookup_name("find_pre_handler");
+ (unsigned long (*)(unsigned long))swap_ksyms("find_pre_handler");
hlist_for_each_entry_rcu (probe, node, &kernel_probes, hlist) {
if(find_pre_handler)
{
// struct dbi_modules_handlers_info *local_mhi;
int i=0;
int nr_handlers=dbi_mhi->dbi_nr_handlers;
- printk ("lookup_name=0x%08x\n", lookup_name);
- if ( lookup_name != NULL){
- for (i=0;i<nr_handlers;i++){
- //handlers[i].func_addr = (void (*)(pte_t) ) lookup_name (handlers[i].func_name);
- dbi_mhi->dbi_handlers[i].func_addr = (void (*)(pte_t) ) lookup_name (dbi_mhi->dbi_handlers[i].func_name);
- printk("[0x%08x]-%s\n",dbi_mhi->dbi_handlers[i].func_addr,dbi_mhi->dbi_handlers[i].func_name);
- }
- }
- else
- {
- printk("[ERROR] lookup_name is NULL\n");
+ for (i = 0; i < nr_handlers; ++i) {
+ dbi_mhi->dbi_handlers[i].func_addr = swap_ksyms(dbi_mhi->dbi_handlers[i].func_name);
+ printk("[0x%08x]-%s\n", dbi_mhi->dbi_handlers[i].func_addr, dbi_mhi->dbi_handlers[i].func_name);
}
spin_lock_irqsave(&dbi_mh.lock, dbi_flags);
}
EXPORT_SYMBOL_GPL(dbi_unregister_handlers_module);
+static inst_us_proc_t empty_uprobes_info =
+{
+ .libs_count = 0,
+ .p_libs = NULL,
+};
+
+static inst_us_proc_t *get_uprobes(void)
+{
+ unsigned long dbi_flags;
+ inst_us_proc_t *ret = &empty_uprobes_info;
+ struct dbi_modules_handlers_info *mhi;
+ struct list_head *head = &dbi_mh.modules_handlers;
+
+ spin_lock_irqsave(&dbi_mh.lock, dbi_flags);
+ list_for_each_entry_rcu(mhi, head, dbi_list_head) {
+ if (mhi->get_uprobes) {
+ ret = mhi->get_uprobes();
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&dbi_mh.lock, dbi_flags);
+
+ return ret;
+}
+
EXPORT_SYMBOL_GPL(us_proc_info);
EXPORT_SYMBOL_GPL(dex_proc_info);
typedef void *(*get_my_uprobes_info_t)(void);
int link_bundle()
{
- get_my_uprobes_info_t get_uprobes = NULL;
- inst_us_proc_t *my_uprobes_info = 0;
- inst_us_proc_t empty_uprobes_info =
- {
- .libs_count = 0,
- .p_libs = NULL,
- };
+ inst_us_proc_t *my_uprobes_info = get_uprobes();
char *p = bundle; /* read pointer for bundle */
int nr_kern_probes;
int i, j, l, k;
int lib_name_len;
int handler_index;
-
- /* Get user-defined us handlers (if they are provided) */
- get_uprobes = (get_my_uprobes_info_t)lookup_name("get_my_uprobes_info");
- if (get_uprobes)
- my_uprobes_info = (inst_us_proc_t *)get_uprobes();
-
- if (my_uprobes_info == 0)
- my_uprobes_info = &empty_uprobes_info;
-
DPRINTF("Going to release us_proc_info");
if (us_proc_info.path)
unlink_bundle();
}
else
{
- mec_post_event = lookup_name("mec_post_event");
+ // FIXME: 'mec_post_event' - not found
+ mec_post_event = swap_ksyms("mec_post_event");
if(mec_post_event == NULL)
{
EPRINTF ("Failed to find function 'mec_post_event' from mec_handlers.ko. Memory Error Checker will work incorrectly.");
{
int i, k, size = 0, probe_size, result, j;
char *buf, *sep1, *sep2;
- get_my_uprobes_info_t get_uprobes = NULL;
- inst_us_proc_t *my_uprobes_info = NULL;
-
- inst_us_proc_t empty_uprobes_info =
- {
- .libs_count = 0,
- .p_libs = NULL,
- };
-
- get_uprobes = (get_my_uprobes_info_t)lookup_name("get_my_uprobes_info");
- if (get_uprobes)
- my_uprobes_info = (inst_us_proc_t *)get_uprobes();
-
- DPRINTF("my_uprobes_info lookup result: 0x%p", my_uprobes_info);
- if (my_uprobes_info == 0)
- my_uprobes_info = &empty_uprobes_info;
+ inst_us_proc_t *my_uprobes_info = get_uprobes();
for(j = 0; j < data->probes_count; j++)
{
int get_predef_uprobes_size(int *size)
{
int i, k;
- get_my_uprobes_info_t get_uprobes = NULL;
- inst_us_proc_t *my_uprobes_info = NULL;
-
- inst_us_proc_t empty_uprobes_info =
- {
- .libs_count = 0,
- .p_libs = NULL,
- };
-
- get_uprobes = (get_my_uprobes_info_t)lookup_name("get_my_uprobes_info");
- if (get_uprobes)
- my_uprobes_info = (inst_us_proc_t *)get_uprobes();
-
- if (my_uprobes_info == 0)
- my_uprobes_info = &empty_uprobes_info;
+ inst_us_proc_t *my_uprobes_info = get_uprobes();
*size = 0;
for(i = 0; i < my_uprobes_info->libs_count; i++)
int i, k, size, lib_size, func_size, result;
unsigned count = 0;
char sep[] = ":";
-
- inst_us_proc_t empty_uprobes_info =
- {
- .libs_count = 0,
- .p_libs = NULL,
- };
-
- get_my_uprobes_info_t get_uprobes = NULL;
- inst_us_proc_t *my_uprobes_info = NULL;
-
- get_uprobes = (get_my_uprobes_info_t)lookup_name("get_my_uprobes_info");
- if (get_uprobes)
- my_uprobes_info = (inst_us_proc_t *)get_uprobes();
-
- if (my_uprobes_info == 0)
- my_uprobes_info = &empty_uprobes_info;
+ inst_us_proc_t *my_uprobes_info = get_uprobes();
// get addr of array
if (copy_from_user ((void *)&data, udata, sizeof (data)))
# name of the device
DEVICE_FILE=__DEV_DIR__/${DEVICE}
-KSYMS=kallsyms_lookup_name
-
-# ADDRESS for "kallsyms_lookup_name" function taken from /proc/kallsyms
-ADDRESS=0x`sed "/ kallsyms_lookup_name/ ! d" /proc/kallsyms | sed "s/ T kallsyms_lookup_name//"`
-
-if [ "${ADDRESS}" = "0x" ]; then
- if [ "$1" = "" ]; then
- echo "Enter kallsyms_lookup_name as parameter:"
- echo "insmod.sh <kallsyms_lookup_name address>"
- exit
- else
- ADDRESS=$1
- echo "kallsyms_lookup_name address is ${ADDRESS}"
- fi
-fi
-
MAJOR=`sed "/${DEVICE_NAME}/ ! d" /proc/devices | sed "s/ ${DEVICE_NAME}//"`
if [ "${MAJOR}" != "" ] ; then
echo "SWAP Driver is already loaded!"
-EXTRA_CFLAGS := $(android_opt) $(board_opt)
+EXTRA_CFLAGS := $(extra_cflags)
obj-m := swap_kprobe.o
swap_kprobe-y := dbi_kprobes_deps.o dbi_insn_slots.o dbi_uprobes.o arch/asm/dbi_kprobes.o arch/dbi_kprobes.o dbi_kprobes.o
module_name = swap_kprobe
cross_compiler = $(subst gcc,,$(CC))
+inlude_opt = -I$(top_srcdir)/src/modules/ksyms
+extra_cflags = "$(inlude_opt) $(android_opt) $(board_opt)"
all-local:
rm -f $(top_srcdir)/src/modules/kprobe/arch/asm && $(LN_S) asm-${target_arch} $(top_srcdir)/src/modules/kprobe/arch/asm
- $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) android_opt=$(android_opt) board_opt=$(board_opt) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(kprobes_module_dir) modules
+ $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) extra_cflags=$(extra_cflags) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(kprobes_module_dir) modules
echo "generate data for version patching <$(OBJDUMP)><$(READELF)>"
#include "../../dbi_insn_slots.h"
#include "../../dbi_kprobes_deps.h"
#include "../../dbi_uprobes.h"
+#include <ksyms.h>
#include <asm/cacheflush.h>
extern struct hlist_head kprobe_insn_pages;
extern struct hlist_head uprobe_insn_pages;
-extern unsigned long (*kallsyms_search) (const char *name);
-
extern struct kprobe *kprobe_running(void);
extern void reset_current_kprobe(void);
extern struct kprobe_ctlblk *get_kprobe_ctlblk(void);
return -1;
}
- do_bp_handler = (unsigned int) kallsyms_search ("do_undefinstr");
+ do_bp_handler = swap_ksyms("do_undefinstr");
if (do_bp_handler == 0) {
DBPRINTF("no do_undefinstr symbol found!");
return -1;
}
arr_traps_template[NOTIFIER_CALL_CHAIN_INDEX] = arch_construct_brunch ((unsigned int)kprobe_handler, do_bp_handler + NOTIFIER_CALL_CHAIN_INDEX * 4, 1);
// Register hooks (kprobe_handler)
- do_kpro = (void *)kallsyms_search ("register_undef_hook");
+ do_kpro = swap_ksyms("register_undef_hook");
if (do_kpro == 0) {
printk("no register_undef_hook symbol found!\n");
return -1;
}
// Unregister hooks (kprobe_handler)
- undo_kpro = (void *)kallsyms_search ("unregister_undef_hook");
+ undo_kpro = swap_ksyms("unregister_undef_hook");
if (undo_kpro == 0) {
printk("no unregister_undef_hook symbol found!\n");
return -1;
#include "../../dbi_insn_slots.h"
#include "../../dbi_kprobes_deps.h"
#include "../../dbi_uprobes.h"
+#include <ksyms.h>
#ifdef OVERHEAD_DEBUG
#include <linux/time.h>
extern struct kprobe_ctlblk *get_kprobe_ctlblk (void);
extern void reset_current_kprobe (void);
-extern unsigned long (*kallsyms_search) (const char *name);
-
#ifdef OVERHEAD_DEBUG
unsigned long swap_sum_time = 0;
unsigned long swap_sum_hit = 0;
return -1;
}
- do_bp_handler = (unsigned int) kallsyms_search ("do_bp");
+ do_bp_handler = (unsigned int)swap_ksyms("do_bp");
kprobe_handler_addr = (unsigned int) &kprobe_handler;
insns_num = sizeof (arr_traps_template) / sizeof (arr_traps_template[0]);
unsigned int code_size = 0;
// Get instruction address
- do_bp_handler = (unsigned int) kallsyms_search ("do_undefinstr");
+ do_bp_handler = (unsigned int)swap_ksyms("do_undefinstr");
//dbi_unregister_jprobe(&do_exit_p, 0);
extern spinlock_t kretprobe_lock;
-extern unsigned long (*kallsyms_search) (const char *name);
-
extern struct kprobe *kprobe_running (void);
extern struct kprobe_ctlblk *get_kprobe_ctlblk (void);
extern void reset_current_kprobe (void);
#include "../dbi_kprobes_deps.h"
#include <linux/module.h>
+#include <ksyms.h>
-typedef unsigned long (*fp_kallsyms_lookup_name_t) (const char *name);
-//export by swap_kprobes.ko
-extern fp_kallsyms_lookup_name_t lookup_name;
extern unsigned long sched_addr;
extern unsigned long fork_addr;
extern struct hlist_head uprobe_insn_pages;
-static int ksyms = INVALID_VALUE;
-module_param(ksyms, uint, 0);
-MODULE_PARM_DESC(ksyms, "kallsyms_lookup_name address");
-
-fp_kallsyms_lookup_name_t lookup_name;
-EXPORT_SYMBOL_GPL(lookup_name);
-
-extern unsigned long (*kallsyms_search) (const char *name);
-
void arch_remove_kprobe (struct kprobe *p, struct task_struct *task)
{
// TODO: check boostable for x86 and MIPS
int arch_init_module_dependencies()
{
- lookup_name = (void *) ksyms;
- kallsyms_search = lookup_name;//(void *) ksyms;
- DBPRINTF ("kallsyms=0x%08x\n", kallsyms_search);
-
- sched_addr = kallsyms_search("__switch_to");//"schedule");
- fork_addr = kallsyms_search("do_fork");
+ sched_addr = swap_ksyms("__switch_to");
+ fork_addr = swap_ksyms("do_fork");
init_module_dependencies();
#include "dbi_kprobes_deps.h"
#include "dbi_insn_slots.h"
#include "dbi_uprobes.h"
-
+#include <ksyms.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
extern unsigned long fork_addr;
extern struct hlist_head kprobe_insn_pages;
-extern unsigned long (*kallsyms_search) (const char *name);
-
DEFINE_PER_CPU (struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU (struct kprobe_ctlblk, kprobe_ctlblk);
{
if (p->addr)
return -EINVAL;
- p->addr = (kprobe_opcode_t *)kallsyms_search (p->symbol_name);
+ p->addr = (kprobe_opcode_t *)swap_ksyms(p->symbol_name);
}
if (!p->addr)
#endif /* copy_to_user_page */
-DECLARE_MOD_CB_DEP(kallsyms_search, unsigned long, const char *name);
DECLARE_MOD_FUNC_DEP(access_process_vm, int, struct task_struct * tsk, unsigned long addr, void *buf, int len, int write);
DECLARE_MOD_FUNC_DEP(find_extend_vma, struct vm_area_struct *, struct mm_struct * mm, unsigned long addr);
struct page *, struct vm_area_struct *vma, \
unsigned long addr, pte_t pte);
-DECLARE_MOD_FUNC_DEP(flush_ptrace_access, \
- void, struct vm_area_struct *vma, struct page *page, \
- unsigned long uaddr, void *kaddr, unsigned long len, int write);
-
#if (LINUX_VERSION_CODE != KERNEL_VERSION(2, 6, 16))
DECLARE_MOD_FUNC_DEP(put_task_struct, \
unsigned long addr, pte_t pte)
IMP_MOD_DEP_WRAPPER (vm_normal_page, vma, addr, pte)
- DECLARE_MOD_DEP_WRAPPER (flush_ptrace_access, \
- void, struct vm_area_struct *vma, struct page *page, \
- unsigned long uaddr, void *kaddr, unsigned long len, int write)
-IMP_MOD_DEP_WRAPPER (flush_ptrace_access, vma, page, uaddr, kaddr, len, write)
-
int init_module_dependencies()
{
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
- init_mm_ptr = (struct mm_struct*) kallsyms_search ("init_mm");
+ init_mm_ptr = (struct mm_struct*)swap_ksyms("init_mm");
memcmp(init_mm_ptr, &init_mm, sizeof(struct mm_struct));
#endif
INIT_MOD_DEP_VAR(copy_to_user_page, copy_to_user_page);
#endif /* copy_to_user_page */
- INIT_MOD_DEP_VAR(flush_ptrace_access, flush_ptrace_access);
INIT_MOD_DEP_VAR(find_extend_vma, find_extend_vma);
INIT_MOD_DEP_VAR(get_gate_vma, get_gate_vma);
*
* 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/mempolicy.h>
#include <linux/highmem.h>
#include <linux/pagemap.h>
+#include <ksyms.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12))
#define INIT_MOD_DEP_VAR(dep, name) \
{ \
- __ref_##dep = (void *) kallsyms_search (#name); \
+ __ref_##dep = (void *) swap_ksyms (#name); \
if (!__ref_##dep) \
{ \
DBPRINTF (#name " is not found! Oops. Where is it?"); \
#define INIT_MOD_DEP_CB(dep, name) \
{ \
- dep = (void *) kallsyms_search (#name); \
+ dep = (void *) swap_ksyms (#name); \
if (!dep) \
{ \
DBPRINTF (#name " is not found! Oops. Where is it?"); \
#!/bin/sh
SWAP_KPROBE=swap_kprobe
-KSYMS=kallsyms_lookup_name
-
-# ADDRESS for "kallsyms_lookup_name" function taken from /proc/kallsyms
-ADDRESS=0x`sed "/ kallsyms_lookup_name/ ! d" /proc/kallsyms | sed "s/ T kallsyms_lookup_name//"`
-
-if [ "${ADDRESS}" = "0x" ]; then
- if [ "$1" = "" ]; then
- echo "Enter kallsyms_lookup_name as parameter:"
- echo "swap_kprobe.sh <kallsyms_lookup_name address>"
- exit 1
- else
- ADDRESS=$1
- echo "kallsyms_lookup_name address is ${ADDRESS}"
- fi
-fi
# Check for running module in /proc/modules
RUNNING=`sed "/${SWAP_KPROBE}/ ! d" /proc/modules`
if [ "${RUNNING}" = "" ]; then
- ./bin/insmod.sh ${SWAP_KPROBE}.ko ksyms=${ADDRESS}
+ ./bin/insmod.sh ${SWAP_KPROBE}.ko
if [ $? -ne 0 ]; then
echo "Error: unable to load SWAP KProbe!"
exit 1
--- /dev/null
+ifneq ($(CONFIG_KALLSYMS),y)
+ obj-m := swap_ksyms.o
+ swap_ksyms-y := ksyms.o
+endif
\ No newline at end of file
--- /dev/null
+target_kernel_src = @KERNEL@
+target_arch = @ARCH@
+module_dir = $(realpath $(top_srcdir)/src/modules/ksyms)
+module_name = swap_ksyms
+cross_compiler = $(subst gcc,,$(CC))
+module_path = $(module_dir)/$(module_name).ko
+
+
+all-local:
+ $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(module_dir) modules
+
+ if [ -e $(module_path) ] ; then \
+ echo "generate data for version patching <$(OBJDUMP)><$(READELF)>" ; \
+ PATH=$(PATH) $(top_srcdir)/src/modules/driver/patchko.sh -g $(module_dir)/$(module_name).ko $(OBJDUMP) $(READELF) ; \
+ fi
+
+clean-local:
+ $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(module_dir) clean
+
+install-exec-local:
+ if [ -e $(module_path) ] ; then \
+ install -m 644 $(module_path) $(prefix) ; \
+ install -m 644 $(module_path).addr $(prefix) ; \
+ \
+ if [ "$(android)" != "yes" ] ; then install -m 755 $(module_dir)/$(module_name).sh $(prefix) ; fi ; \
+ fi
--- /dev/null
+/*
+ * Dynamic Binary Instrumentation Module based on KProbes
+ * modules/ksyms/ksyms.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.
+ *
+ * Copyright (C) Samsung Electronics, 2013
+ *
+ * 2013 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+#include "ksyms.h"
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/semaphore.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <asm/fcntl.h>
+
+
+#ifndef CONFIG_KALLSYMS
+
+#define KSYMS_ERR(format, args...) \
+ do { \
+ char *f = __FILE__; \
+ char *n = strrchr(f, '/'); \
+ printk("%s:%u \'%s\' ERROR: " format "\n" , (n) ? n+1 : f, __LINE__, __FUNCTION__, ##args); \
+ } while(0)
+
+
+struct sys_map_item {
+ struct list_head list;
+
+ unsigned long addr;
+ char *name;
+};
+
+static char* sm_path = NULL;
+module_param(sm_path, charp, 0);
+
+LIST_HEAD(smi_list);
+static struct file *file = NULL;
+
+static int cnt_init_sm = 0;
+DEFINE_SEMAPHORE(cnt_init_sm_lock);
+
+static int file_open(void)
+{
+ struct file *f = filp_open(sm_path, O_RDONLY, 0);
+
+ if (IS_ERR(f)) {
+ KSYMS_ERR("cannot open file \'%s\'", sm_path);
+ return PTR_ERR(f);
+ }
+
+ file = f;
+
+ return 0;
+}
+
+static void file_close(void)
+{
+ if (file) {
+ int ret = filp_close(file, NULL);
+ file = NULL;
+
+ if (ret) {
+ KSYMS_ERR("while closing file \'%s\' err=%d", sm_path, ret);
+ }
+ }
+}
+
+static int file_check(void)
+{
+ int ret = file_open();
+ if (ret == 0) {
+ file_close();
+ }
+
+ return ret;
+}
+
+static long file_size(struct file *file)
+{
+ struct kstat st;
+ if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) {
+ return -1;
+ }
+
+ if (!S_ISREG(st.mode)) {
+ return -1;
+ }
+
+ if (st.size != (long)st.size) {
+ return -1;
+ }
+
+ return st.size;
+}
+
+static struct sys_map_item *create_smi(unsigned long addr, const char *name)
+{
+ struct sys_map_item *smi = kmalloc(sizeof(*smi), GFP_KERNEL);
+
+ if (smi == NULL) {
+ KSYMS_ERR("not enough memory");
+ return NULL;
+ }
+
+ smi->name = kmalloc(strlen(name) + 1, GFP_KERNEL);
+ if (smi->name == NULL) {
+ kfree(smi);
+ KSYMS_ERR("not enough memory");
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&smi->list);
+ smi->addr = addr;
+ strcpy(smi->name, name);
+
+ return smi;
+}
+
+static void free_smi(struct sys_map_item *smi)
+{
+ kfree(smi->name);
+ kfree(smi);
+}
+
+static void add_smi(const struct sys_map_item *smi)
+{
+ list_add_tail(&smi->list, &smi_list);
+}
+
+static int is_endline(char c)
+{
+ return c == '\n' || c == '\r' || c == '\0';
+}
+
+static int is_symbol_attr(char c)
+{
+ return c == 't' || c == 'T';
+}
+
+static struct sys_map_item *get_sys_map_item(char *begin, char *end)
+{
+ struct sys_map_item *smi = NULL;
+ int n, len = end - begin;
+ unsigned long addr;
+ char attr, name[128], *line;
+
+ line = kmalloc(len + 1, GFP_KERNEL);
+ memcpy(line, begin, len);
+ line[len] = '\0';
+
+ n = sscanf(line, "%x %c %127s", &addr, &attr, &name);
+ name[127] = '\0';
+
+ if (n != 3) {
+ KSYMS_ERR("parsing line: \"%s\"", line);
+ attr = '\0';
+ }
+
+ kfree(line);
+
+ if (is_symbol_attr(attr)) {
+ smi = create_smi(addr, name);
+ }
+
+ return smi;
+}
+
+
+static void parsing(char *buf, int size)
+{
+ struct sys_map_item *smi;
+ char *start, *end, *c;
+
+ start = buf;
+ end = buf + size;
+
+ for (c = start; c < end; ++c) {
+ if (is_endline(*c)) {
+ smi = get_sys_map_item(start, c);
+ if (smi) {
+ add_smi(smi);
+ }
+
+ for (start = c; c < end; ++c) {
+ if (!is_endline(*c)) {
+ start = c;
+ break;
+ }
+ }
+ }
+ }
+}
+
+static int create_sys_map(void)
+{
+ char *data;
+ long size;
+ int ret = file_open();
+
+ if (ret) {
+ return ret;
+ }
+
+ size = file_size(file);
+ if (size < 0) {
+ KSYMS_ERR("cannot get file size");
+ ret = size;
+ goto close;
+ }
+
+ data = vmalloc(size);
+ if (data == NULL) {
+ KSYMS_ERR("not enough memory");
+ ret = -1;
+ goto close;
+ }
+
+ if (kernel_read(file, 0, data, size) != size) {
+ KSYMS_ERR("reading file %s", sm_path);
+ ret = -1;
+ goto free;
+ }
+
+ parsing(data, size);
+
+free:
+ vfree(data);
+
+close:
+ file_close();
+
+ return 0;
+}
+
+static void free_sys_map(void)
+{
+ struct sys_map_item *smi, *n;
+ list_for_each_entry_safe(smi, n, &smi_list, list) {
+ list_del(&smi->list);
+ free_smi(smi);
+ }
+}
+
+int swap_get_ksyms(void)
+{
+ int ret = 0;
+
+ down(&cnt_init_sm_lock);
+ if (cnt_init_sm == 0) {
+ ret = create_sys_map();
+ }
+
+ ++cnt_init_sm;
+ up(&cnt_init_sm_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(swap_get_ksyms);
+
+void swap_put_ksyms(void)
+{
+ down(&cnt_init_sm_lock);
+ --cnt_init_sm;
+ if (cnt_init_sm == 0) {
+ free_sys_map();
+ }
+
+ if (cnt_init_sm < 0) {
+ KSYMS_ERR("cnt_init_sm=%d", cnt_init_sm);
+ cnt_init_sm = 0;
+ }
+
+ up(&cnt_init_sm_lock);
+}
+EXPORT_SYMBOL_GPL(swap_put_ksyms);
+
+unsigned long swap_ksyms(const char *name)
+{
+ struct sys_map_item *smi;
+
+ list_for_each_entry(smi, &smi_list, list) {
+ if (strcmp(name, smi->name) == 0) {
+ return smi->addr;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(swap_ksyms);
+
+int __init swap_ksyms_init(void)
+{
+ int ret = 0;
+
+ if (sm_path == NULL) {
+ KSYMS_ERR("sm_path=NULL");
+ return -EINVAL;
+ }
+
+ ret = file_check();
+ if (ret) {
+ return -EINVAL;
+ }
+
+ // TODO: calling func 'swap_get_ksyms' in module used func 'swap_ksyms'
+ swap_get_ksyms();
+
+ return 0;
+}
+
+void __exit swap_ksyms_exit(void)
+{
+ down(&cnt_init_sm_lock);
+
+ if (cnt_init_sm > 0) {
+ free_sys_map();
+ }
+
+ up(&cnt_init_sm_lock);
+}
+
+module_init(swap_ksyms_init);
+module_exit(swap_ksyms_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SWAP ksyms module");
+MODULE_AUTHOR("Vyacheslav Cherkashin <v.cherkashin@samaung.com>");
+
+#endif /*CONFIG_KALLSYMS*/
--- /dev/null
+#ifndef __KSYMS_H__
+#define __KSYMS_H__
+
+/*
+ * Dynamic Binary Instrumentation Module based on KProbes
+ * modules/ksyms/ksyms.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, 2013
+ *
+ * 2013 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
+#include <linux/autoconf.h>
+#else
+#include <generated/autoconf.h>
+#endif
+
+#include <linux/kallsyms.h>
+
+#ifdef CONFIG_KALLSYMS
+
+static int swap_get_ksyms(void)
+{
+ return 0;
+}
+
+static void swap_put_ksyms(void)
+{
+}
+
+static unsigned long swap_ksyms(const char *name)
+{
+ return kallsyms_lookup_name(name);
+}
+
+#else /* !CONFIG_KALLSYMS */
+
+int swap_get_ksyms(void);
+void swap_put_ksyms(void);
+unsigned long swap_ksyms(const char *name);
+
+#endif /*CONFIG_KALLSYMS*/
+
+#endif /*__KSYMS_H__*/
--- /dev/null
+#!/bin/sh
+
+MODULE_NAME=swap_ksyms
+SYS_MAP_PACH=/mnt/nfs/System.map
+
+# Check for running module in /proc/modules
+RUNNING=`sed "/${MODULE_NAME}/ ! d" /proc/modules`
+
+if [ "${RUNNING}" = "" ]; then
+ ./bin/insmod.sh ${MODULE_NAME}.ko sm_path=${SYS_MAP_PACH}
+ if [ $? -ne 0 ]; then
+ echo "Error: unable to load ${MODULE_NAME}!"
+ exit 1
+ fi
+else
+ echo "module ${MODULE_NAME} is already running!"
+ exit 1
+fi