diff mbox

Support ptrace system call on ARM

Message ID 201103211927.p2LJRTKH001631@d06av02.portsmouth.uk.ibm.com
State Accepted
Headers show

Commit Message

Ulrich Weigand March 21, 2011, 7:27 p.m. UTC
[https://bugs.kde.org/show_bug.cgi?id=269079]
diff mbox

Patch

Index: include/vki/vki-arm-linux.h
===================================================================
--- include/vki/vki-arm-linux.h	(revision 11577)
+++ include/vki/vki-arm-linux.h	(working copy)
@@ -190,43 +190,6 @@ 
 // From linux-2.6.8.1/include/asm-i386/sigcontext.h
 //----------------------------------------------------------------------
 
-struct _vki_fpreg {
-	unsigned short significand[4];
-	unsigned short exponent;
-};
-
-struct _vki_fpxreg {
-	unsigned short significand[4];
-	unsigned short exponent;
-	unsigned short padding[3];
-};
-
-struct _vki_xmmreg {
-	unsigned long element[4];
-};
-
-struct _vki_fpstate {
-	/* Regular FPU environment */
-	unsigned long 	cw;
-	unsigned long	sw;
-	unsigned long	tag;
-	unsigned long	ipoff;
-	unsigned long	cssel;
-	unsigned long	dataoff;
-	unsigned long	datasel;
-	struct _vki_fpreg	_st[8];
-	unsigned short	status;
-	unsigned short	magic;		/* 0xffff = regular FPU data only */
-
-	/* FXSR FPU environment */
-	unsigned long	_fxsr_env[6];	/* FXSR FPU env is ignored */
-	unsigned long	mxcsr;
-	unsigned long	reserved;
-	struct _vki_fpxreg	_fxsr_st[8];	/* FXSR FPU reg data is ignored */
-	struct _vki_xmmreg	_xmm[8];
-	unsigned long	padding[56];
-};
-
 struct vki_sigcontext {
 		unsigned long trap_no;
 		unsigned long error_code;
@@ -546,33 +509,41 @@ 
 // From linux-2.6.8.1/include/asm-i386/user.h
 //----------------------------------------------------------------------
 
-struct vki_user_i387_struct {
-	long	cwd;
-	long	swd;
-	long	twd;
-	long	fip;
-	long	fcs;
-	long	foo;
-	long	fos;
-	long	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */
+struct vki_user_fp {
+	struct vki_fp_reg {
+		unsigned int sign1:1;
+		unsigned int unused:15;
+		unsigned int sign2:1;
+		unsigned int exponent:14;
+		unsigned int j:1;
+		unsigned int mantissa1:31;
+		unsigned int mantissa0:32;
+	} fpregs[8];
+	unsigned int fpsr:32;
+	unsigned int fpcr:32;
+	unsigned char ftype[8];
+	unsigned int init_flag;
 };
 
-struct vki_user_fxsr_struct {
-	unsigned short	cwd;
-	unsigned short	swd;
-	unsigned short	twd;
-	unsigned short	fop;
-	long	fip;
-	long	fcs;
-	long	foo;
-	long	fos;
-	long	mxcsr;
-	long	reserved;
-	long	st_space[32];	/* 8*16 bytes for each FP-reg = 128 bytes */
-	long	xmm_space[32];	/* 8*16 bytes for each XMM-reg = 128 bytes */
-	long	padding[56];
+struct vki_user_vfp {
+	unsigned long long fpregs[32];
+	unsigned long fpscr;
 };
 
+#define VKI_IWMMXT_SIZE 0x98
+
+struct vki_iwmmxt_struct {
+	unsigned int save[VKI_IWMMXT_SIZE / sizeof(unsigned int)];
+};
+
+struct vki_crunch_state {
+	unsigned int    mvdx[16][2];
+	unsigned int    mvax[4][3];
+	unsigned int    dspsc[2];
+};
+
+#define VKI_CRUNCH_SIZE sizeof(struct vki_crunch_state)
+
 struct vki_user_regs_struct {
     long uregs[18];
 };
@@ -603,8 +574,7 @@ 
 #define VKI_ELF_NGREG (sizeof (struct vki_user_regs_struct) / sizeof(vki_elf_greg_t))
 typedef vki_elf_greg_t vki_elf_gregset_t[VKI_ELF_NGREG];
 
-typedef struct vki_user_i387_struct vki_elf_fpregset_t;
-typedef struct vki_user_fxsr_struct vki_elf_fpxregset_t;
+typedef struct vki_user_fp vki_elf_fpregset_t;
 
 #define VKI_AT_SYSINFO		32
 
@@ -799,8 +769,16 @@ 
 #define VKI_PTRACE_SETREGS            13
 #define VKI_PTRACE_GETFPREGS          14
 #define VKI_PTRACE_SETFPREGS          15
-#define VKI_PTRACE_GETFPXREGS         18
-#define VKI_PTRACE_SETFPXREGS         19
+#define VKI_PTRACE_GETWMMXREGS        18
+#define VKI_PTRACE_SETWMMXREGS        19
+#define VKI_PTRACE_GET_THREAD_AREA    22
+#define VKI_PTRACE_SET_SYSCALL        23
+#define VKI_PTRACE_GETCRUNCHREGS      25
+#define VKI_PTRACE_SETCRUNCHREGS      26
+#define VKI_PTRACE_GETVFPREGS         27
+#define VKI_PTRACE_SETVFPREGS         28
+#define VKI_PTRACE_GETHBPREGS         29
+#define VKI_PTRACE_SETHBPREGS         30
 
 //----------------------------------------------------------------------
 // From linux-2.6.15.4/include/asm-i386/vm86.h
Index: coregrind/m_syswrap/syswrap-arm-linux.c
===================================================================
--- coregrind/m_syswrap/syswrap-arm-linux.c	(revision 11577)
+++ coregrind/m_syswrap/syswrap-arm-linux.c	(working copy)
@@ -342,6 +342,7 @@ 
 DECL_TEMPLATE(arm_linux, sys_rt_sigreturn);
 DECL_TEMPLATE(arm_linux, sys_set_tls);
 DECL_TEMPLATE(arm_linux, sys_cacheflush);
+DECL_TEMPLATE(arm_linux, sys_ptrace);
 
 PRE(sys_socketcall)
 {
@@ -1205,7 +1206,125 @@ 
    SET_STATUS_Success(0);
 }
 
+// ARG3 is only used for pointers into the traced process's address
+// space and for offsets into the traced process's struct
+// user_regs_struct. It is never a pointer into this process's memory
+// space, and we should therefore not check anything it points to.
+PRE(sys_ptrace)
+{
+   PRINT("sys_ptrace ( %ld, %ld, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4);
+   PRE_REG_READ4(int, "ptrace", 
+                 long, request, long, pid, long, addr, long, data);
+   switch (ARG1) {
+   case VKI_PTRACE_PEEKTEXT:
+   case VKI_PTRACE_PEEKDATA:
+   case VKI_PTRACE_PEEKUSR:
+      PRE_MEM_WRITE( "ptrace(peek)", ARG4, 
+		     sizeof (long));
+      break;
+   case VKI_PTRACE_GETREGS:
+      PRE_MEM_WRITE( "ptrace(getregs)", ARG4, 
+		     sizeof (struct vki_user_regs_struct));
+      break;
+   case VKI_PTRACE_GETFPREGS:
+      PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4, 
+		     sizeof (struct vki_user_fp));
+      break;
+   case VKI_PTRACE_GETWMMXREGS:
+      PRE_MEM_WRITE( "ptrace(getwmmxregs)", ARG4, 
+		     VKI_IWMMXT_SIZE);
+      break;
+   case VKI_PTRACE_GETCRUNCHREGS:
+      PRE_MEM_WRITE( "ptrace(getcrunchregs)", ARG4, 
+		     VKI_CRUNCH_SIZE);
+      break;
+   case VKI_PTRACE_GETVFPREGS:
+      PRE_MEM_WRITE( "ptrace(getvfpregs)", ARG4, 
+                     sizeof (struct vki_user_vfp) );
+      break;
+   case VKI_PTRACE_GETHBPREGS:
+      PRE_MEM_WRITE( "ptrace(gethbpregs)", ARG4, 
+                     sizeof (unsigned long) );
+      break;
+   case VKI_PTRACE_SETREGS:
+      PRE_MEM_READ( "ptrace(setregs)", ARG4, 
+		     sizeof (struct vki_user_regs_struct));
+      break;
+   case VKI_PTRACE_SETFPREGS:
+      PRE_MEM_READ( "ptrace(setfpregs)", ARG4, 
+		     sizeof (struct vki_user_fp));
+      break;
+   case VKI_PTRACE_SETWMMXREGS:
+      PRE_MEM_READ( "ptrace(setwmmxregs)", ARG4, 
+		     VKI_IWMMXT_SIZE);
+      break;
+   case VKI_PTRACE_SETCRUNCHREGS:
+      PRE_MEM_READ( "ptrace(setcrunchregs)", ARG4, 
+		     VKI_CRUNCH_SIZE);
+      break;
+   case VKI_PTRACE_SETVFPREGS:
+      PRE_MEM_READ( "ptrace(setvfpregs)", ARG4, 
+                     sizeof (struct vki_user_vfp));
+      break;
+   case VKI_PTRACE_SETHBPREGS:
+      PRE_MEM_READ( "ptrace(sethbpregs)", ARG4, sizeof(unsigned long));
+      break;
+   case VKI_PTRACE_GET_THREAD_AREA:
+      PRE_MEM_WRITE( "ptrace(get_thread_area)", ARG4, sizeof(unsigned long));
+      break;
+   case VKI_PTRACE_GETEVENTMSG:
+      PRE_MEM_WRITE( "ptrace(geteventmsg)", ARG4, sizeof(unsigned long));
+      break;
+   case VKI_PTRACE_GETSIGINFO:
+      PRE_MEM_WRITE( "ptrace(getsiginfo)", ARG4, sizeof(vki_siginfo_t));
+      break;
+   case VKI_PTRACE_SETSIGINFO:
+      PRE_MEM_READ( "ptrace(setsiginfo)", ARG4, sizeof(vki_siginfo_t));
+      break;
+   default:
+      break;
+   }
+}
 
+POST(sys_ptrace)
+{
+   switch (ARG1) {
+   case VKI_PTRACE_PEEKTEXT:
+   case VKI_PTRACE_PEEKDATA:
+   case VKI_PTRACE_PEEKUSR:
+      POST_MEM_WRITE( ARG4, sizeof (long));
+      break;
+   case VKI_PTRACE_GETREGS:
+      POST_MEM_WRITE( ARG4, sizeof (struct vki_user_regs_struct));
+      break;
+   case VKI_PTRACE_GETFPREGS:
+      POST_MEM_WRITE( ARG4, sizeof (struct vki_user_fp));
+      break;
+   case VKI_PTRACE_GETWMMXREGS:
+      POST_MEM_WRITE( ARG4, VKI_IWMMXT_SIZE);
+      break;
+   case VKI_PTRACE_GETCRUNCHREGS:
+      POST_MEM_WRITE( ARG4, VKI_CRUNCH_SIZE);
+      break;
+   case VKI_PTRACE_GETVFPREGS:
+      POST_MEM_WRITE( ARG4, sizeof(struct vki_user_vfp));
+      break;
+   case VKI_PTRACE_GET_THREAD_AREA:
+   case VKI_PTRACE_GETHBPREGS:
+   case VKI_PTRACE_GETEVENTMSG:
+      POST_MEM_WRITE( ARG4, sizeof(unsigned long));
+      break;
+   case VKI_PTRACE_GETSIGINFO:
+      /* XXX: This is a simplification. Different parts of the
+       * siginfo_t are valid depending on the type of signal.
+       */
+      POST_MEM_WRITE( ARG4, sizeof(vki_siginfo_t));
+      break;
+   default:
+      break;
+   }
+}
+
 #undef PRE
 #undef POST
 
@@ -1262,7 +1381,7 @@ 
    LINX_(__NR_getuid,            sys_getuid16),       // 24 ## P
 //zz 
 //zz    //   (__NR_stime,             sys_stime),          // 25 * (SVr4,SVID,X/OPEN)
-//   PLAXY(__NR_ptrace,            sys_ptrace),         // 26
+   PLAXY(__NR_ptrace,            sys_ptrace),         // 26
    GENX_(__NR_alarm,             sys_alarm),          // 27
 //zz    //   (__NR_oldfstat,          sys_fstat),          // 28 * L -- obsolete
    GENX_(__NR_pause,             sys_pause),          // 29