(unsigned long)rp->handler);
}
+static inline print_ip(struct us_ip *ip, int i)
+{
+ printk("### addr[%2d]=%lx, R_addr=%lx\n",
+ i, (unsigned long)ip->offset,
+ (unsigned long)ip->retprobe.up.kp.addr);
+ print_retprobe(&ip->retprobe);
+}
+
static inline void print_page_probes(const struct sspt_page *page)
{
int i = 0;
struct us_ip *ip;
printk("### offset=%lx\n", page->offset);
- list_for_each_entry(ip, &page->ip_list, list) {
+ printk("### no install:\n");
+ list_for_each_entry(ip, &page->ip_list_no_inst, list) {
+ print_ip(ip, i);
+ ++i;
+ }
- printk("### addr[%2d]=%lx, R_addr=%lx\n",
- i, (unsigned long)ip->offset,
- (unsigned long)ip->retprobe.up.kp.addr);
- print_retprobe(&ip->retprobe);
+ printk("### install:\n");
+ list_for_each_entry(ip, &page->ip_list_inst, list) {
+ print_ip(ip, i);
++i;
}
}
{
struct sspt_page *obj = kmalloc(sizeof(*obj), GFP_ATOMIC);
if (obj) {
- INIT_LIST_HEAD(&obj->ip_list);
+ INIT_LIST_HEAD(&obj->ip_list_inst);
+ INIT_LIST_HEAD(&obj->ip_list_no_inst);
obj->offset = offset;
- obj->install = 0;
spin_lock_init(&obj->lock);
obj->file = NULL;
INIT_HLIST_NODE(&obj->hlist);
{
struct us_ip *ip, *n;
- list_for_each_entry_safe(ip, n, &page->ip_list, list) {
+ list_for_each_entry_safe(ip, n, &page->ip_list_inst, list) {
+ list_del(&ip->list);
+ free_ip(ip);
+ }
+
+ list_for_each_entry_safe(ip, n, &page->ip_list_no_inst, list) {
list_del(&ip->list);
free_ip(ip);
}
static void sspt_list_add_ip(struct sspt_page *page, struct us_ip *ip)
{
- list_add(&ip->list, &page->ip_list);
+ list_add(&ip->list, &page->ip_list_no_inst);
ip->page = page;
}
free_ip(ip);
}
-struct us_ip *sspt_find_ip(struct sspt_page *page, unsigned long offset)
+int sspt_page_is_installed(struct sspt_page *page)
{
- struct us_ip *ip;
-
- list_for_each_entry(ip, &page->ip_list, list) {
- if (ip->offset == offset) {
- return ip;
- }
- }
+ int empty;
- return NULL;
-}
-
-void sspt_set_all_ip_addr(struct sspt_page *page, const struct sspt_file *file)
-{
- struct us_ip *ip;
- unsigned long addr;
+ spin_lock(&page->lock);
+ empty = list_empty(&page->ip_list_inst);
+ spin_unlock(&page->lock);
- list_for_each_entry(ip, &page->ip_list, list) {
- addr = file->vm_start + page->offset + ip->offset;
- ip->retprobe.up.kp.addr = (kprobe_opcode_t *)addr;
- }
+ return !empty;
}
int sspt_register_page(struct sspt_page *page, struct sspt_file *file)
{
int err = 0;
struct us_ip *ip, *n;
+ struct list_head ip_list_tmp;
+ unsigned long addr;
spin_lock(&page->lock);
-
- if (sspt_page_is_installed(page)) {
+ if (list_empty(&page->ip_list_no_inst)) {
struct task_struct *task = page->file->proc->task;
printk("page %lx in %s task[tgid=%u, pid=%u] already installed\n",
goto unlock;
}
- sspt_page_assert_install(page);
- sspt_set_all_ip_addr(page, file);
+ INIT_LIST_HEAD(&ip_list_tmp);
+ list_replace_init(&page->ip_list_no_inst, &ip_list_tmp);
+ spin_unlock(&page->lock);
+
+ list_for_each_entry_safe(ip, n, &ip_list_tmp, list) {
+ /* set uprobe address */
+ addr = file->vm_start + page->offset + ip->offset;
+ ip->retprobe.up.kp.addr = (kprobe_opcode_t *)addr;
- list_for_each_entry_safe(ip, n, &page->ip_list, list) {
err = sspt_register_usprobe(ip);
if (err == -ENOEXEC) {
+ /* TODO: delete?! */
list_del(&ip->list);
free_ip(ip);
continue;
printk("Failed to install probe\n");
}
}
+
+ spin_lock(&page->lock);
+ list_splice(&ip_list_tmp, &page->ip_list_inst);
+
unlock:
- sspt_page_install(page);
spin_unlock(&page->lock);
return 0;
{
int err = 0;
struct us_ip *ip;
+ struct list_head ip_list_tmp, *head;
spin_lock(&page->lock);
- if (!sspt_page_is_installed(page)) {
+ if (list_empty(&page->ip_list_inst)) {
spin_unlock(&page->lock);
return 0;
}
- list_for_each_entry(ip, &page->ip_list, list) {
+ INIT_LIST_HEAD(&ip_list_tmp);
+ list_replace_init(&page->ip_list_inst, &ip_list_tmp);
+ spin_unlock(&page->lock);
+
+ list_for_each_entry(ip, &ip_list_tmp, list) {
err = sspt_unregister_usprobe(task, ip, flag);
if (err != 0) {
//TODO: ERROR
}
}
- if (flag != US_DISARM) {
- sspt_page_uninstall(page);
- }
+ head = (flag == US_DISARM) ? &page->ip_list_inst : &page->ip_list_no_inst;
+
+ spin_lock(&page->lock);
+ list_splice(&ip_list_tmp, head);
spin_unlock(&page->lock);
return err;
enum US_FLAGS;
struct sspt_page {
- struct list_head ip_list;
+ struct list_head ip_list_inst;
+ struct list_head ip_list_no_inst;
unsigned long offset;
- int install;
spinlock_t lock;
struct sspt_file *file;
void sspt_add_ip(struct sspt_page *page, struct us_ip *ip);
void sspt_del_ip(struct us_ip *ip);
-struct us_ip *sspt_find_ip(struct sspt_page *page, unsigned long offset);
-static inline void sspt_page_assert_install(const struct sspt_page *page)
-{
- if (page->install != 0) {
- panic("already installed page %lx\n", page->offset);
- }
-}
-
-static inline int sspt_page_is_installed(struct sspt_page *page)
-{
- return page->install;
-}
-
-static inline void sspt_page_install(struct sspt_page *page)
-{
- page->install = 1;
-}
-
-static inline void sspt_page_uninstall(struct sspt_page *page)
-{
- page->install = 0;
-}
-
-void sspt_set_all_ip_addr(struct sspt_page *page, const struct sspt_file *file);
+int sspt_page_is_installed(struct sspt_page *page);
int sspt_register_page(struct sspt_page *page, struct sspt_file *file);