#include <lttng/ringbuffer-config.h>
#include <lttng/ust-compiler.h>
#include <lttng/tracepoint.h>
+#include <byteswap.h>
#include <string.h>
#undef tp_list_for_each_entry_rcu
/* Reset all macros within TRACEPOINT_EVENT */
#include <lttng/ust-tracepoint-event-reset.h>
+static inline lttng_ust_notrace
+void _TP_COMBINE_TOKENS(__tracepoint_provider_mismatch_, TRACEPOINT_PROVIDER)(void);
static inline
void _TP_COMBINE_TOKENS(__tracepoint_provider_mismatch_, TRACEPOINT_PROVIDER)(void)
{
#define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \
__tracepoint_provider_mismatch_##_provider();
+static inline lttng_ust_notrace
+void _TP_COMBINE_TOKENS(__tracepoint_provider_check_, TRACEPOINT_PROVIDER)(void);
static inline
void _TP_COMBINE_TOKENS(__tracepoint_provider_check_, TRACEPOINT_PROVIDER)(void)
{
},
#undef _ctf_sequence_encoded
-#define _ctf_sequence_encoded(_type, _item, _src, \
- _length_type, _src_length, _encoding, _nowrite) \
+#define _ctf_sequence_encoded(_type, _item, _src, \
+ _length_type, _src_length, _encoding, _nowrite, \
+ _elem_type_base) \
{ \
.name = #_item, \
.type = \
.sequence = \
{ \
.length_type = __type_integer(_length_type, BYTE_ORDER, 10, none), \
- .elem_type = __type_integer(_type, BYTE_ORDER, 10, _encoding), \
+ .elem_type = __type_integer(_type, BYTE_ORDER, _elem_type_base, _encoding), \
}, \
}, \
}, \
#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \
static const struct lttng_event_field __event_fields___##_provider##___##_name[] = { \
_fields \
+ ctf_integer(int, dummy, 0) /* Dummy, C99 forbids 0-len array. */ \
};
#include TRACEPOINT_INCLUDE
__event_len += sizeof(_type) * (_length);
#undef _ctf_sequence_encoded
-#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \
- _src_length, _encoding, _nowrite) \
+#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \
+ _src_length, _encoding, _nowrite, _elem_type_base) \
__event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_length_type)); \
__event_len += sizeof(_length_type); \
__event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \
case 2: \
{ \
union { _type t; int16_t v; } __tmp = { (_type) (_src) }; \
+ if (_byte_order != BYTE_ORDER) \
+ __tmp.v = bswap_16(__tmp.v); \
__ctf_tmp_int64 = (int64_t) __tmp.v; \
break; \
} \
case 4: \
{ \
union { _type t; int32_t v; } __tmp = { (_type) (_src) }; \
+ if (_byte_order != BYTE_ORDER) \
+ __tmp.v = bswap_32(__tmp.v); \
__ctf_tmp_int64 = (int64_t) __tmp.v; \
break; \
} \
case 8: \
{ \
union { _type t; int64_t v; } __tmp = { (_type) (_src) }; \
+ if (_byte_order != BYTE_ORDER) \
+ __tmp.v = bswap_64(__tmp.v); \
__ctf_tmp_int64 = (int64_t) __tmp.v; \
break; \
} \
case 2: \
{ \
union { _type t; uint16_t v; } __tmp = { (_type) (_src) }; \
+ if (_byte_order != BYTE_ORDER) \
+ __tmp.v = bswap_16(__tmp.v); \
__ctf_tmp_uint64 = (uint64_t) __tmp.v; \
break; \
} \
case 4: \
{ \
union { _type t; uint32_t v; } __tmp = { (_type) (_src) }; \
+ if (_byte_order != BYTE_ORDER) \
+ __tmp.v = bswap_32(__tmp.v); \
__ctf_tmp_uint64 = (uint64_t) __tmp.v; \
break; \
} \
case 8: \
{ \
union { _type t; uint64_t v; } __tmp = { (_type) (_src) }; \
+ if (_byte_order != BYTE_ORDER) \
+ __tmp.v = bswap_64(__tmp.v); \
__ctf_tmp_uint64 = (uint64_t) __tmp.v; \
break; \
} \
const void *__ctf_tmp_ptr = (_src); \
memcpy(__stack_data, &__ctf_tmp_ulong, sizeof(unsigned long)); \
__stack_data += sizeof(unsigned long); \
- memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void **)); \
- __stack_data += sizeof(void **); \
+ memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void *)); \
+ __stack_data += sizeof(void *); \
}
#undef _ctf_sequence_encoded
#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \
- _src_length, _encoding, _nowrite) \
+ _src_length, _encoding, _nowrite, _elem_type_base) \
{ \
unsigned long __ctf_tmp_ulong = (unsigned long) (_src_length); \
const void *__ctf_tmp_ptr = (_src); \
memcpy(__stack_data, &__ctf_tmp_ulong, sizeof(unsigned long)); \
__stack_data += sizeof(unsigned long); \
- memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void **)); \
- __stack_data += sizeof(void **); \
+ memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void *)); \
+ __stack_data += sizeof(void *); \
}
#undef _ctf_string
#define _ctf_string(_item, _src, _nowrite) \
{ \
const void *__ctf_tmp_ptr = (_src); \
- memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void **)); \
- __stack_data += sizeof(void **); \
+ memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void *)); \
+ __stack_data += sizeof(void *); \
}
#undef TP_ARGS
__event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_type));
#undef _ctf_sequence_encoded
-#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \
- _src_length, _encoding, _nowrite) \
+#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \
+ _src_length, _encoding, _nowrite, _elem_type_base) \
__event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_length_type)); \
__event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_type));
#undef _ctf_sequence_encoded
#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \
- _src_length, _encoding, _nowrite) \
+ _src_length, _encoding, _nowrite, _elem_type_base) \
{ \
_length_type __tmpl = __stackvar.__dynamic_len[__dynamic_len_idx]; \
lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_length_type));\
__chan->ops->event_write(&__ctx, _src, \
sizeof(_type) * __get_dynamic_len(dest));
+/*
+ * __chan->ops->u.has_strcpy is a flag letting us know if the LTTng-UST
+ * tracepoint provider ABI implements event_strcpy. This dynamic check
+ * can be removed when the tracepoint provider ABI moves to 2.
+ */
+#if (LTTNG_UST_PROVIDER_MAJOR > 1)
+#error "Tracepoint probe provider major version has changed. Please remove dynamic check for has_strcpy."
+#endif
+
#undef _ctf_string
#define _ctf_string(_item, _src, _nowrite) \
lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(*(_src))); \
- __chan->ops->event_write(&__ctx, _src, __get_dynamic_len(dest));
+ if (__chan->ops->u.has_strcpy) \
+ __chan->ops->event_strcpy(&__ctx, _src, \
+ __get_dynamic_len(dest)); \
+ else \
+ __chan->ops->event_write(&__ctx, _src, \
+ __get_dynamic_len(dest));
/* Beware: this get len actually consumes the len value */
#undef __get_dynamic_len
#define _TP_SESSION_CHECK(session, csession) 1
#endif /* TP_SESSION_CHECK */
+/*
+ * Use of __builtin_return_address(0) sometimes seems to cause stack
+ * corruption on 32-bit PowerPC. Disable this feature on that
+ * architecture for now by always using the NULL value for the ip
+ * context.
+ */
+#undef _TP_IP_PARAM
+#ifdef TP_IP_PARAM
+#define _TP_IP_PARAM(x) (x)
+#else /* TP_IP_PARAM */
+
+#if defined(__PPC__) && !defined(__PPC64__)
+#define _TP_IP_PARAM(x) NULL
+#else /* #if defined(__PPC__) && !defined(__PPC64__) */
+#define _TP_IP_PARAM(x) __builtin_return_address(0)
+#endif /* #else #if defined(__PPC__) && !defined(__PPC64__) */
+
+#endif /* TP_IP_PARAM */
+
/*
* Using twice size for filter stack data to hold size and pointer for
* each field (worse case). For integers, max size required is 64-bit.
size_t __event_len, __event_align; \
size_t __dynamic_len_idx = 0; \
union { \
- size_t __dynamic_len[_TP_ARRAY_SIZE(__event_fields___##_provider##___##_name)]; \
- char __filter_stack_data[2 * sizeof(unsigned long) * _TP_ARRAY_SIZE(__event_fields___##_provider##___##_name)]; \
+ size_t __dynamic_len[_TP_ARRAY_SIZE(__event_fields___##_provider##___##_name) - 1]; \
+ char __filter_stack_data[2 * sizeof(unsigned long) * (_TP_ARRAY_SIZE(__event_fields___##_provider##___##_name) - 1)]; \
} __stackvar; \
int __ret; \
\
__event_align = __event_get_align__##_provider##___##_name(_TP_ARGS_VAR(_args)); \
lib_ring_buffer_ctx_init(&__ctx, __chan->chan, __event, __event_len, \
__event_align, -1, __chan->handle); \
- __ctx.ip = __builtin_return_address(0); \
+ __ctx.ip = _TP_IP_PARAM(TP_IP_PARAM); \
__ret = __chan->ops->event_reserve(&__ctx, __event->id); \
if (__ret < 0) \
return; \
/* Reset all macros within TRACEPOINT_EVENT */
#include <lttng/ust-tracepoint-event-reset.h>
+/*
+ * Declare _loglevel___##__provider##___##__name as non-static, with
+ * hidden visibility for c++ handling of weakref. We do a weakref to the
+ * symbol in a later stage, which requires that the symbol is not
+ * mangled.
+ */
+#ifdef __cplusplus
+#define LTTNG_TP_EXTERN_C extern "C"
+#else
+#define LTTNG_TP_EXTERN_C
+#endif
+
#undef TRACEPOINT_LOGLEVEL
#define TRACEPOINT_LOGLEVEL(__provider, __name, __loglevel) \
static const int _loglevel_value___##__provider##___##__name = __loglevel; \
-static const int *_loglevel___##__provider##___##__name = \
+LTTNG_TP_EXTERN_C const int *_loglevel___##__provider##___##__name \
+ __attribute__((visibility("hidden"))) = \
&_loglevel_value___##__provider##___##__name;
#include TRACEPOINT_INCLUDE
+#ifdef __cplusplus
+#undef LTTNG_TP_EXTERN_C
+#endif
+
/*
* Stage 6.1 of tracepoint event generation.
*
/* Reset all macros within TRACEPOINT_EVENT */
#include <lttng/ust-tracepoint-event-reset.h>
+/*
+ * Declare _model_emf_uri___##__provider##___##__name as non-static,
+ * with hidden visibility for c++ handling of weakref. We do a weakref
+ * to the symbol in a later stage, which requires that the symbol is not
+ * mangled.
+ */
+#ifdef __cplusplus
+#define LTTNG_TP_EXTERN_C extern "C"
+#else
+#define LTTNG_TP_EXTERN_C
+#endif
+
#undef TRACEPOINT_MODEL_EMF_URI
#define TRACEPOINT_MODEL_EMF_URI(__provider, __name, __uri) \
-static const char *_model_emf_uri___##__provider##___##__name = __uri;
+LTTNG_TP_EXTERN_C const char *_model_emf_uri___##__provider##___##__name \
+ __attribute__((visibility("hidden"))) = __uri \
#include TRACEPOINT_INCLUDE
+#ifdef __cplusplus
+#undef LTTNG_TP_EXTERN_C
+#endif
+
/*
* Stage 7.1 of tracepoint event generation.
*
.probe_callback = (void (*)(void)) &__event_probe__##_provider##___##_template,\
.ctx = NULL, \
.fields = __event_fields___##_provider##___##_template, \
- .nr_fields = _TP_ARRAY_SIZE(__event_fields___##_provider##___##_template), \
+ .nr_fields = _TP_ARRAY_SIZE(__event_fields___##_provider##___##_template) - 1, \
.loglevel = &__ref_loglevel___##_provider##___##_name, \
.signature = __tp_event_signature___##_provider##___##_template, \
.u = { .ext = { .model_emf_uri = &__ref_model_emf_uri___##_provider##___##_name } }, \
static const struct lttng_event_desc *_TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER)[] = {
#include TRACEPOINT_INCLUDE
+ NULL, /* Dummy, C99 forbids 0-len array. */
};
static struct lttng_probe_desc _TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER) = {
.provider = __tp_stringify(TRACEPOINT_PROVIDER),
.event_desc = _TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER),
- .nr_events = _TP_ARRAY_SIZE(_TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER)),
+ .nr_events = _TP_ARRAY_SIZE(_TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER)) - 1,
.head = { NULL, NULL },
.lazy_init_head = { NULL, NULL },
.lazy = 0,