2003-01-20  Roland McGrath  <roland@redhat.com>

	* defs.h [LINUX] [S390 || S390X] (TCB_WAITEXECVE): Define it.
	* syscall.c (get_scno, syscall_fixup) [LINUX] [S390 || S390X]: Handle
	TCB_WAITEXECVE state with special kludges.
diff --git a/syscall.c b/syscall.c
index f9e39d4..5b04dc9 100644
--- a/syscall.c
+++ b/syscall.c
@@ -730,12 +730,31 @@
 #if defined(S390) || defined(S390X)
 	if (upeek(pid, PT_GPR2, &syscall_mode) < 0)
 		return -1;
-	if (syscall_mode != -ENOSYS){
+	if (syscall_mode != -ENOSYS) {
 		/*
 		 * Since kernel version 2.5.44 the scno gets passed in gpr2.
 		 */
 		scno = syscall_mode;
 	}
+	if (tcp->flags & TCB_WAITEXECVE) {
+		/*
+		 * When the execve system call completes successfully, the
+		 * new process still has -ENOSYS (old style) or __NR_execve
+		 * (new style) in gpr2.  We cannot recover the scno again
+		 * by disassembly, because the image that executed the
+		 * syscall is gone now.  Fortunately, we don't want it.  We
+		 * leave the flag set so that syscall_fixup can fake the
+		 * result.
+		 */
+		if (tcp->flags & TCB_INSYSCALL)
+			return 1;
+		/*
+		 * This is the SIGTRAP after execve.  We cannot try to read
+		 * the system call here either.
+		 */
+		tcp->flags &= ~TCB_WAITEXECVE;
+		return 0;
+	}
 	else {
 	       	/*
 		 * Old style of "passing" the scno via the SVC instruction.
@@ -750,9 +769,12 @@
 
 		if (upeek(pid, PT_PSWADDR, &pc) < 0)
 			return -1;
+		errno = 0;
 		opcode = ptrace(PTRACE_PEEKTEXT, pid, (char *)(pc-sizeof(long)), 0);
-		if (errno)
+		if (errno) {
+			perror("peektext(pc-oneword)");
 			return -1;
+		}
 
 		/*
 		 *  We have to check if the SVC got executed directly or via an
@@ -1202,6 +1224,15 @@
 			fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
 		return 0;
 	}
+	else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
+		  == (TCB_INSYSCALL|TCB_WAITEXECVE))
+		 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
+		/*
+		 * Fake a return value of zero.  We leave the TCB_WAITEXECVE
+		 * flag set for the post-execve SIGTRAP to see and reset.
+		 */
+		gpr2 = 0;
+	}
 #elif defined (POWERPC)
 # define SO_MASK 0x10000000
 	if (upeek(pid, sizeof(unsigned long)*PT_CCR, &flags) < 0)