perf probe: Add perf_probe_event__copy()
authorMasami Hiramatsu <mhiramat@kernel.org>
Wed, 8 Jun 2016 09:29:40 +0000 (18:29 +0900)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 14 Jun 2016 12:29:54 +0000 (09:29 -0300)
Add perf_probe_event__copy() to copy perf_probe_event data structure and
sub data structures under given source perf_probe_event.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Hemant Kumar <hemant@linux.vnet.ibm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20160608092940.3116.18034.stgit@devbox
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/probe-event.c
tools/perf/util/probe-event.h

index 7ae3dd10f147897f763ef84d233014ab5d2dfdef..84f4b2b32ab78e8838634655c3705790ab614282 100644 (file)
@@ -2030,6 +2030,79 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
        memset(pev, 0, sizeof(*pev));
 }
 
+#define strdup_or_goto(str, label)     \
+({ char *__p = NULL; if (str && !(__p = strdup(str))) goto label; __p; })
+
+static int perf_probe_point__copy(struct perf_probe_point *dst,
+                                 struct perf_probe_point *src)
+{
+       dst->file = strdup_or_goto(src->file, out_err);
+       dst->function = strdup_or_goto(src->function, out_err);
+       dst->lazy_line = strdup_or_goto(src->lazy_line, out_err);
+       dst->line = src->line;
+       dst->retprobe = src->retprobe;
+       dst->offset = src->offset;
+       return 0;
+
+out_err:
+       clear_perf_probe_point(dst);
+       return -ENOMEM;
+}
+
+static int perf_probe_arg__copy(struct perf_probe_arg *dst,
+                               struct perf_probe_arg *src)
+{
+       struct perf_probe_arg_field *field, **ppfield;
+
+       dst->name = strdup_or_goto(src->name, out_err);
+       dst->var = strdup_or_goto(src->var, out_err);
+       dst->type = strdup_or_goto(src->type, out_err);
+
+       field = src->field;
+       ppfield = &(dst->field);
+       while (field) {
+               *ppfield = zalloc(sizeof(*field));
+               if (!*ppfield)
+                       goto out_err;
+               (*ppfield)->name = strdup_or_goto(field->name, out_err);
+               (*ppfield)->index = field->index;
+               (*ppfield)->ref = field->ref;
+               field = field->next;
+               ppfield = &((*ppfield)->next);
+       }
+       return 0;
+out_err:
+       return -ENOMEM;
+}
+
+int perf_probe_event__copy(struct perf_probe_event *dst,
+                          struct perf_probe_event *src)
+{
+       int i;
+
+       dst->event = strdup_or_goto(src->event, out_err);
+       dst->group = strdup_or_goto(src->group, out_err);
+       dst->target = strdup_or_goto(src->target, out_err);
+       dst->uprobes = src->uprobes;
+
+       if (perf_probe_point__copy(&dst->point, &src->point) < 0)
+               goto out_err;
+
+       dst->args = zalloc(sizeof(struct perf_probe_arg) * src->nargs);
+       if (!dst->args)
+               goto out_err;
+       dst->nargs = src->nargs;
+
+       for (i = 0; i < src->nargs; i++)
+               if (perf_probe_arg__copy(&dst->args[i], &src->args[i]) < 0)
+                       goto out_err;
+       return 0;
+
+out_err:
+       clear_perf_probe_event(dst);
+       return -ENOMEM;
+}
+
 void clear_probe_trace_event(struct probe_trace_event *tev)
 {
        struct probe_trace_arg_ref *ref, *next;
@@ -2505,9 +2578,6 @@ static int find_probe_functions(struct map *map, char *name,
        return found;
 }
 
-#define strdup_or_goto(str, label)     \
-       ({ char *__p = strdup(str); if (!__p) goto label; __p; })
-
 void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
                                struct probe_trace_event *tev __maybe_unused,
                                struct map *map __maybe_unused,
index 5a27eb4fad05a29e518ac7b9ecad4a25fb8f4dd6..367f886cfe0023671faef839e7f631aa23c55530 100644 (file)
@@ -122,6 +122,9 @@ char *synthesize_perf_probe_command(struct perf_probe_event *pev);
 char *synthesize_probe_trace_command(struct probe_trace_event *tev);
 char *synthesize_perf_probe_arg(struct perf_probe_arg *pa);
 
+int perf_probe_event__copy(struct perf_probe_event *dst,
+                          struct perf_probe_event *src);
+
 /* Check the perf_probe_event needs debuginfo */
 bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);