callsite: support instruction pointer field
[babeltrace.git] / formats / ctf / metadata / ctf-visitor-generate-io-struct.c
index 9ded71627a65af988bc23eb0ddce68c5f0024356..de9986113de508f36bfe66ac5950c6786da728ef 100644 (file)
 #define _bt_list_first_entry(ptr, type, member)        \
        bt_list_entry((ptr)->next, type, member)
 
+struct last_enum_value {
+       union {
+               int64_t s;
+               uint64_t u;
+       } u;
+};
+
 int opt_clock_force_correlate;
 
 static
@@ -933,7 +940,8 @@ error:
 static
 int ctf_enumerator_list_visit(FILE *fd, int depth,
                struct ctf_node *enumerator,
-               struct declaration_enum *enum_declaration)
+               struct declaration_enum *enum_declaration,
+               struct last_enum_value *last)
 {
        GQuark q;
        struct ctf_node *iter;
@@ -969,8 +977,11 @@ int ctf_enumerator_list_visit(FILE *fd, int depth,
                        }
                        nr_vals++;
                }
-               if (nr_vals == 1)
+               if (nr_vals == 0)
+                       start = last->u.s;
+               if (nr_vals <= 1)
                        end = start;
+               last->u.s = end + 1;
                enum_signed_insert(enum_declaration, start, end, q);
        } else {
                uint64_t start, end;
@@ -1006,8 +1017,11 @@ int ctf_enumerator_list_visit(FILE *fd, int depth,
                        }
                        nr_vals++;
                }
-               if (nr_vals == 1)
+               if (nr_vals == 0)
+                       start = last->u.u;
+               if (nr_vals <= 1)
                        end = start;
+               last->u.u = end + 1;
                enum_unsigned_insert(enum_declaration, start, end, q);
        }
        return 0;
