Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package crash for openSUSE:Factory checked in at 2026-09-18 22:08:11 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/crash (Old) and /work/SRC/openSUSE:Factory/.crash.new.383539 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "crash" Fri Sep 18 22:08:11 2026 rev:200 rq:1378796 version:9.0.2 Changes: -------- --- /work/SRC/openSUSE:Factory/crash/crash.changes 2026-06-25 10:54:57.240709436 +0200 +++ /work/SRC/openSUSE:Factory/.crash.new.383539/crash.changes 2026-09-18 22:08:49.280333756 +0200 @@ -1,0 +2,21 @@ +Fri Aug 14 06:10:08 UTC 2026 - Jiri Slaby <[email protected]> + +- add crash-symbols-use-non-debug-BFD-to-retrieve-.rodata.patch + +------------------------------------------------------------------- +Wed Aug 12 08:53:28 UTC 2026 - Jiri Slaby <[email protected]> + +- support kernel 7.1 + 7.2 -- add: + * crash-support-kernel-7.x-and-8.x.patch + * crash-Fix-compound_head-and-bt-F-option-on-Linux-7.1-and-l.patch + * crash-Fix-failure-of-runq-g-option-on-Linux-7.2-and-later-.patch + * crash-Fix-kmem-i-option-to-display-swap-usage-on-Linux-6.1.patch + * crash-Fix-kmem-s-command-on-Linux-7.1-and-later.patch + * crash-Fix-runq-g-option-to-display-task_group-name-on-Linu.patch + * crash-Fix-swap-command-on-Linux-7.1-and-later.patch + * crash-symbols-Add-support-for-mod-symtab-with-combined-GPL.patch + * crash-x86_64-Fix-bt-command-for-noreturn-functions.patch + * crash-x86_64-Fix-bt-command-to-use-correct-ORC-register-va.patch + * crash-x86_64-Make-ORC_REG_SP-and-ORC_REG_PREV_SP-independe.patch + +------------------------------------------------------------------- New: ---- crash-Fix-compound_head-and-bt-F-option-on-Linux-7.1-and-l.patch crash-Fix-failure-of-runq-g-option-on-Linux-7.2-and-later-.patch crash-Fix-kmem-i-option-to-display-swap-usage-on-Linux-6.1.patch crash-Fix-kmem-s-command-on-Linux-7.1-and-later.patch crash-Fix-runq-g-option-to-display-task_group-name-on-Linu.patch crash-Fix-swap-command-on-Linux-7.1-and-later.patch crash-support-kernel-7.x-and-8.x.patch crash-symbols-Add-support-for-mod-symtab-with-combined-GPL.patch crash-symbols-use-non-debug-BFD-to-retrieve-.rodata.patch crash-x86_64-Fix-bt-command-for-noreturn-functions.patch crash-x86_64-Fix-bt-command-to-use-correct-ORC-register-va.patch crash-x86_64-Make-ORC_REG_SP-and-ORC_REG_PREV_SP-independe.patch ----------(New B)---------- New: * crash-support-kernel-7.x-and-8.x.patch * crash-Fix-compound_head-and-bt-F-option-on-Linux-7.1-and-l.patch * crash-Fix-failure-of-runq-g-option-on-Linux-7.2-and-later-.patch New: * crash-Fix-compound_head-and-bt-F-option-on-Linux-7.1-and-l.patch * crash-Fix-failure-of-runq-g-option-on-Linux-7.2-and-later-.patch * crash-Fix-kmem-i-option-to-display-swap-usage-on-Linux-6.1.patch New: * crash-Fix-failure-of-runq-g-option-on-Linux-7.2-and-later-.patch * crash-Fix-kmem-i-option-to-display-swap-usage-on-Linux-6.1.patch * crash-Fix-kmem-s-command-on-Linux-7.1-and-later.patch New: * crash-Fix-kmem-i-option-to-display-swap-usage-on-Linux-6.1.patch * crash-Fix-kmem-s-command-on-Linux-7.1-and-later.patch * crash-Fix-runq-g-option-to-display-task_group-name-on-Linu.patch New: * crash-Fix-kmem-s-command-on-Linux-7.1-and-later.patch * crash-Fix-runq-g-option-to-display-task_group-name-on-Linu.patch * crash-Fix-swap-command-on-Linux-7.1-and-later.patch New: * crash-Fix-runq-g-option-to-display-task_group-name-on-Linu.patch * crash-Fix-swap-command-on-Linux-7.1-and-later.patch * crash-symbols-Add-support-for-mod-symtab-with-combined-GPL.patch New:- support kernel 7.1 + 7.2 -- add: * crash-support-kernel-7.x-and-8.x.patch * crash-Fix-compound_head-and-bt-F-option-on-Linux-7.1-and-l.patch New: * crash-Fix-swap-command-on-Linux-7.1-and-later.patch * crash-symbols-Add-support-for-mod-symtab-with-combined-GPL.patch * crash-x86_64-Fix-bt-command-for-noreturn-functions.patch New: - add crash-symbols-use-non-debug-BFD-to-retrieve-.rodata.patch New: * crash-symbols-Add-support-for-mod-symtab-with-combined-GPL.patch * crash-x86_64-Fix-bt-command-for-noreturn-functions.patch * crash-x86_64-Fix-bt-command-to-use-correct-ORC-register-va.patch New: * crash-x86_64-Fix-bt-command-for-noreturn-functions.patch * crash-x86_64-Fix-bt-command-to-use-correct-ORC-register-va.patch * crash-x86_64-Make-ORC_REG_SP-and-ORC_REG_PREV_SP-independe.patch New: * crash-x86_64-Fix-bt-command-to-use-correct-ORC-register-va.patch * crash-x86_64-Make-ORC_REG_SP-and-ORC_REG_PREV_SP-independe.patch ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ crash.spec ++++++ --- /var/tmp/diff_new_pack.7K3olc/_old 2026-09-18 22:08:51.902443649 +0200 +++ /var/tmp/diff_new_pack.7K3olc/_new 2026-09-18 22:08:51.903443690 +0200 @@ -79,9 +79,14 @@ Source99: crash-rpmlintrc Source100: %{name}-gdb-10.2.series Source101: %{name}-gdb-gnulib-define-warndecl.patch +Patch0: %{name}-symbols-Add-support-for-mod-symtab-with-combined-GPL.patch Patch1: %{name}-make-emacs-default.diff Patch2: %{name}-sles9-quirk.patch +Patch3: %{name}-symbols-use-non-debug-BFD-to-retrieve-.rodata.patch Patch4: %{name}-sles9-time.patch +Patch5: %{name}-support-kernel-7.x-and-8.x.patch +Patch6: %{name}-Fix-compound_head-and-bt-F-option-on-Linux-7.1-and-l.patch +Patch7: %{name}-Fix-kmem-s-command-on-Linux-7.1-and-later.patch Patch9: %{name}-debuginfo-compressed.patch Patch10: %{name}_enable_lzo_support.patch Patch11: %{name}-compressed-booted-kernel.patch @@ -93,6 +98,13 @@ Patch24: %{name}-SLE15-SP1-Fix-for-PPC64-kernel-virtual-address-translation-in.patch Patch30: %{name}-enable-zstd-support.patch Patch32: %{name}-extensions-rule-for-defs.patch +Patch33: %{name}-x86_64-Fix-bt-command-for-noreturn-functions.patch +Patch34: %{name}-x86_64-Fix-bt-command-to-use-correct-ORC-register-va.patch +Patch35: %{name}-Fix-kmem-i-option-to-display-swap-usage-on-Linux-6.1.patch +Patch36: %{name}-Fix-swap-command-on-Linux-7.1-and-later.patch +Patch37: %{name}-Fix-failure-of-runq-g-option-on-Linux-7.2-and-later-.patch +Patch38: %{name}-Fix-runq-g-option-to-display-task_group-name-on-Linu.patch +Patch39: %{name}-x86_64-Make-ORC_REG_SP-and-ORC_REG_PREV_SP-independe.patch Patch90: %{name}-sial-ps-2.6.29.diff Patch99: %{name}-usrmerge.patch Patch100: gcore-fix-use-of-set_context.patch @@ -237,15 +249,27 @@ %prep %setup -q -a 2 -a 4 ln -s %{SOURCE1} . +%patch -P 0 -p1 %patch -P 1 -p1 %patch -P 2 -p1 +%patch -P 3 -p1 %patch -P 4 -p1 +%patch -P 5 -p1 +%patch -P 6 -p1 +%patch -P 7 -p1 %patch -P 9 -p1 %patch -P 10 -p1 %patch -P 11 -p1 %patch -P 13 -p1 %patch -P 18 -p1 %patch -P 21 -p1 +%patch -P 33 -p1 +%patch -P 34 -p1 +%patch -P 35 -p1 +%patch -P 36 -p1 +%patch -P 37 -p1 +%patch -P 38 -p1 +%patch -P 39 -p1 # Patches for SLE 15 SP1 potentially break support for SLE15 and SLE 12 SP4 # Don't apply on these (and earlier) versions - see bsc#1148197 %if 0%{?sle_version} > 120400 && 0%{?sle_version} != 150000 ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.7K3olc/_old 2026-09-18 22:08:52.069450648 +0200 +++ /var/tmp/diff_new_pack.7K3olc/_new 2026-09-18 22:08:52.076450941 +0200 @@ -1,6 +1,6 @@ -mtime: 1782137279 -commit: 7b166c900f7fa8084fef466c1483d00c55710aba7a771e34f5b98b473a9d4fa4 +mtime: 1788772306 +commit: 07270857be0dbd49b66b738d9204c75e879d4d455573c27ac13f06c78d9f95e8 url: https://src.opensuse.org/kernel-kdump/crash -revision: 7b166c900f7fa8084fef466c1483d00c55710aba7a771e34f5b98b473a9d4fa4 +revision: 07270857be0dbd49b66b738d9204c75e879d4d455573c27ac13f06c78d9f95e8 projectscmsync: https://src.opensuse.org/kernel-kdump/_ObsPrj ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-09-07 11:11:46.000000000 +0200 @@ -0,0 +1 @@ +.osc ++++++ crash-Fix-compound_head-and-bt-F-option-on-Linux-7.1-and-l.patch ++++++ From: Kazuhito Hagio <[email protected]> Date: Thu, 23 Jul 2026 05:09:48 +0000 Subject: Fix compound_head() and "bt -F" option on Linux 7.1 and later References: kernel 7.1 Git-repo: https://github.com/crash-utility/crash Git-commit: fa55e121672c5e1a974ebc4af3789b7f25f2269b Patch-mainline: yes Kernel commit d50569612c29 ("mm: rename the 'compound_head' field in the 'struct page' to 'compound_info'") and related patches [1] changed the field name and its value. Without the patch, crash prints the following warning during startup, WARNING: SLUB: cannot determine how compound pages are linked and "bt -F" option fails with the following error. crash> bt -F bt: invalid structure member offset: page_first_page FILE: memory.c LINE: 20238 FUNCTION: compound_head() [1] https://lore.kernel.org/all/[email protected]/ Signed-off-by: Kazuhito Hagio <[email protected]> Acked-by: Tao Liu <[email protected]> Acked-by: Dave Young <[email protected]> Signed-off-by: Dave Young <[email protected]> Signed-off-by: Jiri Slaby <[email protected]> --- defs.h | 1 + memory.c | 44 ++++++++++++++++++++++++++++++++++++-------- symbols.c | 1 + 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/defs.h b/defs.h index e3027e2b9141..88b7bbeb2372 100644 --- a/defs.h +++ b/defs.h @@ -2290,6 +2290,7 @@ struct offset_table { /* stash of commonly-used offsets */ long bpf_ringbuf_nr_pages; long hrtimer_clock_base_index; long klp_patch_list; + long page_compound_info; }; struct size_table { /* stash of commonly-used sizes */ diff --git a/memory.c b/memory.c index 3f3aa274ab5a..5163ee663641 100644 --- a/memory.c +++ b/memory.c @@ -410,6 +410,7 @@ mem_init(void) DISPLAY_DEFAULT = (sizeof(long) == 8) ? DISPLAY_64 : DISPLAY_32; } +static int compound_info_has_mask = FALSE; /* * Stash a few popular offsets and some basic kernel virtual memory @@ -547,6 +548,7 @@ vm_init(void) MEMBER_OFFSET_INIT(page_compound_head, "page", "compound_head"); if (INVALID_MEMBER(page_compound_head)) ANON_MEMBER_OFFSET_INIT(page_compound_head, "page", "compound_head"); + MEMBER_OFFSET_INIT(page_compound_info, "page", "compound_info"); MEMBER_OFFSET_INIT(page_private, "page", "private"); MEMBER_OFFSET_INIT(page_freelist, "page", "freelist"); MEMBER_OFFSET_INIT(page_page_type, "page", "page_type"); @@ -1352,6 +1354,17 @@ vm_init(void) } else if (CRASHDEBUG(1)) error(NOTE, "page_hash_table does not exist in this kernel\n"); + /* + * on Linux 7.1 and later, zone.vmemmap_tails is defined only when + * CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP is enabled. + */ +#define is_power_of_2(n) ((n) > 0 && ((n) & ((n) - 1)) == 0) + if (VALID_MEMBER(page_compound_info) && + is_power_of_2(SIZE(page)) && MEMBER_EXISTS("zone", "vmemmap_tails")) + compound_info_has_mask = TRUE; + if (CRASHDEBUG(1)) + error(NOTE, "compound_info_has_mask = %d\n", compound_info_has_mask); + kmem_cache_init(); page_flags_init(); @@ -5642,10 +5655,11 @@ PG_slab_flag_init(void) } } - if (VALID_MEMBER(page_compound_head)) { + if (VALID_MEMBER(page_compound_head) || VALID_MEMBER(page_compound_info)) { if (CRASHDEBUG(2)) fprintf(fp, - "PG_head_tail_mask: (UNUSED): page.compound_head exists!\n"); + "PG_head_tail_mask: (UNUSED): page.compound_head or " + "page.compound_info exists!\n"); } else if (vt->flags & KMALLOC_SLUB) { /* * PG_slab and the following are hardwired for @@ -9858,7 +9872,8 @@ vaddr_to_kmem_cache(ulong vaddr, char *buf, int verbose) &page_flags, sizeof(ulong), "page.flags", FAULT_ON_ERROR); if (!page_slab(page, page_flags)) { - if (((vt->flags & KMALLOC_SLUB) || VALID_MEMBER(page_compound_head)) || + if (((vt->flags & KMALLOC_SLUB) || VALID_MEMBER(page_compound_head) || + VALID_MEMBER(page_compound_info)) || ((vt->flags & KMALLOC_COMMON) && VALID_MEMBER(page_slab) && VALID_MEMBER(page_first_page))) { readmem(compound_head(page)+OFFSET(page_flags), KVADDR, @@ -9873,7 +9888,8 @@ vaddr_to_kmem_cache(ulong vaddr, char *buf, int verbose) if ((vt->flags & KMALLOC_SLUB) || ((vt->flags & KMALLOC_COMMON) && VALID_MEMBER(page_slab) && - (VALID_MEMBER(page_compound_head) || VALID_MEMBER(page_first_page)))) { + (VALID_MEMBER(page_compound_head) || VALID_MEMBER(page_compound_info) || + VALID_MEMBER(page_first_page)))) { readmem(compound_head(page)+OFFSET(page_slab), KVADDR, &cache, sizeof(void *), "page.slab", FAULT_ON_ERROR); @@ -9904,7 +9920,8 @@ is_slab_overload_page(ulong vaddr, ulong *page_head, char *buf) if ((vt->flags & SLAB_OVERLOAD_PAGE) && is_page_ptr(vaddr, NULL) && VALID_MEMBER(page_slab) && - (VALID_MEMBER(page_compound_head) || VALID_MEMBER(page_first_page))) { + (VALID_MEMBER(page_compound_head) || VALID_MEMBER(page_compound_info) || + VALID_MEMBER(page_first_page))) { readmem(compound_head(vaddr)+OFFSET(page_slab), KVADDR, &cache, sizeof(void *), "page.slab", FAULT_ON_ERROR); @@ -9944,7 +9961,8 @@ vaddr_to_slab(ulong vaddr) slab = 0; - if ((vt->flags & KMALLOC_SLUB) || VALID_MEMBER(page_compound_head)) + if ((vt->flags & KMALLOC_SLUB) || VALID_MEMBER(page_compound_head) || + VALID_MEMBER(page_compound_info)) slab = compound_head(page); else if (vt->flags & SLAB_OVERLOAD_PAGE) slab = compound_head(page); @@ -20222,11 +20240,21 @@ get_kmem_cache_child_list(ulong **cache_buf, ulong root) static ulong compound_head(ulong page) { - ulong flags, first_page, compound_head; + ulong flags, first_page, compound_head, info, mask; first_page = page; - if (VALID_MEMBER(page_compound_head)) { + if (VALID_MEMBER(page_compound_info)) { + if (readmem(page + OFFSET(page_compound_info), KVADDR, &info, + sizeof(ulong), "page.compound_info", RETURN_ON_ERROR)) { + if (compound_info_has_mask) { + mask = (info & 1) - 1; + mask |= info; + first_page = page & mask; + } else if (info & 1) + first_page = info - 1; + } + } else if (VALID_MEMBER(page_compound_head)) { if (readmem(page+OFFSET(page_compound_head), KVADDR, &compound_head, sizeof(ulong), "page.compound_head", RETURN_ON_ERROR)) { if (compound_head & 1) diff --git a/symbols.c b/symbols.c index a7ccdb101033..1b734d775361 100644 --- a/symbols.c +++ b/symbols.c @@ -10505,6 +10505,7 @@ dump_offset_table(char *spec, ulong makestruct) OFFSET(page_active)); fprintf(fp, " page_compound_head: %ld\n", OFFSET(page_compound_head)); + fprintf(fp, " page_compound_info: %ld\n", OFFSET(page_compound_info)); fprintf(fp, " page_private: %ld\n", OFFSET(page_private)); fprintf(fp, " page_page_type: %ld\n", OFFSET(page_page_type)); -- 2.55.0 ++++++ crash-Fix-failure-of-runq-g-option-on-Linux-7.2-and-later-.patch ++++++ From: Kazuhito Hagio <[email protected]> Date: Wed, 8 Jul 2026 02:45:50 +0000 Subject: Fix failure of "runq -g" option on Linux 7.2 and later kernels References: kernel 7.1 Git-repo: https://github.com/crash-utility/crash Git-commit: 82039b0f21de4231d1fc03e8819c868a84b213f8 Patch-mainline: yes Kernel commit b8fea7af0e40 ("sched/fair: Allocate cfs_tg_state with percpu allocator") changed task_group.cfs_rq from a pointer array to a per-cpu variable allocated by the per-cpu allocator. Without the patch, the "runq -g" option fails with the following error on the first time, and with a segmentation fault on the second time. crash> runq -g CPU 0 CURRENT: PID: 5687 TASK: ffff8b0bc175a2c0 COMMAND: "bash" ROOT_TASK_GROUP: ffffffff93a55600 CFS_RQ: 0 runq: invalid kernel virtual address: 58 type: "curr" crash> runq -g Segmentation fault (core dumped) Since there is no way to determine whether it is a per-cpu variable, check wthether it is a pointer array or not. Signed-off-by: Kazuhito Hagio <[email protected]> Signed-off-by: Jiri Slaby <[email protected]> --- defs.h | 2 ++ kernel.c | 14 ++++++++++++++ symbols.c | 27 +++++++++++++++++++++++++++ task.c | 30 ++++++++++++++++++++++-------- 4 files changed, 65 insertions(+), 8 deletions(-) diff --git a/defs.h b/defs.h index d7bcdd083671..e3027e2b9141 100644 --- a/defs.h +++ b/defs.h @@ -691,6 +691,7 @@ struct new_utsname { #define KMOD_PAX (0x100ULL) #define KMOD_MEMORY (0x200ULL) #define IRQ_DESC_TREE_MAPLE (0x400ULL) +#define PER_CPU_CFS_RQ (0x800ULL) #define XEN() (kt->flags & ARCH_XEN) #define OPENVZ() (kt->flags & ARCH_OPENVZ) @@ -5886,6 +5887,7 @@ void parse_for_member_extended(struct datatype_member *, ulong); void add_to_downsized(char *); int is_downsized(char *); int is_string(char *, char *); +int is_ptrptr(char *, char *); struct syment *symbol_complete_match(const char *, struct syment *); /* diff --git a/kernel.c b/kernel.c index eb9754c5e082..e53038d5d8db 100644 --- a/kernel.c +++ b/kernel.c @@ -400,6 +400,18 @@ kernel_init() MEMBER_OFFSET_INIT(task_group_rt_rq, "task_group", "rt_rq"); MEMBER_OFFSET_INIT(task_group_parent, "task_group", "parent"); + /* + * task_group.cfs_rq was changed from a pointer array to a per-cpu + * variable at Linux 7.2 (b8fea7af0e40). Since there is no way to + * determine it, we check whether it is a pointer array or not. + * - struct cfs_rq **cfs_rq; + * + struct cfs_rq __percpu *cfs_rq; + */ + if (VALID_MEMBER(task_group_cfs_rq)) { + if (!is_ptrptr("task_group", "cfs_rq")) + kt->flags2 |= PER_CPU_CFS_RQ; + } + /* * In 2.4, smp_send_stop() sets smp_num_cpus back to 1 * in some, but not all, architectures. So if a count @@ -6362,6 +6374,8 @@ dump_kernel_table(int verbose) fprintf(fp, "%sKMOD_PAX", others++ ? "|" : ""); if (kt->flags2 & KMOD_MEMORY) fprintf(fp, "%sKMOD_MEMORY", others++ ? "|" : ""); + if (kt->flags2 & PER_CPU_CFS_RQ) + fprintf(fp, "%sPER_CPU_CFS_RQ", others++ ? "|" : ""); fprintf(fp, ")\n"); fprintf(fp, " stext: %lx\n", kt->stext); diff --git a/symbols.c b/symbols.c index 78e400ba3756..03511c8cbe8c 100644 --- a/symbols.c +++ b/symbols.c @@ -7933,6 +7933,33 @@ is_string(char *structure, char *member) return retval; } +int +is_ptrptr(char *structure, char *member) +{ + int retval; + char *t; + char buf[BUFSIZE]; + + retval = FALSE; + open_tmpfile(); + whatis_datatype(structure, STRUCT_REQUEST, pc->tmpfile); + rewind(pc->tmpfile); + while (fgets(buf, BUFSIZE, pc->tmpfile)) { + if (!(t = strstr(buf, "**"))) + continue; + t += 2; + if (t != strstr(t, member)) + continue; + t += strlen(member); + if (*t == ';') { + retval = TRUE; + break; + } + } + close_tmpfile(); + + return retval; +} /* * Generic function for dumping data structure declarations, with a small diff --git a/task.c b/task.c index 7dacb05b2406..b95d3d7fb2af 100644 --- a/task.c +++ b/task.c @@ -9542,8 +9542,12 @@ print_parent_task_group_fair(void *t, int cpu) readmem(tgi->task_group + OFFSET(task_group_cfs_rq), KVADDR, &cfs_rq_c, sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR); - readmem(cfs_rq_c + cpu * sizeof(ulong), KVADDR, &cfs_rq_p, - sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR); + + if (kt->flags2 & PER_CPU_CFS_RQ) + cfs_rq_p = cfs_rq_c + kt->__per_cpu_offset[cpu]; + else + readmem(cfs_rq_c + cpu * sizeof(ulong), KVADDR, &cfs_rq_p, + sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR); print_group_header_fair(tgi->depth, cfs_rq_p, tgi); tgi->use = 0; @@ -9569,8 +9573,13 @@ dump_tasks_in_lower_dequeued_cfs_rq(int depth, ulong cfs_rq, int cpu, readmem(tgi_array[i]->task_group + OFFSET(task_group_cfs_rq), KVADDR, &cfs_rq_c, sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR); - readmem(cfs_rq_c + cpu * sizeof(ulong), KVADDR, &cfs_rq_p, - sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR); + + if (kt->flags2 & PER_CPU_CFS_RQ) + cfs_rq_p = cfs_rq_c + kt->__per_cpu_offset[cpu]; + else + readmem(cfs_rq_c + cpu * sizeof(ulong), KVADDR, &cfs_rq_p, + sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR); + if (cfs_rq == cfs_rq_p) continue; @@ -10433,10 +10442,15 @@ dump_tasks_by_task_group(void) readmem(rt_rq + cpu * sizeof(ulong), KVADDR, &rt_rq_p, sizeof(ulong), "task_group rt_rq", FAULT_ON_ERROR); - if (cfs_rq) - readmem(cfs_rq + cpu * sizeof(ulong), KVADDR, - &cfs_rq_p, sizeof(ulong), "task_group cfs_rq", - FAULT_ON_ERROR); + if (cfs_rq) { + if (kt->flags2 & PER_CPU_CFS_RQ) + cfs_rq_p = cfs_rq + kt->__per_cpu_offset[cpu]; + else + readmem(cfs_rq + cpu * sizeof(ulong), KVADDR, + &cfs_rq_p, sizeof(ulong), + "task_group cfs_rq", FAULT_ON_ERROR); + } + fprintf(fp, "%sCPU %d", displayed++ ? "\n" : "", cpu); if (hide_offline_cpu(cpu)) { -- 2.55.0 ++++++ crash-Fix-kmem-i-option-to-display-swap-usage-on-Linux-6.1.patch ++++++ From: Kazuhito Hagio <[email protected]> Date: Wed, 3 Jun 2026 07:12:57 +0000 Subject: Fix "kmem -i" option to display swap usage on Linux 6.18 and later References: kernel 7.1 Git-repo: https://github.com/crash-utility/crash Git-commit: c894f05d3cdc5d3e61775c3f67bd6a0a24362a92 Patch-mainline: yes Kernel commit 8578e0c00dcf ("mm, swap: use the swap table to track the swap count"), which is contained in Linux 6.18 and later kernels, removed swapper_spaces symbol. As a result, "kmem -i" skips swap usage output because the existing check only looks for swapper_space/swapper_spaces. Also check for the swap_info symbol so dump_swap_info() is called on newer kernels as well. Signed-off-by: Kazuhito Hagko <[email protected]> Signed-off-by: Jiri Slaby <[email protected]> --- memory.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/memory.c b/memory.c index 38c6a139e984..15946c58eaf2 100644 --- a/memory.c +++ b/memory.c @@ -8871,7 +8871,8 @@ dump_kmeminfo(struct meminfo *mi) * get swap data from dump_swap_info(). */ fprintf(fp, "\n"); - if (symbol_exists("swapper_space") || symbol_exists("swapper_spaces")) { + if (symbol_exists("swap_info") || + symbol_exists("swapper_space") || symbol_exists("swapper_spaces")) { if (dump_swap_info(RETURN_ON_ERROR, &totalswap_pages, &totalused_pages)) { fprintf(fp, "%13s %7ld %11s ----\n", -- 2.55.0 ++++++ crash-Fix-kmem-s-command-on-Linux-7.1-and-later.patch ++++++ From: Kazuhito Hagio <[email protected]> Date: Fri, 24 Jul 2026 01:27:22 +0000 Subject: Fix "kmem [-s]" command on Linux 7.1 and later References: kernel 7.1 Git-repo: https://github.com/crash-utility/crash Git-commit: bb9a3fa67a79309fac6c805584c5b092c480c09a Patch-mainline: yes Kernel commit 5ba6bc27b1f9 ("slab: decouple pointer to barn from kmem_cache_node") changed kmem_cache.node array into struct kmem_cache_per_node_ptrs kmem_cache.per_node array. Without the patch, "kmem <slab address>" and "kmem -s" option fail with the following error. crash> kmem -s kmem: invalid structure member offset: kmem_cache_local_node FILE: memory.c LINE: 19563 FUNCTION: get_kmem_cache_slub_data() Signed-off-by: Kazuhito Hagio <[email protected]> Acked-by: Tao Liu <[email protected]> Acked-by: Dave Young <[email protected]> Signed-off-by: Dave Young <[email protected]> Signed-off-by: Jiri Slaby <[email protected]> --- defs.h | 3 +++ memory.c | 19 +++++++++++++++---- symbols.c | 4 ++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/defs.h b/defs.h index 88b7bbeb2372..ef34db90113f 100644 --- a/defs.h +++ b/defs.h @@ -2291,6 +2291,8 @@ struct offset_table { /* stash of commonly-used offsets */ long hrtimer_clock_base_index; long klp_patch_list; long page_compound_info; + long kmem_cache_per_node; + long kmem_cache_per_node_ptrs_node; }; struct size_table { /* stash of commonly-used sizes */ @@ -2470,6 +2472,8 @@ struct size_table { /* stash of commonly-used sizes */ long cpumask_t; long task_struct_exit_state; long bpf_ringbuf_map; + long page_compound_order; + long kmem_cache_per_node_ptrs; }; struct array_table { diff --git a/memory.c b/memory.c index 5163ee663641..f2304f3ffe2f 100644 --- a/memory.c +++ b/memory.c @@ -871,6 +871,8 @@ vm_init(void) MEMBER_OFFSET_INIT(kmem_cache_inuse, "kmem_cache", "inuse"); MEMBER_OFFSET_INIT(kmem_cache_align, "kmem_cache", "align"); MEMBER_OFFSET_INIT(kmem_cache_node, "kmem_cache", "node"); + if (INVALID_MEMBER(kmem_cache_node)) + MEMBER_OFFSET_INIT(kmem_cache_per_node, "kmem_cache", "per_node"); MEMBER_OFFSET_INIT(kmem_cache_cpu_slab, "kmem_cache", "cpu_slab"); MEMBER_OFFSET_INIT(kmem_cache_list, "kmem_cache", "list"); MEMBER_OFFSET_INIT(kmem_cache_red_left_pad, "kmem_cache", "red_left_pad"); @@ -922,7 +924,12 @@ vm_init(void) if (INVALID_MEMBER(page_objects)) ANON_MEMBER_OFFSET_INIT(page_objects, "slab", "objects"); } - if (VALID_MEMBER(kmem_cache_node)) { + if (VALID_MEMBER(kmem_cache_per_node)) { /* Linux 7.1 and later */ + MEMBER_OFFSET_INIT(kmem_cache_per_node_ptrs_node, + "kmem_cache_per_node_ptrs", "node"); + STRUCT_SIZE_INIT(kmem_cache_per_node_ptrs, "kmem_cache_per_node_ptrs"); + vt->flags |= CONFIG_NUMA; + } else if (VALID_MEMBER(kmem_cache_node)) { ARRAY_LENGTH_INIT(len, NULL, "kmem_cache.node", NULL, 0); vt->flags |= CONFIG_NUMA; } @@ -19555,9 +19562,13 @@ get_kmem_cache_slub_data(long cmd, struct meminfo *si) for (n = 0; n < vt->numnodes; n++) { if (vt->flags & CONFIG_NUMA) { nt = &vt->node_table[n]; - node_ptr = ULONG(si->cache_buf + - OFFSET(kmem_cache_node) + - (sizeof(void *) * nt->node_id)); + if (VALID_MEMBER(kmem_cache_per_node)) /* Linux 7.1 and later */ + node_ptr = ULONG(si->cache_buf + OFFSET(kmem_cache_per_node) + + (SIZE(kmem_cache_per_node_ptrs) * nt->node_id) + + OFFSET(kmem_cache_per_node_ptrs_node)); + else + node_ptr = ULONG(si->cache_buf + OFFSET(kmem_cache_node) + + (sizeof(void *) * nt->node_id)); } else node_ptr = si->cache + OFFSET(kmem_cache_local_node); diff --git a/symbols.c b/symbols.c index 1b734d775361..1515385d5724 100644 --- a/symbols.c +++ b/symbols.c @@ -10933,6 +10933,9 @@ dump_offset_table(char *spec, ulong makestruct) OFFSET(kmem_cache_oo)); fprintf(fp, " kmem_cache_random: %ld\n", OFFSET(kmem_cache_random)); + fprintf(fp, " kmem_cache_per_node: %ld\n", OFFSET(kmem_cache_per_node)); + + fprintf(fp, " kmem_cache_per_node_ptrs_node: %ld\n", OFFSET(kmem_cache_per_node_ptrs_node)); fprintf(fp, " kmem_cache_node_nr_partial: %ld\n", OFFSET(kmem_cache_node_nr_partial)); @@ -12044,6 +12047,7 @@ dump_offset_table(char *spec, ulong makestruct) fprintf(fp, " kmem_cache: %ld\n", SIZE(kmem_cache)); fprintf(fp, " kmem_cache_node: %ld\n", SIZE(kmem_cache_node)); fprintf(fp, " kmem_cache_cpu: %ld\n", SIZE(kmem_cache_cpu)); + fprintf(fp, " kmem_cache_per_node_ptrs: %ld\n", SIZE(kmem_cache_per_node_ptrs)); fprintf(fp, " swap_info_struct: %ld\n", SIZE(swap_info_struct)); -- 2.55.0 ++++++ crash-Fix-runq-g-option-to-display-task_group-name-on-Linu.patch ++++++ From: Kazuhito Hagio <[email protected]> Date: Wed, 8 Jul 2026 02:45:50 +0000 Subject: Fix "runq -g" option to display task_group name on Linux 6.15 and later References: kernel 7.1 Git-repo: https://github.com/crash-utility/crash Git-commit: f336dfa79ed94895914e132c31f2db7e09bf4ab1 Patch-mainline: yes Kernel commit 633488947ef66 ("kernfs: Use RCU to access kernfs_node::parent.") changed the "parent" member name in struct kernfs_node to "__parent". Without the patch, the "rung -g" option cannot display task_group's name: crash> runq -g CPU 0 CURRENT: PID: 5687 TASK: ffff8b0bc175a2c0 COMMAND: "bash" ROOT_TASK_GROUP: ffffffff93a55600 CFS_RQ: ffff8b0cf8232240 TASK_GROUP: ffff8b0b942a1e00 CFS_RQ: fffff1b5ffc0d540 TASK_GROUP: ffff8b0bc0f27900 CFS_RQ: fffff1b5ffc23f80 TASK_GROUP: ffff8b0b862fcc00 CFS_RQ: fffff1b5ffc29f00 [120] PID: 5687 TASK: ffff8b0bc175a2c0 COMMAND: "bash" [CURRENT] With the patch: crash> runq -g CPU 0 CURRENT: PID: 5687 TASK: ffff8b0bc175a2c0 COMMAND: "bash" ROOT_TASK_GROUP: ffffffff93a55600 CFS_RQ: ffff8b0cf8232240 TASK_GROUP: ffff8b0b942a1e00 CFS_RQ: fffff1b5ffc0d540 <user.slice> TASK_GROUP: ffff8b0bc0f27900 CFS_RQ: fffff1b5ffc23f80 <user-0.slice> TASK_GROUP: ffff8b0b862fcc00 CFS_RQ: fffff1b5ffc29f00 <session-2.scope> [120] PID: 5687 TASK: ffff8b0bc175a2c0 COMMAND: "bash" [CURRENT] Signed-off-by: Kazuhito Hagio <[email protected]> Signed-off-by: Jiri Slaby <[email protected]> --- task.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/task.c b/task.c index b95d3d7fb2af..a4118766fb42 100644 --- a/task.c +++ b/task.c @@ -9879,6 +9879,8 @@ task_group_offset_init(void) MEMBER_OFFSET_INIT(cgroup_kn, "cgroup", "kn"); MEMBER_OFFSET_INIT(kernfs_node_name, "kernfs_node", "name"); MEMBER_OFFSET_INIT(kernfs_node_parent, "kernfs_node", "parent"); + if (INVALID_MEMBER(kernfs_node_parent)) + MEMBER_OFFSET_INIT(kernfs_node_parent, "kernfs_node", "__parent"); MEMBER_OFFSET_INIT(task_group_siblings, "task_group", "siblings"); MEMBER_OFFSET_INIT(task_group_children, "task_group", "children"); -- 2.55.0 ++++++ crash-Fix-swap-command-on-Linux-7.1-and-later.patch ++++++ From: Kazuhito Hagio <[email protected]> Date: Wed, 3 Jun 2026 07:12:58 +0000 Subject: Fix "swap" command on Linux 7.1 and later References: kernel 7.1 Git-repo: https://github.com/crash-utility/crash Git-commit: fdb94ed20ac85e8354224b0d691af342f4b63922 Patch-mainline: yes Kernel commit 0d6af9bcf383 ("mm, swap: use the swap table to track the swap count"), which is contained in Linux 7.1 and later kernels, removed swap_info_struct.swap_map member. As a result, the "swap" command and "kmem -i" option fail with the following error: swap: invalid structure member offset: swap_info_struct_swap_map FILE: memory.c LINE: 16293 FUNCTION: dump_swap_info() Fix it by referencing swap_info_struct.swap_map only for SWAPINFO_V1, where it is actually needed. Newer kernels no longer have that member, and the command can use the existing inuse_pages handling instead. Signed-off-by: Kazuhito Hagio <[email protected]> Signed-off-by: Jiri Slaby <[email protected]> --- memory.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/memory.c b/memory.c index 15946c58eaf2..3f3aa274ab5a 100644 --- a/memory.c +++ b/memory.c @@ -16290,9 +16290,6 @@ dump_swap_info(ulong swapflags, ulong *totalswap_pages, ulong *totalused_pages) OFFSET(swap_info_struct_inuse_pages)); } - swap_map = ULONG(vt->swap_info_struct + - OFFSET(swap_info_struct_swap_map)); - if (swap_file) { if (VALID_MEMBER(swap_info_struct_swap_vfsmnt)) { vfsmnt = ULONG(vt->swap_info_struct + @@ -16322,6 +16319,9 @@ dump_swap_info(ulong swapflags, ulong *totalswap_pages, ulong *totalused_pages) if (vt->flags & SWAPINFO_V1) { smap = (ushort *)GETBUF(sizeof(ushort) * max); + swap_map = ULONG(vt->swap_info_struct + + OFFSET(swap_info_struct_swap_map)); + if (!readmem(swap_map, KVADDR, smap, sizeof(ushort) * max, "swap_info swap_map data", RETURN_ON_ERROR|QUIET)) { -- 2.55.0 ++++++ crash-support-kernel-7.x-and-8.x.patch ++++++ From: Ruirui Yang <[email protected]> Date: Fri, 14 Aug 2026 11:44:03 +0800 Subject: Refactor kernel version checking code References: kernel 7.1 Git-repo: https://github.com/crash-utility/crash Git-commit: 9550178eca33de9533e920e96cd8c05ecf465323 Patch-mainline: yes In case linux banner can not be found in vmlinux for some reason. The fallback checking of "Linux version" failed for kernel 7.x with below error msg: WARNING: kernel version inconsistency between vmlinux and dumpfile crash: incompatible arguments: vmlinux is not SMP -- vmcore is SMP Jiri's case is OpenSUSE uses separate vmlinux.debug file, details see https://github.com/crash-utility/crash/issues/232 But update the kernel version number in kernel sanity checking code does workaround the issue. Let's fix this separately. A few improvements to the sanity checking including: - Replace hardcoded version checks (2.x through 6.x) with a unified kernel_version_str_sanity_check() function - Extend kernel version sanity checking to Linux 7.x kernels - Add proper bounds checking and null pointer validation - Ensure minor version number is numeric for stricter validation - Reduce code duplication in verify_namelist() and debug_kernel_version() Reported-by: Jiri Slaby <[email protected]> Signed-off-by: Dave Young <[email protected]> Reviewed-by: Mukesh Pilaniya <[email protected]> Acked-by: Tao Liu <[email protected]> Signed-off-by: Dave Young <[email protected]> Signed-off-by: Jiri Slaby <[email protected]> --- kernel.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/kernel.c b/kernel.c index e53038d5d8db..cf5e5bcfe785 100644 --- a/kernel.c +++ b/kernel.c @@ -29,6 +29,9 @@ #endif #include "bfd.h" +#define KERNEL_VERSION_MIN '2' +#define KERNEL_VERSION_MAX '7' /* latest linux mainline kernel major number */ + static void do_module_cmd(ulong, char *, ulong, char *, char *); static void show_module_taint(void); static char *find_module_objfile(char *, char *, char *); @@ -104,6 +107,30 @@ static void check_vmcoreinfo(void); static int is_pvops_xen(void); static int get_linux_banner_from_vmlinux(char *, size_t); +static bool kernel_version_str_sanity_check(char *buf) +{ + int n; + char *p; + + if (!buf) + return FALSE; + + p = strstr(buf, "Linux version "); + if (!p) + return FALSE; + + n = strlen(p); + + if (n < 17) /* "Linux version " (14) + "x.y" (3) = 17 */ + return FALSE; + + if (p[14] >= KERNEL_VERSION_MIN && p[14] <= KERNEL_VERSION_MAX + && p[15] == '.' && p[16] >= '0' && p[16] <= '9') + return TRUE; + + return FALSE; +} + /* * popuplate the global kernel table (kt) with kernel version * information parsed from UTSNAME/OSRELEASE string @@ -1396,11 +1423,7 @@ verify_namelist() found = FALSE; sprintf(buffer3, "(unknown)"); while (fgets(buffer, (BUFSIZE/2)-1, pipe)) { - if (!strstr(buffer, "Linux version 2.") && - !strstr(buffer, "Linux version 3.") && - !strstr(buffer, "Linux version 4.") && - !strstr(buffer, "Linux version 5.") && - !strstr(buffer, "Linux version 6.")) + if (!kernel_version_str_sanity_check(buffer)) continue; if (strstr(buffer, kt->proc_version)) { @@ -5987,11 +6010,7 @@ debug_kernel_version(char *namelist) argc = 0; while (fgets(buf, BUFSIZE-1, pipe)) { - if (!strstr(buf, "Linux version 2.") && - !strstr(buf, "Linux version 3.") && - !strstr(buf, "Linux version 4.") && - !strstr(buf, "Linux version 5.") && - !strstr(buf, "Linux version 6.")) + if (!kernel_version_str_sanity_check(buf)) continue; argc = parse_line(buf, arglist); -- 2.55.0 ++++++ crash-symbols-Add-support-for-mod-symtab-with-combined-GPL.patch ++++++ From: Alexander Egorenkov <[email protected]> Date: Tue, 28 Apr 2026 12:16:37 +0200 Subject: symbols: Add support for mod symtab with combined GPL and non-GPL symbols References: kernel 7.1 Git-repo: https://github.com/crash-utility/crash Git-commit: 3a415c07a18a465df2580365b43b4d8f8a5d815b Patch-mainline: yes The commit b4760ff2a5e4 ("module: deprecate usage of *_gpl sections in module loader") eliminated separate GPL symbol sections representing GPL only symbols. Therefore, depending on whether the member gpl_syms is present in struct module, decide whether GPL module symbols are separated or not. https://lore.kernel.org/all/[email protected] Signed-off-by: Alexander Egorenkov <[email protected]> Signed-off-by: Jiri Slaby <[email protected]> --- kernel.c | 13 ++++++++----- symbols.c | 9 +++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/kernel.c b/kernel.c index 6dfc8714a1ff..eb9754c5e082 100644 --- a/kernel.c +++ b/kernel.c @@ -3635,9 +3635,11 @@ module_init(void) case KMOD_V2: MEMBER_OFFSET_INIT(module_num_syms, "module", "num_syms"); MEMBER_OFFSET_INIT(module_list, "module", "list"); - MEMBER_OFFSET_INIT(module_gpl_syms, "module", "gpl_syms"); - MEMBER_OFFSET_INIT(module_num_gpl_syms, "module", - "num_gpl_syms"); + if (MEMBER_EXISTS("module", "gpl_syms")) { + MEMBER_OFFSET_INIT(module_gpl_syms, "module", "gpl_syms"); + MEMBER_OFFSET_INIT(module_num_gpl_syms, "module", + "num_gpl_syms"); + } if (MEMBER_EXISTS("module", "mem")) { /* 6.4 and later */ kt->flags2 |= KMOD_MEMORY; /* MODULE_MEMORY() can be used. */ @@ -3831,8 +3833,9 @@ module_init(void) nsyms = UINT(modbuf + OFFSET(module_nsyms)); break; case KMOD_V2: - nsyms = UINT(modbuf + OFFSET(module_num_syms)) + - UINT(modbuf + OFFSET(module_num_gpl_syms)); + nsyms = UINT(modbuf + OFFSET(module_num_syms)); + if (VALID_MEMBER(module_num_gpl_syms)) + nsyms += UINT(modbuf + OFFSET(module_num_gpl_syms)); break; } diff --git a/symbols.c b/symbols.c index 8eb8b37abc23..3c62f54d4a93 100644 --- a/symbols.c +++ b/symbols.c @@ -1979,9 +1979,14 @@ store_module_symbols_6_4(ulong total, int mods_installed) "module buffer", FAULT_ON_ERROR); syms = ULONG(modbuf + OFFSET(module_syms)); - gpl_syms = ULONG(modbuf + OFFSET(module_gpl_syms)); nsyms = UINT(modbuf + OFFSET(module_num_syms)); - ngplsyms = UINT(modbuf + OFFSET(module_num_gpl_syms)); + if (VALID_MEMBER(module_gpl_syms)) { + gpl_syms = ULONG(modbuf + OFFSET(module_gpl_syms)); + ngplsyms = UINT(modbuf + OFFSET(module_num_gpl_syms)); + } else { + gpl_syms = 0; + ngplsyms = 0; + } nksyms = UINT(modbuf + OFFSET(module_num_symtab)); -- 2.55.0 ++++++ crash-symbols-use-non-debug-BFD-to-retrieve-.rodata.patch ++++++ From: Jiri Slaby <[email protected]> Date: Fri, 14 Aug 2026 08:06:26 +0200 Subject: symbols: use non-debug BFD to retrieve .rodata References: https://github.com/crash-utility/crash/issues/232 Git-repo: https://github.com/crash-utility/crash Git-commit: abcb45e7d443e693a59a759ca2862530e917c891 Patch-mainline: yes When running crash on openSUSE, get_linux_banner_from_vmlinux() returns success but fill the target buffer with all zero bytes (`\0`). This happens because `st->bfd` is initially opened for the main binary (`vmlinux`), but is later overwritten with the debuginfo file (`vmlinux.debug`) in `check_gnu_debuglink()`. In separate debug files, `.rodata` has no content, so is marked only as `ALLOC` without `SEC_HAS_CONTENTS`. When `bfd_get_section_contents()` is called on a section without `SEC_HAS_CONTENTS`, BFD clears the buffer to zeros and returns TRUE. As a result, `get_linux_banner_from_vmlinux()` thinks it successfully read the banner, while it actually received zeroed bytes. Fix this by caching the original main executable's BFD (into `st->bfd_orig`) before `st->bfd` gets swapped for the debuginfo file. `get_linux_banner_from_vmlinux()` will then fall back to `st->bfd_orig` if present, ensuring `.rodata` contents are read from the binary that actually contains the raw section data. Fixes #232. Signed-off-by: Jiri Slaby <[email protected]> Cc: Dave Young <[email protected]> Cc: <[email protected]> Cc: <[email protected]> Reviewed-by: Dave Young <[email protected]> Signed-off-by: Dave Young <[email protected]> Signed-off-by: Jiri Slaby <[email protected]> --- defs.h | 1 + kernel.c | 5 +++-- symbols.c | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/defs.h b/defs.h index ef34db90113f..134e7597e966 100644 --- a/defs.h +++ b/defs.h @@ -2924,6 +2924,7 @@ struct symbol_table_data { #ifdef GDB_5_3 struct _bfd *bfd; #else + struct bfd *bfd_orig; struct bfd *bfd; #endif struct sec *sections; diff --git a/kernel.c b/kernel.c index cf5e5bcfe785..723b88e90cb4 100644 --- a/kernel.c +++ b/kernel.c @@ -12164,6 +12164,7 @@ check_vmcoreinfo(void) static int get_linux_banner_from_vmlinux(char *buf, size_t size) { + struct bfd *bfd = st->bfd_orig ? : st->bfd; struct bfd_section *sect; long offset; ulong start_rodata; @@ -12175,7 +12176,7 @@ int get_linux_banner_from_vmlinux(char *buf, size_t size) else return FALSE; - sect = bfd_get_section_by_name(st->bfd, ".rodata"); + sect = bfd_get_section_by_name(bfd, ".rodata"); if (!sect) return FALSE; @@ -12187,7 +12188,7 @@ int get_linux_banner_from_vmlinux(char *buf, size_t size) */ offset = symbol_value("linux_banner") - start_rodata; - if (!bfd_get_section_contents(st->bfd, + if (!bfd_get_section_contents(bfd, sect, buf, offset, diff --git a/symbols.c b/symbols.c index 1515385d5724..270e14e26d28 100644 --- a/symbols.c +++ b/symbols.c @@ -444,6 +444,7 @@ check_gnu_debuglink(bfd *bfd) return FALSE; reset_bfd: + st->bfd_orig = st->bfd; if ((st->bfd = bfd_openr(pc->debuginfo_file, NULL)) == NULL) error(FATAL, "cannot open object file: %s\n", -- 2.55.0 ++++++ crash-x86_64-Fix-bt-command-for-noreturn-functions.patch ++++++ From: Kazuhito Hagio <[email protected]> Date: Fri, 29 May 2026 05:00:03 +0000 Subject: x86_64: Fix "bt" command for noreturn functions References: kernel 7.1 Git-repo: https://github.com/crash-utility/crash Git-commit: 7b3f6e0f60be1dd2d4c1b20175be96137cf61438 Patch-mainline: yes On x86_64, the "bt" command resolves saved return addresses with value_search(textaddr). However, a return address is the instruction pointer after the call, not the call site itself. This becomes a problem when the caller ends with a call to a noreturn function. In that case, the saved return address can match the start address of the following symbol, and "bt" loses track of the call chain and this can lead to very long session initialization. The same issue also affects symbol+offset formatting, line number lookup, and ORC-based frame size resolution. Fix it by resolving normal backtrace return addresses with textaddr-1, while keeping exact textaddr handling for real RIP values saved in exception frames. Add value_to_symstr_trace() so the displayed symbol+offset still reflects the original return address value. Suggested-by: Kosuke Tatsukawa <[email protected]> Signed-off-by: Kazuhito Hagio <[email protected]> Signed-off-by: Jiri Slaby <[email protected]> --- defs.h | 1 + symbols.c | 24 +++++++++++++++++++++--- x86_64.c | 31 ++++++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/defs.h b/defs.h index 6373ee1831af..4a42bc962817 100644 --- a/defs.h +++ b/defs.h @@ -5807,6 +5807,7 @@ struct syment *prev_symbol(char *, struct syment *); void get_symbol_data(char *, long, void *); int try_get_symbol_data(char *, long, void *); char *value_to_symstr(ulong, char *, ulong); +char *value_to_symstr_trace(ulong, char *, ulong); char *value_symbol(ulong); ulong symbol_value(char *); ulong symbol_value_module(char *, char *); diff --git a/symbols.c b/symbols.c index c0285058c5cb..78e400ba3756 100644 --- a/symbols.c +++ b/symbols.c @@ -104,6 +104,7 @@ static void free_structure(struct struct_elem *); static unsigned char is_right_brace(const char *); static struct struct_elem *find_node(struct struct_elem *, char *); static void dump_node(struct struct_elem *, char *, unsigned char, unsigned char); +static char *_value_to_symstr(ulong value, char *buf, ulong radix, int trace); static int module_mem_type(ulong, struct load_module *); static ulong module_mem_end(ulong, struct load_module *); @@ -5973,14 +5974,25 @@ generic_machdep_value_to_symbol(ulong value, ulong *offset) return NULL; } +char * +value_to_symstr(ulong value, char *buf, ulong radix) +{ + return _value_to_symstr(value, buf, radix, 0); +} + +char * +value_to_symstr_trace(ulong value, char *buf, ulong radix) +{ + return _value_to_symstr(value, buf, radix, 1); +} /* * For a given value, format a string containing the nearest symbol name * plus the offset if appropriate. Display the offset in the specified * radix (10 or 16) -- if it's 0, set it to the current pc->output_radix. */ -char * -value_to_symstr(ulong value, char *buf, ulong radix) +static char * +_value_to_symstr(ulong value, char *buf, ulong radix, int trace) { struct syment *sp; ulong offset; @@ -5996,7 +6008,13 @@ value_to_symstr(ulong value, char *buf, ulong radix) if ((radix != 10) && (radix != 16)) radix = 16; - if ((sp = value_search(value, &offset))) { + if (trace) { + sp = value_search(value-1, &offset); + offset++; + } else + sp = value_search(value, &offset); + + if (sp) { if (offset) sprintf(buf, radix == 16 ? "%s+0x%lx" : "%s+%ld", sp->name, offset); diff --git a/x86_64.c b/x86_64.c index b2cddbf8ba3d..ff283ed68191 100644 --- a/x86_64.c +++ b/x86_64.c @@ -3229,14 +3229,23 @@ x86_64_print_stack_entry(struct bt_info *bt, FILE *ofp, int level, if (!(bt->flags & BT_SAVE_EFRAME_IP)) bt->eframe_ip = 0; offset = 0; - sp = value_search(text, &offset); + if (bt->flags & BT_SAVE_EFRAME_IP) + sp = value_search(text, &offset); + else { + sp = value_search(text-1, &offset); + offset++; + } if (!sp) return BACKTRACE_ENTRY_IGNORED; name = sp->name; if (offset && (bt->flags & BT_SYMBOL_OFFSET)) - name_plus_offset = value_to_symstr(text, buf2, bt->radix); + if (bt->flags & BT_SAVE_EFRAME_IP) + name_plus_offset = value_to_symstr(text, buf2, bt->radix); + else + /* text-1 is used in the function */ + name_plus_offset = value_to_symstr_trace(text, buf2, bt->radix); else name_plus_offset = NULL; @@ -3337,7 +3346,10 @@ x86_64_print_stack_entry(struct bt_info *bt, FILE *ofp, int level, fprintf(ofp, "\n"); if (bt->flags & BT_LINE_NUMBERS) { - get_line_number(text, buf1, FALSE); + if (bt->flags & BT_SAVE_EFRAME_IP) + get_line_number(text, buf1, FALSE); + else + get_line_number(text-1, buf1, FALSE); if (strlen(buf1)) fprintf(ofp, " %s\n", buf1); } @@ -3864,8 +3876,10 @@ in_exception_stack: } level++; + bt->flags |= BT_SAVE_EFRAME_IP; if ((framesize = x86_64_get_framesize(bt, bt->instptr, rsp, NULL)) >= 0) rsp += framesize; + bt->flags &= ~BT_SAVE_EFRAME_IP; } } @@ -8811,7 +8825,13 @@ x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp, char *stack_ return 0; } - if (!(sp = value_search(textaddr, &offset))) { + if (bt->flags & BT_SAVE_EFRAME_IP) + sp = value_search(textaddr, &offset); + else { + sp = value_search(textaddr-1, &offset); + offset++; + } + if (!sp) { if (!(bt->flags & BT_FRAMESIZE_DEBUG)) bt->flags |= BT_FRAMESIZE_DISABLE; return 0; @@ -8887,7 +8907,8 @@ x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp, char *stack_ if ((sp->value >= kt->init_begin) && (sp->value < kt->init_end)) return 0; - if ((machdep->flags & ORC) && (korc = orc_find(textaddr))) { + if ((machdep->flags & ORC) && + (korc = orc_find(bt->flags & BT_SAVE_EFRAME_IP ? textaddr : textaddr-1))) { if (CRASHDEBUG(1)) { struct ORC_data *orc = &machdep->machspec->orc; fprintf(fp, -- 2.55.0 ++++++ crash-x86_64-Fix-bt-command-to-use-correct-ORC-register-va.patch ++++++ From: Kazuhito Hagio <[email protected]> Date: Mon, 1 Jun 2026 05:38:11 +0000 Subject: x86_64: Fix "bt" command to use correct ORC register values on Linux 7.1 and later References: kernel 7.1 Git-repo: https://github.com/crash-utility/crash Git-commit: d0ee428664f90beaf498fa0edc129cdead204abc Patch-mainline: yes Kernel commit 1735858caa4b ("objtool/x86: Reorder ORC register numbering") changed the ORC register numbering. Without the patch, crash can interpret ORC entry incorrectly and the "bt" command may generate broken backtraces on Linux 7.1 and later kernels like this: crash> bt 1 PID: 1 TASK: ffff8ab0009cd100 CPU: 2 COMMAND: "systemd" #0 [ffffd2218003b9c8] __schedule at ffffffffaa9d862b #1 [ffffd2218003ba20] schedule at ffffffffaa9d8993 #2 [ffffd2218003ba30] schedule_hrtimeout_range_clock at ffffffffaa9df77b #3 [ffffd2218003bab0] ep_poll at ffffffffaa1231e4 #4 [ffffd2218003bb50] do_epoll_wait at ffffffffaa123272 #5 [ffffd2218003bb88] __x64_sys_epoll_wait at ffffffffaa123b1f #6 [ffffd2218003bbd8] do_syscall_64 at ffffffffaa9cca6c #7 [ffffd2218003bc58] __memcg_slab_free_hook at ffffffffaa079da3 #8 [ffffd2218003bcf0] __memcg_slab_free_hook at ffffffffaa079da3 #9 [ffffd2218003bd50] __x64_sys_gettid at ffffffffa9ce1656 #10 [ffffd2218003bd58] do_syscall_64 at ffffffffaa9ccaa4 #11 [ffffd2218003bdc0] update_cfs_rq_load_avg at ffffffffa9d1bf59 #12 [ffffd2218003be00] __update_blocked_fair at ffffffffa9d214b8 #13 [ffffd2218003be70] sched_clock at ffffffffa9c460dc #14 [ffffd2218003be78] sched_clock_cpu at ffffffffa9d4aeab #15 [ffffd2218003be98] irqtime_account_irq at ffffffffa9d3af0d #16 [ffffd2218003bec0] handle_softirqs at ffffffffa9cce5ac #17 [ffffd2218003bf40] entry_SYSCALL_64_after_hwframe at ffffffffa9a0012b Fix this by making ORC_REG_SP and ORC_REG_PREV_SP depend on kernel version, as no other way was found. Signed-off-by: Kazuhito Hagio <[email protected]> Signed-off-by: Jiri Slaby <[email protected]> --- defs.h | 6 ++++-- x86_64.c | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/defs.h b/defs.h index 4a42bc962817..a4f70b773cd7 100644 --- a/defs.h +++ b/defs.h @@ -6650,6 +6650,8 @@ struct ORC_data { orc_entry orc_entry_data; int has_signal; int has_end; + int reg_sp; + int reg_prev_sp; }; #define ORC_TYPE_CALL ((machdep->flags & ORC_6_4) ? 2 : 0) @@ -6660,11 +6662,11 @@ struct ORC_data { #define UNWIND_HINT_TYPE_RESTORE 4 #define ORC_REG_UNDEFINED 0 -#define ORC_REG_PREV_SP 1 +#define ORC_REG_PREV_SP (machdep->machspec->orc.reg_prev_sp) #define ORC_REG_DX 2 #define ORC_REG_DI 3 #define ORC_REG_BP 4 -#define ORC_REG_SP 5 +#define ORC_REG_SP (machdep->machspec->orc.reg_sp) #define ORC_REG_R10 6 #define ORC_REG_R13 7 #define ORC_REG_BP_INDIRECT 8 diff --git a/x86_64.c b/x86_64.c index ff283ed68191..55648697baf3 100644 --- a/x86_64.c +++ b/x86_64.c @@ -999,6 +999,8 @@ x86_64_dump_machdep_table(ulong arg) fprintf(fp, " module_ORC: %s\n", ms->orc.module_ORC ? "TRUE" : "FALSE"); fprintf(fp, " has_signal: %s\n", ms->orc.has_signal ? "TRUE" : "FALSE"); fprintf(fp, " has_end: %s\n", ms->orc.has_end ? "TRUE" : "FALSE"); + fprintf(fp, " reg_sp: %d\n", ms->orc.reg_sp); + fprintf(fp, " reg_prev_sp: %d\n", ms->orc.reg_prev_sp); fprintf(fp, " lookup_num_blocks: %d\n", ms->orc.lookup_num_blocks); fprintf(fp, " __start_orc_unwind_ip: %lx\n", ms->orc.__start_orc_unwind_ip); fprintf(fp, " __stop_orc_unwind_ip: %lx\n", ms->orc.__stop_orc_unwind_ip); @@ -6734,6 +6736,15 @@ x86_64_ORC_init(void) if (orc->has_signal && !orc->has_end) machdep->flags |= ORC_6_4; + /* See kernel commit 1735858caa4b */ + if (THIS_KERNEL_VERSION >= LINUX(7,1,0)) { + ORC_REG_SP = 3; + ORC_REG_PREV_SP = 8; + } else { + ORC_REG_SP = 5; + ORC_REG_PREV_SP = 1; + } + machdep->flags |= ORC; } -- 2.55.0 ++++++ crash-x86_64-Make-ORC_REG_SP-and-ORC_REG_PREV_SP-independe.patch ++++++ From: Tao Liu <[email protected]> Date: Tue, 4 Aug 2026 15:20:33 +1200 Subject: x86_64: Make ORC_REG_SP and ORC_REG_PREV_SP independent from kernel version References: kernel 7.1 Git-repo: https://github.com/crash-utility/crash Git-commit: bfce25840cffabf0574825e796b0284ed36276bb Patch-mainline: yes Previously ORC_REG_SP and ORC_REG_PREV_SP will depend on kernel version for their value, however this is fragile since distributions will backport the upstream patch to a lower kernel version, thus break the version assumption. This patch fixes by checking the value of ORC_REG_PREV_SP, which can be get from orc_fp_entry. ORC_REG_PREV_SP's value can work as the indicator of whether the current kernel have applied the upstream patch 1735858caa4b ("objtool/x86: Reorder ORC register numbering"). Fixes: d0ee428664f9 ("x86_64: Fix "bt" command to use correct ORC register values on Linux 7.1 and later") Reviewed-by: HAGIO KAZUHITO <[email protected]> Reviewed-by: MUKESH KUMAR PILANIYA <[email protected]> Reviewed-by: Dave Young <[email protected]> Signed-off-by: Tao Liu <[email protected]> Signed-off-by: Jiri Slaby <[email protected]> --- x86_64.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/x86_64.c b/x86_64.c index 55648697baf3..62b27762a41f 100644 --- a/x86_64.c +++ b/x86_64.c @@ -6736,13 +6736,28 @@ x86_64_ORC_init(void) if (orc->has_signal && !orc->has_end) machdep->flags |= ORC_6_4; - /* See kernel commit 1735858caa4b */ - if (THIS_KERNEL_VERSION >= LINUX(7,1,0)) { - ORC_REG_SP = 3; - ORC_REG_PREV_SP = 8; - } else { - ORC_REG_SP = 5; - ORC_REG_PREV_SP = 1; + /* Try get ORC_REG_(PREV)_SP */ + ORC_REG_SP = 5; + ORC_REG_PREV_SP = 1; + + if (kernel_symbol_exists("orc_fp_entry")) { + /* + * kernel_orc_entry_6_4 & kernel_orc_entry have the same + * offset of bp_reg. + */ + kernel_orc_entry_6_4 entry = {0}; + if (try_get_symbol_data("orc_fp_entry", sizeof(entry), &entry)) { + /* + * orc_fp_entry.bp_reg = ORC_REG_PREV_SP + * See kernel commit 1735858caa4b. Use ORC_REG_PREV_SP + * as the indicator of the commit. + */ + if (entry.bp_reg == 8) { + ORC_REG_SP = 3; + ORC_REG_PREV_SP = 8; + } + } else + error(WARNING, "Cannot get orc_fp_entry.bp_reg info"); } machdep->flags |= ORC; -- 2.55.0
