From: Vyacheslav Cherkashin Date: Mon, 27 Apr 2015 12:22:12 +0000 (+0300) Subject: Merge branch 'tizen_2.4' into 'tizen_2.4_dev' X-Git-Tag: submit/tizen/20151123.110932~94 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=483630ae22b25b202c69d868592daf059f45ad10;p=kernel%2Fswap-modules.git Merge branch 'tizen_2.4' into 'tizen_2.4_dev' Change-Id: I1133d65cd7fe8b74e084b4ea9e0bdc8fb470659d Signed-off-by: Vyacheslav Cherkashin --- 483630ae22b25b202c69d868592daf059f45ad10 diff --cc preload/preload_debugfs.c index d9b4d18,0000000..8af94bb mode 100644,000000..100644 --- a/preload/preload_debugfs.c +++ b/preload/preload_debugfs.c @@@ -1,493 -1,0 +1,493 @@@ +#include +#include +#include +#include +#include +#include +#include +#include +#include - #include ++#include +#include "preload.h" +#include "preload_debugfs.h" +#include "preload_module.h" +#include "preload_control.h" +#include "preload_patcher.h" +#include "preload_storage.h" + +static const char PRELOAD_FOLDER[] = "preload"; +static const char PRELOAD_LOADER[] = "loader"; +static const char PRELOAD_LOADER_OFFSET[] = "loader_offset"; +static const char PRELOAD_LOADER_PATH[] = "loader_path"; +static const char PRELOAD_BINARIES[] = "target_binaries"; +static const char PRELOAD_BINARIES_LIST[] = "bins_list"; +static const char PRELOAD_BINARIES_ADD[] = "bins_add"; +static const char PRELOAD_BINARIES_REMOVE[] = "bins_remove"; +static const char PRELOAD_CALLER[] = "caller"; +static const char PRELOAD_HANDLERS_PATH[] = "handlers_path"; +static const char PRELOAD_LINKER_DATA[] = "linker"; +static const char PRELOAD_LINKER_PATH[] = "linker_path"; +static const char PRELOAD_LINKER_R_DEBUG_OFFSET[] = "r_debug_offset"; + +struct loader_info { + char *path; + unsigned long offset; + struct dentry *dentry; +}; + +static struct dentry *preload_root; +static struct loader_info __loader_info = { + .path = NULL, + .offset = 0, + .dentry = NULL +}; + +static unsigned long r_debug_offset = 0; +static DEFINE_MUTEX(__dentry_lock); + +static inline void dentry_lock(void) +{ + mutex_lock(&__dentry_lock); +} + +static inline void dentry_unlock(void) +{ + mutex_unlock(&__dentry_lock); +} + + +static void set_loader_file(char *path) +{ + __loader_info.path = path; + dentry_lock(); + __loader_info.dentry = get_dentry(__loader_info.path); + dentry_unlock(); +} + +struct dentry *preload_debugfs_get_loader_dentry(void) +{ + struct dentry *dentry; + + dentry_lock(); + dentry = __loader_info.dentry; + dentry_unlock(); + + return dentry; +} + +unsigned long preload_debugfs_get_loader_offset(void) +{ + /* TODO Think about sync */ + return __loader_info.offset; +} + +static void clean_loader_info(void) +{ + if (__loader_info.path != NULL) + kfree(__loader_info.path); + + dentry_lock(); + if (__loader_info.dentry != NULL) + put_dentry(__loader_info.dentry); + dentry_unlock(); +} + +struct dentry *debugfs_create_ptr(const char *name, mode_t mode, + struct dentry *parent, + unsigned long *value) +{ + struct dentry *dentry; + +#if BITS_PER_LONG == 32 + dentry = debugfs_create_x32(name, mode, parent, (u32 *)value); +#elif BITS_PER_LONG == 64 + dentry = debugfs_create_x64(name, mode, parent, (u64 *)value); +#else +#error Unsupported BITS_PER_LONG value +#endif + + return dentry; +} + + +/* =========================================================================== + * = LOADER PATH = + * =========================================================================== + */ + +static ssize_t loader_path_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + ssize_t ret; + char *path; + + if (preload_module_is_running()) + return -EBUSY; + + clean_loader_info(); + + path = kmalloc(len, GFP_KERNEL); + if (path == NULL) { + ret = -ENOMEM; + goto out; + } + + if (copy_from_user(path, buf, len)) { + ret = -EINVAL; + goto out; + } + + path[len - 1] = '\0'; + set_loader_file(path); + ret = len; + +out: + return ret; +} + + +static const struct file_operations loader_path_file_ops = { + .owner = THIS_MODULE, + .write = loader_path_write, +}; + + +/* =========================================================================== + * = BIN PATH = + * =========================================================================== + */ + +static ssize_t bin_add_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + ssize_t ret; + char *path; + + path = kmalloc(len, GFP_KERNEL); + if (path == NULL) { + ret = -ENOMEM; + goto bin_add_write_out; + } + + if (copy_from_user(path, buf, len)) { + ret = -EINVAL; + goto bin_add_write_out; + } + + path[len - 1] = '\0'; + + if (preload_control_add_instrumented_binary(path) != 0) { + printk(PRELOAD_PREFIX "Cannot add binary %s\n", path); + ret = -EINVAL; + goto bin_add_write_out; + } + + ret = len; + +bin_add_write_out: + kfree(path); + + return ret; +} + +static ssize_t bin_remove_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + ssize_t ret; + + ret = preload_control_clean_instrumented_bins(); + if (ret != 0) { + printk(PRELOAD_PREFIX "Error during clean!\n"); + ret = -EINVAL; + goto bin_remove_write_out; + } + + ret = len; + +bin_remove_write_out: + return ret; +} + +static ssize_t bin_list_read(struct file *file, char __user *usr_buf, + size_t count, loff_t *ppos) +{ + unsigned int i; + unsigned int files_cnt = 0; + ssize_t len = 0, tmp, ret = 0; + char **filenames = NULL; + char *buf = NULL; + char *ptr = NULL; + + files_cnt = preload_control_get_bin_names(&filenames); + + if (files_cnt == 0) { + printk(PRELOAD_PREFIX "Cannot read binaries names!\n"); + ret = 0; + goto bin_list_read_out; + } + + for (i = 0; i < files_cnt; i++) + len += strlen(filenames[i]); + + buf = kmalloc(len + files_cnt, GFP_KERNEL); + if (buf == NULL) { + ret = 0; + goto bin_list_read_fail; + } + + ptr = buf; + + for (i = 0; i < files_cnt; i++) { + tmp = strlen(filenames[i]); + memcpy(ptr, filenames[i], tmp); + ptr += tmp; + *ptr = '\n'; + ptr += 1; + } + + preload_control_release_bin_names(&filenames); + + return simple_read_from_buffer(usr_buf, count, ppos, buf, len); + +bin_list_read_fail: + preload_control_release_bin_names(&filenames); + +bin_list_read_out: + return ret; +} + +static const struct file_operations bin_list_file_ops = { + .owner = THIS_MODULE, + .read = bin_list_read +}; + +static const struct file_operations bin_add_file_ops = { + .owner = THIS_MODULE, + .write = bin_add_write, +}; + +static const struct file_operations bin_remove_file_ops = { + .owner = THIS_MODULE, + .write = bin_remove_write, +}; + + +/* =========================================================================== + * = LINKER PATH = + * =========================================================================== + */ + + +static ssize_t linker_path_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + ssize_t ret; + char *path; + + path = kmalloc(len, GFP_KERNEL); + if (path == NULL) { + ret = -ENOMEM; + goto linker_path_write_out; + } + + if (copy_from_user(path, buf, len)) { + ret = -EINVAL; + goto linker_path_write_out; + } + + path[len - 1] = '\0'; + + if (preload_storage_set_linker_info(path) != 0) { + printk(PRELOAD_PREFIX "Cannot set linker path %s\n", path); + ret = -EINVAL; + goto linker_path_write_out; + } + + ret = len; + +linker_path_write_out: + kfree(path); + + return ret; +} + +static const struct file_operations linker_path_file_ops = { + .owner = THIS_MODULE, + .write = linker_path_write, +}; + + +/* =========================================================================== + * = HANDLERS PATH = + * =========================================================================== + */ + + +static ssize_t handlers_path_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + ssize_t ret; + char *path; + + path = kmalloc(len, GFP_KERNEL); + if (path == NULL) { + ret = -ENOMEM; + goto handlers_path_write_out; + } + + if (copy_from_user(path, buf, len)) { + ret = -EINVAL; + goto handlers_path_write_out; + } + + path[len - 1] = '\0'; + + if (preload_storage_set_handlers_info(path) != 0) { + printk(PRELOAD_PREFIX "Cannot set handler path %s\n", path); + ret = -EINVAL; + goto handlers_path_write_out; + } + + ret = len; + +handlers_path_write_out: + kfree(path); + + return ret; +} + +static const struct file_operations handlers_path_file_ops = { + .owner = THIS_MODULE, + .write = handlers_path_write, +}; + + + + +unsigned long preload_debugfs_r_debug_offset(void) +{ + return r_debug_offset; +} + +int preload_debugfs_init(void) +{ + struct dentry *swap_dentry, *root, *loader, *open_p, *lib_path, + *bin_path, *bin_list, *bin_add, *bin_remove, + *linker_dir, *linker_path, *linker_offset, *handlers_path; + int ret; + + ret = -ENODEV; + if (!debugfs_initialized()) + goto fail; + + ret = -ENOENT; - swap_dentry = get_swap_debugfs_dir(); ++ swap_dentry = swap_debugfs_getdir(); + if (!swap_dentry) + goto fail; + + ret = -ENOMEM; + root = debugfs_create_dir(PRELOAD_FOLDER, swap_dentry); + if (IS_ERR_OR_NULL(root)) + goto fail; + + preload_root = root; + + loader = debugfs_create_dir(PRELOAD_LOADER, root); + if (IS_ERR_OR_NULL(root)) { + ret = -ENOMEM; + goto remove; + } + + open_p = debugfs_create_ptr(PRELOAD_LOADER_OFFSET, PRELOAD_DEFAULT_PERMS, + loader, &__loader_info.offset); + if (IS_ERR_OR_NULL(open_p)) { + ret = -ENOMEM; + goto remove; + } + + lib_path = debugfs_create_file(PRELOAD_LOADER_PATH, PRELOAD_DEFAULT_PERMS, + loader, NULL, &loader_path_file_ops); + if (IS_ERR_OR_NULL(lib_path)) { + ret = -ENOMEM; + goto remove; + } + + bin_path = debugfs_create_dir(PRELOAD_BINARIES, root); + if (IS_ERR_OR_NULL(bin_path)) { + ret = -ENOMEM; + goto remove; + } + + bin_list = debugfs_create_file(PRELOAD_BINARIES_LIST, PRELOAD_DEFAULT_PERMS, + bin_path, NULL, &bin_list_file_ops); + if (IS_ERR_OR_NULL(bin_list)) { + ret = -ENOMEM; + goto remove; + } + + bin_add = debugfs_create_file(PRELOAD_BINARIES_ADD, PRELOAD_DEFAULT_PERMS, + bin_path, NULL, &bin_add_file_ops); + if (IS_ERR_OR_NULL(bin_add)) { + ret = -ENOMEM; + goto remove; + } + + bin_remove = debugfs_create_file(PRELOAD_BINARIES_REMOVE, + PRELOAD_DEFAULT_PERMS, bin_path, NULL, + &bin_remove_file_ops); + if (IS_ERR_OR_NULL(bin_remove)) { + ret = -ENOMEM; + goto remove; + } + + linker_dir = debugfs_create_dir(PRELOAD_LINKER_DATA, root); + if (IS_ERR_OR_NULL(linker_dir)) { + ret = -ENOMEM; + goto remove; + } + + linker_path = debugfs_create_file(PRELOAD_LINKER_PATH, + PRELOAD_DEFAULT_PERMS, linker_dir, NULL, + &linker_path_file_ops); + if (IS_ERR_OR_NULL(linker_path)) { + ret = -ENOMEM; + goto remove; + } + + linker_offset = debugfs_create_ptr(PRELOAD_LINKER_R_DEBUG_OFFSET, + PRELOAD_DEFAULT_PERMS, linker_dir, + &r_debug_offset); + if (IS_ERR_OR_NULL(linker_offset)) { + ret = -ENOMEM; + goto remove; + } + + handlers_path = debugfs_create_file(PRELOAD_HANDLERS_PATH, + PRELOAD_DEFAULT_PERMS, root, NULL, + &handlers_path_file_ops); + if (IS_ERR_OR_NULL(handlers_path)) { + ret = -ENOMEM; + goto remove; + } + + return 0; + +remove: + + debugfs_remove_recursive(root); + +fail: + printk(PRELOAD_PREFIX "Debugfs initialization failure: %d\n", ret); + + return ret; +} + +void preload_debugfs_exit(void) +{ + if (preload_root) + debugfs_remove_recursive(preload_root); + preload_root = NULL; + + preload_module_set_not_ready(); + clean_loader_info(); +} diff --cc writer/swap_writer_module.c index d535316,c04bbe0..0a8fa89 --- a/writer/swap_writer_module.c +++ b/writer/swap_writer_module.c @@@ -1457,187 -1456,8 +1458,171 @@@ put_buf } EXPORT_SYMBOL_GPL(custom_exit_event); + + + ++ +/* ============================================================================ + * = WEB APP EVENT = + * ============================================================================ + */ + +/* TODO: develop method for obtaining this data during build... */ +/* location: webkit2-efl-123997_0.11.113/Source/WTF/wtf/text/StringImpl.h:70 */ +struct MStringImpl { + unsigned m_refCount; + unsigned m_length; + union { + const unsigned char *m_data8; + const unsigned short *m_data16; + }; + union { + void* m_buffer; + struct MStringImpl *m_substringBuffer; + unsigned short *m_copyData16; + }; + unsigned m_hashAndFlags; +}; + +/* location: webkit2-efl-123997_0.11.113/Source/JavaScriptCore/profiler/ + * CallIdentifier.h:36 + */ +struct MCallIdentifier { + struct MStringImpl *m_name; + struct MStringImpl *m_url; + unsigned m_lineNumber; +}; + +int entry_web_event(unsigned long func_addr, struct pt_regs *regs) +{ + char *buf, *pl; + long t; + int ret = 0, n, lnum; + struct MCallIdentifier *callIdentifier; + struct { + const char *str; + int len; + } m_name, m_url; + struct task_struct *task = current; + + if (!check_event(current)) + return 0; + + callIdentifier = (void *)swap_get_uarg(regs, 2); + + if (get_user(t, (int *)&callIdentifier->m_name) || + get_user(m_name.str, &((struct MStringImpl *)t)->m_data8) || + get_user(m_name.len, &((struct MStringImpl *)t)->m_length) || + get_user(t, (int *)&callIdentifier->m_url) || + get_user(m_url.str, &((struct MStringImpl *)t)->m_data8) || + get_user(m_url.len, &((struct MStringImpl *)t)->m_length) || + get_user(lnum, (int *)&callIdentifier->m_lineNumber)) { + print_err("%s: cannot read user memory\n", __func__); + return 0; + } + + buf = get_current_buf(); + pl = pack_basic_msg_fmt(buf, MSG_WEB_FUNCTION_ENTRY); + + /* Pack message */ + /* PID */ + *(u32 *)pl = task->tgid; + pl += sizeof(u32); + /* TID */ + *(u32 *)pl = task->pid; + pl += sizeof(u32); + /* Line number (in source file) */ + *(u32 *)pl = lnum; + pl += sizeof(u32); + /* Function name */ + n = strncpy_from_user(pl, m_name.str, m_name.len); + if (n < 0) { + print_err("%s: cannot read user memory (function name)\n", + __func__); + goto put_current_buf_return; + } else { + pl[n] = '\0'; + pl += n + 1; + } + /* URL (source file) */ + n = strncpy_from_user(pl, m_url.str, m_url.len); + if (n < 0) { + print_err("%s: cannot read user memory (url)\n", __func__); + goto put_current_buf_return; + } else { + pl[n] = '\0'; + pl += n + 1; + } + + set_len_msg(buf, pl); + ret = write_to_buffer(buf); + +put_current_buf_return: + put_current_buf(); + return ret; +} +EXPORT_SYMBOL_GPL(entry_web_event); + +int exit_web_event(unsigned long func_addr, struct pt_regs *regs) +{ + char *buf, *pl; + long t; + int ret = 0, n; + struct MCallIdentifier *callIdentifier; + struct { + const char *str; + int len; + } m_name; + struct task_struct *task = current; + + if (!check_event(current)) + return 0; + + callIdentifier = (void *)swap_get_uarg(regs, 2); + + if (get_user(t, (int *)&callIdentifier->m_name) || + get_user(m_name.str, &((struct MStringImpl *)t)->m_data8) || + get_user(m_name.len, &((struct MStringImpl *)t)->m_length)) { + print_err("%s: cannot read user memory\n", __func__); + return 0; + } + + buf = get_current_buf(); + pl = pack_basic_msg_fmt(buf, MSG_WEB_FUNCTION_EXIT); + + /* Pack message */ + /* PID */ + *(u32 *)pl = task->tgid; + pl += sizeof(u32); + /* TID */ + *(u32 *)pl = task->pid; + pl += sizeof(u32); + /* Function name */ + n = strncpy_from_user(pl, m_name.str, m_name.len); + if (n < 0) { + print_err("%s: cannot read user memory (function name)\n", + __func__); + goto put_current_buf_return; + } else { + pl[n] = '\0'; + pl += n + 1; + } + + set_len_msg(buf, pl); + ret = write_to_buffer(buf); + +put_current_buf_return: + put_current_buf(); + return ret; +} +EXPORT_SYMBOL_GPL(exit_web_event); + - static int __init swap_writer_module_init(void) - { - int ret; + - ret = event_filter_init(); - if (ret) - return ret; + - ret = init_debugfs_writer(); - if (ret) - event_filter_exit(); + - return ret; - } - - static void __exit swap_writer_module_exit(void) - { - exit_debugfs_writer(); - event_filter_exit(); - } + - module_init(swap_writer_module_init); - module_exit(swap_writer_module_exit); + SWAP_LIGHT_INIT_MODULE(NULL, event_filter_init, event_filter_exit, + init_debugfs_writer, exit_debugfs_writer); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SWAP Writer module");