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)
 {
                .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)
        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))
                ret = -1;
        }
 out_put:
-       addr_location__put(&al);
+       addr_location__exit(&al);
        return ret;
 }
 
 
        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)
                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,
        }
 
 out:
-       addr_location__put(&al);
+       addr_location__exit(&al);
        return ret;
 
 free_mi:
 
                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) {
                                          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,
                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;
 
                                      true)) {
                        pr_warning("problem incrementing symbol period, "
                                   "skipping event\n");
-                       goto out_put;
+                       goto out;
                }
        }
 
        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;
 }
 
 
        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",
        thread__put(thread);
 repipe:
        perf_event__repipe(tool, event, sample, machine);
+       addr_location__exit(&al);
        return 0;
 }
 
 
        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;
                        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 {
 
        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++;
                atom_del(atom);
        }
 
-       return 0;
+out:
+       addr_location__exit(&al);
+       return ret;
 }
 
 static struct kwork_class kwork_irq;
 
        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;
        }
 
                dso ? dso->long_name : "???",
                al.sym ? al.sym->name : "???");
 out_put:
-       addr_location__put(&al);
+       addr_location__exit(&al);
        return 0;
 }
 
 
        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)
        if (ret < 0)
                pr_debug("problem adding hist entry, skipping event\n");
 out_put:
-       addr_location__put(&al);
+       addr_location__exit(&al);
        return ret;
 }
 
 
        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);
 
        evsel__save_time(evsel, sample->time, sample->cpu);
 
+       addr_location__exit(&al);
        return rc;
 }
 
 
 {
        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;
 
                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);
        }
 {
        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;
 
                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;
 
                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;
 {
        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;
 
                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;
 
                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;
        struct addr_location al;
        bool kernel;
        struct dso *dso;
+       int ret = 0;
 
        if (!start || !end)
                return 0;
                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);
                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 */
        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)
        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;
 }
 
                           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;
                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;
        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,
        struct addr_location al;
        int printed = fprintf(fp, "%16" PRIx64, sample->addr);
 
+       addr_location__init(&al);
        if (!sample_addr_correlates_sym(attr))
                goto out;
 
        if (PRINT_FIELD(DSO))
                printed += map__fprintf_dsoname_dsoff(al.map, PRINT_FIELD(DSOFF), al.addr, fp);
 out:
+       addr_location__exit(&al);
        return printed;
 }
 
        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) {
        }
 
 out_put:
-       if (al.thread)
-               addr_location__put(&al);
+       addr_location__exit(&addr_al);
+       addr_location__exit(&al);
        return ret;
 }
 
 
        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);
 
                return NULL;
        }
 
+       addr_location__init(&al);
        if (!chain)
                goto exit;
 
 
        for (i = 0; i < chain->nr; i++) {
                u64 ip;
+               struct addr_location tal;
 
                if (callchain_param.order == ORDER_CALLEE)
                        ip = chain->ips[i];
                                 * 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;
 
        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);
                mutex_unlock(&hists->lock);
        }
 
-       addr_location__put(&al);
+out:
+       addr_location__exit(&al);
 }
 
 static void
 
        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;
 }
 
        int err = -1;
        int callchain_ret = 0;
 
+       addr_location__init(&al);
        thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
 
        if (sample->callchain) {
        err = 0;
 out_put:
        thread__put(thread);
+       addr_location__exit(&al);
        return err;
 }
 
 
 
        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");
        }
        pr_debug("Bytes read match those read by objdump\n");
 out:
-       map__put(al.map);
+       addr_location__exit(&al);
        return err;
 }
 
 
 #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>
        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,
 
                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;
 }
 
 {
        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 *);
 
 #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>
        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
                        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;
 }
 
 
 #include "machine.h"
 #include "map.h"
 #include "parse-events.h"
+#include "thread.h"
 #include "hists_common.h"
 #include "util/mmap.h"
 #include <errno.h>
        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
                        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;
                }
 
                        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;
 }
 
        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,
 
                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;
 }
 
 {
        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 *);
 
                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);
                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);
 
 // 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);
 }
 
        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 */
 
                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;
 }
 
        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);
 
                                    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,
 
 {
        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;
        }
 
 
                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) {
                        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);
        }
 #endif
        output_json_format(out, false, 2, "}");
+       addr_location__exit(&al);
        return 0;
 }
 
 
                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);
                                             kernel_start);
 
                callchain_cursor_advance(&callchain_cursor);
+               addr_location__exit(&al);
        }
 
        /* Reset the callchain order to its prior value. */
 
        struct addr_location a;
        struct map *map;
        u64 offset;
+       __s32 ret;
 
        if (!d->ctx_valid)
                return -1;
            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 = {
 
        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);
                        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;
        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;
 
        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';
 
                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) {
                /*
 
        bool first = true;
 
        if (sample->callchain) {
-               struct addr_location node_al;
-
                callchain_cursor_commit(cursor);
 
                while (1) {
                                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,
                                        printed += __symbol__fprintf_symname(sym, &node_al,
                                                                             print_unknown_as_addr, fp);
                                }
+                               addr_location__exit(&node_al);
                        }
 
                        if (print_dso && (!sym || !sym->inlined))
 
 
 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;
        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;
 
        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)
                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;
                }
                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;
                }
                                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);
 
                                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;
                        }
                }
 
                                             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);
 
 
                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;
 }
 
        struct addr_location al;
        u8 cpumode;
        u64 offset;
+       int res;
 
        if (ptq->state->to_nr) {
                if (intel_pt_guest_kernel_ip(ip))
        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)
        /* 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;
                }
 
                         * 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,
 
 {
        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.
        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,
 {
        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,
 {
        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;
                                 * Discard all.
                                 */
                                callchain_cursor_reset(cursor);
-                               return 1;
+                               err = 1;
+                               goto out;
                        }
-                       return 0;
+                       goto out;
                }
                thread__find_symbol(thread, *cpumode, ip, &al);
        }
                  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;
 }
 
 
                                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",
                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);
                pydict_set_item_string_decref(pyelem, "to_dsoname",
                                              _PyUnicode_FromString(dsoname));
 
+               addr_location__exit(&al);
                PyList_Append(pylist, pyelem);
                Py_DECREF(pyelem);
        }
        PyObject *pylist;
        u64 i;
        char bf[512];
-       struct addr_location al;
 
        pylist = PyList_New(0);
        if (!pylist)
 
        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");
 
                PyList_Append(pylist, pyelem);
                Py_DECREF(pyelem);
+               addr_location__exit(&al);
        }
 
 exit:
 
        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);
 }
 
 
 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;
 }
 
 /*
        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;
                 al.sym ? al.sym->name : "''",
                 ip,
                 al.map ? map__map_ip(al.map, ip) : (u64) 0);
+       addr_location__exit(&al);
        return 0;
 }
 
        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,
 
 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
 {
        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;
                 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)