On Thursday 08 October 2009 21:09:22 Mike Frysinger wrote:
> On Thursday 08 October 2009 20:33:31 Frederik Schüler wrote:
> > On Friday 09 October 2009 01:14:13 Dmitry V. Levin wrote:
> > > On sparc, it is defined as "static struct regs regs;"
> > > Nothing has changed in this area since v4.5.18.
> >
> > Yes, still barfing:
> >
> > gcc -DHAVE_CONFIG_H -I. -I.. -Ilinux/sparc -I../linux/sparc -Ilinux
> >  -I../linux -Wall -g -O2 -MT syscall.o -MD -MP -MF .deps/syscall.Tpo -c
> > -o syscall.o ../syscall.c
> > ../syscall.c: In function ‘get_scno’:
> > ../syscall.c:1192: error: invalid use of undefined type ‘struct regs’
> > ../syscall.c:1234: error: invalid use of undefined type ‘struct regs’
> > ../syscall.c:1234: warning: format ‘%08x’ expects type ‘unsigned int’,
> > but argument 3 has type ‘long unsigned int’
> >
> > (sid)f...@smetana:~/strace-4.5.19$ uname -a
> > Linux smetana 2.6.26-2-sparc64-smp #1 SMP Thu Aug 20 16:48:42 UTC 2009
> >  sparc64 GNU/Linux
> > (sid)f...@smetana:~/strace-4.5.19$ gcc --version
> > gcc (Debian 4.3.4-4) 4.3.4
> > Copyright (C) 2008 Free Software Foundation, Inc.
> > This is free software; see the source for copying conditions.  There is
> > NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
> > PURPOSE.
> 
> not related to the running kernel or gcc/glibc.  'struct regs' comes from
> asm/regs*.h which comes from the kernel headers.  2.6.28 and older
>  installed it, but it was killed off as "useless" during 2.6.29
>  development.  presumably you're using newer kernel headers version.
> 
> going by arch/sparc/kernel/ptrace_*.c, looks like it should be switched to
> struct pt_regs as asm/ptrace.h is still installed.

i thought learning another ptrace abi would be neat, so ive converted the code 
from 'struct regs' to 'struct pt_regs', but i think the sparc kernel headers 
are a little wonky here.  if you look at the UREG_XX values, they appear to 
all be off by one, and they declare the o registers as i registers.

compare the 32 and 64 bit versions of struct pt_regs to struct regs and you'll 
see that the fields all line up, but for some reason pt_regs.u_regs[UREG_G0] 
actually refers to g1 as in reg.r_g1.  that is why in the attached patch 
register names get changed.  strace still runs fine, but the new code doesnt 
make me happy.  it should however work on both sparc32 and sparc64 userland.

looking at gdb shows that they use sys/ucontext.h from glibc to provide the 
gregset_t type (which is really just a simple array -- they rely on the size 
being correct for the ptrace call).  this header also provides REG_xx defines 
for sparc32 to index this array and the nice thing is that it appears to 
actually line up correctly -- g1 is g1 and o0 is o0.  the downside is that the 
sparc64 api uses diff define names for indexing (MC_xx), and it apparently 
relies on sparc32 layout (so i guess it assumes PTRACE_GETREGS will always be 
used as opposed to PTRACE_GETREGS64).  you can tell this as the 32bit abi has 
the state/pc regs first followed by the g/o regs while the 64bit abi has the 
state/pc regs after the g/o regs.  in turn, this would prevent a pure 64bit 
kernel and userland combo.

perhaps the sanest thing is to use pt_regs from the kernel, but then define 
our own set of defines for indexing the u_regs array.  call them U_REG_xx to 
avoid conflicting with the header.  and we stick a note in there about why we 
arent using UREG_xx from the kernel.  this way the strace sparc code would 
reflect the calling convention actually in use -- g1 is the syscall number and 
o0..o5.
-mike
diff --git a/process.c b/process.c
index 5d956b0..11f5711 100644
--- a/process.c
+++ b/process.c
@@ -726,10 +726,10 @@ change_syscall(struct tcb *tcp, int new)
 		return -1;
 	return 0;
 #elif defined(SPARC) || defined(SPARC64)
-	struct regs regs;
+	struct pt_regs regs;
 	if (ptrace(PTRACE_GETREGS, tcp->pid, (char*)&regs, 0)<0)
 		return -1;
-	regs.r_g1=new;
+	regs.u_regs[UREG_G0] = new;
 	if (ptrace(PTRACE_SETREGS, tcp->pid, (char*)&regs, 0)<0)
 		return -1;
 	return 0;
diff --git a/signal.c b/signal.c
index 4f3111a..1e47639 100644
--- a/signal.c
+++ b/signal.c
@@ -93,12 +93,7 @@
 #endif /* LINUX && SPARC64 */
 #endif /* HAVE_ASM_REG_H */
 
-#if defined (SPARC) || defined (SPARC64)
-typedef struct {
-	struct regs		si_regs;
-	int			si_mask;
-} m_siginfo_t;
-#elif defined (MIPS)
+#if defined (SPARC) || defined (SPARC64) || defined (MIPS)
 typedef struct {
 	struct pt_regs		si_regs;
 	int			si_mask;
@@ -1408,7 +1403,7 @@ sys_sigreturn(struct tcb *tcp)
 	return 0;
 #elif defined (SPARC) || defined (SPARC64)
 	long i1;
-	struct regs regs;
+	struct pt_regs regs;
 	m_siginfo_t si;
 
 	if(ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
@@ -1417,7 +1412,7 @@ sys_sigreturn(struct tcb *tcp)
 	}
 	if(entering(tcp)) {
 		tcp->u_arg[0] = 0;
-		i1 = regs.r_o1;
+		i1 = regs.u_regs[UREG_I0];
 		if(umove(tcp, i1, &si) < 0) {
 			perror("sigreturn: umove ");
 			return 0;
diff --git a/syscall.c b/syscall.c
index a2e6885..f862405 100644
--- a/syscall.c
+++ b/syscall.c
@@ -42,20 +42,6 @@
 #include <sys/syscall.h>
 #include <sys/param.h>
 
-#if HAVE_ASM_REG_H
-#if defined (SPARC) || defined (SPARC64)
-#  define fpq kernel_fpq
-#  define fq kernel_fq
-#  define fpu kernel_fpu
-#endif
-#include <asm/reg.h>
-#if defined (SPARC) || defined (SPARC64)
-#  undef fpq
-#  undef fq
-#  undef fpu
-#endif
-#endif
-
 #ifdef HAVE_SYS_REG_H
 #include <sys/reg.h>
 #ifndef PTRACE_PEEKUSR
@@ -75,7 +61,6 @@
 #endif
 
 #if defined (LINUX) && defined (SPARC64)
-# define r_pc r_tpc
 # undef PTRACE_GETREGS
 # define PTRACE_GETREGS PTRACE_GETREGS64
 # undef PTRACE_SETREGS
@@ -755,7 +755,7 @@ internal_syscall(struct tcb *tcp)
 #elif defined(AVR32)
 	static struct pt_regs regs;
 #elif defined (SPARC) || defined (SPARC64)
-	static struct regs regs;
+	static struct pt_regs regs;
 	static unsigned long trap;
 #elif defined(LINUX_MIPSN32)
 	static long long a3;
@@ -1189,7 +1189,7 @@ get_scno(struct tcb *tcp)
 	if (!(tcp->flags & TCB_INSYSCALL)) {
 		/* Retrieve the syscall trap instruction. */
 		errno = 0;
-		trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.r_pc, 0);
+		trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
 #  if defined(SPARC64)
 		trap >>= 32;
 #  endif
@@ -1229,9 +1229,9 @@ get_scno(struct tcb *tcp)
 				return 0;
 			}
 #  if defined (SPARC64)
-			fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.r_tpc);
+			fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
 #  else
-			fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc);
+			fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.pc);
 #  endif
 			return -1;
 		}
@@ -1240,10 +1240,10 @@ get_scno(struct tcb *tcp)
 		if (trap == 0x91d02027)
 			scno = 156;
 		else
-			scno = regs.r_g1;
+			scno = regs.u_regs[UREG_G0];
 		if (scno == 0) {
-			scno = regs.r_o0;
-			memmove (&regs.r_o0, &regs.r_o1, 7*sizeof(regs.r_o0));
+			scno = regs.u_regs[UREG_G7];
+			memmove (&regs.u_regs[UREG_G7], &regs.u_regs[UREG_I0], 7*sizeof(regs.u_regs[0]));
 		}
 	}
 # elif defined(HPPA)
@@ -1649,21 +1649,21 @@ get_error(struct tcb *tcp)
 			u_error = 0;
 		}
 # elif defined(SPARC)
-		if (regs.r_psr & PSR_C) {
+		if (regs.psr & PSR_C) {
 			tcp->u_rval = -1;
-			u_error = regs.r_o0;
+			u_error = regs.u_regs[UREG_G7];
 		}
 		else {
-			tcp->u_rval = regs.r_o0;
+			tcp->u_rval = regs.u_regs[UREG_G7];
 			u_error = 0;
 		}
 # elif defined(SPARC64)
-		if (regs.r_tstate & 0x1100000000UL) {
+		if (regs.tstate & 0x1100000000UL) {
 			tcp->u_rval = -1;
-			u_error = regs.r_o0;
+			u_error = regs.u_regs[UREG_G7];
 		}
 		else {
-			tcp->u_rval = regs.r_o0;
+			tcp->u_rval = regs.u_regs[UREG_G7];
 			u_error = 0;
 		}
 # elif defined(HPPA)
@@ -1878,12 +1878,12 @@ force_result(tcp, error, rval)
 	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
 		return -1;
 	if (error) {
-		regs.r_psr |= PSR_C;
-		regs.r_o0 = error;
+		regs.psr |= PSR_C;
+		regs.u_regs[UREG_G7] = error;
 	}
 	else {
-		regs.r_psr &= ~PSR_C;
-		regs.r_o0 = rval;
+		regs.psr &= ~PSR_C;
+		regs.u_regs[UREG_G7] = rval;
 	}
 	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
 		return -1;
@@ -1891,12 +1891,12 @@ force_result(tcp, error, rval)
 	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
 		return -1;
 	if (error) {
-		regs.r_tstate |= 0x1100000000UL;
-		regs.r_o0 = error;
+		regs.tstate |= 0x1100000000UL;
+		regs.u_regs[UREG_G7] = error;
 	}
 	else {
-		regs.r_tstate &= ~0x1100000000UL;
-		regs.r_o0 = rval;
+		regs.tstate &= ~0x1100000000UL;
+		regs.u_regs[UREG_G7] = rval;
 	}
 	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
 		return -1;
@@ -2113,7 +2113,7 @@ syscall_enter(struct tcb *tcp)
 		else
 			tcp->u_nargs = MAX_ARGS;
 		for (i = 0; i < tcp->u_nargs; i++)
-			tcp->u_arg[i] = *((&regs.r_o0) + i);
+			tcp->u_arg[i] = regs.u_regs[UREG_G7 + i];
 	}
 #elif defined (HPPA)
 	{
@@ -2683,10 +2683,10 @@ struct tcb *tcp;
 
 #ifdef LINUX
 #if defined (SPARC) || defined (SPARC64)
-	struct regs regs;
+	struct pt_regs regs;
 	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
 		return -1;
-	val = regs.r_o1;
+	val = regs.u_regs[UREG_I0];
 #elif defined(SH)
 	if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
 		return -1;
diff --git a/util.c b/util.c
index c96eb0a..958d1ce 100644
--- a/util.c
+++ b/util.c
@@ -1180,7 +1180,7 @@ getpc(struct tcb *tcp)
 	if (upeek(tcp, REG_EPC, &pc) < 0)
 		return -1;
 # elif defined(SPARC) || defined(SPARC64)
-	struct regs regs;
+	struct pt_regs regs;
 	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
 		return -1;
 	pc = regs.r_pc;
@@ -1297,12 +1297,12 @@ printcall(struct tcb *tcp)
 	}
 	tprintf("[%08lx] ", pc);
 # elif defined(SPARC) || defined(SPARC64)
-	struct regs regs;
+	struct pt_regs regs;
 	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
 		PRINTBADPC;
 		return;
 	}
-	tprintf("[%08lx] ", regs.r_pc);
+	tprintf("[%08lx] ", regs.pc);
 # elif defined(HPPA)
 	long pc;
 
@@ -1532,17 +1532,17 @@ set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
 
 #  elif defined (SPARC) || defined (SPARC64)
 
-typedef struct regs arg_setup_state;
+typedef struct pt_regs arg_setup_state;
 
 #   define arg_setup(tcp, state) \
     (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
 #   define arg_finish_change(tcp, state) \
     (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
 
-#   define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
-#   define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
-#   define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
-#   define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
+#   define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[UREG_G7], 0)
+#   define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[UREG_I0], 0)
+#   define set_arg0(tcp, state, val) ((state)->u_regs[UREG_G7] = (val), 0)
+#   define set_arg1(tcp, state, val) ((state)->u_regs[UREG_I0] = (val), 0)
 #   define restore_arg0(tcp, state, val) 0
 
 #  else /* other architectures */

Attachment: signature.asc
Description: This is a digitally signed message part.

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Strace-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to