Remove building with NOCRYPTO option
[minix.git] / minix / usr.bin / trace / trace.c
blob0c50caa6ab51b35086a411d4039c6707d4c5ab54
1 /* trace(1) - the MINIX3 system call tracer - by D.C. van Moolenbroek */
3 #include "inc.h"
5 #include <signal.h>
6 #include <sys/wait.h>
7 #include <unistd.h>
8 #include <err.h>
10 /* Global variables, used only for a subset of the command line options. */
11 int timestamps; /* 0 = none, 1 = time w/o usecs, 2 = time w/usecs */
12 int allnames; /* FALSE = structure field names, TRUE = all names */
13 unsigned int valuesonly; /* 0 = normal, 1 = no symbols, 2 = no structures */
14 unsigned int verbose; /* 0 = essentials, 1 = elaborate, 2 = everything */
16 /* Local variables, for signal handling. */
17 static int got_signal, got_info;
20 * Signal handler for signals that are supposed to make us terminate. Let the
21 * main loop do the actual work, since it might be in the middle of processing
22 * a process status change right now.
24 static void
25 sig_handler(int __unused sig)
28 got_signal = TRUE;
33 * Signal handler for the SIGINFO signal. Let the main loop report on all
34 * processes currenty being traced. Since SIGINFO is sent to the current
35 * process group, traced children may get the signal as well. This is both
36 * intentional and impossible to prevent.
38 static void
39 info_handler(int __unused sig)
42 got_info = TRUE;
46 * Print a list of traced processes and their call status. We must not
47 * interfere with actual process output, so perform out-of-band printing
48 * (with info lines rather than lines prefixed by each process's PID).
50 static void
51 list_info(void)
53 struct trace_proc *proc;
54 int no_call, in_call;
56 put_newline();
58 for (proc = proc_next(NULL); proc != NULL; proc = proc_next(proc)) {
60 * When attaching to an existing process, there is no way to
61 * find out whether the process is in a system call or not.
63 no_call = (proc->trace_flags & TF_NOCALL);
64 in_call = (proc->trace_flags & TF_INCALL);
65 assert(!in_call || !no_call);
67 put_fmt(NULL, "Tracing %s (pid %d), %s%s%s", proc->name,
68 proc->pid, no_call ? "call status unknown" :
69 (in_call ? "in a " : "not in a call"),
70 in_call ? call_name(proc) : "",
71 in_call ? " call" : "");
72 put_newline();
77 * Either we have just started or attached to the given process, it the process
78 * has performed a successful execve() call. Obtain the new process name, and
79 * print a banner for it.
81 static void
82 new_exec(struct trace_proc * proc)
85 /* Failure to obtain the process name is worrisome, but not fatal.. */
86 if (kernel_get_name(proc->pid, proc->name, sizeof(proc->name)) < 0)
87 strlcpy(proc->name, "<unknown>", sizeof(proc->name));
89 put_newline();
90 put_fmt(proc, "Tracing %s (pid %d)", proc->name, proc->pid);
91 put_newline();
95 * We have started or attached to a process. Set the appropriate flags, and
96 * print a banner showing that we are now tracing it.
98 static void
99 new_proc(struct trace_proc * proc, int follow_fork)
101 int fl;
103 /* Set the desired tracing options. */
104 fl = TO_ALTEXEC;
105 if (follow_fork) fl |= TO_TRACEFORK;
107 (void)ptrace(T_SETOPT, proc->pid, 0, fl);
110 * When attaching to an arbitrary process, this process might be in the
111 * middle of an execve(). Now that we have enabled TO_ALTEXEC, we may
112 * now get a SIGSTOP signal next. Guard against this by marking the
113 * first system call as a possible execve().
115 if ((proc->trace_flags & (TF_ATTACH | TF_STOPPING)) == TF_ATTACH)
116 proc->trace_flags |= TF_EXEC;
118 new_exec(proc);
122 * A process has terminated or is being detached. Print the resulting status.
124 static void
125 discard_proc(struct trace_proc * proc, int status)
127 const char *signame;
130 * The exit() calls are of type no-return, meaning they are expected
131 * not to return. However, calls of this type may in fact return an
132 * error, in which case the error must be printed. Thus, such calls
133 * are not actually finished until the end of the call-leave phase.
134 * For exit() calls, a successful call will never get to the call-leave
135 * phase. The result is that such calls will end up being shown as
136 * suspended, which is unintuitive. To counter this, we pretend that a
137 * clean process exit is in fact preceded by a call-leave event, thus
138 * allowing the call to be printed without suspension. An example:
140 * 3| exit(0) <..>
141 * 2| setsid() = 2
142 * [A] 3| exit(0)
143 * 3| Process exited normally with code 0
145 * The [A] line is the result of the following code.
147 if (WIFEXITED(status) && (proc->trace_flags & TF_INCALL))
148 call_leave(proc, TRUE /*skip*/);
150 put_newline();
151 if (WIFEXITED(status)) {
152 put_fmt(proc, "Process exited normally with code %d",
153 WEXITSTATUS(status));
154 } else if (WIFSIGNALED(status)) {
155 if ((signame = get_signal_name(WTERMSIG(status))) != NULL)
156 put_fmt(proc, "Process terminated from signal %s",
157 signame);
158 else
159 put_fmt(proc, "Process terminated from signal %d",
160 WTERMSIG(status));
161 } else if (WIFSTOPPED(status))
162 put_text(proc, "Process detached");
163 else
164 put_fmt(proc, "Bogus wait result (%04x)", status);
165 put_newline();
167 proc_del(proc);
171 * The given process has been stopped on a system call, either entering or
172 * leaving that call.
174 static void
175 handle_call(struct trace_proc * proc, int show_stack)
177 reg_t pc, sp;
178 int class, skip, new_ctx;
180 proc->trace_flags &= ~TF_NOCALL;
182 if (proc->trace_flags & TF_SKIP) {
183 /* Skip the call leave phase after a successful execve(). */
184 proc->trace_flags &= ~(TF_INCALL | TF_SKIP);
185 } else if (!(proc->trace_flags & TF_INCALL)) {
187 * The call_enter call returns the class of the call:
188 * TC_NORMAL, TC_EXEC, or TC_SIGRET. TC_EXEC means that an
189 * execve() call is being performed. This means that if a
190 * SIGSTOP follows for the current process, the process has
191 * successfully started a different executable. TC_SIGRET
192 * means that if successful, the call will have a bogus return
193 * value. TC_NORMAL means that the call requires no exception.
195 class = call_enter(proc, show_stack);
197 switch (class) {
198 case TC_NORMAL:
199 break;
200 case TC_EXEC:
201 proc->trace_flags |= TF_EXEC;
202 break;
203 case TC_SIGRET:
204 proc->trace_flags |= TF_CTX_SKIP;
205 break;
206 default:
207 assert(0);
210 /* Save the current program counter and stack pointer. */
211 if (!kernel_get_context(proc->pid, &pc, &sp, NULL /*fp*/)) {
212 proc->last_pc = pc;
213 proc->last_sp = sp;
214 } else
215 proc->last_pc = proc->last_sp = 0;
217 proc->trace_flags |= TF_INCALL;
218 } else {
220 * Check if the program counter or stack pointer have changed
221 * during the system call. If so, this is a strong indication
222 * that a sigreturn call has succeeded, and thus its result
223 * must be skipped, since the result register will not contain
224 * the result of the call.
226 new_ctx = (proc->last_pc != 0 &&
227 !kernel_get_context(proc->pid, &pc, &sp, NULL /*fp*/) &&
228 (pc != proc->last_pc || sp != proc->last_sp));
230 skip = ((proc->trace_flags & TF_CTX_SKIP) && new_ctx);
232 call_leave(proc, skip);
235 * On such context changes, also print a short dashed line.
236 * This helps in identifying signal handler invocations,
237 * although it is not reliable for that purpose: no dashed line
238 * will be printed if a signal handler is invoked while the
239 * process is not making a system call.
241 if (new_ctx) {
242 put_text(proc, "---");
243 put_newline();
246 proc->trace_flags &= ~(TF_INCALL | TF_CTX_SKIP | TF_EXEC);
251 * The given process has received the given signal. Report the receipt. Due
252 * to the way that signal handling with traced processes works, the signal may
253 * in fact be delivered to the process much later, or never--a problem inherent
254 * to the way signals are handled in PM right now (namely, deferring signal
255 * delivery would let the traced process block signals meant for the tracer).
257 static void
258 report_signal(struct trace_proc * proc, int sig, int show_stack)
260 const char *signame;
263 * Print a stack trace only if we are not in a call; otherwise, we
264 * would simply get the same stack trace twice and mess up the output
265 * in the process, because call suspension is not expected if we are
266 * tracing a single process only.
267 * FIXME: the check should be for whether we actually print the call..
269 if (show_stack && !(proc->trace_flags & TF_INCALL))
270 kernel_put_stacktrace(proc);
273 * If this process is in the middle of a call, the signal will be
274 * printed within the call. This will always happen on the call split,
275 * that is, between the call's entering (out) and leaving (in) phases.
276 * This also means that the recording of the call-enter phase may be
277 * replayed more than once, and the call may be suspended more than
278 * once--after all, a signal is not necessarily followed immediately
279 * by the call result. If the process is not in the middle of a call,
280 * the signal will end up on a separate line. In both cases, multiple
281 * consecutive signals may be printed right after one another. The
282 * following scenario shows a number of possible combinations:
284 * 2| foo(<..>
285 * 3| ** SIGHUP ** ** SIGUSR1 **
286 * 3| bar() = <..>
287 * 2|*foo(** SIGUSR1 ** ** SIGUSR2 ** <..>
288 * 3|*bar() = ** SIGCHLD ** 0
289 * 2|*foo(** SIGINT ** &0xef852000) = -1 [EINTR]
290 * 3| kill(3, SIGTERM) = ** SIGTERM ** <..>
291 * 3| Process terminated from signal SIGTERM
294 call_replay(proc);
296 if (!valuesonly && (signame = get_signal_name(sig)) != NULL)
297 put_fmt(proc, "** %s **", signame);
298 else
299 put_fmt(proc, "** SIGNAL %d **", sig);
301 put_space(proc);
303 output_flush();
307 * Wait for the given process ID to stop on the given signal. Upon success,
308 * the function will return zero. Upon failure, it will return -1, and errno
309 * will be either set to an error code, or to zero in order to indicate that
310 * the process exited instead.
312 static int
313 wait_sig(pid_t pid, int sig)
315 int status;
317 for (;;) {
318 if (waitpid(pid, &status, 0) == -1) {
319 if (errno == EINTR) continue;
321 return -1;
324 if (!WIFSTOPPED(status)) {
325 /* The process terminated just now. */
326 errno = 0;
328 return -1;
331 if (WSTOPSIG(status) == sig)
332 break;
334 (void)ptrace(T_RESUME, pid, 0, WSTOPSIG(status));
337 return 0;
341 * Attach to the given process, and wait for the resulting SIGSTOP signal.
342 * Other signals may arrive first; we pass these on to the process without
343 * reporting them, thus logically modelling them as having arrived before we
344 * attached to the process. The process might also exit in the meantime,
345 * typically as a result of a lethal signal; following the same logical model,
346 * we pretend the process did not exist in the first place. Since the SIGSTOP
347 * signal will be pending right after attaching to the process, this procedure
348 * will never block.
350 static int
351 attach(pid_t pid)
354 if (ptrace(T_ATTACH, pid, 0, 0) != 0) {
355 warn("Unable to attach to pid %d", pid);
357 return -1;
360 if (wait_sig(pid, SIGSTOP) != 0) {
361 /* If the process terminated, report it as not found. */
362 if (errno == 0)
363 errno = ESRCH;
365 warn("Unable to attach to pid %d", pid);
367 return -1;
370 /* Verify that we can read values from the kernel at all. */
371 if (kernel_check(pid) == FALSE) {
372 (void)ptrace(T_DETACH, pid, 0, 0);
374 warnx("Kernel magic check failed, recompile trace(1)");
376 return -1;
380 * System services are managed by RS, which prevents them from
381 * being traced properly by PM. Attaching to a service could
382 * therefore cause problems, so we should detach immediately.
384 if (kernel_is_service(pid) == TRUE) {
385 (void)ptrace(T_DETACH, pid, 0, 0);
387 warnx("Cannot attach to system services!");
389 return -1;
392 return 0;
396 * Detach from all processes, knowning that they were all processes to which we
397 * attached explicitly (i.e., not started by us) and are all currently stopped.
399 static void
400 detach_stopped(void)
402 struct trace_proc *proc;
404 for (proc = proc_next(NULL); proc != NULL; proc = proc_next(proc))
405 (void)ptrace(T_DETACH, proc->pid, 0, 0);
409 * Start detaching from all processes to which we previously attached. The
410 * function is expected to return before detaching is completed, and the caller
411 * must deal with the new situation appropriately. Do not touch any processes
412 * started by us (to allow graceful termination), unless force is set, in which
413 * case those processes are killed.
415 static void
416 detach_running(int force)
418 struct trace_proc *proc;
420 for (proc = proc_next(NULL); proc != NULL; proc = proc_next(proc)) {
421 if (proc->trace_flags & TF_ATTACH) {
422 /* Already detaching? Then do nothing. */
423 if (proc->trace_flags & TF_DETACH)
424 continue;
426 if (!(proc->trace_flags & TF_STOPPING))
427 (void)kill(proc->pid, SIGSTOP);
429 proc->trace_flags |= TF_DETACH | TF_STOPPING;
430 } else {
432 * The child processes may be ignoring SIGINTs, so upon
433 * the second try, force them to terminate.
435 if (force)
436 (void)kill(proc->pid, SIGKILL);
442 * Print command usage.
444 static void __dead
445 usage(void)
448 (void)fprintf(stderr, "usage: %s [-fgNstVv] [-o file] [-p pid] "
449 "[command]\n", getprogname());
451 exit(EXIT_FAILURE);
455 * The main function of the system call tracer.
458 main(int argc, char * argv[])
460 struct trace_proc *proc;
461 const char *output_file;
462 int status, sig, follow_fork, show_stack, grouping, first_signal;
463 pid_t pid, last_pid;
464 int c, error;
466 setprogname(argv[0]);
468 proc_init();
470 follow_fork = FALSE;
471 show_stack = FALSE;
472 grouping = FALSE;
473 output_file = NULL;
475 timestamps = 0;
476 allnames = FALSE;
477 verbose = 0;
478 valuesonly = 0;
480 while ((c = getopt(argc, argv, "fgNstVvo:p:")) != -1) {
481 switch (c) {
482 case 'f':
483 follow_fork = TRUE;
484 break;
485 case 'g':
486 grouping = TRUE;
487 break;
488 case 'N':
489 allnames = TRUE;
490 break;
491 case 's':
492 show_stack = TRUE;
493 break;
494 case 't':
495 timestamps++;
496 break;
497 case 'V':
498 valuesonly++;
499 break;
500 case 'v':
501 verbose++;
502 break;
503 case 'o':
504 output_file = optarg;
505 break;
506 case 'p':
507 pid = atoi(optarg);
508 if (pid <= 0)
509 usage();
511 if (proc_get(pid) == NULL && proc_add(pid) == NULL)
512 err(EXIT_FAILURE, NULL);
514 break;
515 default:
516 usage();
520 argv += optind;
521 argc -= optind;
523 first_signal = TRUE;
524 got_signal = FALSE;
525 got_info = FALSE;
527 signal(SIGINT, sig_handler);
528 signal(SIGINFO, info_handler);
530 /* Attach to any processes for which PIDs were given. */
531 for (proc = proc_next(NULL); proc != NULL; proc = proc_next(proc)) {
532 if (attach(proc->pid) != 0) {
534 * Detach from the processes that we have attached to
535 * so far, i.e. the ones with the TF_ATTACH flag.
537 detach_stopped();
539 return EXIT_FAILURE;
542 proc->trace_flags = TF_ATTACH | TF_NOCALL;
545 /* If a command is given, start a child that executes the command. */
546 if (argc >= 1) {
547 pid = fork();
549 switch (pid) {
550 case -1:
551 warn("Unable to fork");
553 detach_stopped();
555 return EXIT_FAILURE;
557 case 0:
558 (void)ptrace(T_OK, 0, 0, 0);
560 (void)execvp(argv[0], argv);
562 err(EXIT_FAILURE, "Unable to start %s", argv[0]);
564 default:
565 break;
569 * The first signal will now be SIGTRAP from the execvp(),
570 * unless that fails, in which case the child will terminate.
572 if (wait_sig(pid, SIGTRAP) != 0) {
574 * If the child exited, the most likely cause is a
575 * failure to execute the command. Let the child
576 * report the error, and do not say anything here.
578 if (errno != 0)
579 warn("Unable to start process");
581 detach_stopped();
583 return EXIT_FAILURE;
586 /* If we haven't already, perform the kernel magic check. */
587 if (proc_count() == 0 && kernel_check(pid) == FALSE) {
588 warnx("Kernel magic check failed, recompile trace(1)");
590 (void)kill(pid, SIGKILL);
592 detach_stopped();
594 return EXIT_FAILURE;
597 if ((proc = proc_add(pid)) == NULL) {
598 warn(NULL);
600 (void)kill(pid, SIGKILL);
602 detach_stopped();
604 return EXIT_FAILURE;
607 proc->trace_flags = 0;
608 } else
609 pid = -1;
611 /* The user will have to give us at least one process to trace. */
612 if (proc_count() == 0)
613 usage();
616 * Open an alternative output file if needed. After that, standard
617 * error should no longer be used directly, and all output has to go
618 * through the output module.
620 if (output_init(output_file) < 0) {
621 warn("Unable to open output file");
623 if (pid > 0)
624 (void)kill(pid, SIGKILL);
626 detach_stopped();
628 return EXIT_FAILURE;
632 * All the traced processes are currently stopped. Initialize, report,
633 * and resume them.
635 for (proc = proc_next(NULL); proc != NULL; proc = proc_next(proc)) {
636 new_proc(proc, follow_fork);
638 (void)ptrace(T_SYSCALL, proc->pid, 0, 0);
642 * Handle events until there are no traced processes left.
644 last_pid = 0;
645 error = FALSE;
647 for (;;) {
648 /* If an output error occurred, exit as soon as possible. */
649 if (!error && output_error()) {
650 detach_running(TRUE /*force*/);
652 error = TRUE;
656 * If the user pressed ^C once, start detaching the processes
657 * that we did not start, if any. If the user pressed ^C
658 * twice, kill the process that we did start, if any.
660 if (got_signal) {
661 detach_running(!first_signal);
663 got_signal = FALSE;
664 first_signal = FALSE;
667 /* Upon getting SIGINFO, print a list of traced processes. */
668 if (got_info) {
669 list_info();
671 got_info = FALSE;
675 * Block until something happens to a traced process. If
676 * enabled from the command line, first try waiting for the
677 * last process for which we got results, so as to reduce call
678 * suspensions a bit.
680 if (grouping && last_pid > 0 &&
681 waitpid(last_pid, &status, WNOHANG) > 0)
682 pid = last_pid;
683 else
684 if ((pid = waitpid(-1, &status, 0)) <= 0) {
685 if (pid == -1 && errno == EINTR) continue;
686 if (pid == -1 && errno == ECHILD) break; /* all done */
688 put_fmt(NULL, "Unexpected waitpid failure: %s",
689 (pid == 0) ? "No result" : strerror(errno));
690 put_newline();
693 * We need waitpid to function correctly in order to
694 * detach from any attached processes, so we can do
695 * little more than just exit, effectively killing all
696 * traced processes.
698 return EXIT_FAILURE;
701 last_pid = 0;
703 /* Get the trace data structure for the process. */
704 if ((proc = proc_get(pid)) == NULL) {
706 * The waitpid() call returned the status of a process
707 * that we have not yet seen. This must be a newly
708 * forked child. If it is not stopped, it must have
709 * died immediately, and we choose not to report it.
711 if (!WIFSTOPPED(status))
712 continue;
714 if ((proc = proc_add(pid)) == NULL) {
715 put_fmt(NULL,
716 "Error attaching to new child %d: %s",
717 pid, strerror(errno));
718 put_newline();
721 * Out of memory allocating a new child object!
722 * We can not trace this child, so just let it
723 * run free by detaching from it.
725 if (WSTOPSIG(status) != SIGSTOP) {
726 (void)ptrace(T_RESUME, pid, 0,
727 WSTOPSIG(status));
729 if (wait_sig(pid, SIGSTOP) != 0)
730 continue; /* it died.. */
733 (void)ptrace(T_DETACH, pid, 0, 0);
735 continue;
739 * We must specify TF_ATTACH here, even though it may
740 * be a child of a process we started, in which case it
741 * should be killed when we exit. We do not keep track
742 * of ancestry though, so better safe than sorry.
744 proc->trace_flags = TF_ATTACH | TF_STOPPING;
746 new_proc(proc, follow_fork);
748 /* Repeat entering the fork call for the child. */
749 handle_call(proc, show_stack);
752 /* If the process died, report its status and clean it up. */
753 if (!WIFSTOPPED(status)) {
754 discard_proc(proc, status);
756 continue;
759 sig = WSTOPSIG(status);
761 if (sig == SIGSTOP && (proc->trace_flags & TF_STOPPING)) {
762 /* We expected the process to be stopped; now it is. */
763 proc->trace_flags &= ~TF_STOPPING;
765 if (proc->trace_flags & TF_DETACH) {
766 if (ptrace(T_DETACH, proc->pid, 0, 0) == 0)
767 discard_proc(proc, status);
770 * If detaching failed, the process must have
771 * died, and we'll get notified through wait().
773 continue;
776 sig = 0;
777 } else if (sig == SIGSTOP && (proc->trace_flags & TF_EXEC)) {
778 /* The process has performed a successful execve(). */
779 call_leave(proc, TRUE /*skip*/);
781 put_text(proc, "---");
783 new_exec(proc);
786 * A successful execve() has no result, in the sense
787 * that there is no reply message. We should therefore
788 * not even try to copy in the reply message from the
789 * original location, because it will be invalid.
790 * Thus, we skip the exec's call leave phase entirely.
792 proc->trace_flags &= ~TF_EXEC;
793 proc->trace_flags |= TF_SKIP;
795 sig = 0;
796 } else if (sig == SIGTRAP) {
797 /* The process is entering or leaving a system call. */
798 if (!(proc->trace_flags & TF_DETACH))
799 handle_call(proc, show_stack);
801 sig = 0;
802 } else {
803 /* The process has received a signal. */
804 report_signal(proc, sig, show_stack);
807 * Only in this case do we pass the signal to the
808 * traced process.
813 * Resume process execution. If this call fails, the process
814 * has probably died. We will find out soon enough.
816 (void)ptrace(T_SYSCALL, proc->pid, 0, sig);
818 last_pid = proc->pid;
821 return (error) ? EXIT_FAILURE : EXIT_SUCCESS;