xref: /minix3/minix/usr.bin/trace/service/pm.c (revision d991a2bea3bf996992e1167e804c52cc6c5ab50d)
1521fa314SDavid van Moolenbroek 
2521fa314SDavid van Moolenbroek #include "inc.h"
3521fa314SDavid van Moolenbroek 
4521fa314SDavid van Moolenbroek #include <signal.h>
5521fa314SDavid van Moolenbroek #include <sys/time.h>
6521fa314SDavid van Moolenbroek #include <sys/wait.h>
7521fa314SDavid van Moolenbroek #include <sys/resource.h>
8521fa314SDavid van Moolenbroek #include <sys/utsname.h>
9521fa314SDavid van Moolenbroek #include <sys/reboot.h>
10521fa314SDavid van Moolenbroek #include <minix/profile.h>
11521fa314SDavid van Moolenbroek 
12521fa314SDavid van Moolenbroek static int
pm_exit_out(struct trace_proc * proc,const message * m_out)13521fa314SDavid van Moolenbroek pm_exit_out(struct trace_proc * proc, const message * m_out)
14521fa314SDavid van Moolenbroek {
15521fa314SDavid van Moolenbroek 
16521fa314SDavid van Moolenbroek 	put_value(proc, "status", "%d", m_out->m_lc_pm_exit.status);
17521fa314SDavid van Moolenbroek 
18521fa314SDavid van Moolenbroek 	return CT_NORETURN;
19521fa314SDavid van Moolenbroek }
20521fa314SDavid van Moolenbroek 
21*29346ab0SDavid van Moolenbroek static const struct flags wait4_options[] = {
22521fa314SDavid van Moolenbroek 	FLAG(WNOHANG),
23521fa314SDavid van Moolenbroek 	FLAG(WUNTRACED),
24521fa314SDavid van Moolenbroek 	FLAG(WALTSIG),
25521fa314SDavid van Moolenbroek 	FLAG(WALLSIG),
26521fa314SDavid van Moolenbroek 	FLAG(WNOWAIT),
27521fa314SDavid van Moolenbroek 	FLAG(WNOZOMBIE),
28521fa314SDavid van Moolenbroek 	FLAG(WOPTSCHECKED),
29521fa314SDavid van Moolenbroek };
30521fa314SDavid van Moolenbroek 
31521fa314SDavid van Moolenbroek static void
put_wait4_status(struct trace_proc * proc,const char * name,int status)32*29346ab0SDavid van Moolenbroek put_wait4_status(struct trace_proc * proc, const char * name, int status)
33521fa314SDavid van Moolenbroek {
34521fa314SDavid van Moolenbroek 	const char *signame;
35521fa314SDavid van Moolenbroek 	int sig;
36521fa314SDavid van Moolenbroek 
37521fa314SDavid van Moolenbroek 	/*
38521fa314SDavid van Moolenbroek 	 * There is no suitable set of macros to be used here, so we're going
39521fa314SDavid van Moolenbroek 	 * to invent our own: W_EXITED, W_SIGNALED, and W_STOPPED.  Hopefully
40521fa314SDavid van Moolenbroek 	 * they are sufficiently clear even though they don't actually exist.
41521fa314SDavid van Moolenbroek 	 * The code below is downright messy, but it also ensures that no bits
42521fa314SDavid van Moolenbroek 	 * are set unexpectedly in the status.
43521fa314SDavid van Moolenbroek 	 */
44521fa314SDavid van Moolenbroek 	if (!valuesonly && WIFEXITED(status) &&
45521fa314SDavid van Moolenbroek 	    status == W_EXITCODE(WEXITSTATUS(status), 0)) {
46521fa314SDavid van Moolenbroek 		put_value(proc, name, "W_EXITED(%d)",
47521fa314SDavid van Moolenbroek 		    WEXITSTATUS(status));
48521fa314SDavid van Moolenbroek 
49521fa314SDavid van Moolenbroek 		return;
50521fa314SDavid van Moolenbroek 	}
51521fa314SDavid van Moolenbroek 
52521fa314SDavid van Moolenbroek 	/* WCOREDUMP() actually returns WCOREFLAG or 0, but better safe.. */
53521fa314SDavid van Moolenbroek 	if (!valuesonly && WIFSIGNALED(status) && status == (W_EXITCODE(0,
54521fa314SDavid van Moolenbroek 	    WTERMSIG(status)) | (WCOREDUMP(status) ? WCOREFLAG : 0))) {
55521fa314SDavid van Moolenbroek 		sig = WTERMSIG(status);
56521fa314SDavid van Moolenbroek 
57521fa314SDavid van Moolenbroek 		if ((signame = get_signal_name(sig)) != NULL)
58521fa314SDavid van Moolenbroek 			put_value(proc, name, "W_SIGNALED(%s)", signame);
59521fa314SDavid van Moolenbroek 		else
60521fa314SDavid van Moolenbroek 			put_value(proc, name, "W_SIGNALED(%u)", sig);
61521fa314SDavid van Moolenbroek 
62521fa314SDavid van Moolenbroek 		if (WCOREDUMP(status))
63521fa314SDavid van Moolenbroek 			put_text(proc, "|WCOREDUMP");
64521fa314SDavid van Moolenbroek 
65521fa314SDavid van Moolenbroek 		return;
66521fa314SDavid van Moolenbroek 	}
67521fa314SDavid van Moolenbroek 
68521fa314SDavid van Moolenbroek 	if (!valuesonly && WIFSTOPPED(status) &&
69521fa314SDavid van Moolenbroek 	    status == W_STOPCODE(WSTOPSIG(status))) {
70521fa314SDavid van Moolenbroek 		sig = WSTOPSIG(status);
71521fa314SDavid van Moolenbroek 
72521fa314SDavid van Moolenbroek 		if ((signame = get_signal_name(sig)) != NULL)
73521fa314SDavid van Moolenbroek 			put_value(proc, name, "W_STOPPED(%s)", signame);
74521fa314SDavid van Moolenbroek 		else
75521fa314SDavid van Moolenbroek 			put_value(proc, name, "W_STOPPED(%u)", sig);
76521fa314SDavid van Moolenbroek 
77521fa314SDavid van Moolenbroek 		return;
78521fa314SDavid van Moolenbroek 	}
79521fa314SDavid van Moolenbroek 
80521fa314SDavid van Moolenbroek 	/*
81521fa314SDavid van Moolenbroek 	 * If we get here, either valuesonly is enabled or the resulting status
82521fa314SDavid van Moolenbroek 	 * is not one we recognize, for example because extra bits are set.
83521fa314SDavid van Moolenbroek 	 */
84521fa314SDavid van Moolenbroek 	put_value(proc, name, "0x%04x", status);
85521fa314SDavid van Moolenbroek }
86521fa314SDavid van Moolenbroek 
87521fa314SDavid van Moolenbroek static int
pm_wait4_out(struct trace_proc * proc,const message * m_out)88*29346ab0SDavid van Moolenbroek pm_wait4_out(struct trace_proc * proc, const message * m_out)
89521fa314SDavid van Moolenbroek {
90521fa314SDavid van Moolenbroek 
91*29346ab0SDavid van Moolenbroek 	put_value(proc, "pid", "%d", m_out->m_lc_pm_wait4.pid);
92521fa314SDavid van Moolenbroek 
93521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
94521fa314SDavid van Moolenbroek }
95521fa314SDavid van Moolenbroek 
96521fa314SDavid van Moolenbroek static void
put_struct_rusage(struct trace_proc * proc,const char * name,int flags,vir_bytes addr)97*29346ab0SDavid van Moolenbroek put_struct_rusage(struct trace_proc * proc, const char * name, int flags,
98*29346ab0SDavid van Moolenbroek 	vir_bytes addr)
99*29346ab0SDavid van Moolenbroek {
100*29346ab0SDavid van Moolenbroek 	struct rusage ru;
101*29346ab0SDavid van Moolenbroek 
102*29346ab0SDavid van Moolenbroek 	if (!put_open_struct(proc, name, flags, addr, &ru, sizeof(ru)))
103*29346ab0SDavid van Moolenbroek 		return;
104*29346ab0SDavid van Moolenbroek 
105*29346ab0SDavid van Moolenbroek 	put_struct_timeval(proc, "ru_utime", PF_LOCADDR,
106*29346ab0SDavid van Moolenbroek 	    (vir_bytes)&ru.ru_utime);
107*29346ab0SDavid van Moolenbroek 	put_struct_timeval(proc, "ru_stime", PF_LOCADDR,
108*29346ab0SDavid van Moolenbroek 	    (vir_bytes)&ru.ru_stime);
109*29346ab0SDavid van Moolenbroek 
110*29346ab0SDavid van Moolenbroek 	if (verbose > 0) {
111*29346ab0SDavid van Moolenbroek 		put_value(proc, "ru_maxrss", "%ld", ru.ru_maxrss);
112*29346ab0SDavid van Moolenbroek 		put_value(proc, "ru_minflt", "%ld", ru.ru_minflt);
113*29346ab0SDavid van Moolenbroek 		put_value(proc, "ru_majflt", "%ld", ru.ru_majflt);
114*29346ab0SDavid van Moolenbroek 	}
115*29346ab0SDavid van Moolenbroek 
116*29346ab0SDavid van Moolenbroek 	put_close_struct(proc, verbose > 0);
117*29346ab0SDavid van Moolenbroek }
118*29346ab0SDavid van Moolenbroek 
119*29346ab0SDavid van Moolenbroek static void
pm_wait4_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)120*29346ab0SDavid van Moolenbroek pm_wait4_in(struct trace_proc * proc, const message * m_out,
121521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
122521fa314SDavid van Moolenbroek {
123521fa314SDavid van Moolenbroek 
124521fa314SDavid van Moolenbroek 	/*
125521fa314SDavid van Moolenbroek 	 * If the result is zero, there is no status to show.  Also, since the
126521fa314SDavid van Moolenbroek 	 * status is returned in the result message, we cannot print the user-
127521fa314SDavid van Moolenbroek 	 * given pointer.  Instead, upon failure we show "&.." to indicate an
128521fa314SDavid van Moolenbroek 	 * unknown pointer.
129521fa314SDavid van Moolenbroek 	 */
130521fa314SDavid van Moolenbroek 	if (!failed && m_in->m_type > 0)
131*29346ab0SDavid van Moolenbroek 		put_wait4_status(proc, "status", m_in->m_pm_lc_wait4.status);
132521fa314SDavid van Moolenbroek 	else
133521fa314SDavid van Moolenbroek 		put_field(proc, "status", "&..");
134*29346ab0SDavid van Moolenbroek 	put_flags(proc, "options", wait4_options, COUNT(wait4_options),
135*29346ab0SDavid van Moolenbroek 	    "0x%x", m_out->m_lc_pm_wait4.options);
136*29346ab0SDavid van Moolenbroek 	put_struct_rusage(proc, "rusage", failed, m_out->m_lc_pm_wait4.addr);
137521fa314SDavid van Moolenbroek 	put_equals(proc);
138521fa314SDavid van Moolenbroek 	put_result(proc);
139521fa314SDavid van Moolenbroek }
140521fa314SDavid van Moolenbroek 
141521fa314SDavid van Moolenbroek static void
pm_getpid_in(struct trace_proc * proc,const message * __unused m_out,const message * m_in,int failed)142521fa314SDavid van Moolenbroek pm_getpid_in(struct trace_proc * proc, const message * __unused m_out,
143521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
144521fa314SDavid van Moolenbroek {
145521fa314SDavid van Moolenbroek 
146521fa314SDavid van Moolenbroek 	put_result(proc);
147521fa314SDavid van Moolenbroek 	if (!failed) {
148521fa314SDavid van Moolenbroek 		put_open(proc, NULL, 0, "(", ", ");
149521fa314SDavid van Moolenbroek 		put_value(proc, "ppid", "%d", m_in->m_pm_lc_getpid.parent_pid);
150521fa314SDavid van Moolenbroek 		put_close(proc, ")");
151521fa314SDavid van Moolenbroek 	}
152521fa314SDavid van Moolenbroek }
153521fa314SDavid van Moolenbroek 
154521fa314SDavid van Moolenbroek /* This function is shared between setuid and seteuid. */
155521fa314SDavid van Moolenbroek static int
pm_setuid_out(struct trace_proc * proc,const message * m_out)156521fa314SDavid van Moolenbroek pm_setuid_out(struct trace_proc * proc, const message * m_out)
157521fa314SDavid van Moolenbroek {
158521fa314SDavid van Moolenbroek 
159521fa314SDavid van Moolenbroek 	put_value(proc, "uid", "%u", m_out->m_lc_pm_setuid.uid);
160521fa314SDavid van Moolenbroek 
161521fa314SDavid van Moolenbroek 	return CT_DONE;
162521fa314SDavid van Moolenbroek }
163521fa314SDavid van Moolenbroek 
164521fa314SDavid van Moolenbroek static void
pm_getuid_in(struct trace_proc * proc,const message * __unused m_out,const message * m_in,int failed)165521fa314SDavid van Moolenbroek pm_getuid_in(struct trace_proc * proc, const message * __unused m_out,
166521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
167521fa314SDavid van Moolenbroek {
168521fa314SDavid van Moolenbroek 
169521fa314SDavid van Moolenbroek 	put_result(proc);
170521fa314SDavid van Moolenbroek 	if (!failed) {
171521fa314SDavid van Moolenbroek 		put_open(proc, NULL, 0, "(", ", ");
172521fa314SDavid van Moolenbroek 		put_value(proc, "euid", "%u", m_in->m_pm_lc_getuid.euid);
173521fa314SDavid van Moolenbroek 		put_close(proc, ")");
174521fa314SDavid van Moolenbroek 	}
175521fa314SDavid van Moolenbroek }
176521fa314SDavid van Moolenbroek 
177521fa314SDavid van Moolenbroek static int
pm_stime_out(struct trace_proc * proc,const message * m_out)178521fa314SDavid van Moolenbroek pm_stime_out(struct trace_proc * proc, const message * m_out)
179521fa314SDavid van Moolenbroek {
180521fa314SDavid van Moolenbroek 
181521fa314SDavid van Moolenbroek 	put_time(proc, "time", m_out->m_lc_pm_time.sec);
182521fa314SDavid van Moolenbroek 
183521fa314SDavid van Moolenbroek 	return CT_DONE;
184521fa314SDavid van Moolenbroek }
185521fa314SDavid van Moolenbroek 
186521fa314SDavid van Moolenbroek static void
put_signal(struct trace_proc * proc,const char * name,int sig)187521fa314SDavid van Moolenbroek put_signal(struct trace_proc * proc, const char * name, int sig)
188521fa314SDavid van Moolenbroek {
189521fa314SDavid van Moolenbroek 	const char *signame;
190521fa314SDavid van Moolenbroek 
191521fa314SDavid van Moolenbroek 	if (!valuesonly && (signame = get_signal_name(sig)) != NULL)
192521fa314SDavid van Moolenbroek 		put_field(proc, name, signame);
193521fa314SDavid van Moolenbroek 	else
194521fa314SDavid van Moolenbroek 		put_value(proc, name, "%d", sig);
195521fa314SDavid van Moolenbroek }
196521fa314SDavid van Moolenbroek 
197521fa314SDavid van Moolenbroek static void
put_ptrace_req(struct trace_proc * proc,const char * name,int req)198521fa314SDavid van Moolenbroek put_ptrace_req(struct trace_proc * proc, const char * name, int req)
199521fa314SDavid van Moolenbroek {
200521fa314SDavid van Moolenbroek 	const char *text = NULL;
201521fa314SDavid van Moolenbroek 
202521fa314SDavid van Moolenbroek 	if (!valuesonly) {
203521fa314SDavid van Moolenbroek 		switch (req) {
204521fa314SDavid van Moolenbroek 		TEXT(T_STOP);
205521fa314SDavid van Moolenbroek 		TEXT(T_OK);
206521fa314SDavid van Moolenbroek 		TEXT(T_ATTACH);
207521fa314SDavid van Moolenbroek 		TEXT(T_DETACH);
208521fa314SDavid van Moolenbroek 		TEXT(T_RESUME);
209521fa314SDavid van Moolenbroek 		TEXT(T_STEP);
210521fa314SDavid van Moolenbroek 		TEXT(T_SYSCALL);
211521fa314SDavid van Moolenbroek 		TEXT(T_EXIT);
212521fa314SDavid van Moolenbroek 		TEXT(T_GETINS);
213521fa314SDavid van Moolenbroek 		TEXT(T_GETDATA);
214521fa314SDavid van Moolenbroek 		TEXT(T_GETUSER);
215521fa314SDavid van Moolenbroek 		TEXT(T_SETINS);
216521fa314SDavid van Moolenbroek 		TEXT(T_SETDATA);
217521fa314SDavid van Moolenbroek 		TEXT(T_SETUSER);
218521fa314SDavid van Moolenbroek 		TEXT(T_SETOPT);
219521fa314SDavid van Moolenbroek 		TEXT(T_GETRANGE);
220521fa314SDavid van Moolenbroek 		TEXT(T_SETRANGE);
221521fa314SDavid van Moolenbroek 		TEXT(T_READB_INS);
222521fa314SDavid van Moolenbroek 		TEXT(T_WRITEB_INS);
223521fa314SDavid van Moolenbroek 		}
224521fa314SDavid van Moolenbroek 	}
225521fa314SDavid van Moolenbroek 
226521fa314SDavid van Moolenbroek 	if (text != NULL)
227521fa314SDavid van Moolenbroek 		put_field(proc, name, text);
228521fa314SDavid van Moolenbroek 	else
229521fa314SDavid van Moolenbroek 		put_value(proc, name, "%d", req);
230521fa314SDavid van Moolenbroek }
231521fa314SDavid van Moolenbroek 
232521fa314SDavid van Moolenbroek static void
put_struct_ptrace_range(struct trace_proc * proc,const char * name,int flags,vir_bytes addr)233521fa314SDavid van Moolenbroek put_struct_ptrace_range(struct trace_proc * proc, const char * name, int flags,
234521fa314SDavid van Moolenbroek 	vir_bytes addr)
235521fa314SDavid van Moolenbroek {
236521fa314SDavid van Moolenbroek 	struct ptrace_range pr;
237521fa314SDavid van Moolenbroek 
238521fa314SDavid van Moolenbroek 	if (!put_open_struct(proc, name, flags, addr, &pr, sizeof(pr)))
239521fa314SDavid van Moolenbroek 		return;
240521fa314SDavid van Moolenbroek 
241521fa314SDavid van Moolenbroek 	if (!valuesonly && pr.pr_space == TS_INS)
242521fa314SDavid van Moolenbroek 		put_field(proc, "pr_space", "TS_INS");
243521fa314SDavid van Moolenbroek 	else if (!valuesonly && pr.pr_space == TS_DATA)
244521fa314SDavid van Moolenbroek 		put_field(proc, "pr_space", "TS_DATA");
245521fa314SDavid van Moolenbroek 	else
246521fa314SDavid van Moolenbroek 		put_value(proc, "pr_space", "%d", pr.pr_space);
247521fa314SDavid van Moolenbroek 	put_value(proc, "pr_addr", "0x%lx", pr.pr_addr);
248521fa314SDavid van Moolenbroek 	put_ptr(proc, "pr_ptr", (vir_bytes)pr.pr_ptr);
249521fa314SDavid van Moolenbroek 	put_value(proc, "pr_size", "%zu", pr.pr_size);
250521fa314SDavid van Moolenbroek 
251521fa314SDavid van Moolenbroek 	put_close_struct(proc, TRUE /*all*/);
252521fa314SDavid van Moolenbroek }
253521fa314SDavid van Moolenbroek 
254521fa314SDavid van Moolenbroek static int
pm_ptrace_out(struct trace_proc * proc,const message * m_out)255521fa314SDavid van Moolenbroek pm_ptrace_out(struct trace_proc * proc, const message * m_out)
256521fa314SDavid van Moolenbroek {
257521fa314SDavid van Moolenbroek 
258521fa314SDavid van Moolenbroek 	put_ptrace_req(proc, "req", m_out->m_lc_pm_ptrace.req);
259521fa314SDavid van Moolenbroek 	put_value(proc, "pid", "%d", m_out->m_lc_pm_ptrace.pid);
260521fa314SDavid van Moolenbroek 
261521fa314SDavid van Moolenbroek 	switch (m_out->m_lc_pm_ptrace.req) {
262521fa314SDavid van Moolenbroek 	case T_GETINS:
263521fa314SDavid van Moolenbroek 	case T_GETDATA:
264521fa314SDavid van Moolenbroek 	case T_GETUSER:
265521fa314SDavid van Moolenbroek 	case T_READB_INS:
266521fa314SDavid van Moolenbroek 		put_value(proc, "addr", "0x%lx", m_out->m_lc_pm_ptrace.addr);
267521fa314SDavid van Moolenbroek 		put_value(proc, "data", "%ld", m_out->m_lc_pm_ptrace.data);
268521fa314SDavid van Moolenbroek 		break;
269521fa314SDavid van Moolenbroek 	case T_SETINS:
270521fa314SDavid van Moolenbroek 	case T_SETDATA:
271521fa314SDavid van Moolenbroek 	case T_SETUSER:
272521fa314SDavid van Moolenbroek 	case T_WRITEB_INS:
273521fa314SDavid van Moolenbroek 		put_value(proc, "addr", "0x%lx", m_out->m_lc_pm_ptrace.addr);
274521fa314SDavid van Moolenbroek 		put_value(proc, "data", "0x%lx", m_out->m_lc_pm_ptrace.data);
275521fa314SDavid van Moolenbroek 		break;
276521fa314SDavid van Moolenbroek 	case T_RESUME:
277521fa314SDavid van Moolenbroek 	case T_STEP:
278521fa314SDavid van Moolenbroek 	case T_SYSCALL:
279521fa314SDavid van Moolenbroek 		put_value(proc, "addr", "%ld", m_out->m_lc_pm_ptrace.addr);
280521fa314SDavid van Moolenbroek 		put_signal(proc, "data", m_out->m_lc_pm_ptrace.data);
281521fa314SDavid van Moolenbroek 		break;
282521fa314SDavid van Moolenbroek 	case T_GETRANGE:
283521fa314SDavid van Moolenbroek 	case T_SETRANGE:
284521fa314SDavid van Moolenbroek 		put_struct_ptrace_range(proc, "addr", 0,
285521fa314SDavid van Moolenbroek 		    m_out->m_lc_pm_ptrace.addr);
286521fa314SDavid van Moolenbroek 		put_value(proc, "data", "%ld", m_out->m_lc_pm_ptrace.data);
287521fa314SDavid van Moolenbroek 		break;
288521fa314SDavid van Moolenbroek 	default:
289521fa314SDavid van Moolenbroek 		put_value(proc, "addr", "%ld", m_out->m_lc_pm_ptrace.addr);
290521fa314SDavid van Moolenbroek 		put_value(proc, "data", "%ld", m_out->m_lc_pm_ptrace.data);
291521fa314SDavid van Moolenbroek 		break;
292521fa314SDavid van Moolenbroek 	}
293521fa314SDavid van Moolenbroek 
294521fa314SDavid van Moolenbroek 	return CT_DONE;
295521fa314SDavid van Moolenbroek }
296521fa314SDavid van Moolenbroek 
297521fa314SDavid van Moolenbroek static void
pm_ptrace_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)298521fa314SDavid van Moolenbroek pm_ptrace_in(struct trace_proc * proc, const message * m_out,
299521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
300521fa314SDavid van Moolenbroek {
301521fa314SDavid van Moolenbroek 
302521fa314SDavid van Moolenbroek 	if (!failed) {
303521fa314SDavid van Moolenbroek 		switch (m_out->m_lc_pm_ptrace.req) {
304521fa314SDavid van Moolenbroek 		case T_GETINS:
305521fa314SDavid van Moolenbroek 		case T_GETDATA:
306521fa314SDavid van Moolenbroek 		case T_GETUSER:
307521fa314SDavid van Moolenbroek 		case T_READB_INS:
308521fa314SDavid van Moolenbroek 			put_value(proc, NULL, "0x%lx",
309521fa314SDavid van Moolenbroek 			    m_in->m_pm_lc_ptrace.data);
310521fa314SDavid van Moolenbroek 			return;
311521fa314SDavid van Moolenbroek 		}
312521fa314SDavid van Moolenbroek 	}
313521fa314SDavid van Moolenbroek 
314521fa314SDavid van Moolenbroek 	put_result(proc);
315521fa314SDavid van Moolenbroek }
316521fa314SDavid van Moolenbroek 
317521fa314SDavid van Moolenbroek void
put_groups(struct trace_proc * proc,const char * name,int flags,vir_bytes addr,int count)318521fa314SDavid van Moolenbroek put_groups(struct trace_proc * proc, const char * name, int flags,
319521fa314SDavid van Moolenbroek 	vir_bytes addr, int count)
320521fa314SDavid van Moolenbroek {
321521fa314SDavid van Moolenbroek 	gid_t groups[NGROUPS_MAX];
322521fa314SDavid van Moolenbroek 	int i;
323521fa314SDavid van Moolenbroek 
324521fa314SDavid van Moolenbroek 	if ((flags & PF_FAILED) || valuesonly || count < 0 ||
325521fa314SDavid van Moolenbroek 	    count > NGROUPS_MAX || (count > 0 && mem_get_data(proc->pid, addr,
326521fa314SDavid van Moolenbroek 	    groups, count * sizeof(groups[0])) < 0)) {
327521fa314SDavid van Moolenbroek 		if (flags & PF_LOCADDR)
328521fa314SDavid van Moolenbroek 			put_field(proc, name, "&..");
329521fa314SDavid van Moolenbroek 		else
330521fa314SDavid van Moolenbroek 			put_ptr(proc, name, addr);
331521fa314SDavid van Moolenbroek 
332521fa314SDavid van Moolenbroek 		return;
333521fa314SDavid van Moolenbroek 	}
334521fa314SDavid van Moolenbroek 
335521fa314SDavid van Moolenbroek 	put_open(proc, name, PF_NONAME, "[", ", ");
336521fa314SDavid van Moolenbroek 	for (i = 0; i < count; i++)
337521fa314SDavid van Moolenbroek 		put_value(proc, NULL, "%u", groups[i]);
338521fa314SDavid van Moolenbroek 	put_close(proc, "]");
339521fa314SDavid van Moolenbroek }
340521fa314SDavid van Moolenbroek 
341521fa314SDavid van Moolenbroek static int
pm_setgroups_out(struct trace_proc * proc,const message * m_out)342521fa314SDavid van Moolenbroek pm_setgroups_out(struct trace_proc * proc, const message * m_out)
343521fa314SDavid van Moolenbroek {
344521fa314SDavid van Moolenbroek 
345521fa314SDavid van Moolenbroek 	put_value(proc, "ngroups", "%d", m_out->m_lc_pm_groups.num);
346521fa314SDavid van Moolenbroek 	put_groups(proc, "grouplist", 0, m_out->m_lc_pm_groups.ptr,
347521fa314SDavid van Moolenbroek 	    m_out->m_lc_pm_groups.num);
348521fa314SDavid van Moolenbroek 
349521fa314SDavid van Moolenbroek 	return CT_DONE;
350521fa314SDavid van Moolenbroek }
351521fa314SDavid van Moolenbroek 
352521fa314SDavid van Moolenbroek static int
pm_getgroups_out(struct trace_proc * proc,const message * m_out)353521fa314SDavid van Moolenbroek pm_getgroups_out(struct trace_proc * proc, const message * m_out)
354521fa314SDavid van Moolenbroek {
355521fa314SDavid van Moolenbroek 
356521fa314SDavid van Moolenbroek 	put_value(proc, "ngroups", "%d", m_out->m_lc_pm_groups.num);
357521fa314SDavid van Moolenbroek 
358521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
359521fa314SDavid van Moolenbroek }
360521fa314SDavid van Moolenbroek 
361521fa314SDavid van Moolenbroek static void
pm_getgroups_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)362521fa314SDavid van Moolenbroek pm_getgroups_in(struct trace_proc * proc, const message * m_out,
363521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
364521fa314SDavid van Moolenbroek {
365521fa314SDavid van Moolenbroek 
366521fa314SDavid van Moolenbroek 	put_groups(proc, "grouplist", failed, m_out->m_lc_pm_groups.ptr,
367521fa314SDavid van Moolenbroek 	    m_in->m_type);
368521fa314SDavid van Moolenbroek 	put_equals(proc);
369521fa314SDavid van Moolenbroek 	put_result(proc);
370521fa314SDavid van Moolenbroek }
371521fa314SDavid van Moolenbroek 
372521fa314SDavid van Moolenbroek static int
pm_kill_out(struct trace_proc * proc,const message * m_out)373521fa314SDavid van Moolenbroek pm_kill_out(struct trace_proc * proc, const message * m_out)
374521fa314SDavid van Moolenbroek {
375521fa314SDavid van Moolenbroek 
376521fa314SDavid van Moolenbroek 	put_value(proc, "pid", "%d", m_out->m_lc_pm_sig.pid);
377521fa314SDavid van Moolenbroek 	put_signal(proc, "sig", m_out->m_lc_pm_sig.nr);
378521fa314SDavid van Moolenbroek 
379521fa314SDavid van Moolenbroek 	return CT_DONE;
380521fa314SDavid van Moolenbroek }
381521fa314SDavid van Moolenbroek 
382521fa314SDavid van Moolenbroek /* This function is shared between setgid and setegid. */
383521fa314SDavid van Moolenbroek static int
pm_setgid_out(struct trace_proc * proc,const message * m_out)384521fa314SDavid van Moolenbroek pm_setgid_out(struct trace_proc * proc, const message * m_out)
385521fa314SDavid van Moolenbroek {
386521fa314SDavid van Moolenbroek 
387521fa314SDavid van Moolenbroek 	put_value(proc, "gid", "%u", m_out->m_lc_pm_setgid.gid);
388521fa314SDavid van Moolenbroek 
389521fa314SDavid van Moolenbroek 	return CT_DONE;
390521fa314SDavid van Moolenbroek }
391521fa314SDavid van Moolenbroek 
392521fa314SDavid van Moolenbroek static void
pm_getgid_in(struct trace_proc * proc,const message * __unused m_out,const message * m_in,int failed)393521fa314SDavid van Moolenbroek pm_getgid_in(struct trace_proc * proc, const message * __unused m_out,
394521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
395521fa314SDavid van Moolenbroek {
396521fa314SDavid van Moolenbroek 
397521fa314SDavid van Moolenbroek 	put_result(proc);
398521fa314SDavid van Moolenbroek 	if (!failed) {
399521fa314SDavid van Moolenbroek 		put_open(proc, NULL, 0, "(", ", ");
400521fa314SDavid van Moolenbroek 		put_value(proc, "egid", "%u", m_in->m_pm_lc_getgid.egid);
401521fa314SDavid van Moolenbroek 		put_close(proc, ")");
402521fa314SDavid van Moolenbroek 	}
403521fa314SDavid van Moolenbroek }
404521fa314SDavid van Moolenbroek 
405521fa314SDavid van Moolenbroek static int
put_frame_string(struct trace_proc * proc,vir_bytes frame,size_t len,vir_bytes addr)406521fa314SDavid van Moolenbroek put_frame_string(struct trace_proc * proc, vir_bytes frame, size_t len,
407521fa314SDavid van Moolenbroek 	vir_bytes addr)
408521fa314SDavid van Moolenbroek {
409521fa314SDavid van Moolenbroek 	vir_bytes stacktop, offset;
410521fa314SDavid van Moolenbroek 
411521fa314SDavid van Moolenbroek 	/*
412521fa314SDavid van Moolenbroek 	 * The addresses in the frame assume that the process has already been
413521fa314SDavid van Moolenbroek 	 * changed, and the top of the frame is now located at the new process
414521fa314SDavid van Moolenbroek 	 * stack top, which is a hardcoded system-global value.  In order to
415521fa314SDavid van Moolenbroek 	 * print the strings, we must convert back each address to its location
416521fa314SDavid van Moolenbroek 	 * within the given frame.
417521fa314SDavid van Moolenbroek 	 */
418521fa314SDavid van Moolenbroek 	stacktop = kernel_get_stacktop();
419521fa314SDavid van Moolenbroek 
420521fa314SDavid van Moolenbroek 	if (addr >= stacktop)
421521fa314SDavid van Moolenbroek 		return FALSE;
422521fa314SDavid van Moolenbroek 	offset = stacktop - addr;
423521fa314SDavid van Moolenbroek 	if (offset >= len)
424521fa314SDavid van Moolenbroek 		return FALSE;
425521fa314SDavid van Moolenbroek 	addr = frame + len - offset;
426521fa314SDavid van Moolenbroek 
427521fa314SDavid van Moolenbroek 	/*
428521fa314SDavid van Moolenbroek 	 * TODO: while using put_buf() is highly convenient, it does require at
429521fa314SDavid van Moolenbroek 	 * least one copy operation per printed string.  The strings are very
430521fa314SDavid van Moolenbroek 	 * likely to be consecutive in memory, so copying in larger chunks at
431521fa314SDavid van Moolenbroek 	 * once would be preferable.  Also, if copying from the frame fails,
432521fa314SDavid van Moolenbroek 	 * put_buf() will print the string address as we corrected it above,
433521fa314SDavid van Moolenbroek 	 * rather than the address as found in the frame.  A copy failure would
434521fa314SDavid van Moolenbroek 	 * always be a case of malice on the traced process's behalf, though.
435521fa314SDavid van Moolenbroek 	 */
436521fa314SDavid van Moolenbroek 	put_buf(proc, NULL, PF_STRING, addr, len - offset);
437521fa314SDavid van Moolenbroek 
438521fa314SDavid van Moolenbroek 	return TRUE;
439521fa314SDavid van Moolenbroek }
440521fa314SDavid van Moolenbroek 
441521fa314SDavid van Moolenbroek /*
442521fa314SDavid van Moolenbroek  * Print the contents of the exec frame, which includes both pointers and
443521fa314SDavid van Moolenbroek  * actual string data for the arguments and environment variables to be used.
444521fa314SDavid van Moolenbroek  * Even though we know that the entire frame is not going to exceed ARG_MAX
445521fa314SDavid van Moolenbroek  * bytes, this is too large a size for a static buffer, and we'd like to avoid
446521fa314SDavid van Moolenbroek  * allocating large dynamic buffers as well.  The situation is complicated by
447521fa314SDavid van Moolenbroek  * the fact that any string in the frame may run up to the end of the frame.
448521fa314SDavid van Moolenbroek  */
449521fa314SDavid van Moolenbroek static void
put_exec_frame(struct trace_proc * proc,vir_bytes addr,size_t len)450521fa314SDavid van Moolenbroek put_exec_frame(struct trace_proc * proc, vir_bytes addr, size_t len)
451521fa314SDavid van Moolenbroek {
452521fa314SDavid van Moolenbroek 	void *argv[64];
453521fa314SDavid van Moolenbroek 	size_t off, chunk;
454521fa314SDavid van Moolenbroek 	unsigned int i, count, max, argv_max, envp_max;
455521fa314SDavid van Moolenbroek 	int first, ok, nulls;
456521fa314SDavid van Moolenbroek 
457521fa314SDavid van Moolenbroek 	if (valuesonly) {
458521fa314SDavid van Moolenbroek 		put_ptr(proc, "frame", addr);
459521fa314SDavid van Moolenbroek 		put_value(proc, "framelen", "%zu", len);
460521fa314SDavid van Moolenbroek 
461521fa314SDavid van Moolenbroek 		return;
462521fa314SDavid van Moolenbroek 	}
463521fa314SDavid van Moolenbroek 
464521fa314SDavid van Moolenbroek 	if (verbose == 0) {
465521fa314SDavid van Moolenbroek 		argv_max = 16;
466521fa314SDavid van Moolenbroek 		envp_max = 0;
467521fa314SDavid van Moolenbroek 	} else if (verbose == 1)
468521fa314SDavid van Moolenbroek 		argv_max = envp_max = 64;
469521fa314SDavid van Moolenbroek 	else
470521fa314SDavid van Moolenbroek 		argv_max = envp_max = INT_MAX;
471521fa314SDavid van Moolenbroek 
472521fa314SDavid van Moolenbroek 	off = sizeof(int); /* skip 'argc' at the start of the frame */
473521fa314SDavid van Moolenbroek 	first = TRUE;
474521fa314SDavid van Moolenbroek 	ok = TRUE;
475521fa314SDavid van Moolenbroek 	nulls = 0;
476521fa314SDavid van Moolenbroek 	count = 0;
477521fa314SDavid van Moolenbroek 	max = argv_max;
478521fa314SDavid van Moolenbroek 
479521fa314SDavid van Moolenbroek 	do {
480521fa314SDavid van Moolenbroek 		chunk = sizeof(argv);
481521fa314SDavid van Moolenbroek 		if (chunk > len - off)
482521fa314SDavid van Moolenbroek 			chunk = len - off;
483521fa314SDavid van Moolenbroek 
484521fa314SDavid van Moolenbroek 		if (mem_get_data(proc->pid, addr + off, argv, chunk) != 0)
485521fa314SDavid van Moolenbroek 			break;
486521fa314SDavid van Moolenbroek 
487521fa314SDavid van Moolenbroek 		if (first) {
488521fa314SDavid van Moolenbroek 			put_open(proc, "argv", PF_NONAME, "[", ", ");
489521fa314SDavid van Moolenbroek 
490521fa314SDavid van Moolenbroek 			first = FALSE;
491521fa314SDavid van Moolenbroek 		}
492521fa314SDavid van Moolenbroek 
493521fa314SDavid van Moolenbroek 		for (i = 0; i < chunk / sizeof(void *) && ok; i++) {
494521fa314SDavid van Moolenbroek 			if (argv[i] == NULL) {
495521fa314SDavid van Moolenbroek 				if (count > max)
496521fa314SDavid van Moolenbroek 					put_tail(proc, count, max);
497521fa314SDavid van Moolenbroek 				put_close(proc, "]");
498521fa314SDavid van Moolenbroek 				if (nulls++ == 0) {
499521fa314SDavid van Moolenbroek 					put_open(proc, "envp", PF_NONAME, "[",
500521fa314SDavid van Moolenbroek 					    ", ");
501521fa314SDavid van Moolenbroek 					count = 0;
502521fa314SDavid van Moolenbroek 					max = envp_max;
503521fa314SDavid van Moolenbroek 				} else
504521fa314SDavid van Moolenbroek 					break; /* two NULL pointers: done! */
505521fa314SDavid van Moolenbroek 			} else if (count++ < max)
506521fa314SDavid van Moolenbroek 				ok = put_frame_string(proc, addr, len,
507521fa314SDavid van Moolenbroek 				    (vir_bytes)argv[i]);
508521fa314SDavid van Moolenbroek 		}
509521fa314SDavid van Moolenbroek 
510521fa314SDavid van Moolenbroek 		off += chunk;
511521fa314SDavid van Moolenbroek 	} while (nulls < 2 && ok);
512521fa314SDavid van Moolenbroek 
513521fa314SDavid van Moolenbroek 	/*
514521fa314SDavid van Moolenbroek 	 * Handle failure cases, implied by not reaching the second NULL
515521fa314SDavid van Moolenbroek 	 * in the array.  Successful completion is handled in the loop above.
516521fa314SDavid van Moolenbroek 	 * Note that 'ok' is not always cleared on failure, as it is used only
517521fa314SDavid van Moolenbroek 	 * to break out of the outer loop.
518521fa314SDavid van Moolenbroek 	 */
519521fa314SDavid van Moolenbroek 	if (first) {
520521fa314SDavid van Moolenbroek 		put_ptr(proc, "argv", addr + off);
521521fa314SDavid van Moolenbroek 		put_field(proc, "envp", "&..");
522521fa314SDavid van Moolenbroek 	} else if (nulls < 2) {
523521fa314SDavid van Moolenbroek 		put_tail(proc, 0, 0);
524521fa314SDavid van Moolenbroek 		put_close(proc, "]");
525521fa314SDavid van Moolenbroek 		if (nulls < 1) {
526521fa314SDavid van Moolenbroek 			put_open(proc, "envp", PF_NONAME, "[", ", ");
527521fa314SDavid van Moolenbroek 			put_tail(proc, 0, 0);
528521fa314SDavid van Moolenbroek 			put_close(proc, "]");
529521fa314SDavid van Moolenbroek 		}
530521fa314SDavid van Moolenbroek 	}
531521fa314SDavid van Moolenbroek }
532521fa314SDavid van Moolenbroek 
533521fa314SDavid van Moolenbroek static int
pm_exec_out(struct trace_proc * proc,const message * m_out)534521fa314SDavid van Moolenbroek pm_exec_out(struct trace_proc * proc, const message * m_out)
535521fa314SDavid van Moolenbroek {
536521fa314SDavid van Moolenbroek 
537521fa314SDavid van Moolenbroek 	put_buf(proc, "path", PF_PATH, m_out->m_lc_pm_exec.name,
538521fa314SDavid van Moolenbroek 	    m_out->m_lc_pm_exec.namelen);
539521fa314SDavid van Moolenbroek 	put_exec_frame(proc, m_out->m_lc_pm_exec.frame,
540521fa314SDavid van Moolenbroek 	    m_out->m_lc_pm_exec.framelen);
541521fa314SDavid van Moolenbroek 
542521fa314SDavid van Moolenbroek 	return CT_NORETURN;
543521fa314SDavid van Moolenbroek }
544521fa314SDavid van Moolenbroek 
545521fa314SDavid van Moolenbroek /* The idea is that this function may one day print a human-readable time. */
546521fa314SDavid van Moolenbroek void
put_time(struct trace_proc * proc,const char * name,time_t time)547521fa314SDavid van Moolenbroek put_time(struct trace_proc * proc, const char * name, time_t time)
548521fa314SDavid van Moolenbroek {
549521fa314SDavid van Moolenbroek 
550521fa314SDavid van Moolenbroek 	put_value(proc, name, "%"PRId64, time);
551521fa314SDavid van Moolenbroek }
552521fa314SDavid van Moolenbroek 
553521fa314SDavid van Moolenbroek void
put_struct_timeval(struct trace_proc * proc,const char * name,int flags,vir_bytes addr)554521fa314SDavid van Moolenbroek put_struct_timeval(struct trace_proc * proc, const char * name, int flags,
555521fa314SDavid van Moolenbroek 	vir_bytes addr)
556521fa314SDavid van Moolenbroek {
557521fa314SDavid van Moolenbroek 	struct timeval tv;
558521fa314SDavid van Moolenbroek 
559521fa314SDavid van Moolenbroek 	/* No field names; they just make things harder to read. */
560521fa314SDavid van Moolenbroek 	if (!put_open_struct(proc, name, flags | PF_NONAME, addr, &tv,
561521fa314SDavid van Moolenbroek 	    sizeof(tv)))
562521fa314SDavid van Moolenbroek 		return;
563521fa314SDavid van Moolenbroek 
564521fa314SDavid van Moolenbroek 	if (flags & PF_ALT)
565521fa314SDavid van Moolenbroek 		put_time(proc, "tv_sec", tv.tv_sec);
566521fa314SDavid van Moolenbroek 	else
567521fa314SDavid van Moolenbroek 		put_value(proc, "tv_sec", "%"PRId64, tv.tv_sec);
568521fa314SDavid van Moolenbroek 	put_value(proc, "tv_usec", "%d", tv.tv_usec);
569521fa314SDavid van Moolenbroek 
570521fa314SDavid van Moolenbroek 	put_close_struct(proc, TRUE /*all*/);
571521fa314SDavid van Moolenbroek }
572521fa314SDavid van Moolenbroek 
573521fa314SDavid van Moolenbroek static void
put_struct_itimerval(struct trace_proc * proc,const char * name,int flags,vir_bytes addr)574521fa314SDavid van Moolenbroek put_struct_itimerval(struct trace_proc * proc, const char * name, int flags,
575521fa314SDavid van Moolenbroek 	vir_bytes addr)
576521fa314SDavid van Moolenbroek {
577521fa314SDavid van Moolenbroek 	struct itimerval it;
578521fa314SDavid van Moolenbroek 
579521fa314SDavid van Moolenbroek 	/*
580521fa314SDavid van Moolenbroek 	 * This used to pass PF_NONAME, but the layout may not be clear enough
581521fa314SDavid van Moolenbroek 	 * without names.  It does turn simple alarm(1) calls into rather
582521fa314SDavid van Moolenbroek 	 * lengthy output, though.
583521fa314SDavid van Moolenbroek 	 */
584521fa314SDavid van Moolenbroek 	if (!put_open_struct(proc, name, flags, addr, &it, sizeof(it)))
585521fa314SDavid van Moolenbroek 		return;
586521fa314SDavid van Moolenbroek 
587521fa314SDavid van Moolenbroek 	put_struct_timeval(proc, "it_interval", PF_LOCADDR,
588521fa314SDavid van Moolenbroek 	    (vir_bytes)&it.it_interval);
589521fa314SDavid van Moolenbroek 	put_struct_timeval(proc, "it_value", PF_LOCADDR,
590521fa314SDavid van Moolenbroek 	    (vir_bytes)&it.it_value);
591521fa314SDavid van Moolenbroek 
592521fa314SDavid van Moolenbroek 	put_close_struct(proc, TRUE /*all*/);
593521fa314SDavid van Moolenbroek }
594521fa314SDavid van Moolenbroek 
595521fa314SDavid van Moolenbroek static void
put_itimer_which(struct trace_proc * proc,const char * name,int which)596521fa314SDavid van Moolenbroek put_itimer_which(struct trace_proc * proc, const char * name, int which)
597521fa314SDavid van Moolenbroek {
598521fa314SDavid van Moolenbroek 	const char *text = NULL;
599521fa314SDavid van Moolenbroek 
600521fa314SDavid van Moolenbroek 	if (!valuesonly) {
601521fa314SDavid van Moolenbroek 		switch (which) {
602521fa314SDavid van Moolenbroek 		TEXT(ITIMER_REAL);
603521fa314SDavid van Moolenbroek 		TEXT(ITIMER_VIRTUAL);
604521fa314SDavid van Moolenbroek 		TEXT(ITIMER_PROF);
605521fa314SDavid van Moolenbroek 		TEXT(ITIMER_MONOTONIC);
606521fa314SDavid van Moolenbroek 		}
607521fa314SDavid van Moolenbroek 	}
608521fa314SDavid van Moolenbroek 
609521fa314SDavid van Moolenbroek 	if (text != NULL)
610521fa314SDavid van Moolenbroek 		put_field(proc, name, text);
611521fa314SDavid van Moolenbroek 	else
612521fa314SDavid van Moolenbroek 		put_value(proc, name, "%d", which);
613521fa314SDavid van Moolenbroek }
614521fa314SDavid van Moolenbroek 
615521fa314SDavid van Moolenbroek static const char *
pm_itimer_name(const message * m_out)616521fa314SDavid van Moolenbroek pm_itimer_name(const message * m_out)
617521fa314SDavid van Moolenbroek {
618521fa314SDavid van Moolenbroek 
619521fa314SDavid van Moolenbroek 	return (m_out->m_lc_pm_itimer.value != 0) ? "setitimer" : "getitimer";
620521fa314SDavid van Moolenbroek }
621521fa314SDavid van Moolenbroek 
622521fa314SDavid van Moolenbroek static int
pm_itimer_out(struct trace_proc * proc,const message * m_out)623521fa314SDavid van Moolenbroek pm_itimer_out(struct trace_proc * proc, const message * m_out)
624521fa314SDavid van Moolenbroek {
625521fa314SDavid van Moolenbroek 
626521fa314SDavid van Moolenbroek 	put_itimer_which(proc, "which", m_out->m_lc_pm_itimer.which);
627521fa314SDavid van Moolenbroek 	if (m_out->m_lc_pm_itimer.value != 0) {
628521fa314SDavid van Moolenbroek 		put_struct_itimerval(proc, "value", 0,
629521fa314SDavid van Moolenbroek 		    m_out->m_lc_pm_itimer.value);
630521fa314SDavid van Moolenbroek 
631521fa314SDavid van Moolenbroek 		/*
632521fa314SDavid van Moolenbroek 		 * If there will be no old values to print, finish the call
633521fa314SDavid van Moolenbroek 		 * now.  For setitimer only; getitimer may not pass NULL.
634521fa314SDavid van Moolenbroek 		 */
635521fa314SDavid van Moolenbroek 		if (m_out->m_lc_pm_itimer.ovalue == 0) {
636521fa314SDavid van Moolenbroek 			put_ptr(proc, "ovalue", 0);
637521fa314SDavid van Moolenbroek 
638521fa314SDavid van Moolenbroek 			return CT_DONE;
639521fa314SDavid van Moolenbroek 		}
640521fa314SDavid van Moolenbroek 	}
641521fa314SDavid van Moolenbroek 
642521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
643521fa314SDavid van Moolenbroek }
644521fa314SDavid van Moolenbroek 
645521fa314SDavid van Moolenbroek static void
pm_itimer_in(struct trace_proc * proc,const message * m_out,const message * __unused m_in,int failed)646521fa314SDavid van Moolenbroek pm_itimer_in(struct trace_proc * proc, const message * m_out,
647521fa314SDavid van Moolenbroek 	const message * __unused m_in, int failed)
648521fa314SDavid van Moolenbroek {
649521fa314SDavid van Moolenbroek 
650521fa314SDavid van Moolenbroek 	if (m_out->m_lc_pm_itimer.value == 0 ||
651521fa314SDavid van Moolenbroek 	    m_out->m_lc_pm_itimer.ovalue != 0) {
652521fa314SDavid van Moolenbroek 		put_struct_itimerval(proc,
653521fa314SDavid van Moolenbroek 		    (m_out->m_lc_pm_itimer.value != 0) ? "ovalue" : "value",
654521fa314SDavid van Moolenbroek 		    failed, m_out->m_lc_pm_itimer.ovalue);
655521fa314SDavid van Moolenbroek 		put_equals(proc);
656521fa314SDavid van Moolenbroek 	}
657521fa314SDavid van Moolenbroek 	put_result(proc);
658521fa314SDavid van Moolenbroek }
659521fa314SDavid van Moolenbroek 
660521fa314SDavid van Moolenbroek static void
put_struct_mcontext(struct trace_proc * proc,const char * name,int flags,vir_bytes addr)661521fa314SDavid van Moolenbroek put_struct_mcontext(struct trace_proc * proc, const char * name, int flags,
662521fa314SDavid van Moolenbroek 	vir_bytes addr)
663521fa314SDavid van Moolenbroek {
664521fa314SDavid van Moolenbroek 	mcontext_t ctx;
665521fa314SDavid van Moolenbroek 
666521fa314SDavid van Moolenbroek 	if (!put_open_struct(proc, name, flags, addr, &ctx, sizeof(ctx)))
667521fa314SDavid van Moolenbroek 		return;
668521fa314SDavid van Moolenbroek 
669521fa314SDavid van Moolenbroek 	/*
670521fa314SDavid van Moolenbroek 	 * TODO: print actual fields.  Then again, the ones that are saved and
671521fa314SDavid van Moolenbroek 	 * restored (FPU state) are hardly interesting enough to print..
672521fa314SDavid van Moolenbroek 	 */
673521fa314SDavid van Moolenbroek 
674521fa314SDavid van Moolenbroek 	put_close_struct(proc, FALSE /*all*/);
675521fa314SDavid van Moolenbroek }
676521fa314SDavid van Moolenbroek 
677521fa314SDavid van Moolenbroek static int
pm_getmcontext_out(struct trace_proc * proc,const message * m_out)678521fa314SDavid van Moolenbroek pm_getmcontext_out(struct trace_proc * proc, const message * m_out)
679521fa314SDavid van Moolenbroek {
680521fa314SDavid van Moolenbroek 
681521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
682521fa314SDavid van Moolenbroek }
683521fa314SDavid van Moolenbroek 
684521fa314SDavid van Moolenbroek static void
pm_getmcontext_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)685521fa314SDavid van Moolenbroek pm_getmcontext_in(struct trace_proc * proc, const message * m_out,
686521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
687521fa314SDavid van Moolenbroek {
688521fa314SDavid van Moolenbroek 
689521fa314SDavid van Moolenbroek 	put_struct_mcontext(proc, "mcp", failed, m_out->m_lc_pm_mcontext.ctx);
690521fa314SDavid van Moolenbroek 	put_equals(proc);
691521fa314SDavid van Moolenbroek 	put_result(proc);
692521fa314SDavid van Moolenbroek }
693521fa314SDavid van Moolenbroek 
694521fa314SDavid van Moolenbroek static int
pm_setmcontext_out(struct trace_proc * proc,const message * m_out)695521fa314SDavid van Moolenbroek pm_setmcontext_out(struct trace_proc * proc, const message * m_out)
696521fa314SDavid van Moolenbroek {
697521fa314SDavid van Moolenbroek 
698521fa314SDavid van Moolenbroek 	put_struct_mcontext(proc, "mcp", 0, m_out->m_lc_pm_mcontext.ctx);
699521fa314SDavid van Moolenbroek 
700521fa314SDavid van Moolenbroek 	return CT_DONE;
701521fa314SDavid van Moolenbroek }
702521fa314SDavid van Moolenbroek 
703521fa314SDavid van Moolenbroek static void
put_sigset(struct trace_proc * proc,const char * name,sigset_t set)704521fa314SDavid van Moolenbroek put_sigset(struct trace_proc * proc, const char * name, sigset_t set)
705521fa314SDavid van Moolenbroek {
706521fa314SDavid van Moolenbroek 	const char *signame;
707521fa314SDavid van Moolenbroek 	unsigned int count, unknown;
708521fa314SDavid van Moolenbroek 	int sig, invert;
709521fa314SDavid van Moolenbroek 
710521fa314SDavid van Moolenbroek 	/*
711521fa314SDavid van Moolenbroek 	 * First decide whether we should print a normal or an inverted mask.
712521fa314SDavid van Moolenbroek 	 * Unfortunately, depending on the place, a filled set may or may not
713521fa314SDavid van Moolenbroek 	 * have bits outside the 1..NSIG range set.  Therefore, we ignore the
714521fa314SDavid van Moolenbroek 	 * bits outside this range entirely, and use simple heuristics to
715521fa314SDavid van Moolenbroek 	 * decide whether to show an inverted set.  If we know all the signal
716521fa314SDavid van Moolenbroek 	 * names for either set and not the other, show that one; otherwise,
717521fa314SDavid van Moolenbroek 	 * show an inverted mask if at least 3/4th of the bits are set.
718521fa314SDavid van Moolenbroek 	 */
719521fa314SDavid van Moolenbroek 	count = 0;
720521fa314SDavid van Moolenbroek 	unknown = 0;
721521fa314SDavid van Moolenbroek 	for (sig = 1; sig < NSIG; sig++) {
722521fa314SDavid van Moolenbroek 		if (sigismember(&set, sig))
723521fa314SDavid van Moolenbroek 			count++;
724521fa314SDavid van Moolenbroek 		if (get_signal_name(sig) == NULL)
725521fa314SDavid van Moolenbroek 			unknown |= 1 << !!sigismember(&set, sig);
726521fa314SDavid van Moolenbroek 	}
727521fa314SDavid van Moolenbroek 	if (unknown == 1 /*for unset bit*/ || unknown == 2 /*for set bit*/)
728521fa314SDavid van Moolenbroek 		invert = unknown - 1;
729521fa314SDavid van Moolenbroek 	else
730521fa314SDavid van Moolenbroek 		invert = (count >= (NSIG - 1) * 3 / 4);
731521fa314SDavid van Moolenbroek 
732521fa314SDavid van Moolenbroek 	put_open(proc, name, PF_NONAME, invert ? "~[" : "[", " ");
733521fa314SDavid van Moolenbroek 
734521fa314SDavid van Moolenbroek 	for (sig = 1; sig < NSIG; sig++) {
735521fa314SDavid van Moolenbroek 		/* Note that sigismember() may not strictly return 0 or 1.. */
736521fa314SDavid van Moolenbroek 		if (!sigismember(&set, sig) != invert)
737521fa314SDavid van Moolenbroek 			continue;
738521fa314SDavid van Moolenbroek 
739521fa314SDavid van Moolenbroek 		if ((signame = get_signal_name(sig)) != NULL) {
740521fa314SDavid van Moolenbroek 			/* Skip the "SIG" prefix for brevity. */
741521fa314SDavid van Moolenbroek 			if (!strncmp(signame, "SIG", 3))
742521fa314SDavid van Moolenbroek 				put_field(proc, NULL, &signame[3]);
743521fa314SDavid van Moolenbroek 			else
744521fa314SDavid van Moolenbroek 				put_field(proc, NULL, signame);
745521fa314SDavid van Moolenbroek 		} else
746521fa314SDavid van Moolenbroek 			put_value(proc, NULL, "%d", sig);
747521fa314SDavid van Moolenbroek 	}
748521fa314SDavid van Moolenbroek 
749521fa314SDavid van Moolenbroek 	put_close(proc, "]");
750521fa314SDavid van Moolenbroek }
751521fa314SDavid van Moolenbroek 
752521fa314SDavid van Moolenbroek static const struct flags sa_flags[] = {
753521fa314SDavid van Moolenbroek 	FLAG(SA_ONSTACK),
754521fa314SDavid van Moolenbroek 	FLAG(SA_RESTART),
755521fa314SDavid van Moolenbroek 	FLAG(SA_RESETHAND),
756521fa314SDavid van Moolenbroek 	FLAG(SA_NODEFER),
757521fa314SDavid van Moolenbroek 	FLAG(SA_NOCLDSTOP),
758521fa314SDavid van Moolenbroek 	FLAG(SA_NOCLDWAIT),
759521fa314SDavid van Moolenbroek #ifdef SA_SIGINFO
760521fa314SDavid van Moolenbroek 	FLAG(SA_SIGINFO),
761521fa314SDavid van Moolenbroek #endif
762521fa314SDavid van Moolenbroek 	FLAG(SA_NOKERNINFO)
763521fa314SDavid van Moolenbroek };
764521fa314SDavid van Moolenbroek 
765521fa314SDavid van Moolenbroek static void
put_sa_handler(struct trace_proc * proc,const char * name,vir_bytes handler)766521fa314SDavid van Moolenbroek put_sa_handler(struct trace_proc * proc, const char * name, vir_bytes handler)
767521fa314SDavid van Moolenbroek {
768521fa314SDavid van Moolenbroek 	const char *text = NULL;
769521fa314SDavid van Moolenbroek 
770521fa314SDavid van Moolenbroek 	if (!valuesonly) {
771521fa314SDavid van Moolenbroek 		switch ((int)handler) {
772521fa314SDavid van Moolenbroek 		case (int)SIG_DFL: text = "SIG_DFL"; break;
773521fa314SDavid van Moolenbroek 		case (int)SIG_IGN: text = "SIG_IGN"; break;
774521fa314SDavid van Moolenbroek 		case (int)SIG_HOLD: text = "SIG_HOLD"; break;
775521fa314SDavid van Moolenbroek 		}
776521fa314SDavid van Moolenbroek 	}
777521fa314SDavid van Moolenbroek 
778521fa314SDavid van Moolenbroek 	if (text != NULL)
779521fa314SDavid van Moolenbroek 		put_field(proc, name, text);
780521fa314SDavid van Moolenbroek 	else
781521fa314SDavid van Moolenbroek 		put_ptr(proc, name, handler);
782521fa314SDavid van Moolenbroek }
783521fa314SDavid van Moolenbroek 
784521fa314SDavid van Moolenbroek static void
put_struct_sigaction(struct trace_proc * proc,const char * name,int flags,vir_bytes addr)785521fa314SDavid van Moolenbroek put_struct_sigaction(struct trace_proc * proc, const char * name, int flags,
786521fa314SDavid van Moolenbroek 	vir_bytes addr)
787521fa314SDavid van Moolenbroek {
788521fa314SDavid van Moolenbroek 	struct sigaction sa;
789521fa314SDavid van Moolenbroek 
790521fa314SDavid van Moolenbroek 	if (!put_open_struct(proc, name, flags, addr, &sa, sizeof(sa)))
791521fa314SDavid van Moolenbroek 		return;
792521fa314SDavid van Moolenbroek 
793521fa314SDavid van Moolenbroek 	put_sa_handler(proc, "sa_handler", (vir_bytes)sa.sa_handler);
794521fa314SDavid van Moolenbroek 
795521fa314SDavid van Moolenbroek 	if (verbose > 1)
796521fa314SDavid van Moolenbroek 		put_sigset(proc, "sa_mask", sa.sa_mask);
797521fa314SDavid van Moolenbroek 
798521fa314SDavid van Moolenbroek 	/* A somewhat lame attempt to reduce noise a bit. */
799521fa314SDavid van Moolenbroek 	if ((sa.sa_flags & ~(SA_ONSTACK | SA_RESTART | SA_RESETHAND |
800521fa314SDavid van Moolenbroek 	    SA_NODEFER)) != 0 || sa.sa_handler != SIG_DFL || verbose > 0)
801521fa314SDavid van Moolenbroek 		put_flags(proc, "sa_flags", sa_flags, COUNT(sa_flags), "0x%x",
802521fa314SDavid van Moolenbroek 		    sa.sa_flags);
803521fa314SDavid van Moolenbroek 
804521fa314SDavid van Moolenbroek 	put_close_struct(proc, verbose > 1);
805521fa314SDavid van Moolenbroek }
806521fa314SDavid van Moolenbroek 
807521fa314SDavid van Moolenbroek static int
pm_sigaction_out(struct trace_proc * proc,const message * m_out)808521fa314SDavid van Moolenbroek pm_sigaction_out(struct trace_proc * proc, const message * m_out)
809521fa314SDavid van Moolenbroek {
810521fa314SDavid van Moolenbroek 
811521fa314SDavid van Moolenbroek 	put_signal(proc, "signal", m_out->m_lc_pm_sig.nr);
812521fa314SDavid van Moolenbroek 	put_struct_sigaction(proc, "act", 0, m_out->m_lc_pm_sig.act);
813521fa314SDavid van Moolenbroek 
814521fa314SDavid van Moolenbroek 	/* If there will be no old values to print, finish the call now. */
815521fa314SDavid van Moolenbroek 	if (m_out->m_lc_pm_sig.oact == 0) {
816521fa314SDavid van Moolenbroek 		put_ptr(proc, "oact", 0);
817521fa314SDavid van Moolenbroek 		return CT_DONE;
818521fa314SDavid van Moolenbroek 	} else
819521fa314SDavid van Moolenbroek 		return CT_NOTDONE;
820521fa314SDavid van Moolenbroek }
821521fa314SDavid van Moolenbroek 
822521fa314SDavid van Moolenbroek static void
pm_sigaction_in(struct trace_proc * proc,const message * m_out,const message * __unused m_in,int failed)823521fa314SDavid van Moolenbroek pm_sigaction_in(struct trace_proc * proc, const message * m_out,
824521fa314SDavid van Moolenbroek 	const message * __unused m_in, int failed)
825521fa314SDavid van Moolenbroek {
826521fa314SDavid van Moolenbroek 
827521fa314SDavid van Moolenbroek 	if (m_out->m_lc_pm_sig.oact != 0) {
828521fa314SDavid van Moolenbroek 		put_struct_sigaction(proc, "oact", failed,
829521fa314SDavid van Moolenbroek 		    m_out->m_lc_pm_sig.oact);
830521fa314SDavid van Moolenbroek 		put_equals(proc);
831521fa314SDavid van Moolenbroek 	}
832521fa314SDavid van Moolenbroek 	put_result(proc);
833521fa314SDavid van Moolenbroek }
834521fa314SDavid van Moolenbroek 
835521fa314SDavid van Moolenbroek static int
pm_sigsuspend_out(struct trace_proc * proc,const message * m_out)836521fa314SDavid van Moolenbroek pm_sigsuspend_out(struct trace_proc * proc, const message * m_out)
837521fa314SDavid van Moolenbroek {
838521fa314SDavid van Moolenbroek 
839521fa314SDavid van Moolenbroek 	put_sigset(proc, "set", m_out->m_lc_pm_sigset.set);
840521fa314SDavid van Moolenbroek 
841521fa314SDavid van Moolenbroek 	return CT_DONE;
842521fa314SDavid van Moolenbroek }
843521fa314SDavid van Moolenbroek 
844521fa314SDavid van Moolenbroek static int
pm_sigpending_out(struct trace_proc * __unused proc,const message * __unused m_out)845521fa314SDavid van Moolenbroek pm_sigpending_out(struct trace_proc * __unused proc,
846521fa314SDavid van Moolenbroek 	const message * __unused m_out)
847521fa314SDavid van Moolenbroek {
848521fa314SDavid van Moolenbroek 
849521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
850521fa314SDavid van Moolenbroek }
851521fa314SDavid van Moolenbroek 
852521fa314SDavid van Moolenbroek static void
pm_sigpending_in(struct trace_proc * proc,const message * __unused m_out,const message * m_in,int failed)853521fa314SDavid van Moolenbroek pm_sigpending_in(struct trace_proc * proc, const message * __unused m_out,
854521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
855521fa314SDavid van Moolenbroek {
856521fa314SDavid van Moolenbroek 
857521fa314SDavid van Moolenbroek 	if (!failed)
858521fa314SDavid van Moolenbroek 		put_sigset(proc, "set", m_in->m_pm_lc_sigset.set);
859521fa314SDavid van Moolenbroek 	else
860521fa314SDavid van Moolenbroek 		put_field(proc, "set", "&..");
861521fa314SDavid van Moolenbroek 	put_equals(proc);
862521fa314SDavid van Moolenbroek 	put_result(proc);
863521fa314SDavid van Moolenbroek }
864521fa314SDavid van Moolenbroek 
865521fa314SDavid van Moolenbroek static void
put_sigprocmask_how(struct trace_proc * proc,const char * name,int how)866521fa314SDavid van Moolenbroek put_sigprocmask_how(struct trace_proc * proc, const char * name, int how)
867521fa314SDavid van Moolenbroek {
868521fa314SDavid van Moolenbroek 	const char *text = NULL;
869521fa314SDavid van Moolenbroek 
870521fa314SDavid van Moolenbroek 	if (!valuesonly) {
871521fa314SDavid van Moolenbroek 		switch (how) {
872521fa314SDavid van Moolenbroek 		case SIG_INQUIRE: /* pseudocode, print something else */
873521fa314SDavid van Moolenbroek 		TEXT(SIG_BLOCK);
874521fa314SDavid van Moolenbroek 		TEXT(SIG_UNBLOCK);
875521fa314SDavid van Moolenbroek 		TEXT(SIG_SETMASK);
876521fa314SDavid van Moolenbroek 		}
877521fa314SDavid van Moolenbroek 	}
878521fa314SDavid van Moolenbroek 
879521fa314SDavid van Moolenbroek 	if (text != NULL)
880521fa314SDavid van Moolenbroek 		put_field(proc, name, text);
881521fa314SDavid van Moolenbroek 	else
882521fa314SDavid van Moolenbroek 		put_value(proc, name, "%d", how);
883521fa314SDavid van Moolenbroek }
884521fa314SDavid van Moolenbroek 
885521fa314SDavid van Moolenbroek static int
pm_sigprocmask_out(struct trace_proc * proc,const message * m_out)886521fa314SDavid van Moolenbroek pm_sigprocmask_out(struct trace_proc * proc, const message * m_out)
887521fa314SDavid van Moolenbroek {
888521fa314SDavid van Moolenbroek 
889521fa314SDavid van Moolenbroek 	put_sigprocmask_how(proc, "how", m_out->m_lc_pm_sigset.how);
890521fa314SDavid van Moolenbroek 	if (m_out->m_lc_pm_sigset.how == SIG_INQUIRE)
891521fa314SDavid van Moolenbroek 		put_ptr(proc, "set", 0);
892521fa314SDavid van Moolenbroek 	else
893521fa314SDavid van Moolenbroek 		put_sigset(proc, "set", m_out->m_lc_pm_sigset.set);
894521fa314SDavid van Moolenbroek 
895521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
896521fa314SDavid van Moolenbroek }
897521fa314SDavid van Moolenbroek 
898521fa314SDavid van Moolenbroek static void
pm_sigprocmask_in(struct trace_proc * proc,const message * __unused m_out,const message * m_in,int failed)899521fa314SDavid van Moolenbroek pm_sigprocmask_in(struct trace_proc * proc, const message * __unused m_out,
900521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
901521fa314SDavid van Moolenbroek {
902521fa314SDavid van Moolenbroek 
903521fa314SDavid van Moolenbroek 	if (!failed)
904521fa314SDavid van Moolenbroek 		put_sigset(proc, "oset", m_in->m_pm_lc_sigset.set);
905521fa314SDavid van Moolenbroek 	else
906521fa314SDavid van Moolenbroek 		put_field(proc, "oset", "&..");
907521fa314SDavid van Moolenbroek 	put_equals(proc);
908521fa314SDavid van Moolenbroek 	put_result(proc);
909521fa314SDavid van Moolenbroek }
910521fa314SDavid van Moolenbroek 
911521fa314SDavid van Moolenbroek static int
pm_sigreturn_out(struct trace_proc * proc,const message * m_out)912521fa314SDavid van Moolenbroek pm_sigreturn_out(struct trace_proc * proc, const message * m_out)
913521fa314SDavid van Moolenbroek {
914521fa314SDavid van Moolenbroek 	struct sigcontext scp;
915521fa314SDavid van Moolenbroek 
916521fa314SDavid van Moolenbroek 	if (put_open_struct(proc, "scp", 0, m_out->m_lc_pm_sigset.ctx, &scp,
917521fa314SDavid van Moolenbroek 	    sizeof(scp))) {
918521fa314SDavid van Moolenbroek 		if (verbose == 1) {
919521fa314SDavid van Moolenbroek #if defined(__i386__)
920521fa314SDavid van Moolenbroek 			put_ptr(proc, "sc_eip", scp.sc_eip);
921521fa314SDavid van Moolenbroek 			put_ptr(proc, "sc_esp", scp.sc_esp);
922521fa314SDavid van Moolenbroek #elif defined(__arm__)
923521fa314SDavid van Moolenbroek 			put_ptr(proc, "sc_pc", scp.sc_pc);
924521fa314SDavid van Moolenbroek 			put_ptr(proc, "sc_usr_sp", scp.sc_usr_sp);
925521fa314SDavid van Moolenbroek #endif
926521fa314SDavid van Moolenbroek 		}
927521fa314SDavid van Moolenbroek 
928521fa314SDavid van Moolenbroek 		/*
929521fa314SDavid van Moolenbroek 		 * We deliberately print the signal set from the message rather
930521fa314SDavid van Moolenbroek 		 * than from the structure, since in theory they may be
931521fa314SDavid van Moolenbroek 		 * different and PM uses the one from the message only.
932521fa314SDavid van Moolenbroek 		 */
933521fa314SDavid van Moolenbroek 		put_sigset(proc, "sc_mask", m_out->m_lc_pm_sigset.set);
934521fa314SDavid van Moolenbroek 
935521fa314SDavid van Moolenbroek 		/*
936521fa314SDavid van Moolenbroek 		 * TODO: print some other fields, although it is probably not
937521fa314SDavid van Moolenbroek 		 * useful to print all registers even with verbose > 1?
938521fa314SDavid van Moolenbroek 		 */
939521fa314SDavid van Moolenbroek 		put_close_struct(proc, FALSE /*all*/);
940521fa314SDavid van Moolenbroek 	}
941521fa314SDavid van Moolenbroek 
942521fa314SDavid van Moolenbroek 	return CT_NORETURN;
943521fa314SDavid van Moolenbroek }
944521fa314SDavid van Moolenbroek 
945521fa314SDavid van Moolenbroek static void
pm_sigreturn_in(struct trace_proc * proc,const message * __unused m_out,const message * __unused m_in,int failed)946521fa314SDavid van Moolenbroek pm_sigreturn_in(struct trace_proc * proc, const message * __unused m_out,
947521fa314SDavid van Moolenbroek 	const message * __unused m_in, int failed)
948521fa314SDavid van Moolenbroek {
949521fa314SDavid van Moolenbroek 
950521fa314SDavid van Moolenbroek 	if (failed) {
951521fa314SDavid van Moolenbroek 		put_equals(proc);
952521fa314SDavid van Moolenbroek 		put_result(proc);
953521fa314SDavid van Moolenbroek 	}
954521fa314SDavid van Moolenbroek }
955521fa314SDavid van Moolenbroek 
956521fa314SDavid van Moolenbroek static void
put_priority_which(struct trace_proc * proc,const char * name,int which)957521fa314SDavid van Moolenbroek put_priority_which(struct trace_proc * proc, const char * name, int which)
958521fa314SDavid van Moolenbroek {
959521fa314SDavid van Moolenbroek 	const char *text = NULL;
960521fa314SDavid van Moolenbroek 
961521fa314SDavid van Moolenbroek 	if (!valuesonly) {
962521fa314SDavid van Moolenbroek 		switch (which) {
963521fa314SDavid van Moolenbroek 		TEXT(PRIO_PROCESS);
964521fa314SDavid van Moolenbroek 		TEXT(PRIO_PGRP);
965521fa314SDavid van Moolenbroek 		TEXT(PRIO_USER);
966521fa314SDavid van Moolenbroek 		}
967521fa314SDavid van Moolenbroek 	}
968521fa314SDavid van Moolenbroek 
969521fa314SDavid van Moolenbroek 	if (text != NULL)
970521fa314SDavid van Moolenbroek 		put_field(proc, name, text);
971521fa314SDavid van Moolenbroek 	else
972521fa314SDavid van Moolenbroek 		put_value(proc, name, "%d", which);
973521fa314SDavid van Moolenbroek }
974521fa314SDavid van Moolenbroek 
975521fa314SDavid van Moolenbroek static int
pm_getpriority_out(struct trace_proc * proc,const message * m_out)976521fa314SDavid van Moolenbroek pm_getpriority_out(struct trace_proc * proc, const message * m_out)
977521fa314SDavid van Moolenbroek {
978521fa314SDavid van Moolenbroek 
979521fa314SDavid van Moolenbroek 	put_priority_which(proc, "which", m_out->m_lc_pm_priority.which);
980521fa314SDavid van Moolenbroek 	put_value(proc, "who", "%d", m_out->m_lc_pm_priority.who);
981521fa314SDavid van Moolenbroek 
982521fa314SDavid van Moolenbroek 	return CT_DONE;
983521fa314SDavid van Moolenbroek }
984521fa314SDavid van Moolenbroek 
985521fa314SDavid van Moolenbroek static void
pm_getpriority_in(struct trace_proc * proc,const message * __unused m_out,const message * m_in,int failed)986521fa314SDavid van Moolenbroek pm_getpriority_in(struct trace_proc * proc, const message * __unused m_out,
987521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
988521fa314SDavid van Moolenbroek {
989521fa314SDavid van Moolenbroek 
990521fa314SDavid van Moolenbroek 	if (!failed)
991521fa314SDavid van Moolenbroek 		put_value(proc, NULL, "%d", m_in->m_type + PRIO_MIN);
992521fa314SDavid van Moolenbroek 	else
993521fa314SDavid van Moolenbroek 		put_result(proc);
994521fa314SDavid van Moolenbroek }
995521fa314SDavid van Moolenbroek 
996521fa314SDavid van Moolenbroek static int
pm_setpriority_out(struct trace_proc * proc,const message * m_out)997521fa314SDavid van Moolenbroek pm_setpriority_out(struct trace_proc * proc, const message * m_out)
998521fa314SDavid van Moolenbroek {
999521fa314SDavid van Moolenbroek 
1000521fa314SDavid van Moolenbroek 	put_priority_which(proc, "which", m_out->m_lc_pm_priority.which);
1001521fa314SDavid van Moolenbroek 	put_value(proc, "who", "%d", m_out->m_lc_pm_priority.who);
1002521fa314SDavid van Moolenbroek 	put_value(proc, "prio", "%d", m_out->m_lc_pm_priority.prio);
1003521fa314SDavid van Moolenbroek 
1004521fa314SDavid van Moolenbroek 	return CT_DONE;
1005521fa314SDavid van Moolenbroek }
1006521fa314SDavid van Moolenbroek 
1007521fa314SDavid van Moolenbroek static int
pm_gettimeofday_out(struct trace_proc * __unused proc,const message * __unused m_out)1008521fa314SDavid van Moolenbroek pm_gettimeofday_out(struct trace_proc * __unused proc,
1009521fa314SDavid van Moolenbroek 	const message * __unused m_out)
1010521fa314SDavid van Moolenbroek {
1011521fa314SDavid van Moolenbroek 
1012521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
1013521fa314SDavid van Moolenbroek }
1014521fa314SDavid van Moolenbroek 
1015521fa314SDavid van Moolenbroek static void
put_timespec_as_timeval(struct trace_proc * proc,const char * name,time_t sec,long nsec)1016521fa314SDavid van Moolenbroek put_timespec_as_timeval(struct trace_proc * proc, const char * name,
1017521fa314SDavid van Moolenbroek 	time_t sec, long nsec)
1018521fa314SDavid van Moolenbroek {
1019521fa314SDavid van Moolenbroek 
1020521fa314SDavid van Moolenbroek 	/* No field names within the structure. */
1021521fa314SDavid van Moolenbroek 	put_open(proc, name, PF_NONAME, "{", ", ");
1022521fa314SDavid van Moolenbroek 
1023521fa314SDavid van Moolenbroek 	put_time(proc, "tv_sec", sec);
1024521fa314SDavid van Moolenbroek 	put_value(proc, "tv_usec", "%ld", nsec / 1000);
1025521fa314SDavid van Moolenbroek 
1026521fa314SDavid van Moolenbroek 	put_close(proc, "}");
1027521fa314SDavid van Moolenbroek }
1028521fa314SDavid van Moolenbroek 
1029521fa314SDavid van Moolenbroek static void
pm_gettimeofday_in(struct trace_proc * proc,const message * __unused m_out,const message * m_in,int failed)1030521fa314SDavid van Moolenbroek pm_gettimeofday_in(struct trace_proc * proc, const message * __unused m_out,
1031521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
1032521fa314SDavid van Moolenbroek {
1033521fa314SDavid van Moolenbroek 
1034521fa314SDavid van Moolenbroek 	if (!failed) {
1035521fa314SDavid van Moolenbroek 		/*
1036521fa314SDavid van Moolenbroek 		 * The system call returns values which do not match the call
1037521fa314SDavid van Moolenbroek 		 * being made, so just like libc, we have to correct..
1038521fa314SDavid van Moolenbroek 		 */
1039521fa314SDavid van Moolenbroek 		put_timespec_as_timeval(proc, "tp", m_in->m_pm_lc_time.sec,
1040521fa314SDavid van Moolenbroek 		    m_in->m_pm_lc_time.nsec);
1041521fa314SDavid van Moolenbroek 	} else
1042521fa314SDavid van Moolenbroek 		put_field(proc, "tp", "&..");
1043521fa314SDavid van Moolenbroek 	put_ptr(proc, "tzp", 0); /* not part of the system call (yet) */
1044521fa314SDavid van Moolenbroek 
1045521fa314SDavid van Moolenbroek 	put_equals(proc);
1046521fa314SDavid van Moolenbroek 	put_result(proc);
1047521fa314SDavid van Moolenbroek }
1048521fa314SDavid van Moolenbroek 
1049521fa314SDavid van Moolenbroek static int
pm_getsid_out(struct trace_proc * proc,const message * m_out)1050521fa314SDavid van Moolenbroek pm_getsid_out(struct trace_proc * proc, const message * m_out)
1051521fa314SDavid van Moolenbroek {
1052521fa314SDavid van Moolenbroek 
1053521fa314SDavid van Moolenbroek 	put_value(proc, "pid", "%d", m_out->m_lc_pm_getsid.pid);
1054521fa314SDavid van Moolenbroek 
1055521fa314SDavid van Moolenbroek 	return CT_DONE;
1056521fa314SDavid van Moolenbroek }
1057521fa314SDavid van Moolenbroek 
1058521fa314SDavid van Moolenbroek static void
put_clockid(struct trace_proc * proc,const char * name,clockid_t clock_id)1059521fa314SDavid van Moolenbroek put_clockid(struct trace_proc * proc, const char * name, clockid_t clock_id)
1060521fa314SDavid van Moolenbroek {
1061521fa314SDavid van Moolenbroek 	const char *text = NULL;
1062521fa314SDavid van Moolenbroek 
1063521fa314SDavid van Moolenbroek 	if (!valuesonly) {
1064521fa314SDavid van Moolenbroek 		switch (clock_id) {
1065521fa314SDavid van Moolenbroek 		TEXT(CLOCK_REALTIME);
1066521fa314SDavid van Moolenbroek #ifdef CLOCK_VIRTUAL
1067521fa314SDavid van Moolenbroek 		TEXT(CLOCK_VIRTUAL);
1068521fa314SDavid van Moolenbroek #endif
1069521fa314SDavid van Moolenbroek #ifdef CLOCK_PROF
1070521fa314SDavid van Moolenbroek 		TEXT(CLOCK_PROF);
1071521fa314SDavid van Moolenbroek #endif
1072521fa314SDavid van Moolenbroek 		TEXT(CLOCK_MONOTONIC);
1073521fa314SDavid van Moolenbroek 		}
1074521fa314SDavid van Moolenbroek 	}
1075521fa314SDavid van Moolenbroek 
1076521fa314SDavid van Moolenbroek 	if (text != NULL)
1077521fa314SDavid van Moolenbroek 		put_field(proc, name, text);
1078521fa314SDavid van Moolenbroek 	else
1079521fa314SDavid van Moolenbroek 		put_value(proc, name, "%d", clock_id);
1080521fa314SDavid van Moolenbroek }
1081521fa314SDavid van Moolenbroek 
1082521fa314SDavid van Moolenbroek static void
put_clock_timespec(struct trace_proc * proc,const char * name,int flags,time_t sec,long nsec)1083521fa314SDavid van Moolenbroek put_clock_timespec(struct trace_proc * proc, const char * name, int flags,
1084521fa314SDavid van Moolenbroek 	time_t sec, long nsec)
1085521fa314SDavid van Moolenbroek {
1086521fa314SDavid van Moolenbroek 
1087521fa314SDavid van Moolenbroek 	if (flags & PF_FAILED) {
1088521fa314SDavid van Moolenbroek 		put_field(proc, name, "&..");
1089521fa314SDavid van Moolenbroek 
1090521fa314SDavid van Moolenbroek 		return;
1091521fa314SDavid van Moolenbroek 	}
1092521fa314SDavid van Moolenbroek 
1093521fa314SDavid van Moolenbroek 	/* No field names within the structure. */
1094521fa314SDavid van Moolenbroek 	put_open(proc, name, PF_NONAME, "{", ", ");
1095521fa314SDavid van Moolenbroek 
1096521fa314SDavid van Moolenbroek 	if (flags & PF_ALT)
1097521fa314SDavid van Moolenbroek 		put_time(proc, "tv_sec", sec);
1098521fa314SDavid van Moolenbroek 	else
1099521fa314SDavid van Moolenbroek 		put_value(proc, "tv_sec", "%"PRId64, sec);
1100521fa314SDavid van Moolenbroek 	put_value(proc, "tv_nsec", "%ld", nsec);
1101521fa314SDavid van Moolenbroek 
1102521fa314SDavid van Moolenbroek 	put_close(proc, "}");
1103521fa314SDavid van Moolenbroek }
1104521fa314SDavid van Moolenbroek 
1105521fa314SDavid van Moolenbroek /* This function is shared between clock_getres and clock_gettime. */
1106521fa314SDavid van Moolenbroek static int
pm_clock_get_out(struct trace_proc * proc,const message * m_out)1107521fa314SDavid van Moolenbroek pm_clock_get_out(struct trace_proc * proc, const message * m_out)
1108521fa314SDavid van Moolenbroek {
1109521fa314SDavid van Moolenbroek 
1110521fa314SDavid van Moolenbroek 	put_clockid(proc, "clock_id", m_out->m_lc_pm_time.clk_id);
1111521fa314SDavid van Moolenbroek 
1112521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
1113521fa314SDavid van Moolenbroek }
1114521fa314SDavid van Moolenbroek 
1115521fa314SDavid van Moolenbroek static void
pm_clock_getres_in(struct trace_proc * proc,const message * __unused m_out,const message * m_in,int failed)1116521fa314SDavid van Moolenbroek pm_clock_getres_in(struct trace_proc * proc, const message * __unused m_out,
1117521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
1118521fa314SDavid van Moolenbroek {
1119521fa314SDavid van Moolenbroek 
1120521fa314SDavid van Moolenbroek 	put_clock_timespec(proc, "res", failed, m_in->m_pm_lc_time.sec,
1121521fa314SDavid van Moolenbroek 	    m_in->m_pm_lc_time.nsec);
1122521fa314SDavid van Moolenbroek 	put_equals(proc);
1123521fa314SDavid van Moolenbroek 	put_result(proc);
1124521fa314SDavid van Moolenbroek }
1125521fa314SDavid van Moolenbroek 
1126521fa314SDavid van Moolenbroek /*
1127521fa314SDavid van Moolenbroek  * Same as pm_clock_getres_in, but different field name and the option to print
1128521fa314SDavid van Moolenbroek  * at least some results as time strings (in the future).
1129521fa314SDavid van Moolenbroek  */
1130521fa314SDavid van Moolenbroek static void
pm_clock_gettime_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)1131521fa314SDavid van Moolenbroek pm_clock_gettime_in(struct trace_proc * proc, const message * m_out,
1132521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
1133521fa314SDavid van Moolenbroek {
1134521fa314SDavid van Moolenbroek 	int flags;
1135521fa314SDavid van Moolenbroek 
1136521fa314SDavid van Moolenbroek 	flags = failed;
1137521fa314SDavid van Moolenbroek 	if (m_out->m_lc_pm_time.clk_id == CLOCK_REALTIME)
1138521fa314SDavid van Moolenbroek 		flags |= PF_ALT; /* TODO: make this print a time string. */
1139521fa314SDavid van Moolenbroek 
1140521fa314SDavid van Moolenbroek 	put_clock_timespec(proc, "tp", flags, m_in->m_pm_lc_time.sec,
1141521fa314SDavid van Moolenbroek 	    m_in->m_pm_lc_time.nsec);
1142521fa314SDavid van Moolenbroek 	put_equals(proc);
1143521fa314SDavid van Moolenbroek 	put_result(proc);
1144521fa314SDavid van Moolenbroek }
1145521fa314SDavid van Moolenbroek 
1146521fa314SDavid van Moolenbroek static const char *
pm_clock_settime_name(const message * m_out)1147521fa314SDavid van Moolenbroek pm_clock_settime_name(const message * m_out)
1148521fa314SDavid van Moolenbroek {
1149521fa314SDavid van Moolenbroek 
1150521fa314SDavid van Moolenbroek 	if (m_out->m_lc_pm_time.now == 0)
1151521fa314SDavid van Moolenbroek 		return "adjtime";
1152521fa314SDavid van Moolenbroek 	else
1153521fa314SDavid van Moolenbroek 		return "clock_settime";
1154521fa314SDavid van Moolenbroek }
1155521fa314SDavid van Moolenbroek 
1156521fa314SDavid van Moolenbroek static int
pm_clock_settime_out(struct trace_proc * proc,const message * m_out)1157521fa314SDavid van Moolenbroek pm_clock_settime_out(struct trace_proc * proc, const message * m_out)
1158521fa314SDavid van Moolenbroek {
1159521fa314SDavid van Moolenbroek 	int flags;
1160521fa314SDavid van Moolenbroek 
1161521fa314SDavid van Moolenbroek 	/* These two calls just look completely different.. */
1162521fa314SDavid van Moolenbroek 	if (m_out->m_lc_pm_time.now == 0) {
1163521fa314SDavid van Moolenbroek 		put_timespec_as_timeval(proc, "delta", m_out->m_lc_pm_time.sec,
1164521fa314SDavid van Moolenbroek 		    m_out->m_lc_pm_time.nsec);
1165521fa314SDavid van Moolenbroek 		put_ptr(proc, "odelta", 0); /* not supported on MINIX3 */
1166521fa314SDavid van Moolenbroek 	} else {
1167521fa314SDavid van Moolenbroek 		flags = 0;
1168521fa314SDavid van Moolenbroek 		if (m_out->m_lc_pm_time.clk_id == CLOCK_REALTIME)
1169521fa314SDavid van Moolenbroek 			flags |= PF_ALT;
1170521fa314SDavid van Moolenbroek 		put_clockid(proc, "clock_id", m_out->m_lc_pm_time.clk_id);
1171521fa314SDavid van Moolenbroek 		put_clock_timespec(proc, "tp", flags, m_out->m_lc_pm_time.sec,
1172521fa314SDavid van Moolenbroek 		    m_out->m_lc_pm_time.nsec);
1173521fa314SDavid van Moolenbroek 	}
1174521fa314SDavid van Moolenbroek 
1175521fa314SDavid van Moolenbroek 	return CT_DONE;
1176521fa314SDavid van Moolenbroek }
1177521fa314SDavid van Moolenbroek 
1178521fa314SDavid van Moolenbroek static int
pm_getrusage_out(struct trace_proc * proc,const message * m_out)1179521fa314SDavid van Moolenbroek pm_getrusage_out(struct trace_proc * proc, const message * m_out)
1180521fa314SDavid van Moolenbroek {
1181521fa314SDavid van Moolenbroek 
1182521fa314SDavid van Moolenbroek 	if (!valuesonly && m_out->m_lc_pm_rusage.who == RUSAGE_SELF)
1183521fa314SDavid van Moolenbroek 		put_field(proc, "who", "RUSAGE_SELF");
1184521fa314SDavid van Moolenbroek 	else if (!valuesonly && m_out->m_lc_pm_rusage.who == RUSAGE_CHILDREN)
1185521fa314SDavid van Moolenbroek 		put_field(proc, "who", "RUSAGE_CHILDREN");
1186521fa314SDavid van Moolenbroek 	else
1187521fa314SDavid van Moolenbroek 		put_value(proc, "who", "%d", m_out->m_lc_pm_rusage.who);
1188521fa314SDavid van Moolenbroek 
1189521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
1190521fa314SDavid van Moolenbroek }
1191521fa314SDavid van Moolenbroek 
1192521fa314SDavid van Moolenbroek static void
pm_getrusage_in(struct trace_proc * proc,const message * m_out,const message * __unused m_in,int failed)1193521fa314SDavid van Moolenbroek pm_getrusage_in(struct trace_proc * proc, const message * m_out,
1194521fa314SDavid van Moolenbroek 	const message * __unused m_in, int failed)
1195521fa314SDavid van Moolenbroek {
1196521fa314SDavid van Moolenbroek 
1197*29346ab0SDavid van Moolenbroek 	put_struct_rusage(proc, "rusage", failed, m_out->m_lc_pm_rusage.addr);
1198521fa314SDavid van Moolenbroek 	put_equals(proc);
1199521fa314SDavid van Moolenbroek 	put_result(proc);
1200521fa314SDavid van Moolenbroek }
1201521fa314SDavid van Moolenbroek 
1202521fa314SDavid van Moolenbroek static const struct flags reboot_flags[] = {
1203521fa314SDavid van Moolenbroek 	FLAG_ZERO(RB_AUTOBOOT),
1204521fa314SDavid van Moolenbroek 	FLAG(RB_ASKNAME),
1205521fa314SDavid van Moolenbroek 	FLAG(RB_DUMP),
1206521fa314SDavid van Moolenbroek 	FLAG_MASK(RB_POWERDOWN, RB_HALT),
1207521fa314SDavid van Moolenbroek 	FLAG(RB_POWERDOWN),
1208521fa314SDavid van Moolenbroek 	FLAG(RB_INITNAME),
1209521fa314SDavid van Moolenbroek 	FLAG(RB_KDB),
1210521fa314SDavid van Moolenbroek 	FLAG(RB_NOSYNC),
1211521fa314SDavid van Moolenbroek 	FLAG(RB_RDONLY),
1212521fa314SDavid van Moolenbroek 	FLAG(RB_SINGLE),
1213521fa314SDavid van Moolenbroek 	FLAG(RB_STRING),
1214521fa314SDavid van Moolenbroek 	FLAG(RB_USERCONF),
1215521fa314SDavid van Moolenbroek };
1216521fa314SDavid van Moolenbroek 
1217521fa314SDavid van Moolenbroek static int
pm_reboot_out(struct trace_proc * proc,const message * m_out)1218521fa314SDavid van Moolenbroek pm_reboot_out(struct trace_proc * proc, const message * m_out)
1219521fa314SDavid van Moolenbroek {
1220521fa314SDavid van Moolenbroek 
1221521fa314SDavid van Moolenbroek 	put_flags(proc, "how", reboot_flags, COUNT(reboot_flags), "0x%x",
1222521fa314SDavid van Moolenbroek 	    m_out->m_lc_pm_reboot.how);
1223521fa314SDavid van Moolenbroek 	put_ptr(proc, "bootstr", 0); /* not supported on MINIX3 */
1224521fa314SDavid van Moolenbroek 
1225521fa314SDavid van Moolenbroek 	return CT_DONE;
1226521fa314SDavid van Moolenbroek }
1227521fa314SDavid van Moolenbroek 
1228521fa314SDavid van Moolenbroek static int
pm_svrctl_out(struct trace_proc * proc,const message * m_out)1229521fa314SDavid van Moolenbroek pm_svrctl_out(struct trace_proc * proc, const message * m_out)
1230521fa314SDavid van Moolenbroek {
1231521fa314SDavid van Moolenbroek 
1232521fa314SDavid van Moolenbroek 	put_ioctl_req(proc, "request", m_out->m_lc_svrctl.request,
1233521fa314SDavid van Moolenbroek 	    TRUE /*is_svrctl*/);
1234521fa314SDavid van Moolenbroek 	return put_ioctl_arg_out(proc, "arg", m_out->m_lc_svrctl.request,
1235521fa314SDavid van Moolenbroek 	    m_out->m_lc_svrctl.arg, TRUE /*is_svrctl*/);
1236521fa314SDavid van Moolenbroek }
1237521fa314SDavid van Moolenbroek 
1238521fa314SDavid van Moolenbroek static void
pm_svrctl_in(struct trace_proc * proc,const message * m_out,const message * __unused m_in,int failed)1239521fa314SDavid van Moolenbroek pm_svrctl_in(struct trace_proc * proc, const message * m_out,
1240521fa314SDavid van Moolenbroek 	const message * __unused m_in, int failed)
1241521fa314SDavid van Moolenbroek {
1242521fa314SDavid van Moolenbroek 
1243521fa314SDavid van Moolenbroek 	put_ioctl_arg_in(proc, "arg", failed, m_out->m_lc_svrctl.request,
1244521fa314SDavid van Moolenbroek 	    m_out->m_lc_svrctl.arg, TRUE /*is_svrctl*/);
1245521fa314SDavid van Moolenbroek }
1246521fa314SDavid van Moolenbroek 
1247521fa314SDavid van Moolenbroek static int
pm_sprof_out(struct trace_proc * proc,const message * m_out)1248521fa314SDavid van Moolenbroek pm_sprof_out(struct trace_proc * proc, const message * m_out)
1249521fa314SDavid van Moolenbroek {
1250521fa314SDavid van Moolenbroek 	int freq;
1251521fa314SDavid van Moolenbroek 
1252521fa314SDavid van Moolenbroek 	if (!valuesonly && m_out->m_lc_pm_sprof.action == PROF_START)
1253521fa314SDavid van Moolenbroek 		put_field(proc, "action", "PROF_START");
1254521fa314SDavid van Moolenbroek 	else if (!valuesonly && m_out->m_lc_pm_sprof.action == PROF_STOP)
1255521fa314SDavid van Moolenbroek 		put_field(proc, "action", "PROF_STOP");
1256521fa314SDavid van Moolenbroek 	else
1257521fa314SDavid van Moolenbroek 		put_value(proc, "action", "%d", m_out->m_lc_pm_sprof.action);
1258521fa314SDavid van Moolenbroek 
1259521fa314SDavid van Moolenbroek 	put_value(proc, "size", "%zu", m_out->m_lc_pm_sprof.mem_size);
1260521fa314SDavid van Moolenbroek 
1261521fa314SDavid van Moolenbroek 	freq = m_out->m_lc_pm_sprof.freq;
1262521fa314SDavid van Moolenbroek 	if (!valuesonly && freq >= 3 && freq <= 15) /* no constants.. */
1263521fa314SDavid van Moolenbroek 		put_value(proc, "freq", "%u /*%uHz*/", freq, 1 << (16 - freq));
1264521fa314SDavid van Moolenbroek 	else
1265521fa314SDavid van Moolenbroek 		put_value(proc, "freq", "%u", freq);
1266521fa314SDavid van Moolenbroek 
1267521fa314SDavid van Moolenbroek 	if (!valuesonly && m_out->m_lc_pm_sprof.intr_type == PROF_RTC)
1268521fa314SDavid van Moolenbroek 		put_field(proc, "type", "PROF_RTC");
1269521fa314SDavid van Moolenbroek 	else if (!valuesonly && m_out->m_lc_pm_sprof.intr_type == PROF_NMI)
1270521fa314SDavid van Moolenbroek 		put_field(proc, "type", "PROF_NMI");
1271521fa314SDavid van Moolenbroek 	else
1272521fa314SDavid van Moolenbroek 		put_value(proc, "type", "%d", m_out->m_lc_pm_sprof.intr_type);
1273521fa314SDavid van Moolenbroek 
1274521fa314SDavid van Moolenbroek 	put_ptr(proc, "ctl_ptr", m_out->m_lc_pm_sprof.ctl_ptr);
1275521fa314SDavid van Moolenbroek 	put_ptr(proc, "mem_ptr", m_out->m_lc_pm_sprof.mem_ptr);
1276521fa314SDavid van Moolenbroek 
1277521fa314SDavid van Moolenbroek 	return CT_DONE;
1278521fa314SDavid van Moolenbroek }
1279521fa314SDavid van Moolenbroek 
1280521fa314SDavid van Moolenbroek #define PM_CALL(c) [((PM_ ## c) - PM_BASE)]
1281521fa314SDavid van Moolenbroek 
1282521fa314SDavid van Moolenbroek static const struct call_handler pm_map[] = {
1283521fa314SDavid van Moolenbroek 	PM_CALL(EXIT) = HANDLER("exit", pm_exit_out, default_in),
1284521fa314SDavid van Moolenbroek 	PM_CALL(FORK) = HANDLER("fork", default_out, default_in),
1285*29346ab0SDavid van Moolenbroek 	PM_CALL(WAIT4) = HANDLER("wait4", pm_wait4_out, pm_wait4_in),
1286521fa314SDavid van Moolenbroek 	PM_CALL(GETPID) = HANDLER("getpid", default_out, pm_getpid_in),
1287521fa314SDavid van Moolenbroek 	PM_CALL(SETUID) = HANDLER("setuid", pm_setuid_out, default_in),
1288521fa314SDavid van Moolenbroek 	PM_CALL(GETUID) = HANDLER("getuid", default_out, pm_getuid_in),
1289521fa314SDavid van Moolenbroek 	PM_CALL(STIME) = HANDLER("stime", pm_stime_out, default_in),
1290521fa314SDavid van Moolenbroek 	PM_CALL(PTRACE) = HANDLER("ptrace", pm_ptrace_out, pm_ptrace_in),
1291521fa314SDavid van Moolenbroek 	PM_CALL(SETGROUPS) = HANDLER("setgroups", pm_setgroups_out,
1292521fa314SDavid van Moolenbroek 	    default_in),
1293521fa314SDavid van Moolenbroek 	PM_CALL(GETGROUPS) = HANDLER("getgroups", pm_getgroups_out,
1294521fa314SDavid van Moolenbroek 	    pm_getgroups_in),
1295521fa314SDavid van Moolenbroek 	PM_CALL(KILL) = HANDLER("kill", pm_kill_out, default_in),
1296521fa314SDavid van Moolenbroek 	PM_CALL(SETGID) = HANDLER("setgid", pm_setgid_out, default_in),
1297521fa314SDavid van Moolenbroek 	PM_CALL(GETGID) = HANDLER("getgid", default_out, pm_getgid_in),
1298521fa314SDavid van Moolenbroek 	PM_CALL(EXEC) = HANDLER("execve", pm_exec_out, default_in),
1299521fa314SDavid van Moolenbroek 	PM_CALL(SETSID) = HANDLER("setsid", default_out, default_in),
1300521fa314SDavid van Moolenbroek 	PM_CALL(GETPGRP) = HANDLER("getpgrp", default_out, default_in),
1301521fa314SDavid van Moolenbroek 	PM_CALL(ITIMER) = HANDLER_NAME(pm_itimer_name, pm_itimer_out,
1302521fa314SDavid van Moolenbroek 	    pm_itimer_in),
1303521fa314SDavid van Moolenbroek 	PM_CALL(GETMCONTEXT) = HANDLER("getmcontext", pm_getmcontext_out,
1304521fa314SDavid van Moolenbroek 	    pm_getmcontext_in),
1305521fa314SDavid van Moolenbroek 	PM_CALL(SETMCONTEXT) = HANDLER("setmcontext", pm_setmcontext_out,
1306521fa314SDavid van Moolenbroek 	    default_in),
1307521fa314SDavid van Moolenbroek 	PM_CALL(SIGACTION) = HANDLER("sigaction", pm_sigaction_out,
1308521fa314SDavid van Moolenbroek 	    pm_sigaction_in),
1309521fa314SDavid van Moolenbroek 	PM_CALL(SIGSUSPEND) = HANDLER("sigsuspend", pm_sigsuspend_out,
1310521fa314SDavid van Moolenbroek 	    default_in),
1311521fa314SDavid van Moolenbroek 	PM_CALL(SIGPENDING) = HANDLER("sigpending", pm_sigpending_out,
1312521fa314SDavid van Moolenbroek 	    pm_sigpending_in),
1313521fa314SDavid van Moolenbroek 	PM_CALL(SIGPROCMASK) = HANDLER("sigprocmask", pm_sigprocmask_out,
1314521fa314SDavid van Moolenbroek 	    pm_sigprocmask_in),
1315521fa314SDavid van Moolenbroek 	PM_CALL(SIGRETURN) = HANDLER("sigreturn", pm_sigreturn_out,
1316521fa314SDavid van Moolenbroek 	    pm_sigreturn_in),
1317521fa314SDavid van Moolenbroek 	PM_CALL(GETPRIORITY) = HANDLER("getpriority", pm_getpriority_out,
1318521fa314SDavid van Moolenbroek 	    pm_getpriority_in),
1319521fa314SDavid van Moolenbroek 	PM_CALL(SETPRIORITY) = HANDLER("setpriority", pm_setpriority_out,
1320521fa314SDavid van Moolenbroek 	    default_in),
1321521fa314SDavid van Moolenbroek 	PM_CALL(GETTIMEOFDAY) = HANDLER("gettimeofday", pm_gettimeofday_out,
1322521fa314SDavid van Moolenbroek 	    pm_gettimeofday_in),
1323521fa314SDavid van Moolenbroek 	PM_CALL(SETEUID) = HANDLER("seteuid", pm_setuid_out, default_in),
1324521fa314SDavid van Moolenbroek 	PM_CALL(SETEGID) = HANDLER("setegid", pm_setgid_out, default_in),
1325521fa314SDavid van Moolenbroek 	PM_CALL(ISSETUGID) = HANDLER("issetugid", default_out, default_in),
1326521fa314SDavid van Moolenbroek 	PM_CALL(GETSID) = HANDLER("getsid", pm_getsid_out, default_in),
1327521fa314SDavid van Moolenbroek 	PM_CALL(CLOCK_GETRES) = HANDLER("clock_getres", pm_clock_get_out,
1328521fa314SDavid van Moolenbroek 	    pm_clock_getres_in),
1329521fa314SDavid van Moolenbroek 	PM_CALL(CLOCK_GETTIME) = HANDLER("clock_gettime", pm_clock_get_out,
1330521fa314SDavid van Moolenbroek 	    pm_clock_gettime_in),
1331521fa314SDavid van Moolenbroek 	PM_CALL(CLOCK_SETTIME) = HANDLER_NAME(pm_clock_settime_name,
1332521fa314SDavid van Moolenbroek 	    pm_clock_settime_out, default_in),
1333*29346ab0SDavid van Moolenbroek 	PM_CALL(GETRUSAGE) = HANDLER("getrusage", pm_getrusage_out,
1334521fa314SDavid van Moolenbroek 	    pm_getrusage_in),
1335521fa314SDavid van Moolenbroek 	PM_CALL(REBOOT) = HANDLER("reboot", pm_reboot_out, default_in),
1336521fa314SDavid van Moolenbroek 	PM_CALL(SVRCTL) = HANDLER("pm_svrctl", pm_svrctl_out, pm_svrctl_in),
1337521fa314SDavid van Moolenbroek 	PM_CALL(SPROF) = HANDLER("sprofile", pm_sprof_out, default_in),
1338521fa314SDavid van Moolenbroek };
1339521fa314SDavid van Moolenbroek 
1340521fa314SDavid van Moolenbroek const struct calls pm_calls = {
1341521fa314SDavid van Moolenbroek 	.endpt = PM_PROC_NR,
1342521fa314SDavid van Moolenbroek 	.base = PM_BASE,
1343521fa314SDavid van Moolenbroek 	.map = pm_map,
1344521fa314SDavid van Moolenbroek 	.count = COUNT(pm_map)
1345521fa314SDavid van Moolenbroek };
1346