7 #include <sys/resource.h>
8 #include <sys/utsname.h>
9 #include <sys/reboot.h>
10 #include <minix/profile.h>
13 pm_exit_out(struct trace_proc
* proc
, const message
* m_out
)
16 put_value(proc
, "status", "%d", m_out
->m_lc_pm_exit
.status
);
21 static const struct flags wait4_options
[] = {
32 put_wait4_status(struct trace_proc
* proc
, const char * name
, int status
)
38 * There is no suitable set of macros to be used here, so we're going
39 * to invent our own: W_EXITED, W_SIGNALED, and W_STOPPED. Hopefully
40 * they are sufficiently clear even though they don't actually exist.
41 * The code below is downright messy, but it also ensures that no bits
42 * are set unexpectedly in the status.
44 if (!valuesonly
&& WIFEXITED(status
) &&
45 status
== W_EXITCODE(WEXITSTATUS(status
), 0)) {
46 put_value(proc
, name
, "W_EXITED(%d)",
52 /* WCOREDUMP() actually returns WCOREFLAG or 0, but better safe.. */
53 if (!valuesonly
&& WIFSIGNALED(status
) && status
== (W_EXITCODE(0,
54 WTERMSIG(status
)) | (WCOREDUMP(status
) ? WCOREFLAG
: 0))) {
55 sig
= WTERMSIG(status
);
57 if ((signame
= get_signal_name(sig
)) != NULL
)
58 put_value(proc
, name
, "W_SIGNALED(%s)", signame
);
60 put_value(proc
, name
, "W_SIGNALED(%u)", sig
);
62 if (WCOREDUMP(status
))
63 put_text(proc
, "|WCOREDUMP");
68 if (!valuesonly
&& WIFSTOPPED(status
) &&
69 status
== W_STOPCODE(WSTOPSIG(status
))) {
70 sig
= WSTOPSIG(status
);
72 if ((signame
= get_signal_name(sig
)) != NULL
)
73 put_value(proc
, name
, "W_STOPPED(%s)", signame
);
75 put_value(proc
, name
, "W_STOPPED(%u)", sig
);
81 * If we get here, either valuesonly is enabled or the resulting status
82 * is not one we recognize, for example because extra bits are set.
84 put_value(proc
, name
, "0x%04x", status
);
88 pm_wait4_out(struct trace_proc
* proc
, const message
* m_out
)
91 put_value(proc
, "pid", "%d", m_out
->m_lc_pm_wait4
.pid
);
97 put_struct_rusage(struct trace_proc
* proc
, const char * name
, int flags
,
102 if (!put_open_struct(proc
, name
, flags
, addr
, &ru
, sizeof(ru
)))
105 put_struct_timeval(proc
, "ru_utime", PF_LOCADDR
,
106 (vir_bytes
)&ru
.ru_utime
);
107 put_struct_timeval(proc
, "ru_stime", PF_LOCADDR
,
108 (vir_bytes
)&ru
.ru_stime
);
111 put_value(proc
, "ru_maxrss", "%ld", ru
.ru_maxrss
);
112 put_value(proc
, "ru_minflt", "%ld", ru
.ru_minflt
);
113 put_value(proc
, "ru_majflt", "%ld", ru
.ru_majflt
);
116 put_close_struct(proc
, verbose
> 0);
120 pm_wait4_in(struct trace_proc
* proc
, const message
* m_out
,
121 const message
* m_in
, int failed
)
125 * If the result is zero, there is no status to show. Also, since the
126 * status is returned in the result message, we cannot print the user-
127 * given pointer. Instead, upon failure we show "&.." to indicate an
130 if (!failed
&& m_in
->m_type
> 0)
131 put_wait4_status(proc
, "status", m_in
->m_pm_lc_wait4
.status
);
133 put_field(proc
, "status", "&..");
134 put_flags(proc
, "options", wait4_options
, COUNT(wait4_options
),
135 "0x%x", m_out
->m_lc_pm_wait4
.options
);
136 put_struct_rusage(proc
, "rusage", failed
, m_out
->m_lc_pm_wait4
.addr
);
142 pm_getpid_in(struct trace_proc
* proc
, const message
* __unused m_out
,
143 const message
* m_in
, int failed
)
148 put_open(proc
, NULL
, 0, "(", ", ");
149 put_value(proc
, "ppid", "%d", m_in
->m_pm_lc_getpid
.parent_pid
);
150 put_close(proc
, ")");
154 /* This function is shared between setuid and seteuid. */
156 pm_setuid_out(struct trace_proc
* proc
, const message
* m_out
)
159 put_value(proc
, "uid", "%u", m_out
->m_lc_pm_setuid
.uid
);
165 pm_getuid_in(struct trace_proc
* proc
, const message
* __unused m_out
,
166 const message
* m_in
, int failed
)
171 put_open(proc
, NULL
, 0, "(", ", ");
172 put_value(proc
, "euid", "%u", m_in
->m_pm_lc_getuid
.euid
);
173 put_close(proc
, ")");
178 pm_stime_out(struct trace_proc
* proc
, const message
* m_out
)
181 put_time(proc
, "time", m_out
->m_lc_pm_time
.sec
);
187 put_signal(struct trace_proc
* proc
, const char * name
, int sig
)
191 if (!valuesonly
&& (signame
= get_signal_name(sig
)) != NULL
)
192 put_field(proc
, name
, signame
);
194 put_value(proc
, name
, "%d", sig
);
198 put_ptrace_req(struct trace_proc
* proc
, const char * name
, int req
)
200 const char *text
= NULL
;
227 put_field(proc
, name
, text
);
229 put_value(proc
, name
, "%d", req
);
233 put_struct_ptrace_range(struct trace_proc
* proc
, const char * name
, int flags
,
236 struct ptrace_range pr
;
238 if (!put_open_struct(proc
, name
, flags
, addr
, &pr
, sizeof(pr
)))
241 if (!valuesonly
&& pr
.pr_space
== TS_INS
)
242 put_field(proc
, "pr_space", "TS_INS");
243 else if (!valuesonly
&& pr
.pr_space
== TS_DATA
)
244 put_field(proc
, "pr_space", "TS_DATA");
246 put_value(proc
, "pr_space", "%d", pr
.pr_space
);
247 put_value(proc
, "pr_addr", "0x%lx", pr
.pr_addr
);
248 put_ptr(proc
, "pr_ptr", (vir_bytes
)pr
.pr_ptr
);
249 put_value(proc
, "pr_size", "%zu", pr
.pr_size
);
251 put_close_struct(proc
, TRUE
/*all*/);
255 pm_ptrace_out(struct trace_proc
* proc
, const message
* m_out
)
258 put_ptrace_req(proc
, "req", m_out
->m_lc_pm_ptrace
.req
);
259 put_value(proc
, "pid", "%d", m_out
->m_lc_pm_ptrace
.pid
);
261 switch (m_out
->m_lc_pm_ptrace
.req
) {
266 put_value(proc
, "addr", "0x%lx", m_out
->m_lc_pm_ptrace
.addr
);
267 put_value(proc
, "data", "%ld", m_out
->m_lc_pm_ptrace
.data
);
273 put_value(proc
, "addr", "0x%lx", m_out
->m_lc_pm_ptrace
.addr
);
274 put_value(proc
, "data", "0x%lx", m_out
->m_lc_pm_ptrace
.data
);
279 put_value(proc
, "addr", "%ld", m_out
->m_lc_pm_ptrace
.addr
);
280 put_signal(proc
, "data", m_out
->m_lc_pm_ptrace
.data
);
284 put_struct_ptrace_range(proc
, "addr", 0,
285 m_out
->m_lc_pm_ptrace
.addr
);
286 put_value(proc
, "data", "%ld", m_out
->m_lc_pm_ptrace
.data
);
289 put_value(proc
, "addr", "%ld", m_out
->m_lc_pm_ptrace
.addr
);
290 put_value(proc
, "data", "%ld", m_out
->m_lc_pm_ptrace
.data
);
298 pm_ptrace_in(struct trace_proc
* proc
, const message
* m_out
,
299 const message
* m_in
, int failed
)
303 switch (m_out
->m_lc_pm_ptrace
.req
) {
308 put_value(proc
, NULL
, "0x%lx",
309 m_in
->m_pm_lc_ptrace
.data
);
318 put_groups(struct trace_proc
* proc
, const char * name
, int flags
,
319 vir_bytes addr
, int count
)
321 gid_t groups
[NGROUPS_MAX
];
324 if ((flags
& PF_FAILED
) || valuesonly
|| count
< 0 ||
325 count
> NGROUPS_MAX
|| (count
> 0 && mem_get_data(proc
->pid
, addr
,
326 groups
, count
* sizeof(groups
[0])) < 0)) {
327 if (flags
& PF_LOCADDR
)
328 put_field(proc
, name
, "&..");
330 put_ptr(proc
, name
, addr
);
335 put_open(proc
, name
, PF_NONAME
, "[", ", ");
336 for (i
= 0; i
< count
; i
++)
337 put_value(proc
, NULL
, "%u", groups
[i
]);
338 put_close(proc
, "]");
342 pm_setgroups_out(struct trace_proc
* proc
, const message
* m_out
)
345 put_value(proc
, "ngroups", "%d", m_out
->m_lc_pm_groups
.num
);
346 put_groups(proc
, "grouplist", 0, m_out
->m_lc_pm_groups
.ptr
,
347 m_out
->m_lc_pm_groups
.num
);
353 pm_getgroups_out(struct trace_proc
* proc
, const message
* m_out
)
356 put_value(proc
, "ngroups", "%d", m_out
->m_lc_pm_groups
.num
);
362 pm_getgroups_in(struct trace_proc
* proc
, const message
* m_out
,
363 const message
* m_in
, int failed
)
366 put_groups(proc
, "grouplist", failed
, m_out
->m_lc_pm_groups
.ptr
,
373 pm_kill_out(struct trace_proc
* proc
, const message
* m_out
)
376 put_value(proc
, "pid", "%d", m_out
->m_lc_pm_sig
.pid
);
377 put_signal(proc
, "sig", m_out
->m_lc_pm_sig
.nr
);
382 /* This function is shared between setgid and setegid. */
384 pm_setgid_out(struct trace_proc
* proc
, const message
* m_out
)
387 put_value(proc
, "gid", "%u", m_out
->m_lc_pm_setgid
.gid
);
393 pm_getgid_in(struct trace_proc
* proc
, const message
* __unused m_out
,
394 const message
* m_in
, int failed
)
399 put_open(proc
, NULL
, 0, "(", ", ");
400 put_value(proc
, "egid", "%u", m_in
->m_pm_lc_getgid
.egid
);
401 put_close(proc
, ")");
406 put_frame_string(struct trace_proc
* proc
, vir_bytes frame
, size_t len
,
409 vir_bytes stacktop
, offset
;
412 * The addresses in the frame assume that the process has already been
413 * changed, and the top of the frame is now located at the new process
414 * stack top, which is a hardcoded system-global value. In order to
415 * print the strings, we must convert back each address to its location
416 * within the given frame.
418 stacktop
= kernel_get_stacktop();
420 if (addr
>= stacktop
)
422 offset
= stacktop
- addr
;
425 addr
= frame
+ len
- offset
;
428 * TODO: while using put_buf() is highly convenient, it does require at
429 * least one copy operation per printed string. The strings are very
430 * likely to be consecutive in memory, so copying in larger chunks at
431 * once would be preferable. Also, if copying from the frame fails,
432 * put_buf() will print the string address as we corrected it above,
433 * rather than the address as found in the frame. A copy failure would
434 * always be a case of malice on the traced process's behalf, though.
436 put_buf(proc
, NULL
, PF_STRING
, addr
, len
- offset
);
442 * Print the contents of the exec frame, which includes both pointers and
443 * actual string data for the arguments and environment variables to be used.
444 * Even though we know that the entire frame is not going to exceed ARG_MAX
445 * bytes, this is too large a size for a static buffer, and we'd like to avoid
446 * allocating large dynamic buffers as well. The situation is complicated by
447 * the fact that any string in the frame may run up to the end of the frame.
450 put_exec_frame(struct trace_proc
* proc
, vir_bytes addr
, size_t len
)
454 unsigned int i
, count
, max
, argv_max
, envp_max
;
455 int first
, ok
, nulls
;
458 put_ptr(proc
, "frame", addr
);
459 put_value(proc
, "framelen", "%zu", len
);
467 } else if (verbose
== 1)
468 argv_max
= envp_max
= 64;
470 argv_max
= envp_max
= INT_MAX
;
472 off
= sizeof(int); /* skip 'argc' at the start of the frame */
480 chunk
= sizeof(argv
);
481 if (chunk
> len
- off
)
484 if (mem_get_data(proc
->pid
, addr
+ off
, argv
, chunk
) != 0)
488 put_open(proc
, "argv", PF_NONAME
, "[", ", ");
493 for (i
= 0; i
< chunk
/ sizeof(void *) && ok
; i
++) {
494 if (argv
[i
] == NULL
) {
496 put_tail(proc
, count
, max
);
497 put_close(proc
, "]");
499 put_open(proc
, "envp", PF_NONAME
, "[",
504 break; /* two NULL pointers: done! */
505 } else if (count
++ < max
)
506 ok
= put_frame_string(proc
, addr
, len
,
511 } while (nulls
< 2 && ok
);
514 * Handle failure cases, implied by not reaching the second NULL
515 * in the array. Successful completion is handled in the loop above.
516 * Note that 'ok' is not always cleared on failure, as it is used only
517 * to break out of the outer loop.
520 put_ptr(proc
, "argv", addr
+ off
);
521 put_field(proc
, "envp", "&..");
522 } else if (nulls
< 2) {
523 put_tail(proc
, 0, 0);
524 put_close(proc
, "]");
526 put_open(proc
, "envp", PF_NONAME
, "[", ", ");
527 put_tail(proc
, 0, 0);
528 put_close(proc
, "]");
534 pm_exec_out(struct trace_proc
* proc
, const message
* m_out
)
537 put_buf(proc
, "path", PF_PATH
, m_out
->m_lc_pm_exec
.name
,
538 m_out
->m_lc_pm_exec
.namelen
);
539 put_exec_frame(proc
, m_out
->m_lc_pm_exec
.frame
,
540 m_out
->m_lc_pm_exec
.framelen
);
545 /* The idea is that this function may one day print a human-readable time. */
547 put_time(struct trace_proc
* proc
, const char * name
, time_t time
)
550 put_value(proc
, name
, "%"PRId64
, time
);
554 put_struct_timeval(struct trace_proc
* proc
, const char * name
, int flags
,
559 /* No field names; they just make things harder to read. */
560 if (!put_open_struct(proc
, name
, flags
| PF_NONAME
, addr
, &tv
,
565 put_time(proc
, "tv_sec", tv
.tv_sec
);
567 put_value(proc
, "tv_sec", "%"PRId64
, tv
.tv_sec
);
568 put_value(proc
, "tv_usec", "%d", tv
.tv_usec
);
570 put_close_struct(proc
, TRUE
/*all*/);
574 put_struct_itimerval(struct trace_proc
* proc
, const char * name
, int flags
,
580 * This used to pass PF_NONAME, but the layout may not be clear enough
581 * without names. It does turn simple alarm(1) calls into rather
582 * lengthy output, though.
584 if (!put_open_struct(proc
, name
, flags
, addr
, &it
, sizeof(it
)))
587 put_struct_timeval(proc
, "it_interval", PF_LOCADDR
,
588 (vir_bytes
)&it
.it_interval
);
589 put_struct_timeval(proc
, "it_value", PF_LOCADDR
,
590 (vir_bytes
)&it
.it_value
);
592 put_close_struct(proc
, TRUE
/*all*/);
596 put_itimer_which(struct trace_proc
* proc
, const char * name
, int which
)
598 const char *text
= NULL
;
603 TEXT(ITIMER_VIRTUAL
);
605 TEXT(ITIMER_MONOTONIC
);
610 put_field(proc
, name
, text
);
612 put_value(proc
, name
, "%d", which
);
616 pm_itimer_name(const message
* m_out
)
619 return (m_out
->m_lc_pm_itimer
.value
!= 0) ? "setitimer" : "getitimer";
623 pm_itimer_out(struct trace_proc
* proc
, const message
* m_out
)
626 put_itimer_which(proc
, "which", m_out
->m_lc_pm_itimer
.which
);
627 if (m_out
->m_lc_pm_itimer
.value
!= 0) {
628 put_struct_itimerval(proc
, "value", 0,
629 m_out
->m_lc_pm_itimer
.value
);
632 * If there will be no old values to print, finish the call
633 * now. For setitimer only; getitimer may not pass NULL.
635 if (m_out
->m_lc_pm_itimer
.ovalue
== 0) {
636 put_ptr(proc
, "ovalue", 0);
646 pm_itimer_in(struct trace_proc
* proc
, const message
* m_out
,
647 const message
* __unused m_in
, int failed
)
650 if (m_out
->m_lc_pm_itimer
.value
== 0 ||
651 m_out
->m_lc_pm_itimer
.ovalue
!= 0) {
652 put_struct_itimerval(proc
,
653 (m_out
->m_lc_pm_itimer
.value
!= 0) ? "ovalue" : "value",
654 failed
, m_out
->m_lc_pm_itimer
.ovalue
);
661 put_struct_mcontext(struct trace_proc
* proc
, const char * name
, int flags
,
666 if (!put_open_struct(proc
, name
, flags
, addr
, &ctx
, sizeof(ctx
)))
670 * TODO: print actual fields. Then again, the ones that are saved and
671 * restored (FPU state) are hardly interesting enough to print..
674 put_close_struct(proc
, FALSE
/*all*/);
678 pm_getmcontext_out(struct trace_proc
* proc
, const message
* m_out
)
685 pm_getmcontext_in(struct trace_proc
* proc
, const message
* m_out
,
686 const message
* m_in
, int failed
)
689 put_struct_mcontext(proc
, "mcp", failed
, m_out
->m_lc_pm_mcontext
.ctx
);
695 pm_setmcontext_out(struct trace_proc
* proc
, const message
* m_out
)
698 put_struct_mcontext(proc
, "mcp", 0, m_out
->m_lc_pm_mcontext
.ctx
);
704 put_sigset(struct trace_proc
* proc
, const char * name
, sigset_t set
)
707 unsigned int count
, unknown
;
711 * First decide whether we should print a normal or an inverted mask.
712 * Unfortunately, depending on the place, a filled set may or may not
713 * have bits outside the 1..NSIG range set. Therefore, we ignore the
714 * bits outside this range entirely, and use simple heuristics to
715 * decide whether to show an inverted set. If we know all the signal
716 * names for either set and not the other, show that one; otherwise,
717 * show an inverted mask if at least 3/4th of the bits are set.
721 for (sig
= 1; sig
< NSIG
; sig
++) {
722 if (sigismember(&set
, sig
))
724 if (get_signal_name(sig
) == NULL
)
725 unknown
|= 1 << !!sigismember(&set
, sig
);
727 if (unknown
== 1 /*for unset bit*/ || unknown
== 2 /*for set bit*/)
728 invert
= unknown
- 1;
730 invert
= (count
>= (NSIG
- 1) * 3 / 4);
732 put_open(proc
, name
, PF_NONAME
, invert
? "~[" : "[", " ");
734 for (sig
= 1; sig
< NSIG
; sig
++) {
735 /* Note that sigismember() may not strictly return 0 or 1.. */
736 if (!sigismember(&set
, sig
) != invert
)
739 if ((signame
= get_signal_name(sig
)) != NULL
) {
740 /* Skip the "SIG" prefix for brevity. */
741 if (!strncmp(signame
, "SIG", 3))
742 put_field(proc
, NULL
, &signame
[3]);
744 put_field(proc
, NULL
, signame
);
746 put_value(proc
, NULL
, "%d", sig
);
749 put_close(proc
, "]");
752 static const struct flags sa_flags
[] = {
766 put_sa_handler(struct trace_proc
* proc
, const char * name
, vir_bytes handler
)
768 const char *text
= NULL
;
771 switch ((int)handler
) {
772 case (int)SIG_DFL
: text
= "SIG_DFL"; break;
773 case (int)SIG_IGN
: text
= "SIG_IGN"; break;
774 case (int)SIG_HOLD
: text
= "SIG_HOLD"; break;
779 put_field(proc
, name
, text
);
781 put_ptr(proc
, name
, handler
);
785 put_struct_sigaction(struct trace_proc
* proc
, const char * name
, int flags
,
790 if (!put_open_struct(proc
, name
, flags
, addr
, &sa
, sizeof(sa
)))
793 put_sa_handler(proc
, "sa_handler", (vir_bytes
)sa
.sa_handler
);
796 put_sigset(proc
, "sa_mask", sa
.sa_mask
);
798 /* A somewhat lame attempt to reduce noise a bit. */
799 if ((sa
.sa_flags
& ~(SA_ONSTACK
| SA_RESTART
| SA_RESETHAND
|
800 SA_NODEFER
)) != 0 || sa
.sa_handler
!= SIG_DFL
|| verbose
> 0)
801 put_flags(proc
, "sa_flags", sa_flags
, COUNT(sa_flags
), "0x%x",
804 put_close_struct(proc
, verbose
> 1);
808 pm_sigaction_out(struct trace_proc
* proc
, const message
* m_out
)
811 put_signal(proc
, "signal", m_out
->m_lc_pm_sig
.nr
);
812 put_struct_sigaction(proc
, "act", 0, m_out
->m_lc_pm_sig
.act
);
814 /* If there will be no old values to print, finish the call now. */
815 if (m_out
->m_lc_pm_sig
.oact
== 0) {
816 put_ptr(proc
, "oact", 0);
823 pm_sigaction_in(struct trace_proc
* proc
, const message
* m_out
,
824 const message
* __unused m_in
, int failed
)
827 if (m_out
->m_lc_pm_sig
.oact
!= 0) {
828 put_struct_sigaction(proc
, "oact", failed
,
829 m_out
->m_lc_pm_sig
.oact
);
836 pm_sigsuspend_out(struct trace_proc
* proc
, const message
* m_out
)
839 put_sigset(proc
, "set", m_out
->m_lc_pm_sigset
.set
);
845 pm_sigpending_out(struct trace_proc
* __unused proc
,
846 const message
* __unused m_out
)
853 pm_sigpending_in(struct trace_proc
* proc
, const message
* __unused m_out
,
854 const message
* m_in
, int failed
)
858 put_sigset(proc
, "set", m_in
->m_pm_lc_sigset
.set
);
860 put_field(proc
, "set", "&..");
866 put_sigprocmask_how(struct trace_proc
* proc
, const char * name
, int how
)
868 const char *text
= NULL
;
872 case SIG_INQUIRE
: /* pseudocode, print something else */
880 put_field(proc
, name
, text
);
882 put_value(proc
, name
, "%d", how
);
886 pm_sigprocmask_out(struct trace_proc
* proc
, const message
* m_out
)
889 put_sigprocmask_how(proc
, "how", m_out
->m_lc_pm_sigset
.how
);
890 if (m_out
->m_lc_pm_sigset
.how
== SIG_INQUIRE
)
891 put_ptr(proc
, "set", 0);
893 put_sigset(proc
, "set", m_out
->m_lc_pm_sigset
.set
);
899 pm_sigprocmask_in(struct trace_proc
* proc
, const message
* __unused m_out
,
900 const message
* m_in
, int failed
)
904 put_sigset(proc
, "oset", m_in
->m_pm_lc_sigset
.set
);
906 put_field(proc
, "oset", "&..");
912 pm_sigreturn_out(struct trace_proc
* proc
, const message
* m_out
)
914 struct sigcontext scp
;
916 if (put_open_struct(proc
, "scp", 0, m_out
->m_lc_pm_sigset
.ctx
, &scp
,
919 #if defined(__i386__)
920 put_ptr(proc
, "sc_eip", scp
.sc_eip
);
921 put_ptr(proc
, "sc_esp", scp
.sc_esp
);
922 #elif defined(__arm__)
923 put_ptr(proc
, "sc_pc", scp
.sc_pc
);
924 put_ptr(proc
, "sc_usr_sp", scp
.sc_usr_sp
);
929 * We deliberately print the signal set from the message rather
930 * than from the structure, since in theory they may be
931 * different and PM uses the one from the message only.
933 put_sigset(proc
, "sc_mask", m_out
->m_lc_pm_sigset
.set
);
936 * TODO: print some other fields, although it is probably not
937 * useful to print all registers even with verbose > 1?
939 put_close_struct(proc
, FALSE
/*all*/);
946 pm_sigreturn_in(struct trace_proc
* proc
, const message
* __unused m_out
,
947 const message
* __unused m_in
, int failed
)
957 put_priority_which(struct trace_proc
* proc
, const char * name
, int which
)
959 const char *text
= NULL
;
970 put_field(proc
, name
, text
);
972 put_value(proc
, name
, "%d", which
);
976 pm_getpriority_out(struct trace_proc
* proc
, const message
* m_out
)
979 put_priority_which(proc
, "which", m_out
->m_lc_pm_priority
.which
);
980 put_value(proc
, "who", "%d", m_out
->m_lc_pm_priority
.who
);
986 pm_getpriority_in(struct trace_proc
* proc
, const message
* __unused m_out
,
987 const message
* m_in
, int failed
)
991 put_value(proc
, NULL
, "%d", m_in
->m_type
+ PRIO_MIN
);
997 pm_setpriority_out(struct trace_proc
* proc
, const message
* m_out
)
1000 put_priority_which(proc
, "which", m_out
->m_lc_pm_priority
.which
);
1001 put_value(proc
, "who", "%d", m_out
->m_lc_pm_priority
.who
);
1002 put_value(proc
, "prio", "%d", m_out
->m_lc_pm_priority
.prio
);
1008 pm_gettimeofday_out(struct trace_proc
* __unused proc
,
1009 const message
* __unused m_out
)
1016 put_timespec_as_timeval(struct trace_proc
* proc
, const char * name
,
1017 time_t sec
, long nsec
)
1020 /* No field names within the structure. */
1021 put_open(proc
, name
, PF_NONAME
, "{", ", ");
1023 put_time(proc
, "tv_sec", sec
);
1024 put_value(proc
, "tv_usec", "%ld", nsec
/ 1000);
1026 put_close(proc
, "}");
1030 pm_gettimeofday_in(struct trace_proc
* proc
, const message
* __unused m_out
,
1031 const message
* m_in
, int failed
)
1036 * The system call returns values which do not match the call
1037 * being made, so just like libc, we have to correct..
1039 put_timespec_as_timeval(proc
, "tp", m_in
->m_pm_lc_time
.sec
,
1040 m_in
->m_pm_lc_time
.nsec
);
1042 put_field(proc
, "tp", "&..");
1043 put_ptr(proc
, "tzp", 0); /* not part of the system call (yet) */
1050 pm_getsid_out(struct trace_proc
* proc
, const message
* m_out
)
1053 put_value(proc
, "pid", "%d", m_out
->m_lc_pm_getsid
.pid
);
1059 put_clockid(struct trace_proc
* proc
, const char * name
, clockid_t clock_id
)
1061 const char *text
= NULL
;
1065 TEXT(CLOCK_REALTIME
);
1066 #ifdef CLOCK_VIRTUAL
1067 TEXT(CLOCK_VIRTUAL
);
1072 TEXT(CLOCK_MONOTONIC
);
1077 put_field(proc
, name
, text
);
1079 put_value(proc
, name
, "%d", clock_id
);
1083 put_clock_timespec(struct trace_proc
* proc
, const char * name
, int flags
,
1084 time_t sec
, long nsec
)
1087 if (flags
& PF_FAILED
) {
1088 put_field(proc
, name
, "&..");
1093 /* No field names within the structure. */
1094 put_open(proc
, name
, PF_NONAME
, "{", ", ");
1097 put_time(proc
, "tv_sec", sec
);
1099 put_value(proc
, "tv_sec", "%"PRId64
, sec
);
1100 put_value(proc
, "tv_nsec", "%ld", nsec
);
1102 put_close(proc
, "}");
1105 /* This function is shared between clock_getres and clock_gettime. */
1107 pm_clock_get_out(struct trace_proc
* proc
, const message
* m_out
)
1110 put_clockid(proc
, "clock_id", m_out
->m_lc_pm_time
.clk_id
);
1116 pm_clock_getres_in(struct trace_proc
* proc
, const message
* __unused m_out
,
1117 const message
* m_in
, int failed
)
1120 put_clock_timespec(proc
, "res", failed
, m_in
->m_pm_lc_time
.sec
,
1121 m_in
->m_pm_lc_time
.nsec
);
1127 * Same as pm_clock_getres_in, but different field name and the option to print
1128 * at least some results as time strings (in the future).
1131 pm_clock_gettime_in(struct trace_proc
* proc
, const message
* m_out
,
1132 const message
* m_in
, int failed
)
1137 if (m_out
->m_lc_pm_time
.clk_id
== CLOCK_REALTIME
)
1138 flags
|= PF_ALT
; /* TODO: make this print a time string. */
1140 put_clock_timespec(proc
, "tp", flags
, m_in
->m_pm_lc_time
.sec
,
1141 m_in
->m_pm_lc_time
.nsec
);
1147 pm_clock_settime_name(const message
* m_out
)
1150 if (m_out
->m_lc_pm_time
.now
== 0)
1153 return "clock_settime";
1157 pm_clock_settime_out(struct trace_proc
* proc
, const message
* m_out
)
1161 /* These two calls just look completely different.. */
1162 if (m_out
->m_lc_pm_time
.now
== 0) {
1163 put_timespec_as_timeval(proc
, "delta", m_out
->m_lc_pm_time
.sec
,
1164 m_out
->m_lc_pm_time
.nsec
);
1165 put_ptr(proc
, "odelta", 0); /* not supported on MINIX3 */
1168 if (m_out
->m_lc_pm_time
.clk_id
== CLOCK_REALTIME
)
1170 put_clockid(proc
, "clock_id", m_out
->m_lc_pm_time
.clk_id
);
1171 put_clock_timespec(proc
, "tp", flags
, m_out
->m_lc_pm_time
.sec
,
1172 m_out
->m_lc_pm_time
.nsec
);
1179 pm_getrusage_out(struct trace_proc
* proc
, const message
* m_out
)
1182 if (!valuesonly
&& m_out
->m_lc_pm_rusage
.who
== RUSAGE_SELF
)
1183 put_field(proc
, "who", "RUSAGE_SELF");
1184 else if (!valuesonly
&& m_out
->m_lc_pm_rusage
.who
== RUSAGE_CHILDREN
)
1185 put_field(proc
, "who", "RUSAGE_CHILDREN");
1187 put_value(proc
, "who", "%d", m_out
->m_lc_pm_rusage
.who
);
1193 pm_getrusage_in(struct trace_proc
* proc
, const message
* m_out
,
1194 const message
* __unused m_in
, int failed
)
1197 put_struct_rusage(proc
, "rusage", failed
, m_out
->m_lc_pm_rusage
.addr
);
1202 static const struct flags reboot_flags
[] = {
1203 FLAG_ZERO(RB_AUTOBOOT
),
1206 FLAG_MASK(RB_POWERDOWN
, RB_HALT
),
1218 pm_reboot_out(struct trace_proc
* proc
, const message
* m_out
)
1221 put_flags(proc
, "how", reboot_flags
, COUNT(reboot_flags
), "0x%x",
1222 m_out
->m_lc_pm_reboot
.how
);
1223 put_ptr(proc
, "bootstr", 0); /* not supported on MINIX3 */
1229 pm_svrctl_out(struct trace_proc
* proc
, const message
* m_out
)
1232 put_ioctl_req(proc
, "request", m_out
->m_lc_svrctl
.request
,
1233 TRUE
/*is_svrctl*/);
1234 return put_ioctl_arg_out(proc
, "arg", m_out
->m_lc_svrctl
.request
,
1235 m_out
->m_lc_svrctl
.arg
, TRUE
/*is_svrctl*/);
1239 pm_svrctl_in(struct trace_proc
* proc
, const message
* m_out
,
1240 const message
* __unused m_in
, int failed
)
1243 put_ioctl_arg_in(proc
, "arg", failed
, m_out
->m_lc_svrctl
.request
,
1244 m_out
->m_lc_svrctl
.arg
, TRUE
/*is_svrctl*/);
1248 pm_sprof_out(struct trace_proc
* proc
, const message
* m_out
)
1252 if (!valuesonly
&& m_out
->m_lc_pm_sprof
.action
== PROF_START
)
1253 put_field(proc
, "action", "PROF_START");
1254 else if (!valuesonly
&& m_out
->m_lc_pm_sprof
.action
== PROF_STOP
)
1255 put_field(proc
, "action", "PROF_STOP");
1257 put_value(proc
, "action", "%d", m_out
->m_lc_pm_sprof
.action
);
1259 put_value(proc
, "size", "%zu", m_out
->m_lc_pm_sprof
.mem_size
);
1261 freq
= m_out
->m_lc_pm_sprof
.freq
;
1262 if (!valuesonly
&& freq
>= 3 && freq
<= 15) /* no constants.. */
1263 put_value(proc
, "freq", "%u /*%uHz*/", freq
, 1 << (16 - freq
));
1265 put_value(proc
, "freq", "%u", freq
);
1267 if (!valuesonly
&& m_out
->m_lc_pm_sprof
.intr_type
== PROF_RTC
)
1268 put_field(proc
, "type", "PROF_RTC");
1269 else if (!valuesonly
&& m_out
->m_lc_pm_sprof
.intr_type
== PROF_NMI
)
1270 put_field(proc
, "type", "PROF_NMI");
1272 put_value(proc
, "type", "%d", m_out
->m_lc_pm_sprof
.intr_type
);
1274 put_ptr(proc
, "ctl_ptr", m_out
->m_lc_pm_sprof
.ctl_ptr
);
1275 put_ptr(proc
, "mem_ptr", m_out
->m_lc_pm_sprof
.mem_ptr
);
1280 #define PM_CALL(c) [((PM_ ## c) - PM_BASE)]
1282 static const struct call_handler pm_map
[] = {
1283 PM_CALL(EXIT
) = HANDLER("exit", pm_exit_out
, default_in
),
1284 PM_CALL(FORK
) = HANDLER("fork", default_out
, default_in
),
1285 PM_CALL(WAIT4
) = HANDLER("wait4", pm_wait4_out
, pm_wait4_in
),
1286 PM_CALL(GETPID
) = HANDLER("getpid", default_out
, pm_getpid_in
),
1287 PM_CALL(SETUID
) = HANDLER("setuid", pm_setuid_out
, default_in
),
1288 PM_CALL(GETUID
) = HANDLER("getuid", default_out
, pm_getuid_in
),
1289 PM_CALL(STIME
) = HANDLER("stime", pm_stime_out
, default_in
),
1290 PM_CALL(PTRACE
) = HANDLER("ptrace", pm_ptrace_out
, pm_ptrace_in
),
1291 PM_CALL(SETGROUPS
) = HANDLER("setgroups", pm_setgroups_out
,
1293 PM_CALL(GETGROUPS
) = HANDLER("getgroups", pm_getgroups_out
,
1295 PM_CALL(KILL
) = HANDLER("kill", pm_kill_out
, default_in
),
1296 PM_CALL(SETGID
) = HANDLER("setgid", pm_setgid_out
, default_in
),
1297 PM_CALL(GETGID
) = HANDLER("getgid", default_out
, pm_getgid_in
),
1298 PM_CALL(EXEC
) = HANDLER("execve", pm_exec_out
, default_in
),
1299 PM_CALL(SETSID
) = HANDLER("setsid", default_out
, default_in
),
1300 PM_CALL(GETPGRP
) = HANDLER("getpgrp", default_out
, default_in
),
1301 PM_CALL(ITIMER
) = HANDLER_NAME(pm_itimer_name
, pm_itimer_out
,
1303 PM_CALL(GETMCONTEXT
) = HANDLER("getmcontext", pm_getmcontext_out
,
1305 PM_CALL(SETMCONTEXT
) = HANDLER("setmcontext", pm_setmcontext_out
,
1307 PM_CALL(SIGACTION
) = HANDLER("sigaction", pm_sigaction_out
,
1309 PM_CALL(SIGSUSPEND
) = HANDLER("sigsuspend", pm_sigsuspend_out
,
1311 PM_CALL(SIGPENDING
) = HANDLER("sigpending", pm_sigpending_out
,
1313 PM_CALL(SIGPROCMASK
) = HANDLER("sigprocmask", pm_sigprocmask_out
,
1315 PM_CALL(SIGRETURN
) = HANDLER("sigreturn", pm_sigreturn_out
,
1317 PM_CALL(GETPRIORITY
) = HANDLER("getpriority", pm_getpriority_out
,
1319 PM_CALL(SETPRIORITY
) = HANDLER("setpriority", pm_setpriority_out
,
1321 PM_CALL(GETTIMEOFDAY
) = HANDLER("gettimeofday", pm_gettimeofday_out
,
1322 pm_gettimeofday_in
),
1323 PM_CALL(SETEUID
) = HANDLER("seteuid", pm_setuid_out
, default_in
),
1324 PM_CALL(SETEGID
) = HANDLER("setegid", pm_setgid_out
, default_in
),
1325 PM_CALL(ISSETUGID
) = HANDLER("issetugid", default_out
, default_in
),
1326 PM_CALL(GETSID
) = HANDLER("getsid", pm_getsid_out
, default_in
),
1327 PM_CALL(CLOCK_GETRES
) = HANDLER("clock_getres", pm_clock_get_out
,
1328 pm_clock_getres_in
),
1329 PM_CALL(CLOCK_GETTIME
) = HANDLER("clock_gettime", pm_clock_get_out
,
1330 pm_clock_gettime_in
),
1331 PM_CALL(CLOCK_SETTIME
) = HANDLER_NAME(pm_clock_settime_name
,
1332 pm_clock_settime_out
, default_in
),
1333 PM_CALL(GETRUSAGE
) = HANDLER("getrusage", pm_getrusage_out
,
1335 PM_CALL(REBOOT
) = HANDLER("reboot", pm_reboot_out
, default_in
),
1336 PM_CALL(SVRCTL
) = HANDLER("pm_svrctl", pm_svrctl_out
, pm_svrctl_in
),
1337 PM_CALL(SPROF
) = HANDLER("sprofile", pm_sprof_out
, default_in
),
1340 const struct calls pm_calls
= {
1341 .endpt
= PM_PROC_NR
,
1344 .count
= COUNT(pm_map
)