Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
if (ret)
return ret;
ret = wrapper_get_pageblock_flags_mask_init();
if (ret)
return ret;
ret = wrapper_get_pageblock_flags_mask_init();
+ if (ret)
+ return ret;
+ ret = lttng_probes_init();
if (ret)
return ret;
ret = lttng_context_init();
if (ret)
return ret;
ret = lttng_context_init();
uint64_t version; /* Current version of the metadata cache */
};
uint64_t version; /* Current version of the metadata cache */
};
+#define LTTNG_DYNAMIC_LEN_STACK_SIZE 128
+
+struct lttng_dynamic_len_stack {
+ size_t stack[LTTNG_DYNAMIC_LEN_STACK_SIZE];
+ size_t offset;
+};
+
+DECLARE_PER_CPU(struct lttng_dynamic_len_stack, lttng_dynamic_len_stack);
/*
* struct lttng_pid_tracker declared in header due to deferencing of *v
/*
* struct lttng_pid_tracker declared in header due to deferencing of *v
void lttng_enabler_event_link_bytecode(struct lttng_event *event,
struct lttng_enabler *enabler);
void lttng_enabler_event_link_bytecode(struct lttng_event *event,
struct lttng_enabler *enabler);
+int lttng_probes_init(void);
+
extern struct lttng_ctx *lttng_static_ctx;
int lttng_context_init(void);
extern struct lttng_ctx *lttng_static_ctx;
int lttng_context_init(void);
*/
static int lazy_nesting;
*/
static int lazy_nesting;
+DEFINE_PER_CPU(struct lttng_dynamic_len_stack, lttng_dynamic_len_stack);
+
+EXPORT_PER_CPU_SYMBOL_GPL(lttng_dynamic_len_stack);
+
/*
* Called under sessions lock.
*/
/*
* Called under sessions lock.
*/
.llseek = seq_lseek,
.release = seq_release,
};
.llseek = seq_lseek,
.release = seq_release,
};
+
+int lttng_probes_init(void)
+{
+ int cpu;
+
+ for_each_possible_cpu(cpu)
+ per_cpu_ptr(<tng_dynamic_len_stack, cpu)->offset = 0;
+ return 0;
+}
__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)); \
__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)); \
- __dynamic_len[__dynamic_len_idx] = (_src_length); \
- __event_len += sizeof(_type) * __dynamic_len[__dynamic_len_idx]; \
- __dynamic_len_idx++;
+ { \
+ size_t __seqlen = (_src_length); \
+ \
+ if (unlikely(++this_cpu_ptr(<tng_dynamic_len_stack)->offset >= LTTNG_DYNAMIC_LEN_STACK_SIZE)) \
+ goto error; \
+ barrier(); /* reserve before use. */ \
+ this_cpu_ptr(<tng_dynamic_len_stack)->stack[this_cpu_ptr(<tng_dynamic_len_stack)->offset - 1] = __seqlen; \
+ __event_len += sizeof(_type) * __seqlen; \
+ }
#undef _ctf_sequence_bitfield
#define _ctf_sequence_bitfield(_type, _item, _src, \
#undef _ctf_sequence_bitfield
#define _ctf_sequence_bitfield(_type, _item, _src, \
*/
#undef _ctf_string
#define _ctf_string(_item, _src, _user, _nowrite) \
*/
#undef _ctf_string
#define _ctf_string(_item, _src, _user, _nowrite) \
- if (_user) \
- __event_len += __dynamic_len[__dynamic_len_idx++] = \
+ if (unlikely(++this_cpu_ptr(<tng_dynamic_len_stack)->offset >= LTTNG_DYNAMIC_LEN_STACK_SIZE)) \
+ goto error; \
+ barrier(); /* reserve before use. */ \
+ if (_user) { \
+ __event_len += this_cpu_ptr(<tng_dynamic_len_stack)->stack[this_cpu_ptr(<tng_dynamic_len_stack)->offset - 1] = \
max_t(size_t, lttng_strlen_user_inatomic(_src), 1); \
max_t(size_t, lttng_strlen_user_inatomic(_src), 1); \
- else \
- __event_len += __dynamic_len[__dynamic_len_idx++] = \
- strlen(_src) + 1;
+ } else { \
+ __event_len += this_cpu_ptr(<tng_dynamic_len_stack)->stack[this_cpu_ptr(<tng_dynamic_len_stack)->offset - 1] = \
+ strlen(_src) + 1; \
+ }
#undef TP_PROTO
#define TP_PROTO(...) __VA_ARGS__
#undef TP_PROTO
#define TP_PROTO(...) __VA_ARGS__
#undef LTTNG_TRACEPOINT_EVENT_CLASS_CODE
#define LTTNG_TRACEPOINT_EVENT_CLASS_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
#undef LTTNG_TRACEPOINT_EVENT_CLASS_CODE
#define LTTNG_TRACEPOINT_EVENT_CLASS_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
-static inline size_t __event_get_size__##_name(size_t *__dynamic_len, \
- void *__tp_locvar, _proto) \
+static inline ssize_t __event_get_size__##_name(void *__tp_locvar, _proto) \
{ \
size_t __event_len = 0; \
unsigned int __dynamic_len_idx __attribute__((unused)) = 0; \
{ \
size_t __event_len = 0; \
unsigned int __dynamic_len_idx __attribute__((unused)) = 0; \
\
_fields \
return __event_len; \
\
_fields \
return __event_len; \
+ \
+error: \
+ __attribute__((unused)); \
+ return -1; \
}
#undef LTTNG_TRACEPOINT_EVENT_CLASS_CODE_NOARGS
#define LTTNG_TRACEPOINT_EVENT_CLASS_CODE_NOARGS(_name, _locvar, _code_pre, _fields, _code_post) \
}
#undef LTTNG_TRACEPOINT_EVENT_CLASS_CODE_NOARGS
#define LTTNG_TRACEPOINT_EVENT_CLASS_CODE_NOARGS(_name, _locvar, _code_pre, _fields, _code_post) \
-static inline size_t __event_get_size__##_name(size_t *__dynamic_len, \
- void *__tp_locvar) \
+static inline ssize_t __event_get_size__##_name(void *__tp_locvar) \
{ \
size_t __event_len = 0; \
unsigned int __dynamic_len_idx __attribute__((unused)) = 0; \
{ \
size_t __event_len = 0; \
unsigned int __dynamic_len_idx __attribute__((unused)) = 0; \
\
_fields \
return __event_len; \
\
_fields \
return __event_len; \
+ \
+error: \
+ __attribute__((unused)); \
+ return -1; \
}
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
}
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \
_src_length, _encoding, _byte_order, _base, _user, _nowrite) \
{ \
#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \
_src_length, _encoding, _byte_order, _base, _user, _nowrite) \
{ \
- _length_type __tmpl = __stackvar.__dynamic_len[__dynamic_len_idx]; \
+ _length_type __tmpl = this_cpu_ptr(<tng_dynamic_len_stack)->stack[__dynamic_len_idx]; \
lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_length_type));\
__chan->ops->event_write(&__ctx, &__tmpl, sizeof(_length_type));\
} \
lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_length_type));\
__chan->ops->event_write(&__ctx, &__tmpl, sizeof(_length_type));\
} \
_length_type, _src_length, \
_user, _nowrite) \
{ \
_length_type, _src_length, \
_user, _nowrite) \
{ \
- _length_type __tmpl = __stackvar.__dynamic_len[__dynamic_len_idx] * sizeof(_type) * CHAR_BIT; \
+ _length_type __tmpl = this_cpu_ptr(<tng_dynamic_len_stack)->stack[__dynamic_len_idx] * sizeof(_type) * CHAR_BIT; \
lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_length_type));\
__chan->ops->event_write(&__ctx, &__tmpl, sizeof(_length_type));\
} \
lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_length_type));\
__chan->ops->event_write(&__ctx, &__tmpl, sizeof(_length_type));\
} \
_length_type, _src_length, \
_user, _nowrite) \
{ \
_length_type, _src_length, \
_user, _nowrite) \
{ \
- _length_type __tmpl = __stackvar.__dynamic_len[__dynamic_len_idx] * sizeof(_type) * CHAR_BIT; \
+ _length_type __tmpl = this_cpu_ptr(<tng_dynamic_len_stack)->stack[__dynamic_len_idx] * sizeof(_type) * CHAR_BIT; \
lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_length_type));\
__chan->ops->event_write(&__ctx, &__tmpl, sizeof(_length_type));\
} \
lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_length_type));\
__chan->ops->event_write(&__ctx, &__tmpl, sizeof(_length_type));\
} \
/* Beware: this get len actually consumes the len value */
#undef __get_dynamic_len
/* Beware: this get len actually consumes the len value */
#undef __get_dynamic_len
-#define __get_dynamic_len(field) __stackvar.__dynamic_len[__dynamic_len_idx++]
+#define __get_dynamic_len(field) this_cpu_ptr(<tng_dynamic_len_stack)->stack[__dynamic_len_idx++]
#undef TP_PROTO
#define TP_PROTO(...) __VA_ARGS__
#undef TP_PROTO
#define TP_PROTO(...) __VA_ARGS__
struct lttng_channel *__chan = __event->chan; \
struct lttng_session *__session = __chan->session; \
struct lib_ring_buffer_ctx __ctx; \
struct lttng_channel *__chan = __event->chan; \
struct lttng_session *__session = __chan->session; \
struct lib_ring_buffer_ctx __ctx; \
- size_t __event_len, __event_align; \
- size_t __dynamic_len_idx __attribute__((unused)) = 0; \
+ ssize_t __event_len; \
+ size_t __event_align; \
+ size_t __orig_dynamic_len_offset, __dynamic_len_idx; \
- size_t __dynamic_len[ARRAY_SIZE(__event_fields___##_name)]; \
+ size_t __dynamic_len_removed[ARRAY_SIZE(__event_fields___##_name)]; \
char __filter_stack_data[2 * sizeof(unsigned long) * ARRAY_SIZE(__event_fields___##_name)]; \
} __stackvar; \
int __ret; \
char __filter_stack_data[2 * sizeof(unsigned long) * ARRAY_SIZE(__event_fields___##_name)]; \
} __stackvar; \
int __ret; \
__lpf = lttng_rcu_dereference(__session->pid_tracker); \
if (__lpf && likely(!lttng_pid_tracker_lookup(__lpf, current->pid))) \
return; \
__lpf = lttng_rcu_dereference(__session->pid_tracker); \
if (__lpf && likely(!lttng_pid_tracker_lookup(__lpf, current->pid))) \
return; \
+ __orig_dynamic_len_offset = this_cpu_ptr(<tng_dynamic_len_stack)->offset; \
+ __dynamic_len_idx = __orig_dynamic_len_offset; \
_code_pre \
if (unlikely(!list_empty(&__event->bytecode_runtime_head))) { \
struct lttng_bytecode_runtime *bc_runtime; \
_code_pre \
if (unlikely(!list_empty(&__event->bytecode_runtime_head))) { \
struct lttng_bytecode_runtime *bc_runtime; \
if (likely(!__filter_record)) \
goto __post; \
} \
if (likely(!__filter_record)) \
goto __post; \
} \
- __event_len = __event_get_size__##_name(__stackvar.__dynamic_len, \
- tp_locvar, _args); \
+ __event_len = __event_get_size__##_name(tp_locvar, _args); \
+ if (unlikely(__event_len < 0)) { \
+ lib_ring_buffer_lost_event_too_big(__chan->chan); \
+ goto __post; \
+ } \
__event_align = __event_get_align__##_name(tp_locvar, _args); \
lib_ring_buffer_ctx_init(&__ctx, __chan->chan, &__lttng_probe_ctx, __event_len, \
__event_align, -1); \
__event_align = __event_get_align__##_name(tp_locvar, _args); \
lib_ring_buffer_ctx_init(&__ctx, __chan->chan, &__lttng_probe_ctx, __event_len, \
__event_align, -1); \
__chan->ops->event_commit(&__ctx); \
__post: \
_code_post \
__chan->ops->event_commit(&__ctx); \
__post: \
_code_post \
+ barrier(); /* use before un-reserve. */ \
+ this_cpu_ptr(<tng_dynamic_len_stack)->offset = __orig_dynamic_len_offset; \
struct lttng_channel *__chan = __event->chan; \
struct lttng_session *__session = __chan->session; \
struct lib_ring_buffer_ctx __ctx; \
struct lttng_channel *__chan = __event->chan; \
struct lttng_session *__session = __chan->session; \
struct lib_ring_buffer_ctx __ctx; \
- size_t __event_len, __event_align; \
- size_t __dynamic_len_idx __attribute__((unused)) = 0; \
+ ssize_t __event_len; \
+ size_t __event_align; \
+ size_t __orig_dynamic_len_offset, __dynamic_len_idx; \
- size_t __dynamic_len[ARRAY_SIZE(__event_fields___##_name)]; \
+ size_t __dynamic_len_removed[ARRAY_SIZE(__event_fields___##_name)]; \
char __filter_stack_data[2 * sizeof(unsigned long) * ARRAY_SIZE(__event_fields___##_name)]; \
} __stackvar; \
int __ret; \
char __filter_stack_data[2 * sizeof(unsigned long) * ARRAY_SIZE(__event_fields___##_name)]; \
} __stackvar; \
int __ret; \
__lpf = lttng_rcu_dereference(__session->pid_tracker); \
if (__lpf && likely(!lttng_pid_tracker_lookup(__lpf, current->pid))) \
return; \
__lpf = lttng_rcu_dereference(__session->pid_tracker); \
if (__lpf && likely(!lttng_pid_tracker_lookup(__lpf, current->pid))) \
return; \
+ __orig_dynamic_len_offset = this_cpu_ptr(<tng_dynamic_len_stack)->offset; \
+ __dynamic_len_idx = __orig_dynamic_len_offset; \
_code_pre \
if (unlikely(!list_empty(&__event->bytecode_runtime_head))) { \
struct lttng_bytecode_runtime *bc_runtime; \
_code_pre \
if (unlikely(!list_empty(&__event->bytecode_runtime_head))) { \
struct lttng_bytecode_runtime *bc_runtime; \
if (likely(!__filter_record)) \
goto __post; \
} \
if (likely(!__filter_record)) \
goto __post; \
} \
- __event_len = __event_get_size__##_name(__stackvar.__dynamic_len, tp_locvar); \
+ __event_len = __event_get_size__##_name(tp_locvar); \
+ if (unlikely(__event_len < 0)) { \
+ lib_ring_buffer_lost_event_too_big(__chan->chan); \
+ goto __post; \
+ } \
__event_align = __event_get_align__##_name(tp_locvar); \
lib_ring_buffer_ctx_init(&__ctx, __chan->chan, &__lttng_probe_ctx, __event_len, \
__event_align, -1); \
__event_align = __event_get_align__##_name(tp_locvar); \
lib_ring_buffer_ctx_init(&__ctx, __chan->chan, &__lttng_probe_ctx, __event_len, \
__event_align, -1); \
__chan->ops->event_commit(&__ctx); \
__post: \
_code_post \
__chan->ops->event_commit(&__ctx); \
__post: \
_code_post \
+ barrier(); /* use before un-reserve. */ \
+ this_cpu_ptr(<tng_dynamic_len_stack)->offset = __orig_dynamic_len_offset; \