SoW-2020-0002: Trace Hit Counters: trigger error reporting integration
[lttng-tools.git] / src / bin / lttng-sessiond / trace-kernel.c
index dfdc9fd14e96b9b2124034983dc0d1db4525633a..198e1dd4feca71f1e15333d9c1dfcbb2e0f6110a 100644 (file)
 
 #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/kprobe.h>
+#include <lttng/event-rule/kprobe-internal.h>
+#include <lttng/event-rule/syscall.h>
+#include <lttng/event-rule/syscall-internal.h>
+#include <lttng/event-rule/tracepoint.h>
+#include <lttng/event-rule/tracepoint-internal.h>
+#include <lttng/event-rule/uprobe-internal.h>
 #include <common/common.h>
 #include <common/defaults.h>
 #include <common/trace-chunk.h>
@@ -62,7 +71,7 @@ struct ltt_kernel_channel *trace_kernel_get_channel_by_name(
 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;
@@ -321,7 +330,7 @@ error:
  */
 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;
@@ -468,6 +477,212 @@ error:
        return ret;
 }
 
+/*
+ * Allocate and initialize a kernel token event rule.
+ *
+ * Return pointer to structure or NULL.
+ */
+enum lttng_error_code trace_kernel_create_token_event_rule(
+               struct lttng_trigger *trigger,
+               uint64_t token,
+               uint64_t trigger_error_counter_index,
+               struct ltt_kernel_token_event_rule **kernel_token_event_rule)
+{
+       enum lttng_error_code ret = LTTNG_OK;
+       struct ltt_kernel_token_event_rule *local_kernel_token_event_rule;
+       const struct lttng_condition *condition = NULL;
+       const struct lttng_event_rule *event_rule = NULL;
+
+       assert(kernel_token_event_rule);
+
+       condition = lttng_trigger_get_condition(trigger);
+       assert(condition);
+       assert(lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT);
+
+       assert(lttng_condition_event_rule_get_rule(condition, &event_rule) == LTTNG_CONDITION_STATUS_OK);
+       assert(event_rule);
+       assert(lttng_event_rule_get_type(event_rule) != LTTNG_EVENT_RULE_TYPE_UNKNOWN);
+
+       local_kernel_token_event_rule = zmalloc(sizeof(struct ltt_kernel_token_event_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 = trigger_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 own the filter and bytecode */
+       local_kernel_token_event_rule->filter = lttng_event_rule_get_filter_bytecode(event_rule);
+
+       DBG3("[trace] Kernel token event rule %" PRIu64 " allocated", local_kernel_token_event_rule->token);
+error:
+       *kernel_token_event_rule = local_kernel_token_event_rule;
+       return ret;
+}
+
+/*
+ * Initialize a kernel trigger from an event rule.
+ */
+enum lttng_error_code trace_kernel_init_trigger_from_event_rule(const struct lttng_event_rule *rule,
+               struct lttng_kernel_trigger *kernel_trigger)
+{
+       enum lttng_error_code ret;
+       enum lttng_event_rule_status status;
+       const char *name = NULL;
+
+       /* TODO: do this for now but have disucssion on if this could be the
+        * responsability of the event_rule itself ala
+        * "lttng_even_rule_generate_kernel_trigger"
+        */
+       switch (lttng_event_rule_get_type(rule)) {
+       case LTTNG_EVENT_RULE_TYPE_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;
+
+               status = lttng_event_rule_kprobe_get_location(rule, &location);
+               if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+                       ret = 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);
+                       if (k_status != LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK) {
+                               ERR("Getting kernel probe address failed.");
+                       }
+
+                       break;
+               }
+               case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET:
+               {
+                       k_status = lttng_kernel_probe_location_symbol_get_offset(
+                                       location, &offset);
+                       if (k_status != LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK) {
+                               ERR("Getting kernel probe symbol offset failed.");
+                       }
+
+                       symbol_name = lttng_kernel_probe_location_symbol_get_name(
+                                       location);
+                       break;
+               }
+               default:
+                       ERR("Unknown kernel probe location type (%d)",
+                                       lttng_kernel_probe_location_get_type(
+                                                       location));
+                       ret = LTTNG_ERR_INVALID;
+                       goto error;
+               }
+
+               kernel_trigger->instrumentation = LTTNG_KERNEL_KPROBE;
+               kernel_trigger->u.kprobe.addr = address;
+               kernel_trigger->u.kprobe.offset = offset;
+               if (symbol_name) {
+                       strncpy(kernel_trigger->u.kprobe.symbol_name,
+                                       symbol_name, LTTNG_KERNEL_SYM_NAME_LEN);
+               }
+               kernel_trigger->u.kprobe
+                               .symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] =
+                               '\0';
+               (void) lttng_event_rule_kprobe_get_name(rule, &name);
+               ret = LTTNG_OK;
+               break;
+       }
+       case LTTNG_EVENT_RULE_TYPE_UPROBE:
+       {
+               const struct lttng_userspace_probe_location* location = NULL;
+               const struct lttng_userspace_probe_location_lookup_method *lookup = NULL;
+
+               status = lttng_event_rule_uprobe_get_location(rule, &location);
+               if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+                       ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
+                       goto error;
+               }
+
+               kernel_trigger->instrumentation = LTTNG_KERNEL_UPROBE;
+
+               /*
+                * Only the elf lookup method is supported at the moment.
+                */
+               lookup = lttng_userspace_probe_location_get_lookup_method(
+                               location);
+               if (!lookup) {
+                       ret = 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_trigger->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_trigger->u.uprobe.fd =
+                                       lttng_userspace_probe_location_tracepoint_get_binary_fd(location);
+                       break;
+               default:
+                       DBG("Unsupported lookup method type");
+                       ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
+                       goto error;
+               }
+
+               (void) lttng_event_rule_uprobe_get_name(rule, &name);
+
+               ret = LTTNG_OK;
+               break;
+       }
+       case LTTNG_EVENT_RULE_TYPE_KRETPROBE:
+               assert("Not supported" && 0);
+               ret = LTTNG_OK;
+               break;
+       case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
+               /* TODO: assert his is a kernel domain event-rule */
+               kernel_trigger->instrumentation = LTTNG_KERNEL_TRACEPOINT;
+               (void) lttng_event_rule_tracepoint_get_pattern(rule, &name);
+               ret = LTTNG_OK;
+               break;
+       case LTTNG_EVENT_RULE_TYPE_SYSCALL:
+               kernel_trigger->instrumentation = LTTNG_KERNEL_SYSCALL;
+               (void) lttng_event_rule_syscall_get_pattern(rule, &name);
+               ret = LTTNG_OK;
+               break;
+       default:
+               ERR("Unknown kernel event rule instrumentation type (%d)", lttng_event_rule_get_type(rule));
+               ret = LTTNG_ERR_INVALID;
+               goto error;
+       }
+
+       /*
+        * WTF is LTTNG_EVENT_ALL??? and LTTNG_EVENT_FUNTION_ENTRY?????
+        */
+
+       /* Copy event name */
+       strncpy(kernel_trigger->name, name, LTTNG_KERNEL_SYM_NAME_LEN);
+       kernel_trigger->name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
+
+error:
+       return ret;
+}
 /*
  * Allocate and initialize a kernel metadata.
  *
@@ -623,6 +838,30 @@ void trace_kernel_destroy_event(struct ltt_kernel_event *event)
        free(event);
 }
 
+/*
+ * Cleanup kernel event structure.
+ */
+void trace_kernel_destroy_token_event_rule(struct ltt_kernel_token_event_rule *event)
+{
+       /* TODO: review in depth to ensure adequate disposing */
+       assert(event);
+
+       if (event->fd >= 0) {
+               int ret;
+
+               DBG("[trace] Closing ,token event rule fd %d", event->fd);
+               /* Close kernel fd */
+               ret = close(event->fd);
+               if (ret) {
+                       PERROR("close");
+               }
+       } else {
+               DBG("[trace] Tearing down token event rule (no associated fd)");
+       }
+
+       lttng_trigger_put(event->trigger);
+       free(event);
+}
 /*
  * Cleanup kernel context structure.
  */
This page took 0.039258 seconds and 5 git commands to generate.