* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) Samsung Electronics, 2015
*
*
*/
-
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/stddef.h>
#include <writer/swap_msg.h>
#include <writer/event_filter.h>
#include <swap-asm/swap_uprobes.h>
-
+#include "web_msg.h"
#define WEB_PREFIX KERN_INFO "[WEB_PROF] "
-
/* 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;
-};
+#define LINE_NUMBER_OFFSET 16
+#define FUNCTION_NAME_OFFSET 8
+#define SOURCE_FILE_NAME_OFFSET 12
-enum {
- OFFSET_NAME = offsetof(struct MCallIdentifier, m_name),
- OFFSET_URL = offsetof(struct MCallIdentifier, m_url),
- OFFSET_LNUM = offsetof(struct MCallIdentifier, m_lineNumber)
-};
-
-
-static int pack_web_string(void *data, size_t size,
- struct MStringImpl __user *str_imp)
+static int __string_pack(void *data, size_t size, const char __user *s)
{
int ret;
- char __user *str;
- unsigned len;
- char __user **pstr;
- unsigned __user *plen;
+ long len;
- pstr = (void __user *)str_imp + offsetof(struct MStringImpl, m_data8);
- plen = (void __user *)str_imp + offsetof(struct MStringImpl, m_length);
+ if (!s)
+ return -EPERM;
- if (get_user(str, pstr) ||
- get_user(len, plen)) {
- printk(WEB_PREFIX "%s: cannot read user memory\n", __func__);
+ len = strlen_user(s);
+ if (!len) {
+ pr_err(WEB_PREFIX "failed to get userspace string length\n");
return -EPERM;
}
- if (size < len + 1) {
- printk(WEB_PREFIX "function name is very long(len=%u)\n", len);
+ if (size < len) {
+ printk(WEB_PREFIX "function name is very long(len=%ld)\n", len);
return -ENOMEM;
}
- ret = strncpy_from_user(data, str, len);
+ ret = copy_from_user(data, s, len);
if (ret < 0) {
printk(WEB_PREFIX "%s: cannot read user memory\n", __func__);
return ret;
return ret + 1;
}
-
-void web_msg_entry(struct pt_regs *regs)
+void web_sample_msg(struct pt_regs *regs)
{
- int ret;
struct swap_msg *m;
void *p;
- long t_name, t_url;
- unsigned lnum;
- size_t pack_size = 0, size;
- struct MCallIdentifier *call_id;
struct task_struct *task = current;
+ void *call_id;
+ size_t pack_size = 0, size;
+ int line = 0;
+ long tmp, offset;
+ int ret;
+ u8 type = WEB_MSG_SAMPLING;
if (!check_event(task))
return;
- call_id = (void *)swap_get_uarg(regs, 2);
- if (get_user(t_name, (long *)((long)call_id + OFFSET_NAME)) ||
- get_user(t_url, (long *)((long)call_id + OFFSET_URL)) ||
- get_user(lnum, (unsigned *)((long)call_id + OFFSET_LNUM))) {
- printk(WEB_PREFIX "%s: cannot read user memory\n", __func__);
- return;
- }
+ /* Get opbject pointer */
+ call_id = (void *)swap_get_uarg(regs, 1);
- m = swap_msg_get(MSG_WEB_FUNCTION_ENTRY);
+ m = swap_msg_get(MSG_WEB_PROFILING);
p = swap_msg_payload(m);
size = swap_msg_size(m);
- /* Pack message */
+ /* Type */
+ *(u8 *)p = type;
+ p += sizeof(u8);
+ size -= sizeof(u8);
+ pack_size += sizeof(u8);
+
/* PID */
*(u32 *)p = task->tgid;
p += sizeof(u32);
+ size -= sizeof(u32);
+ pack_size += sizeof(u32);
+
/* TID */
*(u32 *)p = task->pid;
p += sizeof(u32);
+ size -= sizeof(u32);
+ pack_size += sizeof(u32);
+
/* Line number (in source file) */
- *(u32 *)p = lnum;
+ offset = (long)call_id + LINE_NUMBER_OFFSET;
+ if (get_user(line, (int __user *)offset)) {
+ pr_err("failed to get line number\n");
+ goto out;
+ }
+ *(u32 *)p = (u32)line;
p += sizeof(u32);
-
- size -= 3 * sizeof(u32);
- pack_size += 3 * sizeof(u32);
-
- /* Function name */
- ret = pack_web_string(p, size, (struct MStringImpl *)t_name);
+ size -= sizeof(u32);
+ pack_size += sizeof(u32);
+
+ /* Get function name string pointer */
+ offset = (long)call_id + FUNCTION_NAME_OFFSET;
+ if (get_user(tmp, (long __user *)offset)) {
+ pr_err("failed to get function name\n");
+ goto out;
+ }
+ ret = __string_pack(p, size, (const char __user *)tmp);
if (ret < 0)
- goto put_msg;
+ goto out;
p += ret;
size -= ret;
pack_size += ret;
- /* URL (source file) */
- ret = pack_web_string(p, size, (struct MStringImpl *)t_url);
- if (ret < 0)
- goto put_msg;
-
- swap_msg_flush(m, pack_size + ret);
-
-put_msg:
- swap_msg_put(m);
-}
-
-void web_msg_exit(struct pt_regs *regs)
-{
- int ret;
- struct swap_msg *m;
- void *p;
- long t_name;
- size_t pack_size = 0, size;
- struct MCallIdentifier *call_id;
- struct task_struct *task = current;
-
- if (!check_event(task))
- return;
-
- call_id = (void *)swap_get_uarg(regs, 2);
- if (get_user(t_name, (long *)((long)call_id + OFFSET_NAME))) {
- printk(WEB_PREFIX "%s: cannot read user memory\n", __func__);
- return;
+ /* Get source file name string pointer */
+ offset = (long)call_id + SOURCE_FILE_NAME_OFFSET;
+ if (get_user(tmp, (long __user *)offset)) {
+ pr_err("failed to get line number\n");
+ goto out;
}
-
- m = swap_msg_get(MSG_WEB_FUNCTION_EXIT);
- p = swap_msg_payload(m);
- size = swap_msg_size(m);
-
- /* PID */
- *(u32 *)p = task->tgid;
- p += sizeof(u32);
-
- /* TID */
- *(u32 *)p = task->pid;
- p += sizeof(u32);
-
- size -= 2 * sizeof(u32);
- pack_size += 2 * sizeof(u32);
-
- /* Function name */
- ret = pack_web_string(p, size, (struct MStringImpl *)t_name);
+ ret = __string_pack(p, size, (const char __user *)tmp);
if (ret < 0)
- goto put_msg;
+ goto out;
+
+ p += ret;
+ size -= ret;
+ pack_size += ret;
- swap_msg_flush(m, pack_size + ret);
+ swap_msg_flush(m, pack_size);
-put_msg:
+out:
swap_msg_put(m);
}
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) Samsung Electronics, 2015
*
*
*/
-
#ifndef _WEB_MSG_H
#define _WEB_MSG_H
-
struct pt_regs;
+/* Web messages subtype */
+enum web_msg_type {
+ WEB_MSG_SAMPLING = 0x00,
+};
void web_msg_entry(struct pt_regs *regs);
void web_msg_exit(struct pt_regs *regs);
-
+void web_sample_msg(struct pt_regs *regs);
#endif /* _WEB_MSG_H */
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* @section COPYRIGHT
*
* Web application profiling
*/
-
#include <us_manager/us_manager.h>
#include <us_manager/sspt/sspt_ip.h>
#include <us_manager/probes/register_probes.h>
#include "webprobe_prof.h"
#include "web_msg.h"
-
static unsigned long inspserver_addr_local;
-static unsigned long willexecute_addr_local;
-static unsigned long didexecute_addr_local;
+static unsigned long tick_addr_local;
static int webprobe_copy(struct probe_info *dest,
const struct probe_info *source)
{
if (ip->orig_addr == inspserver_addr_local)
web_func_inst_remove(INSPSERVER_START);
- else if (ip->orig_addr == willexecute_addr_local)
- web_func_inst_remove(WILL_EXECUTE);
- else if (ip->orig_addr == didexecute_addr_local)
- web_func_inst_remove(DID_EXECUTE);
+ else if (ip->orig_addr == tick_addr_local)
+ web_func_inst_remove(TICK_PROBE);
__swap_unregister_uretprobe(&ip->retprobe, disarm);
}
unsigned long vaddr, page_vaddr;
struct vm_area_struct *vma;
- if (rp == NULL)
+ if (!rp)
return 0;
ip = container_of(rp, struct sspt_ip, retprobe);
unsigned long addr = vaddr - vma->vm_start;
struct dentry *d = vma->vm_file->f_path.dentry;
- if (addr == web_prof_addr(WILL_EXECUTE) &&
+ if (addr == web_prof_addr(TICK_PROBE) &&
d == web_prof_lib_dentry()) {
- willexecute_addr_local = ip->orig_addr;
- web_msg_entry(regs);
- } else if (addr == web_prof_addr(DID_EXECUTE) &&
- d == web_prof_lib_dentry()) {
- didexecute_addr_local = ip->orig_addr;
- web_msg_exit(regs);
+ tick_addr_local = ip->orig_addr;
+ web_sample_msg(regs);
}
}
return 0;
}
-
static int web_ret_handler(struct uretprobe_instance *ri, struct pt_regs *regs)
{
struct uretprobe *rp = ri->rp;
unsigned long vaddr, page_vaddr;
struct vm_area_struct *vma;
- if (rp == NULL)
+ if (!rp)
return 0;
ip = container_of(rp, struct sspt_ip, retprobe);
webprobe_cleanup(&ip->desc->info);
}
-
static struct probe_iface webprobe_iface = {
.init = webprobe_init,
.uninit = webprobe_uninit,
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) Samsung Electronics, 2015
*
*
*/
-
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/debugfs.h>
static const char ENABLED_FILE[] = "enabled";
static const char APP_INFO_FILE[] = "app_info";
static const char INSPSERVER_START_FILE[] = "inspector_server_start";
-static const char WILL_EXECUTE_FILE[] = "will_execute";
-static const char DID_EXECUTE_FILE[] = "did_execute";
+static const char TICK_PROBE_FILE[] = "tick_probe";
enum { max_count = 256 };
static char app_info[max_count];
return -ENOMEM;
buf = kmalloc(count + 1, GFP_KERNEL);
- if (buf == NULL)
+ if (!buf)
return -ENOMEM;
if (copy_from_user(buf, user_buf, count)) {
buf[count] = '\0';
path = kmalloc(count, GFP_KERNEL);
- if (path == NULL) {
+ if (!path) {
ret = -ENOMEM;
goto free_buf;
}
id = kmalloc(count, GFP_KERNEL);
- if (id == NULL) {
+ if (!id) {
ret = -ENOMEM;
goto free_path;
}
.release = swap_init_simple_release,
};
-
/* ============================================================================
* === INIT/EXIT ===
* ============================================================================
goto fail;
dentry = swap_debugfs_getdir();
- if (dentry == NULL)
+ if (!dentry)
return -ENOENT;
webprobe_dir = debugfs_create_dir("webprobe", dentry);
- if (webprobe_dir == NULL)
+ if (!webprobe_dir)
return -ENOMEM;
dentry = debugfs_create_file(ENABLED_FILE, 0600, webprobe_dir, NULL,
&fops_enabled);
dentry = debugfs_create_file(APP_INFO_FILE, 0600, webprobe_dir,
- NULL, &fops_app_info);
- if (dentry == NULL)
+ NULL, &fops_app_info);
+ if (!dentry)
goto fail;
dentry = debugfs_create_x64(INSPSERVER_START_FILE, 0600, webprobe_dir,
web_prof_addr_ptr(INSPSERVER_START));
- if (dentry == NULL)
- goto fail;
-
- dentry = debugfs_create_x64(WILL_EXECUTE_FILE, 0600, webprobe_dir,
- web_prof_addr_ptr(WILL_EXECUTE));
- if (dentry == NULL)
+ if (!dentry)
goto fail;
- dentry = debugfs_create_x64(DID_EXECUTE_FILE, 0600, webprobe_dir,
- web_prof_addr_ptr(DID_EXECUTE));
- if (dentry == NULL)
+ dentry = debugfs_create_x64(TICK_PROBE_FILE, 0600, webprobe_dir,
+ web_prof_addr_ptr(TICK_PROBE));
+ if (!dentry)
goto fail;
return 0;
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* @section COPYRIGHT
* Copyright (C) Samsung Electronics, 2015
* Debugfs for webprobe
*/
-
int webprobe_debugfs_init(void);
void webprobe_debugfs_exit(void);
-
#endif /* _WEBPROBE_DEBUGFS_H */
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) Samsung Electronics, 2015
*
*
*/
-
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/version.h>
#include "webprobe_prof.h"
-
static DEFINE_MUTEX(mutex_enable);
struct web_prof_data {
struct pf_group *pfg;
u64 inspserver_addr;
struct probe_desc *inspserver;
- u64 willexecute_addr;
- struct probe_desc *willexecute;
- u64 didexecute_addr;
- struct probe_desc *didexecute;
+ u64 tick_addr;
+ struct probe_desc *tick_probe;
enum web_prof_state_t enabled;
};
-static const char *LIBEWEBKIT2_PATH = "/usr/lib/libewebkit2.so.0";
+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;
case INSPSERVER_START:
addr_ptr = &web_data->inspserver_addr;
break;
- case WILL_EXECUTE:
- addr_ptr = &web_data->willexecute_addr;
- break;
- case DID_EXECUTE:
- addr_ptr = &web_data->didexecute_addr;
+ case TICK_PROBE:
+ addr_ptr = &web_data->tick_addr;
break;
default:
pr_err("ERROR: WEB_PROF_ADDR_PTR_TYPE=0x%x\n", type);
case INSPSERVER_START:
addr = web_data->inspserver_addr;
break;
- case WILL_EXECUTE:
- addr = web_data->willexecute_addr;
- break;
- case DID_EXECUTE:
- addr = web_data->didexecute_addr;
+ case TICK_PROBE:
+ addr = web_data->tick_addr;
break;
default:
pr_err("ERROR: WEB_PROF_ADDR_TYPE=0x%x\n", type);
int web_func_inst_remove(enum web_prof_addr_t type)
{
- unsigned long addr = 0;
+ unsigned long addr = 0;
struct probe_desc *pd = NULL;
switch (type) {
addr = web_data->inspserver_addr;
pd = web_data->inspserver;
break;
- case WILL_EXECUTE:
- addr = web_data->willexecute_addr;
- pd = web_data->willexecute;
- break;
- case DID_EXECUTE:
- addr = web_data->didexecute_addr;
- pd = web_data->didexecute;
+ 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 == NULL)
+ if (!web_data->app_dentry)
return -EFAULT;
- web_data->lib_dentry = dentry_by_path(LIBEWEBKIT2_PATH);
- if (web_data->lib_dentry == NULL)
+ 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 == NULL)
+ if (!web_data->pfg)
return -EFAULT;
return 0;
int ret = 0;
mutex_lock(&mutex_enable);
- if (web_data->enabled == PROF_OFF) {
- web_data->enabled = PROF_ON;
-
- if ((web_data->inspserver_addr == 0) ||
- (web_data->willexecute_addr == 0) ||
- (web_data->didexecute_addr == 0)) {
- pr_err("ERROR: Can't enable web profiling\n");
- ret = -EFAULT;
- } else {
- web_data->inspserver =
- web_func_inst_add(web_data->inspserver_addr);
-
- web_data->willexecute =
- web_func_inst_add(web_data->willexecute_addr);
-
- web_data->didexecute =
- web_func_inst_add(web_data->didexecute_addr);
- }
- } else {
+ 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 ret = 0;
mutex_lock(&mutex_enable);
- if (web_data->enabled == PROF_ON) {
- web_data->enabled = PROF_OFF;
-
- if ((web_data->inspserver_addr == 0) ||
- (web_data->willexecute_addr == 0) ||
- (web_data->didexecute_addr == 0)) {
- pr_err("ERROR: Can't disable web profiling\n");
- ret = -EFAULT;
- } else {
- if (!__web_func_inst_remove(web_data->inspserver_addr,
- web_data->inspserver)) {
- kfree(web_data->inspserver);
- web_data->inspserver = NULL;
- }
-
- if (!__web_func_inst_remove(web_data->willexecute_addr,
- web_data->willexecute)) {
- kfree(web_data->willexecute);
- web_data->willexecute = NULL;
- }
-
- if (!__web_func_inst_remove(web_data->didexecute_addr,
- web_data->didexecute)) {
- kfree(web_data->didexecute);
- web_data->didexecute = NULL;
- }
- }
- } else {
+ 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 == NULL)
+ if (!web_data)
return -ENOMEM;
memset(web_data, 0, sizeof(struct web_prof_data));
return 0;
}
-
void web_prof_exit(void)
{
if (web_data->pfg)
put_pf_group(web_data->pfg);
- if (web_data->inspserver)
- kfree(web_data->inspserver);
-
- if (web_data->willexecute)
- kfree(web_data->willexecute);
-
- if (web_data->didexecute)
- kfree(web_data->didexecute);
-
+ kfree(web_data->inspserver);
+ kfree(web_data->tick_probe);
kfree(web_data);
}
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* @section COPYRIGHT
* Copyright (C) Samsung Electronics, 2015
* Profiling for webprobe
*/
-
enum web_prof_addr_t {
INSPSERVER_START = 1,
- WILL_EXECUTE = 2,
- DID_EXECUTE = 3
+ TICK_PROBE
};
enum web_prof_state_t {
MSG_PROC_MAP = 0x0012,
MSG_PROC_UNMAP = 0x0013,
MSG_PROC_COMM = 0x0014,
- MSG_WEB_FUNCTION_ENTRY = 0x0015,
- MSG_WEB_FUNCTION_EXIT = 0x0016,
+ MSG_WEB_PROFILING = 0x0015,
MSG_NSP = 0x0019,
MSG_WSP = 0x001a,
MSG_FBI = 0x0020