@@ -1025,6 +1039,7 @@ struct declaration *ctf_declaration_enum_visit(FILE *fd, int depth,
        struct declaration *declaration;
        struct declaration_enum *enum_declaration;
        struct declaration_integer *integer_declaration;
+       struct last_enum_value last_value;
        struct ctf_node *iter;
        GQuark dummy_id;
        int ret;
@@ -1076,8 +1091,14 @@ struct declaration *ctf_declaration_enum_visit(FILE *fd, int depth,
                integer_declaration = container_of(declaration, struct declaration_integer, p);
                enum_declaration = enum_declaration_new(integer_declaration);
                declaration_unref(&integer_declaration->p);     /* leave ref to enum */
+               if (enum_declaration->integer_declaration->signedness) {
+                       last_value.u.s = 0;
+               } else {
+                       last_value.u.u = 0;
+               }
                bt_list_for_each_entry(iter, enumerator_list, siblings) {
-                       ret = ctf_enumerator_list_visit(fd, depth + 1, iter, enum_declaration);
+                       ret = ctf_enumerator_list_visit(fd, depth + 1, iter, enum_declaration,
+                                       &last_value);
                        if (ret)
                                goto error;
                }
@@ -1720,6 +1741,23 @@ int ctf_event_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru
                        }
                        event->loglevel = (int) loglevel;
                        CTF_EVENT_SET_FIELD(event, loglevel);
+               } else if (!strcmp(left, "model.emf.uri")) {
+                       char *right;
+
+                       if (CTF_EVENT_FIELD_IS_SET(event, model_emf_uri)) {
+                               fprintf(fd, "[error] %s: model.emf.uri already declared in event declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       right = concatenate_unary_strings(&node->u.ctf_expression.right);
+                       if (!right) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for event model.emf.uri\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       event->model_emf_uri = g_quark_from_string(right);
+                       g_free(right);
+                       CTF_EVENT_SET_FIELD(event, model_emf_uri);
                } else {
                        fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in event declaration.\n", __func__, left);
                        /* Fall-through after warning */
@@ -2339,7 +2377,7 @@ int ctf_clock_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace
        }
        if (!CTF_CLOCK_FIELD_IS_SET(clock, name)) {
                ret = -EPERM;
-               fprintf(fd, "[error] %s: missing namefield in clock declaration\n", __func__);
+               fprintf(fd, "[error] %s: missing name field in clock declaration\n", __func__);
                goto error;
        }
        if (g_hash_table_size(trace->clocks) > 0) {
@@ -2395,6 +2433,175 @@ void clock_free(gpointer data)
        g_free(clock);
 }
 
+static
+int ctf_callsite_declaration_visit(FILE *fd, int depth, struct ctf_node *node,
+               struct ctf_callsite *callsite, struct ctf_trace *trace)
+{
+       int ret = 0;
+
+       switch (node->type) {
+       case NODE_CTF_EXPRESSION:
+       {
+               char *left;
+
+               left = concatenate_unary_strings(&node->u.ctf_expression.left);
+               if (!strcmp(left, "name")) {
+                       char *right;
+
+                       if (CTF_CALLSITE_FIELD_IS_SET(callsite, name)) {
+                               fprintf(fd, "[error] %s: name already declared in callsite declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       right = concatenate_unary_strings(&node->u.ctf_expression.right);
+                       if (!right) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for callsite name\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       callsite->name = g_quark_from_string(right);
+                       g_free(right);
+                       CTF_CALLSITE_SET_FIELD(callsite, name);
+               } else if (!strcmp(left, "func")) {
+                       char *right;
+
+                       if (CTF_CALLSITE_FIELD_IS_SET(callsite, func)) {
+                               fprintf(fd, "[error] %s: func already declared in callsite declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       right = concatenate_unary_strings(&node->u.ctf_expression.right);
+                       if (!right) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for callsite func\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       callsite->func = right;
+                       CTF_CALLSITE_SET_FIELD(callsite, func);
+               } else if (!strcmp(left, "file")) {
+                       char *right;
+
+                       if (CTF_CALLSITE_FIELD_IS_SET(callsite, file)) {
+                               fprintf(fd, "[error] %s: file already declared in callsite declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       right = concatenate_unary_strings(&node->u.ctf_expression.right);
+                       if (!right) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for callsite file\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       callsite->file = right;
+                       CTF_CALLSITE_SET_FIELD(callsite, file);
+               } else if (!strcmp(left, "line")) {
+                       if (CTF_CALLSITE_FIELD_IS_SET(callsite, line)) {
+                               fprintf(fd, "[error] %s: line already declared in callsite declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       ret = get_unary_unsigned(&node->u.ctf_expression.right, &callsite->line);
+                       if (ret) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for callsite line\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       CTF_CALLSITE_SET_FIELD(callsite, line);
+               } else if (!strcmp(left, "ip")) {
+                       if (CTF_CALLSITE_FIELD_IS_SET(callsite, ip)) {
+                               fprintf(fd, "[error] %s: ip already declared in callsite declaration\n", __func__);
+                               ret = -EPERM;
+                               goto error;
+                       }
+                       ret = get_unary_unsigned(&node->u.ctf_expression.right, &callsite->ip);
+                       if (ret) {
+                               fprintf(fd, "[error] %s: unexpected unary expression for callsite ip\n", __func__);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       CTF_CALLSITE_SET_FIELD(callsite, ip);
+               } else {
+                       fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in callsite declaration.\n", __func__, left);
+               }
+
+error:
+               g_free(left);
+               break;
+       }
+       default:
+               return -EPERM;
+       /* TODO: declaration specifier should be added. */
+       }
+
+       return ret;
+}
+
+static
+int ctf_callsite_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
+{
+       int ret = 0;
+       struct ctf_node *iter;
+       struct ctf_callsite *callsite;
+       struct ctf_callsite_dups *cs_dups;
+
+       callsite = g_new0(struct ctf_callsite, 1);
+       bt_list_for_each_entry(iter, &node->u.callsite.declaration_list, siblings) {
+               ret = ctf_callsite_declaration_visit(fd, depth + 1, iter, callsite, trace);
+               if (ret)
+                       goto error;
+       }
+       if (!CTF_CALLSITE_FIELD_IS_SET(callsite, name)) {
+               ret = -EPERM;
+               fprintf(fd, "[error] %s: missing name field in callsite declaration\n", __func__);
+               goto error;
+       }
+       if (!CTF_CALLSITE_FIELD_IS_SET(callsite, func)) {
+               ret = -EPERM;
+               fprintf(fd, "[error] %s: missing func field in callsite declaration\n", __func__);
+               goto error;
+       }
+       if (!CTF_CALLSITE_FIELD_IS_SET(callsite, file)) {
+               ret = -EPERM;
+               fprintf(fd, "[error] %s: missing file field in callsite declaration\n", __func__);
+               goto error;
+       }
+       if (!CTF_CALLSITE_FIELD_IS_SET(callsite, line)) {
+               ret = -EPERM;
+               fprintf(fd, "[error] %s: missing line field in callsite declaration\n", __func__);
+               goto error;
+       }
+
+       cs_dups = g_hash_table_lookup(trace->callsites,
+               (gpointer) (unsigned long) callsite->name);
+       if (!cs_dups) {
+               cs_dups = g_new0(struct ctf_callsite_dups, 1);
+               BT_INIT_LIST_HEAD(&cs_dups->head);
+               g_hash_table_insert(trace->callsites,
+                       (gpointer) (unsigned long) callsite->name, cs_dups);
+       }
+       bt_list_add_tail(&callsite->node, &cs_dups->head);
+       return 0;
+
+error:
+       g_free(callsite->func);
+       g_free(callsite->file);
+       g_free(callsite);
+       return ret;
+}
+
+static
+void callsite_free(gpointer data)
+{
+       struct ctf_callsite_dups *cs_dups = data;
+       struct ctf_callsite *callsite, *cs_n;
+
+       bt_list_for_each_entry_safe(callsite, cs_n, &cs_dups->head, node) {
+               g_free(callsite->func);
+               g_free(callsite->file);
+               g_free(callsite);
+       }
+}
+
 static
 int ctf_env_declaration_visit(FILE *fd, int depth, struct ctf_node *node,
                struct ctf_trace *trace)
@@ -2437,6 +2644,21 @@ int ctf_env_declaration_visit(FILE *fd, int depth, struct ctf_node *node,
                        strncpy(env->procname, right, TRACER_ENV_LEN);
                        env->procname[TRACER_ENV_LEN - 1] = '\0';
                        printf_verbose("env.procname = \"%s\"\n", env->procname);
+               } else if (!strcmp(left, "hostname")) {
+                       char *right;
+
+                       if (env->hostname[0]) {
+                               fprintf(fd, "[warning] %s: duplicated env hostname\n", __func__);
+                               goto error;     /* ret is 0, so not an actual error, just warn. */
+                       }
+                       right = concatenate_unary_strings(&node->u.ctf_expression.right);
+                       if (!right) {
+                               fprintf(fd, "[warning] %s: unexpected unary expression for env hostname\n", __func__);
+                               goto error;     /* ret is 0, so not an actual error, just warn. */
+                       }
+                       strncpy(env->hostname, right, TRACER_ENV_LEN);
+                       env->hostname[TRACER_ENV_LEN - 1] = '\0';
+                       printf_verbose("env.hostname = \"%s\"\n", env->hostname);
                } else if (!strcmp(left, "domain")) {
                        char *right;
 
@@ -2541,6 +2763,7 @@ int ctf_env_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *
 
        trace->env.vpid = -1;
        trace->env.procname[0] = '\0';
+       trace->env.hostname[0] = '\0';
        trace->env.domain[0] = '\0';
        trace->env.sysname[0] = '\0';
        trace->env.release[0] = '\0';
@@ -2611,6 +2834,8 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
        trace->byte_order = byte_order;
        trace->clocks = g_hash_table_new_full(g_direct_hash, g_direct_equal,
                                NULL, clock_free);
+       trace->callsites = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+                               NULL, callsite_free);
 
 retry:
        trace->root_declaration_scope = new_declaration_scope(NULL);
@@ -2660,6 +2885,14 @@ retry:
                                goto error;
                        }
                }
+               bt_list_for_each_entry(iter, &node->u.root.callsite, siblings) {
+                       ret = ctf_callsite_visit(fd, depth + 1, iter,
+                                             trace);
+                       if (ret) {
+                               fprintf(fd, "[error] %s: callsite declaration error\n", __func__);
+                               goto error;
+                       }
+               }
                if (!trace->streams) {
                        fprintf(fd, "[error] %s: missing trace declaration\n", __func__);
                        ret = -EINVAL;
@@ -2701,6 +2934,7 @@ retry:
 
 error:
        free_declaration_scope(trace->root_declaration_scope);
+       g_hash_table_destroy(trace->callsites);
        g_hash_table_destroy(trace->clocks);
        return ret;
 }
This page took 0.027046 seconds and 4 git commands to generate.