KTRACE(2)

๐Ÿ“ฆ
version 15.1 ยท 2 versions
, in freebsd 15.1

๐Ÿ’… KTRACE(2) โ€” process tracing, but make it a vibe

okay so first things first: this is the <pink>KTRACE(2)</pink> page from the <purple>System Calls Manual</purple>, and it lives in the <mint>Standard C Library (libc, -lc)</mint> ๐Ÿ’– so yeah, it's a real one, bestie.


โœจ NAME โœจ

ktrace โ€” process tracing ๐Ÿ•ต๏ธโ€โ™€๏ธ literally watching your processes do their thing


๐ŸŽ€ LIBRARY ๐ŸŽ€

Standard C Library (libc, -lc) โ€” she's standard, she's C, she's in libc, and you link her with -lc. iykyk ๐Ÿซถ


๐ŸŒธ SYNOPSIS ๐ŸŒธ

#include <sys/param.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/ktrace.h>

int
ktrace(const char *tracefile, int ops, int trpoints, int pid);

four includes, one function, zero drama. slay ๐Ÿ’…


๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

The ktrace() system call enables or disables tracing of one or more processes. it's giving <hotpink>main character energy</hotpink> but for syscalls. ๐Ÿ”ฅ

so like, important boundary check: <yellow>**users may only trace their own processes**. no spying on your roommate's processes, that's not cute. and only the superuser can trace setuid or setgid programs</yellow> โ€” that one's a hard rule, don't test it, it will not go well for you ๐Ÿ˜ญ

the tracefile argument ๐Ÿ“

The tracefile argument gives the pathname of the file to be used for tracing. and it has OPINIONS:

  • the file <yellow>**must exist**` (you can't just point at vibes)
  • it must be a <yellow>**regular file**` (no sockets, no chaos)
  • it must be <yellow>**writable by the calling process**`

and here's the part that trips people up: all trace records are <hotpink>always appended</hotpink> to the file. always. so if you want to throw away the old trace data, you have to <red>**truncate the file to zero length yourself**` โ€” it will not do it for you, she does not clean up after you ๐Ÿ’€

