[lttng-dev] [RFC] Addition of layout description and format strings to CTF

Mathieu Desnoyers mathieu.desnoyers at efficios.com
Sun Nov 16 05:32:27 EST 2014

This document investigates how to best add description of formatting
layout to the Common Trace Format (CTF). The main intent here is to
allow LTTng-UST tracepoint instrumentation to describe how to print the
content of a sequence or array of bytes, so the resulting printout, in
Babeltrace, looks like this:

000015F0 5F 73 70 72 69 6E 74 66 5F 63 68 6B 00 5F 5F 78 _sprintf_chk.__x
00001600 73 74 61 74 00 6D 65 6D 6D 6F 76 65 00 5F 6F 62 stat.memmove._ob
00001610 73 74 61 63 6B 5F 62 65 67 69 6E 00 62 69 6E 64 stack_begin.bind

In the spirit of keeping this specification as succinct as possible, an
investigation phase is required before adding this descriptive element
to the Common Trace Format (CTF) specification, since it needs to be
done in a way that is as much as possible general, rather than specific
for this single use-case.

Therefore, this document also investigates how layout description can be
used to describe format strings that express the formatting of events.

Let's consider the description of a CTF TSDL event containing a

event {
  name = myevent;
  fields := struct {
    uint32_t len;
    uint8_t myseqfield[len];

We could introduce the concept of "type attribute" to CTF, thus adding
a "format" attribute attached to sequence:

event {
  name = myevent;
  fields := struct {
    uint32_t len;
    uint8_t myseqfield[len] __attribute__((format(hexdump)));

We however have to take into account that this attribute needs to fit
within the format strings that are about to be added to CTF. In order to
use a similar construct to express the event format strings, we could
also attach them as a "format" attribute of the structure type
describing the event payload. Those may look like:

event {
	name = myevent;
	fields := struct {
		uint64_t field1;
		uint32_t field2;
		uint16_t field3;
		uint32_t len;
		uint8_t myseqfield[len];
	} __attribute__((format(printf("Event has: %d, %x, %d. "
			"Sequence string is %s, hexdump is: %s",
		field1, field2, field3,
		myseqfield __attribute__((format(hexdump)))))));

Where %d means printing in base 10, signed, %x means printing in base
16, and %s means printing the target field following the field reference
formatter attribute or else the field's own printing format.

This ensures that the format string is expressed as a subset of type

In case there are many formatters specified for a field, such as:

event {
	name = myevent;
	fields := struct {
		uint64_t field1 __attribute__((format(printf("%x"))));
	} __attribute__((format(printf("Field hex: %s, dec: %s, dec: %d",
		field1, field1 __attribute__((format(printf("%d")))),

The format attribute of the reference always has precedence on the
format attribute of the field it refers to. In the example above, %s
takes the formatter of field1 (printf("%x")), whereas the second
reference to field1 overrides the formatter with a (printf(%d")), to
print it in base 10. The third reference to field1 uses %d directly in
the event structure payload formatter to force a decimal printing of the
field, which has the same result as the second reference.

Attaching the formatter as a type or field reference attribute allows
nesting of print formatting and layout description of nested structures,
arrays, sequences, and variants.

Feedback is welcome!



Mathieu Desnoyers
EfficiOS Inc.

More information about the lttng-dev mailing list