This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
[Patch 1/5][Djprobe]Djprobe Coexist with Kprobes
- From: Masami Hiramatsu <hiramatu at sdl dot hitachi dot co dot jp>
- To: systemtap at sources dot redhat dot com
- Cc: Satoshi Oshima <soshima at redhat dot com>, Hideo Aoki <haoki at redhat dot com>, sugita at sdl dot hitachi dot co dot jp
- Date: Thu, 29 Sep 2005 21:59:25 +0900
- Subject: [Patch 1/5][Djprobe]Djprobe Coexist with Kprobes
Hi,
This patch enables get_insn_slot() to handle slots
that have different size.
It needs for supporting djprobe on NX bit.
--
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: hiramatu@sdl.hitachi.co.jp
kprobes.c | 58 +++++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 39 insertions(+), 19 deletions(-)
diff -Narup linux-2.6.13-mm1/kernel/kprobes.c linux-2.6.13-mm1.djp.1/kernel/kprobes.c
--- linux-2.6.13-mm1/kernel/kprobes.c 2005-09-05 11:34:51.000000000 +0900
+++ linux-2.6.13-mm1.djp.1/kernel/kprobes.c 2005-09-05 19:11:21.000000000 +0900
@@ -58,44 +58,53 @@ static struct kprobe *curr_kprobe;
* stepping on the instruction on a vmalloced/kmalloced/data page
* is a recipe for disaster
*/
-#define INSNS_PER_PAGE (PAGE_SIZE/(MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
+#define INSNS_PER_PAGE(size) (PAGE_SIZE/(size * sizeof(kprobe_opcode_t)))
struct kprobe_insn_page {
struct hlist_node hlist;
kprobe_opcode_t *insns; /* Page of instruction slots */
- char slot_used[INSNS_PER_PAGE];
int nused;
+ char slot_used[1];
};
-static struct hlist_head kprobe_insn_pages;
+struct kprobe_insn_page_list {
+ struct hlist_head list;
+ int insn_size; /* Size of an instruction slot */
+};
+
+static struct kprobe_insn_page_list kprobe_insn_pages = {
+ HLIST_HEAD_INIT, MAX_INSN_SIZE};
/**
- * get_insn_slot() - Find a slot on an executable page for an instruction.
+ * __get_insn_slot() - Find a slot on an executable page for an instruction.
* We allocate an executable page if there's no room on existing ones.
*/
-kprobe_opcode_t __kprobes *get_insn_slot(void)
+static kprobe_opcode_t
+__kprobes *__get_insn_slot(struct kprobe_insn_page_list *pages)
{
struct kprobe_insn_page *kip;
struct hlist_node *pos;
+ int ninsns = INSNS_PER_PAGE(pages->insn_size);
- hlist_for_each(pos, &kprobe_insn_pages) {
+ hlist_for_each(pos, &pages->list) {
kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
- if (kip->nused < INSNS_PER_PAGE) {
+ if (kip->nused < ninsns ) {
int i;
- for (i = 0; i < INSNS_PER_PAGE; i++) {
+ for (i = 0; i < ninsns; i++) {
if (!kip->slot_used[i]) {
kip->slot_used[i] = 1;
kip->nused++;
- return kip->insns + (i * MAX_INSN_SIZE);
+ return kip->insns + (i * pages->insn_size);
}
}
/* Surprise! No unused slots. Fix kip->nused. */
- kip->nused = INSNS_PER_PAGE;
+ kip->nused = ninsns;
}
}
/* All out of space. Need to allocate a new page. Use slot 0.*/
- kip = kmalloc(sizeof(struct kprobe_insn_page), GFP_KERNEL);
+ kip = kmalloc(sizeof(struct kprobe_insn_page)+sizeof(char)*(ninsns-1),
+ GFP_KERNEL);
if (!kip) {
return NULL;
}
@@ -111,23 +120,25 @@ kprobe_opcode_t __kprobes *get_insn_slot
return NULL;
}
INIT_HLIST_NODE(&kip->hlist);
- hlist_add_head(&kip->hlist, &kprobe_insn_pages);
- memset(kip->slot_used, 0, INSNS_PER_PAGE);
+ hlist_add_head(&kip->hlist, &pages->list);
+ memset(kip->slot_used, 0, ninsns);
kip->slot_used[0] = 1;
kip->nused = 1;
return kip->insns;
}
-void __kprobes free_insn_slot(kprobe_opcode_t *slot)
+static void __kprobes __free_insn_slot(struct kprobe_insn_page_list *pages,
+ kprobe_opcode_t *slot)
{
struct kprobe_insn_page *kip;
struct hlist_node *pos;
+ int ninsns = INSNS_PER_PAGE(pages->insn_size);
- hlist_for_each(pos, &kprobe_insn_pages) {
+ hlist_for_each(pos, &pages->list) {
kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
if (kip->insns <= slot &&
- slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) {
- int i = (slot - kip->insns) / MAX_INSN_SIZE;
+ slot < kip->insns + (ninsns * pages->insn_size)) {
+ int i = (slot - kip->insns) / pages->insn_size;
kip->slot_used[i] = 0;
kip->nused--;
if (kip->nused == 0) {
@@ -138,10 +149,10 @@ void __kprobes free_insn_slot(kprobe_opc
* next time somebody inserts a probe.
*/
hlist_del(&kip->hlist);
- if (hlist_empty(&kprobe_insn_pages)) {
+ if (hlist_empty(&pages->list)) {
INIT_HLIST_NODE(&kip->hlist);
hlist_add_head(&kip->hlist,
- &kprobe_insn_pages);
+ &pages->list);
} else {
module_free(NULL, kip->insns);
kfree(kip);
@@ -152,6 +163,15 @@ void __kprobes free_insn_slot(kprobe_opc
}
}
+kprobe_opcode_t __kprobes *get_insn_slot(void)
+{
+ return __get_insn_slot(&kprobe_insn_pages);
+}
+void __kprobes free_insn_slot(kprobe_opcode_t *slot)
+{
+ __free_insn_slot(&kprobe_insn_pages, slot);
+}
+
/* Locks kprobe: irqs must be disabled */
void __kprobes lock_kprobes(void)
{