Merge patch from Greg Banks for Linux/SuperH support
diff --git a/CREDITS b/CREDITS
index 7e16aa8..c6070d8 100644
--- a/CREDITS
+++ b/CREDITS
@@ -43,3 +43,4 @@
 	Gaël Roualland <gael.roualland@iname.com>
 	Richard Hirst <rhirst@linuxcare.com>
 	Ganesan Rajagopal <rganesan@myrealbox.com>
+	Greg Banks <gbanks@pocketpenguins.com>
diff --git a/ChangeLog b/ChangeLog
index 64f5ef8..61a9faa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2002-05-01  Wichert Akkerman <wichert@deephackmode.org>
+
+	* configure.in, defs.h, process.c, sock.c, syscall.c, util.c: merge
+	  patch from Greg Banks <gbanks@pocketpenguins.com> for Linux/SuperH
+	  support
+
 2002-04-01  Wichert Akkerman <wichert@deephackmode.org>
 
 	* strace.c: close tcp->outf in droptcb()
diff --git a/configure.in b/configure.in
index b24a868..ca016ee 100644
--- a/configure.in
+++ b/configure.in
@@ -68,6 +68,9 @@
 hppa*|parisc*)
 	arch=hppa
 	;;
+sh)
+	arch=sh
+	;;
 *)
 	AC_MSG_ERROR(this architecture is not yet supported by strace)
 	;;
@@ -76,7 +79,7 @@
 
 # Autoheader trick.  Heh, heh.
 arch_list='
-@@@syms="$syms I386 IA64 M68K SPARC MIPS ALPHA ARM POWERPC S390 HPPA"@@@
+@@@syms="$syms I386 IA64 M68K SPARC MIPS ALPHA ARM POWERPC S390 HPPA SH"@@@
 '
 
 osarch="$opsys"
diff --git a/defs.h b/defs.h
index 3a2142d..e6b3539 100644
--- a/defs.h
+++ b/defs.h
@@ -289,7 +289,7 @@
 #define TCB_FOLLOWFORK	00400	/* Process should have forks followed */
 #define TCB_REPRINT	01000	/* We should reprint this syscall on exit */
 #ifdef LINUX
-# if defined(ALPHA) || defined(SPARC) || defined(POWERPC) || defined(IA64) || defined(HPPA)
+# if defined(ALPHA) || defined(SPARC) || defined(POWERPC) || defined(IA64) || defined(HPPA) || defined(SH)
 #  define TCB_WAITEXECVE 02000	/* ignore SIGTRAP after exceve */
 # endif
 #endif /* LINUX */
diff --git a/process.c b/process.c
index a160982..afc8f4b 100644
--- a/process.c
+++ b/process.c
@@ -6,6 +6,9 @@
  * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *                     Linux for s390 port by D.J. Barrow
  *                    <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
+ * Copyright (c) 2000 PocketPenguins Inc.  Linux for Hitachi SuperH
+ *                    port by Greg Banks <gbanks@pocketpenguins.com>
+
  *
  * All rights reserved.
  *
@@ -530,6 +533,10 @@
 	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new)<0)
 	    	return -1;
 	return 0;
+#elif defined(SH)
+       if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL), new)<0)
+               return -1;
+       return 0;
 #else
 #warning Do not know how to handle change_syscall for this architecture
 #endif /* architecture */
@@ -1223,9 +1230,9 @@
 		}
 	}
 #ifdef LINUX
-#if defined(ALPHA) || defined(SPARC) || defined(POWERPC) || defined(IA64) || defined(HPPA)
+#if defined(ALPHA) || defined(SPARC) || defined(POWERPC) || defined(IA64) || defined(HPPA) || defined(SH)
 	tcp->flags |= TCB_WAITEXECVE;
-#endif /* ALPHA || SPARC || POWERPC */
+#endif /* ALPHA || SPARC || POWERPC || IA64 || HPPA || SH */
 #endif /* LINUX */
 	return 0;
 }
@@ -1910,6 +1917,58 @@
 	{ 4*PT_PC,		"4*PT_PC"				},
 #endif /* M68K */
 #endif /* !I386 */
+#ifdef SH
+       { 4*REG_REG0,           "4*REG_REG0"                            },
+       { 4*(REG_REG0+1),       "4*REG_REG1"                            },
+       { 4*(REG_REG0+2),       "4*REG_REG2"                            },
+       { 4*(REG_REG0+3),       "4*REG_REG3"                            },
+       { 4*(REG_REG0+4),       "4*REG_REG4"                            },
+       { 4*(REG_REG0+5),       "4*REG_REG5"                            },
+       { 4*(REG_REG0+6),       "4*REG_REG6"                            },
+       { 4*(REG_REG0+7),       "4*REG_REG7"                            },
+       { 4*(REG_REG0+8),       "4*REG_REG8"                            },
+       { 4*(REG_REG0+9),       "4*REG_REG9"                            },
+       { 4*(REG_REG0+10),      "4*REG_REG10"                           },
+       { 4*(REG_REG0+11),      "4*REG_REG11"                           },
+       { 4*(REG_REG0+12),      "4*REG_REG12"                           },
+       { 4*(REG_REG0+13),      "4*REG_REG13"                           },
+       { 4*(REG_REG0+14),      "4*REG_REG14"                           },
+       { 4*REG_REG15,          "4*REG_REG15"                           },
+       { 4*REG_PC,             "4*REG_PC"                              },
+       { 4*REG_PR,             "4*REG_PR"                              },
+       { 4*REG_SR,             "4*REG_SR"                              },
+       { 4*REG_GBR,            "4*REG_GBR"                             },
+       { 4*REG_MACH,           "4*REG_MACH"                            },
+       { 4*REG_MACL,           "4*REG_MACL"                            },
+       { 4*REG_SYSCALL,        "4*REG_SYSCALL"                         },
+       { 4*REG_FPUL,           "4*REG_FPUL"                            },
+       { 4*REG_FPREG0,         "4*REG_FPREG0"                          },
+       { 4*(REG_FPREG0+1),     "4*REG_FPREG1"                          },
+       { 4*(REG_FPREG0+2),     "4*REG_FPREG2"                          },
+       { 4*(REG_FPREG0+3),     "4*REG_FPREG3"                          },
+       { 4*(REG_FPREG0+4),     "4*REG_FPREG4"                          },
+       { 4*(REG_FPREG0+5),     "4*REG_FPREG5"                          },
+       { 4*(REG_FPREG0+6),     "4*REG_FPREG6"                          },
+       { 4*(REG_FPREG0+7),     "4*REG_FPREG7"                          },
+       { 4*(REG_FPREG0+8),     "4*REG_FPREG8"                          },
+       { 4*(REG_FPREG0+9),     "4*REG_FPREG9"                          },
+       { 4*(REG_FPREG0+10),    "4*REG_FPREG10"                         },
+       { 4*(REG_FPREG0+11),    "4*REG_FPREG11"                         },
+       { 4*(REG_FPREG0+12),    "4*REG_FPREG12"                         },
+       { 4*(REG_FPREG0+13),    "4*REG_FPREG13"                         },
+       { 4*(REG_FPREG0+14),    "4*REG_FPREG14"                         },
+       { 4*REG_FPREG15,        "4*REG_FPREG15"                         },
+       { 4*REG_XDREG0,         "4*REG_XDREG0"                          },
+       { 4*(REG_XDREG0+2),     "4*REG_XDREG2"                          },
+       { 4*(REG_XDREG0+4),     "4*REG_XDREG4"                          },
+       { 4*(REG_XDREG0+6),     "4*REG_XDREG6"                          },
+       { 4*(REG_XDREG0+8),     "4*REG_XDREG8"                          },
+       { 4*(REG_XDREG0+10),    "4*REG_XDREG10"                         },
+       { 4*(REG_XDREG0+12),    "4*REG_XDREG12"                         },
+       { 4*REG_XDREG14,        "4*REG_XDREG14"                         },
+       { 4*REG_FPSCR,          "4*REG_FPSCR"                           },
+#endif /* SH */
+
 #if !defined(S390) && !defined(MIPS)
 	{ uoff(u_fpvalid),	"offsetof(struct user, u_fpvalid)"	},
 #endif
@@ -1926,7 +1985,7 @@
 	{ uoff(start_code),	"offsetof(struct user, start_code)"	},
 	{ uoff(start_stack),	"offsetof(struct user, start_stack)"	},
 	{ uoff(signal),		"offsetof(struct user, signal)"		},
-#if !defined(S390) && !defined(MIPS)
+#if !defined(S390) && !defined(MIPS) && !defined(SH)
 	{ uoff(reserved),	"offsetof(struct user, reserved)"	},
 #endif
 	{ uoff(u_ar0),		"offsetof(struct user, u_ar0)"		},
diff --git a/sock.c b/sock.c
index 327a3de..6d494b7 100644
--- a/sock.c
+++ b/sock.c
@@ -35,7 +35,7 @@
 #include <sys/sockio.h>
 #endif
 
-#ifdef ALPHA
+#if defined (ALPHA) || defined(SH)
 #ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
 #elif defined(HAVE_IOCTLS_H)
diff --git a/syscall.c b/syscall.c
index 95c4bad..dfad8f0 100644
--- a/syscall.c
+++ b/syscall.c
@@ -684,6 +684,9 @@
 	static long pc;
 #elif defined(HPPA)
 	static long r28;
+#elif defined(SH)
+       static long r0;
+
 #endif 
 #endif /* LINUX */
 #ifdef FREEBSD
