add 'swap_ksyms' module
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Thu, 24 Jan 2013 14:22:24 +0000 (18:22 +0400)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Thu, 24 Jan 2013 14:22:24 +0000 (18:22 +0400)
23 files changed:
driver/Kbuild
driver/Makefile.am
driver/handlers_core.h
driver/module.c
driver/module.h
driver/probes_manager.c
driver/storage.c
driver/swap_driver.sh
kprobe/Kbuild
kprobe/Makefile.am
kprobe/arch/asm-arm/dbi_kprobes.c
kprobe/arch/asm-mips/dbi_kprobes.c
kprobe/arch/asm-x86/dbi_kprobes.c
kprobe/arch/dbi_kprobes.c
kprobe/dbi_kprobes.c
kprobe/dbi_kprobes_deps.c
kprobe/dbi_kprobes_deps.h
kprobe/swap_kprobe.sh
ksyms/Kbuild [new file with mode: 0644]
ksyms/Makefile.am [new file with mode: 0644]
ksyms/ksyms.c [new file with mode: 0644]
ksyms/ksyms.h [new file with mode: 0644]
ksyms/swap_ksyms.sh [new file with mode: 0755]

index 1a4ab38..4d01ba9 100644 (file)
@@ -1,4 +1,4 @@
-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
index 303cc68..4aa4f95 100644 (file)
@@ -30,11 +30,14 @@ driver_module_dir = $(realpath $(srcdir))
 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)
index 02d3c40..d708fac 100644 (file)
@@ -37,6 +37,7 @@ struct dbi_modules_handlers_info {
        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);
index 00e2472..172e9e8 100644 (file)
@@ -8,7 +8,7 @@
 //      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
@@ -64,10 +64,6 @@ void (*flush_cache_page) (struct vm_area_struct * vma, unsigned long page);
 
 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;
@@ -77,7 +73,7 @@ static int __init InitializeModule(void)
                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?");
@@ -85,7 +81,7 @@ static int __init InitializeModule(void)
        }
 
 #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");
index da0ffee..fe77472 100644 (file)
@@ -7,7 +7,7 @@
 //      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;
index 3c748c0..6ca7abe 100644 (file)
@@ -16,6 +16,7 @@
 ////////////////////////////////////////////////////////////////////////////////////
 
 #include <linux/percpu.h>
+#include <ksyms.h>
 #include "module.h"
 #include "probes_manager.h"
 
@@ -54,36 +55,31 @@ probes_manager_init (void)
        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;
@@ -518,16 +514,17 @@ void dbi_install_user_handlers(void)
        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)
                {
index 8d42da5..da0fa40 100644 (file)
@@ -161,18 +161,10 @@ int dbi_register_handlers_module(struct dbi_modules_handlers_info *dbi_mhi)
 //     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);
@@ -221,6 +213,31 @@ int dbi_unregister_handlers_module(struct dbi_modules_handlers_info *dbi_mhi)
 }
 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);
@@ -607,13 +624,7 @@ extern struct dentry *dentry_by_path(const char *path);
 
 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;
@@ -631,15 +642,6 @@ int link_bundle()
        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();
@@ -1357,7 +1359,8 @@ int put_us_event (char *data, unsigned long len)
                }
                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.");
@@ -1448,22 +1451,7 @@ int set_predef_uprobes (ioctl_predef_uprobes_info_t *data)
 {
        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++)
        {
@@ -1521,21 +1509,7 @@ int set_predef_uprobes (ioctl_predef_uprobes_info_t *data)
 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++)
@@ -1557,22 +1531,7 @@ int get_predef_uprobes(ioctl_predef_uprobes_info_t *udata)
        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)))
index 4993ff7..1837f63 100755 (executable)
@@ -14,22 +14,6 @@ DEVICE_NAME=${DEVICE}
 # 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!"
index 8d92f8d..975a317 100644 (file)
@@ -1,4 +1,4 @@
-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
index 39eebd6..bc703e3 100644 (file)
@@ -12,10 +12,12 @@ kprobes_module_dir = $(realpath $(top_srcdir)/src/modules/kprobe)
 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)>"
