[lttng-dev] Emitting events from shared object constructors is (currently) not possible
Mathieu Desnoyers
mathieu.desnoyers at efficios.com
Thu Nov 22 10:39:01 EST 2012
* Woegerer, Paul (Paul_Woegerer at mentor.com) wrote:
> I recently stumbled over the following lttng-ust limitation:
>
> I tried to emit events from a shared objects constructor function:
>
> __attribute__((constructor))
> void func_constructor()
> {
> tracepoint( foo, bar );
> }
>
> Unfortunately this doesn't work because the constructor functions of
> LTTng itself (__tracepoints__init and the ones from
> ust-tracepoint-event.h) are not yet run.
>
> Trying to solve this problem with explicit constructor priority on my
> side alone doesn't work:
>
> __attribute__((constructor (1111)))
> void func_constructor()
> {
> tracepoint( foo, bar );
> }
>
> That's because whatever I specify as priority is irrelevant. LTTng's
> constructors without priority will always come last.
>
> After also adding priority to the lttng constructor I was able to make
> it work (see patch below):
Hi Paul,
I notice that you probably embed your probes along with your code within
the same shared object/executable, right ?
Unfortunately, this approach does not work if the probes are placed in a
different shared object than the program code. Here is an example:
a.c:
#include <stdio.h>
__attribute__((constructor(998)))
void fcta_prio1(void)
{
fprintf(stderr, "fcta prio 998\n");
}
__attribute__((constructor))
void fcta(void)
{
fprintf(stderr, "fcta\n");
}
__attribute__((constructor(1000)))
void fcta_prio2(void)
{
fprintf(stderr, "fcta prio 1000\n");
}
b.c:
#include <stdio.h>
__attribute__((constructor(999)))
void fctb_prio1(void)
{
fprintf(stderr, "fctb prio 999\n");
}
__attribute__((constructor))
void fctb(void)
{
fprintf(stderr, "fctb\n");
}
__attribute__((constructor(1001)))
void fctb_prio2(void)
{
fprintf(stderr, "fctb prio 1001\n");
}
main.c:
int main()
{
return 0;
}
Makefile:
all:
gcc -fPIC -shared -Wl,-soname,liba.so -o liba.so a.c
gcc -fPIC -shared -Wl,-soname,libb.so -o libb.so b.c
gcc -o test main.c -L./ -la -lb
exec with:
LD_LIBRARY_PATH=. ./test
result:
fctb prio 999
fctb prio 1001
fctb
fcta prio 998
fcta prio 1000
fcta
If we build test2 all within the same executable, then the order is
fine:
gcc -o test2 main.c a.c b.c
./test2
result:
fcta prio 998
fctb prio 999
fcta prio 1000
fctb prio 1001
fcta
fctb
As we can notice, the priority is effective within a shared object, but
has no ordering effect across .so. And having probes in separate .so is
a very typical use case.
One way we could envision allowing tracing of constructors in
applications is to ensure __tracepoints__init, which always resides
within the same object as the traced application code, runs with a
high constructor priorita -- low value -- (for code compiled by
compilers supporting this feature), and allow the application to invoke
the probe constructor early. So the proposed changes would be:
1 - add a constructor priority for
__tracepoints__init/__tracepoints_destroy in tracepoint.h.
Use macros to test for gcc version which allow this attribute.
2 - add some API that could let user code call
__lttng_events_init__PROVIDER_NAME explicitly.
Add an "already executed" flag to guard
__lttng_events_init__PROVIDER_NAME.
This API should still allow to LD_PRELOAD the probes (no dependency
on the probe symbols, possibly by using dlsym ?)
3 - make lttng_probe_register call lttng_ust_init needed.
Add an "already executed" flag to guard lttng_ust_init.
Thoughts ?
Thanks,
Mathieu
>
> diff --git a/include/lttng/tracepoint.h b/include/lttng/tracepoint.h
> index 8b08914..532f1d2 100644
> --- a/include/lttng/tracepoint.h
> +++ b/include/lttng/tracepoint.h
> @@ -261,7 +261,7 @@ int __tracepoint_registered
> struct tracepoint_dlopen tracepoint_dlopen
> __attribute__((weak, visibility("hidden")));
>
> -static void lttng_ust_notrace __attribute__((constructor))
> +static void lttng_ust_notrace __attribute__((constructor (1000)))
> __tracepoints__init(void);
> static void
> __tracepoints__init(void)
> @@ -300,7 +300,7 @@ __tracepoints__init(void)
> __start___tracepoints_ptrs);
> }
>
> -static void lttng_ust_notrace __attribute__((destructor))
> +static void lttng_ust_notrace __attribute__((destructor (1000)))
> __tracepoints__destroy(void);
> static void
> __tracepoints__destroy(void)
> diff --git a/include/lttng/ust-tracepoint-event.h b/include/lttng/ust-tracepoint-event.h
> index 74d06e1..7ad3144 100644
> --- a/include/lttng/ust-tracepoint-event.h
> +++ b/include/lttng/ust-tracepoint-event.h
> @@ -638,7 +638,7 @@ static struct lttng_probe_desc _TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PR
>
> /* Reset all macros within TRACEPOINT_EVENT */
> #include <lttng/ust-tracepoint-event-reset.h>
> -static void lttng_ust_notrace __attribute__((constructor))
> +static void lttng_ust_notrace __attribute__((constructor (1000)))
> _TP_COMBINE_TOKENS(__lttng_events_init__, TRACEPOINT_PROVIDER)(void);
> static void
> _TP_COMBINE_TOKENS(__lttng_events_init__, TRACEPOINT_PROVIDER)(void)
> @@ -649,7 +649,7 @@ _TP_COMBINE_TOKENS(__lttng_events_init__, TRACEPOINT_PROVIDER)(void)
> assert(!ret);
> }
>
> -static void lttng_ust_notrace __attribute__((destructor))
> +static void lttng_ust_notrace __attribute__((destructor (1000)))
> _TP_COMBINE_TOKENS(__lttng_events_exit__, TRACEPOINT_PROVIDER)(void);
> static void
> _TP_COMBINE_TOKENS(__lttng_events_exit__, TRACEPOINT_PROVIDER)(void)
>
>
>
> --
> Paul Woegerer | SW Development Engineer
> http://go.mentor.com/sourceryanalyzer
>
> Mentor Embedded(tm) | Prinz Eugen Straße 72/2/4, Vienna, 1040 Austria
> Nucleus® | Linux® | Android(tm) | Services | UI | Multi-OS
>
> Android is a trademark of Google Inc. Use of this trademark is subject to Google Permissions.
> Linux is the registered trademark of Linus Torvalds in the U.S. and other countries.
>
> _______________________________________________
> lttng-dev mailing list
> lttng-dev at lists.lttng.org
> http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
--
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
More information about the lttng-dev
mailing list