]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - tools/perf/util/probe-finder.c
perf probe: Support "string" type
[mirror_ubuntu-zesty-kernel.git] / tools / perf / util / probe-finder.c
index baf665383498ec54042edee05ea7783c3398967f..aaea16b1c60bd06b5e7a286b959aaf4c969a9897 100644 (file)
@@ -464,18 +464,61 @@ static int convert_location(Dwarf_Op *op, struct probe_finder *pf)
 }
 
 static int convert_variable_type(Dwarf_Die *vr_die,
-                                struct kprobe_trace_arg *targ)
+                                struct kprobe_trace_arg *tvar,
+                                const char *cast)
 {
+       struct kprobe_trace_arg_ref **ref_ptr = &tvar->ref;
        Dwarf_Die type;
        char buf[16];
        int ret;
 
+       /* TODO: check all types */
+       if (cast && strcmp(cast, "string") != 0) {
+               /* Non string type is OK */
+               tvar->type = strdup(cast);
+               return (tvar->type == NULL) ? -ENOMEM : 0;
+       }
+
        if (die_get_real_type(vr_die, &type) == NULL) {
                pr_warning("Failed to get a type information of %s.\n",
                           dwarf_diename(vr_die));
                return -ENOENT;
        }
 
+       if (cast && strcmp(cast, "string") == 0) {      /* String type */
+               ret = dwarf_tag(&type);
+               if (ret != DW_TAG_pointer_type &&
+                   ret != DW_TAG_array_type) {
+                       pr_warning("Failed to cast into string: "
+                                  "%s(%s) is not a pointer nor array.",
+                                  dwarf_diename(vr_die), dwarf_diename(&type));
+                       return -EINVAL;
+               }
+               if (ret == DW_TAG_pointer_type) {
+                       if (die_get_real_type(&type, &type) == NULL) {
+                               pr_warning("Failed to get a type information.");
+                               return -ENOENT;
+                       }
+                       while (*ref_ptr)
+                               ref_ptr = &(*ref_ptr)->next;
+                       /* Add new reference with offset +0 */
+                       *ref_ptr = zalloc(sizeof(struct kprobe_trace_arg_ref));
+                       if (*ref_ptr == NULL) {
+                               pr_warning("Out of memory error\n");
+                               return -ENOMEM;
+                       }
+               }
+               if (die_compare_name(&type, "char") != 0 &&
+                   die_compare_name(&type, "unsigned char") != 0) {
+                       pr_warning("Failed to cast into string: "
+                                  "%s is not (unsigned) char *.",
+                                  dwarf_diename(vr_die));
+                       return -EINVAL;
+               }
+               tvar->type = strdup(cast);
+               return (tvar->type == NULL) ? -ENOMEM : 0;
+       }
+
        ret = die_get_byte_size(&type) * 8;
        if (ret) {
                /* Check the bitwidth */
@@ -495,8 +538,8 @@ static int convert_variable_type(Dwarf_Die *vr_die,
                                   strerror(-ret));
                        return ret;
                }
-               targ->type = strdup(buf);
-               if (targ->type == NULL)
+               tvar->type = strdup(buf);
+               if (tvar->type == NULL)
                        return -ENOMEM;
        }
        return 0;
@@ -606,14 +649,8 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
                                              &die_mem);
                vr_die = &die_mem;
        }
-       if (ret == 0) {
-               if (pf->pvar->type) {
-                       pf->tvar->type = strdup(pf->pvar->type);
-                       if (pf->tvar->type == NULL)
-                               ret = -ENOMEM;
-               } else
-                       ret = convert_variable_type(vr_die, pf->tvar);
-       }
+       if (ret == 0)
+               ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
        /* *expr will be cached in libdw. Don't free it. */
        return ret;
 error: