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:
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);
|
||||
}
|
||||
|
@ -23,6 +23,9 @@ struct addr_location {
|
||||
s32 socket;
|
||||
};
|
||||
|
||||
void addr_location__put(struct addr_location *al);
|
||||
void addr_location__init(struct addr_location *al);
|
||||
void addr_location__exit(struct addr_location *al);
|
||||
|
||||
void addr_location__copy(struct addr_location *dst, struct addr_location *src);
|
||||
|
||||
#endif /* __PERF_ADDR_LOCATION */
|
||||
|
@ -58,9 +58,11 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr_location__init(&al);
|
||||
if (thread__find_map(thread, sample->cpumode, sample->ip, &al))
|
||||
map__dso(al.map)->hit = 1;
|
||||
|
||||
addr_location__exit(&al);
|
||||
thread__put(thread);
|
||||
return 0;
|
||||
}
|
||||
|
@ -910,33 +910,35 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id,
|
||||
struct addr_location al;
|
||||
struct dso *dso;
|
||||
struct cs_etm_traceid_queue *tidq;
|
||||
int ret = 0;
|
||||
|
||||
if (!etmq)
|
||||
return 0;
|
||||
|
||||
addr_location__init(&al);
|
||||
machine = etmq->etm->machine;
|
||||
cpumode = cs_etm__cpu_mode(etmq, address);
|
||||
tidq = cs_etm__etmq_get_traceid_queue(etmq, trace_chan_id);
|
||||
if (!tidq)
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
thread = tidq->thread;
|
||||
if (!thread) {
|
||||
if (cpumode != PERF_RECORD_MISC_KERNEL)
|
||||
return 0;
|
||||
goto out;
|
||||
thread = etmq->etm->unknown_thread;
|
||||
}
|
||||
|
||||
if (!thread__find_map(thread, cpumode, address, &al))
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
dso = map__dso(al.map);
|
||||
if (!dso)
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
if (dso->data.status == DSO_DATA_STATUS_ERROR &&
|
||||
dso__data_status_seen(dso, DSO_DATA_STATUS_SEEN_ITRACE))
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
offset = map__map_ip(al.map, address);
|
||||
|
||||
@ -953,10 +955,12 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id,
|
||||
dso->long_name ? dso->long_name : "Unknown");
|
||||
dso->auxtrace_warned = true;
|
||||
}
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return len;
|
||||
ret = len;
|
||||
out:
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
|
||||
|
@ -154,12 +154,14 @@ static int process_sample_event(struct perf_tool *tool,
|
||||
{
|
||||
struct convert_json *c = container_of(tool, struct convert_json, tool);
|
||||
FILE *out = c->out;
|
||||
struct addr_location al, tal;
|
||||
struct addr_location al;
|
||||
u64 sample_type = __evlist__combined_sample_type(evsel->evlist);
|
||||
u8 cpumode = PERF_RECORD_MISC_USER;
|
||||
|
||||
addr_location__init(&al);
|
||||
if (machine__resolve(machine, &al, sample) < 0) {
|
||||
pr_err("Sample resolution failed!\n");
|
||||
addr_location__exit(&al);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -190,6 +192,7 @@ static int process_sample_event(struct perf_tool *tool,
|
||||
|
||||
for (i = 0; i < sample->callchain->nr; ++i) {
|
||||
u64 ip = sample->callchain->ips[i];
|
||||
struct addr_location tal;
|
||||
|
||||
if (ip >= PERF_CONTEXT_MAX) {
|
||||
switch (ip) {
|
||||
@ -215,8 +218,10 @@ static int process_sample_event(struct perf_tool *tool,
|
||||
else
|
||||
fputc(',', out);
|
||||
|
||||
addr_location__init(&tal);
|
||||
ok = thread__find_symbol(al.thread, cpumode, ip, &tal);
|
||||
output_sample_callchain_entry(tool, ip, ok ? &tal : NULL);
|
||||
addr_location__exit(&tal);
|
||||
}
|
||||
} else {
|
||||
output_sample_callchain_entry(tool, sample->ip, &al);
|
||||
@ -245,6 +250,7 @@ static int process_sample_event(struct perf_tool *tool,
|
||||
}
|
||||
#endif
|
||||
output_json_format(out, false, 2, "}");
|
||||
addr_location__exit(&al);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -239,16 +239,17 @@ static struct call_path *call_path_from_sample(struct db_export *dbe,
|
||||
struct addr_location al;
|
||||
u64 dso_db_id = 0, sym_db_id = 0, offset = 0;
|
||||
|
||||
memset(&al, 0, sizeof(al));
|
||||
|
||||
node = callchain_cursor_current(&callchain_cursor);
|
||||
if (!node)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Handle export of symbol and dso for this node by
|
||||
* constructing an addr_location struct and then passing it to
|
||||
* db_ids_from_al() to perform the export.
|
||||
*/
|
||||
addr_location__init(&al);
|
||||
al.sym = node->ms.sym;
|
||||
al.map = node->ms.map;
|
||||
al.maps = thread__maps(thread);
|
||||
@ -265,6 +266,7 @@ static struct call_path *call_path_from_sample(struct db_export *dbe,
|
||||
kernel_start);
|
||||
|
||||
callchain_cursor_advance(&callchain_cursor);
|
||||
addr_location__exit(&al);
|
||||
}
|
||||
|
||||
/* Reset the callchain order to its prior value. */
|
||||
|
@ -258,6 +258,7 @@ static __s32 dlfilter__object_code(void *ctx, __u64 ip, void *buf, __u32 len)
|
||||
struct addr_location a;
|
||||
struct map *map;
|
||||
u64 offset;
|
||||
__s32 ret;
|
||||
|
||||
if (!d->ctx_valid)
|
||||
return -1;
|
||||
@ -272,16 +273,22 @@ static __s32 dlfilter__object_code(void *ctx, __u64 ip, void *buf, __u32 len)
|
||||
machine__kernel_ip(d->machine, ip) == machine__kernel_ip(d->machine, d->sample->ip))
|
||||
goto have_map;
|
||||
|
||||
addr_location__init(&a);
|
||||
thread__find_map_fb(al->thread, d->sample->cpumode, ip, &a);
|
||||
if (!a.map)
|
||||
return -1;
|
||||
if (!a.map) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
map = a.map;
|
||||
have_map:
|
||||
offset = map__map_ip(map, ip);
|
||||
if (ip + len >= map__end(map))
|
||||
len = map__end(map) - ip;
|
||||
return dso__data_read_offset(map__dso(map), d->machine, offset, buf, len);
|
||||
ret = dso__data_read_offset(map__dso(map), d->machine, offset, buf, len);
|
||||
out:
|
||||
addr_location__exit(&a);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct perf_dlfilter_fns perf_dlfilter_fns = {
|
||||
|
@ -486,6 +486,7 @@ size_t perf_event__fprintf_text_poke(union perf_event *event, struct machine *ma
|
||||
if (machine) {
|
||||
struct addr_location al;
|
||||
|
||||
addr_location__init(&al);
|
||||
al.map = map__get(maps__find(machine__kernel_maps(machine), tp->addr));
|
||||
if (al.map && map__load(al.map) >= 0) {
|
||||
al.addr = map__map_ip(al.map, tp->addr);
|
||||
@ -493,7 +494,7 @@ size_t perf_event__fprintf_text_poke(union perf_event *event, struct machine *ma
|
||||
if (al.sym)
|
||||
ret += symbol__fprintf_symname_offs(al.sym, &al, fp);
|
||||
}
|
||||
map__put(al.map);
|
||||
addr_location__exit(&al);
|
||||
}
|
||||
ret += fprintf(fp, " old len %u new len %u\n", tp->old_len, tp->new_len);
|
||||
old = true;
|
||||
@ -577,8 +578,10 @@ struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
|
||||
struct machine *machine = maps__machine(maps);
|
||||
bool load_map = false;
|
||||
|
||||
al->maps = maps;
|
||||
al->thread = thread;
|
||||
maps__zput(al->maps);
|
||||
map__zput(al->map);
|
||||
thread__zput(al->thread);
|
||||
|
||||
al->addr = addr;
|
||||
al->cpumode = cpumode;
|
||||
al->filtered = 0;
|
||||
@ -590,13 +593,13 @@ struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
|
||||
|
||||
if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
|
||||
al->level = 'k';
|
||||
al->maps = maps = machine__kernel_maps(machine);
|
||||
maps = machine__kernel_maps(machine);
|
||||
load_map = true;
|
||||
} else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
|
||||
al->level = '.';
|
||||
} else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
|
||||
al->level = 'g';
|
||||
al->maps = maps = machine__kernel_maps(machine);
|
||||
maps = machine__kernel_maps(machine);
|
||||
load_map = true;
|
||||
} else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
|
||||
al->level = 'u';
|
||||
@ -615,7 +618,8 @@ struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
al->maps = maps__get(maps);
|
||||
al->thread = thread__get(thread);
|
||||
al->map = map__get(maps__find(maps, al->addr));
|
||||
if (al->map != NULL) {
|
||||
/*
|
||||
|
@ -128,8 +128,6 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
|
||||
bool first = true;
|
||||
|
||||
if (sample->callchain) {
|
||||
struct addr_location node_al;
|
||||
|
||||
callchain_cursor_commit(cursor);
|
||||
|
||||
while (1) {
|
||||
@ -159,9 +157,12 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
|
||||
printed += fprintf(fp, "%c%16" PRIx64, s, node->ip);
|
||||
|
||||
if (print_sym) {
|
||||
struct addr_location node_al;
|
||||
|
||||
addr_location__init(&node_al);
|
||||
printed += fprintf(fp, " ");
|
||||
node_al.addr = addr;
|
||||
node_al.map = map;
|
||||
node_al.map = map__get(map);
|
||||
|
||||
if (print_symoffset) {
|
||||
printed += __symbol__fprintf_symname_offs(sym, &node_al,
|
||||
@ -171,6 +172,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
|
||||
printed += __symbol__fprintf_symname(sym, &node_al,
|
||||
print_unknown_as_addr, fp);
|
||||
}
|
||||
addr_location__exit(&node_al);
|
||||
}
|
||||
|
||||
if (print_dso && (!sym || !sym->inlined))
|
||||
|
@ -588,7 +588,7 @@ static void hist_entry__add_callchain_period(struct hist_entry *he, u64 period)
|
||||
|
||||
static struct hist_entry *hists__findnew_entry(struct hists *hists,
|
||||
struct hist_entry *entry,
|
||||
struct addr_location *al,
|
||||
const struct addr_location *al,
|
||||
bool sample_self)
|
||||
{
|
||||
struct rb_node **p;
|
||||
@ -927,8 +927,10 @@ iter_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *al)
|
||||
if (iter->curr >= iter->total)
|
||||
return 0;
|
||||
|
||||
al->maps = bi[i].to.ms.maps;
|
||||
al->map = bi[i].to.ms.map;
|
||||
maps__put(al->maps);
|
||||
al->maps = maps__get(bi[i].to.ms.maps);
|
||||
map__put(al->map);
|
||||
al->map = map__get(bi[i].to.ms.map);
|
||||
al->sym = bi[i].to.ms.sym;
|
||||
al->addr = bi[i].to.addr;
|
||||
return 1;
|
||||
|
@ -754,13 +754,15 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
|
||||
struct addr_location al;
|
||||
unsigned char buf[INTEL_PT_INSN_BUF_SZ];
|
||||
ssize_t len;
|
||||
int x86_64;
|
||||
int x86_64, ret = 0;
|
||||
u8 cpumode;
|
||||
u64 offset, start_offset, start_ip;
|
||||
u64 insn_cnt = 0;
|
||||
bool one_map = true;
|
||||
bool nr;
|
||||
|
||||
|
||||
addr_location__init(&al);
|
||||
intel_pt_insn->length = 0;
|
||||
|
||||
if (to_ip && *ip == to_ip)
|
||||
@ -773,19 +775,22 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
|
||||
if (ptq->pt->have_guest_sideband) {
|
||||
if (!ptq->guest_machine || ptq->guest_machine_pid != ptq->pid) {
|
||||
intel_pt_log("ERROR: guest sideband but no guest machine\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out_ret;
|
||||
}
|
||||
} else if ((!symbol_conf.guest_code && cpumode != PERF_RECORD_MISC_GUEST_KERNEL) ||
|
||||
intel_pt_get_guest(ptq)) {
|
||||
intel_pt_log("ERROR: no guest machine\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out_ret;
|
||||
}
|
||||
machine = ptq->guest_machine;
|
||||
thread = ptq->guest_thread;
|
||||
if (!thread) {
|
||||
if (cpumode != PERF_RECORD_MISC_GUEST_KERNEL) {
|
||||
intel_pt_log("ERROR: no guest thread\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out_ret;
|
||||
}
|
||||
thread = ptq->unknown_guest_thread;
|
||||
}
|
||||
@ -794,7 +799,8 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
|
||||
if (!thread) {
|
||||
if (cpumode != PERF_RECORD_MISC_KERNEL) {
|
||||
intel_pt_log("ERROR: no thread\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out_ret;
|
||||
}
|
||||
thread = ptq->pt->unknown_thread;
|
||||
}
|
||||
@ -808,13 +814,17 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
|
||||
intel_pt_log("ERROR: thread has no dso for %#" PRIx64 "\n", *ip);
|
||||
else
|
||||
intel_pt_log("ERROR: thread has no map for %#" PRIx64 "\n", *ip);
|
||||
return -EINVAL;
|
||||
addr_location__exit(&al);
|
||||
ret = -EINVAL;
|
||||
goto out_ret;
|
||||
}
|
||||
dso = map__dso(al.map);
|
||||
|
||||
if (dso->data.status == DSO_DATA_STATUS_ERROR &&
|
||||
dso__data_status_seen(dso, DSO_DATA_STATUS_SEEN_ITRACE))
|
||||
return -ENOENT;
|
||||
dso__data_status_seen(dso, DSO_DATA_STATUS_SEEN_ITRACE)) {
|
||||
ret = -ENOENT;
|
||||
goto out_ret;
|
||||
}
|
||||
|
||||
offset = map__map_ip(al.map, *ip);
|
||||
|
||||
@ -833,7 +843,8 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
|
||||
intel_pt_insn->rel = e->rel;
|
||||
memcpy(intel_pt_insn->buf, e->insn, INTEL_PT_INSN_BUF_SZ);
|
||||
intel_pt_log_insn_no_data(intel_pt_insn, *ip);
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto out_ret;
|
||||
}
|
||||
}
|
||||
|
||||
@ -854,11 +865,14 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
|
||||
offset);
|
||||
if (intel_pt_enable_logging)
|
||||
dso__fprintf(dso, intel_pt_log_fp());
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out_ret;
|
||||
}
|
||||
|
||||
if (intel_pt_get_insn(buf, len, x86_64, intel_pt_insn))
|
||||
return -EINVAL;
|
||||
if (intel_pt_get_insn(buf, len, x86_64, intel_pt_insn)) {
|
||||
ret = -EINVAL;
|
||||
goto out_ret;
|
||||
}
|
||||
|
||||
intel_pt_log_insn(intel_pt_insn, *ip);
|
||||
|
||||
@ -909,17 +923,20 @@ out:
|
||||
|
||||
e = intel_pt_cache_lookup(map__dso(al.map), machine, start_offset);
|
||||
if (e)
|
||||
return 0;
|
||||
goto out_ret;
|
||||
}
|
||||
|
||||
/* Ignore cache errors */
|
||||
intel_pt_cache_add(map__dso(al.map), machine, start_offset, insn_cnt,
|
||||
*ip - start_ip, intel_pt_insn);
|
||||
|
||||
return 0;
|
||||
out_ret:
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
|
||||
out_no_cache:
|
||||
*insn_cnt_ptr = insn_cnt;
|
||||
addr_location__exit(&al);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -968,6 +985,7 @@ static int __intel_pt_pgd_ip(uint64_t ip, void *data)
|
||||
struct addr_location al;
|
||||
u8 cpumode;
|
||||
u64 offset;
|
||||
int res;
|
||||
|
||||
if (ptq->state->to_nr) {
|
||||
if (intel_pt_guest_kernel_ip(ip))
|
||||
@ -984,12 +1002,15 @@ static int __intel_pt_pgd_ip(uint64_t ip, void *data)
|
||||
if (!thread)
|
||||
return -EINVAL;
|
||||
|
||||
addr_location__init(&al);
|
||||
if (!thread__find_map(thread, cpumode, ip, &al) || !map__dso(al.map))
|
||||
return -EINVAL;
|
||||
|
||||
offset = map__map_ip(al.map, ip);
|
||||
|
||||
return intel_pt_match_pgd_ip(ptq->pt, ip, offset, map__dso(al.map)->long_name);
|
||||
res = intel_pt_match_pgd_ip(ptq->pt, ip, offset, map__dso(al.map)->long_name);
|
||||
addr_location__exit(&al);
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool intel_pt_pgd_ip(uint64_t ip, void *data)
|
||||
@ -3372,20 +3393,22 @@ static int intel_pt_text_poke(struct intel_pt *pt, union perf_event *event)
|
||||
/* Assume text poke begins in a basic block no more than 4096 bytes */
|
||||
int cnt = 4096 + event->text_poke.new_len;
|
||||
struct thread *thread = pt->unknown_thread;
|
||||
struct addr_location al = { .map = NULL };
|
||||
struct addr_location al;
|
||||
struct machine *machine = pt->machine;
|
||||
struct intel_pt_cache_entry *e;
|
||||
u64 offset;
|
||||
int ret = 0;
|
||||
|
||||
addr_location__init(&al);
|
||||
if (!event->text_poke.new_len)
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
for (; cnt; cnt--, addr--) {
|
||||
struct dso *dso;
|
||||
|
||||
if (intel_pt_find_map(thread, cpumode, addr, &al)) {
|
||||
if (addr < event->text_poke.addr)
|
||||
return 0;
|
||||
goto out;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -3406,15 +3429,16 @@ static int intel_pt_text_poke(struct intel_pt *pt, union perf_event *event)
|
||||
* branch instruction before the text poke address.
|
||||
*/
|
||||
if (e->branch != INTEL_PT_BR_NO_BRANCH)
|
||||
return 0;
|
||||
goto out;
|
||||
} else {
|
||||
intel_pt_cache_invalidate(dso, machine, offset);
|
||||
intel_pt_log("Invalidated instruction cache for %s at %#"PRIx64"\n",
|
||||
dso->long_name, addr);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int intel_pt_process_event(struct perf_session *session,
|
||||
|
@ -2221,7 +2221,7 @@ static void ip__resolve_ams(struct thread *thread,
|
||||
{
|
||||
struct addr_location al;
|
||||
|
||||
memset(&al, 0, sizeof(al));
|
||||
addr_location__init(&al);
|
||||
/*
|
||||
* We cannot use the header.misc hint to determine whether a
|
||||
* branch stack address is user, kernel, guest, hypervisor.
|
||||
@ -2234,11 +2234,12 @@ static void ip__resolve_ams(struct thread *thread,
|
||||
ams->addr = ip;
|
||||
ams->al_addr = al.addr;
|
||||
ams->al_level = al.level;
|
||||
ams->ms.maps = al.maps;
|
||||
ams->ms.maps = maps__get(al.maps);
|
||||
ams->ms.sym = al.sym;
|
||||
ams->ms.map = al.map;
|
||||
ams->ms.map = map__get(al.map);
|
||||
ams->phys_addr = 0;
|
||||
ams->data_page_size = 0;
|
||||
addr_location__exit(&al);
|
||||
}
|
||||
|
||||
static void ip__resolve_data(struct thread *thread,
|
||||
@ -2247,18 +2248,19 @@ static void ip__resolve_data(struct thread *thread,
|
||||
{
|
||||
struct addr_location al;
|
||||
|
||||
memset(&al, 0, sizeof(al));
|
||||
addr_location__init(&al);
|
||||
|
||||
thread__find_symbol(thread, m, addr, &al);
|
||||
|
||||
ams->addr = addr;
|
||||
ams->al_addr = al.addr;
|
||||
ams->al_level = al.level;
|
||||
ams->ms.maps = al.maps;
|
||||
ams->ms.maps = maps__get(al.maps);
|
||||
ams->ms.sym = al.sym;
|
||||
ams->ms.map = al.map;
|
||||
ams->ms.map = map__get(al.map);
|
||||
ams->phys_addr = phys_addr;
|
||||
ams->data_page_size = daddr_page_size;
|
||||
addr_location__exit(&al);
|
||||
}
|
||||
|
||||
struct mem_info *sample__resolve_mem(struct perf_sample *sample,
|
||||
@ -2319,10 +2321,11 @@ static int add_callchain_ip(struct thread *thread,
|
||||
{
|
||||
struct map_symbol ms;
|
||||
struct addr_location al;
|
||||
int nr_loop_iter = 0, err;
|
||||
int nr_loop_iter = 0, err = 0;
|
||||
u64 iter_cycles = 0;
|
||||
const char *srcline = NULL;
|
||||
|
||||
addr_location__init(&al);
|
||||
al.filtered = 0;
|
||||
al.sym = NULL;
|
||||
al.srcline = NULL;
|
||||
@ -2348,9 +2351,10 @@ static int add_callchain_ip(struct thread *thread,
|
||||
* Discard all.
|
||||
*/
|
||||
callchain_cursor_reset(cursor);
|
||||
return 1;
|
||||
err = 1;
|
||||
goto out;
|
||||
}
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
thread__find_symbol(thread, *cpumode, ip, &al);
|
||||
}
|
||||
@ -2363,31 +2367,32 @@ static int add_callchain_ip(struct thread *thread,
|
||||
symbol__match_regex(al.sym, &ignore_callees_regex)) {
|
||||
/* Treat this symbol as the root,
|
||||
forgetting its callees. */
|
||||
*root_al = al;
|
||||
addr_location__copy(root_al, &al);
|
||||
callchain_cursor_reset(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
if (symbol_conf.hide_unresolved && al.sym == NULL)
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
if (iter) {
|
||||
nr_loop_iter = iter->nr_loop_iter;
|
||||
iter_cycles = iter->cycles;
|
||||
}
|
||||
|
||||
ms.maps = al.maps;
|
||||
ms.map = al.map;
|
||||
ms.maps = maps__get(al.maps);
|
||||
ms.map = map__get(al.map);
|
||||
ms.sym = al.sym;
|
||||
|
||||
if (!branch && append_inlines(cursor, &ms, ip) == 0)
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
srcline = callchain_srcline(&ms, al.addr);
|
||||
err = callchain_cursor_append(cursor, ip, &ms,
|
||||
branch, flags, nr_loop_iter,
|
||||
iter_cycles, branch_from, srcline);
|
||||
map__put(al.map);
|
||||
out:
|
||||
addr_location__exit(&al);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -469,9 +469,11 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
|
||||
struct addr_location node_al;
|
||||
unsigned long offset;
|
||||
|
||||
addr_location__init(&node_al);
|
||||
node_al.addr = map__map_ip(map, node->ip);
|
||||
node_al.map = map;
|
||||
node_al.map = map__get(map);
|
||||
offset = get_offset(node->ms.sym, &node_al);
|
||||
addr_location__exit(&node_al);
|
||||
|
||||
pydict_set_item_string_decref(
|
||||
pyelem, "sym_off",
|
||||
@ -539,6 +541,7 @@ static PyObject *python_process_brstack(struct perf_sample *sample,
|
||||
pydict_set_item_string_decref(pyelem, "cycles",
|
||||
PyLong_FromUnsignedLongLong(entries[i].flags.cycles));
|
||||
|
||||
addr_location__init(&al);
|
||||
thread__find_map_fb(thread, sample->cpumode,
|
||||
entries[i].from, &al);
|
||||
dsoname = get_dsoname(al.map);
|
||||
@ -551,6 +554,7 @@ static PyObject *python_process_brstack(struct perf_sample *sample,
|
||||
pydict_set_item_string_decref(pyelem, "to_dsoname",
|
||||
_PyUnicode_FromString(dsoname));
|
||||
|
||||
addr_location__exit(&al);
|
||||
PyList_Append(pylist, pyelem);
|
||||
Py_DECREF(pyelem);
|
||||
}
|
||||
@ -594,7 +598,6 @@ static PyObject *python_process_brstacksym(struct perf_sample *sample,
|
||||
PyObject *pylist;
|
||||
u64 i;
|
||||
char bf[512];
|
||||
struct addr_location al;
|
||||
|
||||
pylist = PyList_New(0);
|
||||
if (!pylist)
|
||||
@ -605,7 +608,9 @@ static PyObject *python_process_brstacksym(struct perf_sample *sample,
|
||||
|
||||
for (i = 0; i < br->nr; i++) {
|
||||
PyObject *pyelem;
|
||||
struct addr_location al;
|
||||
|
||||
addr_location__init(&al);
|
||||
pyelem = PyDict_New();
|
||||
if (!pyelem)
|
||||
Py_FatalError("couldn't create Python dictionary");
|
||||
@ -644,6 +649,7 @@ static PyObject *python_process_brstacksym(struct perf_sample *sample,
|
||||
|
||||
PyList_Append(pylist, pyelem);
|
||||
Py_DECREF(pyelem);
|
||||
addr_location__exit(&al);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
@ -432,18 +432,25 @@ int thread__memcpy(struct thread *thread, struct machine *machine,
|
||||
if (machine__kernel_ip(machine, ip))
|
||||
cpumode = PERF_RECORD_MISC_KERNEL;
|
||||
|
||||
if (!thread__find_map(thread, cpumode, ip, &al))
|
||||
return -1;
|
||||
addr_location__init(&al);
|
||||
if (!thread__find_map(thread, cpumode, ip, &al)) {
|
||||
addr_location__exit(&al);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dso = map__dso(al.map);
|
||||
|
||||
if( !dso || dso->data.status == DSO_DATA_STATUS_ERROR || map__load(al.map) < 0)
|
||||
if (!dso || dso->data.status == DSO_DATA_STATUS_ERROR || map__load(al.map) < 0) {
|
||||
addr_location__exit(&al);
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = map__map_ip(al.map, ip);
|
||||
if (is64bit)
|
||||
*is64bit = dso->is_64_bit;
|
||||
|
||||
addr_location__exit(&al);
|
||||
|
||||
return dso__data_read_offset(dso, machine, offset, buf, len);
|
||||
}
|
||||
|
||||
|
@ -90,8 +90,12 @@ static int __report_module(struct addr_location *al, u64 ip,
|
||||
static int report_module(u64 ip, struct unwind_info *ui)
|
||||
{
|
||||
struct addr_location al;
|
||||
int res;
|
||||
|
||||
return __report_module(&al, ip, ui);
|
||||
addr_location__init(&al);
|
||||
res = __report_module(&al, ip, ui);
|
||||
addr_location__exit(&al);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -104,8 +108,11 @@ static int entry(u64 ip, struct unwind_info *ui)
|
||||
struct unwind_entry *e = &ui->entries[ui->idx++];
|
||||
struct addr_location al;
|
||||
|
||||
if (__report_module(&al, ip, ui))
|
||||
addr_location__init(&al);
|
||||
if (__report_module(&al, ip, ui)) {
|
||||
addr_location__exit(&al);
|
||||
return -1;
|
||||
}
|
||||
|
||||
e->ip = ip;
|
||||
e->ms.maps = al.maps;
|
||||
@ -116,6 +123,7 @@ static int entry(u64 ip, struct unwind_info *ui)
|
||||
al.sym ? al.sym->name : "''",
|
||||
ip,
|
||||
al.map ? map__map_ip(al.map, ip) : (u64) 0);
|
||||
addr_location__exit(&al);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -136,17 +144,22 @@ static int access_dso_mem(struct unwind_info *ui, Dwarf_Addr addr,
|
||||
ssize_t size;
|
||||
struct dso *dso;
|
||||
|
||||
addr_location__init(&al);
|
||||
if (!thread__find_map(ui->thread, PERF_RECORD_MISC_USER, addr, &al)) {
|
||||
pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
|
||||
return -1;
|
||||
goto out_fail;
|
||||
}
|
||||
dso = map__dso(al.map);
|
||||
if (!dso)
|
||||
return -1;
|
||||
goto out_fail;
|
||||
|
||||
size = dso__data_read_addr(dso, al.map, ui->machine, addr, (u8 *) data, sizeof(*data));
|
||||
|
||||
addr_location__exit(&al);
|
||||
return !(size == sizeof(*data));
|
||||
out_fail:
|
||||
addr_location__exit(&al);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool memory_read(Dwfl *dwfl __maybe_unused, Dwarf_Addr addr, Dwarf_Word *result,
|
||||
|
@ -416,7 +416,12 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
|
||||
static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
|
||||
{
|
||||
struct addr_location al;
|
||||
return thread__find_map(ui->thread, PERF_RECORD_MISC_USER, ip, &al);
|
||||
struct map *ret;
|
||||
|
||||
addr_location__init(&al);
|
||||
ret = thread__find_map(ui->thread, PERF_RECORD_MISC_USER, ip, &al);
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -631,7 +636,9 @@ static int entry(u64 ip, struct thread *thread,
|
||||
{
|
||||
struct unwind_entry e;
|
||||
struct addr_location al;
|
||||
int ret;
|
||||
|
||||
addr_location__init(&al);
|
||||
e.ms.sym = thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al);
|
||||
e.ip = ip;
|
||||
e.ms.map = al.map;
|
||||
@ -642,7 +649,9 @@ static int entry(u64 ip, struct thread *thread,
|
||||
ip,
|
||||
al.map ? map__map_ip(al.map, ip) : (u64) 0);
|
||||
|
||||
return cb(&e, arg);
|
||||
ret = cb(&e, arg);
|
||||
addr_location__exit(&al);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void display_error(int err)
|
||||
|
Loading…
Reference in New Issue
Block a user