6 static char ioctlbuf
[IOCPARM_MASK
];
9 const char *(*name
)(unsigned long);
10 int (*arg
)(struct trace_proc
*, unsigned long, void *, int);
13 { block_ioctl_name
, block_ioctl_arg
, FALSE
},
14 { char_ioctl_name
, char_ioctl_arg
, FALSE
},
15 { net_ioctl_name
, net_ioctl_arg
, FALSE
},
16 { svrctl_name
, svrctl_arg
, TRUE
},
20 * Print an IOCTL request code, and save certain values in the corresponding
21 * process structure in order to be able to print the IOCTL argument.
24 put_ioctl_req(struct trace_proc
* proc
, const char * name
, unsigned long req
,
29 unsigned int i
, group
, cmd
;
32 proc
->ioctl_index
= -1;
35 put_value(proc
, name
, "0x%lx", req
);
41 * Lookups are bruteforce across the IOCTL submodules; they're all
42 * checked. We could use the group letter but that would create more
43 * issues than it solves. Our hope is that at least the compiler is
44 * smart about looking up particular codes in each switch statement,
45 * although in the worst case, it's a full O(n) lookup.
47 for (i
= 0; i
< COUNT(ioctl_table
); i
++) {
48 /* IOCTLs and SVRCTLs are considered different name spaces. */
49 if (ioctl_table
[i
].is_svrctl
!= is_svrctl
)
52 if ((text
= ioctl_table
[i
].name(req
)) != NULL
) {
53 proc
->ioctl_index
= i
;
58 put_field(proc
, name
, text
);
64 r
= _MINIX_IOCTL_IOR(req
);
65 w
= _MINIX_IOCTL_IOW(req
);
66 big
= _MINIX_IOCTL_BIG(req
);
67 size
= (size_t)(big
? _MINIX_IOCTL_SIZE_BIG(req
) : IOCPARM_LEN(req
));
68 group
= big
? 0 : IOCGROUP(req
);
69 cmd
= req
& 0xff; /* shockingly there is no macro for this.. */
72 * Not sure why an entire bit is wasted on IOC_VOID (legacy reasons?),
73 * but since the redundancy is there, we might as well check whether
74 * this is a valid IOCTL request. Also, we expect the group to be a
75 * printable character. If either check fails, print just a number.
77 if (((req
& IOC_VOID
) && (r
|| w
|| big
|| size
> 0)) ||
78 (!(req
& IOC_VOID
) && ((!r
&& !w
) || size
== 0)) ||
79 (!big
&& (group
< 32 || group
> 127))) {
80 put_value(proc
, name
, "0x%lx", req
);
86 /* For big IOCTLs, "R" becomes before "W" (old MINIX style). */
87 put_value(proc
, name
, "_IO%s%s_BIG(%u,%zu)",
88 r
? "R" : "", w
? "W" : "", cmd
, size
);
89 } else if (IOCGROUP(req
) >= 32 && IOCGROUP(req
) < 127) {
90 /* For normal IOCTLs, "W" comes before "R" (NetBSD style). */
91 put_value(proc
, name
, "_IO%s%s('%c',%u,%zu)",
92 w
? "W" : "", r
? "R" : "", group
, cmd
, size
);
97 * Print the supplied (out) part of an IOCTL argument, as applicable. For
98 * efficiency reasons, this function assumes that put_ioctl_req() has been
99 * called for the corresponding IOCTL already, so that the necessary fields in
100 * the given proc structure are set as expected.
103 put_ioctl_arg_out(struct trace_proc
* proc
, const char * name
,
104 unsigned long req
, vir_bytes addr
, int is_svrctl
)
109 dir
= (_MINIX_IOCTL_IOW(req
) ? IF_OUT
: 0) |
110 (_MINIX_IOCTL_IOR(req
) ? IF_IN
: 0);
113 proc
->ioctl_index
= -1; /* no argument to print at all */
118 /* No support for printing big-IOCTL contents just yet. */
119 if (valuesonly
> 1 || _MINIX_IOCTL_BIG(req
) ||
120 proc
->ioctl_index
== -1) {
121 put_ptr(proc
, name
, addr
);
126 assert(proc
->ioctl_index
>= 0);
127 assert((unsigned int)proc
->ioctl_index
< COUNT(ioctl_table
));
128 assert(ioctl_table
[proc
->ioctl_index
].is_svrctl
== is_svrctl
);
131 ioctl_table
[proc
->ioctl_index
].arg(proc
, req
, NULL
, dir
);
133 if (proc
->ioctl_flags
== 0) { /* no argument printing for this IOCTL */
134 put_ptr(proc
, name
, addr
);
136 proc
->ioctl_index
= -1; /* forget about the IOCTL handler */
142 * If this triggers, the IOCTL handler returns a direction that is not
143 * part of the actual IOCTL, and the handler should be fixed.
145 if (proc
->ioctl_flags
& ~dir
) {
146 output_flush(); /* show the IOCTL name for debugging */
151 if (!(proc
->ioctl_flags
& IF_OUT
))
154 size
= IOCPARM_LEN(req
);
156 if (size
> sizeof(ioctlbuf
) ||
157 mem_get_data(proc
->pid
, addr
, ioctlbuf
, size
) < 0) {
158 put_ptr(proc
, name
, addr
);
160 /* There's no harm in trying the _in side later anyhow.. */
164 put_open(proc
, name
, 0, "{", ", ");
166 all
= ioctl_table
[proc
->ioctl_index
].arg(proc
, req
, ioctlbuf
, IF_OUT
);
169 put_field(proc
, NULL
, "..");
171 put_close(proc
, "}");
177 * Print the returned (in) part of an IOCTL argument, as applicable. This
178 * function assumes that it is preceded by a call to put_ioctl_arg_out for this
182 put_ioctl_arg_in(struct trace_proc
* proc
, const char * name
, int failed
,
183 unsigned long req
, vir_bytes addr
, int is_svrctl
)
188 if (valuesonly
> 1 || _MINIX_IOCTL_BIG(req
) ||
189 proc
->ioctl_index
== -1) {
195 assert(proc
->ioctl_index
>= 0);
196 assert((unsigned int)proc
->ioctl_index
< COUNT(ioctl_table
));
197 assert(ioctl_table
[proc
->ioctl_index
].is_svrctl
== is_svrctl
);
198 assert(proc
->ioctl_flags
!= 0);
200 if (proc
->ioctl_flags
& IF_OUT
)
202 if (!(proc
->ioctl_flags
& IF_IN
))
205 size
= IOCPARM_LEN(req
);
207 if (failed
|| size
> sizeof(ioctlbuf
) ||
208 mem_get_data(proc
->pid
, addr
, ioctlbuf
, size
) < 0) {
209 if (!(proc
->ioctl_flags
& IF_OUT
)) {
210 put_ptr(proc
, name
, addr
);
214 put_field(proc
, NULL
, "{..}");
219 put_open(proc
, name
, 0, "{", ", ");
221 all
= ioctl_table
[proc
->ioctl_index
].arg(proc
, req
, ioctlbuf
, IF_IN
);
224 put_field(proc
, NULL
, "..");
226 put_close(proc
, "}");
228 if (!(proc
->ioctl_flags
& IF_OUT
)) {