]> granicus.if.org Git - strace/commitdiff
2003-01-20 Roland McGrath <roland@redhat.com>
authorRoland McGrath <roland@redhat.com>
Mon, 20 Jan 2003 10:23:04 +0000 (10:23 +0000)
committerRoland McGrath <roland@redhat.com>
Mon, 20 Jan 2003 10:23:04 +0000 (10:23 +0000)
* 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.

defs.h
syscall.c

diff --git a/defs.h b/defs.h
index d1bafd828daa33b25a180a9fafce285ae6f7b84b..9889efebbfbb7fe52194c4a9433ac5d0cf9f3f79 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -301,7 +301,7 @@ struct tcb {
 #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) || defined(SH)
+# if defined(ALPHA) || defined(SPARC) || defined(POWERPC) || defined(IA64) || defined(HPPA) || defined(SH) || defined(S390) || defined(S390X)
 #  define TCB_WAITEXECVE 02000 /* ignore SIGTRAP after exceve */
 # endif
 # define TCB_CLONE_DETACHED 04000 /* CLONE_DETACHED set in creating syscall */
index f9e39d4ef0ed1a5a441a700b93625eb44c50a8a4..5b04dc913610f67c125591797bd7b68ed8e03c48 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -730,12 +730,31 @@ struct tcb *tcp;
 #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 @@ struct tcb *tcp;
 
                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 @@ struct tcb *tcp;
                        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)