mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
perf addr_location: Add init/exit/copy functions
struct addr_location holds references to multiple reference counted objects. Add init/exit functions to make maintenance of those more consistent with the rest of the code and to try to avoid leaks. Modification of thread reference counts isn't included in this change. Committer notes: I needed to initialize result to sample->ip to make sure is set to something, fixing a compile time error, mostly keeping the previous logic as build_alloc_func_list() already does debugging/error prints about what went wrong if it takes the 'goto out'. Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ali Saidi <alisaidi@amazon.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com> Cc: Brian Robbins <brianrob@linux.microsoft.com> Cc: Changbin Du <changbin.du@huawei.com> Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Fangrui Song <maskray@google.com> Cc: German Gomez <german.gomez@arm.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Ivan Babrou <ivan@cloudflare.com> Cc: James Clark <james.clark@arm.com> Cc: Jing Zhang <renyu.zj@linux.alibaba.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: John Garry <john.g.garry@oracle.com> Cc: K Prateek Nayak <kprateek.nayak@amd.com> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Leo Yan <leo.yan@linaro.org> Cc: Liam Howlett <liam.howlett@oracle.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Miguel Ojeda <ojeda@kernel.org> Cc: Mike Leach <mike.leach@linaro.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Cc: Sean Christopherson <seanjc@google.com> Cc: Steinar H. Gunderson <sesse@google.com> Cc: Suzuki Poulouse <suzuki.poulose@arm.com> Cc: Wenyu Liu <liuwenyu7@huawei.com> Cc: Will Deacon <will@kernel.org> Cc: Yang Jihong <yangjihong1@huawei.com> Cc: Ye Xingchen <ye.xingchen@zte.com.cn> Cc: Yuan Can <yuancan@huawei.com> Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20230608232823.4027869-7-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
committed by
Arnaldo Carvalho de Melo
parent
620be847f4
commit
0dd5041c9a
@@ -184,7 +184,7 @@ out:
|
||||
|
||||
static int process_branch_callback(struct evsel *evsel,
|
||||
struct perf_sample *sample,
|
||||
struct addr_location *al __maybe_unused,
|
||||
struct addr_location *al,
|
||||
struct perf_annotate *ann,
|
||||
struct machine *machine)
|
||||
{
|
||||
@@ -195,21 +195,29 @@ static int process_branch_callback(struct evsel *evsel,
|
||||
.hide_unresolved = symbol_conf.hide_unresolved,
|
||||
.ops = &hist_iter_branch,
|
||||
};
|
||||
|
||||
struct addr_location a;
|
||||
int ret;
|
||||
|
||||
if (machine__resolve(machine, &a, sample) < 0)
|
||||
return -1;
|
||||
addr_location__init(&a);
|
||||
if (machine__resolve(machine, &a, sample) < 0) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (a.sym == NULL)
|
||||
return 0;
|
||||
if (a.sym == NULL) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (a.map != NULL)
|
||||
map__dso(a.map)->hit = 1;
|
||||
|
||||
hist__account_cycles(sample->branch_stack, al, sample, false, NULL);
|
||||
|
||||
return hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann);
|
||||
ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann);
|
||||
out:
|
||||
addr_location__exit(&a);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool has_annotation(struct perf_annotate *ann)
|
||||
@@ -272,10 +280,12 @@ static int process_sample_event(struct perf_tool *tool,
|
||||
struct addr_location al;
|
||||
int ret = 0;
|
||||
|
||||
addr_location__init(&al);
|
||||
if (machine__resolve(machine, &al, sample) < 0) {
|
||||
pr_warning("problem processing %d event, skipping it.\n",
|
||||
event->header.type);
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
|
||||
@@ -288,7 +298,7 @@ static int process_sample_event(struct perf_tool *tool,
|
||||
ret = -1;
|
||||
}
|
||||
out_put:
|
||||
addr_location__put(&al);
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -286,10 +286,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
|
||||
struct mem_info *mi, *mi_dup;
|
||||
int ret;
|
||||
|
||||
addr_location__init(&al);
|
||||
if (machine__resolve(machine, &al, sample) < 0) {
|
||||
pr_debug("problem processing %d event, skipping it.\n",
|
||||
event->header.type);
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c2c.stitch_lbr)
|
||||
@@ -301,8 +303,10 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
|
||||
goto out;
|
||||
|
||||
mi = sample__resolve_mem(sample, &al);
|
||||
if (mi == NULL)
|
||||
return -ENOMEM;
|
||||
if (mi == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* The mi object is released in hists__add_entry_ops,
|
||||
@@ -368,7 +372,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
|
||||
}
|
||||
|
||||
out:
|
||||
addr_location__put(&al);
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
|
||||
free_mi:
|
||||
|
||||
@@ -409,15 +409,17 @@ static int diff__process_sample_event(struct perf_tool *tool,
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr_location__init(&al);
|
||||
if (machine__resolve(machine, &al, sample) < 0) {
|
||||
pr_warning("problem processing %d event, skipping it.\n",
|
||||
event->header.type);
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) {
|
||||
ret = 0;
|
||||
goto out_put;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (compute) {
|
||||
@@ -426,7 +428,7 @@ static int diff__process_sample_event(struct perf_tool *tool,
|
||||
NULL, NULL, NULL, sample, true)) {
|
||||
pr_warning("problem incrementing symbol period, "
|
||||
"skipping event\n");
|
||||
goto out_put;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hist__account_cycles(sample->branch_stack, &al, sample, false,
|
||||
@@ -437,7 +439,7 @@ static int diff__process_sample_event(struct perf_tool *tool,
|
||||
if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH,
|
||||
NULL)) {
|
||||
pr_debug("problem adding hist entry, skipping event\n");
|
||||
goto out_put;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -446,7 +448,7 @@ static int diff__process_sample_event(struct perf_tool *tool,
|
||||
true)) {
|
||||
pr_warning("problem incrementing symbol period, "
|
||||
"skipping event\n");
|
||||
goto out_put;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,8 +462,8 @@ static int diff__process_sample_event(struct perf_tool *tool,
|
||||
if (!al.filtered)
|
||||
hists->stats.total_non_filtered_period += sample->period;
|
||||
ret = 0;
|
||||
out_put:
|
||||
addr_location__put(&al);
|
||||
out:
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -743,6 +743,7 @@ int perf_event__inject_buildid(struct perf_tool *tool, union perf_event *event,
|
||||
struct addr_location al;
|
||||
struct thread *thread;
|
||||
|
||||
addr_location__init(&al);
|
||||
thread = machine__findnew_thread(machine, sample->pid, sample->tid);
|
||||
if (thread == NULL) {
|
||||
pr_err("problem processing %d event, skipping it.\n",
|
||||
@@ -763,6 +764,7 @@ int perf_event__inject_buildid(struct perf_tool *tool, union perf_event *event,
|
||||
thread__put(thread);
|
||||
repipe:
|
||||
perf_event__repipe(tool, event, sample, machine);
|
||||
addr_location__exit(&al);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -399,7 +399,9 @@ static u64 find_callsite(struct evsel *evsel, struct perf_sample *sample)
|
||||
struct addr_location al;
|
||||
struct machine *machine = &kmem_session->machines.host;
|
||||
struct callchain_cursor_node *node;
|
||||
u64 result = sample->ip;
|
||||
|
||||
addr_location__init(&al);
|
||||
if (alloc_func_list == NULL) {
|
||||
if (build_alloc_func_list() < 0)
|
||||
goto out;
|
||||
@@ -427,16 +429,18 @@ static u64 find_callsite(struct evsel *evsel, struct perf_sample *sample)
|
||||
else
|
||||
addr = node->ip;
|
||||
|
||||
return addr;
|
||||
result = addr;
|
||||
goto out;
|
||||
} else
|
||||
pr_debug3("skipping alloc function: %s\n", caller->name);
|
||||
|
||||
callchain_cursor_advance(&callchain_cursor);
|
||||
}
|
||||
|
||||
out:
|
||||
pr_debug2("unknown callsite: %"PRIx64 "\n", sample->ip);
|
||||
return sample->ip;
|
||||
out:
|
||||
addr_location__exit(&al);
|
||||
return result;
|
||||
}
|
||||
|
||||
struct sort_dimension {
|
||||
|
||||
@@ -739,17 +739,22 @@ static int timehist_exit_event(struct perf_kwork *kwork,
|
||||
struct kwork_atom *atom = NULL;
|
||||
struct kwork_work *work = NULL;
|
||||
struct addr_location al;
|
||||
int ret = 0;
|
||||
|
||||
addr_location__init(&al);
|
||||
if (machine__resolve(machine, &al, sample) < 0) {
|
||||
pr_debug("Problem processing event, skipping it\n");
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT,
|
||||
KWORK_TRACE_ENTRY, evsel, sample,
|
||||
machine, &work);
|
||||
if (work == NULL)
|
||||
return -1;
|
||||
if (work == NULL) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (atom != NULL) {
|
||||
work->nr_atoms++;
|
||||
@@ -757,7 +762,9 @@ static int timehist_exit_event(struct perf_kwork *kwork,
|
||||
atom_del(atom);
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct kwork_class kwork_irq;
|
||||
|
||||
@@ -199,9 +199,11 @@ dump_raw_samples(struct perf_tool *tool,
|
||||
char str[PAGE_SIZE_NAME_LEN];
|
||||
struct dso *dso = NULL;
|
||||
|
||||
addr_location__init(&al);
|
||||
if (machine__resolve(machine, &al, sample) < 0) {
|
||||
fprintf(stderr, "problem processing %d event, skipping it.\n",
|
||||
event->header.type);
|
||||
addr_location__exit(&al);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -256,7 +258,7 @@ dump_raw_samples(struct perf_tool *tool,
|
||||
dso ? dso->long_name : "???",
|
||||
al.sym ? al.sym->name : "???");
|
||||
out_put:
|
||||
addr_location__put(&al);
|
||||
addr_location__exit(&al);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -285,10 +285,12 @@ static int process_sample_event(struct perf_tool *tool,
|
||||
if (evswitch__discard(&rep->evswitch, evsel))
|
||||
return 0;
|
||||
|
||||
addr_location__init(&al);
|
||||
if (machine__resolve(machine, &al, sample) < 0) {
|
||||
pr_debug("problem processing %d event, skipping it.\n",
|
||||
event->header.type);
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
if (rep->stitch_lbr)
|
||||
@@ -331,7 +333,7 @@ static int process_sample_event(struct perf_tool *tool,
|
||||
if (ret < 0)
|
||||
pr_debug("problem adding hist entry, skipping event\n");
|
||||
out_put:
|
||||
addr_location__put(&al);
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -2584,6 +2584,7 @@ static int timehist_sched_change_event(struct perf_tool *tool,
|
||||
int rc = 0;
|
||||
int state = evsel__intval(evsel, sample, "prev_state");
|
||||
|
||||
addr_location__init(&al);
|
||||
if (machine__resolve(machine, &al, sample) < 0) {
|
||||
pr_err("problem processing %d event. skipping it\n",
|
||||
event->header.type);
|
||||
@@ -2692,6 +2693,7 @@ out:
|
||||
|
||||
evsel__save_time(evsel, sample->time, sample->cpu);
|
||||
|
||||
addr_location__exit(&al);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -919,7 +919,6 @@ static int perf_sample__fprintf_brstack(struct perf_sample *sample,
|
||||
{
|
||||
struct branch_stack *br = sample->branch_stack;
|
||||
struct branch_entry *entries = perf_sample__branch_entries(sample);
|
||||
struct addr_location alf, alt;
|
||||
u64 i, from, to;
|
||||
int printed = 0;
|
||||
|
||||
@@ -930,20 +929,22 @@ static int perf_sample__fprintf_brstack(struct perf_sample *sample,
|
||||
from = entries[i].from;
|
||||
to = entries[i].to;
|
||||
|
||||
printed += fprintf(fp, " 0x%"PRIx64, from);
|
||||
if (PRINT_FIELD(DSO)) {
|
||||
memset(&alf, 0, sizeof(alf));
|
||||
memset(&alt, 0, sizeof(alt));
|
||||
struct addr_location alf, alt;
|
||||
|
||||
addr_location__init(&alf);
|
||||
addr_location__init(&alt);
|
||||
thread__find_map_fb(thread, sample->cpumode, from, &alf);
|
||||
thread__find_map_fb(thread, sample->cpumode, to, &alt);
|
||||
}
|
||||
|
||||
printed += fprintf(fp, " 0x%"PRIx64, from);
|
||||
if (PRINT_FIELD(DSO))
|
||||
printed += map__fprintf_dsoname_dsoff(alf.map, PRINT_FIELD(DSOFF), alf.addr, fp);
|
||||
|
||||
printed += fprintf(fp, "/0x%"PRIx64, to);
|
||||
if (PRINT_FIELD(DSO))
|
||||
printed += fprintf(fp, "/0x%"PRIx64, to);
|
||||
printed += map__fprintf_dsoname_dsoff(alt.map, PRINT_FIELD(DSOFF), alt.addr, fp);
|
||||
addr_location__exit(&alt);
|
||||
addr_location__exit(&alf);
|
||||
} else
|
||||
printed += fprintf(fp, "/0x%"PRIx64, to);
|
||||
|
||||
printed += print_bstack_flags(fp, entries + i);
|
||||
}
|
||||
@@ -957,7 +958,6 @@ static int perf_sample__fprintf_brstacksym(struct perf_sample *sample,
|
||||
{
|
||||
struct branch_stack *br = sample->branch_stack;
|
||||
struct branch_entry *entries = perf_sample__branch_entries(sample);
|
||||
struct addr_location alf, alt;
|
||||
u64 i, from, to;
|
||||
int printed = 0;
|
||||
|
||||
@@ -965,9 +965,10 @@ static int perf_sample__fprintf_brstacksym(struct perf_sample *sample,
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < br->nr; i++) {
|
||||
struct addr_location alf, alt;
|
||||
|
||||
memset(&alf, 0, sizeof(alf));
|
||||
memset(&alt, 0, sizeof(alt));
|
||||
addr_location__init(&alf);
|
||||
addr_location__init(&alt);
|
||||
from = entries[i].from;
|
||||
to = entries[i].to;
|
||||
|
||||
@@ -982,6 +983,8 @@ static int perf_sample__fprintf_brstacksym(struct perf_sample *sample,
|
||||
if (PRINT_FIELD(DSO))
|
||||
printed += map__fprintf_dsoname_dsoff(alt.map, PRINT_FIELD(DSOFF), alt.addr, fp);
|
||||
printed += print_bstack_flags(fp, entries + i);
|
||||
addr_location__exit(&alt);
|
||||
addr_location__exit(&alf);
|
||||
}
|
||||
|
||||
return printed;
|
||||
@@ -993,7 +996,6 @@ static int perf_sample__fprintf_brstackoff(struct perf_sample *sample,
|
||||
{
|
||||
struct branch_stack *br = sample->branch_stack;
|
||||
struct branch_entry *entries = perf_sample__branch_entries(sample);
|
||||
struct addr_location alf, alt;
|
||||
u64 i, from, to;
|
||||
int printed = 0;
|
||||
|
||||
@@ -1001,9 +1003,10 @@ static int perf_sample__fprintf_brstackoff(struct perf_sample *sample,
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < br->nr; i++) {
|
||||
struct addr_location alf, alt;
|
||||
|
||||
memset(&alf, 0, sizeof(alf));
|
||||
memset(&alt, 0, sizeof(alt));
|
||||
addr_location__init(&alf);
|
||||
addr_location__init(&alt);
|
||||
from = entries[i].from;
|
||||
to = entries[i].to;
|
||||
|
||||
@@ -1022,6 +1025,8 @@ static int perf_sample__fprintf_brstackoff(struct perf_sample *sample,
|
||||
if (PRINT_FIELD(DSO))
|
||||
printed += map__fprintf_dsoname_dsoff(alt.map, PRINT_FIELD(DSOFF), alt.addr, fp);
|
||||
printed += print_bstack_flags(fp, entries + i);
|
||||
addr_location__exit(&alt);
|
||||
addr_location__exit(&alf);
|
||||
}
|
||||
|
||||
return printed;
|
||||
@@ -1036,6 +1041,7 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,
|
||||
struct addr_location al;
|
||||
bool kernel;
|
||||
struct dso *dso;
|
||||
int ret = 0;
|
||||
|
||||
if (!start || !end)
|
||||
return 0;
|
||||
@@ -1057,7 +1063,6 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
memset(&al, 0, sizeof(al));
|
||||
if (end - start > MAXBB - MAXINSN) {
|
||||
if (last)
|
||||
pr_debug("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end);
|
||||
@@ -1066,13 +1071,14 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr_location__init(&al);
|
||||
if (!thread__find_map(thread, *cpumode, start, &al) || (dso = map__dso(al.map)) == NULL) {
|
||||
pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
if (dso->data.status == DSO_DATA_STATUS_ERROR) {
|
||||
pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Load maps to ensure dso->is_64_bit has been updated */
|
||||
@@ -1086,7 +1092,10 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,
|
||||
if (len <= 0)
|
||||
pr_debug("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n",
|
||||
start, end);
|
||||
return len;
|
||||
ret = len;
|
||||
out:
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int map__fprintf_srccode(struct map *map, u64 addr, FILE *fp, struct srccode_state *state)
|
||||
@@ -1137,14 +1146,16 @@ static int print_srccode(struct thread *thread, u8 cpumode, uint64_t addr)
|
||||
struct addr_location al;
|
||||
int ret = 0;
|
||||
|
||||
memset(&al, 0, sizeof(al));
|
||||
addr_location__init(&al);
|
||||
thread__find_map(thread, cpumode, addr, &al);
|
||||
if (!al.map)
|
||||
return 0;
|
||||
goto out;
|
||||
ret = map__fprintf_srccode(al.map, al.addr, stdout,
|
||||
thread__srccode_state(thread));
|
||||
if (ret)
|
||||
ret += printf("\n");
|
||||
out:
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1179,14 +1190,13 @@ static int ip__fprintf_sym(uint64_t addr, struct thread *thread,
|
||||
struct perf_event_attr *attr, FILE *fp)
|
||||
{
|
||||
struct addr_location al;
|
||||
int off, printed = 0;
|
||||
|
||||
memset(&al, 0, sizeof(al));
|
||||
int off, printed = 0, ret = 0;
|
||||
|
||||
addr_location__init(&al);
|
||||
thread__find_map(thread, cpumode, addr, &al);
|
||||
|
||||
if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end)
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
al.cpu = cpu;
|
||||
al.sym = NULL;
|
||||
@@ -1194,7 +1204,7 @@ static int ip__fprintf_sym(uint64_t addr, struct thread *thread,
|
||||
al.sym = map__find_symbol(al.map, al.addr);
|
||||
|
||||
if (!al.sym)
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
if (al.addr < al.sym->end)
|
||||
off = al.addr - al.sym->start;
|
||||
@@ -1209,7 +1219,10 @@ static int ip__fprintf_sym(uint64_t addr, struct thread *thread,
|
||||
printed += fprintf(fp, "\n");
|
||||
*lastsym = al.sym;
|
||||
|
||||
return printed;
|
||||
ret = printed;
|
||||
out:
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
|
||||
@@ -1371,6 +1384,7 @@ static int perf_sample__fprintf_addr(struct perf_sample *sample,
|
||||
struct addr_location al;
|
||||
int printed = fprintf(fp, "%16" PRIx64, sample->addr);
|
||||
|
||||
addr_location__init(&al);
|
||||
if (!sample_addr_correlates_sym(attr))
|
||||
goto out;
|
||||
|
||||
@@ -1387,6 +1401,7 @@ static int perf_sample__fprintf_addr(struct perf_sample *sample,
|
||||
if (PRINT_FIELD(DSO))
|
||||
printed += map__fprintf_dsoname_dsoff(al.map, PRINT_FIELD(DSOFF), al.addr, fp);
|
||||
out:
|
||||
addr_location__exit(&al);
|
||||
return printed;
|
||||
}
|
||||
|
||||
@@ -2338,8 +2353,8 @@ static int process_sample_event(struct perf_tool *tool,
|
||||
int ret = 0;
|
||||
|
||||
/* Set thread to NULL to indicate addr_al and al are not initialized */
|
||||
addr_al.thread = NULL;
|
||||
al.thread = NULL;
|
||||
addr_location__init(&al);
|
||||
addr_location__init(&addr_al);
|
||||
|
||||
ret = dlfilter__filter_event_early(dlfilter, event, sample, evsel, machine, &al, &addr_al);
|
||||
if (ret) {
|
||||
@@ -2405,8 +2420,8 @@ static int process_sample_event(struct perf_tool *tool,
|
||||
}
|
||||
|
||||
out_put:
|
||||
if (al.thread)
|
||||
addr_location__put(&al);
|
||||
addr_location__exit(&addr_al);
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -498,7 +498,6 @@ static const char *cat_backtrace(union perf_event *event,
|
||||
char *p = NULL;
|
||||
size_t p_len;
|
||||
u8 cpumode = PERF_RECORD_MISC_USER;
|
||||
struct addr_location tal;
|
||||
struct ip_callchain *chain = sample->callchain;
|
||||
FILE *f = open_memstream(&p, &p_len);
|
||||
|
||||
@@ -507,6 +506,7 @@ static const char *cat_backtrace(union perf_event *event,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
addr_location__init(&al);
|
||||
if (!chain)
|
||||
goto exit;
|
||||
|
||||
@@ -518,6 +518,7 @@ static const char *cat_backtrace(union perf_event *event,
|
||||
|
||||
for (i = 0; i < chain->nr; i++) {
|
||||
u64 ip;
|
||||
struct addr_location tal;
|
||||
|
||||
if (callchain_param.order == ORDER_CALLEE)
|
||||
ip = chain->ips[i];
|
||||
@@ -544,20 +545,22 @@ static const char *cat_backtrace(union perf_event *event,
|
||||
* Discard all.
|
||||
*/
|
||||
zfree(&p);
|
||||
goto exit_put;
|
||||
goto exit;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
addr_location__init(&tal);
|
||||
tal.filtered = 0;
|
||||
if (thread__find_symbol(al.thread, cpumode, ip, &tal))
|
||||
fprintf(f, "..... %016" PRIx64 " %s\n", ip, tal.sym->name);
|
||||
else
|
||||
fprintf(f, "..... %016" PRIx64 "\n", ip);
|
||||
|
||||
addr_location__exit(&tal);
|
||||
}
|
||||
exit_put:
|
||||
addr_location__put(&al);
|
||||
exit:
|
||||
addr_location__exit(&al);
|
||||
fclose(f);
|
||||
|
||||
return p;
|
||||
|
||||
@@ -773,8 +773,9 @@ static void perf_event__process_sample(struct perf_tool *tool,
|
||||
if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
|
||||
top->exact_samples++;
|
||||
|
||||
addr_location__init(&al);
|
||||
if (machine__resolve(machine, &al, sample) < 0)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
if (top->stitch_lbr)
|
||||
thread__set_lbr_stitch_enable(al.thread, true);
|
||||
@@ -848,7 +849,8 @@ static void perf_event__process_sample(struct perf_tool *tool,
|
||||
mutex_unlock(&hists->lock);
|
||||
}
|
||||
|
||||
addr_location__put(&al);
|
||||
out:
|
||||
addr_location__exit(&al);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -2418,13 +2418,15 @@ static int trace__resolve_callchain(struct trace *trace, struct evsel *evsel,
|
||||
int max_stack = evsel->core.attr.sample_max_stack ?
|
||||
evsel->core.attr.sample_max_stack :
|
||||
trace->max_stack;
|
||||
int err;
|
||||
int err = -1;
|
||||
|
||||
addr_location__init(&al);
|
||||
if (machine__resolve(trace->host, &al, sample) < 0)
|
||||
return -1;
|
||||
goto out;
|
||||
|
||||
err = thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, max_stack);
|
||||
addr_location__put(&al);
|
||||
out:
|
||||
addr_location__exit(&al);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -2893,6 +2895,7 @@ static int trace__pgfault(struct trace *trace,
|
||||
int err = -1;
|
||||
int callchain_ret = 0;
|
||||
|
||||
addr_location__init(&al);
|
||||
thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
|
||||
|
||||
if (sample->callchain) {
|
||||
@@ -2953,6 +2956,7 @@ out:
|
||||
err = 0;
|
||||
out_put:
|
||||
thread__put(thread);
|
||||
addr_location__exit(&al);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -241,6 +241,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
|
||||
|
||||
pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
|
||||
|
||||
addr_location__init(&al);
|
||||
if (!thread__find_map(thread, cpumode, addr, &al) || !map__dso(al.map)) {
|
||||
if (cpumode == PERF_RECORD_MISC_HYPERVISOR) {
|
||||
pr_debug("Hypervisor address can not be resolved - skipping\n");
|
||||
@@ -366,7 +367,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
|
||||
}
|
||||
pr_debug("Bytes read match those read by objdump\n");
|
||||
out:
|
||||
map__put(al.map);
|
||||
addr_location__exit(&al);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#include "util/evsel.h"
|
||||
#include "util/evlist.h"
|
||||
#include "util/machine.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/parse-events.h"
|
||||
#include "util/thread.h"
|
||||
#include "tests/tests.h"
|
||||
#include "tests/hists_common.h"
|
||||
#include <linux/kernel.h>
|
||||
@@ -84,6 +84,7 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
|
||||
struct perf_sample sample = { .period = 1000, };
|
||||
size_t i;
|
||||
|
||||
addr_location__init(&al);
|
||||
for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
|
||||
struct hist_entry_iter iter = {
|
||||
.evsel = evsel,
|
||||
@@ -107,20 +108,22 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
|
||||
|
||||
if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack,
|
||||
NULL) < 0) {
|
||||
addr_location__put(&al);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fake_samples[i].thread = al.thread;
|
||||
thread__put(fake_samples[i].thread);
|
||||
fake_samples[i].thread = thread__get(al.thread);
|
||||
map__put(fake_samples[i].map);
|
||||
fake_samples[i].map = al.map;
|
||||
fake_samples[i].map = map__get(al.map);
|
||||
fake_samples[i].sym = al.sym;
|
||||
}
|
||||
|
||||
addr_location__exit(&al);
|
||||
return TEST_OK;
|
||||
|
||||
out:
|
||||
pr_debug("Not enough memory for adding a hist entry\n");
|
||||
addr_location__exit(&al);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
@@ -152,8 +155,10 @@ static void put_fake_samples(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fake_samples); i++)
|
||||
map__put(fake_samples[i].map);
|
||||
for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
|
||||
map__zput(fake_samples[i].map);
|
||||
thread__zput(fake_samples[i].thread);
|
||||
}
|
||||
}
|
||||
|
||||
typedef int (*test_fn_t)(struct evsel *, struct machine *);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "util/evlist.h"
|
||||
#include "util/machine.h"
|
||||
#include "util/parse-events.h"
|
||||
#include "util/thread.h"
|
||||
#include "tests/tests.h"
|
||||
#include "tests/hists_common.h"
|
||||
#include <linux/kernel.h>
|
||||
@@ -53,6 +54,7 @@ static int add_hist_entries(struct evlist *evlist,
|
||||
struct perf_sample sample = { .period = 100, };
|
||||
size_t i;
|
||||
|
||||
addr_location__init(&al);
|
||||
/*
|
||||
* each evsel will have 10 samples but the 4th sample
|
||||
* (perf [perf] main) will be collapsed to an existing entry
|
||||
@@ -84,21 +86,22 @@ static int add_hist_entries(struct evlist *evlist,
|
||||
al.socket = fake_samples[i].socket;
|
||||
if (hist_entry_iter__add(&iter, &al,
|
||||
sysctl_perf_event_max_stack, NULL) < 0) {
|
||||
addr_location__put(&al);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fake_samples[i].thread = al.thread;
|
||||
thread__put(fake_samples[i].thread);
|
||||
fake_samples[i].thread = thread__get(al.thread);
|
||||
map__put(fake_samples[i].map);
|
||||
fake_samples[i].map = al.map;
|
||||
fake_samples[i].map = map__get(al.map);
|
||||
fake_samples[i].sym = al.sym;
|
||||
}
|
||||
}
|
||||
|
||||
addr_location__exit(&al);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
pr_debug("Not enough memory for adding a hist entry\n");
|
||||
addr_location__exit(&al);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "machine.h"
|
||||
#include "map.h"
|
||||
#include "parse-events.h"
|
||||
#include "thread.h"
|
||||
#include "hists_common.h"
|
||||
#include "util/mmap.h"
|
||||
#include <errno.h>
|
||||
@@ -70,6 +71,7 @@ static int add_hist_entries(struct evlist *evlist, struct machine *machine)
|
||||
struct perf_sample sample = { .period = 1, .weight = 1, };
|
||||
size_t i = 0, k;
|
||||
|
||||
addr_location__init(&al);
|
||||
/*
|
||||
* each evsel will have 10 samples - 5 common and 5 distinct.
|
||||
* However the second evsel also has a collapsed entry for
|
||||
@@ -90,13 +92,13 @@ static int add_hist_entries(struct evlist *evlist, struct machine *machine)
|
||||
he = hists__add_entry(hists, &al, NULL,
|
||||
NULL, NULL, NULL, &sample, true);
|
||||
if (he == NULL) {
|
||||
addr_location__put(&al);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fake_common_samples[k].thread = al.thread;
|
||||
thread__put(fake_common_samples[k].thread);
|
||||
fake_common_samples[k].thread = thread__get(al.thread);
|
||||
map__put(fake_common_samples[k].map);
|
||||
fake_common_samples[k].map = al.map;
|
||||
fake_common_samples[k].map = map__get(al.map);
|
||||
fake_common_samples[k].sym = al.sym;
|
||||
}
|
||||
|
||||
@@ -110,20 +112,22 @@ static int add_hist_entries(struct evlist *evlist, struct machine *machine)
|
||||
he = hists__add_entry(hists, &al, NULL,
|
||||
NULL, NULL, NULL, &sample, true);
|
||||
if (he == NULL) {
|
||||
addr_location__put(&al);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fake_samples[i][k].thread = al.thread;
|
||||
fake_samples[i][k].map = al.map;
|
||||
thread__put(fake_samples[i][k].thread);
|
||||
fake_samples[i][k].thread = thread__get(al.thread);
|
||||
map__put(fake_samples[i][k].map);
|
||||
fake_samples[i][k].map = map__get(al.map);
|
||||
fake_samples[i][k].sym = al.sym;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
addr_location__exit(&al);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
addr_location__exit(&al);
|
||||
pr_debug("Not enough memory for adding a hist entry\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
|
||||
struct perf_sample sample = { .period = 100, };
|
||||
size_t i;
|
||||
|
||||
addr_location__init(&al);
|
||||
for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
|
||||
struct hist_entry_iter iter = {
|
||||
.evsel = evsel,
|
||||
@@ -73,20 +74,21 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
|
||||
|
||||
if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack,
|
||||
NULL) < 0) {
|
||||
addr_location__put(&al);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fake_samples[i].thread = al.thread;
|
||||
map__put(fake_samples[i].map);
|
||||
fake_samples[i].map = al.map;
|
||||
fake_samples[i].map = map__get(al.map);
|
||||
fake_samples[i].sym = al.sym;
|
||||
}
|
||||
|
||||
addr_location__exit(&al);
|
||||
return TEST_OK;
|
||||
|
||||
out:
|
||||
pr_debug("Not enough memory for adding a hist entry\n");
|
||||
addr_location__exit(&al);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
@@ -118,8 +120,10 @@ static void put_fake_samples(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fake_samples); i++)
|
||||
for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
|
||||
map__put(fake_samples[i].map);
|
||||
fake_samples[i].map = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
typedef int (*test_fn_t)(struct evsel *, struct machine *);
|
||||
|
||||
@@ -187,6 +187,7 @@ static int mmap_events(synth_cb synth)
|
||||
struct addr_location al;
|
||||
struct thread *thread;
|
||||
|
||||
addr_location__init(&al);
|
||||
thread = machine__findnew_thread(machine, getpid(), td->tid);
|
||||
|
||||
pr_debug("looking for map %p\n", td->map);
|
||||
@@ -199,11 +200,12 @@ static int mmap_events(synth_cb synth)
|
||||
if (!al.map) {
|
||||
pr_debug("failed, couldn't find map\n");
|
||||
err = -1;
|
||||
addr_location__exit(&al);
|
||||
break;
|
||||
}
|
||||
|
||||
pr_debug("map %p, addr %" PRIx64 "\n", al.map, map__start(al.map));
|
||||
map__put(al.map);
|
||||
addr_location__exit(&al);
|
||||
}
|
||||
|
||||
machine__delete_threads(machine);
|
||||
|
||||
@@ -1,16 +1,44 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "addr_location.h"
|
||||
#include "map.h"
|
||||
#include "maps.h"
|
||||
#include "thread.h"
|
||||
|
||||
void addr_location__init(struct addr_location *al)
|
||||
{
|
||||
al->thread = NULL;
|
||||
al->maps = NULL;
|
||||
al->map = NULL;
|
||||
al->sym = NULL;
|
||||
al->srcline = NULL;
|
||||
al->addr = 0;
|
||||
al->level = 0;
|
||||
al->filtered = 0;
|
||||
al->cpumode = 0;
|
||||
al->cpu = 0;
|
||||
al->socket = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The preprocess_sample method will return with reference counts for the
|
||||
* in it, when done using (and perhaps getting ref counts if needing to
|
||||
* keep a pointer to one of those entries) it must be paired with
|
||||
* addr_location__put(), so that the refcounts can be decremented.
|
||||
*/
|
||||
void addr_location__put(struct addr_location *al)
|
||||
void addr_location__exit(struct addr_location *al)
|
||||
{
|
||||
map__zput(al->map);
|
||||
thread__zput(al->thread);
|
||||
maps__zput(al->maps);
|
||||
}
|
||||
|
||||
void addr_location__copy(struct addr_location *dst, struct addr_location *src)
|
||||
{
|
||||
thread__put(dst->thread);
|
||||
maps__put(dst->maps);
|
||||
map__put(dst->map);
|
||||
*dst = *src;
|
||||
dst->thread = thread__get(src->thread);
|
||||
dst->maps = maps__get(src->maps);
|
||||
dst->map = map__get(src->map);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user