[PATCH 2/5] perf genelf: Use unaligned-safe accessors for debug entries
From: Arnaldo Carvalho de Melo <acme@kernel.org>
Date: 2026-09-04 14:41:16
Also in:
lkml
Subsystem:
performance events subsystem, the rest · Maintainers:
Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Linus Torvalds
From: Arnaldo Carvalho de Melo <redacted> debug_entry records are packed with a variable-length name[] field, so entries after the first may start at addresses that are not naturally aligned. jit_process_debug_info(), get_special_opcode() and emit_lineno_info() read and write the u64 addr and int lineno fields through struct member access, which is undefined behavior on strict-alignment architectures. Use get_unaligned()/put_unaligned() to read and update each field, matching the layout the jitdump writers (LLVM, JVM agents) emit, which packs entries without padding. struct debug_entry.lineno is signed and emit_advance_lineno() takes a long line delta that relies on sign extension, so the field is read into an int: reading it into an unsigned int would turn a backward line jump into a huge forward one and corrupt the line number program. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Stephane Eranian <redacted> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <redacted> --- tools/perf/util/genelf_debug.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/tools/perf/util/genelf_debug.c b/tools/perf/util/genelf_debug.c
index 8588b3e35e008396..7d9ef43aa6ac4ab6 100644
--- a/tools/perf/util/genelf_debug.c
+++ b/tools/perf/util/genelf_debug.c@@ -12,6 +12,8 @@ */ #include <linux/compiler.h> #include <linux/zalloc.h> +#include <linux/kernel.h> +#include <linux/unaligned.h> #include <sys/types.h> #include <stdio.h> #include <getopt.h>
@@ -303,11 +305,13 @@ static ubyte get_special_opcode(struct debug_entry *ent, { unsigned int temp; unsigned long delta_addr; + int lineno = get_unaligned(&ent->lineno); + uint64_t addr = get_unaligned(&ent->addr); /* * delta from line_base */ - temp = (ent->lineno - last_line) - default_debug_line_header.line_base; + temp = (lineno - last_line) - default_debug_line_header.line_base; if (temp >= default_debug_line_header.line_range) return 0;
@@ -315,7 +319,7 @@ static ubyte get_special_opcode(struct debug_entry *ent, /* * delta of addresses */ - delta_addr = (ent->addr - last_vma) / default_debug_line_header.minimum_instruction_length; + delta_addr = (addr - last_vma) / default_debug_line_header.minimum_instruction_length; /* This is not sufficient to ensure opcode will be in [0-256] but * sufficient to ensure when summing with the delta lineno we will
@@ -362,6 +366,8 @@ static void emit_lineno_info(struct buffer_ext *be, for (i = 0; i < nr_entry; i++, ent = debug_entry_next(ent)) { int need_copy = 0; ubyte special_opcode; + int lineno = get_unaligned(&ent->lineno); + uint64_t addr = get_unaligned(&ent->addr); /* * check if filename changed, if so add it
@@ -376,24 +382,24 @@ static void emit_lineno_info(struct buffer_ext *be, special_opcode = get_special_opcode(ent, last_line, last_vma); if (special_opcode != 0) { - last_line = ent->lineno; - last_vma = ent->addr; + last_line = lineno; + last_vma = addr; emit_opcode(be, special_opcode); } else { /* * lines differ, emit line delta */ - if (last_line != ent->lineno) { - emit_advance_lineno(be, ent->lineno - last_line); - last_line = ent->lineno; + if (last_line != lineno) { + emit_advance_lineno(be, lineno - last_line); + last_line = lineno; need_copy = 1; } /* * addresses differ, emit address delta */ - if (last_vma != ent->addr) { - emit_advance_pc(be, ent->addr - last_vma); - last_vma = ent->addr; + if (last_vma != addr) { + emit_advance_pc(be, addr - last_vma); + last_vma = addr; need_copy = 1; } /*
@@ -480,7 +486,7 @@ jit_process_debug_info(uint64_t code_addr, int i; for (i = 0; i < nr_debug_entries; i++) { - ent->addr = ent->addr - code_addr; + put_unaligned(get_unaligned(&ent->addr) - code_addr, &ent->addr); ent = debug_entry_next(ent); } add_compilation_unit(di, buffer_ext_size(dl));
--
2.55.0