#include "lttng-probe-user.h"
#include "../wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */
#include "../wrapper/ringbuffer/frontend_types.h"
+#include "../wrapper/ringbuffer/backend.h"
+#include "../wrapper/rcu.h"
#include "../lttng-events.h"
#include "../lttng-tracer-core.h"
+#include <asm/byteorder.h>
+#include <linux/swab.h>
+
+#define __LTTNG_NULL_STRING "(null)"
/*
* Macro declarations used for all stages.
#undef LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP_NOARGS
#define LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP_NOARGS(_template, _name, _map) \
-void trace_##_name(void *__data);
+void trace_##_name(void);
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+/*
+ * Stage 1.1 of the trace events.
+ *
+ * Create dummy trace prototypes for each event class, and for each used
+ * template. This will allow checking whether the prototypes from the
+ * class and the instance using the class actually match.
+ */
+
+#include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */
+
+#undef TP_PROTO
+#define TP_PROTO(...) __VA_ARGS__
+
+#undef TP_ARGS
+#define TP_ARGS(...) __VA_ARGS__
+
+#undef LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP
+#define LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(_template, _name, _map, _proto, _args) \
+void __event_template_proto___##_template(_proto);
+
+#undef LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP_NOARGS
+#define LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP_NOARGS(_template, _name, _map) \
+void __event_template_proto___##_template(void);
+
+#undef LTTNG_TRACEPOINT_EVENT_CLASS_CODE
+#define LTTNG_TRACEPOINT_EVENT_CLASS_CODE(_name, _proto, _args, _locvar, _code, _fields) \
+void __event_template_proto___##_name(_proto);
+
+#undef LTTNG_TRACEPOINT_EVENT_CLASS_CODE_NOARGS
+#define LTTNG_TRACEPOINT_EVENT_CLASS_CODE_NOARGS(_name, _locvar, _code, _fields) \
+void __event_template_proto___##_name(void);
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
#define _ctf_string(_item, _src, _user, _nowrite) \
if (_user) \
__event_len += __dynamic_len[__dynamic_len_idx++] = \
- strlen(_src) + 1; \
+ max_t(size_t, lttng_strlen_user_inatomic(_src), 1); \
else \
__event_len += __dynamic_len[__dynamic_len_idx++] = \
- max_t(size_t, lttng_strlen_user_inatomic(_src), 1);
+ strlen((_src) ? (_src) : __LTTNG_NULL_STRING) + 1;
#undef TP_PROTO
#define TP_PROTO(...) __VA_ARGS__
case 2: \
{ \
union { _type t; int16_t v; } __tmp = { (_type) (_src) }; \
+ if (_byte_order != __BYTE_ORDER) \
+ __swab16s(&__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) \
+ __swab32s(&__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) \
+ __swab64s(&__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) \
+ __swab16s(&__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) \
+ __swab32s(&__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) \
+ __swab64s(&__tmp.v); \
__ctf_tmp_uint64 = (uint64_t) __tmp.v; \
break; \
} \
#undef _ctf_integer_ext_isuser1
#define _ctf_integer_ext_isuser1(_type, _item, _user_src, _byte_order, _base, _nowrite) \
-{ \
- __typeof__(_user_src) _src; \
- if (get_user(_src, &(_user_src))) \
- _src = 0; \
- _ctf_integer_ext_fetched(_type, _item, _src, _byte_order, _base, _nowrite) \
+{ \
+ union { \
+ char __array[sizeof(_user_src)]; \
+ __typeof__(_user_src) __v; \
+ } __tmp_fetch; \
+ if (lib_ring_buffer_copy_from_user_check_nofault(__tmp_fetch.__array, \
+ &(_user_src), sizeof(_user_src))) \
+ memset(__tmp_fetch.__array, 0, sizeof(__tmp_fetch.__array)); \
+ _ctf_integer_ext_fetched(_type, _item, __tmp_fetch.__v, _byte_order, _base, _nowrite) \
}
#undef _ctf_integer_ext
#undef _ctf_string
#define _ctf_string(_item, _src, _user, _nowrite) \
{ \
- const void *__ctf_tmp_ptr = (_src); \
+ const void *__ctf_tmp_ptr = \
+ ((_src) ? (_src) : __LTTNG_NULL_STRING); \
memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void *)); \
__stack_data += sizeof(void *); \
}
#undef _ctf_integer_ext_isuser1
#define _ctf_integer_ext_isuser1(_type, _item, _user_src, _byte_order, _base, _nowrite) \
{ \
- __typeof__(_user_src) _src; \
- if (get_user(_src, &(_user_src))) \
- _src = 0; \
- _ctf_integer_ext_fetched(_type, _item, _src, _byte_order, _base, _nowrite) \
+ union { \
+ char __array[sizeof(_user_src)]; \
+ __typeof__(_user_src) __v; \
+ } __tmp_fetch; \
+ if (lib_ring_buffer_copy_from_user_check_nofault(__tmp_fetch.__array, \
+ &(_user_src), sizeof(_user_src))) \
+ memset(__tmp_fetch.__array, 0, sizeof(__tmp_fetch.__array)); \
+ _ctf_integer_ext_fetched(_type, _item, __tmp_fetch.__v, _byte_order, _base, _nowrite) \
}
#undef _ctf_integer_ext
#undef _ctf_string
#define _ctf_string(_item, _src, _user, _nowrite) \
- lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(*(_src))); \
if (_user) { \
+ lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(*(_src))); \
__chan->ops->event_strcpy_from_user(&__ctx, _src, \
__get_dynamic_len(dest)); \
} else { \
- __chan->ops->event_strcpy(&__ctx, _src, \
+ const char *__ctf_tmp_string = \
+ ((_src) ? (_src) : __LTTNG_NULL_STRING); \
+ lib_ring_buffer_align_ctx(&__ctx, \
+ lttng_alignof(*__ctf_tmp_string)); \
+ __chan->ops->event_strcpy(&__ctx, __ctf_tmp_string, \
__get_dynamic_len(dest)); \
}
return; \
if (unlikely(!ACCESS_ONCE(__event->enabled))) \
return; \
- __lpf = rcu_dereference(__session->pid_tracker); \
+ __lpf = lttng_rcu_dereference(__session->pid_tracker); \
if (__lpf && likely(!lttng_pid_tracker_lookup(__lpf, current->pid))) \
return; \
_code \
\
__event_prepare_filter_stack__##_name(__stackvar.__filter_stack_data, \
tp_locvar, _args); \
- list_for_each_entry_rcu(bc_runtime, &__event->bytecode_runtime_head, node) { \
+ lttng_list_for_each_entry_rcu(bc_runtime, &__event->bytecode_runtime_head, node) { \
if (unlikely(bc_runtime->filter(bc_runtime, \
__stackvar.__filter_stack_data) & LTTNG_FILTER_RECORD_FLAG)) \
__filter_record = 1; \
return; \
if (unlikely(!ACCESS_ONCE(__event->enabled))) \
return; \
- __lpf = rcu_dereference(__session->pid_tracker); \
+ __lpf = lttng_rcu_dereference(__session->pid_tracker); \
if (__lpf && likely(!lttng_pid_tracker_lookup(__lpf, current->pid))) \
return; \
_code \
\
__event_prepare_filter_stack__##_name(__stackvar.__filter_stack_data, \
tp_locvar); \
- list_for_each_entry_rcu(bc_runtime, &__event->bytecode_runtime_head, node) { \
+ lttng_list_for_each_entry_rcu(bc_runtime, &__event->bytecode_runtime_head, node) { \
if (unlikely(bc_runtime->filter(bc_runtime, \
__stackvar.__filter_stack_data) & LTTNG_FILTER_RECORD_FLAG)) \
__filter_record = 1; \