2 * Dynamic Binary Instrumentation Module based on KProbes
3 * modules/driver/sspt/sspt_page.c
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * Copyright (C) Samsung Electronics, 2013
21 * 2013 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
26 #include "sspt_page.h"
27 #include "sspt_file.h"
29 #include <linux/slab.h>
30 #include <linux/list.h>
32 struct sspt_page *sspt_page_create(unsigned long offset)
34 struct sspt_page *obj = kmalloc(sizeof(*obj), GFP_ATOMIC);
36 INIT_LIST_HEAD(&obj->ip_list);
39 spin_lock_init(&obj->lock);
41 INIT_HLIST_NODE(&obj->hlist);
47 void sspt_page_free(struct sspt_page *page)
51 list_for_each_entry_safe(ip, n, &page->ip_list, list) {
59 static void sspt_list_add_ip(struct sspt_page *page, struct us_ip *ip)
61 list_add(&ip->list, &page->ip_list);
65 static void sspt_list_del_ip(struct us_ip *ip)
70 void sspt_add_ip(struct sspt_page *page, struct us_ip *ip)
74 ip->offset &= ~PAGE_MASK;
76 list_for_each_entry(ip_tmp, &page->ip_list, list) {
77 if (ip_tmp->offset == ip->offset) {
78 /* TODO: process second instanse of probe */
83 sspt_list_add_ip(page, ip);
86 void sspt_del_ip(struct us_ip *ip)
92 struct us_ip *sspt_find_ip(struct sspt_page *page, unsigned long offset)
96 list_for_each_entry(ip, &page->ip_list, list) {
97 if (ip->offset == offset) {
105 void sspt_set_all_ip_addr(struct sspt_page *page, const struct sspt_file *file)
110 list_for_each_entry(ip, &page->ip_list, list) {
111 addr = file->vm_start + page->offset + ip->offset;
112 ip->retprobe.up.kp.addr = ip->jprobe.up.kp.addr = (kprobe_opcode_t *)addr;
116 int sspt_register_page(struct sspt_page *page, struct sspt_file *file)
119 struct us_ip *ip, *n;
121 spin_lock(&page->lock);
123 if (sspt_page_is_installed(page)) {
124 struct task_struct *task = page->file->proc->task;
126 printk("page %lx in %s task[tgid=%u, pid=%u] already installed\n",
127 page->offset, file->dentry->d_iname, task->tgid, task->pid);
131 sspt_page_assert_install(page);
132 sspt_set_all_ip_addr(page, file);
134 list_for_each_entry_safe(ip, n, &page->ip_list, list) {
135 err = sspt_register_usprobe(ip);
136 if (err == -ENOEXEC) {
141 printk("Failed to install probe\n");
145 sspt_page_install(page);
146 spin_unlock(&page->lock);
151 int sspt_unregister_page(struct sspt_page *page,
153 struct task_struct *task)
158 spin_lock(&page->lock);
159 if (!sspt_page_is_installed(page)) {
160 spin_unlock(&page->lock);
164 list_for_each_entry(ip, &page->ip_list, list) {
165 err = sspt_unregister_usprobe(task, ip, flag);
172 if (flag != US_DISARM) {
173 sspt_page_uninstall(page);
175 spin_unlock(&page->lock);