[PATCH 6.18 011/752] perf annotate: Fix args leak of map_symbol

Sasha Levin
2026-02-28T17:48:12Z

From: Ian Rogers <irogers@google.com>

[ Upstream commit 00419892bac28bf148450d762bbff990a6bd5494 ]

map_symbol__exit() needs calling on an annotate_args.ms, however, rather
than introduce proper reference count handling to symbol__annotate()
just switch to passing the map_symbol pointer parameter around, making
the puts the caller's responsibility.

Fix a number of cases to ensure the map in a map_symbol has a
reference count increment and add the then necessary map_symbol_exits.

Fixes: 56e144fe98260a0f ("perf mem_info: Add and use map_symbol__exit and addr_map_symbol__exit")
Reviewed-by: James Clark <james.clark@linaro.org>
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Aditya Bodkhe <aditya.b1@linux.ibm.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexandre Ghiti <alex@ghiti.fr>
Cc: Athira Rajeev <atrajeev@linux.ibm.com>
Cc: Bill Wendling <morbo@google.com>
Cc: Dr. David Alan Gilbert <linux@treblig.org>
Cc: Guo Ren <guoren@kernel.org>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Julia Lawall <Julia.Lawall@inria.fr>
Cc: Justin Stitt <justinstitt@google.com>
Cc: Krzysztof Łopatowski <krzysztof.m.lopatowski@gmail.com>
Cc: Leo Yan <leo.yan@linux.dev>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-csky@vger.kernel.org
Cc: linux-riscv@lists.infradead.org
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nick Desaulniers <nick.desaulniers+lkml@gmail.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Paul Walmsley <pjw@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Sergei Trofimovich <slyich@gmail.com>
Cc: Shimin Guo <shimin.guo@skydio.com>
Cc: Suchit Karunakaran <suchitkarunakaran@gmail.com>
Cc: Thomas Falcon <thomas.falcon@intel.com>
Cc: Tianyou Li <tianyou.li@intel.com>
Cc: Will Deacon <will@kernel.org>
Cc: Zecheng Li <zecheng@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../arch/loongarch/annotate/instructions.c | 14 ++++----
tools/perf/arch/s390/annotate/instructions.c | 11 +++---
tools/perf/util/annotate.c | 2 +-
tools/perf/util/capstone.c | 14 ++++----
tools/perf/util/disasm.c | 36 ++++++++++---------
tools/perf/util/disasm.h | 2 +-
tools/perf/util/llvm.c | 6 ++--
7 files changed, 47 insertions(+), 38 deletions(-)

diff --git a/tools/perf/arch/loongarch/annotate/instructions.c b/tools/perf/arch/loongarch/annotate/instructions.c
index 70262d5f14442..1c3abb43c8d72 100644
--- a/tools/perf/arch/loongarch/annotate/instructions.c
+++ b/tools/perf/arch/loongarch/annotate/instructions.c
@@ -10,9 +10,7 @@ static int loongarch_call__parse(struct arch *arch, struct ins_operands *ops, st
{
char *c, *endptr, *tok, *name;
struct map *map = ms->map;
- struct addr_map_symbol target = {
- .ms = { .map = map, },
- };
+ struct addr_map_symbol target;

c = strchr(ops->raw, '#');
if (c++ == NULL)
@@ -38,12 +36,16 @@ static int loongarch_call__parse(struct arch *arch, struct ins_operands *ops, st
if (ops->target.name == NULL)
return -1;

- target.addr = map__objdump_2mem(map, ops->target.addr);
+ target = (struct addr_map_symbol) {
+ .ms = { .map = map__get(map), },
+ .addr = map__objdump_2mem(map, ops->target.addr),
+ };

if (maps__find_ams(ms->maps, &target) == 0 &&
map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
ops->target.sym = target.ms.sym;

+ addr_map_symbol__exit(&target);
return 0;
}

@@ -58,7 +60,7 @@ static int loongarch_jump__parse(struct arch *arch, struct ins_operands *ops, st
struct map *map = ms->map;
struct symbol *sym = ms->sym;
struct addr_map_symbol target = {
- .ms = { .map = map, },
+ .ms = { .map = map__get(map), },
};
const char *c = strchr(ops->raw, '#');
u64 start, end;
@@ -90,7 +92,7 @@ static int loongarch_jump__parse(struct arch *arch, struct ins_operands *ops, st
} else {
ops->target.offset_avail = false;
}
-
+ addr_map_symbol__exit(&target);
return 0;
}

diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
index c61193f1e0964..626e6d2cbc81a 100644
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ b/tools/perf/arch/s390/annotate/instructions.c
@@ -6,9 +6,7 @@ static int s390_call__parse(struct arch *arch, struct ins_operands *ops,
{
char *endptr, *tok, *name;
struct map *map = ms->map;
- struct addr_map_symbol target = {
- .ms = { .map = map, },
- };
+ struct addr_map_symbol target;

tok = strchr(ops->raw, ',');
if (!tok)
@@ -36,12 +34,17 @@ static int s390_call__parse(struct arch *arch, struct ins_operands *ops,

if (ops->target.name == NULL)
return -1;
- target.addr = map__objdump_2mem(map, ops->target.addr);
+
+ target = (struct addr_map_symbol) {
+ .ms = { .map = map__get(map), },
+ .addr = map__objdump_2mem(map, ops->target.addr),
+ };

if (maps__find_ams(ms->maps, &target) == 0 &&
map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
ops->target.sym = target.ms.sym;

+ addr_map_symbol__exit(&target);
return 0;
}

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 1d6900033b3a0..dc80d922f450d 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1031,7 +1031,7 @@ int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
return 0;

args.arch = arch;
- args.ms = *ms;
+ args.ms = ms;

if (notes->src == NULL) {
notes->src = annotated_source__new();
diff --git a/tools/perf/util/capstone.c b/tools/perf/util/capstone.c
index be5fd44b1f9dc..2c7feab61b7bf 100644
--- a/tools/perf/util/capstone.c
+++ b/tools/perf/util/capstone.c
@@ -143,7 +143,7 @@ static void print_capstone_detail(cs_insn *insn, char *buf, size_t len,
struct annotate_args *args, u64 addr)
{
int i;
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct symbol *sym;

/* TODO: support more architectures */
@@ -222,7 +222,7 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
{
#ifdef HAVE_LIBCAPSTONE_SUPPORT
struct annotation *notes = symbol__annotation(sym);
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct dso *dso = map__dso(map);
u64 start = map__rip_2objdump(map, sym->start);
u64 offset;
@@ -256,7 +256,7 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
args->line = disasm_buf;
args->line_nr = 0;
args->fileloc = NULL;
- args->ms.sym = sym;
+ args->ms->sym = sym;

dl = disasm_line__new(args);
if (dl == NULL)
@@ -268,7 +268,7 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
!strcmp(args->options->disassembler_style, "att"))
disassembler_style = true;

- if (capstone_init(maps__machine(args->ms.maps), &handle, is_64bit, disassembler_style) < 0)
+ if (capstone_init(maps__machine(args->ms->maps), &handle, is_64bit, disassembler_style) < 0)
goto err;

needs_cs_close = true;
@@ -345,7 +345,7 @@ int symbol__disassemble_capstone_powerpc(const char *filename __maybe_unused,
{
#ifdef HAVE_LIBCAPSTONE_SUPPORT
struct annotation *notes = symbol__annotation(sym);
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct dso *dso = map__dso(map);
struct nscookie nsc;
u64 start = map__rip_2objdump(map, sym->start);
@@ -382,7 +382,7 @@ int symbol__disassemble_capstone_powerpc(const char *filename __maybe_unused,
!strcmp(args->options->disassembler_style, "att"))
disassembler_style = true;

- if (capstone_init(maps__machine(args->ms.maps), &handle, is_64bit, disassembler_style) < 0)
+ if (capstone_init(maps__machine(args->ms->maps), &handle, is_64bit, disassembler_style) < 0)
goto err;

needs_cs_close = true;
@@ -408,7 +408,7 @@ int symbol__disassemble_capstone_powerpc(const char *filename __maybe_unused,
args->line = disasm_buf;
args->line_nr = 0;
args->fileloc = NULL;
- args->ms.sym = sym;
+ args->ms->sym = sym;

dl = disasm_line__new(args);
if (dl == NULL)
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index 50b9433f3f8e6..924429142631a 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -269,9 +269,7 @@ static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_s
{
char *endptr, *tok, *name;
struct map *map = ms->map;
- struct addr_map_symbol target = {
- .ms = { .map = map, },
- };
+ struct addr_map_symbol target;

ops->target.addr = strtoull(ops->raw, &endptr, 16);

@@ -296,12 +294,16 @@ static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_s
if (ops->target.name == NULL)
return -1;
find_target:
- target.addr = map__objdump_2mem(map, ops->target.addr);
+ target = (struct addr_map_symbol) {
+ .ms = { .map = map__get(map), },
+ .addr = map__objdump_2mem(map, ops->target.addr),
+ };

if (maps__find_ams(ms->maps, &target) == 0 &&
map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
ops->target.sym = target.ms.sym;

+ addr_map_symbol__exit(&target);
return 0;

indirect_call:
@@ -366,7 +368,7 @@ static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_s
struct map *map = ms->map;
struct symbol *sym = ms->sym;
struct addr_map_symbol target = {
- .ms = { .map = map, },
+ .ms = { .map = map__get(map), },
};
const char *c = strchr(ops->raw, ',');
u64 start, end;
@@ -440,7 +442,7 @@ static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_s
} else {
ops->target.offset_avail = false;
}
-
+ addr_map_symbol__exit(&target);
return 0;
}

@@ -1046,7 +1048,7 @@ static size_t disasm_line_size(int nr)
struct disasm_line *disasm_line__new(struct annotate_args *args)
{
struct disasm_line *dl = NULL;
- struct annotation *notes = symbol__annotation(args->ms.sym);
+ struct annotation *notes = symbol__annotation(args->ms->sym);
int nr = notes->src->nr_events;

dl = zalloc(disasm_line_size(nr));
@@ -1064,7 +1066,7 @@ struct disasm_line *disasm_line__new(struct annotate_args *args)
} else if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
goto out_free_line;

- disasm_line__init_ins(dl, args->arch, &args->ms);
+ disasm_line__init_ins(dl, args->arch, args->ms);
}

return dl;
@@ -1119,7 +1121,7 @@ static int symbol__parse_objdump_line(struct symbol *sym,
struct annotate_args *args,
char *parsed_line, int *line_nr, char **fileloc)
{
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct annotation *notes = symbol__annotation(sym);
struct disasm_line *dl;
char *tmp;
@@ -1151,7 +1153,7 @@ static int symbol__parse_objdump_line(struct symbol *sym,
args->line = parsed_line;
args->line_nr = *line_nr;
args->fileloc = *fileloc;
- args->ms.sym = sym;
+ args->ms->sym = sym;

dl = disasm_line__new(args);
(*line_nr)++;
@@ -1169,12 +1171,14 @@ static int symbol__parse_objdump_line(struct symbol *sym,
if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.sym) {
struct addr_map_symbol target = {
.addr = dl->ops.target.addr,
- .ms = { .map = map, },
+ .ms = { .map = map__get(map), },
};

- if (!maps__find_ams(args->ms.maps, &target) &&
+ if (!maps__find_ams(args->ms->maps, &target) &&
target.ms.sym->start == target.al_addr)
dl->ops.target.sym = target.ms.sym;
+
+ addr_map_symbol__exit(&target);
}

annotation_line__add(&dl->al, &notes->src->source);
@@ -1338,7 +1342,7 @@ static int symbol__disassemble_raw(char *filename, struct symbol *sym,
struct annotate_args *args)
{
struct annotation *notes = symbol__annotation(sym);
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct dso *dso = map__dso(map);
u64 start = map__rip_2objdump(map, sym->start);
u64 end = map__rip_2objdump(map, sym->end);
@@ -1375,7 +1379,7 @@ static int symbol__disassemble_raw(char *filename, struct symbol *sym,
args->line = disasm_buf;
args->line_nr = 0;
args->fileloc = NULL;
- args->ms.sym = sym;
+ args->ms->sym = sym;

dl = disasm_line__new(args);
if (dl == NULL)
@@ -1501,7 +1505,7 @@ static int symbol__disassemble_objdump(const char *filename, struct symbol *sym,
struct annotate_args *args)
{
struct annotation_options *opts = &annotate_opts;
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct dso *dso = map__dso(map);
char *command;
FILE *file;
@@ -1644,7 +1648,7 @@ static int symbol__disassemble_objdump(const char *filename, struct symbol *sym,
int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
{
struct annotation_options *options = args->options;
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct dso *dso = map__dso(map);
char symfs_filename[PATH_MAX];
bool delete_extract = false;
diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h
index d2cb555e4a3be..a3ea9d6762816 100644
--- a/tools/perf/util/disasm.h
+++ b/tools/perf/util/disasm.h
@@ -97,7 +97,7 @@ struct ins_ops {

struct annotate_args {
struct arch *arch;
- struct map_symbol ms;
+ struct map_symbol *ms;
struct annotation_options *options;
s64 offset;
char *line;
diff --git a/tools/perf/util/llvm.c b/tools/perf/util/llvm.c
index 2ebf1f5f65bf7..4ada9a10bd93f 100644
--- a/tools/perf/util/llvm.c
+++ b/tools/perf/util/llvm.c
@@ -118,7 +118,7 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
{
#ifdef HAVE_LIBLLVM_SUPPORT
struct annotation *notes = symbol__annotation(sym);
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct dso *dso = map__dso(map);
u64 start = map__rip_2objdump(map, sym->start);
/* Malloc-ed buffer containing instructions read from disk. */
@@ -184,7 +184,7 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
args->line = disasm_buf;
args->line_nr = 0;
args->fileloc = NULL;
- args->ms.sym = sym;
+ args->ms->sym = sym;

dl = disasm_line__new(args);
if (dl == NULL)
@@ -242,7 +242,7 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
&line_storage_len);
args->line_nr = 0;
args->fileloc = NULL;
- args->ms.sym = sym;
+ args->ms->sym = sym;

llvm_addr2line(filename, pc, &args->fileloc,
(unsigned int *)&args->line_nr, false, NULL);
--
2.51.0