Implement per-context filtering
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 26 Mar 2013 02:36:22 +0000 (22:36 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 27 Mar 2013 17:32:20 +0000 (13:32 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/lttng/ust-events.h
liblttng-ust/filter-bytecode.h
liblttng-ust/lttng-context-procname.c
liblttng-ust/lttng-context-pthread-id.c
liblttng-ust/lttng-context-vpid.c
liblttng-ust/lttng-context-vtid.c
liblttng-ust/lttng-context.c
liblttng-ust/lttng-filter-interpreter.c
liblttng-ust/lttng-filter-specialize.c
liblttng-ust/lttng-filter-validator.c
liblttng-ust/lttng-filter.c

index 2b9603051975d480fd2e3687572149781c154e5a..c79bbed62174c920efcc0b891b94bb3479295cbe 100644 (file)
@@ -205,6 +205,12 @@ struct lttng_event_field {
        char padding[LTTNG_UST_EVENT_FIELD_PADDING];
 };
 
+union lttng_ctx_value {
+       int64_t s64;
+       const char *str;
+       double d;
+};
+
 #define LTTNG_UST_CTX_FIELD_PADDING    40
 struct lttng_ctx_field {
        struct lttng_event_field event_field;
@@ -212,6 +218,8 @@ struct lttng_ctx_field {
        void (*record)(struct lttng_ctx_field *field,
                       struct lttng_ust_lib_ring_buffer_ctx *ctx,
                       struct lttng_channel *chan);
+       void (*get_value)(struct lttng_ctx_field *field,
+                        union lttng_ctx_value *value);
        union {
                char padding[LTTNG_UST_CTX_FIELD_PADDING];
        } u;
@@ -520,6 +528,7 @@ int lttng_fix_pending_event_desc(const struct lttng_event_desc *desc);
 int lttng_probes_init(void);
 void lttng_probes_exit(void);
 int lttng_find_context(struct lttng_ctx *ctx, const char *name);
+int lttng_get_context_index(struct lttng_ctx *ctx, const char *name);
 struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p);
 void lttng_remove_context_field(struct lttng_ctx **ctx_p,
                                struct lttng_ctx_field *field);
index 3358a2fd6c90c733cc43ee49b65d2d4c1e0b1310..ce2dbc7394db17d37506bb7ed210adc1f06b172d 100644 (file)
@@ -124,13 +124,14 @@ enum filter_op {
        FILTER_OP_AND,
        FILTER_OP_OR,
 
-       /* load */
+       /* load field ref */
        FILTER_OP_LOAD_FIELD_REF,
        FILTER_OP_LOAD_FIELD_REF_STRING,
        FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
        FILTER_OP_LOAD_FIELD_REF_S64,
        FILTER_OP_LOAD_FIELD_REF_DOUBLE,
 
+       /* load immediate from operand */
        FILTER_OP_LOAD_STRING,
        FILTER_OP_LOAD_S64,
        FILTER_OP_LOAD_DOUBLE,
@@ -140,6 +141,12 @@ enum filter_op {
        FILTER_OP_CAST_DOUBLE_TO_S64,
        FILTER_OP_CAST_NOP,
 
+       /* get context ref */
+       FILTER_OP_GET_CONTEXT_REF,
+       FILTER_OP_GET_CONTEXT_REF_STRING,
+       FILTER_OP_GET_CONTEXT_REF_S64,
+       FILTER_OP_GET_CONTEXT_REF_DOUBLE,
+
        NR_FILTER_OPS,
 };
 
index 0e7bf1ce6080ed264be4335dfc8f9de6334273a0..c76d8ba397b1c2abdb758ca5bbd8033b82d24bdc 100644 (file)
@@ -74,6 +74,16 @@ void procname_record(struct lttng_ctx_field *field,
        chan->ops->event_write(ctx, procname, LTTNG_UST_PROCNAME_LEN);
 }
 
+static
+void procname_get_value(struct lttng_ctx_field *field,
+               union lttng_ctx_value *value)
+{
+       char *procname;
+
+       procname = wrapper_getprocname();
+       value->str = procname;
+}
+
 int lttng_add_procname_to_ctx(struct lttng_ctx **ctx)
 {
        struct lttng_ctx_field *field;
@@ -97,6 +107,7 @@ int lttng_add_procname_to_ctx(struct lttng_ctx **ctx)
        field->event_field.type.u.array.length = LTTNG_UST_PROCNAME_LEN;
        field->get_size = procname_get_size;
        field->record = procname_record;
+       field->get_value = procname_get_value;
        return 0;
 }
 
index e0f662f2c52da6a5c211055e3c3a9bd5044539b1..bf20c695f2d48f08f0787114de576ab44b152c0d 100644 (file)
@@ -47,6 +47,16 @@ void pthread_id_record(struct lttng_ctx_field *field,
        chan->ops->event_write(ctx, &pthread_id, sizeof(pthread_id));
 }
 
+static
+void pthread_id_get_value(struct lttng_ctx_field *field,
+               union lttng_ctx_value *value)
+{
+       unsigned long pthread_id;
+
+       pthread_id = (unsigned long) pthread_self();
+       value->s64 = pthread_id;
+}
+
 int lttng_add_pthread_id_to_ctx(struct lttng_ctx **ctx)
 {
        struct lttng_ctx_field *field;
@@ -68,5 +78,6 @@ int lttng_add_pthread_id_to_ctx(struct lttng_ctx **ctx)
        field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
        field->get_size = pthread_id_get_size;
        field->record = pthread_id_record;
+       field->get_value = pthread_id_get_value;
        return 0;
 }
index 3ab786f4c8f616243deb751dbcbfc1bd425b4106..949529c606c253d6fdf272360658370ad818b2d7 100644 (file)
@@ -83,6 +83,16 @@ void vpid_record(struct lttng_ctx_field *field,
        chan->ops->event_write(ctx, &pid, sizeof(pid));
 }
 
+static
+void vpid_get_value(struct lttng_ctx_field *field,
+               union lttng_ctx_value *value)
+{
+       pid_t pid;
+
+       pid = wrapper_getpid();
+       value->s64 = pid;
+}
+
 int lttng_add_vpid_to_ctx(struct lttng_ctx **ctx)
 {
        struct lttng_ctx_field *field;
@@ -104,5 +114,6 @@ int lttng_add_vpid_to_ctx(struct lttng_ctx **ctx)
        field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
        field->get_size = vpid_get_size;
        field->record = vpid_record;
+       field->get_value = vpid_get_value;
        return 0;
 }
index 4b1da4f8e9b78541473f3e838352e04ac4461679..7d83b87c90bcf804f796e497d5ecd35162668cb0 100644 (file)
@@ -67,6 +67,15 @@ void vtid_record(struct lttng_ctx_field *field,
                sizeof(URCU_TLS(cached_vtid)));
 }
 
+static
+void vtid_get_value(struct lttng_ctx_field *field,
+               union lttng_ctx_value *value)
+{
+       if (caa_unlikely(!URCU_TLS(cached_vtid)))
+               URCU_TLS(cached_vtid) = gettid();
+       value->s64 = URCU_TLS(cached_vtid);
+}
+
 int lttng_add_vtid_to_ctx(struct lttng_ctx **ctx)
 {
        struct lttng_ctx_field *field;
@@ -88,6 +97,7 @@ int lttng_add_vtid_to_ctx(struct lttng_ctx **ctx)
        field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
        field->get_size = vtid_get_size;
        field->record = vtid_record;
+       field->get_value = vtid_get_value;
        return 0;
 }
 
index 16894ec1032b722407ce578d43f47051a62bbc60..fc2ab4f570b8182ef69f44a8e3375e5adcde1630 100644 (file)
 #include <string.h>
 #include <assert.h>
 
+/*
+ * The filter implementation requires that two consecutive "get" for the
+ * same context performed by the same thread return the same result.
+ */
+
 int lttng_find_context(struct lttng_ctx *ctx, const char *name)
 {
        unsigned int i;
@@ -41,6 +46,22 @@ int lttng_find_context(struct lttng_ctx *ctx, const char *name)
        return 0;
 }
 
+int lttng_get_context_index(struct lttng_ctx *ctx, const char *name)
+{
+       unsigned int i;
+
+       if (!ctx)
+               return -1;
+       for (i = 0; i < ctx->nr_fields; i++) {
+               /* Skip allocated (but non-initialized) contexts */
+               if (!ctx->fields[i].event_field.name)
+                       continue;
+               if (!strcmp(ctx->fields[i].event_field.name, name))
+                       return i;
+       }
+       return -1;
+}
+
 /*
  * Note: as we append context information, the pointer location may change.
  */
index 8640960801b323d9ce5403d01c2234abfd21392c..1f43decee2e32414cb71b3f06e2cd2e9d3afbbaf 100644 (file)
@@ -176,6 +176,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                const char *filter_stack_data)
 {
        struct bytecode_runtime *bytecode = filter_data;
+       struct lttng_ctx *ctx = bytecode->p.bc->enabler->chan->ctx;
        void *pc, *next_pc, *start_pc;
        int ret = -EINVAL;
        uint64_t retval = 0;
@@ -263,13 +264,14 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
                [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
 
-               /* load */
+               /* load field ref */
                [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
                [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
                [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
                [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
                [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
 
+               /* load from immediate operand */
                [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
                [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
                [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
@@ -278,6 +280,12 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                [ FILTER_OP_CAST_TO_S64 ] = &&LABEL_FILTER_OP_CAST_TO_S64,
                [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64,
                [ FILTER_OP_CAST_NOP ] = &&LABEL_FILTER_OP_CAST_NOP,
+
+               /* get context ref */
+               [ FILTER_OP_GET_CONTEXT_REF ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF,
+               [ FILTER_OP_GET_CONTEXT_REF_STRING ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_STRING,
+               [ FILTER_OP_GET_CONTEXT_REF_S64 ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_S64,
+               [ FILTER_OP_GET_CONTEXT_REF_DOUBLE ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_DOUBLE,
        };
 #endif /* #ifndef INTERPRETER_USE_SWITCH */
 
@@ -285,6 +293,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
 
                OP(FILTER_OP_UNKNOWN):
                OP(FILTER_OP_LOAD_FIELD_REF):
+               OP(FILTER_OP_GET_CONTEXT_REF):
 #ifdef INTERPRETER_USE_SWITCH
                default:
 #endif /* INTERPRETER_USE_SWITCH */
@@ -710,7 +719,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                }
 
 
-               /* load */
+               /* load field ref */
                OP(FILTER_OP_LOAD_FIELD_REF_STRING):
                {
                        struct load_op *insn = (struct load_op *) pc;
@@ -786,6 +795,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        PO;
                }
 
+               /* load from immediate operand */
                OP(FILTER_OP_LOAD_STRING):
                {
                        struct load_op *insn = (struct load_op *) pc;
@@ -844,6 +854,68 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        PO;
                }
 
+               /* get context ref */
+               OP(FILTER_OP_GET_CONTEXT_REF_STRING):
+               {
+                       struct load_op *insn = (struct load_op *) pc;
+                       struct field_ref *ref = (struct field_ref *) insn->data;
+                       struct lttng_ctx_field *ctx_field;
+                       union lttng_ctx_value v;
+
+                       dbg_printf("get context ref offset %u type string\n",
+                               ref->offset);
+                       ctx_field = &ctx->fields[ref->offset];
+                       ctx_field->get_value(ctx_field, &v);
+                       estack_push(stack, top, ax, bx);
+                       estack_ax(stack, top)->u.s.str = v.str;
+                       if (unlikely(!estack_ax(stack, top)->u.s.str)) {
+                               dbg_printf("Filter warning: loading a NULL string.\n");
+                               ret = -EINVAL;
+                               goto end;
+                       }
+                       estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
+                       estack_ax(stack, top)->u.s.literal = 0;
+                       dbg_printf("ref get context string %s\n", estack_ax(stack, top)->u.s.str);
+                       next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
+                       PO;
+               }
+
+               OP(FILTER_OP_GET_CONTEXT_REF_S64):
+               {
+                       struct load_op *insn = (struct load_op *) pc;
+                       struct field_ref *ref = (struct field_ref *) insn->data;
+                       struct lttng_ctx_field *ctx_field;
+                       union lttng_ctx_value v;
+
+                       dbg_printf("get context ref offset %u type s64\n",
+                               ref->offset);
+                       ctx_field = &ctx->fields[ref->offset];
+                       ctx_field->get_value(ctx_field, &v);
+                       estack_push(stack, top, ax, bx);
+                       estack_ax_v = v.s64;
+                       dbg_printf("ref get context s64 %" PRIi64 "\n", estack_ax_v);
+                       next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
+                       PO;
+               }
+
+               OP(FILTER_OP_GET_CONTEXT_REF_DOUBLE):
+               {
+                       struct load_op *insn = (struct load_op *) pc;
+                       struct field_ref *ref = (struct field_ref *) insn->data;
+                       struct lttng_ctx_field *ctx_field;
+                       union lttng_ctx_value v;
+
+                       dbg_printf("get context ref offset %u type double\n",
+                               ref->offset);
+                       ctx_field = &ctx->fields[ref->offset];
+                       ctx_field->get_value(ctx_field, &v);
+                       estack_push(stack, top, ax, bx);
+                       memcpy(&estack_ax(stack, top)->u.d, &v.d, sizeof(struct literal_double));
+                       dbg_printf("ref get context double %g\n", estack_ax(stack, top)->u.d);
+                       next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
+                       PO;
+               }
+
        END_OP
 end:
        /* return 0 (discard) on error */
index 66e3db6f7228b379fc9fe0d584f05465d483b404..a729e427f9dead2c3ebdaffc931f79cb9ff79b39 100644 (file)
@@ -406,15 +406,23 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                        break;
                }
 
-               /* load */
+               /* load field ref */
                case FILTER_OP_LOAD_FIELD_REF:
                {
                        ERR("Unknown field ref type\n");
                        ret = -EINVAL;
                        goto end;
                }
+               /* get context ref */
+               case FILTER_OP_GET_CONTEXT_REF:
+               {
+                       ERR("Unknown get context ref type\n");
+                       ret = -EINVAL;
+                       goto end;
+               }
                case FILTER_OP_LOAD_FIELD_REF_STRING:
                case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
+               case FILTER_OP_GET_CONTEXT_REF_STRING:
                {
                        if (vstack_push(stack)) {
                                ret = -EINVAL;
@@ -425,6 +433,7 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                        break;
                }
                case FILTER_OP_LOAD_FIELD_REF_S64:
+               case FILTER_OP_GET_CONTEXT_REF_S64:
                {
                        if (vstack_push(stack)) {
                                ret = -EINVAL;
@@ -435,6 +444,7 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                        break;
                }
                case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
+               case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
                {
                        if (vstack_push(stack)) {
                                ret = -EINVAL;
@@ -445,6 +455,7 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                        break;
                }
 
+               /* load from immediate operand */
                case FILTER_OP_LOAD_STRING:
                {
                        struct load_op *insn = (struct load_op *) pc;
@@ -522,7 +533,6 @@ int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
                        break;
                }
 
-
                }
        }
 end:
index 456407ffde228fa625e3973b3d5e02c71b0bd4d7..6cdfd8c164764e075bab11a5cb8234c51765890f 100644 (file)
@@ -286,17 +286,27 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode,
                break;
        }
 
-       /* load */
+       /* load field ref */
        case FILTER_OP_LOAD_FIELD_REF:
        {
                ERR("Unknown field ref type\n");
                ret = -EINVAL;
                break;
        }
+       /* get context ref */
+       case FILTER_OP_GET_CONTEXT_REF:
+       {
+               ERR("Unknown field ref type\n");
+               ret = -EINVAL;
+               break;
+       }
        case FILTER_OP_LOAD_FIELD_REF_STRING:
        case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
        case FILTER_OP_LOAD_FIELD_REF_S64:
        case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
+       case FILTER_OP_GET_CONTEXT_REF_STRING:
+       case FILTER_OP_GET_CONTEXT_REF_S64:
+       case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
        {
                if (unlikely(pc + sizeof(struct load_op) + sizeof(struct field_ref)
                                > start_pc + bytecode->len)) {
@@ -305,6 +315,7 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode,
                break;
        }
 
+       /* load from immediate operand */
        case FILTER_OP_LOAD_STRING:
        {
                struct load_op *insn = (struct load_op *) pc;
@@ -353,6 +364,7 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode,
                }
                break;
        }
+
        }
 
        return ret;
@@ -657,7 +669,7 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                break;
        }
 
-       /* load */
+       /* load field ref */
        case FILTER_OP_LOAD_FIELD_REF:
        {
                ERR("Unknown field ref type\n");
@@ -693,6 +705,7 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                break;
        }
 
+       /* load from immediate operand */
        case FILTER_OP_LOAD_STRING:
        {
                break;
@@ -747,6 +760,41 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                break;
        }
 
+       /* get context ref */
+       case FILTER_OP_GET_CONTEXT_REF:
+       {
+               ERR("Unknown get context ref type\n");
+               ret = -EINVAL;
+               goto end;
+       }
+       case FILTER_OP_GET_CONTEXT_REF_STRING:
+       {
+               struct load_op *insn = (struct load_op *) pc;
+               struct field_ref *ref = (struct field_ref *) insn->data;
+
+               dbg_printf("Validate get context ref offset %u type string\n",
+                       ref->offset);
+               break;
+       }
+       case FILTER_OP_GET_CONTEXT_REF_S64:
+       {
+               struct load_op *insn = (struct load_op *) pc;
+               struct field_ref *ref = (struct field_ref *) insn->data;
+
+               dbg_printf("Validate get context ref offset %u type s64\n",
+                       ref->offset);
+               break;
+       }
+       case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
+       {
+               struct load_op *insn = (struct load_op *) pc;
+               struct field_ref *ref = (struct field_ref *) insn->data;
+
+               dbg_printf("Validate get context ref offset %u type double\n",
+                       ref->offset);
+               break;
+       }
+
        }
 end:
        return ret;
@@ -966,15 +1014,23 @@ int exec_insn(struct bytecode_runtime *bytecode,
                break;
        }
 
-       /* load */
+       /* load field ref */
        case FILTER_OP_LOAD_FIELD_REF:
        {
                ERR("Unknown field ref type\n");
                ret = -EINVAL;
                goto end;
        }
+       /* get context ref */
+       case FILTER_OP_GET_CONTEXT_REF:
+       {
+               ERR("Unknown get context ref type\n");
+               ret = -EINVAL;
+               goto end;
+       }
        case FILTER_OP_LOAD_FIELD_REF_STRING:
        case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
+       case FILTER_OP_GET_CONTEXT_REF_STRING:
        {
                if (vstack_push(stack)) {
                        ret = -EINVAL;
@@ -985,6 +1041,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                break;
        }
        case FILTER_OP_LOAD_FIELD_REF_S64:
+       case FILTER_OP_GET_CONTEXT_REF_S64:
        {
                if (vstack_push(stack)) {
                        ret = -EINVAL;
@@ -995,6 +1052,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                break;
        }
        case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
+       case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
        {
                if (vstack_push(stack)) {
                        ret = -EINVAL;
@@ -1005,6 +1063,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                break;
        }
 
+       /* load from immediate operand */
        case FILTER_OP_LOAD_STRING:
        {
                struct load_op *insn = (struct load_op *) pc;
index 11e7e376a03006bec8fb2af8b86f95f16d53874a..4bb7d4dc87f0793705a11804d7fe91fefab5a427 100644 (file)
@@ -102,13 +102,14 @@ static const char *opnames[] = {
        [ FILTER_OP_AND ] = "AND",
        [ FILTER_OP_OR ] = "OR",
 
-       /* load */
+       /* load field ref */
        [ FILTER_OP_LOAD_FIELD_REF ] = "LOAD_FIELD_REF",
        [ FILTER_OP_LOAD_FIELD_REF_STRING ] = "LOAD_FIELD_REF_STRING",
        [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = "LOAD_FIELD_REF_SEQUENCE",
        [ FILTER_OP_LOAD_FIELD_REF_S64 ] = "LOAD_FIELD_REF_S64",
        [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = "LOAD_FIELD_REF_DOUBLE",
 
+       /* load from immediate operand */
        [ FILTER_OP_LOAD_STRING ] = "LOAD_STRING",
        [ FILTER_OP_LOAD_S64 ] = "LOAD_S64",
        [ FILTER_OP_LOAD_DOUBLE ] = "LOAD_DOUBLE",
@@ -117,6 +118,12 @@ static const char *opnames[] = {
        [ FILTER_OP_CAST_TO_S64 ] = "CAST_TO_S64",
        [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = "CAST_DOUBLE_TO_S64",
        [ FILTER_OP_CAST_NOP ] = "CAST_NOP",
+
+       /* get context ref */
+       [ FILTER_OP_GET_CONTEXT_REF ] = "GET_CONTEXT_REF",
+       [ FILTER_OP_GET_CONTEXT_REF_STRING ] = "GET_CONTEXT_REF_STRING",
+       [ FILTER_OP_GET_CONTEXT_REF_S64 ] = "GET_CONTEXT_REF_S64",
+       [ FILTER_OP_GET_CONTEXT_REF_DOUBLE ] = "GET_CONTEXT_REF_DOUBLE",
 };
 
 const char *print_op(enum filter_op op)
@@ -141,11 +148,7 @@ int apply_field_reloc(struct lttng_event *event,
        struct load_op *op;
        uint32_t field_offset = 0;
 
-       dbg_printf("Apply reloc: %u %s\n", reloc_offset, field_name);
-
-       /* Ensure that the reloc is within the code */
-       if (runtime_len - reloc_offset < sizeof(uint16_t))
-               return -EINVAL;
+       dbg_printf("Apply field reloc: %u %s\n", reloc_offset, field_name);
 
        /* Lookup event by name */
        desc = event->desc;
@@ -214,6 +217,85 @@ int apply_field_reloc(struct lttng_event *event,
        return 0;
 }
 
+static
+int apply_context_reloc(struct lttng_event *event,
+               struct bytecode_runtime *runtime,
+               uint32_t runtime_len,
+               uint32_t reloc_offset,
+               const char *context_name)
+{
+       struct field_ref *field_ref;
+       struct load_op *op;
+       struct lttng_ctx_field *ctx_field;
+       int idx;
+
+       dbg_printf("Apply context reloc: %u %s\n", reloc_offset, context_name);
+
+       /* Get context index */
+       idx = lttng_get_context_index(event->chan->ctx, context_name);
+       if (idx < 0)
+               return -ENOENT;
+
+       /* Check if idx is too large for 16-bit offset */
+       if (idx > FILTER_BYTECODE_MAX_LEN - 1)
+               return -EINVAL;
+
+       /* Get context return type */
+       ctx_field = &event->chan->ctx->fields[idx];
+       op = (struct load_op *) &runtime->data[reloc_offset];
+       field_ref = (struct field_ref *) op->data;
+       switch (ctx_field->event_field.type.atype) {
+       case atype_integer:
+       case atype_enum:
+               op->op = FILTER_OP_GET_CONTEXT_REF_S64;
+               break;
+               /* Sequence and array supported as string */
+       case atype_string:
+       case atype_array:
+       case atype_sequence:
+               op->op = FILTER_OP_GET_CONTEXT_REF_STRING;
+               break;
+       case atype_float:
+               op->op = FILTER_OP_GET_CONTEXT_REF_DOUBLE;
+               break;
+       default:
+               return -EINVAL;
+       }
+       /* set offset to context index within channel contexts */
+       field_ref->offset = (uint16_t) idx;
+       return 0;
+}
+
+static
+int apply_reloc(struct lttng_event *event,
+               struct bytecode_runtime *runtime,
+               uint32_t runtime_len,
+               uint32_t reloc_offset,
+               const char *name)
+{
+       struct load_op *op;
+
+       dbg_printf("Apply reloc: %u %s\n", reloc_offset, name);
+
+       /* Ensure that the reloc is within the code */
+       if (runtime_len - reloc_offset < sizeof(uint16_t))
+               return -EINVAL;
+
+       op = (struct load_op *) &runtime->data[reloc_offset];
+       switch (op->op) {
+       case FILTER_OP_LOAD_FIELD_REF:
+               return apply_field_reloc(event, runtime, runtime_len,
+                       reloc_offset, name);
+       case FILTER_OP_GET_CONTEXT_REF:
+               return apply_context_reloc(event, runtime, runtime_len,
+                       reloc_offset, name);
+       default:
+               ERR("Unknown reloc op type %u\n", op->op);
+               return -EINVAL;
+       }
+       return 0;
+}
+
 static
 int bytecode_is_linked(struct lttng_ust_filter_bytecode_node *filter_bytecode,
                struct lttng_event *event)
@@ -269,14 +351,14 @@ int _lttng_filter_event_link_bytecode(struct lttng_event *event,
                        offset = next_offset) {
                uint16_t reloc_offset =
                        *(uint16_t *) &filter_bytecode->bc.data[offset];
-               const char *field_name =
+               const char *name =
                        (const char *) &filter_bytecode->bc.data[offset + sizeof(uint16_t)];
 
-               ret = apply_field_reloc(event, runtime, runtime->len, reloc_offset, field_name);
+               ret = apply_reloc(event, runtime, runtime->len, reloc_offset, name);
                if (ret) {
                        goto link_error;
                }
-               next_offset = offset + sizeof(uint16_t) + strlen(field_name) + 1;
+               next_offset = offset + sizeof(uint16_t) + strlen(name) + 1;
        }
        /* Validate bytecode */
        ret = lttng_filter_validate_bytecode(runtime);
This page took 0.036793 seconds and 4 git commands to generate.