truss reports every system call a process makes, which for anything
larger than a toy program buries the calls of interest. Add -t, taking
a comma-separated expression naming the system calls to report.
A term is the name of a system call, which may contain the fnmatch(3)
wildcards; a system call number in decimal; or "@group" naming a group
of related system calls. A term prefixed with '!' excludes what that
one term matches rather than including it, and applies to no other
term. An expression whose terms are all negated subtracts from the set
of every system call; any other expression selects from an empty one.
Terms apply in order and the last one to match a system call decides
whether it is reported. Repeating -t appends, so "-t a -t b" and
"-t a,b" are equivalent. An empty term is ignored, so an empty
expression filters nothing and a stray comma is not an error.
truss -t @file,@net fetch https://www.freebsd.org/ truss -t '!@memory' make buildworld truss -t '@desc,!@read,!@write' -p 34 truss -c -t 'readlink*' /bin/ls truss -t 3,4 cat file
A number selects the system call with that number in the ABI of the
traced process, so "-t 3" selects read(2) from a native process but
close() from a Linux one.
Thirteen groups are provided to start with: @all, @creds, @desc, @file,
@ipc, @memory, @net, @none, @proc, @read, @signal, @time and @write.
These were derived by working through sys/kern/syscalls.master; the
audit event in that file is too sparse to drive the grouping by itself
(316 distinct events over 509 live system calls, 111 of them AUE_NULL),
so the groups are curated, but they are curated as patterns rather than
as name lists. A family sharing a naming convention is written as one
pattern -- "extattr_*_file", "__acl_*_fd", "sctp_*" -- so system calls
added later join the right group without further change here.
A group's member list is an expression in exactly the form -t accepts,
so a group can say anything a user can say on the command line: a
member may be a pattern, a number or another group, and may be negated.
@desc is built from @read and @write without repeating them, and @none
is the single member "!*". Keeping the two languages identical means a
group defined from a -t expression supplied elsewhere needs no
translation to become a member list. Adding a group is a member list
plus one entry in syscall_groups[].
"truss -t" with no expression prints the groups and exits.
Matching is done against the name truss displays and against that name
with any compatibility or ABI prefix removed, so @file selects
compat11.stat, freebsd32_stat and linux_newstat as well as stat.
A name or pattern matching no system call of any ABI truss understands
is reported with a warning, since it is almost always a typo, but it is
kept and simply never matches. sysdecode(3) is the oracle: it names
every system call of every such ABI whether or not that ABI's module is
loaded, and names them exactly as truss reports them. Numbers are not
checked this way. A process may issue any number the kernel can hold,
whether or not a system call is implemented behind it; one that is not
returns ENOSYS, which truss reports like any other result. Only a
number too large to be one at all is rejected.
A system call excluded by -t is not decoded, so the filter also removes
the cost of formatting arguments that would never be printed, and it is
left out of the -c summary.
The option letter is the one truss on System V Release 4 and SunOS uses
for this feature, "-t [!]syscall,...", and which truss(1) already names
as its model. The syntax is deliberately not bug-compatible with it:
there '!' is sticky for the remainder of a list, and a second -t
discards the first when the first began with '!'.
usr.bin/truss/tests is new, so etc/mtree/BSD.tests.dist gains an entry.
Without -t the behaviour is unchanged.
MFC after: 2 weeks