small mercy tho: if tracing points are being disabled (that's KTROP_CLEAR down below ๐Ÿ‘‡), tracefile may be NULL. ngl that's the one time NULL is acceptable here.

the ops argument ๐Ÿ”ฅ

The ops argument specifies the requested ktrace operation. the defined operations are:

  • KTROP_SET โ€” Enable trace points specified in trpoints. (turn the lights on โœจ)
  • KTROP_CLEAR โ€” Disable trace points specified in trpoints. (turn those specific lights off ๐ŸŒ™)
  • KTROP_CLEARFILE โ€” Stop all tracing. periodt. everything off, go home ๐Ÿ’…
  • KTRFLAG_DESCEND โ€” The tracing change should apply to the specified process and all its current children. (yes, the whole friend group gets included ๐Ÿ‘ฏโ€โ™€๏ธ)

the trpoints argument ๐Ÿงš

The trpoints argument specifies the trace points of interest. the defined trace points are:

  • KTRFAC_SYSCALL โ€” Trace system calls. the classics ๐ŸŽฌ
  • KTRFAC_SYSRET โ€” Trace return values from system calls. what did she say back ๐Ÿ‘€
  • KTRFAC_NAMEI โ€” Trace name lookup operations. path resolution tea โ˜•
  • KTRFAC_GENIO โ€” Trace all I/O (note that this option can generate much output). and bestie, when they say <red>**much**` output they mean it โ€” this is the firehose option, prepare your disk ๐Ÿ˜ญ๐Ÿ”ฅ
  • KTRFAC_PSIG โ€” Trace posted signals. ๐Ÿ“ฎ
  • KTRFAC_CSW โ€” Trace context switch points. the switching, the switching ๐Ÿ”„
  • KTRFAC_USER โ€” Trace application-specific events. your app's own little diary ๐Ÿ“”
  • KTRFAC_STRUCT โ€” Trace certain data structures. structural, literally ๐Ÿ—๏ธ
  • KTRFAC_SYSCTL โ€” Trace sysctls. โš™๏ธ
  • KTRFAC_PROCCTOR โ€” Trace process construction. baby process being born ๐Ÿผ ๐Ÿ‘ถ
  • KTRFAC_PROCDTOR โ€” Trace process destruction. rip in peace ๐Ÿชฆ
  • KTRFAC_CAPFAIL โ€” Trace capability failures. the audacity was not permitted ๐Ÿ’€
  • KTRFAC_FAULT โ€” Trace page faults. oops, not in memory ๐Ÿ™ˆ
  • KTRFAC_FAULTEND โ€” Trace the end of page faults. and we're back ๐ŸŽ€
  • KTRFAC_STRUCT_ARRAY โ€” Trace arrays of certain data structures. the structures, but plural, in formation ๐Ÿ‘‘
  • KTRFAC_INHERIT โ€” Inherit tracing to future children. passing the torch to the next generation ๐Ÿซถ

what a record actually looks like ๐Ÿ“

Each tracing event outputs a record composed of a generic header followed by a trace point specific structure. the generic header is:

struct ktr_header {
        int             ktr_len;                /* length of buf */
        short           ktr_type;               /* trace record type */
        pid_t           ktr_pid;                /* process id */
        char            ktr_comm[MAXCOMLEN+1];  /* command name */
        struct timeval  ktr_time;               /* timestamp */
        long            ktr_tid;                /* thread id */
};

okay so let's break down the header fields, because they all have jobs:

  • The ktr_len field specifies the length of the ktr_type data that follows this header. so it's like, "how much stuff after me" ๐Ÿ“
  • The ktr_pid and ktr_comm fields specify the process and command generating the record. who and what ๐Ÿ‘‘
  • The ktr_time field gives the time (with <purple>microsecond resolution</purple>) that the record was generated. precise, she's very precise โฑ๏ธ
  • The ktr_tid field holds a thread id. the specific thread, bestie ๐Ÿงต

then: The generic header is followed by ktr_len bytes of a ktr_type record. and the type specific records are defined in the <sys/ktrace.h> include file โ€” go look, they're in there ๐Ÿฆ‹


โš™๏ธ SYSCTL TUNABLES โš™๏ธ

The following sysctl(8) tunables influence the behaviour of ktrace():

  • kern.ktrace.genio_size โ€” bounds the amount of data a traced I/O request will log to the trace file. (your emergency brake for KTRFAC_GENIO ๐Ÿ›‘)
  • kern.ktrace.request_pool โ€” bounds the number of trace events being logged at a time. (a queue size, basically, so the kernel doesn't get overwhelmed ๐Ÿšฆ)

also heads up: Sysctl tunables that control process debuggability (as determined by p_candebug(9)) also affect the operation of ktrace(). so permissions stuff elsewhere can absolutely come for you and block this. it's giving connected lore ๐Ÿงšโ€โ™€๏ธ


๐ŸŒˆ RETURN VALUES ๐ŸŒˆ

The ktrace() function returns the value 0 if successful; otherwise the value -1 is returned and the global variable errno is set to indicate the error. classic 0 good, -1 bad, errno tells you why ๐Ÿ˜ค


๐Ÿ’€ ERRORS ๐Ÿ’€

The ktrace() system call will fail if:

  • [ENOTDIR] โ€” A component of the path prefix is not a directory. (bestie you pointed at a file where a folder should be ๐Ÿ˜ญ)
  • [ENAMETOOLONG] โ€” A component of a pathname exceeded 255 characters, or an entire path name exceeded 1023 characters. (that's a really long path, chill ๐Ÿ™ˆ)
  • [ENOENT] โ€” The named tracefile does not exist. (it must exist! we said this! ๐Ÿ’€)
  • [EACCES] โ€” Search permission is denied for a component of the path prefix. ๐Ÿ”’
  • [ELOOP] โ€” Too many symbolic links were encountered in translating the pathname. (the symlinks are giving infinite recursion, and not the slay kind ๐ŸŒ€)
  • [EIO] โ€” An I/O error occurred while reading from or writing to the file system. ๐Ÿ’ฅ
  • [EINTEGRITY] โ€” Corrupted data was detected while reading from the file system. (something's rotten and it's not the vibe โš ๏ธ)
  • [ENOSYS] โ€” The kernel was not compiled with ktrace support. (they simply did not build it in ๐Ÿ’”)
โš ๏ธ lowkey important aside: A thread may be unable to log one or more tracing events due to a temporary shortage of resources. This condition is remembered by the kernel, and the next tracing request that succeeds will have the flag KTR_DROP set in its ktr_type field. so basically: if you ever see KTR_DROP, that means things got dropped earlier and the kernel remembered. don't ignore her ๐Ÿซถ

๐Ÿ‘‘ SEE ALSO ๐Ÿ‘‘


๐ŸŒˆ HISTORY ๐ŸŒˆ

The ktrace() system call first appeared in <rainbow>4.4BSD. a legacy icon, honestly ๐Ÿ’œ


anyway that's the whole page bestie ๐ŸŽ€ 10/10 would trace again. this version came to you from <pink>Debian</pink>, dated <purple>November 2, 2022</purple> โ€” mwah, love u, go read your trace files โœจ๐Ÿฆ‹๐Ÿ’…

๐Ÿ“ฆ where this page comes from
  • freebsd 15.1: base 15.1
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms