8 #include <sys/resource.h>
9 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #if 0 /* not yet, header is missing */
13 #include <netbt/bluetooth.h>
15 #include <arpa/inet.h>
18 * This function should always be used when printing a file descriptor. It
19 * currently offers no benefit, but will in the future allow for features such
20 * as color highlighting and tracking of specific open files (TODO).
23 put_fd(struct trace_proc
* proc
, const char * name
, int fd
)
26 put_value(proc
, name
, "%d", fd
);
30 vfs_read_out(struct trace_proc
* proc
, const message
* m_out
)
33 put_fd(proc
, "fd", m_out
->m_lc_vfs_readwrite
.fd
);
39 vfs_read_in(struct trace_proc
* proc
, const message
* m_out
,
40 const message
* m_in
, int failed
)
43 put_buf(proc
, "buf", failed
, m_out
->m_lc_vfs_readwrite
.buf
,
45 put_value(proc
, "len", "%zu", m_out
->m_lc_vfs_readwrite
.len
);
51 vfs_write_out(struct trace_proc
* proc
, const message
* m_out
)
54 put_fd(proc
, "fd", m_out
->m_lc_vfs_readwrite
.fd
);
55 put_buf(proc
, "buf", 0, m_out
->m_lc_vfs_readwrite
.buf
,
56 m_out
->m_lc_vfs_readwrite
.len
);
57 put_value(proc
, "len", "%zu", m_out
->m_lc_vfs_readwrite
.len
);
63 put_lseek_whence(struct trace_proc
* proc
, const char * name
, int whence
)
65 const char *text
= NULL
;
76 put_field(proc
, name
, text
);
78 put_value(proc
, name
, "%d", whence
);
82 vfs_lseek_out(struct trace_proc
* proc
, const message
* m_out
)
85 put_fd(proc
, "fd", m_out
->m_lc_vfs_lseek
.fd
);
86 put_value(proc
, "offset", "%"PRId64
, m_out
->m_lc_vfs_lseek
.offset
);
87 put_lseek_whence(proc
, "whence", m_out
->m_lc_vfs_lseek
.whence
);
93 vfs_lseek_in(struct trace_proc
* proc
, const message
* __unused m_out
,
94 const message
* m_in
, int failed
)
98 put_value(proc
, NULL
, "%"PRId64
, m_in
->m_vfs_lc_lseek
.offset
);
103 static const struct flags open_flags
[] = {
104 FLAG_MASK(O_ACCMODE
, O_RDONLY
),
105 FLAG_MASK(O_ACCMODE
, O_WRONLY
),
106 FLAG_MASK(O_ACCMODE
, O_RDWR
),
107 #define ACCMODE_ENTRIES 3 /* the first N entries are for O_ACCMODE */
130 put_open_flags(struct trace_proc
* proc
, const char * name
, int value
,
133 const struct flags
*fp
;
137 num
= COUNT(open_flags
);
140 * If we're not printing a full open()-style set of flags, but instead
141 * just a loose set of flags, then skip the access mode altogether,
142 * otherwise we'd be printing O_RDONLY when no access mode is given.
145 fp
+= ACCMODE_ENTRIES
;
146 num
-= ACCMODE_ENTRIES
;
149 put_flags(proc
, name
, fp
, num
, "0x%x", value
);
152 static const struct flags mode_flags
[] = {
153 FLAG_MASK(S_IFMT
, S_IFIFO
),
154 FLAG_MASK(S_IFMT
, S_IFCHR
),
155 FLAG_MASK(S_IFMT
, S_IFDIR
),
156 FLAG_MASK(S_IFMT
, S_IFBLK
),
157 FLAG_MASK(S_IFMT
, S_IFREG
),
158 FLAG_MASK(S_IFMT
, S_IFLNK
),
159 FLAG_MASK(S_IFMT
, S_IFSOCK
),
160 FLAG_MASK(S_IFMT
, S_IFWHT
),
168 /* Do not use %04o instead of 0%03o; it is octal even if greater than 0777. */
169 #define put_mode(p, n, v) \
170 put_flags(p, n, mode_flags, COUNT(mode_flags), "0%03o", v)
173 put_path(struct trace_proc
* proc
, const message
* m_out
)
177 if ((len
= m_out
->m_lc_vfs_path
.len
) <= M_PATH_STRING_MAX
)
178 put_buf(proc
, "path", PF_LOCADDR
| PF_PATH
,
179 (vir_bytes
)m_out
->m_lc_vfs_path
.buf
, len
);
181 put_buf(proc
, "path", PF_PATH
, m_out
->m_lc_vfs_path
.name
, len
);
185 vfs_open_out(struct trace_proc
* proc
, const message
* m_out
)
188 put_path(proc
, m_out
);
189 put_open_flags(proc
, "flags", m_out
->m_lc_vfs_path
.flags
,
195 /* This function is shared between creat and open. */
197 vfs_open_in(struct trace_proc
* proc
, const message
* __unused m_out
,
198 const message
* m_in
, int failed
)
202 put_fd(proc
, NULL
, m_in
->m_type
);
208 vfs_creat_out(struct trace_proc
* proc
, const message
* m_out
)
211 put_buf(proc
, "path", PF_PATH
, m_out
->m_lc_vfs_creat
.name
,
212 m_out
->m_lc_vfs_creat
.len
);
213 put_open_flags(proc
, "flags", m_out
->m_lc_vfs_creat
.flags
,
215 put_mode(proc
, "mode", m_out
->m_lc_vfs_creat
.mode
);
221 vfs_close_out(struct trace_proc
* proc
, const message
* m_out
)
224 put_fd(proc
, "fd", m_out
->m_lc_vfs_close
.fd
);
229 /* This function is used for link, rename, and symlink. */
231 vfs_link_out(struct trace_proc
* proc
, const message
* m_out
)
234 put_buf(proc
, "path1", PF_PATH
, m_out
->m_lc_vfs_link
.name1
,
235 m_out
->m_lc_vfs_link
.len1
);
236 put_buf(proc
, "path2", PF_PATH
, m_out
->m_lc_vfs_link
.name2
,
237 m_out
->m_lc_vfs_link
.len2
);
243 vfs_path_out(struct trace_proc
* proc
, const message
* m_out
)
246 put_path(proc
, m_out
);
252 vfs_path_mode_out(struct trace_proc
* proc
, const message
* m_out
)
255 put_path(proc
, m_out
);
256 put_mode(proc
, "mode", m_out
->m_lc_vfs_path
.mode
);
262 put_dev(struct trace_proc
* proc
, const char * name
, dev_t dev
)
270 /* The value 0 ("no device") should print as "0". */
271 if (dev
!= 0 && makedev(major
, minor
) == dev
&& !valuesonly
)
272 put_value(proc
, name
, "<%d,%d>", major
, minor
);
274 put_value(proc
, name
, "%"PRIu64
, dev
);
278 vfs_mknod_out(struct trace_proc
* proc
, const message
* m_out
)
281 put_buf(proc
, "path", PF_PATH
, m_out
->m_lc_vfs_mknod
.name
,
282 m_out
->m_lc_vfs_mknod
.len
);
283 put_mode(proc
, "mode", m_out
->m_lc_vfs_mknod
.mode
);
284 put_dev(proc
, "dev", m_out
->m_lc_vfs_mknod
.device
);
290 vfs_chown_out(struct trace_proc
* proc
, const message
* m_out
)
293 put_buf(proc
, "path", PF_PATH
, m_out
->m_lc_vfs_chown
.name
,
294 m_out
->m_lc_vfs_chown
.len
);
295 /* -1 means "keep the current value" so print as signed */
296 put_value(proc
, "owner", "%d", m_out
->m_lc_vfs_chown
.owner
);
297 put_value(proc
, "group", "%d", m_out
->m_lc_vfs_chown
.group
);
302 /* TODO: expand this to the full ST_ set. */
303 static const struct flags mount_flags
[] = {
308 vfs_mount_out(struct trace_proc
* proc
, const message
* m_out
)
311 put_buf(proc
, "special", PF_PATH
, m_out
->m_lc_vfs_mount
.dev
,
312 m_out
->m_lc_vfs_mount
.devlen
);
313 put_buf(proc
, "path", PF_PATH
, m_out
->m_lc_vfs_mount
.path
,
314 m_out
->m_lc_vfs_mount
.pathlen
);
315 put_flags(proc
, "flags", mount_flags
, COUNT(mount_flags
), "0x%x",
316 m_out
->m_lc_vfs_mount
.flags
);
317 put_buf(proc
, "type", PF_STRING
, m_out
->m_lc_vfs_mount
.type
,
318 m_out
->m_lc_vfs_mount
.typelen
);
319 put_buf(proc
, "label", PF_STRING
, m_out
->m_lc_vfs_mount
.label
,
320 m_out
->m_lc_vfs_mount
.labellen
);
326 vfs_umount_out(struct trace_proc
* proc
, const message
* m_out
)
329 put_buf(proc
, "path", PF_PATH
, m_out
->m_lc_vfs_umount
.name
,
330 m_out
->m_lc_vfs_umount
.namelen
);
336 vfs_umount_in(struct trace_proc
* proc
, const message
* m_out
,
337 const message
* __unused m_in
, int failed
)
343 put_open(proc
, NULL
, 0, "(", ", ");
344 put_buf(proc
, "label", PF_STRING
, m_out
->m_lc_vfs_umount
.label
,
345 m_out
->m_lc_vfs_umount
.labellen
);
347 put_close(proc
, ")");
352 static const struct flags access_flags
[] = {
360 vfs_access_out(struct trace_proc
* proc
, const message
* m_out
)
363 put_path(proc
, m_out
);
364 put_flags(proc
, "mode", access_flags
, COUNT(access_flags
), "0x%x",
365 m_out
->m_lc_vfs_path
.mode
);
371 vfs_readlink_out(struct trace_proc
* proc
, const message
* m_out
)
374 put_buf(proc
, "path", PF_PATH
, m_out
->m_lc_vfs_readlink
.name
,
375 m_out
->m_lc_vfs_readlink
.namelen
);
381 vfs_readlink_in(struct trace_proc
* proc
, const message
* m_out
,
382 const message
* m_in
, int failed
)
385 /* The call does not return a string, so do not use PF_STRING here. */
386 put_buf(proc
, "buf", failed
, m_out
->m_lc_vfs_readlink
.buf
,
388 put_value(proc
, "bufsize", "%zd", m_out
->m_lc_vfs_readlink
.bufsize
);
394 put_struct_stat(struct trace_proc
* proc
, const char * name
, int flags
,
400 if (!put_open_struct(proc
, name
, flags
, addr
, &buf
, sizeof(buf
)))
404 * The combination of struct stat's frequent usage and large number of
405 * fields makes this structure a pain to print. For now, the idea is
406 * that for verbosity level 0, we print the mode, and the target device
407 * for block/char special files or the file size for all other files.
408 * For higher verbosity levels, largely maintain the structure's own
409 * order of fields. Violate this general structure printing rule for
410 * some fields though, because the actual field order in struct stat is
411 * downright ridiculous. Like elsewhere, for verbosity level 1 print
412 * all fields with meaningful values, and for verbosity level 2 just
413 * print everything, including fields that are known to be not yet
414 * supported and fields that contain known values.
416 is_special
= (S_ISBLK(buf
.st_mode
) || S_ISCHR(buf
.st_mode
));
419 put_dev(proc
, "st_dev", buf
.st_dev
);
420 put_value(proc
, "st_ino", "%"PRId64
, buf
.st_ino
);
422 put_mode(proc
, "st_mode", buf
.st_mode
);
424 put_value(proc
, "st_nlink", "%u", buf
.st_nlink
);
425 put_value(proc
, "st_uid", "%u", buf
.st_uid
);
426 put_value(proc
, "st_gid", "%u", buf
.st_gid
);
428 if (is_special
|| verbose
> 1)
429 put_dev(proc
, "st_rdev", buf
.st_rdev
);
432 * TODO: print the nanosecond part, but possibly only if we are
433 * not actually interpreting the time as a date (another TODO),
434 * and/or possibly only with verbose > 1 (largely unsupported).
436 put_time(proc
, "st_atime", buf
.st_atime
);
437 put_time(proc
, "st_mtime", buf
.st_mtime
);
438 put_time(proc
, "st_ctime", buf
.st_ctime
);
440 if (verbose
> 1) /* not yet supported on MINIX3 */
441 put_time(proc
, "st_birthtime", buf
.st_birthtime
);
442 if (!is_special
|| verbose
> 1)
443 put_value(proc
, "st_size", "%"PRId64
, buf
.st_size
);
445 put_value(proc
, "st_blocks", "%"PRId64
, buf
.st_blocks
);
446 put_value(proc
, "st_blksize", "%"PRId32
, buf
.st_blksize
);
449 put_value(proc
, "st_flags", "%"PRIu32
, buf
.st_flags
);
450 put_value(proc
, "st_gen", "%"PRIu32
, buf
.st_gen
);
453 put_close_struct(proc
, verbose
> 1);
457 vfs_stat_out(struct trace_proc
* proc
, const message
* m_out
)
460 put_buf(proc
, "path", PF_PATH
, m_out
->m_lc_vfs_stat
.name
,
461 m_out
->m_lc_vfs_stat
.len
);
467 vfs_stat_in(struct trace_proc
* proc
, const message
* m_out
,
468 const message
* __unused m_in
, int failed
)
471 put_struct_stat(proc
, "buf", failed
, m_out
->m_lc_vfs_stat
.buf
);
477 vfs_fstat_out(struct trace_proc
* proc
, const message
* m_out
)
480 put_fd(proc
, "fd", m_out
->m_lc_vfs_fstat
.fd
);
486 vfs_fstat_in(struct trace_proc
* proc
, const message
* m_out
,
487 const message
* __unused m_in
, int failed
)
490 put_struct_stat(proc
, "buf", failed
, m_out
->m_lc_vfs_fstat
.buf
);
496 vfs_ioctl_out(struct trace_proc
* proc
, const message
* m_out
)
499 put_fd(proc
, "fd", m_out
->m_lc_vfs_ioctl
.fd
);
500 put_ioctl_req(proc
, "req", m_out
->m_lc_vfs_ioctl
.req
,
501 FALSE
/*is_svrctl*/);
502 return put_ioctl_arg_out(proc
, "arg", m_out
->m_lc_vfs_ioctl
.req
,
503 (vir_bytes
)m_out
->m_lc_vfs_ioctl
.arg
, FALSE
/*is_svrctl*/);
507 vfs_ioctl_in(struct trace_proc
* proc
, const message
* m_out
,
508 const message
* __unused m_in
, int failed
)
511 put_ioctl_arg_in(proc
, "arg", failed
, m_out
->m_lc_vfs_ioctl
.req
,
512 (vir_bytes
)m_out
->m_lc_vfs_ioctl
.arg
, FALSE
/*is_svrctl*/);
516 put_fcntl_cmd(struct trace_proc
* proc
, const char * name
, int cmd
)
518 const char *text
= NULL
;
534 TEXT(F_DUPFD_CLOEXEC
);
535 TEXT(F_GETNOSIGPIPE
);
536 TEXT(F_SETNOSIGPIPE
);
538 TEXT(F_FLUSH_FS_CACHE
);
543 put_field(proc
, name
, text
);
545 put_value(proc
, name
, "%d", cmd
);
548 static const struct flags fd_flags
[] = {
552 #define put_fd_flags(p, n, v) \
553 put_flags(p, n, fd_flags, COUNT(fd_flags), "0x%x", v)
556 put_flock_type(struct trace_proc
* proc
, const char * name
, int type
)
558 const char *text
= NULL
;
569 put_field(proc
, name
, text
);
571 put_value(proc
, name
, "%d", type
);
575 * With PF_FULL, also print l_pid, unless l_type is F_UNLCK in which case
576 * only that type is printed. With PF_ALT, print only l_whence/l_start/l_len.
579 put_struct_flock(struct trace_proc
* proc
, const char * name
, int flags
,
585 if (!put_open_struct(proc
, name
, flags
, addr
, &flock
, sizeof(flock
)))
588 limited
= ((flags
& PF_FULL
) && flock
.l_type
== F_UNLCK
);
590 if (!(flags
& PF_ALT
))
591 put_flock_type(proc
, "l_type", flock
.l_type
);
593 put_lseek_whence(proc
, "l_whence", flock
.l_whence
);
594 put_value(proc
, "l_start", "%"PRId64
, flock
.l_start
);
595 put_value(proc
, "l_len", "%"PRId64
, flock
.l_len
);
597 put_value(proc
, "l_pid", "%d", flock
.l_pid
);
600 put_close_struct(proc
, TRUE
/*all*/);
604 vfs_fcntl_out(struct trace_proc
* proc
, const message
* m_out
)
607 put_fd(proc
, "fd", m_out
->m_lc_vfs_fcntl
.fd
);
608 put_fcntl_cmd(proc
, "cmd", m_out
->m_lc_vfs_fcntl
.cmd
);
610 switch (m_out
->m_lc_vfs_fcntl
.cmd
) {
612 case F_DUPFD_CLOEXEC
:
613 put_fd(proc
, "fd2", m_out
->m_lc_vfs_fcntl
.arg_int
);
616 put_fd_flags(proc
, "flags", m_out
->m_lc_vfs_fcntl
.arg_int
);
620 * One of those difficult cases: the access mode is ignored, so
621 * we don't want to print O_RDONLY if it is not given. On the
622 * other hand, fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_..) is
623 * a fairly common construction, in which case we don't want to
624 * print eg O_..|0x2 if the access mode is O_RDWR. Thus, we
625 * compromise: show the access mode if any of its bits are set.
627 put_open_flags(proc
, "flags", m_out
->m_lc_vfs_fcntl
.arg_int
,
628 m_out
->m_lc_vfs_fcntl
.arg_int
& O_ACCMODE
/*full*/);
632 put_struct_flock(proc
, "lkp", 0,
633 m_out
->m_lc_vfs_fcntl
.arg_ptr
);
636 put_struct_flock(proc
, "lkp", PF_ALT
,
637 m_out
->m_lc_vfs_fcntl
.arg_ptr
);
640 put_value(proc
, "arg", "%d", m_out
->m_lc_vfs_fcntl
.arg_int
);
644 return (m_out
->m_lc_vfs_fcntl
.cmd
!= F_GETLK
) ? CT_DONE
: CT_NOTDONE
;
648 vfs_fcntl_in(struct trace_proc
* proc
, const message
* m_out
,
649 const message
* m_in
, int failed
)
652 switch (m_out
->m_lc_vfs_fcntl
.cmd
) {
656 put_fd_flags(proc
, NULL
, m_in
->m_type
);
661 put_open_flags(proc
, NULL
, m_in
->m_type
, TRUE
/*full*/);
664 put_struct_flock(proc
, "lkp", failed
| PF_FULL
,
665 m_out
->m_lc_vfs_fcntl
.arg_ptr
);
674 vfs_pipe2_out(struct trace_proc
* __unused proc
,
675 const message
* __unused m_out
)
682 vfs_pipe2_in(struct trace_proc
* proc
, const message
* m_out
,
683 const message
* m_in
, int failed
)
687 put_open(proc
, "fd", PF_NONAME
, "[", ", ");
688 put_fd(proc
, "rfd", m_in
->m_vfs_lc_fdpair
.fd0
);
689 put_fd(proc
, "wfd", m_in
->m_vfs_lc_fdpair
.fd1
);
690 put_close(proc
, "]");
692 put_field(proc
, "fd", "&..");
693 put_open_flags(proc
, "flags", m_out
->m_lc_vfs_pipe2
.flags
,
700 vfs_umask_out(struct trace_proc
* proc
, const message
* m_out
)
703 put_mode(proc
, NULL
, m_out
->m_lc_vfs_umask
.mask
);
709 vfs_umask_in(struct trace_proc
* proc
, const message
* __unused m_out
,
710 const message
* m_in
, int failed
)
714 put_mode(proc
, NULL
, m_in
->m_type
);
721 put_dirent_type(struct trace_proc
* proc
, const char * name
, unsigned int type
)
723 const char *text
= NULL
;
740 put_field(proc
, name
, text
);
742 put_value(proc
, name
, "%u", type
);
746 put_struct_dirent(struct trace_proc
* proc
, const char *name
, int flags
,
749 struct dirent dirent
;
751 if (!put_open_struct(proc
, name
, flags
, addr
, &dirent
, sizeof(dirent
)))
755 put_value(proc
, "d_fileno", "%"PRIu64
, dirent
.d_fileno
);
757 put_value(proc
, "d_reclen", "%u", dirent
.d_reclen
);
758 put_value(proc
, "d_namlen", "%u", dirent
.d_namlen
);
760 if (verbose
>= 1 + (dirent
.d_type
== DT_UNKNOWN
))
761 put_dirent_type(proc
, "d_type", dirent
.d_type
);
762 put_buf(proc
, "d_name", PF_LOCADDR
, (vir_bytes
)dirent
.d_name
,
763 MIN(dirent
.d_namlen
, sizeof(dirent
.d_name
)));
765 put_close_struct(proc
, verbose
> 1);
769 put_dirent_array(struct trace_proc
* proc
, const char * name
, int flags
,
770 vir_bytes addr
, ssize_t size
)
772 struct dirent dirent
;
776 if ((flags
& PF_FAILED
) || valuesonly
> 1 || size
< 0) {
777 put_ptr(proc
, name
, addr
);
783 put_field(proc
, name
, "[]");
789 max
= 0; /* TODO: should we set this to 1 instead? */
790 else if (verbose
== 1)
791 max
= 3; /* low; just to give an indication where we are */
796 * TODO: as is, this is highly inefficient, as we are typically copying
797 * in the same pieces of memory in repeatedly..
800 for (off
= 0; off
< size
; off
+= chunk
) {
802 if ((size_t)chunk
> sizeof(dirent
))
803 chunk
= (ssize_t
)sizeof(dirent
);
804 if ((size_t)chunk
< _DIRENT_MINSIZE(&dirent
))
807 if (mem_get_data(proc
->pid
, addr
+ off
, &dirent
, chunk
) < 0) {
809 put_ptr(proc
, name
, addr
);
818 put_open(proc
, name
, PF_NONAME
, "[", ", ");
821 put_struct_dirent(proc
, NULL
, PF_LOCADDR
,
824 if (chunk
> dirent
.d_reclen
)
825 chunk
= dirent
.d_reclen
;
830 put_tail(proc
, 0, 0);
831 else if (count
> max
)
832 put_tail(proc
, count
, max
);
833 put_close(proc
, "]");
837 vfs_getdents_out(struct trace_proc
* proc
, const message
* m_out
)
840 put_fd(proc
, "fd", m_out
->m_lc_vfs_readwrite
.fd
);
846 vfs_getdents_in(struct trace_proc
* proc
, const message
* m_out
,
847 const message
* m_in
, int failed
)
850 put_dirent_array(proc
, "buf", failed
, m_out
->m_lc_vfs_readwrite
.buf
,
852 put_value(proc
, "len", "%zu", m_out
->m_lc_vfs_readwrite
.len
);
858 put_fd_set(struct trace_proc
* proc
, const char * name
, vir_bytes addr
,
863 unsigned int i
, j
, words
, count
, max
;
865 if (addr
== 0 || nfds
< 0) {
866 put_ptr(proc
, name
, addr
);
872 * Each process may define its own FD_SETSIZE, so our fd_set may be of
873 * a different size than theirs. Thus, we copy at a granularity known
874 * to be valid in any case: a single word of bits. We make the
875 * assumption that fd_set consists purely of bits, so that we can use
876 * the second (and so on) bit word as an fd_set by itself.
878 words
= (nfds
+ NFDBITS
- 1) / NFDBITS
;
884 else if (verbose
== 1)
889 /* TODO: copy in more at once, but stick to fd_mask boundaries. */
890 for (off
= 0, i
= 0; i
< words
; i
++, off
+= sizeof(fd_mask
)) {
891 if (mem_get_data(proc
->pid
, addr
+ off
, &set
,
892 sizeof(fd_mask
)) != 0) {
894 put_ptr(proc
, name
, addr
);
902 for (j
= 0; j
< NFDBITS
; j
++) {
903 if (FD_ISSET(j
, &set
)) {
905 put_open(proc
, name
, PF_NONAME
, "[",
909 put_fd(proc
, NULL
, i
* NFDBITS
+ j
);
917 * The empty set should print as "[]". If copying any part failed, it
918 * should print as "[x, ..(?)]" where x is the set printed so far, if
919 * any. If copying never failed, and we did not print all fds in the
920 * set, print the remaining count n as "[x, ..(+n)]" at the end.
923 put_open(proc
, name
, PF_NONAME
, "[", " ");
926 put_tail(proc
, 0, 0);
927 else if (count
> max
)
928 put_tail(proc
, count
, max
);
930 put_close(proc
, "]");
934 vfs_select_out(struct trace_proc
* proc
, const message
* m_out
)
938 nfds
= m_out
->m_lc_vfs_select
.nfds
;
940 put_fd(proc
, "nfds", nfds
); /* not really a file descriptor.. */
941 put_fd_set(proc
, "readfds",
942 (vir_bytes
)m_out
->m_lc_vfs_select
.readfds
, nfds
);
943 put_fd_set(proc
, "writefds",
944 (vir_bytes
)m_out
->m_lc_vfs_select
.writefds
, nfds
);
945 put_fd_set(proc
, "errorfds",
946 (vir_bytes
)m_out
->m_lc_vfs_select
.errorfds
, nfds
);
947 put_struct_timeval(proc
, "timeout", 0, m_out
->m_lc_vfs_select
.timeout
);
953 vfs_select_in(struct trace_proc
* proc
, const message
* m_out
,
954 const message
* __unused m_in
, int failed
)
956 vir_bytes readfds
, writefds
, errorfds
;
963 nfds
= m_out
->m_lc_vfs_select
.nfds
;
965 readfds
= (vir_bytes
)m_out
->m_lc_vfs_select
.readfds
;
966 writefds
= (vir_bytes
)m_out
->m_lc_vfs_select
.writefds
;
967 errorfds
= (vir_bytes
)m_out
->m_lc_vfs_select
.errorfds
;
969 if (readfds
== 0 && writefds
== 0 && errorfds
== 0)
972 /* Omit names, because it looks weird. */
973 put_open(proc
, NULL
, PF_NONAME
, "(", ", ");
975 put_fd_set(proc
, "readfds", readfds
, nfds
);
977 put_fd_set(proc
, "writefds", writefds
, nfds
);
979 put_fd_set(proc
, "errorfds", errorfds
, nfds
);
980 put_close(proc
, ")");
984 vfs_fchdir_out(struct trace_proc
* proc
, const message
* m_out
)
987 put_fd(proc
, "fd", m_out
->m_lc_vfs_fchdir
.fd
);
993 vfs_fsync_out(struct trace_proc
* proc
, const message
* m_out
)
996 put_fd(proc
, "fd", m_out
->m_lc_vfs_fsync
.fd
);
1002 vfs_truncate_out(struct trace_proc
* proc
, const message
* m_out
)
1005 put_buf(proc
, "path", PF_PATH
, m_out
->m_lc_vfs_truncate
.name
,
1006 m_out
->m_lc_vfs_truncate
.len
);
1007 put_value(proc
, "length", "%"PRId64
, m_out
->m_lc_vfs_truncate
.offset
);
1013 vfs_ftruncate_out(struct trace_proc
* proc
, const message
* m_out
)
1016 put_fd(proc
, "fd", m_out
->m_lc_vfs_truncate
.fd
);
1017 put_value(proc
, "length", "%"PRId64
, m_out
->m_lc_vfs_truncate
.offset
);
1023 vfs_fchmod_out(struct trace_proc
* proc
, const message
* m_out
)
1026 put_fd(proc
, "fd", m_out
->m_lc_vfs_fchmod
.fd
);
1027 put_mode(proc
, "mode", m_out
->m_lc_vfs_fchmod
.mode
);
1033 vfs_fchown_out(struct trace_proc
* proc
, const message
* m_out
)
1036 put_fd(proc
, "fd", m_out
->m_lc_vfs_chown
.fd
);
1037 /* -1 means "keep the current value" so print as signed */
1038 put_value(proc
, "owner", "%d", m_out
->m_lc_vfs_chown
.owner
);
1039 put_value(proc
, "group", "%d", m_out
->m_lc_vfs_chown
.group
);
1045 vfs_utimens_name(const message
* m_out
)
1047 int has_path
, has_flags
;
1049 has_path
= (m_out
->m_vfs_utimens
.name
!= NULL
);
1050 has_flags
= (m_out
->m_vfs_utimens
.flags
!= 0);
1052 if (has_path
&& m_out
->m_vfs_utimens
.flags
== AT_SYMLINK_NOFOLLOW
)
1054 if (has_path
&& !has_flags
)
1056 else if (!has_path
&& !has_flags
)
1062 static const struct flags at_flags
[] = {
1064 FLAG(AT_SYMLINK_NOFOLLOW
),
1065 FLAG(AT_SYMLINK_FOLLOW
),
1070 put_utimens_timespec(struct trace_proc
* proc
, const char * name
,
1071 time_t sec
, long nsec
)
1074 /* No field names. */
1075 put_open(proc
, name
, PF_NONAME
, "{", ", ");
1077 put_time(proc
, "tv_sec", sec
);
1079 if (!valuesonly
&& nsec
== UTIME_NOW
)
1080 put_field(proc
, "tv_nsec", "UTIME_NOW");
1081 else if (!valuesonly
&& nsec
== UTIME_OMIT
)
1082 put_field(proc
, "tv_nsec", "UTIME_OMIT");
1084 put_value(proc
, "tv_nsec", "%ld", nsec
);
1086 put_close(proc
, "}");
1090 vfs_utimens_out(struct trace_proc
* proc
, const message
* m_out
)
1092 int has_path
, has_flags
;
1094 /* Here we do not care about the utimens/lutimens distinction. */
1095 has_path
= (m_out
->m_vfs_utimens
.name
!= NULL
);
1096 has_flags
= !!(m_out
->m_vfs_utimens
.flags
& ~AT_SYMLINK_NOFOLLOW
);
1098 if (has_path
&& has_flags
)
1099 put_field(proc
, "fd", "AT_CWD"); /* utimensat */
1101 put_fd(proc
, "fd", m_out
->m_vfs_utimens
.fd
); /* futimes */
1102 if (has_path
|| has_flags
) /* lutimes, utimes, utimensat */
1103 put_buf(proc
, "path", PF_PATH
,
1104 (vir_bytes
)m_out
->m_vfs_utimens
.name
,
1105 m_out
->m_vfs_utimens
.len
);
1107 put_open(proc
, "times", 0, "[", ", ");
1108 put_utimens_timespec(proc
, "atime", m_out
->m_vfs_utimens
.atime
,
1109 m_out
->m_vfs_utimens
.ansec
);
1110 put_utimens_timespec(proc
, "mtime", m_out
->m_vfs_utimens
.mtime
,
1111 m_out
->m_vfs_utimens
.mnsec
);
1112 put_close(proc
, "]");
1115 put_flags(proc
, "flag", at_flags
, COUNT(at_flags
), "0x%x",
1116 m_out
->m_vfs_utimens
.flags
);
1121 static const struct flags statvfs_flags
[] = {
1126 static const struct flags st_flags
[] = {
1128 FLAG(ST_SYNCHRONOUS
),
1134 FLAG(ST_NOCOREDUMP
),
1139 FLAG(ST_NODEVMTIME
),
1145 FLAG(ST_DEFEXPORTED
),
1146 FLAG(ST_EXPORTANON
),
1148 FLAG(ST_EXNORESPORT
),
1157 put_struct_statvfs(struct trace_proc
* proc
, const char * name
, int flags
,
1162 if (!put_open_struct(proc
, name
, flags
, addr
, &buf
, sizeof(buf
)))
1165 put_flags(proc
, "f_flag", st_flags
, COUNT(st_flags
), "0x%x",
1167 put_value(proc
, "f_bsize", "%lu", buf
.f_bsize
);
1168 if (verbose
> 0 || buf
.f_bsize
!= buf
.f_frsize
)
1169 put_value(proc
, "f_frsize", "%lu", buf
.f_frsize
);
1171 put_value(proc
, "f_iosize", "%lu", buf
.f_iosize
);
1173 put_value(proc
, "f_blocks", "%"PRIu64
, buf
.f_blocks
);
1174 put_value(proc
, "f_bfree", "%"PRIu64
, buf
.f_bfree
);
1176 put_value(proc
, "f_bavail", "%"PRIu64
, buf
.f_bavail
);
1177 put_value(proc
, "f_bresvd", "%"PRIu64
, buf
.f_bresvd
);
1181 put_value(proc
, "f_files", "%"PRIu64
, buf
.f_files
);
1182 put_value(proc
, "f_ffree", "%"PRIu64
, buf
.f_ffree
);
1185 put_value(proc
, "f_favail", "%"PRIu64
, buf
.f_favail
);
1186 put_value(proc
, "f_fresvd", "%"PRIu64
, buf
.f_fresvd
);
1190 put_value(proc
, "f_syncreads", "%"PRIu64
, buf
.f_syncreads
);
1191 put_value(proc
, "f_syncwrites", "%"PRIu64
, buf
.f_syncwrites
);
1192 put_value(proc
, "f_asyncreads", "%"PRIu64
, buf
.f_asyncreads
);
1193 put_value(proc
, "f_asyncwrites", "%"PRIu64
, buf
.f_asyncwrites
);
1195 put_value(proc
, "f_fsidx", "<%"PRId32
",%"PRId32
">",
1196 buf
.f_fsidx
.__fsid_val
[0], buf
.f_fsidx
.__fsid_val
[1]);
1198 put_dev(proc
, "f_fsid", buf
.f_fsid
); /* MINIX3 interpretation! */
1201 put_value(proc
, "f_namemax", "%lu", buf
.f_namemax
);
1203 put_value(proc
, "f_owner", "%u", buf
.f_owner
);
1205 put_buf(proc
, "f_fstypename", PF_STRING
| PF_LOCADDR
,
1206 (vir_bytes
)&buf
.f_fstypename
, sizeof(buf
.f_fstypename
));
1208 put_buf(proc
, "f_mntfromname", PF_STRING
| PF_LOCADDR
,
1209 (vir_bytes
)&buf
.f_mntfromname
, sizeof(buf
.f_mntfromname
));
1210 put_buf(proc
, "f_mntonname", PF_STRING
| PF_LOCADDR
,
1211 (vir_bytes
)&buf
.f_mntonname
, sizeof(buf
.f_mntonname
));
1213 put_close_struct(proc
, verbose
> 1);
1217 put_statvfs_array(struct trace_proc
* proc
, const char * name
, int flags
,
1218 vir_bytes addr
, int count
)
1223 if ((flags
& PF_FAILED
) || valuesonly
> 1 || count
< 0) {
1224 put_ptr(proc
, name
, addr
);
1230 put_field(proc
, name
, "[]");
1237 else if (verbose
== 1)
1238 max
= 1; /* TODO: is this reasonable? */
1245 for (i
= 0; i
< max
; i
++) {
1246 if (mem_get_data(proc
->pid
, addr
+ i
* sizeof(buf
), &buf
,
1249 put_ptr(proc
, name
, addr
);
1258 put_open(proc
, name
, PF_NONAME
, "[", ", ");
1260 put_struct_statvfs(proc
, NULL
, PF_LOCADDR
, (vir_bytes
)&buf
);
1264 put_open(proc
, name
, PF_NONAME
, "[", ", ");
1266 put_tail(proc
, 0, 0);
1268 put_tail(proc
, count
, i
);
1269 put_close(proc
, "]");
1273 vfs_getvfsstat_out(struct trace_proc
* proc
, const message
* m_out
)
1276 if (m_out
->m_lc_vfs_getvfsstat
.buf
== 0) {
1277 put_ptr(proc
, "buf", m_out
->m_lc_vfs_getvfsstat
.buf
);
1278 put_value(proc
, "bufsize", "%zu",
1279 m_out
->m_lc_vfs_getvfsstat
.len
);
1280 put_flags(proc
, "flags", statvfs_flags
, COUNT(statvfs_flags
),
1281 "%d", m_out
->m_lc_vfs_getvfsstat
.flags
);
1288 vfs_getvfsstat_in(struct trace_proc
* proc
, const message
* m_out
,
1289 const message
* m_in
, int failed
)
1292 if (m_out
->m_lc_vfs_getvfsstat
.buf
!= 0) {
1293 put_statvfs_array(proc
, "buf", failed
,
1294 m_out
->m_lc_vfs_getvfsstat
.buf
, m_in
->m_type
);
1295 put_value(proc
, "bufsize", "%zu",
1296 m_out
->m_lc_vfs_getvfsstat
.len
);
1297 put_flags(proc
, "flags", statvfs_flags
, COUNT(statvfs_flags
),
1298 "%d", m_out
->m_lc_vfs_getvfsstat
.flags
);
1305 vfs_statvfs1_out(struct trace_proc
* proc
, const message
* m_out
)
1308 put_buf(proc
, "path", PF_PATH
, m_out
->m_lc_vfs_statvfs1
.name
,
1309 m_out
->m_lc_vfs_statvfs1
.len
);
1315 vfs_statvfs1_in(struct trace_proc
* proc
, const message
* m_out
,
1316 const message
* __unused m_in
, int failed
)
1319 put_struct_statvfs(proc
, "buf", failed
, m_out
->m_lc_vfs_statvfs1
.buf
);
1320 put_flags(proc
, "flags", statvfs_flags
, COUNT(statvfs_flags
), "%d",
1321 m_out
->m_lc_vfs_statvfs1
.flags
);
1326 /* This function is shared between statvfs1 and fstatvfs1. */
1328 vfs_fstatvfs1_out(struct trace_proc
* proc
, const message
* m_out
)
1331 put_fd(proc
, "fd", m_out
->m_lc_vfs_statvfs1
.fd
);
1337 vfs_svrctl_out(struct trace_proc
* proc
, const message
* m_out
)
1340 put_ioctl_req(proc
, "request", m_out
->m_lc_svrctl
.request
,
1341 TRUE
/*is_svrctl*/);
1342 return put_ioctl_arg_out(proc
, "arg", m_out
->m_lc_svrctl
.request
,
1343 m_out
->m_lc_svrctl
.arg
, TRUE
/*is_svrctl*/);
1347 vfs_svrctl_in(struct trace_proc
* proc
, const message
* m_out
,
1348 const message
* __unused m_in
, int failed
)
1351 put_ioctl_arg_in(proc
, "arg", failed
, m_out
->m_lc_svrctl
.request
,
1352 m_out
->m_lc_svrctl
.arg
, TRUE
/*is_svrctl*/);
1356 vfs_gcov_flush_out(struct trace_proc
* proc
, const message
* m_out
)
1359 put_buf(proc
, "label", PF_STRING
, m_out
->m_lc_vfs_gcov
.label
,
1360 m_out
->m_lc_vfs_gcov
.labellen
);
1361 put_ptr(proc
, "buff", m_out
->m_lc_vfs_gcov
.buf
);
1362 put_value(proc
, "buff_sz", "%zu", m_out
->m_lc_vfs_gcov
.buflen
);
1368 put_socket_family(struct trace_proc
* proc
, const char * name
, int family
)
1370 const char *text
= NULL
;
1374 * For socket(2) and socketpair(2) this should really be using
1375 * the prefix "PF_" since those functions take a protocol
1376 * family rather than an address family. This rule is applied
1377 * fairly consistently within the system. Here I caved because
1378 * I don't want to duplicate this entire function just for the
1379 * one letter. There are exceptions however; some names only
1421 put_field(proc
, name
, text
);
1423 put_value(proc
, name
, "%d", family
);
1426 static const struct flags socket_types
[] = {
1427 FLAG_MASK(~SOCK_FLAGS_MASK
, SOCK_STREAM
),
1428 FLAG_MASK(~SOCK_FLAGS_MASK
, SOCK_DGRAM
),
1429 FLAG_MASK(~SOCK_FLAGS_MASK
, SOCK_RAW
),
1430 FLAG_MASK(~SOCK_FLAGS_MASK
, SOCK_RDM
),
1431 FLAG_MASK(~SOCK_FLAGS_MASK
, SOCK_SEQPACKET
),
1432 FLAG_MASK(~SOCK_FLAGS_MASK
, SOCK_CONN_DGRAM
),
1434 FLAG(SOCK_NONBLOCK
),
1435 FLAG(SOCK_NOSIGPIPE
),
1439 put_socket_type(struct trace_proc
* proc
, const char * name
, int type
)
1442 put_flags(proc
, name
, socket_types
, COUNT(socket_types
), "%d", type
);
1446 put_socket_protocol(struct trace_proc
* proc
, const char * name
, int family
,
1447 int type
, int protocol
)
1449 const char *text
= NULL
;
1451 if (!valuesonly
&& (type
== SOCK_RAW
|| protocol
!= 0)) {
1455 /* TODO: is this all that is used in socket(2)? */
1462 TEXT(IPPROTO_ICMPV6
);
1470 TEXT(BTPROTO_L2CAP
);
1471 TEXT(BTPROTO_RFCOMM
);
1480 put_field(proc
, name
, text
);
1482 put_value(proc
, name
, "%d", protocol
);
1486 vfs_socket_out(struct trace_proc
* proc
, const message
* m_out
)
1489 put_socket_family(proc
, "domain", m_out
->m_lc_vfs_socket
.domain
);
1490 put_socket_type(proc
, "type", m_out
->m_lc_vfs_socket
.type
);
1491 put_socket_protocol(proc
, "protocol", m_out
->m_lc_vfs_socket
.domain
,
1492 m_out
->m_lc_vfs_socket
.type
& ~SOCK_FLAGS_MASK
,
1493 m_out
->m_lc_vfs_socket
.protocol
);
1499 vfs_socketpair_out(struct trace_proc
* proc
, const message
* m_out
)
1502 put_socket_family(proc
, "domain", m_out
->m_lc_vfs_socket
.domain
);
1503 put_socket_type(proc
, "type", m_out
->m_lc_vfs_socket
.type
);
1504 put_socket_protocol(proc
, "protocol", m_out
->m_lc_vfs_socket
.domain
,
1505 m_out
->m_lc_vfs_socket
.type
& ~SOCK_FLAGS_MASK
,
1506 m_out
->m_lc_vfs_socket
.protocol
);
1512 vfs_socketpair_in(struct trace_proc
* proc
, const message
* m_out
,
1513 const message
* m_in
, int failed
)
1517 put_open(proc
, "fd", PF_NONAME
, "[", ", ");
1518 put_fd(proc
, "fd0", m_in
->m_vfs_lc_fdpair
.fd0
);
1519 put_fd(proc
, "fd1", m_in
->m_vfs_lc_fdpair
.fd1
);
1520 put_close(proc
, "]");
1522 put_field(proc
, "fd", "&..");
1528 put_in_addr(struct trace_proc
* proc
, const char * name
, struct in_addr in
)
1532 /* Is this an acceptable encapsulation? */
1533 put_value(proc
, name
, "[%s]", inet_ntoa(in
));
1535 put_value(proc
, name
, "0x%08x", ntohl(in
.s_addr
));
1539 put_in6_addr(struct trace_proc
* proc
, const char * name
, struct in6_addr
* in
)
1541 char buf
[INET6_ADDRSTRLEN
];
1546 (ptr
= inet_ntop(AF_INET6
, in
, buf
, sizeof(buf
))) != NULL
) {
1547 put_value(proc
, name
, "[%s]", ptr
);
1549 for (i
= n
= 0; i
< 16; i
++)
1550 n
+= snprintf(buf
+ n
, sizeof(buf
) - n
, "%02x",
1551 ((unsigned char *)in
)[i
]);
1552 put_value(proc
, name
, "0x%s", buf
);
1557 put_struct_sockaddr(struct trace_proc
* proc
, const char * name
, int flags
,
1558 vir_bytes addr
, socklen_t addr_len
)
1560 char buf
[UCHAR_MAX
+ 1];
1564 struct sockaddr_in sin
;
1565 struct sockaddr_in6 sin6
;
1569 * For UNIX domain sockets, make sure there's always room to add a
1570 * trailing NULL byte, because UDS paths are not necessarily null
1573 if (addr_len
< offsetof(struct sockaddr
, sa_data
) ||
1574 addr_len
>= sizeof(buf
)) {
1575 put_ptr(proc
, name
, addr
);
1580 if (!put_open_struct(proc
, name
, flags
, addr
, buf
, addr_len
))
1583 memcpy(&sa
, buf
, sizeof(sa
));
1585 family
= sa
.sa_family
;
1586 all
= (verbose
> 1);
1591 put_value(proc
, "sun_len", "%u", len
);
1593 put_socket_family(proc
, "sun_family", family
);
1594 off
= (int)offsetof(struct sockaddr_un
, sun_path
);
1595 left
= addr_len
- off
;
1597 buf
[addr_len
] = 0; /* force null termination */
1598 put_buf(proc
, "sun_path", PF_LOCADDR
| PF_PATH
,
1599 (vir_bytes
)&buf
[off
],
1600 left
+ 1 /* include null byte */);
1605 put_value(proc
, "sin_len", "%u", len
);
1607 put_socket_family(proc
, "sin_family", family
);
1608 if (addr_len
== sizeof(sin
)) {
1609 memcpy(&sin
, buf
, sizeof(sin
));
1610 put_value(proc
, "sin_port", "%u", ntohs(sin
.sin_port
));
1611 put_in_addr(proc
, "sin_addr", sin
.sin_addr
);
1617 put_value(proc
, "sin6_len", "%u", len
);
1619 put_socket_family(proc
, "sin6_family", family
);
1620 if (addr_len
== sizeof(sin6
)) {
1621 memcpy(&sin6
, buf
, sizeof(sin6
));
1622 put_value(proc
, "sin6_port", "%u",
1623 ntohs(sin6
.sin6_port
));
1625 put_value(proc
, "sin6_flowinfo", "%"PRIu32
,
1626 sin6
.sin6_flowinfo
);
1627 put_in6_addr(proc
, "sin6_addr", &sin6
.sin6_addr
);
1628 if (IN6_IS_ADDR_LINKLOCAL(&sin6
.sin6_addr
) ||
1629 IN6_IS_ADDR_MC_NODELOCAL(&sin6
.sin6_addr
) ||
1630 IN6_IS_ADDR_MC_LINKLOCAL(&sin6
.sin6_addr
) ||
1632 put_value(proc
, "sin6_scope_id", "%"PRIu32
,
1633 sin6
.sin6_scope_id
);
1637 /* TODO: support for other address families */
1640 put_value(proc
, "sa_len", "%u", len
);
1641 put_socket_family(proc
, "sa_family", family
);
1642 all
= (verbose
> 1 && family
== AF_UNSPEC
);
1645 put_close_struct(proc
, all
);
1648 /* This function is shared between bind and connect. */
1650 vfs_bind_out(struct trace_proc
* proc
, const message
* m_out
)
1653 put_fd(proc
, "fd", m_out
->m_lc_vfs_sockaddr
.fd
);
1654 put_struct_sockaddr(proc
, "addr", 0, m_out
->m_lc_vfs_sockaddr
.addr
,
1655 m_out
->m_lc_vfs_sockaddr
.addr_len
);
1656 put_value(proc
, "addr_len", "%u", m_out
->m_lc_vfs_sockaddr
.addr_len
);
1662 vfs_listen_out(struct trace_proc
* proc
, const message
* m_out
)
1665 put_fd(proc
, "fd", m_out
->m_lc_vfs_listen
.fd
);
1666 put_value(proc
, "backlog", "%d", m_out
->m_lc_vfs_listen
.backlog
);
1672 vfs_accept_out(struct trace_proc
* proc
, const message
* m_out
)
1675 put_fd(proc
, "fd", m_out
->m_lc_vfs_sockaddr
.fd
);
1681 vfs_accept_in(struct trace_proc
* proc
, const message
* m_out
,
1682 const message
* m_in
, int failed
)
1685 put_struct_sockaddr(proc
, "addr", failed
,
1686 m_out
->m_lc_vfs_sockaddr
.addr
, m_in
->m_vfs_lc_socklen
.len
);
1688 * We print the resulting address length rather than the given buffer
1689 * size here, as we do in recvfrom, getsockname, getpeername, and (less
1690 * explicitly) recvmsg. We could also print both, by adding the
1691 * resulting length after the call result.
1693 if (m_out
->m_lc_vfs_sockaddr
.addr
== 0)
1694 put_field(proc
, "addr_len", "NULL");
1696 put_value(proc
, "addr_len", "{%u}",
1697 m_in
->m_vfs_lc_socklen
.len
);
1699 put_field(proc
, "addr_len", "&..");
1705 static const struct flags msg_flags
[] = {
1708 FLAG(MSG_DONTROUTE
),
1719 FLAG(MSG_CMSG_CLOEXEC
),
1721 FLAG(MSG_WAITFORONE
),
1725 vfs_sendto_out(struct trace_proc
* proc
, const message
* m_out
)
1728 put_fd(proc
, "fd", m_out
->m_lc_vfs_sendrecv
.fd
);
1729 put_buf(proc
, "buf", 0, m_out
->m_lc_vfs_sendrecv
.buf
,
1730 m_out
->m_lc_vfs_readwrite
.len
);
1731 put_value(proc
, "len", "%zu", m_out
->m_lc_vfs_sendrecv
.len
);
1732 put_flags(proc
, "flags", msg_flags
, COUNT(msg_flags
), "0x%x",
1733 m_out
->m_lc_vfs_sendrecv
.flags
);
1734 put_struct_sockaddr(proc
, "addr", 0, m_out
->m_lc_vfs_sendrecv
.addr
,
1735 m_out
->m_lc_vfs_sendrecv
.addr_len
);
1736 put_value(proc
, "addr_len", "%u", m_out
->m_lc_vfs_sendrecv
.addr_len
);
1742 put_struct_iovec(struct trace_proc
* proc
, const char * name
, int flags
,
1743 vir_bytes addr
, int len
, ssize_t bmax
)
1750 * For simplicity and clarity reasons, we currently print the I/O
1751 * vector as an array of data elements rather than an array of
1752 * structures. We also copy in each element separately, because as of
1753 * writing there is no system support for more than one element anyway.
1754 * All of this may be changed later.
1756 if ((flags
& PF_FAILED
) || valuesonly
> 1 || addr
== 0 || len
< 0) {
1757 put_ptr(proc
, name
, addr
);
1762 if (len
== 0 || bmax
== 0) {
1763 put_field(proc
, name
, "[]");
1768 /* As per logic below, 'imax' must be set to a nonzero value here. */
1771 else if (verbose
== 1)
1776 for (i
= 0; i
< len
&& bmax
> 0; i
++) {
1777 if (mem_get_data(proc
->pid
, addr
, &iov
, sizeof(iov
)) < 0) {
1779 put_ptr(proc
, name
, addr
);
1784 len
= imax
= 0; /* make put_tail() print an error */
1789 put_open(proc
, name
, 0, "[", ", ");
1791 bytes
= MIN(iov
.iov_len
, (size_t)bmax
);
1794 put_buf(proc
, NULL
, 0, (vir_bytes
)iov
.iov_base
, bytes
);
1796 addr
+= sizeof(struct iovec
);
1800 if (imax
== 0 || imax
< len
)
1801 put_tail(proc
, len
, imax
);
1802 put_close(proc
, "]");
1806 put_struct_sockcred(struct trace_proc
* proc
, const char * name
, int flags
,
1807 vir_bytes addr
, size_t left
)
1811 if (!put_open_struct(proc
, name
, flags
, addr
, &sc
, sizeof(sc
)))
1814 put_value(proc
, "sc_uid", "%u", sc
.sc_uid
);
1816 put_value(proc
, "sc_euid", "%u", sc
.sc_euid
);
1817 put_value(proc
, "sc_gid", "%u", sc
.sc_gid
);
1819 put_value(proc
, "sc_egid", "%u", sc
.sc_egid
);
1821 put_value(proc
, "sc_ngroups", "%d", sc
.sc_ngroups
);
1822 if (left
>= sizeof(sc
.sc_groups
[0]) * (sc
.sc_ngroups
- 1)) {
1823 put_groups(proc
, "sc_groups", flags
,
1824 addr
+ offsetof(struct sockcred
, sc_groups
),
1827 put_field(proc
, "sc_groups", "..");
1830 put_close_struct(proc
, verbose
> 1);
1834 put_socket_level(struct trace_proc
* proc
, const char * name
, int level
)
1838 * Unfortunately, the level is a domain-specific protocol number. That
1839 * means that without knowing how the socket was created, we cannot
1840 * tell what it means. The only thing we can print is SOL_SOCKET,
1841 * which is the same across all domains.
1843 if (!valuesonly
&& level
== SOL_SOCKET
)
1844 put_field(proc
, name
, "SOL_SOCKET");
1846 put_value(proc
, name
, "%d", level
);
1850 put_cmsg_type(struct trace_proc
* proc
, const char * name
, int type
)
1852 const char *text
= NULL
;
1858 TEXT(SCM_TIMESTAMP
);
1863 put_field(proc
, name
, text
);
1865 put_value(proc
, name
, "%d", type
);
1869 put_cmsg_rights(struct trace_proc
* proc
, const char * name
, char * buf
,
1870 size_t size
, char * cptr
, size_t chunk
, vir_bytes addr
, size_t len
)
1872 unsigned int i
, nfds
;
1875 put_open(proc
, name
, PF_NONAME
, "[", ", ");
1878 * Since file descriptors are important, we print them all, regardless
1879 * of the current verbosity level. Start with the file descriptors
1880 * that are already copied into the local buffer.
1883 chunk
= MIN(chunk
, len
);
1885 nfds
= chunk
/ sizeof(int);
1886 for (i
= 0; i
< nfds
; i
++)
1887 put_fd(proc
, NULL
, ptr
[i
]);
1889 /* Then do the remaining file descriptors, in chunks. */
1890 size
-= size
% sizeof(int);
1892 for (len
-= chunk
; len
>= sizeof(int); len
-= chunk
) {
1893 chunk
= MIN(len
, size
);
1895 if (mem_get_data(proc
->pid
, addr
, buf
, chunk
) < 0) {
1896 put_field(proc
, NULL
, "..");
1902 nfds
= chunk
/ sizeof(int);
1903 for (i
= 0; i
< nfds
; i
++)
1904 put_fd(proc
, NULL
, ptr
[i
]);
1909 put_close(proc
, "]");
1913 put_cmsg(struct trace_proc
* proc
, const char * name
, vir_bytes addr
,
1916 struct cmsghdr cmsg
;
1917 char buf
[CMSG_SPACE(sizeof(struct sockcred
))];
1918 size_t off
, chunk
, datalen
;
1920 if (valuesonly
> 1 || addr
== 0 || len
< CMSG_LEN(0)) {
1921 put_ptr(proc
, name
, addr
);
1926 for (off
= 0; off
< len
; off
+= CMSG_SPACE(datalen
)) {
1927 chunk
= MIN(len
- off
, sizeof(buf
));
1929 if (chunk
< CMSG_LEN(0))
1932 if (mem_get_data(proc
->pid
, addr
+ off
, buf
, chunk
) < 0) {
1934 put_ptr(proc
, name
, addr
);
1942 put_open(proc
, name
, 0, "[", ", ");
1944 memcpy(&cmsg
, buf
, sizeof(cmsg
));
1946 put_open(proc
, NULL
, 0, "{", ", ");
1948 put_value(proc
, "cmsg_len", "%u", cmsg
.cmsg_len
);
1949 put_socket_level(proc
, "cmsg_level", cmsg
.cmsg_level
);
1950 if (cmsg
.cmsg_level
== SOL_SOCKET
)
1951 put_cmsg_type(proc
, "cmsg_type", cmsg
.cmsg_type
);
1953 put_value(proc
, "cmsg_type", "%d", cmsg
.cmsg_type
);
1955 if (cmsg
.cmsg_len
< CMSG_LEN(0) || off
+ cmsg
.cmsg_len
> len
) {
1956 put_tail(proc
, 0, 0);
1957 put_close(proc
, "}");
1961 datalen
= cmsg
.cmsg_len
- CMSG_LEN(0);
1963 if (cmsg
.cmsg_level
== SOL_SOCKET
&&
1964 cmsg
.cmsg_type
== SCM_RIGHTS
) {
1965 put_cmsg_rights(proc
, "cmsg_data", buf
, sizeof(buf
),
1966 &buf
[CMSG_LEN(0)], chunk
- CMSG_LEN(0),
1967 addr
+ off
+ chunk
, datalen
);
1968 } else if (cmsg
.cmsg_level
== SOL_SOCKET
&&
1969 cmsg
.cmsg_type
== SCM_CREDS
&&
1970 datalen
>= sizeof(struct sockcred
) &&
1971 chunk
>= CMSG_LEN(datalen
)) {
1972 put_struct_sockcred(proc
, "cmsg_data", PF_LOCADDR
,
1973 (vir_bytes
)&buf
[CMSG_LEN(0)],
1974 datalen
- sizeof(struct sockcred
));
1975 } else if (datalen
> 0)
1976 put_field(proc
, "cmsg_data", "..");
1979 put_field(proc
, NULL
, "..");
1980 put_close(proc
, "}");
1984 put_field(proc
, NULL
, "..");
1985 put_close(proc
, "]");
1989 put_struct_msghdr(struct trace_proc
* proc
, const char * name
, int flags
,
1990 vir_bytes addr
, ssize_t max
)
1995 if (!put_open_struct(proc
, name
, flags
, addr
, &msg
, sizeof(msg
)))
2000 if (msg
.msg_name
!= NULL
|| verbose
> 1) {
2001 put_struct_sockaddr(proc
, "msg_name", 0,
2002 (vir_bytes
)msg
.msg_name
, msg
.msg_namelen
);
2004 put_value(proc
, "msg_namelen", "%u", msg
.msg_namelen
);
2010 put_struct_iovec(proc
, "msg_iov", 0, (vir_bytes
)msg
.msg_iov
,
2011 msg
.msg_iovlen
, max
);
2013 put_value(proc
, "msg_iovlen", "%d", msg
.msg_iovlen
);
2017 if (msg
.msg_control
!= NULL
|| verbose
> 1) {
2018 put_cmsg(proc
, "msg_control", (vir_bytes
)msg
.msg_control
,
2019 msg
.msg_controllen
);
2022 put_value(proc
, "msg_controllen", "%u",
2023 msg
.msg_controllen
);
2029 /* When receiving, print the flags field as well. */
2031 put_flags(proc
, "msg_flags", msg_flags
, COUNT(msg_flags
),
2032 "0x%x", msg
.msg_flags
);
2034 put_close_struct(proc
, all
);
2038 vfs_sendmsg_out(struct trace_proc
* proc
, const message
* m_out
)
2041 put_fd(proc
, "fd", m_out
->m_lc_vfs_sockmsg
.fd
);
2042 put_struct_msghdr(proc
, "msg", 0, m_out
->m_lc_vfs_sockmsg
.msgbuf
,
2044 put_flags(proc
, "flags", msg_flags
, COUNT(msg_flags
), "0x%x",
2045 m_out
->m_lc_vfs_sockmsg
.flags
);
2051 vfs_recvfrom_out(struct trace_proc
* proc
, const message
* m_out
)
2054 put_fd(proc
, "fd", m_out
->m_lc_vfs_sendrecv
.fd
);
2060 vfs_recvfrom_in(struct trace_proc
* proc
, const message
* m_out
,
2061 const message
* m_in
, int failed
)
2064 put_buf(proc
, "buf", failed
, m_out
->m_lc_vfs_sendrecv
.buf
,
2066 put_value(proc
, "len", "%zu", m_out
->m_lc_vfs_sendrecv
.len
);
2067 put_flags(proc
, "flags", msg_flags
, COUNT(msg_flags
), "0x%x",
2068 m_out
->m_lc_vfs_sendrecv
.flags
);
2069 put_struct_sockaddr(proc
, "addr", failed
,
2070 m_out
->m_lc_vfs_sendrecv
.addr
, m_in
->m_vfs_lc_socklen
.len
);
2071 if (m_out
->m_lc_vfs_sendrecv
.addr
== 0)
2072 put_field(proc
, "addr_len", "NULL");
2074 put_value(proc
, "addr_len", "{%u}",
2075 m_in
->m_vfs_lc_socklen
.len
);
2077 put_field(proc
, "addr_len", "&..");
2084 vfs_recvmsg_out(struct trace_proc
* proc
, const message
* m_out
)
2087 put_fd(proc
, "fd", m_out
->m_lc_vfs_sockmsg
.fd
);
2093 vfs_recvmsg_in(struct trace_proc
* proc
, const message
* m_out
,
2094 const message
* m_in
, int failed
)
2098 * We choose to print only the resulting structure in this case. Doing
2099 * so is easier and less messy than printing both the original and the
2100 * result for the fields that are updated by the system (msg_namelen
2101 * and msg_controllen); also, this approach is stateless. Admittedly
2102 * it is not entirely consistent with many other parts of the trace
2105 put_struct_msghdr(proc
, "msg", PF_ALT
| failed
,
2106 m_out
->m_lc_vfs_sockmsg
.msgbuf
, m_in
->m_type
);
2107 put_flags(proc
, "flags", msg_flags
, COUNT(msg_flags
), "0x%x",
2108 m_out
->m_lc_vfs_sockmsg
.flags
);
2115 put_sockopt_name(struct trace_proc
* proc
, const char * name
, int level
,
2118 const char *text
= NULL
;
2121 * The only level for which we can know names is SOL_SOCKET. See also
2122 * put_socket_level(). Of course we could guess, but then we need a
2123 * proper guessing system, which should probably also take into account
2124 * the [gs]etsockopt option length. TODO.
2126 if (!valuesonly
&& level
== SOL_SOCKET
) {
2129 TEXT(SO_ACCEPTCONN
);
2134 TEXT(SO_USELOOPBACK
);
2146 TEXT(SO_OVERFLOWED
);
2154 put_field(proc
, name
, text
);
2156 put_value(proc
, name
, "0x%x", optname
);
2160 put_sockopt_data(struct trace_proc
* proc
, const char * name
, int flags
,
2161 int level
, int optname
, vir_bytes addr
, socklen_t len
)
2170 /* See above regarding ambiguity for levels other than SOL_SOCKET. */
2171 if ((flags
& PF_FAILED
) || valuesonly
> 1 || len
== 0 ||
2172 level
!= SOL_SOCKET
) {
2173 put_ptr(proc
, name
, addr
);
2178 /* Determine how much data to get, and where to put it. */
2186 case SO_USELOOPBACK
:
2212 put_ptr(proc
, name
, addr
);
2216 /* Get the data. Do not bother with truncated values. */
2217 if (len
< size
|| mem_get_data(proc
->pid
, addr
, ptr
, size
) < 0) {
2218 put_ptr(proc
, name
, addr
);
2223 /* Print the data according to the option name. */
2226 /* This isn't going to appear anywhere else; do it inline. */
2227 put_open(proc
, name
, 0, "{", ", ");
2228 put_value(proc
, "l_onoff", "%d", l
.l_onoff
);
2229 put_value(proc
, "l_linger", "%d", l
.l_linger
);
2230 put_close(proc
, "}");
2233 put_open(proc
, name
, 0, "{", ", ");
2234 if (!valuesonly
&& (text
= get_error_name(i
)) != NULL
)
2235 put_field(proc
, NULL
, text
);
2237 put_value(proc
, NULL
, "%d", i
);
2238 put_close(proc
, "}");
2241 put_open(proc
, name
, 0, "{", ", ");
2242 put_socket_type(proc
, NULL
, i
);
2243 put_close(proc
, "}");
2247 put_struct_timeval(proc
, name
, PF_LOCADDR
, (vir_bytes
)&tv
);
2250 /* All other options are integer values. */
2251 put_value(proc
, name
, "{%d}", i
);
2256 vfs_setsockopt_out(struct trace_proc
* proc
, const message
* m_out
)
2260 level
= m_out
->m_lc_vfs_sockopt
.level
;
2261 name
= m_out
->m_lc_vfs_sockopt
.name
;
2263 put_fd(proc
, "fd", m_out
->m_lc_vfs_sockopt
.fd
);
2264 put_socket_level(proc
, "level", level
);
2265 put_sockopt_name(proc
, "name", level
, name
);
2266 put_sockopt_data(proc
, "buf", 0, level
, name
,
2267 m_out
->m_lc_vfs_sockopt
.buf
, m_out
->m_lc_vfs_sockopt
.len
);
2268 put_value(proc
, "len", "%u", m_out
->m_lc_vfs_sockopt
.len
);
2274 vfs_getsockopt_out(struct trace_proc
* proc
, const message
* m_out
)
2278 level
= m_out
->m_lc_vfs_sockopt
.level
;
2280 put_fd(proc
, "fd", m_out
->m_lc_vfs_sockopt
.fd
);
2281 put_socket_level(proc
, "level", level
);
2282 put_sockopt_name(proc
, "name", level
, m_out
->m_lc_vfs_sockopt
.name
);
2288 vfs_getsockopt_in(struct trace_proc
* proc
, const message
* m_out
,
2289 const message
* m_in
, int failed
)
2292 put_sockopt_data(proc
, "buf", failed
, m_out
->m_lc_vfs_sockopt
.level
,
2293 m_out
->m_lc_vfs_sockopt
.name
, m_out
->m_lc_vfs_sockopt
.buf
,
2294 m_in
->m_vfs_lc_socklen
.len
);
2296 * For the length, we follow the same scheme as for addr_len pointers
2297 * in accept() et al., in that we print the result only. We need not
2298 * take into account that the given buffer is NULL as it must not be.
2301 put_value(proc
, "len", "%u", m_out
->m_lc_vfs_sockopt
.len
);
2303 put_field(proc
, "len", "&..");
2309 /* This function is shared between getsockname and getpeername. */
2311 vfs_getsockname_out(struct trace_proc
* proc
, const message
* m_out
)
2314 put_fd(proc
, "fd", m_out
->m_lc_vfs_sockaddr
.fd
);
2320 vfs_getsockname_in(struct trace_proc
* proc
, const message
* m_out
,
2321 const message
* m_in
, int failed
)
2324 put_struct_sockaddr(proc
, "addr", failed
,
2325 m_out
->m_lc_vfs_sockaddr
.addr
, m_in
->m_vfs_lc_socklen
.len
);
2326 if (m_out
->m_lc_vfs_sockaddr
.addr
== 0)
2327 put_field(proc
, "addr_len", "NULL");
2329 put_value(proc
, "addr_len", "{%u}",
2330 m_in
->m_vfs_lc_socklen
.len
);
2332 put_field(proc
, "addr_len", "&..");
2339 put_shutdown_how(struct trace_proc
* proc
, const char * name
, int how
)
2341 const char *text
= NULL
;
2352 put_field(proc
, name
, text
);
2354 put_value(proc
, name
, "%d", how
);
2358 vfs_shutdown_out(struct trace_proc
* proc
, const message
* m_out
)
2361 put_fd(proc
, "fd", m_out
->m_lc_vfs_shutdown
.fd
);
2362 put_shutdown_how(proc
, "how", m_out
->m_lc_vfs_shutdown
.how
);
2367 #define VFS_CALL(c) [((VFS_ ## c) - VFS_BASE)]
2369 static const struct call_handler vfs_map
[] = {
2370 VFS_CALL(READ
) = HANDLER("read", vfs_read_out
, vfs_read_in
),
2371 VFS_CALL(WRITE
) = HANDLER("write", vfs_write_out
, default_in
),
2372 VFS_CALL(LSEEK
) = HANDLER("lseek", vfs_lseek_out
, vfs_lseek_in
),
2373 VFS_CALL(OPEN
) = HANDLER("open", vfs_open_out
, vfs_open_in
),
2374 VFS_CALL(CREAT
) = HANDLER("open", vfs_creat_out
, vfs_open_in
),
2375 VFS_CALL(CLOSE
) = HANDLER("close", vfs_close_out
, default_in
),
2376 VFS_CALL(LINK
) = HANDLER("link", vfs_link_out
, default_in
),
2377 VFS_CALL(UNLINK
) = HANDLER("unlink", vfs_path_out
, default_in
),
2378 VFS_CALL(CHDIR
) = HANDLER("chdir", vfs_path_out
, default_in
),
2379 VFS_CALL(MKDIR
) = HANDLER("mkdir", vfs_path_mode_out
, default_in
),
2380 VFS_CALL(MKNOD
) = HANDLER("mknod", vfs_mknod_out
, default_in
),
2381 VFS_CALL(CHMOD
) = HANDLER("chmod", vfs_path_mode_out
, default_in
),
2382 VFS_CALL(CHOWN
) = HANDLER("chown", vfs_chown_out
, default_in
),
2383 VFS_CALL(MOUNT
) = HANDLER("mount", vfs_mount_out
, default_in
),
2384 VFS_CALL(UMOUNT
) = HANDLER("umount", vfs_umount_out
, vfs_umount_in
),
2385 VFS_CALL(ACCESS
) = HANDLER("access", vfs_access_out
, default_in
),
2386 VFS_CALL(SYNC
) = HANDLER("sync", default_out
, default_in
),
2387 VFS_CALL(RENAME
) = HANDLER("rename", vfs_link_out
, default_in
),
2388 VFS_CALL(RMDIR
) = HANDLER("rmdir", vfs_path_out
, default_in
),
2389 VFS_CALL(SYMLINK
) = HANDLER("symlink", vfs_link_out
, default_in
),
2390 VFS_CALL(READLINK
) = HANDLER("readlink", vfs_readlink_out
,
2392 VFS_CALL(STAT
) = HANDLER("stat", vfs_stat_out
, vfs_stat_in
),
2393 VFS_CALL(FSTAT
) = HANDLER("fstat", vfs_fstat_out
, vfs_fstat_in
),
2394 VFS_CALL(LSTAT
) = HANDLER("lstat", vfs_stat_out
, vfs_stat_in
),
2395 VFS_CALL(IOCTL
) = HANDLER("ioctl", vfs_ioctl_out
, vfs_ioctl_in
),
2396 VFS_CALL(FCNTL
) = HANDLER("fcntl", vfs_fcntl_out
, vfs_fcntl_in
),
2397 VFS_CALL(PIPE2
) = HANDLER("pipe2", vfs_pipe2_out
, vfs_pipe2_in
),
2398 VFS_CALL(UMASK
) = HANDLER("umask", vfs_umask_out
, vfs_umask_in
),
2399 VFS_CALL(CHROOT
) = HANDLER("chroot", vfs_path_out
, default_in
),
2400 VFS_CALL(GETDENTS
) = HANDLER("getdents", vfs_getdents_out
,
2402 VFS_CALL(SELECT
) = HANDLER("select", vfs_select_out
, vfs_select_in
),
2403 VFS_CALL(FCHDIR
) = HANDLER("fchdir", vfs_fchdir_out
, default_in
),
2404 VFS_CALL(FSYNC
) = HANDLER("fsync", vfs_fsync_out
, default_in
),
2405 VFS_CALL(TRUNCATE
) = HANDLER("truncate", vfs_truncate_out
, default_in
),
2406 VFS_CALL(FTRUNCATE
) = HANDLER("ftruncate", vfs_ftruncate_out
,
2408 VFS_CALL(FCHMOD
) = HANDLER("fchmod", vfs_fchmod_out
, default_in
),
2409 VFS_CALL(FCHOWN
) = HANDLER("fchown", vfs_fchown_out
, default_in
),
2410 VFS_CALL(UTIMENS
) = HANDLER_NAME(vfs_utimens_name
, vfs_utimens_out
,
2412 VFS_CALL(GETVFSSTAT
) = HANDLER("getvfsstat", vfs_getvfsstat_out
,
2414 VFS_CALL(STATVFS1
) = HANDLER("statvfs1", vfs_statvfs1_out
,
2416 VFS_CALL(FSTATVFS1
) = HANDLER("fstatvfs1", vfs_fstatvfs1_out
,
2418 VFS_CALL(SVRCTL
) = HANDLER("vfs_svrctl", vfs_svrctl_out
,
2420 VFS_CALL(GCOV_FLUSH
) = HANDLER("gcov_flush", vfs_gcov_flush_out
,
2422 VFS_CALL(SOCKET
) = HANDLER("socket", vfs_socket_out
, default_in
),
2423 VFS_CALL(SOCKETPAIR
) = HANDLER("socketpair", vfs_socketpair_out
,
2425 VFS_CALL(BIND
) = HANDLER("bind", vfs_bind_out
, default_in
),
2426 VFS_CALL(CONNECT
) = HANDLER("connect", vfs_bind_out
, default_in
),
2427 VFS_CALL(LISTEN
) = HANDLER("listen", vfs_listen_out
, default_in
),
2428 VFS_CALL(ACCEPT
) = HANDLER("accept", vfs_accept_out
, vfs_accept_in
),
2429 VFS_CALL(SENDTO
) = HANDLER("sendto", vfs_sendto_out
, default_in
),
2430 VFS_CALL(SENDMSG
) = HANDLER("sendmsg", vfs_sendmsg_out
, default_in
),
2431 VFS_CALL(RECVFROM
) = HANDLER("recvfrom", vfs_recvfrom_out
,
2433 VFS_CALL(RECVMSG
) = HANDLER("recvmsg", vfs_recvmsg_out
,
2435 VFS_CALL(SETSOCKOPT
) = HANDLER("setsockopt", vfs_setsockopt_out
,
2437 VFS_CALL(GETSOCKOPT
) = HANDLER("getsockopt", vfs_getsockopt_out
,
2439 VFS_CALL(GETSOCKNAME
) = HANDLER("getsockname", vfs_getsockname_out
,
2440 vfs_getsockname_in
),
2441 VFS_CALL(GETPEERNAME
) = HANDLER("getpeername", vfs_getsockname_out
,
2442 vfs_getsockname_in
),
2443 VFS_CALL(SHUTDOWN
) = HANDLER("shutdown", vfs_shutdown_out
, default_in
),
2446 const struct calls vfs_calls
= {
2447 .endpt
= VFS_PROC_NR
,
2450 .count
= COUNT(vfs_map
)