This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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)
 {




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]