#include <lttng/event.h>
#include <lttng/lttng-error.h>
+#include <lttng/kernel-probe.h>
#include <lttng/userspace-probe.h>
#include <lttng/userspace-probe-internal.h>
-
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/event-rule/kernel-kprobe.h>
+#include <lttng/event-rule/kernel-kprobe-internal.h>
+#include <lttng/event-rule/kernel-syscall.h>
+#include <lttng/event-rule/kernel-syscall-internal.h>
+#include <lttng/event-rule/kernel-tracepoint.h>
+#include <lttng/event-rule/kernel-tracepoint-internal.h>
+#include <lttng/event-rule/kernel-uprobe.h>
+#include <lttng/event-rule/kernel-uprobe-internal.h>
#include <common/common.h>
#include <common/defaults.h>
#include <common/trace-chunk.h>
{
struct ltt_kernel_channel *chan;
- assert(session);
- assert(name);
+ LTTNG_ASSERT(session);
+ LTTNG_ASSERT(name);
/*
* If we receive an empty string for channel name, it means the
struct ltt_kernel_event *trace_kernel_find_event(
char *name, struct ltt_kernel_channel *channel,
enum lttng_event_type type,
- struct lttng_filter_bytecode *filter)
+ struct lttng_bytecode *filter)
{
struct ltt_kernel_event *ev;
int found = 0;
- assert(name);
- assert(channel);
+ LTTNG_ASSERT(name);
+ LTTNG_ASSERT(channel);
cds_list_for_each_entry(ev, &channel->events_list.head, list) {
if (type != LTTNG_EVENT_ALL && ev->type != type) {
struct ltt_kernel_event *ev;
int found = 0;
- assert(name);
- assert(channel);
+ LTTNG_ASSERT(name);
+ LTTNG_ASSERT(channel);
cds_list_for_each_entry(ev, &channel->events_list.head, list) {
if (type != LTTNG_EVENT_ALL && ev->type != type) {
struct ltt_kernel_channel *lkc;
struct lttng_channel_extended *extended = NULL;
- assert(chan);
+ LTTNG_ASSERT(chan);
lkc = zmalloc(sizeof(struct ltt_kernel_channel));
if (lkc == NULL) {
strncpy(lkc->channel->name, DEFAULT_CHANNEL_NAME,
sizeof(lkc->channel->name));
}
- lkc->channel->name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
+ lkc->channel->name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
lkc->fd = -1;
lkc->stream_count = 0;
* Return the allocated object or NULL on error.
*/
struct ltt_kernel_context *trace_kernel_create_context(
- struct lttng_kernel_context *ctx)
+ struct lttng_kernel_abi_context *ctx)
{
struct ltt_kernel_context *kctx;
{
struct ltt_kernel_context *kctx_copy;
- assert(kctx);
+ LTTNG_ASSERT(kctx);
kctx_copy = zmalloc(sizeof(*kctx_copy));
if (!kctx_copy) {
PERROR("zmalloc ltt_kernel_context");
*/
enum lttng_error_code trace_kernel_create_event(
struct lttng_event *ev, char *filter_expression,
- struct lttng_filter_bytecode *filter,
+ struct lttng_bytecode *filter,
struct ltt_kernel_event **kernel_event)
{
enum lttng_error_code ret;
- struct lttng_kernel_event *attr;
+ struct lttng_kernel_abi_event *attr;
struct ltt_kernel_event *local_kernel_event;
struct lttng_userspace_probe_location *userspace_probe_location = NULL;
- assert(ev);
+ LTTNG_ASSERT(ev);
local_kernel_event = zmalloc(sizeof(struct ltt_kernel_event));
- attr = zmalloc(sizeof(struct lttng_kernel_event));
+ attr = zmalloc(sizeof(struct lttng_kernel_abi_event));
if (local_kernel_event == NULL || attr == NULL) {
PERROR("kernel event zmalloc");
ret = LTTNG_ERR_NOMEM;
switch (ev->type) {
case LTTNG_EVENT_PROBE:
- attr->instrumentation = LTTNG_KERNEL_KPROBE;
+ attr->instrumentation = LTTNG_KERNEL_ABI_KPROBE;
attr->u.kprobe.addr = ev->attr.probe.addr;
attr->u.kprobe.offset = ev->attr.probe.offset;
strncpy(attr->u.kprobe.symbol_name,
- ev->attr.probe.symbol_name, LTTNG_KERNEL_SYM_NAME_LEN);
- attr->u.kprobe.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
+ ev->attr.probe.symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
+ attr->u.kprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
break;
case LTTNG_EVENT_USERSPACE_PROBE:
{
* In the interactions with the kernel tracer, we use the
* uprobe term.
*/
- attr->instrumentation = LTTNG_KERNEL_UPROBE;
+ attr->instrumentation = LTTNG_KERNEL_ABI_UPROBE;
- /*
- * Only the elf lookup method is supported at the moment.
- */
lookup = lttng_userspace_probe_location_get_lookup_method(
location);
if (!lookup) {
/*
* Save a reference to the probe location used during
- * the listing of events. Close its FD since it won't
- * be needed for listing.
+ * the listing of events.
*/
userspace_probe_location =
lttng_userspace_probe_location_copy(location);
- ret = lttng_userspace_probe_location_function_set_binary_fd(
- userspace_probe_location, -1);
- if (ret) {
- goto error;
- }
break;
case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
/* Get the file descriptor on the target binary. */
/*
* Save a reference to the probe location used during the listing of
- * events. Close its FD since it won't be needed for listing.
+ * events.
*/
userspace_probe_location =
lttng_userspace_probe_location_copy(location);
- ret = lttng_userspace_probe_location_tracepoint_set_binary_fd(
- userspace_probe_location, -1);
- if (ret) {
- goto error;
- }
break;
default:
DBG("Unsupported lookup method type");
break;
}
case LTTNG_EVENT_FUNCTION:
- attr->instrumentation = LTTNG_KERNEL_KRETPROBE;
+ attr->instrumentation = LTTNG_KERNEL_ABI_KRETPROBE;
attr->u.kretprobe.addr = ev->attr.probe.addr;
attr->u.kretprobe.offset = ev->attr.probe.offset;
strncpy(attr->u.kretprobe.symbol_name,
- ev->attr.probe.symbol_name, LTTNG_KERNEL_SYM_NAME_LEN);
- attr->u.kretprobe.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
+ ev->attr.probe.symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
+ attr->u.kretprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
break;
case LTTNG_EVENT_FUNCTION_ENTRY:
- attr->instrumentation = LTTNG_KERNEL_FUNCTION;
+ attr->instrumentation = LTTNG_KERNEL_ABI_FUNCTION;
strncpy(attr->u.ftrace.symbol_name,
- ev->attr.ftrace.symbol_name, LTTNG_KERNEL_SYM_NAME_LEN);
- attr->u.ftrace.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
+ ev->attr.ftrace.symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
+ attr->u.ftrace.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
break;
case LTTNG_EVENT_TRACEPOINT:
- attr->instrumentation = LTTNG_KERNEL_TRACEPOINT;
+ attr->instrumentation = LTTNG_KERNEL_ABI_TRACEPOINT;
break;
case LTTNG_EVENT_SYSCALL:
- attr->instrumentation = LTTNG_KERNEL_SYSCALL;
+ attr->instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
+ attr->u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL;
+ attr->u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT;
+ attr->u.syscall.match = LTTNG_KERNEL_ABI_SYSCALL_MATCH_NAME;
break;
case LTTNG_EVENT_ALL:
- attr->instrumentation = LTTNG_KERNEL_ALL;
+ attr->instrumentation = LTTNG_KERNEL_ABI_ALL;
break;
default:
ERR("Unknown kernel instrumentation type (%d)", ev->type);
}
/* Copy event name */
- strncpy(attr->name, ev->name, LTTNG_KERNEL_SYM_NAME_LEN);
- attr->name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
+ strncpy(attr->name, ev->name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
+ attr->name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
/* Setting up a kernel event */
local_kernel_event->fd = -1;
return ret;
}
+/*
+ * Allocate and initialize a kernel token event rule.
+ *
+ * Return pointer to structure or NULL.
+ */
+enum lttng_error_code trace_kernel_create_event_notifier_rule(
+ struct lttng_trigger *trigger,
+ uint64_t token,
+ uint64_t error_counter_index,
+ struct ltt_kernel_event_notifier_rule **event_notifier_rule)
+{
+ enum lttng_error_code ret = LTTNG_OK;
+ enum lttng_condition_type condition_type;
+ enum lttng_event_rule_type event_rule_type;
+ enum lttng_condition_status condition_status;
+ struct ltt_kernel_event_notifier_rule *local_kernel_token_event_rule;
+ const struct lttng_condition *condition = NULL;
+ const struct lttng_event_rule *event_rule = NULL;
+
+ LTTNG_ASSERT(event_notifier_rule);
+
+ condition = lttng_trigger_get_const_condition(trigger);
+ LTTNG_ASSERT(condition);
+
+ condition_type = lttng_condition_get_type(condition);
+ LTTNG_ASSERT(condition_type == LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES);
+
+ condition_status = lttng_condition_event_rule_matches_get_rule(
+ condition, &event_rule);
+ LTTNG_ASSERT(condition_status == LTTNG_CONDITION_STATUS_OK);
+ LTTNG_ASSERT(event_rule);
+
+ event_rule_type = lttng_event_rule_get_type(event_rule);
+ LTTNG_ASSERT(event_rule_type != LTTNG_EVENT_RULE_TYPE_UNKNOWN);
+
+ local_kernel_token_event_rule =
+ zmalloc(sizeof(struct ltt_kernel_event_notifier_rule));
+ if (local_kernel_token_event_rule == NULL) {
+ PERROR("Failed to allocate ltt_kernel_token_event_rule structure");
+ ret = LTTNG_ERR_NOMEM;
+ goto error;
+ }
+
+ local_kernel_token_event_rule->fd = -1;
+ local_kernel_token_event_rule->enabled = 1;
+ local_kernel_token_event_rule->token = token;
+ local_kernel_token_event_rule->error_counter_index = error_counter_index;
+
+ /* Get the reference of the event rule. */
+ lttng_trigger_get(trigger);
+
+ local_kernel_token_event_rule->trigger = trigger;
+ /* The event rule still owns the filter and bytecode. */
+ local_kernel_token_event_rule->filter =
+ lttng_event_rule_get_filter_bytecode(event_rule);
+
+ DBG3("Created kernel event notifier rule: token = %" PRIu64,
+ local_kernel_token_event_rule->token);
+error:
+ *event_notifier_rule = local_kernel_token_event_rule;
+ return ret;
+}
+
+/*
+ * Initialize a kernel trigger from an event rule.
+ */
+enum lttng_error_code trace_kernel_init_event_notifier_from_event_rule(
+ const struct lttng_event_rule *rule,
+ struct lttng_kernel_abi_event_notifier *kernel_event_notifier)
+{
+ enum lttng_error_code ret_code;
+ const char *name;
+ int strncpy_ret;
+
+ switch (lttng_event_rule_get_type(rule)) {
+ case LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE:
+ {
+ uint64_t address = 0, offset = 0;
+ const char *symbol_name = NULL;
+ const struct lttng_kernel_probe_location *location = NULL;
+ enum lttng_kernel_probe_location_status k_status;
+ enum lttng_event_rule_status status;
+
+ status = lttng_event_rule_kernel_kprobe_get_location(rule, &location);
+ if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+ ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
+ goto error;
+ }
+
+ switch (lttng_kernel_probe_location_get_type(location)) {
+ case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS:
+ {
+ k_status = lttng_kernel_probe_location_address_get_address(
+ location, &address);
+ LTTNG_ASSERT(k_status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK);
+ break;
+ }
+ case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET:
+ {
+ k_status = lttng_kernel_probe_location_symbol_get_offset(
+ location, &offset);
+ LTTNG_ASSERT(k_status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK);
+ symbol_name = lttng_kernel_probe_location_symbol_get_name(
+ location);
+ break;
+ }
+ default:
+ abort();
+ }
+
+ kernel_event_notifier->event.instrumentation = LTTNG_KERNEL_ABI_KPROBE;
+ kernel_event_notifier->event.u.kprobe.addr = address;
+ kernel_event_notifier->event.u.kprobe.offset = offset;
+ if (symbol_name) {
+ strncpy_ret = lttng_strncpy(
+ kernel_event_notifier->event.u.kprobe.symbol_name,
+ symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
+
+ if (strncpy_ret) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto error;
+ }
+ }
+
+ kernel_event_notifier->event.u.kprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
+
+ status = lttng_event_rule_kernel_kprobe_get_event_name(rule, &name);
+ LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
+ ret_code = LTTNG_OK;
+ break;
+ }
+ case LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE:
+ {
+ const struct lttng_userspace_probe_location* location = NULL;
+ const struct lttng_userspace_probe_location_lookup_method *lookup = NULL;
+ enum lttng_event_rule_status status;
+
+ status = lttng_event_rule_kernel_uprobe_get_location(rule, &location);
+ if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+ ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
+ goto error;
+ }
+
+ kernel_event_notifier->event.instrumentation = LTTNG_KERNEL_ABI_UPROBE;
+
+ lookup = lttng_userspace_probe_location_get_lookup_method(
+ location);
+ if (!lookup) {
+ ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL;
+ goto error;
+ }
+
+ /*
+ * From the kernel tracer's perspective, all userspace probe
+ * event types are all the same: a file and an offset.
+ */
+ switch (lttng_userspace_probe_location_lookup_method_get_type(lookup)) {
+ case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
+ /* Get the file descriptor on the target binary. */
+ kernel_event_notifier->event.u.uprobe.fd =
+ lttng_userspace_probe_location_function_get_binary_fd(location);
+
+ break;
+ case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
+ /* Get the file descriptor on the target binary. */
+ kernel_event_notifier->event.u.uprobe.fd =
+ lttng_userspace_probe_location_tracepoint_get_binary_fd(location);
+ break;
+ default:
+ abort();
+ }
+
+ status = lttng_event_rule_kernel_uprobe_get_event_name(
+ rule, &name);
+ LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
+ ret_code = LTTNG_OK;
+ break;
+ }
+ case LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT:
+ {
+ const enum lttng_event_rule_status status =
+ lttng_event_rule_kernel_tracepoint_get_name_pattern(
+ rule, &name);
+
+ LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
+ kernel_event_notifier->event.instrumentation =
+ LTTNG_KERNEL_ABI_TRACEPOINT;
+
+ ret_code = LTTNG_OK;
+ break;
+ }
+ case LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL:
+ {
+ const enum lttng_event_rule_status status =
+ lttng_event_rule_kernel_syscall_get_name_pattern(
+ rule, &name);
+ const enum lttng_event_rule_kernel_syscall_emission_site
+ emission_site =
+ lttng_event_rule_kernel_syscall_get_emission_site(rule);
+ enum lttng_kernel_abi_syscall_entryexit entryexit;
+
+ LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
+ LTTNG_ASSERT(emission_site != LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_UNKNOWN);
+
+ switch(emission_site) {
+ case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY:
+ entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
+ break;
+ case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT:
+ entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
+ break;
+ case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT:
+ entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT;
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ kernel_event_notifier->event.instrumentation =
+ LTTNG_KERNEL_ABI_SYSCALL;
+ kernel_event_notifier->event.u.syscall.abi =
+ LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL;
+ kernel_event_notifier->event.u.syscall.entryexit =
+ entryexit;
+ kernel_event_notifier->event.u.syscall.match =
+ LTTNG_KERNEL_ABI_SYSCALL_MATCH_NAME;
+ ret_code = LTTNG_OK;
+ break;
+ }
+ default:
+ abort();
+ break;
+ }
+
+ strncpy_ret = lttng_strncpy(kernel_event_notifier->event.name, name,
+ LTTNG_KERNEL_ABI_SYM_NAME_LEN);
+ if (strncpy_ret) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+error:
+ return ret_code;
+}
/*
* Allocate and initialize a kernel metadata.
*
int ret;
struct ltt_kernel_stream *lks;
- assert(name);
+ LTTNG_ASSERT(name);
lks = zmalloc(sizeof(struct ltt_kernel_stream));
if (lks == NULL) {
*/
void trace_kernel_destroy_stream(struct ltt_kernel_stream *stream)
{
- assert(stream);
+ LTTNG_ASSERT(stream);
DBG("[trace] Closing stream fd %d", stream->fd);
/* Close kernel fd */
*/
void trace_kernel_destroy_event(struct ltt_kernel_event *event)
{
- assert(event);
+ LTTNG_ASSERT(event);
if (event->fd >= 0) {
int ret;
PERROR("close");
}
} else {
- DBG("[trace] Tearing down event (no associated fd)");
+ DBG("[trace] Tearing down event (no associated file descriptor)");
}
/* Remove from event list */
free(event);
}
+/*
+ * Cleanup kernel event structure.
+ */
+static void free_token_event_rule_rcu(struct rcu_head *rcu_node)
+{
+ struct ltt_kernel_event_notifier_rule *rule = caa_container_of(rcu_node,
+ struct ltt_kernel_event_notifier_rule, rcu_node);
+
+ free(rule);
+}
+
+void trace_kernel_destroy_event_notifier_rule(
+ struct ltt_kernel_event_notifier_rule *event)
+{
+ LTTNG_ASSERT(event);
+
+ if (event->fd >= 0) {
+ const int ret = close(event->fd);
+
+ DBG("Closing kernel event notifier rule file descriptor: fd = %d",
+ event->fd);
+ if (ret) {
+ PERROR("Failed to close kernel event notifier file descriptor: fd = %d",
+ event->fd);
+ }
+ } else {
+ DBG("Destroying kernel event notifier rule (no associated file descriptor)");
+ }
+
+ lttng_trigger_put(event->trigger);
+ call_rcu(&event->rcu_node, free_token_event_rule_rcu);
+}
/*
* Cleanup kernel context structure.
*/
void trace_kernel_destroy_context(struct ltt_kernel_context *ctx)
{
- assert(ctx);
+ LTTNG_ASSERT(ctx);
if (ctx->in_list) {
cds_list_del(&ctx->list);
int ret;
enum lttng_error_code status;
- assert(channel);
+ LTTNG_ASSERT(channel);
DBG("[trace] Closing channel fd %d", channel->fd);
/* Close kernel fd */
/* Remove from channel list */
cds_list_del(&channel->list);
- if (notification_thread_handle
- && channel->published_to_notification_thread) {
+ if (the_notification_thread_handle &&
+ channel->published_to_notification_thread) {
status = notification_thread_command_remove_channel(
- notification_thread_handle,
- channel->key, LTTNG_DOMAIN_KERNEL);
- assert(status == LTTNG_OK);
+ the_notification_thread_handle, channel->key,
+ LTTNG_DOMAIN_KERNEL);
+ LTTNG_ASSERT(status == LTTNG_OK);
}
free(channel->channel->attr.extended.ptr);
free(channel->channel);
*/
void trace_kernel_destroy_metadata(struct ltt_kernel_metadata *metadata)
{
- assert(metadata);
+ LTTNG_ASSERT(metadata);
DBG("[trace] Closing metadata fd %d", metadata->fd);
/* Close kernel fd */
struct ltt_kernel_channel *channel, *ctmp;
int ret;
- assert(session);
+ LTTNG_ASSERT(session);
DBG("[trace] Closing session fd %d", session->fd);
/* Close kernel fds */