struct timeval dtime; /* Delta for system time usage */
struct timeval etime; /* Syscall entry time */
/* Support for tracing forked processes */
- struct tcb *parent; /* Parent of this process */
long baddr; /* `Breakpoint' address */
long inst[2]; /* Instructions on above */
int pfd; /* proc file descriptor */
#define TCB_INUSE 00002 /* This table entry is in use */
#define TCB_INSYSCALL 00004 /* A system call is in progress */
#define TCB_ATTACHED 00010 /* Process is not our own child */
+#ifdef LINUX
+#define TCB_ATTACH_DONE 00020 /* PTRACE_ATTACH was done on this tcb->pid */
+#endif
#define TCB_BPTSET 00100 /* "Breakpoint" set after fork(2) */
#define TCB_SIGTRAPPED 00200 /* Process wanted to block SIGTRAP */
#define TCB_REPRINT 01000 /* We should reprint this syscall on exit */
|| defined(POWERPC) || defined(IA64) || defined(HPPA) \
|| defined(SH) || defined(SH64) || defined(S390) || defined(S390X) \
|| defined(ARM) || defined(MIPS) || defined(BFIN) || defined(TILE)
-# define TCB_WAITEXECVE 04000 /* ignore SIGTRAP after exceve */
+# define TCB_WAITEXECVE 04000 /* ignore SIGTRAP after execve */
# endif
-# define TCB_CLONE_THREAD 010000 /* CLONE_THREAD set in creating syscall */
# include <sys/syscall.h>
# ifndef __NR_exit_group
# /* Hack: Most headers around are too old to have __NR_exit_group. */
#ifdef LINUX
# include <asm/unistd.h>
-# if defined __NR_tgkill
-# define my_tgkill(pid, tid, sig) syscall(__NR_tgkill, (pid), (tid), (sig))
-# elif defined __NR_tkill
-# define my_tgkill(pid, tid, sig) syscall(__NR_tkill, (tid), (sig))
+# if defined __NR_tkill
+# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
# else
/* kill() may choose arbitrarily the target task of the process group
while we later wait on a that specific TID. PID process waits become
TID task specific waits for a process under ptrace(2). */
# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
-# define my_tgkill(pid, tid, sig) kill((tid), (sig))
+# define my_tkill(tid, sig) kill((tid), (sig))
# endif
#endif
for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
tcp = tcbtab[tcbi];
+
if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
continue;
#ifdef LINUX
- if (tcp->flags & TCB_CLONE_THREAD)
+ if (tcp->flags & TCB_ATTACH_DONE)
continue;
#endif
/* Reinitialize the output since it may have changed. */
else {
if (debug)
fprintf(stderr, "attach to pid %d succeeded\n", tid);
- if (tid != tcbtab[tcbi]->pid) {
- tcp = alloctcb(tid);
- tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD;
- tcp->parent = tcbtab[tcbi];
+ if (tid != tcp->pid) {
+ struct tcb *new_tcp = alloctcb(tid);
+ new_tcp->flags |= TCB_ATTACHED|TCB_ATTACH_DONE;
}
}
if (interactive) {
sigprocmask(SIG_SETMASK, &empty_set, NULL);
if (interrupted)
- return;
+ goto ret;
sigprocmask(SIG_BLOCK, &blocked_set, NULL);
}
}
fprintf(stderr, ntid > 1
? "Process %u attached with %u threads - interrupt to quit\n"
: "Process %u attached - interrupt to quit\n",
- tcbtab[tcbi]->pid, ntid);
+ tcp->pid, ntid);
}
continue;
} /* if (opendir worked) */
} /* if (-f) */
-# endif
+# endif /* LINUX */
if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
perror("attach: ptrace(PTRACE_ATTACH, ...)");
droptcb(tcp);
tcp->pid);
} /* for each tcbtab[] */
+ ret:
+#ifdef LINUX
+ /* TCB_ATTACH_DONE flag is used only in this function */
+ for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
+ tcp = tcbtab[tcbi];
+ tcp->flags &= ~TCB_ATTACH_DONE;
+ }
+#endif
+
if (interactive)
sigprocmask(SIG_SETMASK, &empty_set, NULL);
}
/* Shouldn't happen. */
perror("detach: ptrace(PTRACE_DETACH, ...)");
}
- else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
- : tcp->pid),
- tcp->pid, 0) < 0) {
+ else if (my_tkill(tcp->pid, 0) < 0) {
if (errno != ESRCH)
perror("detach: checking sanity");
}
- else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
- ? tcp->parent->pid : tcp->pid),
- tcp->pid, SIGSTOP) < 0) {
+ else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
if (errno != ESRCH)
perror("detach: stopping child");
}
}
}
#ifdef LINUX
- /* If options were not set for this tracee yet */
- if (tcp->parent == NULL) {
- if (ptrace_setoptions) {
- if (debug)
- fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
- if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
- if (errno != ESRCH) {
- /* Should never happen, really */
- perror_msg_and_die("PTRACE_SETOPTIONS");
- }
+ if (ptrace_setoptions) {
+ if (debug)
+ fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
+ if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
+ if (errno != ESRCH) {
+ /* Should never happen, really */
+ perror_msg_and_die("PTRACE_SETOPTIONS");
}
}
}