X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=include%2Flttng%2Ftracepoint.h;h=bcab5e2d7b0fa3c2ac0efb71b2c4f2ed3a68f2fe;hb=c0c0989ab70574e09b2f7e8b48c2da6af664a849;hp=e88db89242750c591909fb56ae912eb6cc670ff3;hpb=afeea86ff5c59e77ccd0684e8685220da963ad21;p=lttng-ust.git diff --git a/include/lttng/tracepoint.h b/include/lttng/tracepoint.h index e88db892..bcab5e2d 100644 --- a/include/lttng/tracepoint.h +++ b/include/lttng/tracepoint.h @@ -1,28 +1,12 @@ -#ifndef _LTTNG_TRACEPOINT_H -#define _LTTNG_TRACEPOINT_H - /* - * Copyright 2011-2012 - Mathieu Desnoyers - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * SPDX-License-Identifier: MIT + * + * Copyright (C) 2011-2012 Mathieu Desnoyers */ +#ifndef _LTTNG_TRACEPOINT_H +#define _LTTNG_TRACEPOINT_H + #include #include #include @@ -35,9 +19,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 @@ -165,12 +164,12 @@ void __tracepoint_cb_##_provider##___##_name(_TP_ARGS_PROTO(__VA_ARGS__)); \ static \ void __tracepoint_cb_##_provider##___##_name(_TP_ARGS_PROTO(__VA_ARGS__)) \ { \ - struct lttng_ust_tracepoint_probe *__tp_probe; \ + struct lttng_ust_tracepoint_probe *__tp_probe; \ \ if (caa_unlikely(!TP_RCU_LINK_TEST())) \ return; \ - tp_rcu_read_lock_bp(); \ - __tp_probe = tp_rcu_dereference_bp(__tracepoint_##_provider##___##_name.probes); \ + tp_rcu_read_lock(); \ + __tp_probe = tp_rcu_dereference(__tracepoint_##_provider##___##_name.probes); \ if (caa_unlikely(!__tp_probe)) \ goto end; \ do { \ @@ -181,7 +180,7 @@ void __tracepoint_cb_##_provider##___##_name(_TP_ARGS_PROTO(__VA_ARGS__)) \ (_TP_ARGS_DATA_VAR(__VA_ARGS__)); \ } while ((++__tp_probe)->func); \ end: \ - tp_rcu_read_unlock_bp(); \ + tp_rcu_read_unlock(); \ } \ static inline lttng_ust_notrace \ void __tracepoint_register_##_provider##___##_name(char *name, \ @@ -218,16 +217,13 @@ struct lttng_ust_tracepoint_dlopen { int (*tracepoint_register_lib)(struct lttng_ust_tracepoint * const *tracepoints_start, int tracepoints_count); int (*tracepoint_unregister_lib)(struct lttng_ust_tracepoint * const *tracepoints_start); -#ifndef _LGPL_SOURCE - void (*rcu_read_lock_sym_bp)(void); - void (*rcu_read_unlock_sym_bp)(void); - void *(*rcu_dereference_sym_bp)(void *p); -#endif + void (*rcu_read_lock_sym)(void); + void (*rcu_read_unlock_sym)(void); + void *(*rcu_dereference_sym)(void *p); }; extern struct lttng_ust_tracepoint_dlopen tracepoint_dlopen; - -#if defined(TRACEPOINT_DEFINE) || defined(TRACEPOINT_CREATE_PROBES) +extern struct lttng_ust_tracepoint_dlopen *tracepoint_dlopen_ptr; /* * These weak symbols, the constructor, and destructor take care of @@ -240,6 +236,47 @@ int __tracepoint_ptrs_registered __attribute__((weak, visibility("hidden"))); struct lttng_ust_tracepoint_dlopen tracepoint_dlopen __attribute__((weak, visibility("hidden"))); +/* + * Deal with gcc O1 optimisation issues with weak hidden symbols. gcc + * 4.8 and prior does not have the same behavior for symbol scoping on + * 32-bit powerpc depending on the object size: symbols for objects of 8 + * bytes or less have the same address throughout a module, whereas they + * have different addresses between compile units for objects larger + * than 8 bytes. Add this pointer indirection to ensure that the symbol + * scoping match that of the other weak hidden symbols found in this + * header. + */ +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 { + 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(); +} #ifndef _LGPL_SOURCE static inline void lttng_ust_notrace @@ -247,25 +284,27 @@ __tracepoint__init_urcu_sym(void); static inline void __tracepoint__init_urcu_sym(void) { + if (!tracepoint_dlopen_ptr) + tracepoint_dlopen_ptr = &tracepoint_dlopen; /* * Symbols below are needed by tracepoint call sites and probe * providers. */ - if (!tracepoint_dlopen.rcu_read_lock_sym_bp) - tracepoint_dlopen.rcu_read_lock_sym_bp = + if (!tracepoint_dlopen_ptr->rcu_read_lock_sym) + tracepoint_dlopen_ptr->rcu_read_lock_sym = URCU_FORCE_CAST(void (*)(void), - dlsym(tracepoint_dlopen.liblttngust_handle, - "tp_rcu_read_lock_bp")); - if (!tracepoint_dlopen.rcu_read_unlock_sym_bp) - tracepoint_dlopen.rcu_read_unlock_sym_bp = + dlsym(tracepoint_dlopen_ptr->liblttngust_handle, + "tp_rcu_read_lock")); + if (!tracepoint_dlopen_ptr->rcu_read_unlock_sym) + tracepoint_dlopen_ptr->rcu_read_unlock_sym = URCU_FORCE_CAST(void (*)(void), - dlsym(tracepoint_dlopen.liblttngust_handle, - "tp_rcu_read_unlock_bp")); - if (!tracepoint_dlopen.rcu_dereference_sym_bp) - tracepoint_dlopen.rcu_dereference_sym_bp = + dlsym(tracepoint_dlopen_ptr->liblttngust_handle, + "tp_rcu_read_unlock")); + if (!tracepoint_dlopen_ptr->rcu_dereference_sym) + tracepoint_dlopen_ptr->rcu_dereference_sym = URCU_FORCE_CAST(void *(*)(void *p), - dlsym(tracepoint_dlopen.liblttngust_handle, - "tp_rcu_dereference_sym_bp")); + dlsym(tracepoint_dlopen_ptr->liblttngust_handle, + "tp_rcu_dereference_sym")); } #else static inline void lttng_ust_notrace @@ -281,13 +320,19 @@ __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.liblttngust_handle) - tracepoint_dlopen.liblttngust_handle = - dlopen("liblttng-ust-tracepoint.so.0", RTLD_NOW | RTLD_GLOBAL); - if (!tracepoint_dlopen.liblttngust_handle) + if (!tracepoint_dlopen_ptr) + tracepoint_dlopen_ptr = &tracepoint_dlopen; + if (!tracepoint_dlopen_ptr->liblttngust_handle) + tracepoint_dlopen_ptr->liblttngust_handle = + dlopen("liblttng-ust-tracepoint.so.1", RTLD_NOW | RTLD_GLOBAL); + if (!tracepoint_dlopen_ptr->liblttngust_handle) return; __tracepoint__init_urcu_sym(); } @@ -301,18 +346,34 @@ __tracepoints__destroy(void) if (--__tracepoint_registered) return; - if (tracepoint_dlopen.liblttngust_handle && !__tracepoint_ptrs_registered) { - ret = dlclose(tracepoint_dlopen.liblttngust_handle); - if (ret) { - fprintf(stderr, "Error (%d) in dlclose\n", ret); - abort(); - } - memset(&tracepoint_dlopen, 0, sizeof(tracepoint_dlopen)); + 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) + 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; } + 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)); } -#endif - #ifdef TRACEPOINT_DEFINE /* @@ -364,7 +425,8 @@ 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)) @@ -374,22 +436,34 @@ __tracepoints__ptrs_init(void) { if (__tracepoint_ptrs_registered++) return; - if (!tracepoint_dlopen.liblttngust_handle) - tracepoint_dlopen.liblttngust_handle = - dlopen("liblttng-ust-tracepoint.so.0", RTLD_NOW | RTLD_GLOBAL); - if (!tracepoint_dlopen.liblttngust_handle) + if (!tracepoint_dlopen_ptr) + tracepoint_dlopen_ptr = &tracepoint_dlopen; + if (!tracepoint_dlopen_ptr->liblttngust_handle) + tracepoint_dlopen_ptr->liblttngust_handle = + dlopen("liblttng-ust-tracepoint.so.1", RTLD_NOW | RTLD_GLOBAL); + if (!tracepoint_dlopen_ptr->liblttngust_handle) return; - tracepoint_dlopen.tracepoint_register_lib = + 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.liblttngust_handle, + dlsym(tracepoint_dlopen_ptr->liblttngust_handle, "tracepoint_register_lib")); - tracepoint_dlopen.tracepoint_unregister_lib = + tracepoint_dlopen_ptr->tracepoint_unregister_lib = URCU_FORCE_CAST(int (*)(struct lttng_ust_tracepoint * const *), - dlsym(tracepoint_dlopen.liblttngust_handle, + dlsym(tracepoint_dlopen_ptr->liblttngust_handle, "tracepoint_unregister_lib")); + 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.tracepoint_register_lib) { - tracepoint_dlopen.tracepoint_register_lib(__start___tracepoints_ptrs, + if (tracepoint_dlopen_ptr->tracepoint_register_lib) { + tracepoint_dlopen_ptr->tracepoint_register_lib(__start___tracepoints_ptrs, __stop___tracepoints_ptrs - __start___tracepoints_ptrs); } @@ -404,15 +478,22 @@ __tracepoints__ptrs_destroy(void) if (--__tracepoint_ptrs_registered) return; - if (tracepoint_dlopen.tracepoint_unregister_lib) - tracepoint_dlopen.tracepoint_unregister_lib(__start___tracepoints_ptrs); - if (tracepoint_dlopen.liblttngust_handle && !__tracepoint_registered) { - ret = dlclose(tracepoint_dlopen.liblttngust_handle); + 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 (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) { fprintf(stderr, "Error (%d) in dlclose\n", ret); abort(); } - memset(&tracepoint_dlopen, 0, sizeof(tracepoint_dlopen)); + memset(tracepoint_dlopen_ptr, 0, sizeof(*tracepoint_dlopen_ptr)); } } @@ -430,13 +511,57 @@ __tracepoints__ptrs_destroy(void) /* The following declarations must be outside re-inclusion protection. */ +#ifndef TRACEPOINT_ENUM + +/* + * Tracepoint Enumerations + * + * The enumeration is a mapping between an integer, or range of integers, and + * a string. It can be used to have a more compact trace in cases where the + * possible values for a field are limited: + * + * An example: + * + * TRACEPOINT_ENUM(someproject_component, enumname, + * TP_ENUM_VALUES( + * ctf_enum_value("even", 0) + * ctf_enum_value("uneven", 1) + * ctf_enum_range("twoto4", 2, 4) + * ctf_enum_value("five", 5) + * ) + * ) + * + * Where "someproject_component" is the name of the component this enumeration + * belongs to and "enumname" identifies this enumeration. Inside the + * TP_ENUM_VALUES macro is the actual mapping. Each string value can map + * to either a single value with ctf_enum_value or a range of values + * with ctf_enum_range. + * + * Enumeration ranges may overlap, but the behavior is implementation-defined, + * each trace reader will handle overlapping as it wishes. + * + * That enumeration can then be used in a field inside the TP_FIELD macro using + * the following line: + * + * ctf_enum(someproject_component, enumname, enumtype, enumfield, enumval) + * + * Where "someproject_component" and "enumname" match those in the + * TRACEPOINT_ENUM, "enumtype" is a signed or unsigned integer type + * backing the enumeration, "enumfield" is the name of the field and + * "enumval" is the value. + */ + +#define TRACEPOINT_ENUM(provider, name, values) + +#endif /* #ifndef TRACEPOINT_ENUM */ + #ifndef TRACEPOINT_EVENT /* * 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 * @@ -447,20 +572,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) * - * * Array Sequence, printed as UTF8-encoded array of bytes * + * * Enumeration * + * ctf_enum(someproject_component, enum_name, int, field_e, arg0) + * + * * 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) * )