X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=include%2Flttng%2Ftracepoint.h;h=8886e900a0511738895b1c9048e294dc6fc26f55;hb=780fc9ad99d9fe9c460886a40f724f333fd88148;hp=a73056030d0be4c3dc12b06035bf18191d649f95;hpb=32855a09dc8925f578624cab645a33ecb139389c;p=lttng-ust.git diff --git a/include/lttng/tracepoint.h b/include/lttng/tracepoint.h index a7305603..8886e900 100644 --- a/include/lttng/tracepoint.h +++ b/include/lttng/tracepoint.h @@ -35,9 +35,24 @@ #include #ifdef LTTNG_UST_HAVE_SDT_INTEGRATION -#define SDT_USE_VARIADIC +/* + * Instead of using SDT_USE_VARIADIC from 'sys/sdt.h', use our own namespaced + * macros since the instrumented application might already have included + * 'sys/sdt.h' without variadic support. + */ #include -#define LTTNG_STAP_PROBEV STAP_PROBEV + +#define _LTTNG_SDT_NARG(...) \ + __LTTNG_SDT_NARG(__VA_ARGS__, 12,11,10,9,8,7,6,5,4,3,2,1,0) + +#define __LTTNG_SDT_NARG(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12, N, ...) N + +#define _LTTNG_SDT_PROBE_N(provider, name, N, ...) \ + _SDT_PROBE(provider, name, N, (__VA_ARGS__)) + +#define LTTNG_STAP_PROBEV(provider, name, ...) \ + _LTTNG_SDT_PROBE_N(provider, name, _LTTNG_SDT_NARG(0, ##__VA_ARGS__), ##__VA_ARGS__) + #else #define LTTNG_STAP_PROBEV(...) #endif @@ -226,23 +241,6 @@ struct lttng_ust_tracepoint_dlopen { extern struct lttng_ust_tracepoint_dlopen tracepoint_dlopen; extern struct lttng_ust_tracepoint_dlopen *tracepoint_dlopen_ptr; -/* Disable tracepoint destructors. */ -int __tracepoints__disable_destructors __attribute__((weak)); - -/* - * Programs that have threads that survive after they exit, and - * therefore call library destructors, should disable the tracepoint - * destructors by calling tracepoint_disable_destructors(). This will - * leak the tracepoint instrumentation library shared object, leaving - * its teardown to the operating system process teardown. - */ -static inline void tracepoint_disable_destructors(void) -{ - __tracepoints__disable_destructors = 1; -} - -#if defined(TRACEPOINT_DEFINE) || defined(TRACEPOINT_CREATE_PROBES) - /* * These weak symbols, the constructor, and destructor take care of * registering only _one_ instance of the tracepoints per shared-ojbect @@ -267,6 +265,37 @@ struct lttng_ust_tracepoint_dlopen tracepoint_dlopen struct lttng_ust_tracepoint_dlopen *tracepoint_dlopen_ptr __attribute__((weak, visibility("hidden"))); +/* + * Tracepoint dynamic linkage handling (callbacks). Hidden visibility: shared + * across objects in a module/main executable. The callbacks are used to + * control and check if the destructors should be executed. + */ +struct lttng_ust_tracepoint_destructors_syms { + int *old_tracepoint_disable_destructors; + void (*tracepoint_disable_destructors)(void); + int (*tracepoint_get_destructors_state)(void); +}; + +extern struct lttng_ust_tracepoint_destructors_syms tracepoint_destructors_syms; +extern struct lttng_ust_tracepoint_destructors_syms *tracepoint_destructors_syms_ptr; + +struct lttng_ust_tracepoint_destructors_syms tracepoint_destructors_syms + __attribute__((weak, visibility("hidden"))); +struct lttng_ust_tracepoint_destructors_syms *tracepoint_destructors_syms_ptr + __attribute__((weak, visibility("hidden"))); + +static inline void tracepoint_disable_destructors(void) +{ + if (!tracepoint_dlopen_ptr) + tracepoint_dlopen_ptr = &tracepoint_dlopen; + if (!tracepoint_destructors_syms_ptr) + tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms; + if (tracepoint_dlopen_ptr->liblttngust_handle + && tracepoint_destructors_syms_ptr->tracepoint_disable_destructors) + tracepoint_destructors_syms_ptr->tracepoint_disable_destructors(); + *tracepoint_destructors_syms_ptr->old_tracepoint_disable_destructors = 1; +} + #ifndef _LGPL_SOURCE static inline void lttng_ust_notrace __tracepoint__init_urcu_sym(void); @@ -304,13 +333,17 @@ __tracepoint__init_urcu_sym(void) } #endif -static void lttng_ust_notrace __attribute__((constructor)) +static void lttng_ust_notrace __attribute__((constructor(LTTNG_UST_CONSTRUCTOR_PRIO))) __tracepoints__init(void); static void __tracepoints__init(void) { - if (__tracepoint_registered++) + if (__tracepoint_registered++) { + if (!tracepoint_dlopen_ptr->liblttngust_handle) + return; + __tracepoint__init_urcu_sym(); return; + } if (!tracepoint_dlopen_ptr) tracepoint_dlopen_ptr = &tracepoint_dlopen; @@ -322,7 +355,7 @@ __tracepoints__init(void) __tracepoint__init_urcu_sym(); } -static void lttng_ust_notrace __attribute__((destructor)) +static void lttng_ust_notrace __attribute__((destructor(LTTNG_UST_CONSTRUCTOR_PRIO))) __tracepoints__destroy(void); static void __tracepoints__destroy(void) @@ -333,22 +366,62 @@ __tracepoints__destroy(void) return; if (!tracepoint_dlopen_ptr) tracepoint_dlopen_ptr = &tracepoint_dlopen; - if (!__tracepoints__disable_destructors - && tracepoint_dlopen_ptr->liblttngust_handle - && !__tracepoint_ptrs_registered) { - ret = dlclose(tracepoint_dlopen_ptr->liblttngust_handle); - if (ret) { - fprintf(stderr, "Error (%d) in dlclose\n", ret); - abort(); - } - memset(tracepoint_dlopen_ptr, 0, sizeof(*tracepoint_dlopen_ptr)); + if (!tracepoint_destructors_syms_ptr) + tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms; + if (!tracepoint_dlopen_ptr->liblttngust_handle) + return; + if (__tracepoint_ptrs_registered) + return; + /* + * Lookup if destructors must be executed using the new method. + */ + if (tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state + && !tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state()) { + /* + * The tracepoint_get_destructors_state symbol was found with + * dlsym but its returned value is 0 meaning that destructors + * must not be executed. + */ + return; + } + /* + * Lookup if destructors must be executed using the old method. + */ + if (tracepoint_destructors_syms_ptr->old_tracepoint_disable_destructors + && *tracepoint_destructors_syms_ptr->old_tracepoint_disable_destructors) { + /* + * The old_tracepoint_disable_destructors symbol was found with + * dlsym but its value is 1 meaning that destructors must not + * be executed. + */ + return; + } + + ret = dlclose(tracepoint_dlopen_ptr->liblttngust_handle); + if (ret) { + fprintf(stderr, "Error (%d) in dlclose\n", ret); + abort(); } + memset(tracepoint_dlopen_ptr, 0, sizeof(*tracepoint_dlopen_ptr)); } +#ifdef __cplusplus +} #endif +#endif /* _LTTNG_TRACEPOINT_H */ + +/* The following declarations must be outside re-inclusion protection. */ + #ifdef TRACEPOINT_DEFINE +#ifndef _LTTNG_UST_TRACEPOINT_DEFINE_ONCE +#define _LTTNG_UST_TRACEPOINT_DEFINE_ONCE + +#ifdef __cplusplus +extern "C" { +#endif + /* * These weak symbols, the constructor, and destructor take care of * registering only _one_ instance of the tracepoints per shared-ojbect @@ -381,6 +454,7 @@ extern struct lttng_ust_tracepoint * const __stop___tracepoints_ptrs[] */ #define _TP_EXTRACT_STRING(...) #__VA_ARGS__ +#undef _DEFINE_TRACEPOINT #define _DEFINE_TRACEPOINT(_provider, _name, _args) \ extern int __tracepoint_provider_##_provider; \ static const char __tp_strtab_##_provider##___##_name[] \ @@ -398,10 +472,11 @@ extern struct lttng_ust_tracepoint * const __stop___tracepoints_ptrs[] }; \ static struct lttng_ust_tracepoint * \ __tracepoint_ptr_##_provider##___##_name \ - __attribute__((used, section("__tracepoints_ptrs"))) = \ + __attribute__((section("__tracepoints_ptrs"), used)) \ + __lttng_ust_variable_attribute_no_sanitize_address = \ &__tracepoint_##_provider##___##_name; -static void lttng_ust_notrace __attribute__((constructor)) +static void lttng_ust_notrace __attribute__((constructor(LTTNG_UST_CONSTRUCTOR_PRIO))) __tracepoints__ptrs_init(void); static void __tracepoints__ptrs_init(void) @@ -415,6 +490,8 @@ __tracepoints__ptrs_init(void) dlopen("liblttng-ust-tracepoint.so.0", RTLD_NOW | RTLD_GLOBAL); if (!tracepoint_dlopen_ptr->liblttngust_handle) return; + if (!tracepoint_destructors_syms_ptr) + tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms; tracepoint_dlopen_ptr->tracepoint_register_lib = URCU_FORCE_CAST(int (*)(struct lttng_ust_tracepoint * const *, int), dlsym(tracepoint_dlopen_ptr->liblttngust_handle, @@ -423,6 +500,18 @@ __tracepoints__ptrs_init(void) URCU_FORCE_CAST(int (*)(struct lttng_ust_tracepoint * const *), dlsym(tracepoint_dlopen_ptr->liblttngust_handle, "tracepoint_unregister_lib")); + tracepoint_destructors_syms_ptr->old_tracepoint_disable_destructors = + URCU_FORCE_CAST(int *, + dlsym(tracepoint_dlopen_ptr->liblttngust_handle, + "__tracepoints__disable_destructors")); + tracepoint_destructors_syms_ptr->tracepoint_disable_destructors = + URCU_FORCE_CAST(void (*)(void), + dlsym(tracepoint_dlopen_ptr->liblttngust_handle, + "tp_disable_destructors")); + tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state = + URCU_FORCE_CAST(int (*)(void), + dlsym(tracepoint_dlopen_ptr->liblttngust_handle, + "tp_get_destructors_state")); __tracepoint__init_urcu_sym(); if (tracepoint_dlopen_ptr->tracepoint_register_lib) { tracepoint_dlopen_ptr->tracepoint_register_lib(__start___tracepoints_ptrs, @@ -431,7 +520,7 @@ __tracepoints__ptrs_init(void) } } -static void lttng_ust_notrace __attribute__((destructor)) +static void lttng_ust_notrace __attribute__((destructor(LTTNG_UST_CONSTRUCTOR_PRIO))) __tracepoints__ptrs_destroy(void); static void __tracepoints__ptrs_destroy(void) @@ -442,10 +531,13 @@ __tracepoints__ptrs_destroy(void) return; if (!tracepoint_dlopen_ptr) tracepoint_dlopen_ptr = &tracepoint_dlopen; + if (!tracepoint_destructors_syms_ptr) + tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms; if (tracepoint_dlopen_ptr->tracepoint_unregister_lib) tracepoint_dlopen_ptr->tracepoint_unregister_lib(__start___tracepoints_ptrs); - if (!__tracepoints__disable_destructors - && tracepoint_dlopen_ptr->liblttngust_handle + if (tracepoint_dlopen_ptr->liblttngust_handle + && tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state + && tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state() && !__tracepoint_ptrs_registered) { ret = dlclose(tracepoint_dlopen_ptr->liblttngust_handle); if (ret) { @@ -456,19 +548,18 @@ __tracepoints__ptrs_destroy(void) } } -#else /* TRACEPOINT_DEFINE */ - -#define _DEFINE_TRACEPOINT(_provider, _name, _args) - -#endif /* #else TRACEPOINT_DEFINE */ - #ifdef __cplusplus } #endif -#endif /* _LTTNG_TRACEPOINT_H */ +#endif /* _LTTNG_UST_TRACEPOINT_DEFINE_ONCE */ -/* The following declarations must be outside re-inclusion protection. */ +#else /* TRACEPOINT_DEFINE */ + +#undef _DEFINE_TRACEPOINT +#define _DEFINE_TRACEPOINT(_provider, _name, _args) + +#endif /* #else TRACEPOINT_DEFINE */ #ifndef TRACEPOINT_ENUM @@ -520,7 +611,7 @@ __tracepoints__ptrs_destroy(void) * How to use the TRACEPOINT_EVENT macro: * * An example: - * + * * TRACEPOINT_EVENT(someproject_component, event_name, * * * TP_ARGS takes from 0 to 10 "type, field_name" pairs * @@ -531,23 +622,23 @@ __tracepoints__ptrs_destroy(void) * * TP_FIELDS describes the event payload layout in the trace * * * TP_FIELDS( - * * Integer, printed in base 10 * + * * Integer, printed in base 10 * * ctf_integer(int, field_a, arg0) * - * * Integer, printed with 0x base 16 * + * * Integer, printed with 0x base 16 * * ctf_integer_hex(unsigned long, field_d, arg1) * * * Enumeration * * ctf_enum(someproject_component, enum_name, int, field_e, arg0) * - * * Array Sequence, printed as UTF8-encoded array of bytes * + * * Array Sequence, printed as UTF8-encoded array of bytes * * ctf_array_text(char, field_b, string, FIXED_LEN) * ctf_sequence_text(char, field_c, string, size_t, strlen) * - * * String, printed as UTF8-encoded string * + * * String, printed as UTF8-encoded string * * ctf_string(field_e, string) * - * * Array sequence of signed integer values * + * * Array sequence of signed integer values * * ctf_array(long, field_f, arg4, FIXED_LEN4) * ctf_sequence(long, field_g, arg4, size_t, arg4_len) * )