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 RFC] itrace probe point problem on ppc64: unknown symbol 'access_process_vm'


Hi,
As I mentioned in my previous post today, besides the need for updating runtime/itrace.c to use the new utrace interface, I found another problem when trying to use the itrace probe point on ppc64 -- I got an "unknown symbol" error for 'access_process_vm' when systemtap tried to insert the generated kernel module.  Turns out that on the ppc64 kernel for Fedora, this symbol isn't exported.  :-(  I've gotten around this by simply pasting the access_process_vm code into runtime/itrace.c and renaming it to avoid a clash when using on Fedora/x86_64 (where this kernel function *is* exported).  The attached patch shows this change.  Is this an acceptable way to handle this problem?  Or does someone have a better idea?

Thanks.
-Maynard
diff -paur systemtap-orig/runtime/itrace.c systemtap-fixes/runtime/itrace.c
--- systemtap-orig/runtime/itrace.c	2009-03-02 23:32:51.000000000 -0500
+++ systemtap-fixes/runtime/itrace.c	2009-03-02 23:35:43.000000000 -0500
@@ -63,6 +63,61 @@ static struct itrace_info *create_itrace
 	struct task_struct *tsk, u32 step_flag,
 	struct stap_itrace_probe *itrace_probe);
 
+/*
+ * The kernel's access_process_vm is not exported in kernel.org kernels, although
+ * some distros export it on some architectures.  To workaround this inconsistency,
+ * we copied and pasted it here.  Fortunately, everything it calls is exported.
+ */
+#include <linux/pagemap.h>
+#include <asm/cacheflush.h>
+static int __access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
+{
+	struct mm_struct *mm;
+	struct vm_area_struct *vma;
+	struct page *page;
+	void *old_buf = buf;
+
+	mm = get_task_mm(tsk);
+	if (!mm)
+		return 0;
+
+	down_read(&mm->mmap_sem);
+	/* ignore errors, just check how much was sucessfully transfered */
+	while (len) {
+		int bytes, ret, offset;
+		void *maddr;
+
+		ret = get_user_pages(tsk, mm, addr, 1,
+				     write, 1, &page, &vma);
+		if (ret <= 0)
+			break;
+
+		bytes = len;
+		offset = addr & (PAGE_SIZE-1);
+		if (bytes > PAGE_SIZE-offset)
+			bytes = PAGE_SIZE-offset;
+
+		maddr = kmap(page);
+		if (write) {
+			copy_to_user_page(vma, page, addr,
+					  maddr + offset, buf, bytes);
+			set_page_dirty_lock(page);
+		} else {
+			copy_from_user_page(vma, page, addr,
+					    buf, maddr + offset, bytes);
+		}
+		kunmap(page);
+		page_cache_release(page);
+		len -= bytes;
+		buf += bytes;
+		addr += bytes;
+	}
+	up_read(&mm->mmap_sem);
+	mmput(mm);
+
+	return buf - old_buf;
+}
+
 static u32 usr_itrace_report_quiesce(enum utrace_resume_action action,
 				struct utrace_attached_engine *engine,
 				struct task_struct *tsk,
@@ -325,7 +380,7 @@ static void insert_atomic_ss_breakpoint 
 	cur_instr = get_instr(bpt->addr, "insert_atomic_ss_breakpoint");
 	if (cur_instr != BPT_TRAP) {
 		bpt->instr = cur_instr;
-		WARN_ON(access_process_vm(tsk, bpt->addr, &bp_instr, INSTR_SZ, 1) !=
+		WARN_ON(__access_process_vm(tsk, bpt->addr, &bp_instr, INSTR_SZ, 1) !=
 			INSTR_SZ);
 	}
 }
@@ -333,7 +388,7 @@ static void insert_atomic_ss_breakpoint 
 static void remove_atomic_ss_breakpoint (struct task_struct *tsk,
 	struct bpt_info *bpt)
 {
-	WARN_ON(access_process_vm(tsk, bpt->addr, &bpt->instr, INSTR_SZ, 1) !=
+	WARN_ON(__access_process_vm(tsk, bpt->addr, &bpt->instr, INSTR_SZ, 1) !=
 		INSTR_SZ);
 }
 

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