TRACE-CMD.DAT.V(5)

๐Ÿ’– TRACE-CMD.DAT.V(5) ๐Ÿ’–

okay bestie, so this page is literally called TRACE-CMD.DAT.V(5) in the manual index, but plot twist โ€” the page itself is all about trace-cmd.dat.v6, the version 6 file format. yes, the numbering is giving chaotic. anyway, buckle up ๐ŸŽ€

โœจ NAME โœจ

trace-cmd.dat.v6 โ€” the file format of trace-cmd version 6, no cap.

๐ŸŒธ SYNOPSIS ๐ŸŒธ

trace-cmd.dat ignore

๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

So trace-cmd(1) produces a "trace.dat" file. It might also be named literally anything else if the user passes a different output name โ€” the name is not the moment, the binary format is. This file is what trace-cmd uses to save kernel traces into, so it can scoop the trace back out later (see trace-cmd-report(1)). iconic behavior honestly โœจ


๐Ÿ’œ INITIAL FORMAT ๐Ÿ’œ

The first three bytes are the magic value, and yes she's magic:

0x17 0x08  0x44

Then the next 7 bytes hold these characters:

"tracing"

Then comes a null '\0' terminated string with the version of the file:

"6\0"

Next, 1 byte of flags for the file's endianness:

  • 0 = little endian
  • 1 = big endian

Then the next byte tells you the number of bytes per "long" value:

  • 4 โ€” 32-bit long values
  • 8 โ€” 64-bit long values
๐Ÿซถ Note: this is the long size of the target's userspace, not the kernel space size. important distinction, don't mix them up bestie.

[ Now all numbers are written in file defined endianess. ]

Then the next 4 bytes are a 32-bit word defining what the traced host machine page size was. cute.


๐ŸŽ€ HEADER INFO FORMAT ๐ŸŽ€

Right after the initial format comes the info about the trace headers recorded from the target box.

The next 12 bytes contain this string:

"header_page\0"

The next 8 bytes are a 64-bit word holding the size of the page header info stored next.

Then the actual data, sized by that previous 8 bytes, containing what was retrieved from debugfs/tracing/events/header_page.

๐Ÿ’… Note: the size of the second field commit contains the target kernel long size. for example: field: local_t commit; offset:8; size:8; signed:1; shows the kernel has a 64-bit long. slay, we love a self-describing field.

The next 13 bytes contain this string:

"header_event\0"

The next 8 bytes are a 64-bit word holding the size of the event header information stored next.

Then the data itself โ€” sized by the previous 8 bytes โ€” containing what was retrieved from debugfs/tracing/events/header_event.

This data is how the trace-cmd tool knows whether the ring buffer format of the kernel made any changes. lowkey a whole vibe check for the kernel ๐Ÿ”ฅ


๐Ÿงš FTRACE EVENT FORMATS ๐Ÿงš

