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 <us_manager/probes/use_probes.h>
30 #include <linux/slab.h>
31 #include <linux/list.h>
34 * @brief Create sspt_page struct
36 * @param offset File ofset
37 * @return Pointer to the created sspt_page struct
39 struct sspt_page *sspt_page_create(unsigned long offset)
41 struct sspt_page *obj = kmalloc(sizeof(*obj), GFP_ATOMIC);
43 INIT_LIST_HEAD(&obj->ip_list_inst);
44 INIT_LIST_HEAD(&obj->ip_list_no_inst);
46 spin_lock_init(&obj->lock);
48 INIT_HLIST_NODE(&obj->hlist);
55 * @brief Remove sspt_page struct
57 * @param page remove object
60 void sspt_page_free(struct sspt_page *page)
64 list_for_each_entry_safe(ip, n, &page->ip_list_inst, list) {
69 list_for_each_entry_safe(ip, n, &page->ip_list_no_inst, list) {
77 static void sspt_list_add_ip(struct sspt_page *page, struct us_ip *ip)
79 list_add(&ip->list, &page->ip_list_no_inst);
82 static void sspt_list_del_ip(struct us_ip *ip)
88 * @brief Add instruction pointer to sspt_page
90 * @param page Pointer to the sspt_page struct
91 * @param ip Pointer to the us_ip struct
94 void sspt_add_ip(struct sspt_page *page, struct us_ip *ip)
96 ip->offset &= ~PAGE_MASK;
98 sspt_list_add_ip(page, ip);
102 * @brief Del instruction pointer from sspt_page
104 * @param ip Pointer to the us_ip struct
107 void sspt_del_ip(struct us_ip *ip)
109 sspt_list_del_ip(ip);
114 * @brief Check if probes are set on the page
116 * @param page Pointer to the sspt_page struct
121 int sspt_page_is_installed(struct sspt_page *page)
125 spin_lock(&page->lock);
126 empty = list_empty(&page->ip_list_inst);
127 spin_unlock(&page->lock);
133 * @brief Install probes on the page
135 * @param page Pointer to the sspt_page struct
136 * @param file Pointer to the sspt_file struct
139 int sspt_register_page(struct sspt_page *page, struct sspt_file *file)
142 struct us_ip *ip, *n;
143 struct list_head ip_list_tmp;
145 spin_lock(&page->lock);
146 if (list_empty(&page->ip_list_no_inst)) {
147 struct task_struct *task = page->file->proc->task;
149 printk(KERN_INFO "page %lx in %s task[tgid=%u, pid=%u] "
150 "already installed\n",
151 page->offset, file->dentry->d_iname,
152 task->tgid, task->pid);
156 INIT_LIST_HEAD(&ip_list_tmp);
157 list_replace_init(&page->ip_list_no_inst, &ip_list_tmp);
158 spin_unlock(&page->lock);
160 list_for_each_entry_safe(ip, n, &ip_list_tmp, list) {
161 /* set virtual address */
162 ip->orig_addr = file->vm_start + page->offset + ip->offset;
164 err = sspt_register_usprobe(ip);
172 spin_lock(&page->lock);
173 list_splice(&ip_list_tmp, &page->ip_list_inst);
176 spin_unlock(&page->lock);
182 * @brief Uninstall probes on the page
184 * @param page Pointer to the sspt_page struct
185 * @param flag Action for probes
186 * @param task Pointer to the task_struct struct
189 int sspt_unregister_page(struct sspt_page *page,
191 struct task_struct *task)
195 struct list_head ip_list_tmp, *head;
197 spin_lock(&page->lock);
198 if (list_empty(&page->ip_list_inst)) {
199 spin_unlock(&page->lock);
203 INIT_LIST_HEAD(&ip_list_tmp);
204 list_replace_init(&page->ip_list_inst, &ip_list_tmp);
206 spin_unlock(&page->lock);
208 list_for_each_entry(ip, &ip_list_tmp, list) {
209 err = sspt_unregister_usprobe(task, ip, flag);
216 head = (flag == US_DISARM) ?
217 &page->ip_list_inst : &page->ip_list_no_inst;
219 spin_lock(&page->lock);
221 list_splice(&ip_list_tmp, head);
222 spin_unlock(&page->lock);
227 void sspt_page_on_each_ip(struct sspt_page *page,
228 void (*func)(struct us_ip *, void *), void *data)
232 spin_lock(&page->lock);
233 list_for_each_entry(ip, &page->ip_list_inst, list)
236 spin_unlock(&page->lock);