From 628e1d81fe575cfd281d8e0758b672b23d890c09 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Sat, 4 Feb 2012 14:37:34 -0500 Subject: [PATCH] Fix static provider linking: introduce TRACEPOINT_PROBE_DYNAMIC_LINKAGE We need to emit an unresolved symbol in the case where the provider is put into a statically linked library, otherwise the linker removes the provider object. See README for details. Signed-off-by: Mathieu Desnoyers --- README | 24 +++++++++++++++++++++--- include/lttng/tracepoint-types.h | 1 + include/lttng/tracepoint.h | 19 ++++++++++++++++++- include/lttng/ust-tracepoint-event.h | 6 +++++- tests/demo/demo.c | 1 + 5 files changed, 46 insertions(+), 5 deletions(-) diff --git a/README b/README index a3979763..23b83197 100644 --- a/README +++ b/README @@ -56,14 +56,31 @@ USAGE: - Create an instrumentation header following the tracepoint examples. See lttng/tracepoint.h, and examples. - - Either compile the Tracepoint probes with the application: + + There are 2 ways to compile the Tracepoint Provider with the + application: either statically or dynamically. Please follow + carefully: + + 1.1) Compile the Tracepoint provider with the application, either + directly or through a static library (.a): + - Into exactly one object of your application: define + "TRACEPOINT_DEFINE" and include the tracepoint provider. - Use "-I." for the compilation unit containing the tracepoint provider include (e.g. tp.c). - Link application with "-ldl -llttng-ust". + - Include the tracepoint provider header into all C files using + the provider. - Example: tests/hello/ hello.c tp.c ust_tests_hello.h Makefile.example - - Or compile the Tracepoint probes separately from the application, - using dynamic linking: + + 2) Compile the Tracepoint Provider separately from the application, + using dynamic linking: + - Into exactly one object of your application: define + "TRACEPOINT_DEFINE" _and_ also define + "TRACEPOINT_PROBE_DYNAMIC_LINKAGE", then include the tracepoint + provider header. + - Include the tracepoint provider header into all instrumented C + files that use the provider. - Compile the tracepoint provider with "-I.". - Link the tracepoint provider with "-llttng-ust". - Link application with "-ldl". @@ -72,6 +89,7 @@ USAGE: needed. - Example: - tests/demo/ demo.c tp*.c ust_tests_demo*.h demo-trace + - Note about dlopen() usage: due to locking side-effects due to the way libc lazily resolves Thread-Local Storage (TLS) symbols when a library is dlopen'd, linking the tracepoint probe or liblttng-ust diff --git a/include/lttng/tracepoint-types.h b/include/lttng/tracepoint-types.h index b6353c80..37a7662b 100644 --- a/include/lttng/tracepoint-types.h +++ b/include/lttng/tracepoint-types.h @@ -23,6 +23,7 @@ struct tracepoint { const char *name; int state; struct tracepoint_probe *probes; + int *tracepoint_provider_ref; }; #endif /* _LTTNG_TRACEPOINT_TYPES_H */ diff --git a/include/lttng/tracepoint.h b/include/lttng/tracepoint.h index fa39b272..887c9dee 100644 --- a/include/lttng/tracepoint.h +++ b/include/lttng/tracepoint.h @@ -152,18 +152,35 @@ extern int __tracepoint_probe_unregister(const char *name, void *func, void *dat #ifdef TRACEPOINT_DEFINE +/* + * When TRACEPOINT_PROBE_DYNAMIC_LINKAGE is defined, we do not emit a + * unresolved symbol that requires the provider to be linked in. When + * TRACEPOINT_PROBE_DYNAMIC_LINKAGE is not defined, we emit an + * unresolved symbol that depends on having the provider linked in, + * otherwise the linker complains. This deals with use of static + * libraries, ensuring that the linker does not remove the provider + * object from the executable. + */ +#ifdef TRACEPOINT_PROBE_DYNAMIC_LINKAGE +#define _TRACEPOINT_UNDEFINED_REF(provider) +#else /* TRACEPOINT_PROBE_DYNAMIC_LINKAGE */ +#define _TRACEPOINT_UNDEFINED_REF(provider) \ + &__tracepoint_provider_##provider, +#endif /* TRACEPOINT_PROBE_DYNAMIC_LINKAGE */ + /* * Note: to allow PIC code, we need to allow the linker to update the pointers * in the __tracepoints_ptrs section. * Therefore, this section is _not_ const (read-only). */ #define _DEFINE_TRACEPOINT(provider, name) \ + extern int __tracepoint_provider_##provider; \ static const char __tp_strtab_##provider##___##name[] \ __attribute__((section("__tracepoints_strings"))) = \ #provider ":" #name; \ struct tracepoint __tracepoint_##provider##___##name \ __attribute__((section("__tracepoints"))) = \ - { __tp_strtab_##provider##___##name, 0, NULL }; \ + { __tp_strtab_##provider##___##name, 0, NULL, _TRACEPOINT_UNDEFINED_REF(provider) }; \ static struct tracepoint * __tracepoint_ptr_##provider##___##name \ __attribute__((used, section("__tracepoints_ptrs"))) = \ &__tracepoint_##provider##___##name; diff --git a/include/lttng/ust-tracepoint-event.h b/include/lttng/ust-tracepoint-event.h index dbd04855..18aa4e44 100644 --- a/include/lttng/ust-tracepoint-event.h +++ b/include/lttng/ust-tracepoint-event.h @@ -514,11 +514,13 @@ static struct lttng_probe_desc _TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PR * Stage 9 of tracepoint event generation. * * Register/unregister probes at module load/unload. + * + * Generate the constructor as an externally visible symbol for use when + * linking the probe statically. */ /* Reset all macros within TRACEPOINT_EVENT */ #include - static void __attribute__((constructor)) _TP_COMBINE_TOKENS(__lttng_events_init__, TRACEPOINT_PROVIDER)(void) { @@ -533,3 +535,5 @@ _TP_COMBINE_TOKENS(__lttng_events_exit__, TRACEPOINT_PROVIDER)(void) { ltt_probe_unregister(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER)); } + +int _TP_COMBINE_TOKENS(__tracepoint_provider_, TRACEPOINT_PROVIDER); diff --git a/tests/demo/demo.c b/tests/demo/demo.c index 66a90607..e2b61c2e 100644 --- a/tests/demo/demo.c +++ b/tests/demo/demo.c @@ -30,6 +30,7 @@ #include #define TRACEPOINT_DEFINE +#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE #include "ust_tests_demo.h" #include "ust_tests_demo2.h" #include "ust_tests_demo3.h" -- 2.34.1