Skip to content

Commit c06310f

Browse files
committed
Merge tag 'perf-tools-fixes-for-v6.14-2025-01-30' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools
Pull perf tools fixes from Namhyung Kim: "An early round of random fixes in perf tools for this cycle. perf trace: - Fix loading of BPF program on certain clang versions - Fix out-of-bound access in syscalls with 6 arguments - Skip syscall enum test if landlock syscall is not available perf annotate: - Fix segfaults due to invalid access in disasm arrays perf stat: - Fix error handling in topology parsing" * tag 'perf-tools-fixes-for-v6.14-2025-01-30' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools: perf cpumap: Fix die and cluster IDs perf test: Skip syscall enum test if no landlock syscall perf trace: Fix runtime error of index out of bounds perf annotate: Use an array for the disassembler preference perf trace: Fix BPF loading failure (-E2BIG)
2 parents e20f2bb + 9fae588 commit c06310f

File tree

7 files changed

+113
-90
lines changed

7 files changed

+113
-90
lines changed

tools/perf/builtin-trace.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2107,8 +2107,12 @@ static int trace__read_syscall_info(struct trace *trace, int id)
21072107
return PTR_ERR(sc->tp_format);
21082108
}
21092109

2110+
/*
2111+
* The tracepoint format contains __syscall_nr field, so it's one more
2112+
* than the actual number of syscall arguments.
2113+
*/
21102114
if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ?
2111-
RAW_SYSCALL_ARGS_NUM : sc->tp_format->format.nr_fields))
2115+
RAW_SYSCALL_ARGS_NUM : sc->tp_format->format.nr_fields - 1))
21122116
return -ENOMEM;
21132117

21142118
sc->args = sc->tp_format->format.fields;

tools/perf/tests/shell/trace_btf_enum.sh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,12 @@ check_vmlinux() {
2626
trace_landlock() {
2727
echo "Tracing syscall ${syscall}"
2828

29-
# test flight just to see if landlock_add_rule and libbpf are available
30-
$TESTPROG
29+
# test flight just to see if landlock_add_rule is available
30+
if ! perf trace $TESTPROG 2>&1 | grep -q landlock
31+
then
32+
echo "No landlock system call found, skipping to non-syscall tracing."
33+
return
34+
fi
3135

3236
if perf trace -e $syscall $TESTPROG 2>&1 | \
3337
grep -q -E ".*landlock_add_rule\(ruleset_fd: 11, rule_type: (LANDLOCK_RULE_PATH_BENEATH|LANDLOCK_RULE_NET_PORT), rule_attr: 0x[a-f0-9]+, flags: 45\) = -1.*"

tools/perf/util/annotate.c

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2100,6 +2100,57 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
21002100
return 0;
21012101
}
21022102

2103+
const char * const perf_disassembler__strs[] = {
2104+
[PERF_DISASM_UNKNOWN] = "unknown",
2105+
[PERF_DISASM_LLVM] = "llvm",
2106+
[PERF_DISASM_CAPSTONE] = "capstone",
2107+
[PERF_DISASM_OBJDUMP] = "objdump",
2108+
};
2109+
2110+
2111+
static void annotation_options__add_disassembler(struct annotation_options *options,
2112+
enum perf_disassembler dis)
2113+
{
2114+
for (u8 i = 0; i < ARRAY_SIZE(options->disassemblers); i++) {
2115+
if (options->disassemblers[i] == dis) {
2116+
/* Disassembler is already present then don't add again. */
2117+
return;
2118+
}
2119+
if (options->disassemblers[i] == PERF_DISASM_UNKNOWN) {
2120+
/* Found a free slot. */
2121+
options->disassemblers[i] = dis;
2122+
return;
2123+
}
2124+
}
2125+
pr_err("Failed to add disassembler %d\n", dis);
2126+
}
2127+
2128+
static int annotation_options__add_disassemblers_str(struct annotation_options *options,
2129+
const char *str)
2130+
{
2131+
while (str && *str != '\0') {
2132+
const char *comma = strchr(str, ',');
2133+
int len = comma ? comma - str : (int)strlen(str);
2134+
bool match = false;
2135+
2136+
for (u8 i = 0; i < ARRAY_SIZE(perf_disassembler__strs); i++) {
2137+
const char *dis_str = perf_disassembler__strs[i];
2138+
2139+
if (len == (int)strlen(dis_str) && !strncmp(str, dis_str, len)) {
2140+
annotation_options__add_disassembler(options, i);
2141+
match = true;
2142+
break;
2143+
}
2144+
}
2145+
if (!match) {
2146+
pr_err("Invalid disassembler '%.*s'\n", len, str);
2147+
return -1;
2148+
}
2149+
str = comma ? comma + 1 : NULL;
2150+
}
2151+
return 0;
2152+
}
2153+
21032154
static int annotation__config(const char *var, const char *value, void *data)
21042155
{
21052156
struct annotation_options *opt = data;
@@ -2115,11 +2166,10 @@ static int annotation__config(const char *var, const char *value, void *data)
21152166
else if (opt->offset_level < ANNOTATION__MIN_OFFSET_LEVEL)
21162167
opt->offset_level = ANNOTATION__MIN_OFFSET_LEVEL;
21172168
} else if (!strcmp(var, "annotate.disassemblers")) {
2118-
opt->disassemblers_str = strdup(value);
2119-
if (!opt->disassemblers_str) {
2120-
pr_err("Not enough memory for annotate.disassemblers\n");
2121-
return -1;
2122-
}
2169+
int err = annotation_options__add_disassemblers_str(opt, value);
2170+
2171+
if (err)
2172+
return err;
21232173
} else if (!strcmp(var, "annotate.hide_src_code")) {
21242174
opt->hide_src_code = perf_config_bool("hide_src_code", value);
21252175
} else if (!strcmp(var, "annotate.jump_arrows")) {
@@ -2185,9 +2235,25 @@ void annotation_options__exit(void)
21852235
zfree(&annotate_opts.objdump_path);
21862236
}
21872237

2238+
static void annotation_options__default_init_disassemblers(struct annotation_options *options)
2239+
{
2240+
if (options->disassemblers[0] != PERF_DISASM_UNKNOWN) {
2241+
/* Already initialized. */
2242+
return;
2243+
}
2244+
#ifdef HAVE_LIBLLVM_SUPPORT
2245+
annotation_options__add_disassembler(options, PERF_DISASM_LLVM);
2246+
#endif
2247+
#ifdef HAVE_LIBCAPSTONE_SUPPORT
2248+
annotation_options__add_disassembler(options, PERF_DISASM_CAPSTONE);
2249+
#endif
2250+
annotation_options__add_disassembler(options, PERF_DISASM_OBJDUMP);
2251+
}
2252+
21882253
void annotation_config__init(void)
21892254
{
21902255
perf_config(annotation__config, &annotate_opts);
2256+
annotation_options__default_init_disassemblers(&annotate_opts);
21912257
}
21922258

21932259
static unsigned int parse_percent_type(char *str1, char *str2)

tools/perf/util/annotate.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,13 @@ struct annotated_data_type;
3434
#define ANNOTATION__BR_CNTR_WIDTH 30
3535
#define ANNOTATION_DUMMY_LEN 256
3636

37-
// llvm, capstone, objdump
38-
#define MAX_DISASSEMBLERS 3
37+
enum perf_disassembler {
38+
PERF_DISASM_UNKNOWN = 0,
39+
PERF_DISASM_LLVM,
40+
PERF_DISASM_CAPSTONE,
41+
PERF_DISASM_OBJDUMP,
42+
};
43+
#define MAX_DISASSEMBLERS (PERF_DISASM_OBJDUMP + 1)
3944

4045
struct annotation_options {
4146
bool hide_src_code,
@@ -52,14 +57,12 @@ struct annotation_options {
5257
annotate_src,
5358
full_addr;
5459
u8 offset_level;
55-
u8 nr_disassemblers;
60+
u8 disassemblers[MAX_DISASSEMBLERS];
5661
int min_pcnt;
5762
int max_lines;
5863
int context;
5964
char *objdump_path;
6065
char *disassembler_style;
61-
const char *disassemblers_str;
62-
const char *disassemblers[MAX_DISASSEMBLERS];
6366
const char *prefix;
6467
const char *prefix_strip;
6568
unsigned int percent_type;
@@ -134,6 +137,8 @@ struct disasm_line {
134137
struct annotation_line al;
135138
};
136139

140+
extern const char * const perf_disassembler__strs[];
141+
137142
void annotation_line__add(struct annotation_line *al, struct list_head *head);
138143

139144
static inline double annotation_data__percent(struct annotation_data *data,

tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -431,9 +431,9 @@ static bool pid_filter__has(struct pids_filtered *pids, pid_t pid)
431431
static int augment_sys_enter(void *ctx, struct syscall_enter_args *args)
432432
{
433433
bool augmented, do_output = false;
434-
int zero = 0, size, aug_size, index,
435-
value_size = sizeof(struct augmented_arg) - offsetof(struct augmented_arg, value);
434+
int zero = 0, index, value_size = sizeof(struct augmented_arg) - offsetof(struct augmented_arg, value);
436435
u64 output = 0; /* has to be u64, otherwise it won't pass the verifier */
436+
s64 aug_size, size;
437437
unsigned int nr, *beauty_map;
438438
struct beauty_payload_enter *payload;
439439
void *arg, *payload_offset;
@@ -484,14 +484,11 @@ static int augment_sys_enter(void *ctx, struct syscall_enter_args *args)
484484
} else if (size > 0 && size <= value_size) { /* struct */
485485
if (!bpf_probe_read_user(((struct augmented_arg *)payload_offset)->value, size, arg))
486486
augmented = true;
487-
} else if (size < 0 && size >= -6) { /* buffer */
487+
} else if ((int)size < 0 && size >= -6) { /* buffer */
488488
index = -(size + 1);
489489
barrier_var(index); // Prevent clang (noticed with v18) from removing the &= 7 trick.
490490
index &= 7; // Satisfy the bounds checking with the verifier in some kernels.
491-
aug_size = args->args[index];
492-
493-
if (aug_size > TRACE_AUG_MAX_BUF)
494-
aug_size = TRACE_AUG_MAX_BUF;
491+
aug_size = args->args[index] > TRACE_AUG_MAX_BUF ? TRACE_AUG_MAX_BUF : args->args[index];
495492

496493
if (aug_size > 0) {
497494
if (!bpf_probe_read_user(((struct augmented_arg *)payload_offset)->value, aug_size, arg))

tools/perf/util/cpumap.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ struct aggr_cpu_id aggr_cpu_id__die(struct perf_cpu cpu, void *data)
293293

294294
die = cpu__get_die_id(cpu);
295295
/* There is no die_id on legacy system. */
296-
if (die == -1)
296+
if (die < 0)
297297
die = 0;
298298

299299
/*
@@ -322,7 +322,7 @@ struct aggr_cpu_id aggr_cpu_id__cluster(struct perf_cpu cpu, void *data)
322322
struct aggr_cpu_id id;
323323

324324
/* There is no cluster_id on legacy system. */
325-
if (cluster == -1)
325+
if (cluster < 0)
326326
cluster = 0;
327327

328328
id = aggr_cpu_id__die(cpu, data);

tools/perf/util/disasm.c

Lines changed: 15 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2216,56 +2216,6 @@ static int symbol__disassemble_objdump(const char *filename, struct symbol *sym,
22162216
return err;
22172217
}
22182218

2219-
static int annotation_options__init_disassemblers(struct annotation_options *options)
2220-
{
2221-
char *disassembler;
2222-
2223-
if (options->disassemblers_str == NULL) {
2224-
const char *default_disassemblers_str =
2225-
#ifdef HAVE_LIBLLVM_SUPPORT
2226-
"llvm,"
2227-
#endif
2228-
#ifdef HAVE_LIBCAPSTONE_SUPPORT
2229-
"capstone,"
2230-
#endif
2231-
"objdump";
2232-
2233-
options->disassemblers_str = strdup(default_disassemblers_str);
2234-
if (!options->disassemblers_str)
2235-
goto out_enomem;
2236-
}
2237-
2238-
disassembler = strdup(options->disassemblers_str);
2239-
if (disassembler == NULL)
2240-
goto out_enomem;
2241-
2242-
while (1) {
2243-
char *comma = strchr(disassembler, ',');
2244-
2245-
if (comma != NULL)
2246-
*comma = '\0';
2247-
2248-
options->disassemblers[options->nr_disassemblers++] = strim(disassembler);
2249-
2250-
if (comma == NULL)
2251-
break;
2252-
2253-
disassembler = comma + 1;
2254-
2255-
if (options->nr_disassemblers >= MAX_DISASSEMBLERS) {
2256-
pr_debug("annotate.disassemblers can have at most %d entries, ignoring \"%s\"\n",
2257-
MAX_DISASSEMBLERS, disassembler);
2258-
break;
2259-
}
2260-
}
2261-
2262-
return 0;
2263-
2264-
out_enomem:
2265-
pr_err("Not enough memory for annotate.disassemblers\n");
2266-
return -1;
2267-
}
2268-
22692219
int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
22702220
{
22712221
struct annotation_options *options = args->options;
@@ -2274,7 +2224,6 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
22742224
char symfs_filename[PATH_MAX];
22752225
bool delete_extract = false;
22762226
struct kcore_extract kce;
2277-
const char *disassembler;
22782227
bool decomp = false;
22792228
int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));
22802229

@@ -2334,28 +2283,26 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
23342283
}
23352284
}
23362285

2337-
err = annotation_options__init_disassemblers(options);
2338-
if (err)
2339-
goto out_remove_tmp;
2340-
23412286
err = -1;
2287+
for (u8 i = 0; i < ARRAY_SIZE(options->disassemblers) && err != 0; i++) {
2288+
enum perf_disassembler dis = options->disassemblers[i];
23422289

2343-
for (int i = 0; i < options->nr_disassemblers && err != 0; ++i) {
2344-
disassembler = options->disassemblers[i];
2345-
2346-
if (!strcmp(disassembler, "llvm"))
2290+
switch (dis) {
2291+
case PERF_DISASM_LLVM:
23472292
err = symbol__disassemble_llvm(symfs_filename, sym, args);
2348-
else if (!strcmp(disassembler, "capstone"))
2293+
break;
2294+
case PERF_DISASM_CAPSTONE:
23492295
err = symbol__disassemble_capstone(symfs_filename, sym, args);
2350-
else if (!strcmp(disassembler, "objdump"))
2296+
break;
2297+
case PERF_DISASM_OBJDUMP:
23512298
err = symbol__disassemble_objdump(symfs_filename, sym, args);
2352-
else
2353-
pr_debug("Unknown disassembler %s, skipping...\n", disassembler);
2354-
}
2355-
2356-
if (err == 0) {
2357-
pr_debug("Disassembled with %s\nannotate.disassemblers=%s\n",
2358-
disassembler, options->disassemblers_str);
2299+
break;
2300+
case PERF_DISASM_UNKNOWN: /* End of disassemblers. */
2301+
default:
2302+
goto out_remove_tmp;
2303+
}
2304+
if (err == 0)
2305+
pr_debug("Disassembled with %s\n", perf_disassembler__strs[dis]);
23592306
}
23602307
out_remove_tmp:
23612308
if (decomp)

0 commit comments

Comments
 (0)