index 152fc86..99d45b1 100644 (file)
@@ -39,6 +39,7 @@
 #include "../../dbi_insn_slots.h"
 #include "../../dbi_kprobes_deps.h"
 #include "../../dbi_uprobes.h"
+#include <ksyms.h>
 
 #include <asm/cacheflush.h>
 
@@ -63,8 +64,6 @@ extern struct kretprobe *sched_rp;
 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);
@@ -1586,21 +1585,21 @@ int __init arch_init_kprobes (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;
index 52ced9a..ac97010 100644 (file)
@@ -33,6 +33,7 @@
 #include "../../dbi_insn_slots.h"
 #include "../../dbi_kprobes_deps.h"
 #include "../../dbi_uprobes.h"
+#include <ksyms.h>
 
 #ifdef OVERHEAD_DEBUG
 #include <linux/time.h>
@@ -55,8 +56,6 @@ extern struct kprobe *kprobe_running (void);
 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;
@@ -816,7 +815,7 @@ int __init arch_init_kprobes (void)
                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]);
@@ -855,7 +854,7 @@ void __exit dbi_arch_exit_kprobes (void)
        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);
 
index 14dc364..5771243 100644 (file)
@@ -78,8 +78,6 @@ extern struct hlist_head uprobe_insn_pages;
 
 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);
index 7bcdca8..8c3ec7f 100644 (file)
 #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;
@@ -68,15 +66,6 @@ extern struct hlist_head kprobe_insn_pages;
 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
@@ -118,12 +107,8 @@ void arch_disarm_uretprobe (struct kretprobe *p, struct task_struct *tsk)
 
 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();
 
index cba8fd1..995ca6d 100644 (file)
@@ -56,7 +56,7 @@
 #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)
@@ -74,8 +74,6 @@ extern unsigned long sched_addr;
 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);
 
@@ -468,7 +466,7 @@ int dbi_register_kprobe (struct kprobe *p)
     {
         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)
index 53af180..f656f97 100644 (file)
@@ -59,7 +59,6 @@ IMP_MOD_DEP_WRAPPER(copy_to_user_page, vma, page, uaddr, dst, src, len)
 #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);
@@ -107,10 +106,6 @@ DECLARE_MOD_FUNC_DEP(vm_normal_page, \
                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, \
@@ -202,17 +197,12 @@ IMP_MOD_DEP_WRAPPER (__flush_anon_page, vma, page, vmaddr)
                        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
 
@@ -224,7 +214,6 @@ int init_module_dependencies()
        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);
 
index 57b9f64..c8c05b5 100644 (file)
@@ -23,9 +23,8 @@
  *
  * 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()
@@ -33,6 +32,7 @@
 #include <linux/mempolicy.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <ksyms.h>
 
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12))
@@ -58,7 +58,7 @@
 
 #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?"); \
@@ -68,7 +68,7 @@
 
 #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?"); \
index 66d6686..dcebf69 100755 (executable)
@@ -1,27 +1,12 @@
 #!/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
diff --git a/ksyms/Kbuild b/ksyms/Kbuild
new file mode 100644 (file)
index 0000000..317f398
--- /dev/null
@@ -0,0 +1,4 @@
+ifneq ($(CONFIG_KALLSYMS),y)
+       obj-m := swap_ksyms.o
+       swap_ksyms-y := ksyms.o
+endif
\ No newline at end of file
diff --git a/ksyms/Makefile.am b/ksyms/Makefile.am
new file mode 100644 (file)
index 0000000..41498ce
--- /dev/null
@@ -0,0 +1,26 @@
+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
diff --git a/ksyms/ksyms.c b/ksyms/ksyms.c
new file mode 100644 (file)
index 0000000..6cf9ada
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ *  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*/
diff --git a/ksyms/ksyms.h b/ksyms/ksyms.h
new file mode 100644 (file)
index 0000000..6e50d6d
--- /dev/null
@@ -0,0 +1,61 @@
+#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__*/
diff --git a/ksyms/swap_ksyms.sh b/ksyms/swap_ksyms.sh
new file mode 100755 (executable)
index 0000000..21e85e3
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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