static dev_t swap_device_no;
/* Device cdev struct */
-static struct cdev *swap_device_cdev;
+static struct cdev swap_device_cdev;
/* Device class struct */
static struct class *swap_device_class;
goto init_fail;
}
- /* Cdev allocation */
- swap_device_cdev = cdev_alloc();
- if (!swap_device_cdev) {
- print_crit("Cdev structure allocation has failed\n");
- result = -E_SD_CDEV_ALLOC_FAIL;
- goto init_fail;
- }
-
/* Cdev intialization and setting file operations */
- cdev_init(swap_device_cdev, &swap_device_fops);
+ cdev_init(&swap_device_cdev, &swap_device_fops);
/* Adding cdev to system */
- result = cdev_add(swap_device_cdev, swap_device_no, 1);
+ result = cdev_add(&swap_device_cdev, swap_device_no, 1);
if (result < 0) {
print_crit("Device adding has failed\n");
result = -E_SD_CDEV_ADD_FAIL;
return 0;
init_fail:
- if (swap_device_cdev)
- cdev_del(swap_device_cdev);
+ cdev_del(&swap_device_cdev);
if (swap_device_class)
class_destroy(swap_device_class);
if (swap_device_no)
splice_grow_spd_p = NULL;
device_destroy(swap_device_class, swap_device_no);
- cdev_del(swap_device_cdev);
+ cdev_del(&swap_device_cdev);
class_destroy(swap_device_class);
unregister_chrdev_region(swap_device_no, 1);
}
return 0;
}
-static int fbi_probe_handler(struct kprobe *p, struct pt_regs *regs)
+static int fbi_probe_handler(struct uprobe *p, struct pt_regs *regs)
{
- struct uprobe *up = container_of(p, struct uprobe, kp);
- struct us_ip *ip = container_of(up, struct us_ip, uprobe);
- struct fbi_info *fbi_i = &ip->info->fbi_i;
+ struct us_ip *ip = container_of(p, struct us_ip, uprobe);
+ struct fbi_info *fbi_i = &ip->desc->info.fbi_i;
struct fbi_var_data *fbi_d = NULL;
uint8_t i;
- if (ip->info->probe_type != SWAP_FBIPROBE) {
+ if (ip->desc->type != SWAP_FBIPROBE) {
/* How this can occure? Doesn't matter, just print and go */
print_err("Not FBI probe in FBI handler!\n");
return 0;
void fbi_probe_init(struct us_ip *ip)
{
- ip->uprobe.kp.pre_handler = (kprobe_pre_handler_t)fbi_probe_handler;
+ ip->uprobe.pre_handler = (uprobe_pre_handler_t)fbi_probe_handler;
}
void fbi_probe_uninit(struct us_ip *ip)
{
if (ip != NULL)
- fbi_probe_cleanup(ip->info);
+ fbi_probe_cleanup(&ip->desc->info);
}
static int fbi_probe_register_probe(struct us_ip *ip)
#include <kprobe/dbi_uprobes.h>
#include <ksyms/ksyms.h>
-#define SUPRESS_BUG_MESSAGES
-
unsigned int *arr_traps_original;
int ret = 0, pid = 0, retprobe = 0, reenter = 0;
kprobe_opcode_t *addr = NULL, *ssaddr = 0;
struct kprobe_ctlblk *kcb;
-#ifdef SUPRESS_BUG_MESSAGES
- int swap_oops_in_progress;
-#endif
/* We're in an interrupt, but this is clear and BUG()-safe. */
addr = (kprobe_opcode_t *) regs->cp0_epc;
DBPRINTF("regs->regs[ 31 ] = 0x%lx\n", regs->regs[31]);
-#ifdef SUPRESS_BUG_MESSAGES
- /* oops_in_progress used to avoid BUG() messages that
- * slow down kprobe_handler() execution */
- swap_oops_in_progress = oops_in_progress;
- oops_in_progress = 1;
-#endif
preempt_disable();
kcb = get_kprobe_ctlblk();
if (!p->ainsn.boostable)
kcb->kprobe_status = KPROBE_REENTER;
preempt_enable_no_resched();
-#ifdef SUPRESS_BUG_MESSAGES
- oops_in_progress = swap_oops_in_progress;
-#endif
return 1;
}
} else {
if (!p->ainsn.boostable)
kcb->kprobe_status = KPROBE_HIT_SS;
else if (p->pre_handler != trampoline_probe_handler) {
-#ifdef SUPRESS_BUG_MESSAGES
- preempt_disable();
-#endif
reset_current_kprobe();
-#ifdef SUPRESS_BUG_MESSAGES
- preempt_enable_no_resched();
-#endif
}
}
if (ret) {
DBPRINTF("p->pre_handler[] 1");
-#ifdef SUPRESS_BUG_MESSAGES
- oops_in_progress = swap_oops_in_progress;
-#endif
/* handler has already set things up, so skip ss setup */
return 1;
}
no_kprobe:
preempt_enable_no_resched();
-#ifdef SUPRESS_BUG_MESSAGES
- oops_in_progress = swap_oops_in_progress;
-#endif
return ret;
}
#include <kprobe/swap_kdebug.h>
#include <kprobe/swap_slots.h>
#include <kprobe/swap_kprobes_deps.h>
-#define SUPRESS_BUG_MESSAGES /**< Debug-off definition. */
static int (*swap_fixup_exception)(struct pt_regs *regs);
static int kprobe_handler(struct pt_regs *regs)
{
int ret;
-#ifdef SUPRESS_BUG_MESSAGES
- int swap_oops_in_progress;
- /*
- * oops_in_progress used to avoid BUG() messages
- * that slow down kprobe_handler() execution
- */
- swap_oops_in_progress = oops_in_progress;
- oops_in_progress = 1;
-#endif
ret = __kprobe_handler(regs);
-#ifdef SUPRESS_BUG_MESSAGES
- oops_in_progress = swap_oops_in_progress;
-#endif
-
return ret;
}
/* dlopen@plt */
static int dlopen_eh(struct uretprobe_instance *ri, struct pt_regs *regs);
static int dlopen_rh(struct uretprobe_instance *ri, struct pt_regs *regs);
-static struct probe_info_new pin_dlopen = MAKE_URPROBE(dlopen_eh, dlopen_rh, 0);
+static struct probe_desc pin_dlopen = MAKE_URPROBE(dlopen_eh, dlopen_rh, 0);
static struct probe_new p_dlopen = {
- .info = &pin_dlopen
+ .desc = &pin_dlopen
};
/* dlsym@plt */
static int dlsym_eh(struct uretprobe_instance *ri, struct pt_regs *regs);
static int dlsym_rh(struct uretprobe_instance *ri, struct pt_regs *regs);
-static struct probe_info_new pin_dlsym = MAKE_URPROBE(dlsym_eh, dlsym_rh, 0);
+static struct probe_desc pin_dlsym = MAKE_URPROBE(dlsym_eh, dlsym_rh, 0);
static struct probe_new p_dlsym = {
- .info = &pin_dlsym
+ .desc = &pin_dlsym
};
/* main */
static int main_eh(struct uretprobe_instance *ri, struct pt_regs *regs);
static int main_rh(struct uretprobe_instance *ri, struct pt_regs *regs);
-static struct probe_info_new pin_main = MAKE_URPROBE(main_eh, main_rh, 0);
+static struct probe_desc pin_main = MAKE_URPROBE(main_eh, main_rh, 0);
/* appcore_efl_main */
-static int ac_efl_main_h(struct kprobe *p, struct pt_regs *regs);
-static struct probe_info_new pin_ac_efl_main = MAKE_UPROBE(ac_efl_main_h);
+static int ac_efl_main_h(struct uprobe *p, struct pt_regs *regs);
+static struct probe_desc pin_ac_efl_main = MAKE_UPROBE(ac_efl_main_h);
static struct probe_new p_ac_efl_main = {
- .info = &pin_ac_efl_main
+ .desc = &pin_ac_efl_main
};
/* appcore_init@plt */
static int ac_init_rh(struct uretprobe_instance *ri, struct pt_regs *regs);
-static struct probe_info_new pin_ac_init = MAKE_URPROBE(NULL, ac_init_rh, 0);
+static struct probe_desc pin_ac_init = MAKE_URPROBE(NULL, ac_init_rh, 0);
static struct probe_new p_ac_init = {
- .info = &pin_ac_init
+ .desc = &pin_ac_init
};
/* elm_run@plt */
-static int elm_run_h(struct kprobe *p, struct pt_regs *regs);
-static struct probe_info_new pin_elm_run = MAKE_UPROBE(elm_run_h);
+static int elm_run_h(struct uprobe *p, struct pt_regs *regs);
+static struct probe_desc pin_elm_run = MAKE_UPROBE(elm_run_h);
static struct probe_new p_elm_run = {
- .info = &pin_elm_run
+ .desc = &pin_elm_run
};
/* __do_app */
static int do_app_eh(struct uretprobe_instance *ri, struct pt_regs *regs);
static int do_app_rh(struct uretprobe_instance *ri, struct pt_regs *regs);
-static struct probe_info_new pin_do_app = MAKE_URPROBE(do_app_eh, do_app_rh, 0);
+static struct probe_desc pin_do_app = MAKE_URPROBE(do_app_eh, do_app_rh, 0);
static struct probe_new p_do_app = {
- .info = &pin_do_app
+ .desc = &pin_do_app
};
}
data->app_dentry = dentry;
- data->p_main.info = &pin_main;
+ data->p_main.desc = &pin_main;
data->p_main.offset = main_addr;
data->pfg = NULL;
}
}
-static int main_h(struct kprobe *p, struct pt_regs *regs)
+static int main_h(struct uprobe *p, struct pt_regs *regs)
{
struct tdata *tdata;
u64 time_start;
struct uretprobe *rp = ri->rp;
if (rp) {
- main_h(&rp->up.kp, regs);
+ main_h(&rp->up, regs);
if (get_quiet() == QT_OFF) {
struct us_ip *ip;
ip = container_of(rp, struct us_ip, retprobe);
func_addr = (unsigned long)ip->orig_addr;
ret_addr = (unsigned long)ri->ret_addr;
- ret_type = ip->info->rp_i.ret_type;
+ ret_type = ip->desc->info.rp_i.ret_type;
rp_msg_exit(regs, func_addr, 'n', ret_addr);
}
return 0;
}
-static int ac_efl_main_h(struct kprobe *p, struct pt_regs *regs)
+static int ac_efl_main_h(struct uprobe *p, struct pt_regs *regs)
{
stage_end(NPS_MAIN_E, NPS_AC_EFL_MAIN_E, NMS_MAIN);
return 0;
return 0;
}
-static int elm_run_h(struct kprobe *p, struct pt_regs *regs)
+static int elm_run_h(struct uprobe *p, struct pt_regs *regs)
{
stage_end(NPS_AC_INIT_R, NPS_ELM_RUN_E, NMS_CREATE);
return 0;
#include <us_manager/us_manager.h>
+static LIST_HEAD(app_inst_head);
static int wrt_launcher_port;
static int set_config(struct conf_data *conf)
int msg_start(struct msg_buf *mb)
{
int ret = 0;
- struct us_inst_data *us_inst;
+ u32 cnt;
struct conf_data conf;
swap_msg_seq_num_reset();
swap_msg_discard_reset();
- us_inst = create_us_inst_data(mb);
- if (us_inst == NULL)
+ cnt = create_us_inst_data(mb, &app_inst_head);
+ if (!cnt)
return -EINVAL;
if (!is_end_mb(mb)) {
goto free_us_inst;
}
- ret = mod_us_inst(us_inst, MT_ADD);
+ ret = mod_us_inst(&app_inst_head, MT_ADD);
if (ret) {
printk(KERN_INFO "Cannot mod us inst, ret = %d\n", ret);
ret = -EINVAL;
restore_config(&conf);
set_config(&conf);
+ return ret;
+
free_us_inst:
- destroy_us_inst_data(us_inst);
+ destroy_us_inst_data(&app_inst_head);
return ret;
}
printk(KERN_INFO "discarded messages: %d\n", discarded);
swap_msg_discard_reset();
+ destroy_us_inst_data(&app_inst_head);
+
return ret;
}
int msg_swap_inst_add(struct msg_buf *mb)
{
int ret = 0;
- struct us_inst_data *us_inst;
+ u32 cnt;
+ struct app_inst_data *src, *n;
+ struct list_head app_head;
- us_inst = create_us_inst_data(mb);
- if (us_inst == NULL)
+ INIT_LIST_HEAD(&app_head);
+ cnt = create_us_inst_data(mb, &app_head);
+ if (!cnt)
return -EINVAL;
if (!is_end_mb(mb)) {
goto free_us_inst;
}
- ret = mod_us_inst(us_inst, MT_ADD);
+ list_for_each_entry_safe(src, n, &app_head, list) {
+ struct app_inst_data *dst;
+
+ dst = app_inst_data_find(&app_inst_head, src);
+ if (dst) {
+ app_inst_data_splice(dst, src);
+ } else {
+ list_del(&src->list);
+ list_add_tail(&src->list, &app_inst_head);
+ }
+ }
+
+ ret = mod_us_inst(&app_inst_head, MT_ADD);
free_us_inst:
- destroy_us_inst_data(us_inst);
+ destroy_us_inst_data(&app_head);
return ret;
}
int msg_swap_inst_remove(struct msg_buf *mb)
{
int ret = 0;
- struct us_inst_data *us_inst;
+ u32 cnt;
+ struct list_head app_head;
+ struct app_inst_data *src, *n;
- us_inst = create_us_inst_data(mb);
- if (us_inst == NULL)
+ INIT_LIST_HEAD(&app_head);
+ cnt = create_us_inst_data(mb, &app_head);
+ if (!cnt)
return -EINVAL;
if (!is_end_mb(mb)) {
goto free_us_inst;
}
- ret = mod_us_inst(us_inst, MT_DEL);
+ list_for_each_entry_safe(src, n, &app_inst_head, list) {
+ struct app_inst_data *dst;
+
+ dst = app_inst_data_find(&app_head, src);
+ if (dst) {
+ app_inst_data_move(dst, src);
+ if (list_empty(&src->f_head) &&
+ list_empty(&src->l_head)) {
+ destroy_app_inst_data(src);
+ }
+ }
+ }
+
+ ret = mod_us_inst(&app_head, MT_DEL);
free_us_inst:
- destroy_us_inst_data(us_inst);
+ destroy_us_inst_data(&app_head);
return ret;
}
#include "msg_buf.h"
#include "parser_defs.h"
-
-static int str_to_u32(const char *str, u32 *val)
-{
- u32 result;
- if (!str || !*str)
- return -EINVAL;
-
- for (result = 0 ; *str; ++str) {
- if (*str < '0' || *str > '9')
- return -EINVAL;
-
- result = result * 10 + (*str - '0');
- }
-
- *val = result;
-
- return 0;
-}
-
-
-
-
-
/* ============================================================================
* == APP_INFO ==
* ============================================================================
* @brief Creates and fills app_info_data struct.
*
* @param mb Pointer to the message buffer.
- * @return Pointer to the filled app_info_data struct on success;\n
- * NULL on error.
+ * @param ai Pointer to the target app_inst_data.
+ * @return 0 on success, error code on error.
*/
-struct app_info_data *create_app_info(struct msg_buf *mb)
+int create_app_info(struct msg_buf *mb, struct app_inst_data *ai)
{
int ret;
- struct app_info_data *ai;
u32 app_type;
char *ta_id, *exec_path;
ret = get_u32(mb, &app_type);
if (ret) {
print_err("failed to read target application type\n");
- return NULL;
+ return -EINVAL;
}
print_parse_debug("id:");
ret = get_string(mb, &ta_id);
if (ret) {
print_err("failed to read target application ID\n");
- return NULL;
+ return -EINVAL;
}
print_parse_debug("exec path:");
goto free_ta_id;
}
- ai = kmalloc(sizeof(*ai), GFP_KERNEL);
- if (ai == NULL) {
- print_err("out of memory\n");
- goto free_exec_path;
- }
-
switch (app_type) {
case AT_TIZEN_NATIVE_APP:
case AT_TIZEN_WEB_APP:
u32 tgid = 0;
if (*ta_id != '\0') {
- ret = str_to_u32(ta_id, &tgid);
+ ret = kstrtou32(ta_id, 10, &tgid);
if (ret) {
print_err("converting string to PID, "
"str='%s'\n", ta_id);
- goto free_ai;
+ goto free_exec_path;
}
}
default:
print_err("wrong application type(%u)\n", app_type);
ret = -EINVAL;
- goto free_ai;
+ goto free_exec_path;
}
- ai->app_type = (enum APP_TYPE)app_type;
- ai->app_id = ta_id;
- ai->exec_path = exec_path;
-
- return ai;
+ ai->type = (enum APP_TYPE)app_type;
+ ai->id = ta_id;
+ ai->path = exec_path;
-free_ai:
- kfree(ai);
+ return 0;
free_exec_path:
put_string(exec_path);
free_ta_id:
put_string(ta_id);
- return NULL;
-}
-
-/**
- * @brief app_info_data cleanup.
- *
- * @param ai Pointer to the target app_info_data.
- * @return Void.
- */
-void destroy_app_info(struct app_info_data *ai)
-{
- put_string(ai->exec_path);
- put_string(ai->app_id);
- kfree(ai);
+ return -EINVAL;
}
-
-
/* ============================================================================
* == CONFIG ==
* ============================================================================
*
* @param mb Pointer to the message buffer.
* @return Pointer to the filled conf_data struct on success;\n
- * 0 on error.
+ * NULL on error.
*/
struct conf_data *create_conf_data(struct msg_buf *mb)
{
* @brief Gets retprobe data and puts it to the probe_info struct.
*
* @param mb Pointer to the message buffer.
- * @param pi Pointer to the probe_info struct.
+ * @param pd Pointer to the probe_desc struct.
* @return 0 on success, error code on error.
*/
-int get_retprobe(struct msg_buf *mb, struct probe_info *pi)
+int get_retprobe(struct msg_buf *mb, struct probe_desc *pd)
{
char *args;
char ret_type;
goto free_args;
}
- pi->probe_type = SWAP_RETPROBE;
- pi->size = 0;
- pi->rp_i.args = args;
- pi->rp_i.ret_type = ret_type;
+ pd->type = SWAP_RETPROBE;
+ pd->info.rp_i.args = args;
+ pd->info.rp_i.ret_type = ret_type;
return 0;
* @brief Gets webprobe data and puts it to the probe_info struct.
*
* @param mb Pointer to the message buffer.
- * @param pi Pointer to the probe_info struct.
+ * @param pd Pointer to the probe_desc struct.
* @return 0 on success, error code on error.
*/
-int get_webprobe(struct msg_buf *mb, struct probe_info *pi)
+int get_webprobe(struct msg_buf *mb, struct probe_desc *pd)
{
- pi->probe_type = SWAP_WEBPROBE;
- pi->size = 0;
+ pd->type = SWAP_WEBPROBE;
return 0;
}
* @brief Gets preload data and puts it to the probe_info struct.
*
* @param mb Pointer to the message buffer.
- * @param pi Pointer to the probe_info struct.
+ * @param pd Pointer to the probe_desc struct.
* @return 0 on success, error code on error.
*/
-int get_preload_probe(struct msg_buf *mb, struct probe_info *pi)
+int get_preload_probe(struct msg_buf *mb, struct probe_desc *pd)
{
u64 handler;
u8 flags;
return -EINVAL;
}
- pi->probe_type = SWAP_PRELOAD_PROBE;
- pi->size = 0;
- pi->pl_i.handler = handler;
- pi->pl_i.flags = flags;
+ pd->type = SWAP_PRELOAD_PROBE;
+ pd->info.pl_i.handler = handler;
+ pd->info.pl_i.flags = flags;
return 0;
}
/**
* @brief Preload probe data cleanup.
*
- * @param pi Pointer to the probe_info comprising retprobe.
+ * @param pi Pointer to the probe_info struct.
* @return Void.
*/
void put_preload_probe(struct probe_info *pi)
* @brief Gets preload get_caller and puts it to the probe_info struct.
*
* @param mb Pointer to the message buffer.
- * @param pi Pointer to the probe_info struct.
+ * @param pd Pointer to the probe_desc struct.
* @return 0 on success, error code on error.
*/
-int get_get_caller_probe(struct msg_buf *mb, struct probe_info *pi)
+int get_get_caller_probe(struct msg_buf *mb, struct probe_desc *pd)
{
- pi->probe_type = SWAP_GET_CALLER;
- pi->size = 0;
+ pd->type = SWAP_GET_CALLER;
return 0;
}
/**
* @brief Preload get_caller probe data cleanup.
*
- * @param pi Pointer to the probe_info comprising retprobe.
+ * @param pi Pointer to the probe_info struct.
* @return Void.
*/
void put_get_caller_probe(struct probe_info *pi)
* @brief Gets preload get_call_type and puts it to the probe_info struct.
*
* @param mb Pointer to the message buffer.
- * @param pi Pointer to the probe_info struct.
+ * @param pd Pointer to the probe_desc struct.
* @return 0 on success, error code on error.
*/
-int get_get_call_type_probe(struct msg_buf *mb, struct probe_info *pi)
+int get_get_call_type_probe(struct msg_buf *mb, struct probe_desc *pd)
{
- pi->probe_type = SWAP_GET_CALL_TYPE;
- pi->size = 0;
+ pd->type = SWAP_GET_CALL_TYPE;
return 0;
}
/**
* @brief Preload get_call type probe data cleanup.
*
- * @param pi Pointer to the probe_info comprising retprobe.
+ * @param pi Pointer to the probe_info struct.
* @return Void.
*/
void put_get_call_type_probe(struct probe_info *pi)
* @param pi Pointer to the probe_info struct.
* @return 0 on success, error code on error.
*/
-int get_write_msg_probe(struct msg_buf *mb, struct probe_info *pi)
+int get_write_msg_probe(struct msg_buf *mb, struct probe_desc *pd)
{
- pi->probe_type = SWAP_WRITE_MSG;
- pi->size = 0;
+ pd->type = SWAP_WRITE_MSG;
return 0;
}
return -EINVAL;
}
-int get_fbi_probe(struct msg_buf *mb, struct probe_info *pi)
+int get_fbi_probe(struct msg_buf *mb, struct probe_desc *pd)
{
uint8_t var_count, i;
struct fbi_var_data *vars;
goto free_vars;
}
- pi->probe_type = SWAP_FBIPROBE;
- pi->fbi_i.var_count = var_count;
- pi->fbi_i.vars = vars;
- pi->size =0 ;
+ pd->type = SWAP_FBIPROBE;
+ pd->info.fbi_i.var_count = var_count;
+ pd->info.fbi_i.vars = vars;
return 0;
free_vars:
struct func_inst_data *create_func_inst_data(struct msg_buf *mb)
{
struct func_inst_data *fi;
+ struct probe_desc *pd;
u64 addr;
u8 type;
print_err("out of memory\n");
return NULL;
}
+ INIT_LIST_HEAD(&fi->list);
+ fi->registered = 0;
- fi->addr = addr;
+ pd = &fi->p_desc;
switch (type) {
case SWAP_RETPROBE:
- if (get_retprobe(mb, &(fi->probe_i)) != 0)
- goto free_func_inst;
+ if (get_retprobe(mb, pd) != 0)
+ goto err;
break;
case SWAP_WEBPROBE:
- if (get_webprobe(mb, &(fi->probe_i)) != 0)
- goto free_func_inst;
+ if (get_webprobe(mb, pd) != 0)
+ goto err;
break;
case SWAP_PRELOAD_PROBE:
- if (get_preload_probe(mb, &(fi->probe_i)) != 0)
- goto free_func_inst;
+ if (get_preload_probe(mb, pd) != 0)
+ goto err;
break;
case SWAP_GET_CALLER:
- if (get_get_caller_probe(mb, &(fi->probe_i)) != 0)
- goto free_func_inst;
+ if (get_get_caller_probe(mb, pd) != 0)
+ goto err;
break;
case SWAP_GET_CALL_TYPE:
- if (get_get_call_type_probe(mb, &(fi->probe_i)) != 0)
- goto free_func_inst;
+ if (get_get_call_type_probe(mb, pd) != 0)
+ goto err;
break;
case SWAP_FBIPROBE:
- if (get_fbi_probe(mb, &(fi->probe_i)) != 0)
- goto free_func_inst;
+ if (get_fbi_probe(mb, pd) != 0)
+ goto err;
break;
case SWAP_WRITE_MSG:
- if (get_write_msg_probe(mb, &(fi->probe_i)) != 0)
- goto free_func_inst;
+ if (get_write_msg_probe(mb, pd) != 0)
+ goto err;
break;
default:
printk(KERN_WARNING "SWAP PARSER: Wrong probe type %d!\n",
type);
- goto free_func_inst;
+ goto err;
}
+ fi->addr = addr;
return fi;
-
-free_func_inst:
+err:
kfree(fi);
return NULL;
*/
void destroy_func_inst_data(struct func_inst_data *fi)
{
- switch (fi->probe_i.probe_type) {
+ switch (fi->p_desc.type) {
case SWAP_RETPROBE:
- put_retprobe(&(fi->probe_i));
+ put_retprobe(&(fi->p_desc.info));
break;
case SWAP_WEBPROBE:
break;
case SWAP_PRELOAD_PROBE:
- put_preload_probe(&(fi->probe_i));
+ put_preload_probe(&(fi->p_desc.info));
break;
case SWAP_GET_CALLER:
- put_get_caller_probe(&(fi->probe_i));
+ put_get_caller_probe(&(fi->p_desc.info));
break;
case SWAP_GET_CALL_TYPE:
- put_get_call_type_probe(&(fi->probe_i));
+ put_get_call_type_probe(&(fi->p_desc.info));
break;
case SWAP_FBIPROBE:
- put_fbi_probe(&(fi->probe_i));
+ put_fbi_probe(&(fi->p_desc.info));
break;
case SWAP_WRITE_MSG:
- put_write_msg_probe(&(fi->probe_i));
+ put_write_msg_probe(&(fi->p_desc.info));
break;
default:
printk(KERN_WARNING "SWAP PARSER: Wrong probe type %d!\n",
- fi->probe_i.probe_type);
+ fi->p_desc.type);
}
kfree(fi);
}
+/**
+ * @brief func_inst_data find.
+ *
+ * @param head Pointer to the list head with func_inst_data.
+ * @param func Pointer to the func_inst_data looking for.
+ * @return Pointer to the found func_inst_data struct on success;\n
+ * NULL on error.
+ */
+struct func_inst_data *func_inst_data_find(struct list_head *head,
+ struct func_inst_data *func)
+{
+ struct func_inst_data *f;
+
+ list_for_each_entry(f, head, list) {
+ if (func->addr == f->addr)
+ return f;
+ }
+ return NULL;
+}
+
+/**
+ * @brief func_inst_data lists splice
+ *
+ * @param dst Pointer to the destination list head.
+ * @param src Pointer to the source list head.
+ * @return u32 count of spliced elements.
+ */
+u32 func_inst_data_splice(struct list_head *dst,
+ struct list_head *src)
+{
+ struct func_inst_data *f, *n, *s;
+ u32 cnt = 0;
+
+ list_for_each_entry_safe(f, n, src, list) {
+ s = func_inst_data_find(dst, f);
+ if (s) {
+ printk(KERN_WARNING "duplicate func probe\n");
+ continue;
+ }
+
+ list_del(&f->list);
+ list_add_tail(&f->list, dst);
+ cnt++;
+ }
+
+ return cnt;
+}
+
+/**
+ * @brief func_inst_data move from one list to another
+ *
+ * @param dst Pointer to the destination list head.
+ * @param src Pointer to the source list head.
+ * @return u32 Counter of moved elements.
+ */
+u32 func_inst_data_move(struct list_head *dst,
+ struct list_head *src)
+{
+ struct func_inst_data *f, *n, *s;
+ u32 cnt = 0;
+
+ list_for_each_entry_safe(f, n, src, list) {
+ s = func_inst_data_find(dst, f);
+ if (s) {
+ print_parse_debug("move func 0x%016llX\n", f->addr);
+ list_del(&f->list);
+ list_del(&s->list);
+ destroy_func_inst_data(s);
+ list_add_tail(&f->list, dst);
+ cnt++;
+ }
+ }
+
+ return cnt;
+}
struct lib_inst_data *create_lib_inst_data(struct msg_buf *mb)
{
struct lib_inst_data *li;
- struct func_inst_data *fi;
+ struct func_inst_data *fi, *fin;
char *path;
- u32 cnt, j, i = 0;
+ u32 cnt, i = 0;
print_parse_debug("bin path:");
if (get_string(mb, &path)) {
print_err("out of memory\n");
goto free_path;
}
+ INIT_LIST_HEAD(&li->list);
+ INIT_LIST_HEAD(&li->f_head);
if (cnt) {
- li->func = vmalloc(sizeof(*li->func) * cnt);
- if (li->func == NULL) {
- print_err("out of memory\n");
- goto free_li;
- }
-
for (i = 0; i < cnt; ++i) {
print_parse_debug("func #%d:\n", i + 1);
fi = create_func_inst_data(mb);
if (fi == NULL)
goto free_func;
-
- li->func[i] = fi;
+ list_add_tail(&fi->list, &li->f_head);
}
- } else {
- li->func = NULL;
}
li->path = path;
return li;
free_func:
- for (j = 0; j < i; ++j)
- destroy_func_inst_data(li->func[j]);
- vfree(li->func);
-
-free_li:
- kfree(li);
+ list_for_each_entry_safe(fi, fin, &li->f_head, list) {
+ list_del(&fi->list);
+ destroy_func_inst_data(fi);
+ }
free_path:
put_string(path);
*/
void destroy_lib_inst_data(struct lib_inst_data *li)
{
- int i;
+ struct func_inst_data *fi, *fin;
+
+ list_for_each_entry_safe(fi, fin, &li->f_head, list) {
+ list_del(&fi->list);
+ destroy_func_inst_data(fi);
+ }
put_string(li->path);
+ kfree(li);
+}
- for (i = 0; i < li->cnt_func; ++i)
- destroy_func_inst_data(li->func[i]);
+/**
+ * @brief lib_inst_data find.
+ *
+ * @param head Pointer to the list head with lib_inst_data.
+ * @param lib Pointer to the lib_inst_data looking for.
+ * @return Pointer to the found lib_inst_data struct on success;\n
+ * NULL on error.
+ */
+struct lib_inst_data *lib_inst_data_find(struct list_head *head,
+ struct lib_inst_data *lib)
+{
+ struct lib_inst_data *l;
- vfree(li->func);
- kfree(li);
+ list_for_each_entry(l, head, list) {
+ if (!strcmp(l->path, lib->path))
+ return l;
+ }
+
+ return NULL;
}
+/**
+ * @brief lib_inst_data lists splice
+ *
+ * @param dst Pointer to the destination list head.
+ * @param src Pointer to the source list head.
+ * @return u32 count of spliced elements.
+ */
+u32 lib_inst_data_splice(struct list_head *dst, struct list_head *src)
+{
+ struct lib_inst_data *l, *n, *s;
+ u32 cnt = 0;
+
+ list_for_each_entry_safe(l, n, src, list) {
+ s = lib_inst_data_find(dst, l);
+
+ if (s) {
+ print_parse_debug("update lib %s\n", s->path);
+ s->cnt_func += func_inst_data_splice(&s->f_head,
+ &l->f_head);
+
+ } else {
+ print_parse_debug("add new lib %s\n", s->path);
+ list_del(&l->list);
+ list_add_tail(&l->list, dst);
+ cnt++;
+ }
+ }
+
+ return cnt;
+}
+/**
+ * @brief lib_inst_data move from one list to another
+ *
+ * @param dst Pointer to the destination list head.
+ * @param src Pointer to the source list head.
+ * @return u32 Counter of moved elements.
+ */
+u32 lib_inst_data_move(struct list_head *dst, struct list_head *src)
+{
+ struct lib_inst_data *l, *n, *s;
+ u32 cnt = 0;
+
+ list_for_each_entry_safe(l, n, src, list) {
+ s = lib_inst_data_find(dst, l);
+
+ if (s) {
+ print_parse_debug("update lib %s\n", s->path);
+ l->cnt_func -= func_inst_data_move(&s->f_head,
+ &l->f_head);
+ if (list_empty(&l->f_head)) {
+ list_del(&l->list);
+ destroy_lib_inst_data(l);
+ cnt++;
+ }
+ }
+ }
+
+ return cnt;
+}
/* ============================================================================
struct app_inst_data *create_app_inst_data(struct msg_buf *mb)
{
struct app_inst_data *app_inst;
- struct app_info_data *app_info;
- struct func_inst_data *func;
- struct lib_inst_data *lib;
- u32 cnt_func, i_func = 0, cnt_lib, i_lib = 0, i;
+ struct func_inst_data *func, *func_n;
+ struct lib_inst_data *lib, *lib_n;
+ u32 cnt_func, i_func = 0, cnt_lib, i_lib = 0;
- app_info = create_app_info(mb);
- if (app_info == NULL)
+ app_inst = kmalloc(sizeof(*app_inst), GFP_KERNEL);
+ if (app_inst == NULL) {
+ print_err("out of memory\n");
return NULL;
+ }
+
+ INIT_LIST_HEAD(&app_inst->list);
+ INIT_LIST_HEAD(&app_inst->f_head);
+ INIT_LIST_HEAD(&app_inst->l_head);
+
+ if (create_app_info(mb, app_inst))
+ goto err;
- print_parse_debug("func count:");
if (get_u32(mb, &cnt_func)) {
print_err("failed to read count of functions\n");
- goto free_app_info;
+ goto err;
}
+ print_parse_debug("func count:%d", cnt_func);
if (remained_mb(mb) / MIN_SIZE_FUNC_INST < cnt_func) {
print_err("to match count of functions(%u)\n", cnt_func);
- goto free_app_info;
- }
-
- app_inst = kmalloc(sizeof(*app_inst), GFP_KERNEL);
- if (app_inst == NULL) {
- print_err("out of memory\n");
- goto free_app_info;
+ goto err;
}
if (cnt_func) {
- app_inst->func = vmalloc(sizeof(*app_inst->func) * cnt_func);
- if (app_inst->func == NULL) {
- print_err("out of memory\n");
- goto free_app_inst;
- }
-
for (i_func = 0; i_func < cnt_func; ++i_func) {
print_parse_debug("func #%d:\n", i_func + 1);
func = create_func_inst_data(mb);
if (func == NULL)
goto free_func;
-
- app_inst->func[i_func] = func;
+ list_add_tail(&func->list, &app_inst->f_head);
}
- } else {
- app_inst->func = NULL;
}
- print_parse_debug("lib count:");
if (get_u32(mb, &cnt_lib)) {
print_err("failed to read count of libraries\n");
goto free_func;
}
+ print_parse_debug("lib count:i%d", cnt_lib);
if (remained_mb(mb) / MIN_SIZE_LIB_INST < cnt_lib) {
print_err("to match count of libraries(%u)\n", cnt_lib);
}
if (cnt_lib) {
- app_inst->lib = vmalloc(sizeof(*app_inst->lib) * cnt_lib);
- if (app_inst->lib == NULL) {
- print_err("out of memory\n");
- goto free_func;
- }
-
for (i_lib = 0; i_lib < cnt_lib; ++i_lib) {
print_parse_debug("lib #%d:\n", i_lib + 1);
lib = create_lib_inst_data(mb);
if (lib == NULL)
goto free_lib;
- app_inst->lib[i_lib] = lib;
+ list_add_tail(&lib->list, &app_inst->l_head);
}
- } else {
- app_inst->lib = NULL;
}
- app_inst->app_info = app_info;
app_inst->cnt_func = cnt_func;
app_inst->cnt_lib = cnt_lib;
return app_inst;
free_lib:
- for (i = 0; i < i_lib; ++i)
- destroy_lib_inst_data(app_inst->lib[i]);
- vfree(app_inst->lib);
+ list_for_each_entry_safe(lib, lib_n, &app_inst->l_head, list) {
+ list_del(&lib->list);
+ destroy_lib_inst_data(lib);
+ }
free_func:
- for (i = 0; i < i_func; ++i)
- destroy_func_inst_data(app_inst->func[i]);
- vfree(app_inst->func);
+ list_for_each_entry_safe(func, func_n, &app_inst->f_head, list) {
+ list_del(&func->list);
+ destroy_func_inst_data(func);
+ }
-free_app_inst:
+err:
kfree(app_inst);
-free_app_info:
- destroy_app_info(app_info);
-
return NULL;
}
*/
void destroy_app_inst_data(struct app_inst_data *ai)
{
- int i;
+ struct func_inst_data *func, *func_n;
+ struct lib_inst_data *lib, *lib_n;
- for (i = 0; i < ai->cnt_lib; ++i)
- destroy_lib_inst_data(ai->lib[i]);
- vfree(ai->lib);
+ list_for_each_entry_safe(lib, lib_n, &ai->l_head, list) {
+ list_del(&lib->list);
+ destroy_lib_inst_data(lib);
+ }
- for (i = 0; i < ai->cnt_func; ++i)
- destroy_func_inst_data(ai->func[i]);
- vfree(ai->func);
+ list_for_each_entry_safe(func, func_n, &ai->f_head, list) {
+ list_del(&func->list);
+ destroy_func_inst_data(func);
+ }
+
+ put_string(ai->path);
+ put_string(ai->id);
- destroy_app_info(ai->app_info);
kfree(ai);
}
+/**
+ * @brief find app_inst_data.
+ *
+ * @param head Pointer to the list head with app_inst_data.
+ * @param ai Pointer to the target app_inst_data.
+ * @return Pointer to the target app_inst_data.
+ */
+struct app_inst_data *app_inst_data_find(struct list_head *head,
+ struct app_inst_data *ai)
+{
+ struct app_inst_data *p;
+
+ list_for_each_entry(p, head, list) {
+
+ print_parse_debug("app1: %d, %d, %s, %s\n",
+ p->type, p->tgid, p->id, p->path);
+
+ print_parse_debug("app2: %d, %d, %s, %s\n",
+ ai->type, ai->tgid, ai->id, ai->path);
+
+ if ((p->type == ai->type) &&
+ (p->tgid == ai->tgid) &&
+ !strcmp(p->id, ai->id) &&
+ !strcmp(p->path, ai->path)) {
+ return p;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief app_inst_data splice
+ *
+ * @param dst Pointer to the destination app_inst_data.
+ * @param src Pointer to the source app_inst_data..
+ * @return void.
+ */
+void app_inst_data_splice(struct app_inst_data *dst,
+ struct app_inst_data *src)
+{
+ print_parse_debug("find app, splice func and lib to %s\n",
+ dst->path);
+
+ dst->cnt_func += func_inst_data_splice(&dst->f_head, &src->f_head);
+ dst->cnt_lib += lib_inst_data_splice(&dst->l_head, &src->l_head);
+
+ return;
+}
+/**
+ * @brief app_inst_data move from one to another
+ *
+ * @param dst Pointer to the destination app_inst_data.
+ * @param src Pointer to the source app_inst_data.
+ * @return void.
+ */
+void app_inst_data_move(struct app_inst_data *dst,
+ struct app_inst_data *src)
+{
+ print_parse_debug("find app, delete func and lib from %s\n",
+ dst->path);
+ dst->cnt_func -= func_inst_data_move(&dst->f_head, &src->f_head);
+ dst->cnt_lib -= lib_inst_data_move(&dst->l_head, &src->l_head);
+ return;
+}
/* ============================================================================
* == US_INST ==
* @brief Creates and fills us_inst_data struct.
*
* @param mb Pointer to the message buffer.
- * @return Pointer to the filled us_inst_data struct on success;\n
- * 0 on error.
+ * @param head Pointer to the list head.
+ * @return u32 count of created elements.
*/
-struct us_inst_data *create_us_inst_data(struct msg_buf *mb)
+u32 create_us_inst_data(struct msg_buf *mb,
+ struct list_head *head)
{
- struct us_inst_data *ui;
- struct app_inst_data *ai;
- u32 cnt, j, i = 0;
+ struct app_inst_data *ai, *n;
+ u32 cnt, i = 0;
print_parse_debug("us_inst_data:\n");
print_parse_debug("app count:");
if (get_u32(mb, &cnt)) {
print_err("failed to read count of applications\n");
- return NULL;
+ return 0;
}
if (remained_mb(mb) / MIN_SIZE_APP_INST < cnt) {
print_err("to match count of applications(%u)\n", cnt);
- return NULL;
- }
-
- ui = kmalloc(sizeof(struct us_inst_data), GFP_KERNEL);
- if (ui == NULL) {
- print_err("out of memory\n");
- return NULL;
- }
-
- ui->app_inst = kmalloc(sizeof(struct app_inst_data *) * cnt,
- GFP_KERNEL);
- if (ui->app_inst == NULL) {
- print_err("out of memory\n");
- goto free_ui;
+ return 0;
}
for (i = 0; i < cnt; ++i) {
print_parse_debug("app #%d:\n", i + 1);
ai = create_app_inst_data(mb);
if (ai == NULL)
- goto free_app_inst;
+ goto err;
- ui->app_inst[i] = ai;
+ list_add_tail(&ai->list, head);
}
- ui->cnt = cnt;
+ return cnt;
- return ui;
-
-free_app_inst:
- for (j = 0; j < i; ++j)
- destroy_app_inst_data(ui->app_inst[j]);
- kfree(ui->app_inst);
-
-free_ui:
- kfree(ui);
+err:
+ list_for_each_entry_safe(ai, n, head, list) {
+ list_del(&ai->list);
+ destroy_app_inst_data(ai);
+ }
- return NULL;
+ return 0;
}
/**
* @brief us_inst_data cleanup.
*
- * @param ui Pointer to the target us_inst_data.
+ * @param head Pointer to the list head.
* @return Void.
*/
-void destroy_us_inst_data(struct us_inst_data *ui)
+void destroy_us_inst_data(struct list_head *head)
{
- int i;
-
- for (i = 0; i < ui->cnt; ++i)
- destroy_app_inst_data(ui->app_inst[i]);
-
- kfree(ui->app_inst);
- kfree(ui);
+ struct app_inst_data *ai, *n;
+ list_for_each_entry_safe(ai, n, head, list) {
+ list_del(&ai->list);
+ destroy_app_inst_data(ai);
+ }
}
* @brief Application and library functions to set probes.
*/
struct func_inst_data {
+ struct list_head list;
u64 addr; /**< Function address. */
- struct probe_info probe_i; /**< Probe info. */
+ struct probe_desc p_desc; /**< Probe info. */
+ int registered;
};
/**
* @brief Library struct.
*/
struct lib_inst_data {
+ struct list_head list;
char *path; /**< Library path. */
u32 cnt_func; /**< Function probes count in this library. */
- struct func_inst_data **func; /**< Pointer to the probes array. */
+ struct list_head f_head; /**< List head of func_inst_data */
};
/**
* @brief Application struct.
*/
struct app_inst_data {
- struct app_info_data *app_info; /**< Pointer to app_info struct. */
- u32 cnt_func; /**< Function probes count in app. */
- struct func_inst_data **func; /**< Pointer to the probes array. */
- u32 cnt_lib; /**< Libs count. */
- struct lib_inst_data **lib; /**< Pointer to the libs array. */
+ struct list_head list;
+ enum APP_TYPE type; /**< Application type. */
+ pid_t tgid; /**< Application PID. */
+ char *id; /**< Application ID */
+ char *path; /**< Application execution path. */
+ struct list_head f_head; /**< List head of func_inst_data */
+ struct list_head l_head; /**< List head of lib_inst_data */
+ u32 cnt_func; /**< Function probes count in app. */
+ u32 cnt_lib; /**< Libs count. */
};
-/**
- * @struct us_inst_data
- * @brief User space instrumentation struct.
- */
-struct us_inst_data {
- u32 cnt; /**< Apps count. */
- struct app_inst_data **app_inst; /**< Pointer to the apps array. */
-};
-
-
-struct app_info_data *create_app_info(struct msg_buf *mb);
-void destroy_app_info(struct app_info_data *app_info);
+int create_app_info(struct msg_buf *mb, struct app_inst_data *ai);
struct conf_data *create_conf_data(struct msg_buf *mb);
void destroy_conf_data(struct conf_data *conf);
struct app_inst_data *create_app_inst_data(struct msg_buf *mb);
void destroy_app_inst_data(struct app_inst_data *app_inst);
+struct app_inst_data *app_inst_data_find(struct list_head *head,
+ struct app_inst_data *ai);
+void app_inst_data_move(struct app_inst_data *dst,
+ struct app_inst_data *src);
+void app_inst_data_splice(struct app_inst_data *dst,
+ struct app_inst_data *src);
-struct us_inst_data *create_us_inst_data(struct msg_buf *mb);
-void destroy_us_inst_data(struct us_inst_data *us_inst);
+u32 create_us_inst_data(struct msg_buf *mb, struct list_head *head);
+void destroy_us_inst_data(struct list_head *head);
/* empty functions for calculating size fields in structures */
MIN_SIZE_APP_INFO = SIZE_APP_TYPE + MIN_SIZE_STRING + MIN_SIZE_STRING,
MIN_SIZE_APP_INST = MIN_SIZE_APP_INFO +
sizeof(make_app_inst_data().cnt_func) +
- sizeof(make_app_inst_data().cnt_lib),
- MIN_SIZE_US_INST = sizeof(make_us_inst_data().cnt)
+ sizeof(make_app_inst_data().cnt_lib)
};
#endif /* _MSG_PARSER_H */
static int mod_func_inst(struct func_inst_data *func, struct pf_group *pfg,
struct dentry *dentry, enum MOD_TYPE mt)
{
- int ret;
+ int ret = 0;
switch (mt) {
case MT_ADD:
- ret = pf_register_probe(pfg, dentry, func->addr,
- &func->probe_i);
+ if (func->registered == 0) {
+ ret = pf_register_probe(pfg, dentry, func->addr,
+ &func->p_desc);
+ if (!ret)
+ func->registered = 1;
+ }
break;
case MT_DEL:
- ret = pf_unregister_probe(pfg, dentry, func->addr);
+ if (func->registered == 1) {
+ ret = pf_unregister_probe(pfg, dentry, func->addr,
+ &func->p_desc);
+ if (!ret)
+ func->registered = 0;
+ }
break;
default:
printk(KERN_INFO "ERROR: mod_type=0x%x\n", mt);
static int mod_lib_inst(struct lib_inst_data *lib, struct pf_group *pfg,
enum MOD_TYPE mt)
{
- int ret = 0, i;
+ struct func_inst_data *func;
+ int ret = 0;
struct dentry *dentry;
dentry = dentry_by_path(lib->path);
return -EINVAL;
}
- for (i = 0; i < lib->cnt_func; ++i) {
- ret = mod_func_inst(lib->func[i], pfg, dentry, mt);
+ list_for_each_entry(func, &lib->f_head, list) {
+ ret = mod_func_inst(func, pfg, dentry, mt);
if (ret) {
printk(KERN_INFO "Cannot mod func inst, ret = %d\n",
ret);
return ret;
}
-static int get_pfg_by_app_info(struct app_info_data *app_info,
+static int get_pfg_by_app_info(struct app_inst_data *ai,
struct pf_group **pfg)
{
struct dentry *dentry;
- dentry = dentry_by_path(app_info->exec_path);
+ dentry = dentry_by_path(ai->path);
if (dentry == NULL)
return -EINVAL;
- switch (app_info->app_type) {
+ switch (ai->type) {
case AT_PID:
- if (app_info->tgid == 0) {
- if (app_info->exec_path[0] == '\0')
+ if (ai->tgid == 0) {
+ if (ai->path[0] == '\0')
*pfg = get_pf_group_dumb(dentry);
else
goto pf_dentry;
} else
- *pfg = get_pf_group_by_tgid(app_info->tgid, dentry);
+ *pfg = get_pf_group_by_tgid(ai->tgid, dentry);
break;
case AT_TIZEN_WEB_APP:
- *pfg = get_pf_group_by_comm(app_info->app_id, dentry);
+ *pfg = get_pf_group_by_comm(ai->id, dentry);
break;
case AT_TIZEN_NATIVE_APP:
case AT_COMMON_EXEC:
*pfg = get_pf_group_by_dentry(dentry, dentry);
break;
default:
- printk(KERN_INFO "ERROR: app_type=0x%x\n", app_info->app_type);
+ printk(KERN_INFO "ERROR: app_type=0x%x\n", ai->type);
return -EINVAL;
}
static int mod_us_app_inst(struct app_inst_data *app_inst, enum MOD_TYPE mt)
{
- int ret, i;
+ int ret;
struct pf_group *pfg;
struct dentry *dentry;
+ struct func_inst_data *func;
+ struct lib_inst_data *lib;
- ret = get_pfg_by_app_info(app_inst->app_info, &pfg);
+ ret = get_pfg_by_app_info(app_inst, &pfg);
if (ret) {
printk(KERN_INFO "Cannot get pfg by app info, ret = %d\n", ret);
return ret;
return ret;
}
- for (i = 0; i < app_inst->cnt_func; ++i) {
+ list_for_each_entry(func, &app_inst->f_head, list) {
/* TODO: */
- dentry = dentry_by_path(app_inst->app_info->exec_path);
+ dentry = dentry_by_path(app_inst->path);
if (dentry == NULL) {
printk(KERN_INFO "Cannot find dentry by path %s\n",
- app_inst->app_info->exec_path);
+ app_inst->path);
return -EINVAL;
}
- ret = mod_func_inst(app_inst->func[i], pfg, dentry, mt);
+ ret = mod_func_inst(func, pfg, dentry, mt);
if (ret) {
printk(KERN_INFO "Cannot mod func inst, ret = %d\n",
ret);
}
}
- for (i = 0; i < app_inst->cnt_lib; ++i) {
- ret = mod_lib_inst(app_inst->lib[i], pfg, mt);
+ list_for_each_entry(lib, &app_inst->l_head, list) {
+ ret = mod_lib_inst(lib, pfg, mt);
if (ret) {
printk(KERN_INFO "Cannot mod lib inst, ret = %d\n",
ret);
* @param mt Modificator, indicates whether we install or remove probes.
* @return 0 on suceess, error code on error.
*/
-int mod_us_inst(struct us_inst_data *us_inst, enum MOD_TYPE mt)
+int mod_us_inst(struct list_head *head, enum MOD_TYPE mt)
{
- u32 i;
int ret;
+ struct app_inst_data *ai;
- for (i = 0; i < us_inst->cnt; ++i) {
- ret = mod_us_app_inst(us_inst->app_inst[i], mt);
+ list_for_each_entry(ai, head, list) {
+ ret = mod_us_app_inst(ai, mt);
if (ret) {
printk(KERN_INFO "Cannot mod us app inst, ret = %d\n",
ret);
MT_DEL /**< Remove probes. */
};
-struct us_inst_data;
-
-int mod_us_inst(struct us_inst_data *us_inst, enum MOD_TYPE mt);
+int mod_us_inst(struct list_head *head, enum MOD_TYPE mt);
void pfg_put_all(void);
#endif /* _US_INST_H */
if (__is_instrumented(caller))
return INTERNAL_CALL;
- if (ip->info->pl_i.flags & SWAP_PRELOAD_ALWAYS_RUN)
+ if (ip->desc->info.pl_i.flags & SWAP_PRELOAD_ALWAYS_RUN)
return EXTERNAL_CALL;
return NOT_INSTRUMENTED;
struct pt_regs *regs,
unsigned long vaddr)
{
- ri->rp->up.kp.ss_addr[smp_processor_id()] = (kprobe_opcode_t *)vaddr;
+ ri->rp->up.ss_addr[smp_processor_id()] = (kprobe_opcode_t *)vaddr;
#ifdef CONFIG_ARM
if (thumb_mode(regs)) {
"sp(%08lx), lr(%08lx), pc(%08lx)\n",
current->comm, current->tgid, current->pid,
(int)preload_pd_get_state(__get_process_data(ri->rp)),
- prefix, (unsigned long)ri->rp->up.kp.addr,
+ prefix, (unsigned long)ri->rp->up.addr,
regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3,
regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7,
regs->ARM_sp, regs->ARM_lr, regs->ARM_pc);
"ip(%08lx), arg0(%08lx), arg1(%08lx), raddr(%08lx)\n",
current->comm, current->tgid, current->pid,
(int)preload_pd_get_state(__get_process_data(ri->rp)),
- prefix, (unsigned long)ri->rp->up.kp.addr,
+ prefix, (unsigned long)ri->rp->up.addr,
regs->EREG(ip), swap_get_arg(regs, 0), swap_get_arg(regs, 1),
swap_get_ret_addr(regs));
#endif /* CONFIG_ARM */
static inline bool __inverted(struct us_ip *ip)
{
- unsigned long flags = ip->info->pl_i.flags;
+ unsigned long flags = ip->desc->info.pl_i.flags;
if (flags & SWAP_PRELOAD_INVERTED_PROBE)
return true;
static inline bool __is_probe_non_block(struct us_ip *ip)
{
- if (ip->info->pl_i.flags & SWAP_PRELOAD_NON_BLOCK_PROBE)
+ if (ip->desc->info.pl_i.flags & SWAP_PRELOAD_NON_BLOCK_PROBE)
return true;
return false;
struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
struct us_priv *priv = (struct us_priv *)ri->data;
unsigned long flags = get_preload_flags(current);
- unsigned long offset = ip->info->pl_i.handler;
+ unsigned long offset = ip->desc->info.pl_i.handler;
unsigned long vaddr = 0;
unsigned long base;
char __user *path = NULL;
struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
struct us_priv *priv = (struct us_priv *)ri->data;
unsigned long flags = get_preload_flags(current);
- unsigned long offset = ip->info->pl_i.handler;
+ unsigned long offset = ip->desc->info.pl_i.handler;
unsigned long vaddr = 0;
switch (preload_pd_get_state(pd)) {
-static int get_caller_handler(struct kprobe *p, struct pt_regs *regs)
+static int get_caller_handler(struct uprobe *p, struct pt_regs *regs)
{
unsigned long caller;
int ret;
return 0;
}
-static int get_call_type_handler(struct kprobe *p, struct pt_regs *regs)
+static int get_call_type_handler(struct uprobe *p, struct pt_regs *regs)
{
unsigned char call_type;
int ret;
return 0;
}
-static int write_msg_handler(struct kprobe *p, struct pt_regs *regs)
+static int write_msg_handler(struct uprobe *p, struct pt_regs *regs)
{
char *user_buf;
char *buf;
{
struct uprobe *up = &ip->uprobe;
- up->kp.pre_handler = get_caller_handler;
+ up->pre_handler = get_caller_handler;
return 0;
}
{
struct uprobe *up = &ip->uprobe;
- up->kp.pre_handler = get_call_type_handler;
+ up->pre_handler = get_call_type_handler;
return 0;
}
{
struct uprobe *up = &ip->uprobe;
- up->kp.pre_handler = write_msg_handler;
+ up->pre_handler = write_msg_handler;
return 0;
}
{
preload_module_uprobe_exit(ip);
- preload_info_cleanup(ip->info);
+ preload_info_cleanup(&ip->desc->info);
}
static struct probe_iface preload_iface = {
{
preload_module_get_caller_exit(ip);
- get_caller_info_cleanup(ip->info);
+ get_caller_info_cleanup(&ip->desc->info);
}
static struct probe_iface get_caller_iface = {
{
preload_module_get_call_type_exit(ip);
- get_caller_info_cleanup(ip->info);
+ get_caller_info_cleanup(&ip->desc->info);
}
static struct probe_iface get_call_type_iface = {
{
preload_module_write_msg_exit(ip);
- get_caller_info_cleanup(ip->info);
+ get_caller_info_cleanup(&ip->desc->info);
}
static struct probe_iface write_msg_iface = {
if (rp && get_quiet() == QT_OFF) {
struct us_ip *ip = container_of(rp, struct us_ip, retprobe);
- const char *fmt = ip->info->rp_i.args;
+ const char *fmt = ip->desc->info.rp_i.args;
const unsigned long func_addr = (unsigned long)ip->orig_addr;
rp_msg_entry(regs, func_addr, fmt);
struct us_ip *ip = container_of(rp, struct us_ip, retprobe);
const unsigned long func_addr = (unsigned long)ip->orig_addr;
const unsigned long ret_addr = (unsigned long)ri->ret_addr;
- const char ret_type = ip->info->rp_i.ret_type;
+ const char ret_type = ip->desc->info.rp_i.ret_type;
rp_msg_exit(regs, func_addr, ret_type, ret_addr);
}
static void retprobe_uninit(struct us_ip *ip)
{
- retprobe_cleanup(ip->info);
+ retprobe_cleanup(&ip->desc->info);
}
flush_icache_range((unsigned long)(addr), \
(unsigned long)(addr) + (size))
-static inline long branch_t16_dest(kprobe_opcode_t insn, unsigned int insn_addr)
+static inline long branch_t16_dest(uprobe_opcode_t insn, unsigned int insn_addr)
{
long offset = insn & 0x3ff;
offset -= insn & 0x400;
return insn_addr + 4 + offset * 2;
}
-static inline long branch_cond_t16_dest(kprobe_opcode_t insn,
+static inline long branch_cond_t16_dest(uprobe_opcode_t insn,
unsigned int insn_addr)
{
long offset = insn & 0x7f;
return insn_addr + 4 + offset * 2;
}
-static inline long branch_t32_dest(kprobe_opcode_t insn, unsigned int insn_addr)
+static inline long branch_t32_dest(uprobe_opcode_t insn, unsigned int insn_addr)
{
unsigned int poff = insn & 0x3ff;
unsigned int offset = (insn & 0x07fe0000) >> 17;
return (insn_addr + 4 + (poff << 12) + offset * 4) & ~3;
}
-static inline long cbz_t16_dest(kprobe_opcode_t insn, unsigned int insn_addr)
+static inline long cbz_t16_dest(uprobe_opcode_t insn, unsigned int insn_addr)
{
unsigned int i = (insn & 0x200) >> 3;
unsigned int offset = (insn & 0xf8) >> 2;
}
/* is instruction Thumb2 and NOT a branch, etc... */
-static int is_thumb2(kprobe_opcode_t insn)
+static int is_thumb2(uprobe_opcode_t insn)
{
return ((insn & 0xf800) == 0xe800 ||
(insn & 0xf800) == 0xf000 ||
return ret;
}
-static int prep_pc_dep_insn_execbuf_thumb(kprobe_opcode_t *insns,
- kprobe_opcode_t insn, int uregs)
+static int prep_pc_dep_insn_execbuf_thumb(uprobe_opcode_t *insns,
+ uprobe_opcode_t insn, int uregs)
{
unsigned char mreg = 0;
unsigned char reg = 0;
* @return 0 on success,\n
* negative error code on error.
*/
-int arch_prepare_uprobe(struct uprobe *up)
+int arch_prepare_uprobe(struct uprobe *p)
{
int ret;
- struct kprobe *p = up2kp(up);
- struct task_struct *task = up->task;
+ struct task_struct *task = p->task;
unsigned long vaddr = (unsigned long)p->addr & ~((unsigned long)1);
unsigned long insn;
int thumb_mode = (unsigned long)p->addr & 1;
return ret;
}
- utramp = swap_slot_alloc(up->sm);
+ utramp = swap_slot_alloc(p->sm);
if (utramp == NULL) {
printk(KERN_INFO "Error: swap_slot_alloc failed (%08lx)\n",
vaddr);
return -ENOMEM;
}
- if (!write_proc_vm_atomic(up->task, (unsigned long)utramp, tramp,
+ if (!write_proc_vm_atomic(p->task, (unsigned long)utramp, tramp,
tramp_len)) {
pr_err("failed to write memory tramp=%p!\n", utramp);
- swap_slot_free(up->sm, utramp);
+ swap_slot_free(p->sm, utramp);
return -EINVAL;
}
void arch_opcode_analysis_uretprobe(struct uretprobe *rp)
{
/* Remove retprobe if first insn overwrites lr */
- rp->thumb_noret = !!(THUMB2_INSN_MATCH(BL, rp->up.kp.opcode) ||
- THUMB2_INSN_MATCH(BLX1, rp->up.kp.opcode) ||
- THUMB_INSN_MATCH(BLX2, rp->up.kp.opcode));
+ rp->thumb_noret = !!(THUMB2_INSN_MATCH(BL, rp->up.opcode) ||
+ THUMB2_INSN_MATCH(BLX1, rp->up.opcode) ||
+ THUMB_INSN_MATCH(BLX2, rp->up.opcode));
- rp->arm_noret = !!(ARM_INSN_MATCH(BL, rp->up.kp.opcode) ||
- ARM_INSN_MATCH(BLX1, rp->up.kp.opcode) ||
- ARM_INSN_MATCH(BLX2, rp->up.kp.opcode));
+ rp->arm_noret = !!(ARM_INSN_MATCH(BL, rp->up.opcode) ||
+ ARM_INSN_MATCH(BLX1, rp->up.opcode) ||
+ ARM_INSN_MATCH(BLX2, rp->up.opcode));
}
/**
*/
int arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs)
{
- ri->ret_addr = (kprobe_opcode_t *)regs->ARM_lr;
- ri->sp = (kprobe_opcode_t *)regs->ARM_sp;
+ ri->ret_addr = (uprobe_opcode_t *)regs->ARM_lr;
+ ri->sp = (uprobe_opcode_t *)regs->ARM_sp;
/* Set flag of current mode */
- ri->sp = (kprobe_opcode_t *)((long)ri->sp | !!thumb_mode(regs));
+ ri->sp = (uprobe_opcode_t *)((long)ri->sp | !!thumb_mode(regs));
if (ri->preload_thumb) {
- regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn) + 0x1b;
+ regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn) + 0x1b;
} else {
if (thumb_mode(regs))
- regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn) + 0x1b;
+ regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn) + 0x1b;
else
- regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn +
+ regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn +
UPROBES_TRAMP_RET_BREAK_IDX);
}
{
/* Understand function mode */
return ((unsigned long)ri->sp & 1) ?
- ((unsigned long)ri->rp->up.kp.ainsn.insn + 0x1b) :
- (unsigned long)(ri->rp->up.kp.ainsn.insn +
+ ((unsigned long)ri->rp->up.ainsn.insn + 0x1b) :
+ (unsigned long)(ri->rp->up.ainsn.insn +
UPROBES_TRAMP_RET_BREAK_IDX);
}
int i, retval;
if (tr == 0) {
- vaddr = (unsigned long)ri->rp->up.kp.addr;
+ vaddr = (unsigned long)ri->rp->up.addr;
tramp = (unsigned long *)arch_tramp_by_ri(ri);
} else {
/* ri - invalid */
/**
* @brief Jump pre-handler.
*
- * @param p Pointer to the kprobe.
+ * @param p Pointer to the uprobe.
* @param regs Pointer to CPU register data.
* @return 0.
*/
-int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs)
+int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs)
{
- struct uprobe *up = container_of(p, struct uprobe, kp);
- struct ujprobe *jp = container_of(up, struct ujprobe, up);
+ struct ujprobe *jp = container_of(p, struct ujprobe, up);
- kprobe_pre_entry_handler_t pre_entry =
- (kprobe_pre_entry_handler_t)jp->pre_entry;
+ uprobe_pre_entry_handler_t pre_entry =
+ (uprobe_pre_entry_handler_t)jp->pre_entry;
entry_point_t entry = (entry_point_t)jp->entry;
if (pre_entry) {
- p->ss_addr[smp_processor_id()] = (kprobe_opcode_t *)
+ p->ss_addr[smp_processor_id()] = (uprobe_opcode_t *)
pre_entry(jp->priv_arg, regs);
}
/**
* @brief Gets trampoline address.
*
- * @param p Pointer to the kprobe.
+ * @param p Pointer to the uprobe.
* @param regs Pointer to CPU register data.
* @return Trampoline address.
*/
-unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs)
+unsigned long arch_get_trampoline_addr(struct uprobe *p, struct pt_regs *regs)
{
return thumb_mode(regs) ?
(unsigned long)(p->ainsn.insn) + 0x1b :
*/
void arch_remove_uprobe(struct uprobe *up)
{
- swap_slot_free(up->sm, up->kp.ainsn.insn);
+ swap_slot_free(up->sm, up->ainsn.insn);
}
int arch_arm_uprobe(struct uprobe *p)
{
int ret;
- unsigned long vaddr = (unsigned long)p->kp.addr & ~((unsigned long)1);
- int thumb_mode = (unsigned long)p->kp.addr & 1;
+ unsigned long vaddr = (unsigned long)p->addr & ~((unsigned long)1);
+ int thumb_mode = (unsigned long)p->addr & 1;
int len = 4 >> thumb_mode; /* if thumb_mode then len = 2 */
unsigned long insn = thumb_mode ? UBP_THUMB : UBP_ARM;
return 0;
}
-void arch_disarm_uprobe(struct kprobe *p, struct task_struct *task)
+void arch_disarm_uprobe(struct uprobe *p, struct task_struct *task)
{
int ret;
static int urp_handler(struct pt_regs *regs, pid_t tgid)
{
- struct kprobe *p;
+ struct uprobe *p;
unsigned long vaddr = regs->ARM_pc;
unsigned long offset_bp = thumb_mode(regs) ?
0x1a :
4 * UPROBES_TRAMP_RET_BREAK_IDX;
unsigned long tramp_addr = vaddr - offset_bp;
- p = get_ukprobe_by_insn_slot((void *)tramp_addr, tgid, regs);
+ p = get_uprobe_by_insn_slot((void *)tramp_addr, tgid, regs);
if (p == NULL) {
printk(KERN_INFO
"no_uprobe: Not one of ours: let kernel handle it %lx\n",
return 0;
}
+/**
+ * @brief Prepares singlestep for current CPU.
+ *
+ * @param p Pointer to kprobe.
+ * @param regs Pointer to CPU registers data.
+ * @return Void.
+ */
+static void arch_prepare_singlestep(struct uprobe *p, struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+
+ if (p->ss_addr[cpu]) {
+ regs->ARM_pc = (unsigned long)p->ss_addr[cpu];
+ p->ss_addr[cpu] = NULL;
+ } else {
+ regs->ARM_pc = (unsigned long)p->ainsn.insn;
+ }
+}
/**
* @brief Breakpoint instruction handler.
int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
{
int ret = 0;
- struct kprobe *p;
+ struct uprobe *p;
unsigned long flags;
unsigned long vaddr = regs->ARM_pc | !!thumb_mode(regs);
pid_t tgid = current->tgid;
local_irq_save(flags);
preempt_disable();
- p = get_ukprobe((kprobe_opcode_t *)vaddr, tgid);
+ p = get_uprobe((uprobe_opcode_t *)vaddr, tgid);
if (p) {
- struct uprobe *up = kp2up(p);
bool prepare = false;
- if (up->atomic_ctx) {
+ if (p->atomic_ctx) {
if (!p->pre_handler || !p->pre_handler(p, regs))
prepare = true;
} else {
}
if (prepare)
- prepare_singlestep(p, regs);
+ arch_prepare_singlestep(p, regs);
} else {
ret = urp_handler(regs, tgid);
/* check ARM/THUMB mode on correct */
if (ret) {
vaddr ^= 1;
- p = get_ukprobe((kprobe_opcode_t *)vaddr, tgid);
+ p = get_uprobe((uprobe_opcode_t *)vaddr, tgid);
if (p) {
pr_err("invalid mode: thumb=%d addr=%p insn=%08lx\n",
!!thumb_mode(regs), p->addr, p->opcode);
#include <swap-asm/swap_kprobes.h> /* FIXME: for UPROBES_TRAMP_LEN */
-struct kprobe;
struct task_struct;
struct uprobe;
struct uretprobe;
struct uretprobe_instance;
+typedef unsigned long uprobe_opcode_t;
+
+/**
+ * @struct arch_insn
+ * @brief Architecture depend copy of original instruction.
+ * @var arch_insn::insn
+ * Copy of the original instruction.
+ */
+struct arch_insn {
+ uprobe_opcode_t *insn;
+};
+
/**
- * @struct arch_specific_tramp
+ * @struct arch_tramp
* @brief Stores arch-dependent trampolines.
*/
-struct arch_specific_tramp {
+struct arch_tramp {
+ unsigned long tramp_arm[UPROBES_TRAMP_LEN]; /**< ARM trampoline */
+ unsigned long tramp_thumb[UPROBES_TRAMP_LEN]; /**< Thumb trampoline */
+ void *utramp; /**< Pointer to trampoline */
};
int arch_prepare_uprobe(struct uprobe *up);
-int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs);
-static inline int longjmp_break_uhandler(struct kprobe *p, struct pt_regs *regs)
+int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs);
+static inline int longjmp_break_uhandler(struct uprobe *p, struct pt_regs *regs)
{
return 0;
}
struct task_struct *task, unsigned long tr);
unsigned long arch_tramp_by_ri(struct uretprobe_instance *ri);
-unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs);
+unsigned long arch_get_trampoline_addr(struct uprobe *p, struct pt_regs *regs);
void arch_set_orig_ret_addr(unsigned long orig_ret_addr, struct pt_regs *regs);
void arch_remove_uprobe(struct uprobe *up);
int arch_arm_uprobe(struct uprobe *p);
-void arch_disarm_uprobe(struct kprobe *p, struct task_struct *task);
+void arch_disarm_uprobe(struct uprobe *p, struct task_struct *task);
static inline unsigned long swap_get_uarg(struct pt_regs *regs, unsigned long n)
{
*/
struct uprobe_ctlblk {
unsigned long flags; /**< Flags */
- struct kprobe *p; /**< Pointer to the uprobe's kprobe */
+ struct uprobe *p; /**< Pointer to the uprobe */
};
static unsigned long trampoline_addr(struct uprobe *up)
{
- return (unsigned long)(up->kp.ainsn.insn +
+ return (unsigned long)(up->ainsn.insn +
UPROBES_TRAMP_RET_BREAK_IDX);
}
return (struct uprobe_ctlblk *)(end_of_stack(current) + 20);
}
-static struct kprobe *get_current_probe(void)
+static struct uprobe *get_current_probe(void)
{
return current_ucb()->p;
}
-static void set_current_probe(struct kprobe *p)
+static void set_current_probe(struct uprobe *p)
{
current_ucb()->p = p;
}
* @return 0 on success,\n
* -1 on error.
*/
-int arch_prepare_uprobe(struct uprobe *up)
+int arch_prepare_uprobe(struct uprobe *p)
{
- struct kprobe *p = up2kp(up);
- struct task_struct *task = up->task;
- u8 *tramp = up->atramp.tramp;
+ struct task_struct *task = p->task;
+ u8 *tramp = p->atramp.tramp;
enum { call_relative_opcode = 0xe8 };
if (!read_proc_vm_atomic(task, (unsigned long)p->addr,
p->ainsn.boostable = swap_can_boost(tramp) ? 0 : -1;
- p->ainsn.insn = swap_slot_alloc(up->sm);
+ p->ainsn.insn = swap_slot_alloc(p->sm);
if (p->ainsn.insn == NULL) {
printk(KERN_ERR "trampoline out of memory\n");
return -ENOMEM;
}
if (!write_proc_vm_atomic(task, (unsigned long)p->ainsn.insn,
- tramp, sizeof(up->atramp.tramp))) {
- swap_slot_free(up->sm, p->ainsn.insn);
+ tramp, sizeof(p->atramp.tramp))) {
+ swap_slot_free(p->sm, p->ainsn.insn);
printk(KERN_INFO "failed to write memory %p!\n", tramp);
return -EINVAL;
}
/**
* @brief Jump pre-handler.
*
- * @param p Pointer to the uprobe's kprobe.
+ * @param p Pointer to the uprobe.
* @param regs Pointer to CPU register data.
* @return 0.
*/
-int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs)
+int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs)
{
- struct uprobe *up = container_of(p, struct uprobe, kp);
- struct ujprobe *jp = container_of(up, struct ujprobe, up);
- kprobe_pre_entry_handler_t pre_entry =
- (kprobe_pre_entry_handler_t)jp->pre_entry;
+ struct ujprobe *jp = container_of(p, struct ujprobe, up);
+ uprobe_pre_entry_handler_t pre_entry =
+ (uprobe_pre_entry_handler_t)jp->pre_entry;
entry_point_t entry = (entry_point_t)jp->entry;
unsigned long args[6];
regs->sp + 4);
if (pre_entry)
- p->ss_addr[smp_processor_id()] = (kprobe_opcode_t *)
+ p->ss_addr[smp_processor_id()] = (uprobe_opcode_t *)
pre_entry(jp->priv_arg, regs);
if (entry)
if (get_user(ret_addr, (unsigned long *)regs->sp)) {
pr_err("failed to read user space func ra %lx addr=%p!\n",
- regs->sp, ri->rp->up.kp.addr);
+ regs->sp, ri->rp->up.addr);
return -EINVAL;
}
return -EINVAL;
}
- ri->ret_addr = (kprobe_opcode_t *)ret_addr;
+ ri->ret_addr = (uprobe_opcode_t *)ret_addr;
return 0;
}
/**
* @brief Gets trampoline address.
*
- * @param p Pointer to the uprobe's kprobe.
+ * @param p Pointer to the uprobe.
* @param regs Pointer to CPU register data.
* @return Trampoline address.
*/
-unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs)
+unsigned long arch_get_trampoline_addr(struct uprobe *p, struct pt_regs *regs)
{
- return trampoline_addr(kp2up(p));
+ return trampoline_addr(p);
}
/**
* @param up Pointer to the target uprobe.
* @return Void.
*/
-void arch_remove_uprobe(struct uprobe *up)
+void arch_remove_uprobe(struct uprobe *p)
{
- struct kprobe *p = up2kp(up);
-
- swap_slot_free(up->sm, p->ainsn.insn);
+ swap_slot_free(p->sm, p->ainsn.insn);
}
int arch_arm_uprobe(struct uprobe *p)
{
int ret;
- kprobe_opcode_t insn = BREAKPOINT_INSTRUCTION;
- unsigned long vaddr = (unsigned long)p->kp.addr;
+ uprobe_opcode_t insn = BREAKPOINT_INSTRUCTION;
+ unsigned long vaddr = (unsigned long)p->addr;
ret = write_proc_vm_atomic(p->task, vaddr, &insn, sizeof(insn));
if (!ret) {
return 0;
}
-void arch_disarm_uprobe(struct kprobe *p, struct task_struct *task)
+void arch_disarm_uprobe(struct uprobe *p, struct task_struct *task)
{
int ret;
unsigned long vaddr = (unsigned long)p->addr;
pr_err("failed to write jump opcode to user space %p\n", from);
}
-static void resume_execution(struct kprobe *p,
+static void resume_execution(struct uprobe *p,
struct pt_regs *regs,
unsigned long flags)
{
unsigned long *tos, tos_dword = 0;
unsigned long copy_eip = (unsigned long)p->ainsn.insn;
unsigned long orig_eip = (unsigned long)p->addr;
- kprobe_opcode_t insns[2];
+ uprobe_opcode_t insns[2];
regs->EREG(flags) &= ~TF_MASK;
return;
}
-static bool prepare_ss_addr(struct kprobe *p, struct pt_regs *regs)
+static bool prepare_ss_addr(struct uprobe *p, struct pt_regs *regs)
{
unsigned long *ss_addr = (long *)&p->ss_addr[smp_processor_id()];
static int uprobe_handler(struct pt_regs *regs)
{
- struct kprobe *p;
- kprobe_opcode_t *addr;
+ struct uprobe *p;
+ uprobe_opcode_t *addr;
struct task_struct *task = current;
pid_t tgid = task->tgid;
save_current_flags(regs);
- addr = (kprobe_opcode_t *)(regs->EREG(ip) - sizeof(kprobe_opcode_t));
- p = get_ukprobe(addr, tgid);
+ addr = (uprobe_opcode_t *)(regs->EREG(ip) - sizeof(uprobe_opcode_t));
+ p = get_uprobe(addr, tgid);
if (p == NULL) {
void *tramp_addr = (void *)addr - UPROBES_TRAMP_RET_BREAK_IDX;
- p = get_ukprobe_by_insn_slot(tramp_addr, tgid, regs);
+ p = get_uprobe_by_insn_slot(tramp_addr, tgid, regs);
if (p == NULL) {
printk(KERN_INFO "no_uprobe\n");
return 0;
static int post_uprobe_handler(struct pt_regs *regs)
{
- struct kprobe *p = get_current_probe();
+ struct uprobe *p = get_current_probe();
unsigned long flags = current_ucb()->flags;
if (p == NULL) {
struct uretprobe;
struct uretprobe_instance;
+typedef u8 uprobe_opcode_t;
+
+/**
+ * @struct arch_insn
+ * @brief Architecture depend copy of original instruction.
+ * @var arch_insn::insn
+ * Copy of the original instruction.
+ * @var arch_insn::boostable
+ * If this flag is not 0, this kprobe can be boost when its
+ * post_handler and break_handler is not set.
+ */
+struct arch_insn {
+ uprobe_opcode_t *insn;
+ int boostable;
+};
+
/**
- * @struct arch_specific_tramp
+ * @struct arch_tramp
* @brief Stores x86 trampoline
*/
-struct arch_specific_tramp {
+struct arch_tramp {
u8 tramp[UPROBES_TRAMP_LEN + BP_INSN_SIZE]; /**< BP for uretprobe */
};
}
int arch_prepare_uprobe(struct uprobe *up);
-int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs);
-static inline int longjmp_break_uhandler(struct kprobe *p, struct pt_regs *regs)
+int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs);
+static inline int longjmp_break_uhandler(struct uprobe *p, struct pt_regs *regs)
{
return 0;
}
int arch_disarm_urp_inst(struct uretprobe_instance *ri,
struct task_struct *task, unsigned long tr);
unsigned long arch_tramp_by_ri(struct uretprobe_instance *ri);
-unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs);
+unsigned long arch_get_trampoline_addr(struct uprobe *p, struct pt_regs *regs);
void arch_set_orig_ret_addr(unsigned long orig_ret_addr, struct pt_regs *regs);
void arch_remove_uprobe(struct uprobe *up);
int arch_arm_uprobe(struct uprobe *p);
-void arch_disarm_uprobe(struct kprobe *p, struct task_struct *task);
+void arch_disarm_uprobe(struct uprobe *p, struct task_struct *task);
static inline unsigned long swap_get_uarg(struct pt_regs *regs, unsigned long n)
{
{
int i;
struct hlist_head *head;
- struct kprobe *p;
+ struct uprobe *p;
DECLARE_NODE_PTR_FOR_HLIST(node);
/* print uprobe table */
for (i = 0; i < UPROBE_TABLE_SIZE; ++i) {
head = &uprobe_insn_slot_table[i];
- swap_hlist_for_each_entry_rcu(p, node, head, is_hlist_arm) {
- printk(KERN_INFO "####### find U tgid=%u, addr=%x\n",
- p->tgid, p->addr);
+ swap_hlist_for_each_entry_rcu(p, node, head, is_hlist) {
+ printk(KERN_INFO "####### find U tgid=%u, addr=0x%lx\n",
+ p->task->tgid, (unsigned long)p->addr);
}
}
}
/*
* Keep all fields in the uprobe consistent
*/
-static inline void copy_uprobe(struct kprobe *old_p, struct kprobe *p)
+static inline void copy_uprobe(struct uprobe *old_p, struct uprobe *p)
{
- memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t));
- memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn));
+ memcpy(&p->opcode, &old_p->opcode, sizeof(uprobe_opcode_t));
+ memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_insn));
}
/*
* Aggregate handlers for multiple uprobes support - these handlers
* take care of invoking the individual uprobe handlers on p->list
*/
-static int aggr_pre_uhandler(struct kprobe *p, struct pt_regs *regs)
+static int aggr_pre_uhandler(struct uprobe *p, struct pt_regs *regs)
{
- struct kprobe *kp;
+ struct uprobe *up;
int ret;
- list_for_each_entry_rcu(kp, &p->list, list) {
- if (kp->pre_handler) {
- ret = kp->pre_handler(kp, regs);
+ list_for_each_entry_rcu(up, &p->list, list) {
+ if (up->pre_handler) {
+ ret = up->pre_handler(up, regs);
if (ret)
return ret;
}
return 0;
}
-static void aggr_post_uhandler(struct kprobe *p, struct pt_regs *regs,
+static void aggr_post_uhandler(struct uprobe *p, struct pt_regs *regs,
unsigned long flags)
{
- struct kprobe *kp;
+ struct uprobe *up;
- list_for_each_entry_rcu(kp, &p->list, list) {
- if (kp->post_handler)
- kp->post_handler(kp, regs, flags);
+ list_for_each_entry_rcu(up, &p->list, list) {
+ if (up->post_handler)
+ up->post_handler(up, regs, flags);
}
}
-static int aggr_fault_uhandler(struct kprobe *p,
+static int aggr_fault_uhandler(struct uprobe *p,
struct pt_regs *regs,
int trapnr)
{
return 0;
}
-static int aggr_break_uhandler(struct kprobe *p, struct pt_regs *regs)
+static int aggr_break_uhandler(struct uprobe *p, struct pt_regs *regs)
{
return 0;
}
* Add the new probe to old_p->list. Fail if this is the
* second ujprobe at the address - two ujprobes can't coexist
*/
-static int add_new_uprobe(struct kprobe *old_p, struct kprobe *p)
+static int add_new_uprobe(struct uprobe *old_p, struct uprobe *p)
{
if (p->break_handler) {
if (old_p->break_handler)
* Fill in the required fields of the "manager uprobe". Replace the
* earlier uprobe in the hlist with the manager uprobe
*/
-static inline void add_aggr_uprobe(struct kprobe *ap, struct kprobe *p)
+static inline void add_aggr_uprobe(struct uprobe *ap, struct uprobe *p)
{
copy_uprobe(p, ap);
* This is the second or subsequent uprobe at the address - handle
* the intricacies
*/
-static int register_aggr_uprobe(struct kprobe *old_p, struct kprobe *p)
+static int register_aggr_uprobe(struct uprobe *old_p, struct uprobe *p)
{
int ret = 0;
- struct kprobe *ap;
if (old_p->pre_handler == aggr_pre_uhandler) {
copy_uprobe(old_p, p);
if (!uap)
return -ENOMEM;
- uap->task = kp2up(p)->task;
- ap = up2kp(uap);
- add_aggr_uprobe(ap, old_p);
- copy_uprobe(ap, p);
- ret = add_new_uprobe(ap, p);
+ uap->task = p->task;
+ add_aggr_uprobe(uap, old_p);
+ copy_uprobe(uap, p);
+ ret = add_new_uprobe(uap, p);
}
return ret;
/**
* @brief Disarms uprobe.
*
- * @param p Pointer to the uprobe's kprobe.
+ * @param p Pointer to the uprobe.
* @param task Pointer to the target task.
* @return Void.
*/
-void disarm_uprobe(struct kprobe *p, struct task_struct *task)
+void disarm_uprobe(struct uprobe *p, struct task_struct *task)
{
arch_disarm_uprobe(p, task);
}
}
/**
- * @brief Gets uprobe's kprobe.
+ * @brief Gets uprobe.
*
* @param addr Probe's address.
* @param tgid Probes's thread group ID.
- * @return Pointer to the kprobe on success,\n
+ * @return Pointer to the uprobe on success,\n
* NULL otherwise.
*/
-struct kprobe *get_ukprobe(void *addr, pid_t tgid)
+struct uprobe *get_uprobe(void *addr, pid_t tgid)
{
struct hlist_head *head;
- struct kprobe *p;
+ struct uprobe *p;
DECLARE_NODE_PTR_FOR_HLIST(node);
head = &uprobe_table[hash_ptr(addr, UPROBE_HASH_BITS)];
swap_hlist_for_each_entry_rcu(p, node, head, hlist) {
- if (p->addr == addr && kp2up(p)->task->tgid == tgid)
+ if (p->addr == addr && p->task->tgid == tgid)
return p;
}
/**
* @brief Adds uprobe to hlist when trampoline have been made.
*
- * @param p Pointer to the uprobe's kprobe.
+ * @param p Pointer to the uprobe.
* @return Void.
*/
-void add_uprobe_table(struct kprobe *p)
+void add_uprobe_table(struct uprobe *p)
{
write_lock(&st_lock);
hlist_add_head(&p->is_hlist,
write_unlock(&st_lock);
}
-static void del_uprobe_table(struct kprobe *p)
+static void del_uprobe_table(struct uprobe *p)
{
write_lock(&st_lock);
if (!hlist_unhashed(&p->is_hlist))
}
/**
- * @brief Gets kprobe by insn slot.
+ * @brief Gets uprobe by insn slot.
*
* @param addr Probe's address.
* @param tgit Probe's thread group ID.
* @param regs Pointer to CPU registers data.
- * @return Pointer to the kprobe on success,\n
+ * @return Pointer to the uprobe on success,\n
* NULL otherwise.
*/
-struct kprobe *get_ukprobe_by_insn_slot(void *addr,
- pid_t tgid,
- struct pt_regs *regs)
+struct uprobe *get_uprobe_by_insn_slot(void *addr,
+ pid_t tgid,
+ struct pt_regs *regs)
{
struct hlist_head *head;
- struct kprobe *p;
+ struct uprobe *p;
DECLARE_NODE_PTR_FOR_HLIST(node);
read_lock(&st_lock);
head = &slot_table[hash_ptr(addr, UPROBE_HASH_BITS)];
swap_hlist_for_each_entry(p, node, head, is_hlist) {
- if (p->ainsn.insn == addr && kp2up(p)->task->tgid == tgid) {
+ if (p->ainsn.insn == addr && p->task->tgid == tgid) {
read_unlock(&st_lock);
return p;
}
static void remove_uprobe(struct uprobe *up)
{
- del_uprobe_table(&up->kp);
+ del_uprobe_table(up);
arch_remove_uprobe(up);
}
* @return 0 on success,\n
* negative error code on error.
*/
-int swap_register_uprobe(struct uprobe *up)
+int swap_register_uprobe(struct uprobe *p)
{
int ret = 0;
- struct kprobe *p, *old_p;
+ struct uprobe *old_p;
- p = &up->kp;
if (!p->addr)
return -EINVAL;
p->ainsn.insn = NULL;
- p->mod_refcounted = 0;
- p->nmissed = 0;
INIT_LIST_HEAD(&p->list);
#ifdef KPROBES_PROFILE
p->start_tm.tv_sec = p->start_tm.tv_usec = 0;
#endif
/* get the first item */
- old_p = get_ukprobe(p->addr, kp2up(p)->task->tgid);
+ old_p = get_uprobe(p->addr, p->task->tgid);
if (old_p) {
- struct task_struct *task = up->task;
+ struct task_struct *task = p->task;
/* TODO: add support many uprobes on address */
printk(KERN_INFO "uprobe on task[%u %u %s] vaddr=%p is there\n",
INIT_HLIST_NODE(&p->is_hlist);
- ret = arch_prepare_uprobe(up);
+ ret = arch_prepare_uprobe(p);
if (ret) {
DBPRINTF("goto out\n", ret);
goto out;
hlist_add_head_rcu(&p->hlist,
&uprobe_table[hash_ptr(p->addr, UPROBE_HASH_BITS)]);
- ret = arm_uprobe(up);
+ ret = arm_uprobe(p);
if (ret) {
hlist_del_rcu(&p->hlist);
synchronize_rcu();
- remove_uprobe(up);
+ remove_uprobe(p);
}
out:
* @param disarm Disarm flag. When true uprobe is disarmed.
* @return Void.
*/
-void __swap_unregister_uprobe(struct uprobe *up, int disarm)
+void __swap_unregister_uprobe(struct uprobe *p, int disarm)
{
- struct kprobe *p, *old_p, *list_p;
+ struct uprobe *old_p, *list_p;
int cleanup_p;
- p = &up->kp;
- old_p = get_ukprobe(p->addr, kp2up(p)->task->tgid);
+ /* we MUST check probe for uncreated process */
+ if (!p->task)
+ return;
+
+ old_p = get_uprobe(p->addr, p->task->tgid);
if (unlikely(!old_p))
return;
(p->list.next == &old_p->list) && (p->list.prev == &old_p->list))) {
/* Only probe on the hash list */
if (disarm)
- disarm_uprobe(&up->kp, up->task);
+ disarm_uprobe(p, p->task);
hlist_del_rcu(&old_p->hlist);
cleanup_p = 1;
if (!in_atomic())
synchronize_sched();
- remove_uprobe(up);
+ remove_uprobe(p);
} else {
if (p->break_handler)
old_p->break_handler = NULL;
int ret = 0;
/* Todo: Verify probepoint is a function entry point */
- jp->up.kp.pre_handler = setjmp_upre_handler;
- jp->up.kp.break_handler = longjmp_break_uhandler;
+ jp->up.pre_handler = setjmp_upre_handler;
+ jp->up.break_handler = longjmp_break_uhandler;
ret = swap_register_uprobe(&jp->up);
/**
* @brief Trampoline uprobe handler.
*
- * @param p Pointer to the uprobe's kprobe.
+ * @param p Pointer to the uprobe.
* @param regs Pointer to CPU register data.
* @return 1
*/
-int trampoline_uprobe_handler(struct kprobe *p, struct pt_regs *regs)
+int trampoline_uprobe_handler(struct uprobe *p, struct pt_regs *regs)
{
struct uretprobe_instance *ri = NULL;
- struct kprobe *kp;
+ struct uprobe *up;
struct hlist_head *head;
unsigned long flags, tramp_addr, orig_ret_addr = 0;
struct hlist_node *tmp;
continue;
}
- kp = NULL;
+ up = NULL;
if (ri->rp) {
- kp = up2kp(&ri->rp->up);
+ up = &ri->rp->up;
if (ri->rp->handler)
ri->rp->handler(ri, regs);
orig_ret_addr = (unsigned long)ri->ret_addr;
recycle_urp_inst(ri);
- if ((orig_ret_addr != tramp_addr && kp == p) || kp == NULL) {
+ if ((orig_ret_addr != tramp_addr && up == p) || up == NULL) {
/*
* This is the real return address. Any other
* instances associated with this task are for
return 1;
}
-static int pre_handler_uretprobe(struct kprobe *p, struct pt_regs *regs)
+static int pre_handler_uretprobe(struct uprobe *p, struct pt_regs *regs)
{
- struct uprobe *up = container_of(p, struct uprobe, kp);
- struct uretprobe *rp = container_of(up, struct uretprobe, up);
+ struct uretprobe *rp = container_of(p, struct uretprobe, up);
#ifdef CONFIG_ARM
int noret = thumb_mode(regs) ? rp->thumb_noret : rp->arm_noret;
#endif
DBPRINTF("START\n");
- rp->up.kp.pre_handler = pre_handler_uretprobe;
- rp->up.kp.post_handler = NULL;
- rp->up.kp.fault_handler = NULL;
- rp->up.kp.break_handler = NULL;
+ rp->up.pre_handler = pre_handler_uretprobe;
+ rp->up.post_handler = NULL;
+ rp->up.fault_handler = NULL;
+ rp->up.break_handler = NULL;
/* Pre-allocate memory for max kretprobe instances */
if (rp->maxactive <= 0) {
printk(KERN_INFO "%s (%d/%d): "
"cannot disarm urp instance (%08lx)\n",
ri->task->comm, ri->task->tgid, ri->task->pid,
- (unsigned long)rp->up.kp.addr);
+ (unsigned long)rp->up.addr);
if (is_current)
spin_lock_irqsave(&uretprobe_lock, flags);
void swap_unregister_all_uprobes(struct task_struct *task)
{
struct hlist_head *head;
- struct kprobe *p;
+ struct uprobe *p;
int i;
struct hlist_node *tnode;
DECLARE_NODE_PTR_FOR_HLIST(node);
for (i = 0; i < UPROBE_TABLE_SIZE; ++i) {
head = &uprobe_table[i];
swap_hlist_for_each_entry_safe(p, node, tnode, head, hlist) {
- if (kp2up(p)->task->tgid == task->tgid) {
- struct uprobe *up =
- container_of(p, struct uprobe, kp);
+ if (p->task->tgid == task->tgid) {
printk(KERN_INFO "%s: delete uprobe at %p[%lx]"
" for %s/%d\n", __func__, p->addr,
(unsigned long)p->opcode,
task->comm, task->pid);
- swap_unregister_uprobe(up);
+ swap_unregister_uprobe(p);
}
}
}
#include <swap-asm/swap_uprobes.h>
+/**
+ * @brief Uprobe pre-handler pointer.
+ */
+typedef int (*uprobe_pre_handler_t) (struct uprobe *, struct pt_regs *);
+
+/**
+ * @brief Uprobe break handler pointer.
+ */
+typedef int (*uprobe_break_handler_t) (struct uprobe *, struct pt_regs *);
+
+/**
+ * @brief Uprobe post handler pointer.
+ */
+typedef void (*uprobe_post_handler_t) (struct uprobe *,
+ struct pt_regs *,
+ unsigned long flags);
+
+/**
+ * @brief Uprobe fault handler pointer.
+ */
+typedef int (*uprobe_fault_handler_t) (struct uprobe *,
+ struct pt_regs *,
+ int trapnr);
/**
* @struct uprobe
- * @brief Stores uprobe data, based on kprobe.
+ * @brief Stores uprobe data.
*/
struct uprobe {
- struct kprobe kp; /**< Kprobe for this uprobe */
- struct task_struct *task; /**< Pointer to the task struct */
- struct slot_manager *sm; /**< Pointer to slot manager */
- struct arch_specific_tramp atramp; /**< Stores trampoline */
+ struct hlist_node hlist; /**< Hash list.*/
+ /** List of probes to search by instruction slot.*/
+ struct hlist_node is_hlist;
+ /** List of uprobes for multi-handler support.*/
+ struct list_head list;
+ /** Location of the probe point. */
+ uprobe_opcode_t *addr;
+ /** Called before addr is executed.*/
+ uprobe_pre_handler_t pre_handler;
+ /** Called after addr is executed, unless...*/
+ uprobe_post_handler_t post_handler;
+ /** ... called if executing addr causes a fault (eg. page fault).*/
+ uprobe_fault_handler_t fault_handler;
+ /** Return 1 if it handled fault, otherwise kernel will see it.*/
+ uprobe_break_handler_t break_handler;
+ /** Saved opcode (which has been replaced with breakpoint).*/
+ uprobe_opcode_t opcode;
+ /** Override single-step target address, may be used to redirect
+ * control-flow to arbitrary address after probe point without
+ * invocation of original instruction; useful for functions
+ * replacement. If jprobe.entry should return address of function or
+ * NULL if original function should be called.
+ * Not supported for X86, not tested for MIPS. */
+ uprobe_opcode_t *ss_addr[NR_CPUS];
+#ifdef CONFIG_ARM
+ /** Safe/unsafe to use probe on ARM.*/
+ unsigned safe_arm:1;
+ /** Safe/unsafe to use probe on Thumb.*/
+ unsigned safe_thumb:1;
+#endif
+ struct arch_insn ainsn; /**< Copy of the original instruction.*/
+ struct arch_tramp atramp; /**< Stores trampoline */
+ struct task_struct *task; /**< Pointer to the task struct */
+ struct slot_manager *sm; /**< Pointer to slot manager */
bool atomic_ctx; /**< Handler context */
};
struct hlist_node uflist; /**< Free list */
struct hlist_node hlist; /**< Used list */
struct uretprobe *rp; /**< Pointer to the parent uretprobe */
- kprobe_opcode_t *ret_addr; /**< Return address */
- kprobe_opcode_t *sp; /**< Pointer to stack */
+ uprobe_opcode_t *ret_addr; /**< Return address */
+ uprobe_opcode_t *sp; /**< Pointer to stack */
struct task_struct *task; /**< Pointer to the task struct */
#ifdef CONFIG_ARM
/* FIXME Preload: if this flag is set then ignore the thumb_mode(regs)
void swap_unregister_all_uprobes(struct task_struct *task);
void swap_ujprobe_return(void);
-struct kprobe *get_ukprobe(void *addr, pid_t tgid);
-struct kprobe *get_ukprobe_by_insn_slot(void *addr,
+struct uprobe *get_uprobe(void *addr, pid_t tgid);
+struct uprobe *get_uprobe_by_insn_slot(void *addr,
pid_t tgid,
struct pt_regs *regs);
-static inline struct uprobe *kp2up(struct kprobe *p)
-{
- return container_of(p, struct uprobe, kp);
-}
-
-static inline struct kprobe *up2kp(struct uprobe *p)
-{
- return &p->kp;
-}
-
-void disarm_uprobe(struct kprobe *p, struct task_struct *task);
+void disarm_uprobe(struct uprobe *p, struct task_struct *task);
-int trampoline_uprobe_handler(struct kprobe *p, struct pt_regs *regs);
+int trampoline_uprobe_handler(struct uprobe *p, struct pt_regs *regs);
-void add_uprobe_table(struct kprobe *p);
+void add_uprobe_table(struct uprobe *p);
#endif /* _SWAP_UPROBES_H */
struct hlist_head *head = (struct hlist_head *)data;
struct uprobe *up;
- up = probe_info_get_uprobe(ip->info, ip);
+ up = probe_info_get_uprobe(ip->desc->type, ip);
if (up) {
struct uinst_info *uinst;
- unsigned long vaddr = (unsigned long)up->kp.addr;
+ unsigned long vaddr = (unsigned long)up->addr;
- uinst = uinst_info_create(vaddr, up->kp.opcode);
+ uinst = uinst_info_create(vaddr, up->opcode);
if (uinst)
hlist_add_head(&uinst->hlist, head);
}
list_del(&ip->list);
}
-static struct img_ip *find_img_ip(struct img_file *file, unsigned long addr)
+static struct img_ip *find_img_ip(struct img_file *file, unsigned long addr,
+ struct probe_desc *pd)
{
struct img_ip *ip;
list_for_each_entry(ip, &file->ip_list, list) {
- if (ip->addr == addr)
+ if ((ip->addr == addr) &&
+ (ip->desc == pd))
return ip;
}
* @return Error code
*/
int img_file_add_ip(struct img_file *file, unsigned long addr,
- struct probe_info *probe_i)
+ struct probe_desc *pd)
{
struct img_ip *ip;
- ip = find_img_ip(file, addr);
+ ip = find_img_ip(file, addr, pd);
if (ip) {
/* ip already exists in img */
return 0;
}
- ip = create_img_ip(addr, probe_i);
+ ip = create_img_ip(addr, pd);
if (ip == NULL)
return -ENOMEM;
-
img_add_ip_by_list(file, ip);
return 0;
* @param addr Function address
* @return Error code
*/
-int img_file_del_ip(struct img_file *file, unsigned long addr)
+int img_file_del_ip(struct img_file *file, unsigned long addr,
+ struct probe_desc *pd)
{
struct img_ip *ip;
- ip = find_img_ip(file, addr);
+ ip = find_img_ip(file, addr, pd);
if (ip == NULL) {
printk(KERN_INFO "Warning: no ip found in img, addr = %lx\n",
addr);
}
img_del_ip_by_list(ip);
+ free_img_ip(ip);
return 0;
}
#include <linux/types.h>
-struct probe_info;
+struct probe_desc;
/**
* @struct img_file
void free_img_file(struct img_file *ip);
int img_file_add_ip(struct img_file *file, unsigned long addr,
- struct probe_info *probe_i);
-int img_file_del_ip(struct img_file *file, unsigned long addr);
+ struct probe_desc *pd);
+int img_file_del_ip(struct img_file *file, unsigned long addr,
+ struct probe_desc *pd);
int img_file_empty(struct img_file *file);
#include "img_ip.h"
#include <us_manager/probes/use_probes.h>
+#include <us_manager/sspt/ip.h>
#include <linux/slab.h>
/**
* @param probe_i Pointer to the probe info data.
* @return Pointer to the created img_ip struct
*/
-struct img_ip *create_img_ip(unsigned long addr, struct probe_info *info)
+struct img_ip *create_img_ip(unsigned long addr, struct probe_desc *pd)
{
struct img_ip *ip;
- ip = kmalloc(sizeof(*ip), GFP_ATOMIC);
- if (ip) {
- struct probe_info *info_new;
+ ip = kmalloc(sizeof(*ip), GFP_KERNEL);
+ if (!ip)
+ return NULL;
- info_new = probe_info_dup(info);
- if (info_new == NULL) {
- kfree(ip);
- return NULL;
- }
-
- probe_info_copy(info, info_new);
-
- INIT_LIST_HEAD(&ip->list);
- ip->addr = addr;
- ip->info = info_new;
- }
+ INIT_LIST_HEAD(&ip->list);
+ INIT_LIST_HEAD(&ip->ihead);
+ ip->addr = addr;
+ ip->desc = pd;
return ip;
}
*/
void free_img_ip(struct img_ip *ip)
{
- probe_info_cleanup(ip->info);
- probe_info_free(ip->info);
+ struct us_ip *p, *n;
+
+ list_for_each_entry_safe(p, n, &ip->ihead, img_list) {
+ list_del_init(&p->img_list);
+ p->iip = NULL;
+ list_del(&p->list);
+ probe_info_unregister(p->desc->type, p, 1);
+ free_ip(p);
+ }
+
kfree(ip);
}
/* debug */
void img_ip_print(struct img_ip *ip)
{
- if (ip->info->probe_type == SWAP_RETPROBE)
+ if (ip->desc->type == SWAP_RETPROBE)
printk(KERN_INFO "### addr=8%lx, args=%s\n",
- ip->addr, ip->info->rp_i.args);
+ ip->addr, ip->desc->info.rp_i.args);
}
/* debug */
struct img_ip {
struct list_head list; /**< For img_file */
unsigned long addr; /**< Function address */
- struct probe_info *info; /**< Probe info */
+ struct list_head ihead; /**< List head for sspt ip */
+ struct probe_desc *desc; /**< Probe info */
};
-struct img_ip *create_img_ip(unsigned long addr, struct probe_info *info);
+struct img_ip *create_img_ip(unsigned long addr, struct probe_desc *info);
void free_img_ip(struct img_ip *ip);
/* debug */
* @return Error code
*/
int img_proc_add_ip(struct img_proc *proc, struct dentry *dentry,
- unsigned long addr, struct probe_info *probe_i)
+ unsigned long addr, struct probe_desc *pd)
{
int ret;
struct img_file *file;
write_lock(&proc->rwlock);
file = find_img_file(proc, dentry);
if (file) {
- ret = img_file_add_ip(file, addr, probe_i);
+ ret = img_file_add_ip(file, addr, pd);
goto unlock;
}
goto unlock;
}
- ret = img_file_add_ip(file, addr, probe_i);
+ ret = img_file_add_ip(file, addr, pd);
if (ret) {
printk(KERN_INFO "Cannot add ip to img file\n");
free_img_file(file);
*/
int img_proc_del_ip(struct img_proc *proc,
struct dentry *dentry,
- unsigned long addr)
+ unsigned long addr,
+ struct probe_desc *pd)
{
int ret;
struct img_file *file;
goto unlock;
}
- ret = img_file_del_ip(file, addr);
+ ret = img_file_del_ip(file, addr, pd);
if (ret == 0 && img_file_empty(file)) {
img_del_file_by_list(file);
free_img_file(file);
read_lock(&i_proc->rwlock);
list_for_each_entry(i_file, &i_proc->file_list, list) {
file = sspt_proc_find_file_or_new(proc, i_file->dentry);
-
if (file) {
struct img_ip *i_ip;
list_for_each_entry(i_ip, &i_file->ip_list, list)
- sspt_file_add_ip(file, i_ip->addr, i_ip->info);
+ sspt_file_add_ip(file, i_ip);
}
}
read_unlock(&i_proc->rwlock);
struct dentry;
struct sspt_proc;
-struct probe_info;
+struct probe_desc;
struct img_proc *create_img_proc(void);
void free_img_proc(struct img_proc *proc);
int img_proc_add_ip(struct img_proc *proc, struct dentry *dentry,
- unsigned long addr, struct probe_info *probe_i);
-int img_proc_del_ip(struct img_proc *proc,
- struct dentry *dentry,
- unsigned long addr);
+ unsigned long addr, struct probe_desc *pd);
+int img_proc_del_ip(struct img_proc *proc, struct dentry *dentry,
+ unsigned long addri, struct probe_desc *pd);
void img_proc_copy_to_sspt(struct img_proc *i_proc, struct sspt_proc *proc);
* @return Error code
*/
int pf_register_probe(struct pf_group *pfg, struct dentry *dentry,
- unsigned long offset, struct probe_info *probe_i)
+ unsigned long offset, struct probe_desc *pd)
{
- return img_proc_add_ip(pfg->i_proc, dentry, offset, probe_i);
+ return img_proc_add_ip(pfg->i_proc, dentry, offset, pd);
}
EXPORT_SYMBOL_GPL(pf_register_probe);
* @return Error code
*/
int pf_unregister_probe(struct pf_group *pfg, struct dentry *dentry,
- unsigned long offset)
+ unsigned long offset, struct probe_desc *pd)
{
- return img_proc_del_ip(pfg->i_proc, dentry, offset);
+ return img_proc_del_ip(pfg->i_proc, dentry, offset, pd);
}
EXPORT_SYMBOL_GPL(pf_unregister_probe);
struct dentry;
struct pf_group;
struct sspt_proc;
-struct probe_info;
+struct probe_desc;
struct pfg_msg_cb {
struct pfg_msg_cb *pfg_msg_cb_get(struct pf_group *pfg);
int pf_register_probe(struct pf_group *pfg, struct dentry *dentry,
- unsigned long offset, struct probe_info *probe_i);
+ unsigned long offset, struct probe_desc *pd);
int pf_unregister_probe(struct pf_group *pfg, struct dentry *dentry,
- unsigned long offset);
+ unsigned long offset, struct probe_desc *pd);
void install_all(void);
void uninstall_all(void);
if (rp) {
struct us_ip *ip = container_of(rp, struct us_ip, retprobe);
- struct probe_info_new *info_new;
+ struct probe_desc *pd = NULL;
- info_new = probe_info_get_val(ip->info, struct probe_info_new *);
- if (info_new->u.rp.entry_handler)
- return info_new->u.rp.entry_handler(ri, regs);
+ pd = ip->desc;
+ if (pd && pd->u.rp.entry_handler)
+ return pd->u.rp.entry_handler(ri, regs);
}
if (rp) {
struct us_ip *ip = container_of(rp, struct us_ip, retprobe);
- struct probe_info_new *info_new;
+ struct probe_desc *pd = NULL;
- info_new = probe_info_get_val(ip->info, struct probe_info_new *);
- if (info_new->u.rp.ret_handler)
- return info_new->u.rp.ret_handler(ri, regs);
+ pd = ip->desc;
+ if (pd && pd->u.rp.ret_handler)
+ return pd->u.rp.ret_handler(ri, regs);
}
return 0;
}
-static int uprobe_handler(struct kprobe *p, struct pt_regs *regs)
+static int uprobe_handler(struct uprobe *p, struct pt_regs *regs)
{
- struct uprobe *up = container_of(p, struct uprobe, kp);
- struct us_ip *ip = container_of(up, struct us_ip, uprobe);
- struct probe_info_new *info_new;
+ struct us_ip *ip = container_of(p, struct us_ip, uprobe);
+ struct probe_desc *pd = NULL;
- info_new = probe_info_get_val(ip->info, struct probe_info_new *);
- if (info_new->u.p.handler)
- return info_new->u.p.handler(p, regs);
+ pd = ip->desc;
+ if (pd && pd->u.p.handler)
+ return pd->u.p.handler(p, regs);
return 0;
}
-
-
-
-void pin_set_probe(struct probe_info_otg *otg, unsigned long vaddr)
-{
- struct sspt_proc *proc;
- struct task_struct *task = current;
-
- otg->info.probe_type = otg->data->type;
- otg->info.size = sizeof(struct probe_info_new *);
-
- proc = sspt_proc_get_by_task(task);
- if (proc) {
- sspt_proc_install_probe(proc, vaddr, &otg->info);
- } else {
- pr_err("task[%u %u %s] not in sspt\n",
- task->tgid, task->pid, task->comm);
- }
-}
-EXPORT_SYMBOL_GPL(pin_set_probe);
-
/*
* register/unregister interface
*/
struct dentry *dentry)
{
int ret;
- struct probe_info *info;
- struct probe_info_new *info_new = probe->info;
-
- info = probe_info_create(struct probe_info_new *, info_new->type);
- if (info == NULL)
- return -ENOMEM;
-
- probe_info_set_val(info, struct probe_info_new *, info_new);
-
- ret = pf_register_probe(pfg, dentry, probe->offset, info);
+ ret = pf_register_probe(pfg, dentry, probe->offset, probe->desc);
if (ret) {
- probe_info_free(info);
+ printk(KERN_ERR "%s: register probe failed (%d)\n",
+ __FUNCTION__, ret);
return ret;
}
- info_new->info = info;
-
return 0;
}
EXPORT_SYMBOL_GPL(pin_register);
struct dentry *dentry)
{
int ret;
- struct probe_info_new *info_new = probe->info;
- ret = pf_unregister_probe(pfg, dentry, probe->offset);
+ ret = pf_unregister_probe(pfg, dentry, probe->offset, probe->desc);
if (ret) {
- /* error */
+ printk(KERN_ERR "%s: unregister probe failed (%d)\n",
+ __FUNCTION__, ret);
return ret;
}
- probe_info_free(info_new->info);
-
return 0;
}
EXPORT_SYMBOL_GPL(pin_unregister);
static void up_init(struct us_ip *ip)
{
- ip->uprobe.kp.pre_handler = uprobe_handler;
+ ip->uprobe.pre_handler = uprobe_handler;
}
static void up_uninit(struct us_ip *ip)
enum probe_t type;
union {
struct {
- kprobe_pre_handler_t handler;
+ uprobe_pre_handler_t handler;
} p;
struct {
} u;
/* private */
- struct probe_info *info;
+ struct probe_info info;
};
-
struct probe_new {
unsigned long offset;
- struct probe_info_new *info;
+ struct probe_desc *desc;
};
struct probe_info_new *data; /* field 'data[0]' in probe_info struct */
};
-void pin_set_probe(struct probe_info_otg *otg, unsigned long vaddr);
-
int pin_register(struct probe_new *probe, struct pf_group *pfg,
struct dentry *dentry);
int pin_unregister(struct probe_new *probe, struct pf_group *pfg,
#include <linux/errno.h>
#include <linux/module.h>
-
-struct probe_info *probe_info_malloc(size_t size, enum probe_t type)
-{
- struct probe_info *info;
-
- info = kmalloc(sizeof(*info) + size, GFP_ATOMIC);
- if (info) {
- info->probe_type = type;
- info->size = size;
- }
-
- return info;
-}
-EXPORT_SYMBOL_GPL(probe_info_malloc);
-
-struct probe_info *probe_info_dup(const struct probe_info *info)
-{
- struct probe_info *info_new;
- size_t size = info->size;
-
- info_new = probe_info_malloc(size, info->probe_type);
- if (info_new && size)
- memcpy(info_new->data, info->data, size);
-
- return info_new;
-}
-EXPORT_SYMBOL_GPL(probe_info_dup);
-
-void probe_info_free(struct probe_info *info)
-{
- kfree(info);
-}
-EXPORT_SYMBOL_GPL(probe_info_free);
-
-
static struct probe_iface *probes_methods[SWAP_PROBE_MAX_VAL] = { NULL };
/* 1 - correct probe type
static inline int methods_exist(enum probe_t probe_type)
{
- if (!correct_probe_type(probe_type))
- return 0;
-
- if (probes_methods[probe_type] == NULL)
+ if (!correct_probe_type(probe_type) ||
+ (probes_methods[probe_type] == NULL)) {
+ printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
return 0;
+ }
return 1;
}
* @param ip Pointer to the probe us_ip struct.
* @return Void.
*/
-void probe_info_init(struct probe_info *pi, struct us_ip *ip)
+void probe_info_init(enum probe_t type, struct us_ip *ip)
{
- enum probe_t probe_type = pi->probe_type;
-
- if (!methods_exist(probe_type)) {
- printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
+ if (!methods_exist(type)) {
return;
}
- probes_methods[probe_type]->init(ip);
+ probes_methods[type]->init(ip);
}
/**
* @param ip Pointer to the probe us_ip struct.
* @return Void.
*/
-void probe_info_uninit(struct probe_info *pi, struct us_ip *ip)
+void probe_info_uninit(enum probe_t type, struct us_ip *ip)
{
- enum probe_t probe_type = pi->probe_type;
-
- if (!methods_exist(probe_type)) {
- printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
+ if (!methods_exist(type)) {
return;
}
- probes_methods[probe_type]->uninit(ip);
+ probes_methods[type]->uninit(ip);
}
/**
* @param ip Pointer to the probe us_ip struct.
* @return -EINVAL on wrong probe type, method result otherwise.
*/
-int probe_info_register(struct probe_info *pi, struct us_ip *ip)
+int probe_info_register(enum probe_t type, struct us_ip *ip)
{
- enum probe_t probe_type = pi->probe_type;
-
- if (!methods_exist(probe_type)) {
- printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
+ if (!methods_exist(type)) {
return -EINVAL;
}
- return probes_methods[probe_type]->reg(ip);
+ return probes_methods[type]->reg(ip);
}
/**
* @param disarm Disarm flag.
* @return Void.
*/
-void probe_info_unregister(struct probe_info *pi, struct us_ip *ip, int disarm)
+void probe_info_unregister(enum probe_t type, struct us_ip *ip, int disarm)
{
- enum probe_t probe_type = pi->probe_type;
-
- if (!methods_exist(probe_type)) {
- printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
+ if (!methods_exist(type)) {
return;
}
- probes_methods[probe_type]->unreg(ip, disarm);
+ probes_methods[type]->unreg(ip, disarm);
}
/**
* @param ip Pointer to the probe us_ip struct.
* @return Pointer to the uprobe struct, NULL on error.
*/
-struct uprobe *probe_info_get_uprobe(struct probe_info *pi, struct us_ip *ip)
+struct uprobe *probe_info_get_uprobe(enum probe_t type, struct us_ip *ip)
{
- enum probe_t probe_type = pi->probe_type;
-
- if (!methods_exist(probe_type)) {
- printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
+ if (!methods_exist(type)) {
return NULL;
}
- return probes_methods[probe_type]->get_uprobe(ip);
-}
-
-/**
- * @brief Calls specified probe type copy method.
- *
- * @param pi Pointer to the source probe_info.
- * @param dest Pointer to the probe us_ip struct.
- * @return -EINVAL on error, method result otherwise.
- */
-int probe_info_copy(const struct probe_info *pi, struct probe_info *dest)
-{
- enum probe_t probe_type = pi->probe_type;
-
- if (!methods_exist(probe_type)) {
- printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
- return -EINVAL;
- }
-
- return probes_methods[probe_type]->copy(dest, pi);
-}
-
-/**
- * @brief Calls specified probe type cleanup method.
- *
- * @param pi Pointer to the source probe_info.
- * @return Void.
- */
-void probe_info_cleanup(struct probe_info *pi)
-{
- enum probe_t probe_type = pi->probe_type;
-
- if (!methods_exist(probe_type)) {
- printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
- return;
- }
-
- probes_methods[probe_type]->cleanup(pi);
+ return probes_methods[type]->get_uprobe(ip);
}
/**
int swap_register_probe_type(enum probe_t probe_type, struct probe_iface *pi)
{
if (!correct_probe_type(probe_type)) {
- printk(KERN_ERR "SWAP US_MANAGER: Wrong probe type!\n");
+ printk(KERN_ERR "SWAP US_MANAGER: incorrect probe type!\n");
return -EINVAL;
}
void swap_unregister_probe_type(enum probe_t probe_type)
{
if (!correct_probe_type(probe_type)) {
- printk(KERN_ERR "SWAP US_MANAGER: Wrong probe type!\n");
+ printk(KERN_ERR "SWAP US_MANAGER: incorrect probe type!\n");
return;
}
#define __PROBES_H__
#include <linux/types.h>
+#include <uprobe/swap_uprobes.h>
#include <preload/preload_probe.h> /* TODO Remove */
#include <retprobe/retprobe.h> /* TODO Remove */
/* Probe info stuct. It contains the whole information about probe. */
struct probe_info {
- enum probe_t probe_type;
- size_t size;
/* Union of all SWAP supported probe types */
union {
struct retprobe_info rp_i;
struct get_call_type_info gct_i;
struct write_msg_info wm_i;
};
-
- char data[0];
};
+struct probe_desc {
+ enum probe_t type;
-#define probe_info_create(val_t, type) probe_info_malloc(sizeof(val_t), type)
-struct probe_info *probe_info_malloc(size_t size, enum probe_t type);
-struct probe_info *probe_info_dup(const struct probe_info *info);
-void probe_info_free(struct probe_info *info);
-
+ union {
+ struct {
+ uprobe_pre_handler_t handler;
+ } p;
-#define probe_info_get_data(info) ((void *)(info->data))
-#define probe_info_get_ptr(info, val_t) (val_t *)probe_info_get_data(info)
-#define probe_info_get_val(info, val_t) *probe_info_get_ptr(info, val_t)
-#define probe_info_set_val(info, val_t, v) *probe_info_get_ptr(info, val_t) = v
+ struct {
+ uretprobe_handler_t entry_handler;
+ uretprobe_handler_t ret_handler;
+ /*
+ * FIXME: make dynamic size,
+ * currently data_size = sizeof(void *)
+ */
+ size_t data_size;
+ } rp;
+ } u;
+ struct probe_info info;
+};
#endif /* __PROBES_H__ */
struct us_ip;
-void probe_info_init(struct probe_info *pi, struct us_ip *ip);
-void probe_info_uninit(struct probe_info *pi, struct us_ip *ip);
-int probe_info_register(struct probe_info *pi, struct us_ip *ip);
-void probe_info_unregister(struct probe_info *pi, struct us_ip *ip, int disarm);
-struct uprobe *probe_info_get_uprobe(struct probe_info *pi, struct us_ip *ip);
+void probe_info_init(enum probe_t type, struct us_ip *ip);
+void probe_info_uninit(enum probe_t type, struct us_ip *ip);
+int probe_info_register(enum probe_t type, struct us_ip *ip);
+void probe_info_unregister(enum probe_t type, struct us_ip *ip, int disarm);
+struct uprobe *probe_info_get_uprobe(enum probe_t type, struct us_ip *ip);
int probe_info_copy(const struct probe_info *pi, struct probe_info *dest);
void probe_info_cleanup(struct probe_info *pi);
#include "sspt_page.h"
#include "sspt_file.h"
#include <us_manager/probes/use_probes.h>
+#include <us_manager/img/img_ip.h>
/**
* @brief Create us_ip struct
* @param page Pointer to the parent sspt_page struct
* @return Pointer to the created us_ip struct
*/
-struct us_ip *create_ip(unsigned long offset, const struct probe_info *info,
- struct sspt_page *page)
+struct us_ip *create_ip(struct img_ip *img_ip)
{
struct us_ip *ip;
- struct probe_info *info_new;
-
- info_new = probe_info_dup(info);
- if (info_new == NULL) {
- printk("Cannot probe_info_dup in %s function!\n", __func__);
- return NULL;
- }
ip = kmalloc(sizeof(*ip), GFP_ATOMIC);
- if (ip != NULL) {
- memset(ip, 0, sizeof(*ip));
-
- INIT_LIST_HEAD(&ip->list);
- ip->offset = offset;
- ip->page = page;
+ if (!ip)
+ return NULL;
- probe_info_copy(info, info_new);
- probe_info_init(info_new, ip);
- ip->info = info_new;
- } else {
- printk(KERN_INFO "Cannot kmalloc in create_ip function!\n");
- probe_info_free(info_new);
- }
+ memset(ip, 0, sizeof(*ip));
+ INIT_LIST_HEAD(&ip->list);
+ INIT_LIST_HEAD(&ip->img_list);
+ ip->offset = img_ip->addr;
+ ip->desc = img_ip->desc;
+ ip->iip = img_ip;
+ list_add(&ip->img_list, &img_ip->ihead);
return ip;
}
*/
void free_ip(struct us_ip *ip)
{
- probe_info_uninit(ip->info, ip);
- probe_info_free(ip->info);
+ if (!list_empty(&ip->img_list))
+ list_del(&ip->img_list);
+
kfree(ip);
}
struct us_ip {
struct list_head list; /**< For sspt_page */
struct sspt_page *page; /**< Pointer on the page (parent) */
- struct probe_info *info; /**< Probe's data */
+ struct probe_desc *desc; /**< Probe's data */
+ struct img_ip *iip;
+ struct list_head img_list;
unsigned long orig_addr; /**< Function address */
unsigned long offset; /**< Page offset */
#define to_us_ip(rp) container_of(rp, struct us_ip, retprobe)
-struct us_ip *create_ip(unsigned long offset, const struct probe_info *info,
- struct sspt_page *page);
+struct us_ip *create_ip(struct img_ip *img_ip);
void free_ip(struct us_ip *ip);
#endif /* __IP__ */
int ret;
struct uprobe *up = NULL;
- up = probe_info_get_uprobe(ip->info, ip);
+ up = probe_info_get_uprobe(ip->desc->type, ip);
if (!up) {
printk(KERN_INFO "SWAP US_MANAGER: failed getting uprobe!\n");
return -EINVAL;
}
- up->kp.addr = (kprobe_opcode_t *)ip->orig_addr;
+ up->addr = (kprobe_opcode_t *)ip->orig_addr;
up->task = ip->page->file->proc->task;
up->sm = ip->page->file->proc->sm;
up->atomic_ctx = true;
- ret = probe_info_register(ip->info, ip);
+ ret = probe_info_register(ip->desc->type, ip);
if (ret) {
struct sspt_file *file = ip->page->file;
char *name = file->dentry->d_iname;
- unsigned long addr = (unsigned long)up->kp.addr;
+ unsigned long addr = (unsigned long)up->addr;
unsigned long offset = addr - file->vm_start;
- printk(KERN_INFO "swap_register_uretprobe() failure %d "
- "(%s:%lx|%lx)\n", ret, name, offset,
- (unsigned long)ip->retprobe.up.kp.opcode);
+ printk(KERN_ERR "probe_info_register failed %d (%s:%lx|%lx)\n",
+ ret, name, offset,
+ (unsigned long)ip->retprobe.up.opcode);
}
return ret;
switch (flag) {
case US_UNREGS_PROBE:
- probe_info_unregister(ip->info, ip, 1);
+ probe_info_unregister(ip->desc->type, ip, 1);
break;
case US_DISARM:
- up = probe_info_get_uprobe(ip->info, ip);
+ up = probe_info_get_uprobe(ip->desc->type, ip);
if (up)
- disarm_uprobe(&up->kp, task);
+ disarm_uprobe(up, task);
break;
case US_UNINSTALL:
- probe_info_unregister(ip->info, ip, 0);
+ probe_info_unregister(ip->desc->type, ip, 0);
break;
default:
panic("incorrect value flag=%d", flag);
static inline void print_ip(struct us_ip *ip, int i)
{
- if (ip->info->probe_type == SWAP_RETPROBE) {
+ if (ip->desc->type == SWAP_RETPROBE) {
struct uretprobe *rp = &ip->retprobe;
printk(KERN_INFO "### addr[%2d]=%lx, R_addr=%lx\n",
i, (unsigned long)ip->offset,
- (unsigned long)rp->up.kp.addr);
+ (unsigned long)rp->up.addr);
print_retprobe(rp);
}
}
#include <linux/hash.h>
#include <linux/sched.h>
#include <kprobe/swap_kprobes_deps.h>
+#include <us_manager/probes/probes.h>
+#include <us_manager/img/img_ip.h>
static int calculation_hash_bits(int cnt)
{
* @param ret_type Return type
* @return Void
*/
-void sspt_file_add_ip(struct sspt_file *file, unsigned long offset,
- struct probe_info *probe_i)
+void sspt_file_add_ip(struct sspt_file *file, struct img_ip *img_ip)
{
- struct sspt_page *page =
- sspt_find_page_or_new(file, offset & PAGE_MASK);
+ unsigned long offset = 0;
+ struct sspt_page *page = NULL;
+ struct us_ip *ip = NULL;
+
+ offset = img_ip->addr & PAGE_MASK;
+ page = sspt_find_page_or_new(file, offset);
/* FIXME: delete ip */
- struct us_ip *ip = create_ip(offset, probe_i, page);
+ ip = create_ip(img_ip);
+ if (!ip)
+ return;
- if (page && ip)
- sspt_add_ip(page, ip);
+ sspt_add_ip(page, ip);
+ probe_info_init(ip->desc->type, ip);
}
void sspt_file_on_each_ip(struct sspt_file *file,
struct sspt_page *sspt_find_page_mapped(struct sspt_file *file,
unsigned long page);
-void sspt_file_add_ip(struct sspt_file *file, unsigned long offset,
- struct probe_info *probe_i);
+void sspt_file_add_ip(struct sspt_file *file, struct img_ip *img_ip);
void sspt_file_on_each_ip(struct sspt_file *file,
void (*func)(struct us_ip *, void *), void *data);
void sspt_add_ip(struct sspt_page *page, struct us_ip *ip)
{
ip->offset &= ~PAGE_MASK;
-
+ ip->page = page;
sspt_list_add_ip(page, ip);
}
return NULL;
}
-void sspt_proc_install_probe(struct sspt_proc *proc, unsigned long vaddr,
- struct probe_info *probe_i)
-{
- struct vm_area_struct *vma;
- struct task_struct *task = proc->task;
- struct mm_struct *mm = task->mm;
- unsigned long page_vaddr = vaddr & PAGE_MASK;
-
- vma = find_vma_intersection(mm, page_vaddr, page_vaddr + 1);
- if (vma && check_vma(vma)) {
- struct sspt_file *file;
- struct dentry *dentry = vma->vm_file->f_dentry;
-
- file = sspt_proc_find_file_or_new(proc, dentry);
- if (file) {
- unsigned long addr = vaddr - vma->vm_start;
- struct sspt_page *page;
-
- sspt_file_set_mapping(file, vma);
- sspt_file_add_ip(file, addr, probe_i);
-
- page = sspt_find_page_mapped(file, page_vaddr);
- if (page)
- sspt_register_page(page, file);
- }
- }
-}
-EXPORT_SYMBOL_GPL(sspt_proc_install_probe);
-
/**
* @brief Install probes on the page to monitored process
*
struct dentry *dentry);
struct sspt_file *sspt_proc_find_file_or_new(struct sspt_proc *proc,
struct dentry *dentry);
-
-void sspt_proc_install_probe(struct sspt_proc *proc, unsigned long vaddr,
- struct probe_info *probe_i);
void sspt_proc_install_page(struct sspt_proc *proc, unsigned long page_addr);
void sspt_proc_install(struct sspt_proc *proc);
int sspt_proc_uninstall(struct sspt_proc *proc,
static void webprobe_unregister_probe(struct us_ip *ip, int disarm)
{
if (ip->orig_addr == inspserver_addr_local)
- web_func_inst_remove(web_prof_addr(INSPSERVER_START));
+ web_func_inst_remove(INSPSERVER_START);
else if (ip->orig_addr == willexecute_addr_local)
- web_func_inst_remove(web_prof_addr(WILL_EXECUTE));
+ web_func_inst_remove(WILL_EXECUTE);
else if (ip->orig_addr == didexecute_addr_local)
- web_func_inst_remove(web_prof_addr(DID_EXECUTE));
+ web_func_inst_remove(DID_EXECUTE);
__swap_unregister_uretprobe(&ip->retprobe, disarm);
}
static void webprobe_uninit(struct us_ip *ip)
{
- webprobe_cleanup(ip->info);
+ webprobe_cleanup(&ip->desc->info);
}
#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"
struct dentry *lib_dentry;
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;
enum web_prof_state_t enabled;
};
return addr;
}
-static int web_func_inst_add(unsigned long addr)
+static struct probe_desc *web_func_inst_add(unsigned long addr)
{
int ret;
- struct probe_info probe;
+ struct probe_desc *probe = NULL;
- probe.probe_type = SWAP_WEBPROBE;
- probe.size = 0;
+ 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);
+ addr, probe);
- return ret;
+ return probe;
}
-int web_func_inst_remove(unsigned long addr)
+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);
+ 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 WILL_EXECUTE:
+ addr = web_data->willexecute_addr;
+ pd = web_data->willexecute;
+ break;
+ case DID_EXECUTE:
+ addr = web_data->didexecute_addr;
+ pd = web_data->didexecute;
+ 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);
pr_err("ERROR: Can't enable web profiling\n");
ret = -EFAULT;
} else {
- web_func_inst_add(web_data->inspserver_addr);
- web_func_inst_add(web_data->willexecute_addr);
- web_func_inst_add(web_data->didexecute_addr);
+ 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 {
pr_err("ERROR: Web profiling is already enabled\n");
pr_err("ERROR: Can't disable web profiling\n");
ret = -EFAULT;
} else {
- web_func_inst_remove(web_data->inspserver_addr);
- web_func_inst_remove(web_data->willexecute_addr);
- web_func_inst_remove(web_data->didexecute_addr);
+ if (!__web_func_inst_remove(web_data->inspserver_addr,
+ web_data->inspserver))
+ kfree(web_data->inspserver);
+
+ if (!__web_func_inst_remove(web_data->willexecute_addr,
+ web_data->willexecute))
+ kfree(web_data->willexecute);
+
+ if (!__web_func_inst_remove(web_data->didexecute_addr,
+ web_data->didexecute))
+ kfree(web_data->willexecute);
}
} else {
pr_err("ERROR: Web profiling is already disabled\n");
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);
}
int web_prof_enable(void);
int web_prof_disable(void);
enum web_prof_state_t web_prof_enabled(void);
-int web_func_inst_remove(unsigned long addr);
+int web_func_inst_remove(enum web_prof_addr_t type);
u64 *web_prof_addr_ptr(enum web_prof_addr_t type);
unsigned long web_prof_addr(enum web_prof_addr_t type);
int web_prof_data_set(char *app_path, char *app_id);
static const char ewebkit_path[] = "/usr/lib/libewebkit2.so";
-#define WSP_PROBE_MAKE(_name, _info) \
+#define WSP_PROBE_MAKE(__name, __desc) \
{ \
- .name = _name, \
+ .name = __name, \
.probe.offset = 0, \
- .probe.info = _info \
+ .probe.desc = __desc \
}
/*
* soup_req
*/
-static int soup_req_handle(struct kprobe *p, struct pt_regs *regs)
+static int soup_req_handle(struct uprobe *p, struct pt_regs *regs)
{
enum { max_str_len = 512 };
const char __user *user_s;
return 0;
}
-static struct probe_info_new soup_req = MAKE_UPROBE(soup_req_handle);
+static struct probe_desc soup_req = MAKE_UPROBE(soup_req_handle);
/*
* main_res_req
*/
-static int mres_req_handle(struct kprobe *p, struct pt_regs *regs)
+static int mres_req_handle(struct uprobe *p, struct pt_regs *regs)
{
void *ptr = (void *)swap_get_uarg(regs, 0);
struct wsp_res *res;
return 0;
}
-static struct probe_info_new mres_req = MAKE_UPROBE(mres_req_handle);
+static struct probe_desc mres_req = MAKE_UPROBE(mres_req_handle);
/*
return 0;
}
-static struct probe_info_new mres_adata =
+static struct probe_desc mres_adata =
MAKE_URPROBE(mres_adata_eh, mres_adata_rh,
sizeof(struct wsp_res *));
/*
* main_res_finish
*/
-static int mres_finish_handle(struct kprobe *p, struct pt_regs *regs)
+static int mres_finish_handle(struct uprobe *p, struct pt_regs *regs)
{
void *ptr = (void *)swap_get_uarg(regs, 0);
struct wsp_res *res;
return 0;
}
-static struct probe_info_new mres_finish = MAKE_UPROBE(mres_finish_handle);
+static struct probe_desc mres_finish = MAKE_UPROBE(mres_finish_handle);
/*
* res_request
*/
-static int res_request_handle(struct kprobe *p, struct pt_regs *regs)
+static int res_request_handle(struct uprobe *p, struct pt_regs *regs)
{
void *ptr = (void *)swap_get_uarg(regs, 0);
struct wsp_res *res;
return 0;
}
-static struct probe_info_new res_request = MAKE_UPROBE(res_request_handle);
+static struct probe_desc res_request = MAKE_UPROBE(res_request_handle);
/*
return 0;
}
-static struct probe_info_new res_finish =
+static struct probe_desc res_finish =
MAKE_URPROBE(res_finish_ehandle, res_finish_rhandle,
sizeof(struct wsp_res *));
return 0;
}
-static struct probe_info_new redraw = MAKE_URPROBE(redraw_eh, redraw_rh, 0);
+static struct probe_desc redraw = MAKE_URPROBE(redraw_eh, redraw_rh, 0);
static struct wsp_probe ewebkit_probe_array[] = {