uint64_t user_token;
int has_enablers_without_filter_bytecode;
- /* list of struct lttng_kernel_bytecode_runtime, sorted by seqnum */
+ /* list of struct lttng_bytecode_runtime, sorted by seqnum */
struct list_head filter_bytecode_runtime_head;
enum lttng_kernel_abi_instrumentation instrumentation;
/* Selected by instrumentation */
};
+enum lttng_kernel_bytecode_interpreter_ret {
+ LTTNG_KERNEL_BYTECODE_INTERPRETER_ERROR = -1,
+ LTTNG_KERNEL_BYTECODE_INTERPRETER_OK = 0,
+};
+
+enum lttng_kernel_bytecode_filter_result {
+ LTTNG_KERNEL_BYTECODE_FILTER_ACCEPT = 0,
+ LTTNG_KERNEL_BYTECODE_FILTER_REJECT = 1,
+};
+
+struct lttng_kernel_bytecode_filter_ctx {
+ enum lttng_kernel_bytecode_filter_result result;
+};
+
static inline
const struct lttng_kernel_type_integer *lttng_kernel_get_type_integer(const struct lttng_kernel_type_common *type)
{
return true;
}
+int lttng_kernel_interpret_event_filter(const struct lttng_kernel_event_common *event,
+ const char *interpreter_stack_data,
+ struct lttng_probe_ctx *probe_ctx,
+ void *event_filter_ctx);
+
#endif /* _LTTNG_EVENTS_INTERNAL_H */
struct lttng_krp; /* Kretprobe handling */
-enum lttng_bytecode_node_type {
- LTTNG_BYTECODE_NODE_TYPE_FILTER,
- LTTNG_BYTECODE_NODE_TYPE_CAPTURE,
+enum lttng_kernel_bytecode_type {
+ LTTNG_KERNEL_BYTECODE_TYPE_FILTER,
+ LTTNG_KERNEL_BYTECODE_TYPE_CAPTURE,
};
struct lttng_bytecode_node {
- enum lttng_bytecode_node_type type;
+ enum lttng_kernel_bytecode_type type;
struct list_head node;
struct lttng_enabler *enabler;
struct {
} bc;
};
-/*
- * Bytecode interpreter return value masks.
- */
-enum lttng_bytecode_interpreter_ret {
- LTTNG_INTERPRETER_DISCARD = 0,
- LTTNG_INTERPRETER_RECORD_FLAG = (1ULL << 0),
- /* Other bits are kept for future use. */
-};
-
struct lttng_interpreter_output;
struct lttng_bytecode_runtime {
/* Associated bytecode */
+ enum lttng_kernel_bytecode_type type;
struct lttng_bytecode_node *bc;
- union {
- uint64_t (*filter)(void *filter_data,
- struct lttng_probe_ctx *lttng_probe_ctx,
- const char *filter_stack_data);
- uint64_t (*capture)(void *filter_data,
- const char *capture_stack_data,
+ int (*interpreter_func)(struct lttng_bytecode_runtime *kernel_bytecode,
+ const char *interpreter_stack_data,
struct lttng_probe_ctx *lttng_probe_ctx,
- struct lttng_interpreter_output *output);
- } interpreter_funcs;
+ void *caller_ctx);
int link_failed;
struct list_head node; /* list of bytecode runtime in event */
struct lttng_kernel_ctx *ctx;
LTTNG_SYSCALL_ABI_COMPAT,
};
+/*
+ * Result of the run_filter() callback.
+ */
+enum lttng_kernel_event_filter_result {
+ LTTNG_KERNEL_EVENT_FILTER_ACCEPT = 0,
+ LTTNG_KERNEL_EVENT_FILTER_REJECT = 1,
+};
+
struct lttng_kernel_event_common_private;
enum lttng_kernel_event_type {
int enabled;
int eval_filter; /* Need to evaluate filters */
- int (*run_filter)(struct lttng_kernel_event_common *event,
+ int (*run_filter)(const struct lttng_kernel_event_common *event,
const char *stack_data,
+ struct lttng_probe_ctx *probe_ctx,
void *filter_ctx);
};
const char *lttng_bytecode_print_op(enum bytecode_op op);
-void lttng_bytecode_filter_sync_state(struct lttng_bytecode_runtime *runtime);
-void lttng_bytecode_capture_sync_state(struct lttng_bytecode_runtime *runtime);
+void lttng_bytecode_sync_state(struct lttng_bytecode_runtime *runtime);
int lttng_bytecode_validate(struct bytecode_runtime *bytecode);
int lttng_bytecode_specialize(const struct lttng_kernel_event_desc *event_desc,
struct bytecode_runtime *bytecode);
-uint64_t lttng_bytecode_filter_interpret_false(void *filter_data,
- struct lttng_probe_ctx *lttng_probe_ctx,
- const char *filter_stack_data);
-uint64_t lttng_bytecode_filter_interpret(void *filter_data,
- struct lttng_probe_ctx *lttng_probe_ctx,
- const char *filter_stack_data);
+int lttng_bytecode_interpret_error(struct lttng_bytecode_runtime *bytecode_runtime,
+ const char *stack_data,
+ struct lttng_probe_ctx *probe_ctx,
+ void *ctx);
-uint64_t lttng_bytecode_capture_interpret_false(void *capture_data,
- const char *capture_stack_data,
- struct lttng_probe_ctx *lttng_probe_ctx,
- struct lttng_interpreter_output *output);
-uint64_t lttng_bytecode_capture_interpret(void *capture_data,
- const char *capture_stack_data,
+int lttng_bytecode_interpret(struct lttng_bytecode_runtime *kernel_bytecode,
+ const char *interpreter_stack_data,
struct lttng_probe_ctx *lttng_probe_ctx,
- struct lttng_interpreter_output *output);
+ void *caller_ctx);
#endif /* _LTTNG_FILTER_H */
__dynamic_len_idx = __orig_dynamic_len_offset; \
_code_pre \
if (unlikely(READ_ONCE(__event->eval_filter))) { \
- struct lttng_bytecode_runtime *bc_runtime; \
- bool __filter_record = false; \
- \
__event_prepare_interpreter_stack__##_name(__stackvar.__interpreter_stack_data, \
_locvar_args); \
__interpreter_stack_prepared = true; \
- lttng_list_for_each_entry_rcu(bc_runtime, &__event->priv->filter_bytecode_runtime_head, node) { \
- if (unlikely(bc_runtime->interpreter_funcs.filter(bc_runtime, &__lttng_probe_ctx, \
- __stackvar.__interpreter_stack_data) & LTTNG_INTERPRETER_RECORD_FLAG)) { \
- __filter_record = true; \
- break; \
- } \
- } \
- if (likely(!__filter_record)) \
+ if (likely(__event->run_filter(__event, \
+ __stackvar.__interpreter_stack_data, &__lttng_probe_ctx, NULL) != LTTNG_KERNEL_EVENT_FILTER_ACCEPT)) \
goto __post; \
} \
switch (__event->type) { \
return diff;
}
-uint64_t lttng_bytecode_filter_interpret_false(void *filter_data,
- struct lttng_probe_ctx *lttng_probe_ctx,
- const char *filter_stack_data)
-{
- return LTTNG_INTERPRETER_DISCARD;
-}
-
-uint64_t lttng_bytecode_capture_interpret_false(void *filter_data,
- const char *capture_stack_data,
- struct lttng_probe_ctx *lttng_probe_ctx,
- struct lttng_interpreter_output *output)
+int lttng_bytecode_interpret_error(
+ struct lttng_bytecode_runtime *bytecode_runtime __attribute__((unused)),
+ const char *stack_data __attribute__((unused)),
+ struct lttng_probe_ctx *probe_ctx __attribute__((unused)),
+ void *ctx __attribute__((unused)))
{
- return LTTNG_INTERPRETER_DISCARD;
+ return LTTNG_KERNEL_BYTECODE_INTERPRETER_ERROR;
}
#ifdef INTERPRETER_USE_SWITCH
return -EINVAL;
}
- return LTTNG_INTERPRETER_RECORD_FLAG;
+ return 0;
}
#ifdef DEBUG
#endif
/*
- * Return 0 (discard), or raise the 0x1 flag (log event).
- * Currently, other flags are kept for future extensions and have no
- * effect.
+ * Return LTTNG_KERNEL_BYTECODE_INTERPRETER_OK on success.
+ * Return LTTNG_KERNEL_BYTECODE_INTERPRETER_ERROR on error.
+ *
+ * For FILTER bytecode: expect a struct lttng_kernel_bytecode_filter_ctx *
+ * as @ctx argument.
+ * For CAPTURE bytecode: expect a struct lttng_interpreter_output *
+ * as @ctx argument.
*/
-static
-uint64_t bytecode_interpret(void *interpreter_data,
+int lttng_bytecode_interpret(struct lttng_bytecode_runtime *kernel_bytecode,
const char *interpreter_stack_data,
struct lttng_probe_ctx *lttng_probe_ctx,
- struct lttng_interpreter_output *output)
+ void *caller_ctx)
{
- struct bytecode_runtime *bytecode = interpreter_data;
+ struct bytecode_runtime *bytecode = container_of(kernel_bytecode, struct bytecode_runtime, p);
void *pc, *next_pc, *start_pc;
int ret = -EINVAL;
uint64_t retval = 0;
goto end;
OP(BYTECODE_OP_RETURN):
- OP(BYTECODE_OP_RETURN_S64):
- /* LTTNG_INTERPRETER_DISCARD or LTTNG_INTERPRETER_RECORD_FLAG */
+ /* LTTNG_KERNEL_BYTECODE_INTERPRETER_ERROR or LTTNG_KERNEL_BYTECODE_INTERPRETER_OK */
switch (estack_ax_t) {
case REG_S64:
case REG_U64:
case REG_DOUBLE:
case REG_STRING:
case REG_PTR:
- if (!output) {
+ if (kernel_bytecode->type != LTTNG_KERNEL_BYTECODE_TYPE_CAPTURE) {
ret = -EINVAL;
goto end;
}
ret = 0;
goto end;
+ OP(BYTECODE_OP_RETURN_S64):
+ /* LTTNG_KERNEL_BYTECODE_INTERPRETER_ERROR or LTTNG_KERNEL_BYTECODE_INTERPRETER_OK */
+ retval = !!estack_ax_v;
+ ret = 0;
+ goto end;
+
/* binary */
OP(BYTECODE_OP_MUL):
OP(BYTECODE_OP_DIV):
END_OP
end:
- /* Return _DISCARD on error. */
+ /* No need to prepare output if an error occurred. */
if (ret)
- return LTTNG_INTERPRETER_DISCARD;
+ return LTTNG_KERNEL_BYTECODE_INTERPRETER_ERROR;
- if (output) {
- return lttng_bytecode_interpret_format_output(
- estack_ax(stack, top), output);
+ /* Prepare output. */
+ switch (kernel_bytecode->type) {
+ case LTTNG_KERNEL_BYTECODE_TYPE_FILTER:
+ {
+ struct lttng_kernel_bytecode_filter_ctx *filter_ctx =
+ (struct lttng_kernel_bytecode_filter_ctx *) caller_ctx;
+ if (retval)
+ filter_ctx->result = LTTNG_KERNEL_BYTECODE_FILTER_ACCEPT;
+ else
+ filter_ctx->result = LTTNG_KERNEL_BYTECODE_FILTER_REJECT;
+ break;
}
-
- return retval;
-}
-LTTNG_STACK_FRAME_NON_STANDARD(bytecode_interpret);
-
-uint64_t lttng_bytecode_filter_interpret(void *filter_data,
- struct lttng_probe_ctx *lttng_probe_ctx,
- const char *filter_stack_data)
-{
- return bytecode_interpret(filter_data,
- filter_stack_data, lttng_probe_ctx, NULL);
+ case LTTNG_KERNEL_BYTECODE_TYPE_CAPTURE:
+ ret = lttng_bytecode_interpret_format_output(estack_ax(stack, top),
+ (struct lttng_interpreter_output *) caller_ctx);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ if (ret)
+ return LTTNG_KERNEL_BYTECODE_INTERPRETER_ERROR;
+ else
+ return LTTNG_KERNEL_BYTECODE_INTERPRETER_OK;
}
+LTTNG_STACK_FRAME_NON_STANDARD(lttng_bytecode_interpret);
-uint64_t lttng_bytecode_capture_interpret(void *capture_data,
- const char *capture_stack_data,
- struct lttng_probe_ctx *lttng_probe_ctx,
- struct lttng_interpreter_output *output)
+/*
+ * Return LTTNG_KERNEL_EVENT_FILTER_ACCEPT or LTTNG_KERNEL_EVENT_FILTER_REJECT.
+ */
+int lttng_kernel_interpret_event_filter(const struct lttng_kernel_event_common *event,
+ const char *interpreter_stack_data,
+ struct lttng_probe_ctx *probe_ctx,
+ void *event_filter_ctx __attribute__((unused)))
{
- return bytecode_interpret(capture_data,
- capture_stack_data, lttng_probe_ctx, output);
+ struct lttng_bytecode_runtime *filter_bc_runtime;
+ struct list_head *filter_bytecode_runtime_head = &event->priv->filter_bytecode_runtime_head;
+ struct lttng_kernel_bytecode_filter_ctx bytecode_filter_ctx;
+ bool filter_record = false;
+
+ list_for_each_entry_rcu(filter_bc_runtime, filter_bytecode_runtime_head, node) {
+ if (likely(filter_bc_runtime->interpreter_func(filter_bc_runtime,
+ interpreter_stack_data, probe_ctx, &bytecode_filter_ctx) == LTTNG_KERNEL_BYTECODE_INTERPRETER_OK)) {
+ if (unlikely(bytecode_filter_ctx.result == LTTNG_KERNEL_BYTECODE_FILTER_ACCEPT)) {
+ filter_record = true;
+ break;
+ }
+ }
+ }
+ if (filter_record)
+ return LTTNG_KERNEL_EVENT_FILTER_ACCEPT;
+ else
+ return LTTNG_KERNEL_EVENT_FILTER_REJECT;
}
#undef START_OP
ret = -ENOMEM;
goto alloc_error;
}
+ runtime->p.type = bytecode->type;
runtime->p.bc = bytecode;
runtime->p.ctx = ctx;
runtime->len = bytecode->bc.reloc_offset;
if (ret) {
goto link_error;
}
-
- switch (bytecode->type) {
- case LTTNG_BYTECODE_NODE_TYPE_FILTER:
- runtime->p.interpreter_funcs.filter = lttng_bytecode_filter_interpret;
- break;
- case LTTNG_BYTECODE_NODE_TYPE_CAPTURE:
- runtime->p.interpreter_funcs.capture = lttng_bytecode_capture_interpret_false;
- break;
- default:
- WARN_ON(1);
- }
-
+ runtime->p.interpreter_func = lttng_bytecode_interpret;
runtime->p.link_failed = 0;
list_add_rcu(&runtime->p.node, insert_loc);
dbg_printk("Linking successful.\n");
link_error:
- switch (bytecode->type) {
- case LTTNG_BYTECODE_NODE_TYPE_FILTER:
- runtime->p.interpreter_funcs.filter = lttng_bytecode_filter_interpret_false;
- break;
- case LTTNG_BYTECODE_NODE_TYPE_CAPTURE:
- runtime->p.interpreter_funcs.capture = lttng_bytecode_capture_interpret_false;
- break;
- default:
- WARN_ON(1);
- }
+ runtime->p.interpreter_func = lttng_bytecode_interpret_error;
runtime->p.link_failed = 1;
list_add_rcu(&runtime->p.node, insert_loc);
alloc_error:
return ret;
}
-void lttng_bytecode_filter_sync_state(struct lttng_bytecode_runtime *runtime)
-{
- struct lttng_bytecode_node *bc = runtime->bc;
-
- if (!bc->enabler->enabled || runtime->link_failed)
- runtime->interpreter_funcs.filter = lttng_bytecode_filter_interpret_false;
- else
- runtime->interpreter_funcs.filter = lttng_bytecode_filter_interpret;
-}
-
-void lttng_bytecode_capture_sync_state(struct lttng_bytecode_runtime *runtime)
+void lttng_bytecode_sync_state(struct lttng_bytecode_runtime *runtime)
{
struct lttng_bytecode_node *bc = runtime->bc;
if (!bc->enabler->enabled || runtime->link_failed)
- runtime->interpreter_funcs.capture = lttng_bytecode_capture_interpret_false;
+ runtime->interpreter_func = lttng_bytecode_interpret_error;
else
- runtime->interpreter_funcs.capture = lttng_bytecode_capture_interpret;
+ runtime->interpreter_func = lttng_bytecode_interpret;
}
/*
reserve_size += capture_buffer_content_len;
kernel_notif.capture_buf_size = capture_buffer_content_len;
- lib_ring_buffer_ctx_init(&ctx, event_notifier_group->chan, NULL, reserve_size,
- lttng_alignof(kernel_notif), -1);
+ lib_ring_buffer_ctx_init(&ctx, event_notifier_group->chan, reserve_size,
+ lttng_alignof(kernel_notif), -1, NULL);
ret = event_notifier_group->ops->event_reserve(&ctx, 0);
if (ret < 0) {
record_error(event_notifier);
&event_notifier->priv->capture_bytecode_runtime_head, node) {
struct lttng_interpreter_output output;
- if (capture_bc_runtime->interpreter_funcs.capture(capture_bc_runtime,
- stack_data, probe_ctx, &output) & LTTNG_INTERPRETER_RECORD_FLAG)
+ if (capture_bc_runtime->interpreter_func(capture_bc_runtime,
+ stack_data, probe_ctx, &output) == LTTNG_KERNEL_BYTECODE_INTERPRETER_OK)
ret = notification_append_capture(¬if, &output);
else
ret = notification_append_empty_capture(¬if);
event_recorder->parent.priv = &event_recorder_priv->parent;
event_recorder->parent.type = LTTNG_KERNEL_EVENT_TYPE_RECORDER;
+ event_recorder->parent.run_filter = lttng_kernel_interpret_event_filter;
event_recorder->chan = chan;
event_recorder->priv->id = chan->free_event_id++;
event_recorder->priv->parent.instrumentation = itype;
event_recorder_return->parent.priv = &event_recorder_return_priv->parent;
event_recorder_return->parent.type = LTTNG_KERNEL_EVENT_TYPE_RECORDER;
+ event_recorder_return->parent.run_filter = lttng_kernel_interpret_event_filter;
event_recorder_return->chan = chan;
event_recorder_return->priv->id = chan->free_event_id++;
event_recorder_return->priv->parent.instrumentation = itype;
INIT_LIST_HEAD(&event_notifier->priv->parent.filter_bytecode_runtime_head);
INIT_LIST_HEAD(&event_notifier->priv->parent.enablers_ref_head);
INIT_LIST_HEAD(&event_notifier->priv->capture_bytecode_runtime_head);
+ event_notifier->parent.run_filter = lttng_kernel_interpret_event_filter;
switch (itype) {
case LTTNG_KERNEL_ABI_TRACEPOINT:
if (ret)
goto error_free;
- bytecode_node->type = LTTNG_BYTECODE_NODE_TYPE_FILTER;
+ bytecode_node->type = LTTNG_KERNEL_BYTECODE_TYPE_FILTER;
bytecode_node->enabler = enabler;
/* Enforce length based on allocated size */
bytecode_node->bc.len = bytecode_len;
if (ret)
goto error_free;
- bytecode_node->type = LTTNG_BYTECODE_NODE_TYPE_CAPTURE;
+ bytecode_node->type = LTTNG_KERNEL_BYTECODE_TYPE_CAPTURE;
bytecode_node->enabler = enabler;
/* Enforce length based on allocated size */
/* Enable filters */
list_for_each_entry(runtime,
&event_recorder_priv->parent.filter_bytecode_runtime_head, node) {
- lttng_bytecode_filter_sync_state(runtime);
+ lttng_bytecode_sync_state(runtime);
nr_filters++;
}
WRITE_ONCE(event_recorder_priv->parent.pub->eval_filter,
/* Enable filters */
list_for_each_entry(runtime,
&event_notifier_priv->parent.filter_bytecode_runtime_head, node) {
- lttng_bytecode_filter_sync_state(runtime);
+ lttng_bytecode_sync_state(runtime);
nr_filters++;
}
WRITE_ONCE(event_notifier_priv->parent.pub->eval_filter,
/* Enable captures */
list_for_each_entry(runtime,
&event_notifier_priv->capture_bytecode_runtime_head, node) {
- lttng_bytecode_capture_sync_state(runtime);
+ lttng_bytecode_sync_state(runtime);
nr_captures++;
}
WRITE_ONCE(event_notifier->eval_capture, !!nr_captures);