[lttng-dev] instrumenting shared library

Lingyu Zhu lynuszhu at gmail.com
Sat Apr 5 08:14:12 EDT 2014


Hi Andnd Neeli,
if you omit TRACEPOINT_PROBE_DYNAMIC_LINKAGE , you don't have to LD_PRELOAD
the share tp library. It acts just like statically linked app. and you can
use lttng enable-event command to enable the event tracing when your app
get something wrong without reloading(restarting)  your app.

'tracing mode' is not an official term, I just made it up :-) . It involves
to the UST internal implementation. You can consider app is not in tracing
mode when you have not LD_PRELOAD tp library, and it's in tracing mode if
you LD_PRELOAD.   Of course, the app is always in tracing mode when you
statically link tp library, or you omit TRACEPOINT_PROBE_DYNAMIC_LINKAGE..


On Sat, Apr 5, 2014 at 5:56 PM, Anand Neeli <anand.neeli at gmail.com> wrote:

> Hi Lingyu Zhu,
> what do you mean by switching on or off tracing mode?
> will i be able to trace or not trace without reloading the app?
> If i dont use LD_PRELOAD with tracepoint it never traces. and for tracing
> to start i should reload the app with ld_preload tracepoints.
> We would like to see the traces only when there is a problem in the app.
> And by reloading the app to enable traces we would loose all the app
> context (in problem state).
>
> Hope i'm not missing anything here.
>
> Thanks,
> Anand Neeli
>
>
>
> On Sat, Apr 5, 2014 at 12:14 PM, Lingyu Zhu <lynuszhu at gmail.com> wrote:
>
>> If you omit defining the macro TRACEPOINT_PROBE_DYNAMIC_LINKAGE in your
>> library which you want to trace, your library will depend on the trace
>> provider shared library. And you will not bother LD_PRELOAD your tracepoint
>> provider library before launching app.
>>
>> However, by doing so you will lose control over switching on or off
>> 'tracing mode': whenever your code is called,your tracepoint will try to
>> register and tracepoint() might have more overhead if you build your
>> library like that, whereas your tracepoint won't register and tracepoint()
>> macro just cost a simple branch if you do so by normal way and skip
>> LD_PRELOAD.
>>
>>
>> On Sat, Apr 5, 2014 at 4:16 AM, Anand Neeli <anand.neeli at gmail.com>wrote:
>>
>>> Hi Daniel,
>>> Thanks for your detailed mail.
>>> I will spend time with my code and get back if i have more queries.
>>>
>>> What i'm looking at it is: adding lttng infra in our code base. I'm
>>> looking for a solution where most of the lttng build and launch parts are
>>> abstracted to the end app/library developer.
>>> That is the reason why i'm not in favor of having LD_PRELOAD while
>>> launching an app. This would need the app developer to check if included
>>> libraries has tracing support and add .so appropriately to LD_PRELOAD
>>> (which needs more education to developer on lttng and included libraries)
>>> If we can launch app(with or without instrumented library) normally and
>>> limit the complexity of linking to makefile it will be great.
>>>
>>> Please keep me posted if you have any more thoughts on this.
>>> Also, can you please send me the users guide.
>>>
>>> Thanks,
>>> Anand Neeli
>>>
>>>
>>> On Fri, Apr 4, 2014 at 8:13 PM, Thibault, Daniel <
>>> Daniel.Thibault at drdc-rddc.gc.ca> wrote:
>>>
>>>>  *De :* Anand Neeli [mailto:anand.neeli at gmail.com]
>>>> *Envoyé :* 4 avril 2014 01:45
>>>>
>>>>   > Thanks for your reply.
>>>>
>>>> > Sorry for my ignorance but how are you generating libtp.so in your
>>>> example?
>>>>
>>>>
>>>>
>>>> Non-boilerplate parts are in red.
>>>>
>>>>
>>>>
>>>> tp.c:
>>>>
>>>> #####
>>>>
>>>> /*
>>>>
>>>> * Defining macro creates the code objects of the traceprobes.
>>>>
>>>> * Must be done only once per file (this #define controls tracepoint.h
>>>> and
>>>>
>>>> * tracepoint-event.h).
>>>>
>>>> */
>>>>
>>>> #define TRACEPOINT_CREATE_PROBES
>>>>
>>>> /*
>>>>
>>>> * The header containing our TRACEPOINT_EVENTs.
>>>>
>>>> */
>>>>
>>>> #include "tp.h"
>>>>
>>>> #####
>>>>
>>>> tp.h:
>>>> #####
>>>> #undef TRACEPOINT_PROVIDER
>>>>
>>>> #define TRACEPOINT_PROVIDER sample_component
>>>>
>>>> /*
>>>>
>>>> * include file (this files's name)
>>>>
>>>> */
>>>>
>>>> #undef TRACEPOINT_INCLUDE
>>>>
>>>> #define TRACEPOINT_INCLUDE "./tp.h"
>>>>
>>>> /*
>>>>
>>>> * Add this precompiler conditional to ensure the tracepoint event
>>>> generation
>>>>
>>>> * can include this file more than once.
>>>>
>>>> */
>>>>
>>>> #if !defined(_SAMPLE_COMPONENT_PROVIDER_H) ||
>>>> defined(TRACEPOINT_HEADER_MULTI_READ)
>>>>
>>>> #define _SAMPLE_COMPONENT_PROVIDER_H
>>>>
>>>> /*
>>>>
>>>> * Add this to allow programs to call "tracepoint(...)".
>>>>
>>>> * This #include must not be within an extern "C" block; if it is,
>>>>
>>>> * C++ instrumentation will fail when SystemTap is also installed.
>>>>
>>>> * (This may have been fixed since I wrote this)
>>>>
>>>> */
>>>>
>>>> #include <lttng/tracepoint.h>
>>>>
>>>> /*
>>>>
>>>> * Add this macro and its matching element to make sure the program
>>>>
>>>> * works in C++.
>>>>
>>>> */
>>>>
>>>> #ifdef __cplusplus
>>>>
>>>> extern "C" {
>>>>
>>>> #endif /* __cplusplus */
>>>>
>>>>
>>>>
>>>> /*
>>>>
>>>> * The following tracepoint event writes a message (C string) into the
>>>>
>>>> * field "message" of the trace event "event" in the provider
>>>>
>>>> * "sample_component" in other words:
>>>>
>>>> *
>>>>
>>>> *    sample_component:event:message = text.
>>>>
>>>> */
>>>>
>>>> TRACEPOINT_EVENT(
>>>>
>>>>             /*
>>>>
>>>>             * provider name, not a variable but a string starting with
>>>> a letter
>>>>
>>>>             * and containing either letters, numbers or underscores.
>>>>
>>>>             * Needs to be the same as TRACEPOINT_PROVIDER
>>>>
>>>>             */
>>>>
>>>>             sample_component,
>>>>
>>>>             /*
>>>>
>>>>             * tracepoint name, same format as sample provider. Does not
>>>> need to be
>>>>
>>>>             * declared before. in this case the name is "event"
>>>>
>>>>             */
>>>>
>>>>             event,
>>>>
>>>>             /*
>>>>
>>>>             * TP_ARGS macro contains the arguments passed for the
>>>> tracepoint.
>>>>
>>>>             * It is in the following format:
>>>>
>>>>             *                     TP_ARGS( type1, name1, type2, name2,
>>>> ... type10, name10)
>>>>
>>>>             * where there can be from zero to ten elements.
>>>>
>>>>             * "typeN" is the datatype, such as int, struct or double **.
>>>>
>>>>             * "name" is the variable name (in "int myInt" the name
>>>> would be "myInt")
>>>>
>>>>             *                     TP_ARGS() is valid (no arguments)
>>>>
>>>>             *                     TP_ARGS( void ) is valid too
>>>>
>>>>             */
>>>>
>>>>             TP_ARGS(const char *, text),
>>>>
>>>>             /*
>>>>
>>>>             * TP_FIELDS describes how to write the fields of the trace
>>>> event.
>>>>
>>>>             * You can use the args here
>>>>
>>>>             */
>>>>
>>>>             TP_FIELDS(
>>>>
>>>>             /*
>>>>
>>>>             * The ctf_string macro takes a C string and writes it into
>>>> a field
>>>>
>>>>             * named "message"
>>>>
>>>>             */
>>>>
>>>>                         ctf_string(message, text)
>>>>
>>>>             )
>>>>
>>>> )
>>>>
>>>> /*
>>>>
>>>> * Trace loglevel, shows the level of the trace event. It can be
>>>> TRACE_EMERG,
>>>>
>>>> * TRACE_ALERT, TRACE_CRIT, TRACE_ERR, TRACE_WARNING, TRACE_INFO, etc.
>>>>
>>>> * If this is not set, TRACE_DEFAULT is assumed.
>>>>
>>>> * The first two arguments identify the tracepoint.
>>>>
>>>> * See details in <lttng/tracepoint.h> line 347
>>>>
>>>> */
>>>>
>>>> TRACEPOINT_LOGLEVEL(
>>>>
>>>>        /*
>>>>
>>>>         * The provider name, must be the same as the provider name in
>>>> the
>>>>
>>>>         * TRACEPOINT_EVENT and as TRACEPOINT_PROVIDER above.
>>>>
>>>>         */
>>>>
>>>>             sample_component,
>>>>
>>>>        /*
>>>>
>>>>         * The tracepoint name, must be the same as the tracepoint name
>>>> in the
>>>>
>>>>         * TRACEPOINT_EVENT
>>>>
>>>>         */
>>>>
>>>>             event,
>>>>
>>>>        /*
>>>>
>>>>         * The tracepoint loglevel. WARNING: Some levels are abbreviated
>>>> and
>>>>
>>>>         * others are not, please see <lttng/tracepoint.h>
>>>>
>>>>         */
>>>>
>>>>             TRACE_WARNING
>>>>
>>>> )
>>>>
>>>>  (more tracepoints…)
>>>>
>>>>
>>>>
>>>> /*
>>>>
>>>> * Add this macro and its matching element to make sure the program
>>>>
>>>> * works in C++.
>>>>
>>>> */
>>>>
>>>> #ifdef __cplusplus
>>>>
>>>> }
>>>>
>>>> #endif /* __cplusplus */
>>>>
>>>> /*
>>>>
>>>> * Add this after defining the tracepoint events to expand the macros.
>>>>
>>>> */
>>>>
>>>> #include <lttng/tracepoint-event.h>
>>>>
>>>> #endif /* _SAMPLE_COMPONENT_PROVIDER_H */
>>>>
>>>> #####
>>>>
>>>> The relevant Makefile fragments:
>>>> #####
>>>> CC = gcc
>>>> LIBUST = -llttng-ust
>>>>
>>>> LOCAL_CPPFLAGS += -I. $(AM_CPPFLAGS)
>>>> LDFLAGS += -L/usr/local/lib $(AM_LDFLAGS)
>>>> SOFLAGS = -fPIC
>>>> SOVERSION_MAJOR = 1
>>>> SOVERSION_MINOR = 0
>>>>
>>>> libtp.so: libtp.o
>>>>
>>>>             @echo "~~~~~~Packaging $@:"
>>>>
>>>>             $(CC) -shared -Wl,-soname,$@.$(SOVERSION_MAJOR)
>>>> -Wl,-no-as-needed \
>>>>
>>>>                -o $@.$(SOVERSION_MAJOR).$(SOVERSION_MINOR) $(LDFLAGS)
>>>> $(LIBUST) $<
>>>>
>>>>             ln -sf $@.$(SOVERSION_MAJOR).$(SOVERSION_MINOR)
>>>> $@.$(SOVERSION_MAJOR)
>>>>
>>>>             ln -sf $@.$(SOVERSION_MAJOR) $@
>>>>
>>>>
>>>>
>>>> libtp.o: tp.c tp.h
>>>>
>>>>             @echo "~~~~~~Compiling $@:"
>>>>
>>>>             $(CC) $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(SOFLAGS) -c -o $@ $<
>>>>
>>>>
>>>> > 1) Also will this solution scale if my binary depends on lots
>>>> of libraries which are instrumented?
>>>>
>>>>
>>>>
>>>> Sure.  I’d expect linear scaling.  Each library, upon being loaded,
>>>> looks for its tracepoint provider and turns its tracepoints off if they’re
>>>> not found.
>>>>
>>>>
>>>>
>>>> > 2) i'm fine with linking statically, can we avoid LD_PRELOAD?
>>>>
>>>>
>>>>
>>>> Besides the LD_PRELOAD technique, you could also use LD_LIBRARY_PATH,
>>>> but that works only if the application statically includes the tracepoint
>>>> provider (I suppose it would likewise work for an instrumented shared
>>>> object only if it statically includes the tracepoint provider).
>>>>
>>>>
>>>>
>>>> You could also add "-Wl,-rpath,'$$ORIGIN'" to the linker call to add an
>>>> RPATH tag to the application (or shared object).  This makes it look for
>>>> its dependencies in its starting directory ($ORIGIN).  RPATH is, unlike
>>>> RUNPATH, applicable to libraries as well: a library with an RPATH tag will
>>>> look there for its dependencies; failing its own RPATH, it will use its
>>>> executable's RPATH.
>>>>
>>>>
>>>>
>>>> Finally, you can dynamically include the tracepoint provider (libtp) as
>>>> a dependency.  The application (sample_static_aware) is then statically
>>>> aware of libtp and won't run without it.  The application (sample_dynamic)
>>>> can alternately dynamically include the tracepoint provider *without*static awareness.  Here’s how it’s done:
>>>>
>>>>
>>>>
>>>> LIBDL = -ldl # On Linux
>>>>
>>>> #LIBDL = -lc # On BSD
>>>>
>>>> TP_DEFINE = -D TRACEPOINT_DEFINE
>>>>
>>>> TP_DEFINE_DYNAMIC = $(TP_DEFINE) -D TRACEPOINT_PROBE_DYNAMIC_LINKAGE
>>>>
>>>>
>>>>
>>>> #(the inclusion of a libtp NEEDED tag requires "-no-as-needed -ltp").
>>>>
>>>> #Note that "-L. -ltp", when used, should appear before $(LDFLAGS)
>>>> $(LIBDL).
>>>>
>>>> static_aware: static.o libtp.so
>>>>
>>>>             @echo "~~~~~~Linking sample_$@:"
>>>>
>>>> #          $(CC) -Wl,-no-as-needed -o sample_$@ -L. -ltp $< $(LDFLAGS)
>>>> $(LIBDL) \
>>>>
>>>> #             -Wl,-rpath,'$$ORIGIN',--enable-new-dtags
>>>>
>>>>             $(CC) -Wl,-no-as-needed -o sample_$@ -L. -ltp $< $(LDFLAGS)
>>>> $(LIBDL)
>>>>
>>>>             @echo "   Use 'LD_PRELOAD=./libtp.so ./sample_$@' to run
>>>> sample_$@"
>>>>
>>>>
>>>>
>>>> static.o: sample.c tp.h
>>>>
>>>>             @echo "~~~~~~Compiling $@:"
>>>>
>>>>             $(CC) $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(TP_DEFINE) -c -o $@ $<
>>>>
>>>>
>>>>
>>>> #If not preloaded, the sample application runs but won't be traceable.
>>>>
>>>> #Putting libtp in the path won't work: the sample does not look for it.
>>>>
>>>> dynamic: dynamic.o libtp.so
>>>>
>>>>             @echo "~~~~~~Linking sample_$@:"
>>>>
>>>>             $(CC) -o sample_$@ $< $(LDFLAGS) $(LIBDL)
>>>>
>>>>             @echo "   Use '[LD_PRELOAD=./libtp.so] ./sample_$@' to run
>>>> sample_$@"
>>>>
>>>>
>>>>
>>>> #Compare with the 'static.o' target.
>>>>
>>>> dynamic.o: sample.c tp.h
>>>>
>>>>             @echo "~~~~~~Compiling $@:"
>>>>
>>>>             $(CC) $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(TP_DEFINE_DYNAMIC) \
>>>>
>>>>                -c -o $@ $<
>>>>
>>>>
>>>>
>>>>    The case where the app isn’t traced but the library it uses is
>>>> traced should be a variation on this.  I’ll try it out sometime in the near
>>>> future, but you should be able to figure it out from the above.  Here’s a
>>>> first guess (it may need $(LIBDL) alongside $(LIBUST)):
>>>>
>>>>
>>>>
>>>> libtp.so: libtp.o
>>>>
>>>>             @echo "~~~~~~Packaging $@:"
>>>>
>>>>             $(CC) -shared -Wl,-soname,$@.$(SOVERSION_MAJOR)
>>>> -Wl,-no-as-needed -L. -ltp \
>>>>
>>>>                -o $@.$(SOVERSION_MAJOR).$(SOVERSION_MINOR) $(LDFLAGS)
>>>> $(LIBUST) $<
>>>>
>>>>             ln -sf $@.$(SOVERSION_MAJOR).$(SOVERSION_MINOR)
>>>> $@.$(SOVERSION_MAJOR)
>>>>
>>>>             ln -sf $@.$(SOVERSION_MAJOR) $@
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> > 3) Is there any page which explains on why and how to use
>>>>
>>>> > TRACEPOINT_PROVIDER, TRACEPOINT_CREATE_PROBES, TRACEPOINT_INCLUDE,
>>>> TRACEPOINT_DEFINE, TRACEPOINT_PROBE_DYNAMIC_LINKAGE
>>>>
>>>>
>>>>
>>>> They’re reasonably explained in the demonstration apps.  I discuss them
>>>> a little more in depth in the forthcoming LTTng Comprehensive User’s Guide
>>>> (I could send you a copy of the draft, as we’ve just begun its first review
>>>> round).
>>>>
>>>>
>>>>
>>>> > my tp.h is, are there any errors in this?
>>>>
>>>> > #############
>>>>
>>>>
>>>>
>>>> #undef TRACEPOINT_PROVIDER
>>>>
>>>>
>>>>
>>>> > #define TRACEPOINT_PROVIDER sample_component
>>>>
>>>> >
>>>>
>>>> > #undef TRACEPOINT_INCLUDE
>>>>
>>>> > #define TRACEPOINT_INCLUDE "./tp.h"
>>>>
>>>> >
>>>>
>>>> > #if !defined(_TP_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
>>>>
>>>> > #define _TP_H
>>>>
>>>>
>>>>
>>>> (Ideally, use _SAMPLE_COMPONENT_PROVIDER_H instead of _TP_H)
>>>>
>>>>
>>>>
>>>> > #include <lttng/tracepoint.h>
>>>>
>>>>
>>>>
>>>> #ifdef __cplusplus
>>>>
>>>> extern "C" {
>>>>
>>>> #endif /* __cplusplus */
>>>>
>>>>
>>>>
>>>> > TRACEPOINT_EVENT(
>>>>
>>>> >        sample_component,
>>>>
>>>> >        event,
>>>>
>>>> >        TP_ARGS(char *, text),
>>>>
>>>>
>>>>
>>>> (the compiler may be happier with const char * instead)
>>>>
>>>>
>>>>
>>>> >        TP_FIELDS(
>>>>
>>>> >                ctf_string(message, text)
>>>>
>>>> >        )
>>>>
>>>> >)
>>>>
>>>> > TRACEPOINT_LOGLEVEL(
>>>>
>>>> >        sample_component,
>>>>
>>>> >        event,
>>>>
>>>> >        TRACE_WARNING)
>>>>
>>>>
>>>>
>>>> #ifdef __cplusplus
>>>>
>>>> }
>>>>
>>>> #endif /* __cplusplus */
>>>>
>>>>
>>>>
>>>> > #endif /* _TP_H */
>>>>
>>>> > #include <lttng/tracepoint-event.h>
>>>>
>>>>
>>>>
>>>> (move #include <lttng/tracepoint-event.h> inside of the #if
>>>> !defined(_TP_H) || defined(TRACEPOINT_HEADER_MULTI_READ))
>>>>
>>>>
>>>>
>>>> > #############
>>>>
>>>> >
>>>>
>>>> > Thanks,
>>>>
>>>> > Anand Neeli
>>>>
>>>>
>>>>
>>>>    One key change I made to my sample applications is to remove the
>>>> “#define TRACEPOINT_DEFINE” that precedes the “#include "tp.h"” line.  I
>>>> prefer to control that #define using a compiler -D option.  It makes the
>>>> makefile clearer and resolves the problem of making sure there is just one
>>>> module that turns that #define on.
>>>>
>>>>
>>>>
>>>>    Hope this helps.
>>>>
>>>>
>>>>
>>>> Daniel U. Thibault
>>>> Protection des systèmes et contremesures (PSC) | Systems Protection &
>>>> Countermeasures (SPC)
>>>> Cyber sécurité pour les missions essentielles (CME) | Mission Critical
>>>> Cyber Security (MCCS)
>>>> R & D pour la défense Canada - Valcartier (RDDC Valcartier) | Defence
>>>> R&D Canada - Valcartier (DRDC Valcartier)
>>>> 2459 route de la Bravoure
>>>> Québec QC  G3J 1X5
>>>> CANADA
>>>> Vox : (418) 844-4000 x4245
>>>> Fax : (418) 844-4538
>>>> NAC : 918V QSDJ <http://www.travelgis.com/map.asp?addr=918V%20QSDJ<http://--ESFSECEV-TY3011-------------------------------->
>>>> >
>>>> Gouvernement du Canada | Government of Canada
>>>> <http://www.valcartier.drdc-rddc.gc.ca/<http://--ESFSECEV-TY3011--------------------->
>>>> >
>>>>
>>>
>>>
>>> _______________________________________________
>>> lttng-dev mailing list
>>> lttng-dev at lists.lttng.org
>>> http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lttng.org/pipermail/lttng-dev/attachments/20140405/c9ba9fec/attachment-0001.html>


More information about the lttng-dev mailing list