2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * Copyright (C) Samsung Electronics, 2015
18 * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
23 #include <uprobe/swap_uaccess.h>
24 #include <us_manager/sspt/sspt.h>
25 #include <us_manager/probes/probe_info_new.h>
33 struct probe_new probe;
39 struct wsp_probe *probe_array;
43 /* TODO: configure this from outside (using debugfs) */
44 static const char webapp_path[] = "/usr/bin/wrt_launchpad_daemon";
45 static const char ewebkit_path[] = "/usr/lib/libewebkit2.so";
48 #define WSP_PROBE_MAKE(__name, __desc) \
52 .probe.desc = __desc \
56 static void do_res_processing_begin(void *data, void *ptr, enum wsp_res_t type)
58 struct wsp_res **save_res = (struct wsp_res **)data;
61 res = wsp_res_find(ptr, type);
63 /* save res pointer */
66 wsp_msg(WSP_RES_PROC_BEGIN, res->id, NULL);
67 wsp_res_stat_set_next(res, WRS_ADD_DATA);
71 static void do_res_processing_end(struct wsp_res *res)
73 wsp_msg(WSP_RES_PROC_END, res->id, NULL);
76 static void do_res_finish(struct wsp_res *res)
78 wsp_msg(WSP_RES_LOAD_END, res->id, NULL);
79 wsp_res_stat_set_next(res, WRS_FINISH);
87 static int soup_req_handle(struct uprobe *p, struct pt_regs *regs)
89 enum { max_str_len = 512 };
90 const char __user *user_s;
96 pr_err("last wsp_res is not found\n");
100 user_s = (const char __user *)swap_get_uarg(regs, 1);
101 path = strdup_from_user(user_s, GFP_ATOMIC);
103 pr_warn("soup_req_handle: invalid path\n");
107 wsp_msg(WSP_RES_LOAD_BEGIN, res->id, path);
108 wsp_res_stat_set_next(res, WRS_SOUP_REQ);
114 static struct probe_desc soup_req = MAKE_UPROBE(soup_req_handle);
120 static int mres_req_handle(struct uprobe *p, struct pt_regs *regs)
122 void *ptr = (void *)swap_get_uarg(regs, 0);
125 res = wsp_res_new(ptr, WR_MAIN);
127 wsp_res_stat_set_next(res, WRS_WILL_REQ);
132 static struct probe_desc mres_req = MAKE_UPROBE(mres_req_handle);
139 static int mres_adata_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
141 void *ptr = (void *)swap_get_uarg(regs, 0);
143 do_res_processing_begin(ri->data, ptr, WR_MAIN);
148 static int mres_adata_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
150 struct wsp_res *res = *(struct wsp_res **)ri->data;
153 do_res_processing_end(res);
158 static struct probe_desc mres_adata =
159 MAKE_URPROBE(mres_adata_eh, mres_adata_rh,
160 sizeof(struct wsp_res *));
166 static int mres_finish_handle(struct uprobe *p, struct pt_regs *regs)
168 void *ptr = (void *)swap_get_uarg(regs, 0);
171 res = wsp_res_find(ptr, WR_MAIN);
173 wsp_current_set_stat(TDS_FINISH_MAIN_LOAD);
180 static struct probe_desc mres_finish = MAKE_UPROBE(mres_finish_handle);
186 static int res_request_handle(struct uprobe *p, struct pt_regs *regs)
188 void *ptr = (void *)swap_get_uarg(regs, 0);
191 res = wsp_res_last();
193 if (res->type == WR_MAIN && res->stat == WRS_WILL_REQ)
198 res = wsp_res_new(ptr, WR_ANY);
200 wsp_res_stat_set_next(res, WRS_WILL_REQ);
205 static struct probe_desc res_request = MAKE_UPROBE(res_request_handle);
211 static int res_finish_ehandle(struct uretprobe_instance *ri,
212 struct pt_regs *regs)
214 void *ptr = (void *)swap_get_uarg(regs, 0);
216 do_res_processing_begin(ri->data, ptr, WR_ANY);
221 static int res_finish_rhandle(struct uretprobe_instance *ri,
222 struct pt_regs *regs)
224 struct wsp_res *res = *(struct wsp_res **)ri->data;
227 do_res_processing_end(res);
234 static struct probe_desc res_finish =
235 MAKE_URPROBE(res_finish_ehandle, res_finish_rhandle,
236 sizeof(struct wsp_res *));
242 static int redraw_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
244 enum tdata_stat stat;
246 stat = wsp_current_get_stat();
248 if (stat == TDS_FINISH_MAIN_LOAD)
249 wsp_msg(WSP_DRAW_BEGIN, 0, NULL);
254 static int redraw_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
256 if (wsp_current_get_stat() == TDS_FINISH_MAIN_LOAD) {
257 wsp_current_set_stat(TDS_DRAW);
258 wsp_msg(WSP_DRAW_END, 0, NULL);
264 static struct probe_desc redraw = MAKE_URPROBE(redraw_eh, redraw_rh, 0);
267 static struct wsp_probe ewebkit_probe_array[] = {
269 /* soup_requester_request@plt */
270 WSP_PROBE_MAKE("soup_requester_request@plt", &soup_req),
273 /* WebCore::MainResourceLoader::willSendRequest(WebCore::ResourceRequest&, WebCore::ResourceResponse const&) */
274 WSP_PROBE_MAKE("_ZN7WebCore18MainResourceLoader15willSendRequestERNS_15ResourceRequestERKNS_16ResourceResponseE", &mres_req),
275 /* WebCore::MainResourceLoader::addData(char const*, int, bool) */
276 WSP_PROBE_MAKE("_ZN7WebCore18MainResourceLoader7addDataEPKcib", &mres_adata),
277 /* WebCore::MainResourceLoader::didFinishLoading(double) */
278 WSP_PROBE_MAKE("_ZN7WebCore18MainResourceLoader16didFinishLoadingEd", &mres_finish),
282 /* WebCore::ResourceLoader::willSendRequest(WebCore::ResourceRequest&, WebCore::ResourceResponse const&) */
283 WSP_PROBE_MAKE("_ZN7WebCore14ResourceLoader15willSendRequestERNS_15ResourceRequestERKNS_16ResourceResponseE", &res_request),
284 /* WebCore::ResourceLoader::didFinishLoading(WebCore::ResourceHandle*, double) */
285 WSP_PROBE_MAKE("_ZN7WebCore14ResourceLoader16didFinishLoadingEPNS_14ResourceHandleEd", &res_finish),
289 /* WebKit::LayerTreeCoordinator::flushPendingLayerChanges() */
290 WSP_PROBE_MAKE("_ZN6WebKit20LayerTreeCoordinator24flushPendingLayerChangesEv", &redraw),
295 sizeof(ewebkit_probe_array) / sizeof(struct wsp_probe)
298 static struct wsp_bin ewebkit = {
299 .name = ewebkit_path,
300 .cnt = ewebkit_probes_cnt,
301 .probe_array = ewebkit_probe_array
305 /* check ewebkit_probe_array on init address */
306 static bool wsp_is_addr_init(void)
310 for (i = 0; i < ewebkit_probes_cnt; ++i)
311 if (ewebkit_probe_array[i].probe.offset == 0)
318 static int wsp_probe_register(struct pf_group *pfg, struct dentry *dentry,
319 struct wsp_probe *wsp_probe)
321 struct probe_new *probe_new = &wsp_probe->probe;
323 return pin_register(probe_new, pfg, dentry);
326 static void wsp_probe_unregister(struct pf_group *pfg, struct dentry *dentry,
327 struct wsp_probe *wsp_probe)
329 struct probe_new *probe_new = &wsp_probe->probe;
331 pin_unregister(probe_new, pfg, dentry);
337 static int wsp_bin_register(struct pf_group *pfg, struct wsp_bin *bin)
340 struct dentry *dentry;
342 dentry = dentry_by_path(bin->name);
343 if (dentry == NULL) {
344 pr_err("dentry not found (path='%s'\n", bin->name);
348 for (i = 0; i < bin->cnt; ++i) {
349 struct wsp_probe *p = &bin->probe_array[i];
351 ret = wsp_probe_register(pfg, dentry, p);
353 pr_err("ERROR: wsp_probe_register, addr=%lx ret=%d\n",
354 p->probe.offset, ret);
362 static void wsp_bin_unregister(struct pf_group *pfg, struct wsp_bin *bin)
365 struct dentry *dentry;
367 dentry = dentry_by_path(bin->name);
368 for (i = 0; i < bin->cnt; ++i)
369 wsp_probe_unregister(pfg, dentry, &bin->probe_array[i]);
373 static struct pf_group *g_pfg;
375 static int wsp_app_register(void)
377 struct dentry *dentry;
379 dentry = dentry_by_path(webapp_path);
380 if (dentry == NULL) {
381 pr_err("dentry not found (path='%s'\n", webapp_path);
385 g_pfg = get_pf_group_by_dentry(dentry, (void *)dentry);
387 pr_err("g_pfg is NULL (by dentry=%p)\n", dentry);
391 return wsp_bin_register(g_pfg, &ewebkit);
394 static void wsp_app_unregister(void)
396 wsp_bin_unregister(g_pfg, &ewebkit);
401 static int do_wsp_on(void)
405 ret = wsp_res_init();
409 ret = wsp_app_register();
416 static void do_wsp_off(void)
418 wsp_app_unregister();
423 static enum wsp_mode g_mode = WSP_OFF;
424 static DEFINE_MUTEX(g_mode_mutex);
426 int wsp_set_addr(const char *name, unsigned long offset)
430 if (mutex_trylock(&g_mode_mutex) == 0)
433 for (i = 0; i < ewebkit_probes_cnt; ++i) {
434 if (0 == strcmp(name, ewebkit_probe_array[i].name)) {
435 ewebkit_probe_array[i].probe.offset = offset;
443 mutex_unlock(&g_mode_mutex);
447 int wsp_set_mode(enum wsp_mode mode)
451 mutex_lock(&g_mode_mutex);
454 if (g_mode == WSP_ON) {
459 ret = wsp_is_addr_init() ? do_wsp_on() : -EPERM;
462 if (g_mode == WSP_OFF) {
478 mutex_unlock(&g_mode_mutex);
482 enum wsp_mode wsp_get_mode(void)
494 wsp_set_mode(WSP_OFF);