From b3b9cf7dc1912c4df8c9d8dd740144dab8050bff Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 30 May 2020 23:18:42 +0200 Subject: Add support for tracing threads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- common.h | 3 +++ sctrace.c | 16 ++++++++++++---- util.c | 15 +++++++++++---- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/common.h b/common.h index 996b9ef..d3df014 100644 --- a/common.h +++ b/common.h @@ -67,8 +67,10 @@ enum type { enum state { Normal, Syscall, + CloneChild, ForkChild, VforkChild, + CloneParent, ForkParent, VforkParent, Exec @@ -76,6 +78,7 @@ enum state { struct process { pid_t pid; + pid_t thread_group_leader; struct process *next; struct process *prev; enum state state; diff --git a/sctrace.c b/sctrace.c index f027a77..65216a5 100644 --- a/sctrace.c +++ b/sctrace.c @@ -8,7 +8,7 @@ char *argv0; static void usage(void) { - fprintf(stderr, "usage: %s [-o trace-output-file] [-f] (command | -0 command argv0) [argument] ...\n", argv0); + fprintf(stderr, "usage: %s [-o trace-output-file] [-ft] (command | -0 command argv0) [argument] ...\n", argv0); exit(1); } @@ -42,6 +42,7 @@ handle_syscall(struct process *proc) break; case Syscall: + case CloneParent: case ForkParent: /* Get system call result */ if (ptrace(PTRACE_GETREGS, proc->pid, NULL, ®s)) @@ -82,6 +83,7 @@ handle_syscall(struct process *proc) proc->state = Syscall; break; + case CloneChild: case ForkChild: case VforkChild: tprintf(proc, "= 0\n"); @@ -104,7 +106,6 @@ main(int argc, char **argv) struct process *proc, *proc2; unsigned long int event; - /* TODO add option to trace threads (-t) */ /* TODO add option to trace signals (-s) */ ARGBEGIN { case '0': @@ -118,6 +119,9 @@ main(int argc, char **argv) case 'f': trace_options |= PTRACE_O_TRACEFORK; trace_options |= PTRACE_O_TRACEVFORK; + /* fall through */ + case 't': + trace_options |= PTRACE_O_TRACECLONE; multiprocess = 1; break; default: @@ -226,20 +230,24 @@ have_outfp: tprintf(proc, "\nProcess stopped by vfork until child exits or exec(2)s\n"); /* fall thought */ case PTRACE_EVENT_FORK: + case PTRACE_EVENT_CLONE: if (ptrace(PTRACE_GETEVENTMSG, proc->pid, NULL, &event)) eprintf("ptrace PTRACE_GETEVENTMSG %ju NULL :", (uintmax_t)proc->pid); proc2 = add_process((pid_t)event, trace_options); + if (trace_event == PTRACE_EVENT_CLONE) + proc2->thread_group_leader = proc->pid; proc->ret = event; if (trace_event == PTRACE_EVENT_VFORK) { proc2->continue_on_exit = proc; proc->vfork_waiting_on = proc2; proc->state = VforkParent; } else { - proc->state = ForkParent; + proc->state = trace_event == PTRACE_EVENT_CLONE ? CloneParent : ForkParent; handle_syscall(proc); } tprintf(proc2, "\nTracing new process\n"); - proc2->state = trace_event == PTRACE_EVENT_FORK ? ForkChild : VforkChild; + proc2->state = trace_event == PTRACE_EVENT_FORK ? ForkChild : + trace_event == PTRACE_EVENT_VFORK ? VforkChild : CloneChild; handle_syscall(proc2); break; diff --git a/util.c b/util.c index 7ee9c51..521f73a 100644 --- a/util.c +++ b/util.c @@ -25,10 +25,17 @@ tprintf(struct process *proc, const char *fmt, ...) fmt = &fmt[1]; } if (multiproctrace) { - if (last_char == '\n') - fprintf(trace_fp, "[%ju] ", (uintmax_t)proc->pid); - else if (proc->pid != last_pid) - fprintf(trace_fp, "\n[%ju] ", (uintmax_t)proc->pid); + if (proc->thread_group_leader) { + if (last_char == '\n') + fprintf(trace_fp, "[%ju, %ju] ", (uintmax_t)proc->thread_group_leader, (uintmax_t)proc->pid); + else if (proc->pid != last_pid) + fprintf(trace_fp, "\n[%ju, %ju] ", (uintmax_t)proc->thread_group_leader, (uintmax_t)proc->pid); + } else { + if (last_char == '\n') + fprintf(trace_fp, "[%ju] ", (uintmax_t)proc->pid); + else if (proc->pid != last_pid) + fprintf(trace_fp, "\n[%ju] ", (uintmax_t)proc->pid); + } } va_start(ap, fmt); vfprintf(trace_fp, fmt, ap); -- cgit v1.2.3-70-g09d2