5 #include <minix/callnr.h>
6 #include <minix/endpoint.h>
8 static const struct calls
*call_table
[] = {
18 * Find a call handler for the given endpoint, call number pair. Return NULL
19 * if no call handler for this call exists.
21 static const struct call_handler
*
22 find_handler(endpoint_t endpt
, int call_nr
)
24 unsigned int i
, index
;
26 for (i
= 0; i
< COUNT(call_table
); i
++) {
27 if (call_table
[i
]->endpt
!= ANY
&&
28 call_table
[i
]->endpt
!= endpt
)
31 if ((unsigned int)call_nr
< call_table
[i
]->base
)
34 index
= (unsigned int)call_nr
- call_table
[i
]->base
;
36 if (index
>= call_table
[i
]->count
)
39 if (call_table
[i
]->map
[index
].outfunc
== NULL
)
42 return &call_table
[i
]->map
[index
];
52 put_endpoint(struct trace_proc
* proc
, const char * name
, endpoint_t endpt
)
54 const char *text
= NULL
;
80 put_field(proc
, name
, text
);
82 put_value(proc
, name
, "%d", endpt
);
86 * Print a message structure. The source field will be printed only if the
87 * PF_ALT flag is given.
90 put_message(struct trace_proc
* proc
, const char * name
, int flags
,
95 if (!put_open_struct(proc
, name
, flags
, addr
, &m
, sizeof(m
)))
99 put_endpoint(proc
, "m_source", m
.m_source
);
101 put_value(proc
, "m_type", "0x%x", m
.m_type
);
103 put_close_struct(proc
, FALSE
/*all*/);
107 * Print the call's equals sign, which also implies that the parameters part of
108 * the call has been fully printed and the corresponding closing parenthesis
109 * may have to be printed, if it has not been printed already.
112 put_equals(struct trace_proc
* proc
)
116 * Do not allow multiple equals signs on a single line. This check is
117 * protection against badly written handlers. It does not work for the
118 * no-return type, but such calls are rare and less error prone anyway.
120 assert((proc
->call_flags
& (CF_DONE
| CF_NORETURN
)) != CF_DONE
);
123 * We allow (and in fact force) handlers to call put_equals in order to
124 * indicate that the call's parameters block has ended, so we must end
125 * the block here, if we hadn't done so before.
127 if (!(proc
->call_flags
& CF_DONE
)) {
128 put_close(proc
, ") ");
130 proc
->call_flags
|= CF_DONE
;
134 put_text(proc
, "= ");
136 format_set_sep(proc
, NULL
);
140 * Print the primary result of a call, after the equals sign. It is always
141 * possible that this is an IPC-level or other low-level error, in which case
142 * this takes precedence, which is why this function must be called to print
143 * the result if the call failed in any way at all; it may or may not be used
144 * if the call succeeded. For regular call results, default MINIX3/POSIX
145 * semantics are used: if the return value is negative, the actual call failed
146 * with -1 and the negative return value is the call's error code. The caller
147 * may consider other cases a failure (e.g., waitpid() returning 0), but
148 * negative return values *not* signifying an error are currently not supported
149 * since they are not present in MINIX3.
152 put_result(struct trace_proc
* proc
)
157 /* This call should always be preceded by a put_equals call. */
158 assert(proc
->call_flags
& CF_DONE
);
161 * If we failed to copy in the result register or message, print a
162 * basic error and nothing else.
164 if (proc
->call_flags
& (CF_REG_ERR
| CF_MSG_ERR
)) {
165 put_text(proc
, "<fault>");
171 * If we are printing a system call rather than an IPC call, and an
172 * error occurred at the IPC level, prefix the output with "<ipc>" to
173 * indicate the IPC failure. If we are printing an IPC call, an IPC-
174 * level result is implied, so we do not print this.
176 if (proc
->call_handler
!= NULL
&& (proc
->call_flags
& CF_IPC_ERR
))
177 put_text(proc
, "<ipc> ");
179 value
= proc
->call_result
;
182 put_fmt(proc
, "%d", value
);
183 else if (!valuesonly
&& (errname
= get_error_name(-value
)) != NULL
)
184 put_fmt(proc
, "-1 [%s]", errname
);
186 put_fmt(proc
, "-1 [%d]", -value
);
188 format_set_sep(proc
, " ");
192 * The default enter-call (out) printer, which prints no parameters and is thus
193 * immediately done with printing parameters.
196 default_out(struct trace_proc
* __unused proc
, const message
* __unused m_out
)
203 * The default leave-call (in) printer, which simply prints the call result,
204 * possibly preceded by an equals sign if none was printed yet. For obvious
205 * reasons, if the handler's out printer returned CT_NOTDONE, this default
206 * printer must not be used.
209 default_in(struct trace_proc
* proc
, const message
* __unused m_out
,
210 const message
* __unused m_in
, int __unused failed
)
213 if ((proc
->call_flags
& (CF_DONE
| CF_NORETURN
)) != CF_DONE
)
219 * Prepare a sendrec call, by copying in the request message, determining
220 * whether it is one of the calls that the tracing engine should know about,
221 * searching for a handler for the call, and returning a name for the call.
224 sendrec_prepare(struct trace_proc
* proc
, endpoint_t endpt
, vir_bytes addr
,
230 r
= mem_get_data(proc
->pid
, addr
, &proc
->m_out
, sizeof(proc
->m_out
));
233 if (endpt
== PM_PROC_NR
) {
234 if (proc
->m_out
.m_type
== PM_EXEC
)
235 *trace_class
= TC_EXEC
;
236 else if (proc
->m_out
.m_type
== PM_SIGRETURN
)
237 *trace_class
= TC_SIGRET
;
240 proc
->call_handler
= find_handler(endpt
, proc
->m_out
.m_type
);
242 proc
->call_handler
= NULL
;
244 if (proc
->call_handler
!= NULL
) {
245 if (proc
->call_handler
->namefunc
!= NULL
)
246 name
= proc
->call_handler
->namefunc(&proc
->m_out
);
248 name
= proc
->call_handler
->name
;
250 assert(name
!= NULL
);
252 name
= "ipc_sendrec";
258 * Print the outgoing (request) part of a sendrec call. If we found a call
259 * handler for the call, let the handler generate output. Otherwise, print the
260 * sendrec call at the kernel IPC level. Return the resulting call flags.
263 sendrec_out(struct trace_proc
* proc
, endpoint_t endpt
, vir_bytes addr
)
266 if (proc
->call_handler
!= NULL
) {
267 return proc
->call_handler
->outfunc(proc
, &proc
->m_out
);
269 put_endpoint(proc
, "src_dest", endpt
);
271 * We have already copied in the message, but if we used m_out
272 * and PF_LOCADDR here, a copy failure would cause "&.." to be
273 * printed rather than the actual message address.
275 put_message(proc
, "m_ptr", 0, addr
);
282 * Print the incoming (reply) part of a sendrec call. Copy in the reply
283 * message, determine whether the call is considered to have failed, and let
284 * the call handler do the rest. If no call handler was found, print an
288 sendrec_in(struct trace_proc
* proc
, int failed
)
293 /* The call failed at the IPC level. */
294 memset(&m_in
, 0, sizeof(m_in
)); /* not supposed to be used */
295 assert(proc
->call_flags
& CF_IPC_ERR
);
296 } else if (mem_get_data(proc
->pid
, proc
->m_addr
, &m_in
,
297 sizeof(m_in
)) != 0) {
298 /* The reply message is somehow unavailable to us. */
299 memset(&m_in
, 0, sizeof(m_in
)); /* not supposed to be used */
300 proc
->call_result
= EGENERIC
; /* not supposed to be used */
301 proc
->call_flags
|= CF_MSG_ERR
;
304 /* The result is for the actual call. */
305 proc
->call_result
= m_in
.m_type
;
306 failed
= (proc
->call_result
< 0) ? PF_FAILED
: 0;
309 if (proc
->call_handler
!= NULL
)
310 proc
->call_handler
->infunc(proc
, &proc
->m_out
, &m_in
, failed
);
316 * Perform preparations for printing a system call. Return two things: the
317 * name to use for the call, and the trace class of the call.
318 * special treatment).
321 call_prepare(struct trace_proc
* proc
, reg_t reg
[3], int * trace_class
)
324 switch (proc
->call_type
) {
326 return sendrec_prepare(proc
, (endpoint_t
)reg
[1],
327 (vir_bytes
)reg
[2], trace_class
);
336 return "ipc_receive";
345 return "minix_kerninfo";
349 * It would be nice to include the call number here, but we
350 * must return a string that will last until the entire call is
351 * finished. Adding another buffer to the trace_proc structure
352 * is an option, but it seems overkill..
354 return "ipc_unknown";
359 * Print the outgoing (request) part of a system call. Return the resulting
363 call_out(struct trace_proc
* proc
, reg_t reg
[3])
366 switch (proc
->call_type
) {
368 proc
->m_addr
= (vir_bytes
)reg
[2];
370 return sendrec_out(proc
, (endpoint_t
)reg
[1],
375 put_endpoint(proc
, "dest", (endpoint_t
)reg
[1]);
376 put_message(proc
, "m_ptr", 0, (vir_bytes
)reg
[2]);
381 proc
->m_addr
= (vir_bytes
)reg
[2];
383 put_endpoint(proc
, "src", (endpoint_t
)reg
[1]);
388 put_endpoint(proc
, "dest", (endpoint_t
)reg
[1]);
393 put_ptr(proc
, "table", (vir_bytes
)reg
[2]);
394 put_value(proc
, "count", "%zu", (size_t)reg
[1]);
405 * Print the incoming (reply) part of a call.
408 call_in(struct trace_proc
* proc
, int failed
)
411 switch (proc
->call_type
) {
413 sendrec_in(proc
, failed
);
418 /* Print the source as well. */
419 put_message(proc
, "m_ptr", failed
| PF_ALT
, proc
->m_addr
);
427 * We do not have a platform-independent means to access the
428 * secondary IPC return value, so we cannot print the receive
429 * status or minix_kerninfo address.
440 * Determine whether to skip printing the given call, based on its name.
443 call_hide(const char * __unused name
)
447 * TODO: add support for such filtering, with an strace-like -e command
448 * line option. For now, we filter nothing, although calls may still
449 * be hidden as the result of a register retrieval error.
455 * The given process entered a system call. Return the trace class of the
456 * call: TC_EXEC for an execve() call, TC_SIGRET for a sigreturn() call, or
457 * TC_NORMAL for a call that requires no exceptions in the trace engine.
460 call_enter(struct trace_proc
* proc
, int show_stack
)
464 int trace_class
, type
;
466 /* Get the IPC-level type and parameters of the system call. */
467 if (kernel_get_syscall(proc
->pid
, reg
) < 0) {
469 * If obtaining the details of the system call failed, even
470 * though we know the process is stopped on a system call, we
471 * are going to assume that the process got killed somehow.
472 * Thus, the best we can do is ignore the system call entirely,
473 * and hope that the next thing we hear about this process is
474 * its termination. At worst, we ignore a serious error..
476 proc
->call_flags
= CF_HIDE
;
482 * Obtain the call name that is to be used for this call, and decide
483 * whether we want to print this call at all.
485 proc
->call_type
= (int)reg
[0];
486 trace_class
= TC_NORMAL
;
488 name
= call_prepare(proc
, reg
, &trace_class
);
490 proc
->call_name
= name
;
492 if (call_hide(name
)) {
493 proc
->call_flags
= CF_HIDE
;
498 /* Only print a stack trace if we are printing the call itself. */
500 kernel_put_stacktrace(proc
);
503 * Start a new line, start recording, and print the call name and
504 * opening parenthesis.
512 put_text(proc
, name
);
513 put_open(proc
, NULL
, PF_NONAME
, "(", ", ");
516 * Print the outgoing part of the call, that is, some or all of its
517 * parameters. This call returns flags indicating how far printing
518 * got, and may be one of the following combinations:
519 * - CT_NOTDONE (0) if printing parameters is not yet complete; after
520 * the call split, the in handler must print the rest itself;
521 * - CT_DONE (CF_DONE) if printing parameters is complete, and we
522 * should now print the closing parenthesis and equals sign;
523 * - CT_NORETURN (CF_DONE|CF_NORETURN) if printing parameters is
524 * complete, but we should not print the equals sign, because the
525 * call is expected not to return (the no-return call type).
527 type
= call_out(proc
, reg
);
528 assert(type
== CT_NOTDONE
|| type
== CT_DONE
|| type
== CT_NORETURN
);
531 * Print whatever the handler told us to print for now.
533 if (type
& CF_DONE
) {
534 if (type
& CF_NORETURN
) {
535 put_close(proc
, ")");
539 proc
->call_flags
|= type
;
542 * The equals sign is printed implicitly for the
543 * CT_DONE type only. For CT_NORETURN and CT_NOTDONE,
544 * the "in" handler has to do it explicitly.
550 * If at least one parameter was printed, print the separator
551 * now. We know that another parameter will follow (otherwise
552 * the caller would have returned CT_DONE), and this way the
553 * output looks better.
555 format_push_sep(proc
);
559 * We are now at the call split; further printing will be done once the
560 * call returns, through call_leave. Stop recording; if the call gets
561 * suspended and later resumed, we should replay everything up to here.
564 put_text(proc
, "|"); /* warning, this may push a space */
575 * The given process left a system call, or if skip is set, the leave phase of
576 * the current system call should be ended.
579 call_leave(struct trace_proc
* proc
, int skip
)
584 /* If the call is skipped, it must be a no-return type call. */
585 assert(!skip
|| (proc
->call_flags
& (CF_NORETURN
| CF_HIDE
)));
588 * Start by replaying the current call, if necessary. If the call was
589 * suspended and we are about to print the "in" part, this is obviously
590 * needed. If the call is hidden, replaying will be a no-op, since
591 * nothing was recorded for this call. The special case is a skipped
592 * call (which, as established above, must be a no-return call, e.g.
593 * exec), for which replaying has the effect that if the call was
594 * previously suspended, it will now be replayed, without suspension:
596 * 2| execve("./test", ["./test"], [..(12)]) <..>
597 * 3| sigsuspend([]) = <..>
598 * [A] 2| execve("./test", ["./test"], [..(12)])
600 * 2| Tracing test (pid 2)
602 * The [A] line is the result of replaying the skipped call.
606 hide
= (proc
->call_flags
& CF_HIDE
);
608 if (!hide
&& !skip
) {
609 /* Get the IPC-level result of the call. */
610 if (kernel_get_retreg(proc
->pid
, &retreg
) < 0) {
611 /* This should never happen. Deal with it anyway. */
612 proc
->call_flags
|= CF_REG_ERR
;
614 } else if ((proc
->call_result
= (int)retreg
) < 0) {
615 proc
->call_flags
|= CF_IPC_ERR
;
621 * Print the incoming part of the call, that is, possibly some
622 * or all of its parameters and the call's closing parenthesis
623 * (if CT_NOTDONE), and the equals sign (if not CT_DONE), then
626 call_in(proc
, failed
);
631 * The call is complete now, so clear the recording. This also
632 * implies that no suspension marker will be printed anymore.
640 * For calls not of the no-return type, an equals sign must have been
641 * printed by now. This is protection against badly written handlers.
643 assert(proc
->call_flags
& CF_DONE
);
645 proc
->call_name
= NULL
;
646 proc
->call_flags
= 0;
650 * Replay the recorded text, if any, for the enter phase of the given process.
651 * If there is no recorded text, start a new line anyway.
654 call_replay(struct trace_proc
* proc
)
658 * We get TRUE if the recorded call should be replayed, but the
659 * recorded text for the call did not fit in the recording buffer.
660 * In that case, we have to come up with a replacement text for the
661 * call up to the call split.
663 if (record_replay(proc
) == TRUE
) {
665 * We basically place a "<..>" suspension marker in the
666 * parameters part of the call, and use its call name and flags
667 * for the rest. There is a trailing space in all cases.
669 put_fmt(proc
, "%s(<..>%s", proc
->call_name
,
670 !(proc
->call_flags
& CF_DONE
) ? "," :
671 ((proc
->call_flags
& CF_NORETURN
) ? ")" : ") ="));
677 * Return the human-readable name of the call currently being made by the given
678 * process. The process is guaranteed to be in a call, although the call may
679 * be hidden. Under no circumstances may this function return a NULL pointer.
682 call_name(struct trace_proc
* proc
)
685 assert(proc
->call_name
!= NULL
);
687 return proc
->call_name
;
691 * Return whether the current call failed due to an error at the system call
692 * level, and if so, return the error code as well. May be called during the
693 * leave phase of a call only.
696 call_errno(struct trace_proc
* proc
, int * err
)
699 if (proc
->call_flags
& (CF_REG_ERR
| CF_MSG_ERR
| CF_IPC_ERR
))
702 if (proc
->call_result
>= 0)
705 *err
= -proc
->call_result
;