@@ -873,11 +876,44 @@
 			return 0;
 		}
 	}
-#endif 
+#elif defined(SH)
+       /*
+        * In the new syscall ABI, the system call number is in R3.
+        */
+       if (upeek(pid, 4*(REG_REG0+3), &scno) < 0)
+               return -1;
+
+       if (scno < 0) {
+           /* Odd as it may seem, a glibc bug has been known to cause
+              glibc to issue bogus negative syscall numbers.  So for
+              our purposes, make strace print what it *should* have been */
+           long correct_scno = (scno & 0xff);
+           if (debug)
+               fprintf(stderr,
+                   "Detected glibc bug: bogus system call number = %ld,
+correcting to %ld\n",
+                   scno,
+                   correct_scno);
+           scno = correct_scno;
+       }
+
+
+       if (!(tcp->flags & TCB_INSYSCALL)) {
+               /* Check if we return from execve. */
+               if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
+                       tcp->flags &= ~TCB_WAITEXECVE;
+                       return 0;
+               }
+       }
+#endif /* SH */
 #endif /* LINUX */
 #ifdef SUNOS4
 	if (upeek(pid, uoff(u_arg[7]), &scno) < 0)
 		return -1;
+#elif defined(SH)
+       /* new syscall ABI returns result in R0 */
+       if (upeek(pid, 4*REG_REG0, (long *)&r0) < 0)
+               return -1;
 #endif
 #ifdef USE_PROCFS
 #ifdef HAVE_PR_SYSCALL
@@ -1152,6 +1188,18 @@
 			tcp->u_rval = r28;
 			u_error = 0;
 		}
+#else
+#ifdef SH
+               /* interpret R0 as return value or error number */
+               if (r0 && (unsigned) -r0 < nerrnos) {
+                       tcp->u_rval = -1;
+                       u_error = -r0;
+               }
+               else {
+                       tcp->u_rval = r0;
+                       u_error = 0;
+               }
+#endif /* SH */
 #endif /* HPPA */
 #endif /* SPARC */
 #endif /* ALPHA */
@@ -1378,6 +1426,20 @@
 				return -1;
 		}
 	}
+#elif defined(SH)
+       {
+               int i; 
+               static int syscall_regs[] = {
+                   REG_REG0+4, REG_REG0+5, REG_REG0+6, REG_REG0+7,
+                   REG_REG0, REG_REG0+1, REG_REG0+2
+                   };
+
+               tcp->u_nargs = sysent[tcp->scno].nargs;
+               for (i = 0; i < tcp->u_nargs; i++) {
+                       if (upeek(pid, 4*syscall_regs[i], &tcp->u_arg[i]) < 0)
+                               return -1;
+               }
+        }
 #else /* Other architecture (like i386) (32bits specific) */
 	{
 		int i;
diff --git a/util.c b/util.c
index c59d25a..3d4fee3 100644
--- a/util.c
+++ b/util.c
@@ -955,6 +955,9 @@
 #elif defined(HPPA)
 	if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
 		return -1;
+#elif defined(SH)
+       if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
+               return -1;
 #endif
 	return pc;
 #endif /* LINUX */
@@ -1054,6 +1057,14 @@
 		return;
 	}
 	tprintf("[%08lx] ", pc);
+#elif defined(SH)
+       long pc;
+
+       if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
+               tprintf ("[????????] ");
+               return;
+       }
+       tprintf("[%08lx] ", pc);
 #endif /* !architecture */
 #endif /* LINUX */
 
@@ -1217,6 +1228,12 @@
 #define LOOP	0xa7f40000	/* BRC 15,0 */
 #elif defined(HPPA)
 #define LOOP	0xe81f1ff7	/* b,l,n <loc>,r0 */
+#elif defined(SH)
+#ifdef __LITTLE_ENDIAN__
+#define LOOP   0x0000affe
+#else
+#define LOOP   0xfeaf0000
+#endif
 #else
 #error unknown architecture
 #endif
@@ -1247,6 +1264,9 @@
 	if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
 		return -1;
 	tcp->baddr &= ~0x03;
+#elif defined(SH)
+       if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
+               return -1;
 #else
 #error unknown architecture
 #endif
@@ -1336,6 +1356,8 @@
 	long pc;
 #elif defined(HPPA)
 	long iaoq;
+#elif defined(SH)
+       long pc;
 #endif /* architecture */
 
 #ifdef SPARC
@@ -1493,6 +1515,17 @@
 	 */
 	ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
 	ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
+#elif defined(SH)
+       if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
+               return -1;
+        if (pc != tcp->baddr) {
+                /* The breakpoint has not been reached yet.  */
+                if (debug)
+                        fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
+                                pc, tcp->baddr);
+                return 0;
+        }
+
 #endif /* arch */
 #endif /* !SPARC && !IA64 */
 #endif /* LINUX */