[PATCH] 2-ptrace_multi

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



ptmulti kernel patch inserts a new useful option for ptrace() call, 
adding a new request type to ptrace() syscall.

With PTRACE_MULTI option you can send multiple ptrace requests with a 
single system call: commonly a process that uses ptrace() needs
several PTRACE_PEEKDATA for getting some useful, even small pieces of data.
It is useful for these programs to run several ptrace
operations while limiting the number of context switches.

Ptrace-multi gets a "struct ptrace_multi" array (together with its 
number of elements). It is in this way similar to the management of buffers
for readv or writev.
Each "struct ptrace_multi" specifies a single request of normal type of
ptrace. So you have can join several requests into a requests array that will
be passed through the "void* addr" parameter (the third) of ptrace().
The last argument specify the numbers of request to be accomplished by ptrace.

While normal ptrace requests can get a word at a time, we have added some other
request for simplify the interface between kernel
and applications that use ptrace(); these requests can get from user space more
than one word at a time: 
- PTRACE_PEEKCHARDATA and PTRACE_POKECHARDATA is used for transferring general
  data, like structure, buffer, and so on...
- PTRACE_PEEKSTRINGDATA get strings from user space  (it relies on
  access_process_vm_user patch) and it check that data returned is a well formed
  string (null-terminated)

Debuggers and virtual machines (like User Mode Linux) and many other 
applications that are based on ptrace can get great 
performance improvements by PTRACE_MULTI: the number of system
calls (and context switches) decreases significantly.

This patch is architecture independent.

Signed-off-by: renzo davoli <[email protected]>

diff -Naur linux-2.6.17-rc1/include/linux/ptrace.h linux-2.6.17-rc1-ptmulti/include/linux/ptrace.h
--- linux-2.6.17-rc1/include/linux/ptrace.h	2006-04-04 16:18:55.000000000 +0200
+++ linux-2.6.17-rc1-ptmulti/include/linux/ptrace.h	2006-04-04 16:17:30.000000000 +0200
@@ -27,6 +27,18 @@
 #define PTRACE_GETSIGINFO	0x4202
 #define PTRACE_SETSIGINFO	0x4203
 
+#define PTRACE_MULTI            0x4300
+#define PTRACE_PEEKCHARDATA     0x4301
+#define PTRACE_POKECHARDATA     0x4302
+#define PTRACE_PEEKSTRINGDATA   0x4303
+
+struct ptrace_multi {
+	long request;
+	long addr;
+	void *localaddr;
+	long length;
+};
+
 /* options set using PTRACE_SETOPTIONS */
 #define PTRACE_O_TRACESYSGOOD	0x00000001
 #define PTRACE_O_TRACEFORK	0x00000002
diff -Naur linux-2.6.17-rc1/kernel/ptrace.c linux-2.6.17-rc1-ptmulti/kernel/ptrace.c
--- linux-2.6.17-rc1/kernel/ptrace.c	2006-04-04 16:18:55.000000000 +0200
+++ linux-2.6.17-rc1-ptmulti/kernel/ptrace.c	2006-04-04 16:17:30.000000000 +0200
@@ -2,6 +2,7 @@
  * linux/kernel/ptrace.c
  *
  * (C) Copyright 1999 Linus Torvalds
+ * PTRACE_MULTI support 2006 Renzo Davoli 
  *
  * Common interfaces for "ptrace()" which we do not want
  * to continually duplicate across every architecture.
@@ -503,6 +504,53 @@
 	return child;
 }
 
+static int multi_ptrace(struct task_struct *child, long request, long addr, long size)
+{
+	int i, ret;
+	long j;
+	ret=0;
+	if (!access_ok(VERIFY_READ, addr,size*sizeof(struct ptrace_multi))) {
+		ret = -EIO;
+		goto out_multi_ptrace;
+	}
+	for (i=0; i<size && ret==0; i++, addr+=sizeof(struct ptrace_multi)) {
+		unsigned long len;
+		struct ptrace_multi __user pm ;
+		__copy_from_user(&pm, (struct ptrace_multi __user *)addr, sizeof(struct ptrace_multi));
+		len = pm.length;
+		switch ( pm.request){
+			case PTRACE_PEEKTEXT:
+			case PTRACE_PEEKDATA:
+			case PTRACE_PEEKUSR:
+				if (len <= 0) len=1;
+				for (j=0; j<len && ret==0; j++)
+					ret=arch_ptrace(child, pm.request, (long) (pm.addr) + j*sizeof(long), (long) (pm.localaddr) + j*sizeof(long));
+				break;
+			case PTRACE_POKETEXT:
+			case PTRACE_POKEDATA:
+			case PTRACE_POKEUSR:
+				if (len <= 0) len=1;
+				for (j=0; j<len && ret==0; j++)
+					ret=arch_ptrace(child, pm.request, (long) (pm.addr) + j*sizeof(long), *(((long *) (pm.localaddr)) + j));
+				break;
+			case PTRACE_PEEKCHARDATA:
+				ret = ptrace_readdata(child, pm.addr, pm.localaddr, len);
+				break;
+			case PTRACE_POKECHARDATA:
+				ret = ptrace_writedata(child, pm.localaddr, pm.addr, len);
+				break;
+			case PTRACE_PEEKSTRINGDATA:
+				ret = ptrace_readstringdata(child, pm.addr, pm.localaddr, len);
+				break;
+			default:
+				ret=arch_ptrace(child, pm.request, (long) (pm.addr), (long) (pm.localaddr));
+				break;
+		}
+	}
+ out_multi_ptrace:
+	return ret;
+}
+
 #ifndef __ARCH_SYS_PTRACE
 asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
@@ -533,6 +581,9 @@
 	if (ret < 0)
 		goto out_put_task_struct;
 
+	if (request == PTRACE_MULTI) 
+		ret = multi_ptrace(child, request, addr, data);
+	else
 	ret = arch_ptrace(child, request, addr, data);
 	if (ret < 0)
 		goto out_put_task_struct;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux