]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
perf addr_location: Add init/exit/copy functions
authorIan Rogers <irogers@google.com>
Thu, 8 Jun 2023 23:28:03 +0000 (16:28 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 12 Jun 2023 18:57:53 +0000 (15:57 -0300)
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>
35 files changed:
tools/perf/builtin-annotate.c
tools/perf/builtin-c2c.c
tools/perf/builtin-diff.c
tools/perf/builtin-inject.c
tools/perf/builtin-kmem.c
tools/perf/builtin-kwork.c
tools/perf/builtin-mem.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
tools/perf/builtin-timechart.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/tests/code-reading.c
tools/perf/tests/hists_cumulate.c
tools/perf/tests/hists_filter.c
tools/perf/tests/hists_link.c
tools/perf/tests/hists_output.c
tools/perf/tests/mmap-thread-lookup.c
tools/perf/util/addr_location.c
tools/perf/util/addr_location.h
tools/perf/util/build-id.c
tools/perf/util/cs-etm.c
tools/perf/util/data-convert-json.c
tools/perf/util/db-export.c
tools/perf/util/dlfilter.c
tools/perf/util/event.c
tools/perf/util/evsel_fprintf.c
tools/perf/util/hist.c
tools/perf/util/intel-pt.c
tools/perf/util/machine.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/thread.c
tools/perf/util/unwind-libdw.c
tools/perf/util/unwind-libunwind-local.c

index 425a7e2fd6fb26ffe05f72effc7ff3638a38462e..aeeb801f1ed7b15f1118de904d4366feb7ed3a97 100644 (file)
@@ -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;
 }
 
index ee41a96f0c7362c15268694a25224e7612694656..530a44a59f41ac98bd070de36cfb0c98a48e6769 100644 (file)
@@ -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:
index dbb0562d6a4f5cc442385b46d0090f7b5fc94d1f..ca39657ee4074858036a9f3b4a89d714e58b4361 100644 (file)
@@ -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;
 }
 
index d9e96d4624c6f13f3cb30ccfe7fdbeb14197d113..d19a1b862306e4d18b8e5e0947e9d1ae16750ec4 100644 (file)
@@ -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;
 }
 
index fe9439a4fd664ac30c0257bbac7f537c72378954..96a6611e4e53f448d1cbe018e704a1a5ef514f72 100644 (file)
@@ -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 {
index a9395c52b23b7905e06ff4876cc7e19d8929ceb0..2d80aef4ecccece0632fdccd7079f3a7ac69b1de 100644 (file)
@@ -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;
index 960bfd4b732a9d98809b915752f45a218a6c48c2..51499c20da01e82239f2fa5f8a3da9b7696c83a5 100644 (file)
@@ -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;
 }
 
index 8ea6ab18534a1cfa021e37a41031fe227c62f487..0b091a8983a56a948ca4b70b3fb9411e0d6c2ddf 100644 (file)
@@ -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;
 }
 
index fd37468c4f623780b5410f1c6aaabac17597a6c0..c75ad82a6729d6f85cb78a1269605edc14829c12 100644 (file)
@@ -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;
 }
 
index e756290de2ac1ed845c0d16e96e977d64a680d22..784d478c2e0580afb2f3d5edfcdaf5a6d61de0a1 100644 (file)
@@ -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;
 }
 
index 829d99fecfd00f9eddfc210b37f74b4dd2f00605..19d4542ea18a1367ea3713acd4c0471d4b9da990 100644 (file)
@@ -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;
index 9d3cbebb9b79605134d32c4a409b08dc43c307c1..99010dfa57609f58b4f93934b8cfbb6cfe04a48a 100644 (file)
@@ -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
index 4c9bec39423bd6233818cf11aa58f79fb90b2fae..6a1e75f06832bf35283c898927e687ce722ec9c4 100644 (file)
@@ -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;
 }
 
index 9d8eefbebd489696c4d08429d8146a95b3c066ff..2a7b2b6f5286e5a71ebf40b3dcede49cd91884a9 100644 (file)
@@ -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;
 }
 
index 62b9c6461ea6a5edd7732e889f4d6343769bda8f..71dacb0fec4d584f4bac52372f738d8df56e3c74 100644 (file)
@@ -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 *);
index 98eff5935a1c7e0061128d038e525e3e84661af6..4b2e4f2fbe4854306d94d362c42ce7003ab30b61 100644 (file)
@@ -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;
 }
 
index 141e2972e34f2087efd4e3ef7b6329a88f64461a..12bad88406991038cf2b9b829ee9cb75090325af 100644 (file)
@@ -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;
 }
index cd2094c13e1e5c6658416d9a39fc3eef2bb95194..ba1cccf57049fe09233257b8569797110bd5cf64 100644 (file)
@@ -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 *);
index 898eda55b7a8169af91fc798fbfa636c44178060..3891a2a3b46fc7a7b266e9643fc5838890d94fb2 100644 (file)
@@ -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);
index c73fc2aa236ceccfba11567372fb3d6b5d6ccaaf..51825ef8c0ab77a701414ba5b2ea0426dc511dc0 100644 (file)
@@ -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);
 }
index 7dfa7417c0fe65f146d30ab60073ce8f683ae1b2..d8ac0428dff232ec9ac4a7e5bbb3cec6fdf7e989 100644 (file)
@@ -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 */
index 06a8cd88cbef146b262ec0462c8e579d5524fcc7..36728222a5b4ea354a4182a805b8d25b48098b1d 100644 (file)
@@ -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;
 }
index b550c739315581b1702783f6c8cd69ba464bd5d2..416f2ddc3895f0c21011ae5a51ad7440ff738df8 100644 (file)
@@ -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,
index 291591e303cd8f141e4b33be7e2f6720f75bb34b..5bb3c2ba95ca29545f595228a18deb88aba9253c 100644 (file)
@@ -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;
 }
 
index 751fd53bfd93770e78a092e1c887f6f262009cae..6184696dc266e540a6dbbe45748459e604f1fa99 100644 (file)
@@ -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. */
index 8016f21dc0b881f8ed7a488523cb4080628144d2..46f74b2344dbb34c33c17f6fbd3534b632408222 100644 (file)
@@ -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 = {
index 6ee23145ee7e6aaa11b0f4252cf9549a66b3388f..2fcfba38fc488ed54726383a8890b32f894e9343 100644 (file)
@@ -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) {
                /*
index a1655fd7ed9b889323dcef6660667cf498d0bf00..cf45ca0e768fb882aaf272a7f5e64dd3802548fe 100644 (file)
@@ -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))
index 4bc3affbe891ba1f5552f9d624be51daf132e8f5..a4c1b617f6e4d8d1afa21505ba78a7e13738ef0b 100644 (file)
@@ -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;
index 45c7e7722916230d96e7bf4b42cdcbfaf6e64178..783ce61c6d25a956fe419bab979a11184af975bf 100644 (file)
@@ -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,
index 8972c852d3bd5d68f71d91f6d951d807b11d88f0..9fcf357a4d53337a4cf2698ee28e477fc76a458e 100644 (file)
@@ -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;
 }
 
index f3d262e871ac0c3f15a76c6dda4691156a161e90..d7c99028c6e63a87cae8ef722731478e31b6eda9 100644 (file)
@@ -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:
index 9a1db3be6436c7575ce6de399d1a5e23ad148d3a..bee4ac1051ee532ea04efcfe4bb034d63bc42cf7 100644 (file)
@@ -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);
 }
 
index 3723b5e31b2a60d13a28f35f9047855ef726066e..83eea968482e5f5f8efcf0c4b0f4472dfc0187f5 100644 (file)
@@ -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,
index 11f3fc95aa11db89cfc8740565befbd40f8a57db..36bf5100bad21c301927cda833ee5282a7fa0f56 100644 (file)
@@ -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)