Directly after the header information comes the info about the Ftrace specific events. These are the events used by the Ftrace plugins, and they are not enabled by the event tracing. (yes, they're the special ones.)

The next 4 bytes contain a 32-bit word: the number of Ftrace event format files stored in the file.

For that many times (as defined by the previous 4 bytes), you get:

  • 8 bytes for the size of the Ftrace event format file.

And the Ftrace event format file, copied from the target machine at:

debugfs/tracing/events/ftrace/<event>/format

๐ŸŒˆ EVENT FORMATS ๐ŸŒˆ

Directly after the Ftrace formats comes the info about the event layout.

The next 4 bytes are a 32-bit word containing the number of event systems stored in the file. These are the directories in debugfs/tracing/events โ€” excluding the ftrace directory. (not invited to this party.)

For that many times (as defined by the previous 4 bytes), here's the lineup:

  • A null-terminated string containing the system name.
  • 4 bytes containing a 32-bit word with the number of events within the system.

Then, for that many times (as defined in the previous 4 bytes):

  • 8 bytes for the size of the event format file.

And the event format file, copied from the target machine at:

debugfs/tracing/events/<system>/<event>/format

โญ KALLSYMS INFORMATION โญ

Directly after the event formats comes the info mapping function addresses to function names. the ultimate name-drop directory ๐Ÿ’…

The next 4 bytes are a 32-bit word containing the size of the data holding the function mappings.

Then the data itself, sized by the previous 4 bytes, containing the info from the target machine's file:

/proc/kallsyms

๐Ÿ“ TRACE_PRINTK INFORMATION ๐Ÿ“

If a developer used trace_printk() inside the kernel, it may store the format string outside the ring buffer. messy but valid. This information lives in:

debugfs/tracing/printk_formats

The next 4 bytes are a 32-bit word containing the size of the data holding the printk formats.

Then the data, sized by the previous 4 bytes, containing the info from debugfs/tracing/printk_formats.


๐Ÿ”ฅ PROCESS INFORMATION ๐Ÿ”ฅ

Directly after the trace_printk formats comes the info mapping a PID to a process name. main character identification energy, honestly.

The next 8 bytes contain a 64-bit word holding the size of the data mapping the PID to a process name.

Then the data, sized by the previous 8 bytes, containing the info from:

debugfs/tracing/saved_cmdlines

๐Ÿ‘‘ REST OF TRACE-CMD HEADER ๐Ÿ‘‘

Directly after the process info comes the last lil bit of the trace.dat file header.

The next 4 bytes are a 32-bit word defining the number of CPUs that were discovered on the target machine (and that have matching trace data for it).

The next 10 bytes are one of the following:

"options  \0"

"latency  \0"

"flyrecord\0"

๐Ÿ’ซ If it's "options \0" ๐Ÿ’ซ

Then:

  • The next 2 bytes are a 16-bit word defining the current option.
  • If that value is zero, there are no more options. periodt.
  • Otherwise, the next 4 bytes contain a 32-bit word with the option size. If the reader doesn't know how to handle the option, it can simply skip it. Currently there are no options defined, but this is here to extend the data. future-proofing queen.

The next option will be directly after the previous option, and the options end with a zero in the option type field.

The next 10 bytes after the options are one of the following:

"latency  \0"

"flyrecord\0"

โ€ฆwhich follows exactly the same as if the options were never present. no drama.

๐ŸŒธ If the value is "latency \0" ๐ŸŒธ

Then the rest of the file is simply ASCII text taken from the target's:

debugfs/tracing/trace

easy, readable, a little retro. we respect it.

๐Ÿฆ‹ If the value is "flyrecord\0" ๐Ÿฆ‹

Then the following is present:

For the number of CPUs that were read earlier, you get:

  • 8 bytes that are a 64-bit word containing the offset into the file that holds the data for the CPU.
  • 8 bytes that are a 64-bit word containing the size of the CPU data at that offset.

๐Ÿ’œ CPU DATA ๐Ÿ’œ

The CPU data lives in the part of the file specified at the end of the header. Padding is placed between the header and the CPU data, which places the CPU data at a page aligned (target page) position in the file. aesthetic AND functional.

This data is copied directly from the Ftrace ring buffer and has the same format as the ring buffer specified by the event header files loaded in the header format file.

The trace-cmd tool will try to mmap(2) the data page by page with the target's page size if possible. If it fails to mmap, it will just read the data instead. plan B never looked so good ๐Ÿ˜ญ


๐Ÿซถ SEE ALSO ๐Ÿซถ


โœจ AUTHOR โœจ

Written by Steven Rostedt, <rostedt@goodmis.org[1]> โ€” the legend himself ๐Ÿ‘‘


๐ŸŒˆ RESOURCES ๐ŸŒˆ

https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/

๐ŸŽ€ COPYING ๐ŸŽ€

Copyright (C) 2010 Red Hat, Inc. Free use of this software is granted under the terms of the GNU Public License (GPL).


๐Ÿ’… NOTES ๐Ÿ’…

  1. rostedt@goodmis.org mailto:rostedt@goodmis.org

okay that's the whole byte-by-byte tour bestie, you ate that ๐Ÿ“โœจ this page came from libtracefs, dated 03/09/2026 โ€” go forth and parse some traces, iykyk ๐Ÿ’–

๐Ÿ“ฆ where this page comes from