#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 */
#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.
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
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)