Creating an LTTng tracepoint file

LTTng is a framework to collect kernel tracepoint logs with low overhead (see 5.5 in Desnoyers’ thesis for eval). Instrumenting the kernel is done in two parts: adding a kernel tracepoint, and writing the LTTng adaptation layer. The process is documented in a section of the LTTng docs, however there are a few points that required fixing to make the adaptation layer work, detailed here.

The docs (at the time of writing of this post) show the following adaptation header:

#undef TRACE_SYSTEM
#define TRACE_SYSTEM hello
#if !defined(_TRACE_HELLO_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_HELLO_H
#include <linux/tracepoint.h>
LTTNG_TRACEPOINT_EVENT(
    /* format identical to mainline version for those */
    hello_world,
    TP_PROTO(int foo, const char* bar),
    TP_ARGS(foo, bar),
    /* possible differences */
    TP_STRUCT__entry(
        __field(int, my_int)
        __field(char, char0)
        __field(char, char1)
        __string(product, bar)
    ),
    /* notice the use of tp_assign()/tp_strcpy() and no semicolons */
    TP_fast_assign(
        tp_assign(my_int, foo)
        tp_assign(char0, bar[0])
        tp_assign(char1, bar[1])
        tp_strcpy(product, bar)
    ),
    /* This one is actually not used by LTTng either, but must be
     * present for the moment.
     */
    TP_printk("", 0)
/* no semicolon after this either */
)
#endif
/* other difference: do NOT include <trace/define_trace.h> */
#include "../../../probes/define_trace.h"

Correct #include

Compiling our module, with the described changes produced an error:

In file included from linux-stable-3.10-trace/include/linux/module.h:18:0,
                 from lttng-modules/probes/lttng-probe-tracelight.c:1:
lttng-modules/probes/../instrumentation/events/lttng-module/../../../probes/../instrumentation/events/lttng-module/tracelight.h:17:11: error: expected ‘)’ before ‘struct’
  TP_PROTO(struct inet_sock *inet, size_t len),
           ^
linux-stable-3.10-trace/include/linux/tracepoint.h:107:27: note: in definition of macro ‘TP_PROTO’
 #define TP_PROTO(args...) args
                           ^

We fixed those by removing “#include <linux/tracepoint.h>” and instead adding  “#include “../../../probes/lttng-tracepoint-event.h” as the first include.

Include guards

The next hurdle was many warnings that LTTNG_TRACEPOINT_EVENT is redefined:

In file included from lttng-modules/probes/../instrumentation/events/lttng-module/../../../probes/../instrumentation/events/lttng-module/tracelight.h:8:0,
                 from lttng-modules/probes/../instrumentation/events/lttng-module/../../../probes/define_trace.h:129,
                 from lttng-modules/probes/../instrumentation/events/lttng-module/tracelight.h:208,
                 from lttng-modules/probes/lttng-probe-tracelight.c:14:
/mnt/sdb1/yonch/unison/tracelight/lttng-modules/probes/../instrumentation/events/lttng-module/../../../probes/../instrumentation/events/lttng-module/../../../probes/lttng-tracepoint-event.h:38:0: warning: "LTTNG_TRACEPOINT_EVENT" redefined [enabled by default]
 #define LTTNG_TRACEPOINT_EVENT(name, proto, args, struct, assign, print) \
 ^
In file included from lttng-modules/probes/../instrumentation/events/lttng-module/tracelight.h:208:0,
                 from lttng-modules/probes/lttng-probe-tracelight.c:14:
/mnt/sdb1/yonch/unison/tracelight/lttng-modules/probes/../instrumentation/events/lttng-module/../../../probes/define_trace.h:75:0: note: this is the location of the previous definition
 #define LTTNG_TRACEPOINT_EVENT(name, proto, args, tstruct, assign, print)
 ^

Other LTTng headers in lttng-modules have changed their include guards from the linux kernel’s tracepoint files. For example:

#if !defined(_TRACE_NET_H) || defined(TRACE_HEADER_MULTI_READ)

versus LTTng:

#if !defined(LTTNG_TRACE_NET_H) || defined(TRACE_HEADER_MULTI_READ)

Having separate macros to guard the kernel header and the LTTng adaptation header fixed the warnings.

 Translating macros

Here’s a quick translation for some of the macros:

TRACE_EVENT = LTTNG_TRACEPOINT_EVENT
DECLARE_EVENT_CLASS = LTTNG_TRACEPOINT_EVENT_CLASS
DEFINE_EVENT = LTTNG_TRACEPOINT_EVENT_INSTANCE

Fixing semicolons

While the kernel tracepoints require a semicolon (;) after DEFINE_EVENT, these cause problems for LTTng, for example:

 CC [M] lttng-modules/probes/lttng-probe-tracelight-udp.o
In file included from lttng-modules/probes/../instrumentation/events/lttng-module/../../../probes/lttng-events.h:406:0,
 from lttng-modules/probes/../instrumentation/events/lttng-module/../../../probes/define_trace.h:136,
 from lttng-modules/probes/../instrumentation/events/lttng-module/tracelight_udp.h:83,
 from lttng-modules/probes/lttng-probe-tracelight-udp.c:14:
lttng-modules/probes/../instrumentation/events/lttng-module/../../../probes/../instrumentation/events/lttng-module/tracelight_udp.h:45:2: error: expected expression before ‘;’ token
 );
 ^
make[4]: *** [lttng-modules/probes/lttng-probe-tracelight-udp.o] Error 1

Removing all semicolons after the LTTNG_TRACEPOINT_* macros fixes this.

Multiple adaptation headers in one lttng-probe-*.c file – doesn’t work

Not everyone might encounter this, but if you’re trying to #include multiple LTTng adaptation headers in one file, this does not seem to be supported (at least not in the git repo of mid-January 2015). Both cases failed: (1) multiple headers are included for the same TRACE_SYSTEM (2) multiple headers with different TRACE_SYSTEMs. The macros redefine some functions, causing a compile error. FYI!

Happy LTTng’ing!

Posted in Tech Blog.

Leave a Reply

Your email address will not be published. Required fields are marked *