* Web application profiling
*/
+#include <linux/module.h>
+#include <linux/slab.h>
#include <us_manager/us_manager.h>
-#include <us_manager/sspt/sspt_ip.h>
-#include <us_manager/probes/register_probes.h>
-#include <us_manager/sspt/sspt.h>
+#include <us_manager/pf/pf_group.h>
+#include <us_manager/probes/probe_info_new.h>
#include <uprobe/swap_uprobes.h>
#include <parser/msg_cmd.h>
-#include <linux/module.h>
-#include <linux/slab.h>
#include <master/swap_initializer.h>
+#include "webprobe.h"
#include "webprobe_debugfs.h"
-#include "webprobe_prof.h"
#include "web_msg.h"
-static unsigned long inspserver_addr_local;
-static unsigned long tick_addr_local;
+struct web_prof_data {
+ struct dentry *app_dentry;
+ struct dentry *lib_dentry;
+ struct pf_group *pfg;
+ u64 inspserver_addr;
+ u64 tick_addr;
+ bool enable;
+};
-static int webprobe_copy(struct probe_info *dest,
- const struct probe_info *source)
+static DEFINE_MUTEX(web_mutex);
+static const char *CHROMIUM_EWK = "/usr/lib/libchromium-ewk.so";
+static struct web_prof_data *web_data;
+
+/* function tick handler */
+static int tick_handler(struct uprobe *p, struct pt_regs *regs);
+static struct probe_desc pin_tick_handler = MAKE_UPROBE(tick_handler);
+static struct probe_new tick_probe = {
+ .desc = &pin_tick_handler
+};
+
+/* function inspector port */
+static int insport_rhandler(struct uretprobe_instance *ri,
+ struct pt_regs *regs);
+static struct probe_desc pin_insport_rhandler =
+ MAKE_URPROBE(NULL, insport_rhandler, 0);
+static struct probe_new insport_probe = {
+ .desc = &pin_insport_rhandler
+};
+
+static int insport_rhandler(struct uretprobe_instance *ri,
+ struct pt_regs *regs)
{
- memcpy(dest, source, sizeof(*source));
+ set_wrt_launcher_port((int)regs_return_value(regs));
return 0;
}
-static void webprobe_cleanup(struct probe_info *probe_i)
+static int tick_handler(struct uprobe *p, struct pt_regs *regs)
{
-}
+ web_sample_msg(regs);
-static struct uprobe *webprobe_get_uprobe(struct sspt_ip *ip)
-{
- return &ip->retprobe.up;
+ return 0;
}
-static int webprobe_register_probe(struct sspt_ip *ip)
+u64 *web_prof_addr_ptr(enum web_prof_addr_t type)
{
- return swap_register_uretprobe(&ip->retprobe);
-}
+ u64 *addr_ptr;
-static void webprobe_unregister_probe(struct sspt_ip *ip, int disarm)
-{
- if (ip->orig_addr == inspserver_addr_local)
- web_func_inst_remove(INSPSERVER_START);
- else if (ip->orig_addr == tick_addr_local)
- web_func_inst_remove(TICK_PROBE);
+ mutex_lock(&web_mutex);
+ switch (type) {
+ case INSPSERVER_START:
+ addr_ptr = &web_data->inspserver_addr;
+ break;
+ case TICK_PROBE:
+ addr_ptr = &web_data->tick_addr;
+ break;
+ default:
+ pr_err("ERROR: WEB_PROF_ADDR_PTR_TYPE=0x%x\n", type);
+ addr_ptr = NULL;
+ }
+ mutex_unlock(&web_mutex);
- __swap_unregister_uretprobe(&ip->retprobe, disarm);
+ return addr_ptr;
}
-static int web_entry_handler(struct uretprobe_instance *ri,
- struct pt_regs *regs)
+int web_prof_data_set(char *app_path, char *app_id)
{
- struct uretprobe *rp = ri->rp;
- struct sspt_ip *ip;
- unsigned long vaddr, page_vaddr;
- struct vm_area_struct *vma;
-
- if (!rp)
- return 0;
-
- ip = container_of(rp, struct sspt_ip, retprobe);
- vaddr = (unsigned long)ip->orig_addr;
- page_vaddr = vaddr & PAGE_MASK;
-
- vma = find_vma_intersection(current->mm, page_vaddr, page_vaddr + 1);
- if (vma && check_vma(vma)) {
- unsigned long addr = vaddr - vma->vm_start;
- struct dentry *d = vma->vm_file->f_path.dentry;
-
- if (addr == web_prof_addr(TICK_PROBE) &&
- d == web_prof_lib_dentry()) {
- tick_addr_local = ip->orig_addr;
- web_sample_msg(regs);
- }
+ int ret = 0;
+
+ mutex_lock(&web_mutex);
+ web_data->app_dentry = dentry_by_path(app_path);
+ if (!web_data->app_dentry) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ web_data->lib_dentry = dentry_by_path(CHROMIUM_EWK);
+ if (!web_data->lib_dentry) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (web_data->pfg)
+ put_pf_group(web_data->pfg);
+
+ web_data->pfg = get_pf_group_by_comm(app_id, web_data->app_dentry);
+ if (!web_data->pfg) {
+ ret = -EFAULT;
+ goto out;
}
+out:
+ mutex_unlock(&web_mutex);
+
return 0;
}
-static int web_ret_handler(struct uretprobe_instance *ri, struct pt_regs *regs)
+bool web_prof_enabled(void)
{
- struct uretprobe *rp = ri->rp;
- struct sspt_ip *ip;
- unsigned long vaddr, page_vaddr;
- struct vm_area_struct *vma;
-
- if (!rp)
- return 0;
-
- ip = container_of(rp, struct sspt_ip, retprobe);
- vaddr = (unsigned long)ip->orig_addr;
- page_vaddr = vaddr & PAGE_MASK;
-
- vma = find_vma_intersection(current->mm, page_vaddr, page_vaddr + 1);
- if (vma && check_vma(vma)) {
- unsigned long addr = vaddr - vma->vm_start;
- struct dentry *d = vma->vm_file->f_path.dentry;
-
- if (addr == web_prof_addr(INSPSERVER_START) &&
- d == web_prof_lib_dentry()) {
- inspserver_addr_local = ip->orig_addr;
- set_wrt_launcher_port((int)regs_return_value(regs));
- }
- }
+ bool ret;
- return 0;
+ mutex_lock(&web_mutex);
+ ret = web_data->enable;
+ mutex_unlock(&web_mutex);
+
+ return ret;
}
-static void webprobe_init(struct sspt_ip *ip)
+static void __web_prof_disable(struct web_prof_data *data)
{
- ip->retprobe.entry_handler = web_entry_handler;
- ip->retprobe.handler = web_ret_handler;
- ip->retprobe.maxactive = 0;
+ pin_unregister(&tick_probe, data->pfg, data->lib_dentry);
+ pin_unregister(&insport_probe, data->pfg, data->lib_dentry);
}
-static void webprobe_uninit(struct sspt_ip *ip)
+static int __web_prof_enable(struct web_prof_data *data)
{
- webprobe_cleanup(&ip->desc->info);
+ int ret;
+
+ tick_probe.offset = data->tick_addr;
+ ret = pin_register(&tick_probe, data->pfg, data->lib_dentry);
+ if (ret)
+ goto fail0;
+
+ insport_probe.offset = data->inspserver_addr;
+ ret = pin_register(&insport_probe, data->pfg, data->lib_dentry);
+ if (ret)
+ goto fail1;
+
+ return 0;
+
+fail1:
+ pin_unregister(&tick_probe, data->pfg, data->lib_dentry);
+fail0:
+ return ret;
}
-static struct probe_iface webprobe_iface = {
- .init = webprobe_init,
- .uninit = webprobe_uninit,
- .reg = webprobe_register_probe,
- .unreg = webprobe_unregister_probe,
- .get_uprobe = webprobe_get_uprobe,
- .copy = webprobe_copy,
- .cleanup = webprobe_cleanup
-};
+int web_prof_enable(void)
+{
+ int ret = 0;
-static int webprobe_module_init(void)
+ mutex_lock(&web_mutex);
+ if (web_data->enable) {
+ pr_err("ERROR: Web profiling is already enabled\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (!web_data->inspserver_addr) {
+ pr_err("bad inspserver addr 0x%llx\n",
+ web_data->inspserver_addr);
+ goto out;
+ }
+
+ if (!web_data->tick_addr) {
+ pr_err("bad tick addr 0x%llx\n", web_data->tick_addr);
+ goto out;
+ }
+
+ ret = __web_prof_enable(web_data);
+ if (ret) {
+ pr_err("failed to enable Web profiling\n");
+ goto out;
+ }
+
+ web_data->enable = true;
+
+out:
+ mutex_unlock(&web_mutex);
+
+ return ret;
+}
+
+int web_prof_disable(void)
{
int ret = 0;
- ret = swap_register_probe_type(SWAP_WEBPROBE, &webprobe_iface);
- if (ret)
- pr_err("Cannot register probe type SWAP_WEBPROBE\n");
+ mutex_lock(&web_mutex);
+ if (!web_data->enable) {
+ pr_err("ERROR: Web profiling is already disabled\n");
+ ret = -EBUSY;
+ goto out;
+ }
+ __web_prof_disable(web_data);
+ web_data->enable = false;
+
+out:
+ mutex_unlock(&web_mutex);
return ret;
}
+static int webprobe_module_init(void)
+{
+ mutex_lock(&web_mutex);
+ web_data = kzalloc(sizeof(*web_data), GFP_KERNEL);
+ if (!web_data)
+ return -ENOMEM;
+
+ web_data->enable = false;
+ mutex_unlock(&web_mutex);
+
+ return 0;
+}
+
static void webprobe_module_exit(void)
{
- swap_unregister_probe_type(SWAP_WEBPROBE);
+ mutex_lock(&web_mutex);
+ if (web_data->enable)
+ __web_prof_disable(web_data);
+
+ if (web_data->pfg)
+ put_pf_group(web_data->pfg);
+
+ kfree(web_data);
+ web_data = NULL;
+ mutex_unlock(&web_mutex);
}
SWAP_LIGHT_INIT_MODULE(NULL, webprobe_module_init, webprobe_module_exit,
+++ /dev/null
-/**
- * webprobe/webprobe_prof.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, see <http://www.gnu.org/licenses/>.
- *
- * Copyright (C) Samsung Electronics, 2015
- *
- * 2015 Anastasia Lyupa <a.lyupa@samsung.com>
- *
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/version.h>
-
-#include <us_manager/pf/pf_group.h>
-#include <us_manager/probes/probes.h>
-#include <us_manager/probes/probe_info_new.h>
-
-#include "webprobe_prof.h"
-
-static DEFINE_MUTEX(mutex_enable);
-
-struct web_prof_data {
- struct dentry *app_dentry;
- struct dentry *lib_dentry;
- struct pf_group *pfg;
- u64 inspserver_addr;
- struct probe_desc *inspserver;
- u64 tick_addr;
- struct probe_desc *tick_probe;
- enum web_prof_state_t enabled;
-};
-
-static const char *CHROMIUM_EWK = "/usr/lib/libchromium-ewk.so";
-static struct web_prof_data *web_data;
-
-u64 *web_prof_addr_ptr(enum web_prof_addr_t type)
-{
- u64 *addr_ptr;
-
- switch (type) {
- case INSPSERVER_START:
- addr_ptr = &web_data->inspserver_addr;
- break;
- case TICK_PROBE:
- addr_ptr = &web_data->tick_addr;
- break;
- default:
- pr_err("ERROR: WEB_PROF_ADDR_PTR_TYPE=0x%x\n", type);
- addr_ptr = NULL;
- }
-
- return addr_ptr;
-}
-
-unsigned long web_prof_addr(enum web_prof_addr_t type)
-{
- unsigned long addr;
-
- switch (type) {
- case INSPSERVER_START:
- addr = web_data->inspserver_addr;
- break;
- case TICK_PROBE:
- addr = web_data->tick_addr;
- break;
- default:
- pr_err("ERROR: WEB_PROF_ADDR_TYPE=0x%x\n", type);
- addr = 0;
- }
-
- return addr;
-}
-
-static struct probe_desc *web_func_inst_add(unsigned long addr)
-{
- int ret;
- struct probe_desc *probe = NULL;
-
- probe = kmalloc(sizeof(*probe), GFP_KERNEL);
-
- if (!probe)
- return NULL;
-
- memset(probe, 0, sizeof(*probe));
- probe->type = SWAP_WEBPROBE;
-
- ret = pf_register_probe(web_data->pfg, web_data->lib_dentry,
- addr, probe);
-
- return probe;
-}
-
-static int __web_func_inst_remove(unsigned long addr, struct probe_desc *pd)
-{
- int ret;
-
- if (!addr || !pd)
- return -EINVAL;
-
- /* FIXME: check that address needs removing */
- ret = pf_unregister_probe(web_data->pfg, web_data->lib_dentry,
- addr, pd);
-
- return ret;
-}
-
-int web_func_inst_remove(enum web_prof_addr_t type)
-{
- unsigned long addr = 0;
- struct probe_desc *pd = NULL;
-
- switch (type) {
- case INSPSERVER_START:
- addr = web_data->inspserver_addr;
- pd = web_data->inspserver;
- break;
- case TICK_PROBE:
- addr = web_data->tick_addr;
- pd = web_data->tick_probe;
- break;
- default:
- pr_err("ERROR: WEB_PROF_ADDR_TYPE=0x%x\n", type);
- }
-
- return __web_func_inst_remove(addr, pd);
-}
-
-int web_prof_data_set(char *app_path, char *app_id)
-{
- web_data->app_dentry = dentry_by_path(app_path);
- if (!web_data->app_dentry)
- return -EFAULT;
-
- web_data->lib_dentry = dentry_by_path(CHROMIUM_EWK);
- if (!web_data->lib_dentry)
- return -EFAULT;
-
- if (web_data->pfg)
- put_pf_group(web_data->pfg);
-
- web_data->pfg = get_pf_group_by_comm(app_id, web_data->app_dentry);
- if (!web_data->pfg)
- return -EFAULT;
-
- return 0;
-}
-
-struct dentry *web_prof_lib_dentry(void)
-{
- return web_data->lib_dentry;
-}
-
-enum web_prof_state_t web_prof_enabled(void)
-{
- return web_data->enabled;
-}
-
-int web_prof_enable(void)
-{
- int ret = 0;
-
- mutex_lock(&mutex_enable);
- if (web_data->enabled != PROF_OFF) {
- pr_err("ERROR: Web profiling is already enabled\n");
- goto out;
- }
-
- web_data->enabled = PROF_ON;
-
- if (web_data->inspserver_addr) {
- web_data->inspserver =
- web_func_inst_add(web_data->inspserver_addr);
- }
-
- if (web_data->tick_addr) {
- web_data->tick_probe =
- web_func_inst_add(web_data->tick_addr);
- }
-
-out:
- mutex_unlock(&mutex_enable);
-
- return ret;
-}
-
-int web_prof_disable(void)
-{
- int ret = 0;
-
- mutex_lock(&mutex_enable);
- if (web_data->enabled != PROF_ON) {
- pr_err("ERROR: Web profiling is already disabled\n");
- ret = -EBUSY;
- goto out;
- }
-
- web_data->enabled = PROF_OFF;
-
- if (web_data->inspserver_addr) {
- if (!__web_func_inst_remove(web_data->inspserver_addr,
- web_data->inspserver)) {
- kfree(web_data->inspserver);
- web_data->inspserver = NULL;
- }
- }
-
- if (web_data->tick_addr) {
- if (!__web_func_inst_remove(web_data->tick_addr,
- web_data->tick_probe)) {
- kfree(web_data->tick_probe);
- web_data->tick_probe = NULL;
- }
- }
-
-out:
- mutex_unlock(&mutex_enable);
-
- return ret;
-}
-
-int web_prof_init(void)
-{
- web_data = kmalloc(sizeof(*web_data), GFP_KERNEL);
- if (!web_data)
- return -ENOMEM;
-
- memset(web_data, 0, sizeof(struct web_prof_data));
-
- web_data->enabled = PROF_OFF;
-
- return 0;
-}
-
-void web_prof_exit(void)
-{
- if (web_data->pfg)
- put_pf_group(web_data->pfg);
-
- kfree(web_data->inspserver);
- kfree(web_data->tick_probe);
- kfree(web_data);
-}