summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-trace.c87
1 files changed, 53 insertions, 34 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 1c080d95c1e2..a5f31472980b 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -151,7 +151,7 @@ struct trace {
struct perf_tool tool;
struct {
/** Sorted sycall numbers used by the trace. */
- struct syscall *table;
+ struct syscall **table;
/** Size of table. */
size_t table_size;
struct {
@@ -2473,24 +2473,41 @@ next_arg:
return printed;
}
-static void syscall__init(struct syscall *sc, int e_machine, int id)
+static struct syscall *syscall__new(int e_machine, int id)
{
- memset(sc, 0, sizeof(*sc));
+ struct syscall *sc = zalloc(sizeof(*sc));
+
+ if (!sc)
+ return NULL;
+
sc->e_machine = e_machine;
sc->id = id;
+ return sc;
}
-static void syscall__exit(struct syscall *sc)
+static void syscall__delete(struct syscall *sc)
{
if (!sc)
return;
- zfree(&sc->arg_fmt);
+ free(sc->arg_fmt);
+ free(sc);
+}
+
+static int syscall__bsearch_cmp(const void *key, const void *entry)
+{
+ const struct syscall *a = key, *b = *((const struct syscall **)entry);
+
+ if (a->e_machine != b->e_machine)
+ return a->e_machine - b->e_machine;
+
+ return a->id - b->id;
}
static int syscall__cmp(const void *va, const void *vb)
{
- const struct syscall *a = va, *b = vb;
+ const struct syscall *a = *((const struct syscall **)va);
+ const struct syscall *b = *((const struct syscall **)vb);
if (a->e_machine != b->e_machine)
return a->e_machine - b->e_machine;
@@ -2504,27 +2521,33 @@ static struct syscall *trace__find_syscall(struct trace *trace, int e_machine, i
.e_machine = e_machine,
.id = id,
};
- struct syscall *sc, *tmp;
+ struct syscall *sc, **tmp;
if (trace->syscalls.table) {
- sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
- sizeof(struct syscall), syscall__cmp);
- if (sc)
- return sc;
+ struct syscall **sc_entry = bsearch(&key, trace->syscalls.table,
+ trace->syscalls.table_size,
+ sizeof(trace->syscalls.table[0]),
+ syscall__bsearch_cmp);
+
+ if (sc_entry)
+ return *sc_entry;
}
+ sc = syscall__new(e_machine, id);
+ if (!sc)
+ return NULL;
+
tmp = reallocarray(trace->syscalls.table, trace->syscalls.table_size + 1,
- sizeof(struct syscall));
- if (!tmp)
+ sizeof(trace->syscalls.table[0]));
+ if (!tmp) {
+ syscall__delete(sc);
return NULL;
+ }
trace->syscalls.table = tmp;
- sc = &trace->syscalls.table[trace->syscalls.table_size++];
- syscall__init(sc, e_machine, id);
- qsort(trace->syscalls.table, trace->syscalls.table_size, sizeof(struct syscall),
+ trace->syscalls.table[trace->syscalls.table_size++] = sc;
+ qsort(trace->syscalls.table, trace->syscalls.table_size, sizeof(trace->syscalls.table[0]),
syscall__cmp);
- sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
- sizeof(struct syscall), syscall__cmp);
return sc;
}
@@ -3855,14 +3878,14 @@ static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int e_machine, i
return -1;
}
-static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace, struct syscall *_sc)
+static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace,
+ struct syscall *sc)
{
- struct syscall sc = *_sc; /* Copy as trace__syscall_info may invalidate pointer. */
struct tep_format_field *field, *candidate_field;
/*
* We're only interested in syscalls that have a pointer:
*/
- for (field = sc.args; field; field = field->next) {
+ for (field = sc->args; field; field = field->next) {
if (field->flags & TEP_FIELD_IS_POINTER)
goto try_to_find_pair;
}
@@ -3870,18 +3893,17 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
return NULL;
try_to_find_pair:
- for (int i = 0, num_idx = syscalltbl__num_idx(sc.e_machine); i < num_idx; ++i) {
- int id = syscalltbl__id_at_idx(sc.e_machine, i);
- /* calling trace__syscall_info() may invalidate '_sc' */
- struct syscall *pair = trace__syscall_info(trace, NULL, sc.e_machine, id);
+ for (int i = 0, num_idx = syscalltbl__num_idx(sc->e_machine); i < num_idx; ++i) {
+ int id = syscalltbl__id_at_idx(sc->e_machine, i);
+ struct syscall *pair = trace__syscall_info(trace, NULL, sc->e_machine, id);
struct bpf_program *pair_prog;
bool is_candidate = false;
- if (pair == NULL || pair->id == sc.id ||
+ if (pair == NULL || pair->id == sc->id ||
pair->bpf_prog.sys_enter == trace->skel->progs.syscall_unaugmented)
continue;
- for (field = sc.args, candidate_field = pair->args;
+ for (field = sc->args, candidate_field = pair->args;
field && candidate_field; field = field->next, candidate_field = candidate_field->next) {
bool is_pointer = field->flags & TEP_FIELD_IS_POINTER,
candidate_is_pointer = candidate_field->flags & TEP_FIELD_IS_POINTER;
@@ -3948,7 +3970,8 @@ try_to_find_pair:
goto next_candidate;
}
- pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name, sc.name);
+ pr_debug("Reusing \"%s\" BPF sys_enter augmenter for \"%s\"\n", pair->name,
+ sc->name);
return pair_prog;
next_candidate:
continue;
@@ -4044,11 +4067,7 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_m
pair_prog = trace__find_usable_bpf_prog_entry(trace, sc);
if (pair_prog == NULL)
continue;
- /*
- * Get syscall info again as find usable entry above might
- * modify the syscall table and shuffle it.
- */
- sc = trace__syscall_info(trace, NULL, e_machine, key);
+
sc->bpf_prog.sys_enter = pair_prog;
/*
@@ -5316,7 +5335,7 @@ static void trace__exit(struct trace *trace)
zfree(&trace->ev_qualifier_ids.entries);
if (trace->syscalls.table) {
for (size_t i = 0; i < trace->syscalls.table_size; i++)
- syscall__exit(&trace->syscalls.table[i]);
+ syscall__delete(trace->syscalls.table[i]);
zfree(&trace->syscalls.table);
}
zfree(&trace->perfconfig_events);