|
@@ -2030,6 +2030,79 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
|
|
memset(pev, 0, sizeof(*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)
|
|
void clear_probe_trace_event(struct probe_trace_event *tev)
|
|
{
|
|
{
|
|
struct probe_trace_arg_ref *ref, *next;
|
|
struct probe_trace_arg_ref *ref, *next;
|
|
@@ -2505,9 +2578,6 @@ static int find_probe_functions(struct map *map, char *name,
|
|
return found;
|
|
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,
|
|
void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
|
|
struct probe_trace_event *tev __maybe_unused,
|
|
struct probe_trace_event *tev __maybe_unused,
|
|
struct map *map __maybe_unused,
|
|
struct map *map __maybe_unused,
|