diff --git a/add-SDEI-stack-resolution.patch b/add-SDEI-stack-resolution.patch new file mode 100644 index 0000000000000000000000000000000000000000..70ebb78683d74dc4e1294f0349cdf274cc25ca38 --- /dev/null +++ b/add-SDEI-stack-resolution.patch @@ -0,0 +1,366 @@ +From e43071b6ceaa4fe20c65befe1b5685b68dc9f33f Mon Sep 17 00:00:00 2001 +From: Jialong Chen +Date: Wed, 5 Jun 2019 21:25:34 +0800 +Subject: [PATCH] crash: add SDEI stack resolution +reason: The kernel adds NMI dog detection, and the NMI interrupt stack uses a separate SDEI stack. +When the NMI dog is called, the kernel stack will switch to the sdei stack. +If the crash reads the stack data, the stack data cannot be parsed normally. + +normal call trace as follows: +PID: 55429 TASK: ffff802772e3ae80 CPU: 19 COMMAND: "insmod" + #0 [ffff00000d4e3c70] __crash_kexec at ffff0000081b4ac0 + #1 [ffff00000d4e3e00] panic at ffff0000080ebd0c + #2 [ffff00000d4e3ee0] nmi_panic at ffff0000080eb864 + #3 [ffff00000d4e3f00] watchdog_hardlockup_check at ffff0000081ecd6c + #4 [ffff00000d4e3f40] sdei_watchdog_callback at ffff0000080a411c + #5 [ffff00000d4e3f60] sdei_event_handler at ffff0000087971ec + #6 [ffff00000d4e3f90] __sdei_handler at ffff000008995964 + #7 [ffff00000d4e3ff0] __sdei_asm_handler at ffff0000080862dc +--- --- + #8 [ffff0000ccad3b70] __delay at ffff000008973658 + #9 [ffff0000ccad3ba0] __const_udelay at ffff0000089735e8 +#10 [ffff0000ccad3bb0] init_module at ffff0000009c6038 [test] +#11 [ffff0000ccad3bd0] do_one_initcall at ffff000008084ae0 +#12 [ffff0000ccad3c60] do_init_module at ffff0000081b1418 +#13 [ffff0000ccad3c90] load_module at ffff0000081afc54 +#14 [ffff0000ccad3d80] __se_sys_finit_module at ffff0000081b0134 +#15 [ffff0000ccad3e40] __arm64_sys_finit_module at ffff0000081b01a0 +#16 [ffff0000ccad3e60] el0_svc_common at ffff000008097b44 +#17 [ffff0000ccad3ea0] el0_svc_handler at ffff000008097c34 +#18 [ffff0000ccad3ff0] el0_svc at ffff000008084144 + +Signed-off-by: Jialong Chen +--- + arm64.c | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- + defs.h | 3 + + 2 files changed, 209 insertions(+), 4 deletions(-) + +diff --git a/arm64.c b/arm64.c +index fdf77bd..cc32d9d 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -87,6 +87,10 @@ static void arm64_calc_VA_BITS(void); + static int arm64_is_uvaddr(ulong, struct task_context *); + static void arm64_calc_KERNELPACMASK(void); + ++static int arm64_in_sdei_normal_stack(int cpu, ulong stkptr); ++static void arm64_set_sdei_normal_stack(struct bt_info *bt); ++static void arm64_sdei_stack_init(void); ++static int arm64_in_kdump_text_on_sdei_stack(struct bt_info *bt); + + /* + * Do all necessary machine-specific setup here. This is called several times +@@ -461,6 +465,7 @@ arm64_init(int when) + + arm64_irq_stack_init(); + arm64_stackframe_init(); ++ arm64_sdei_stack_init(); + break; + + case POST_VM: +@@ -1655,6 +1660,70 @@ arm64_irq_stack_init(void) + readmem(p, KVADDR, &(ms->irq_stacks[i]), sizeof(ulong), + "IRQ stack pointer", RETURN_ON_ERROR); + } ++ } ++} ++ ++/* ++ * Gather IRQ stack values. ++ */ ++static void ++arm64_sdei_stack_init(void) ++{ ++ int i; ++ struct syment *sp; ++ struct gnu_request request, *req; ++ struct machine_specific *ms = machdep->machspec; ++ ulong p, sz; ++ req = &request; ++ ++ if (symbol_exists("sdei_stack_normal_ptr") && ++ (sp = per_cpu_symbol_search("sdei_stack_normal_ptr")) && ++ get_symbol_type("sdei_stack_normal_ptr", NULL, req)) { ++ /* v4.14 and later with CONFIG_VMAP_STACK enabled */ ++ if (CRASHDEBUG(1)) { ++ fprintf(fp, "sdei_stack_normal_ptr: \n"); ++ fprintf(fp, " type: %x, %s\n", ++ (int)req->typecode, ++ (req->typecode == TYPE_CODE_PTR) ? ++ "TYPE_CODE_PTR" : "other"); ++ fprintf(fp, " target_typecode: %x, %s\n", ++ (int)req->target_typecode, ++ req->target_typecode == TYPE_CODE_INT ? ++ "TYPE_CODE_INT" : "other"); ++ fprintf(fp, " target_length: %ld\n", ++ req->target_length); ++ fprintf(fp, " length: %ld\n", req->length); ++ } ++ ++ if (!(ms->sdei_stacks = (ulong *)malloc((size_t)(kt->cpus * sizeof(ulong))))) ++ error(FATAL, "cannot malloc irq_stack addresses\n"); ++ ++ /* ++ * Determining the IRQ_STACK_SIZE is tricky, but for now ++ * 4.14 kernel has: ++ * ++ * #define IRQ_STACK_SIZE THREAD_SIZE ++ * ++ * and finding a solid usage of THREAD_SIZE is hard, but: ++ * ++ * union thread_union { ++ * ... ++ * unsigned long stack[THREAD_SIZE/sizeof(long)]; ++ * }; ++ */ ++ if (MEMBER_EXISTS("thread_union", "stack")) { ++ if ((sz = MEMBER_SIZE("thread_union", "stack")) > 0) ++ ms->sdei_stack_size = sz; ++ } else ++ ms->sdei_stack_size = ARM64_IRQ_STACK_SIZE; ++ ++ machdep->flags |= IRQ_STACKS; ++ ++ for (i = 0; i < kt->cpus; i++) { ++ p = kt->__per_cpu_offset[i] + sp->value; ++ readmem(p, KVADDR, &(ms->sdei_stacks[i]), sizeof(ulong), ++ "SDEI stack pointer", RETURN_ON_ERROR); ++ } + } + } + +@@ -2173,7 +2242,7 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame) + { + unsigned long high, low, fp; + unsigned long stack_mask; +- unsigned long irq_stack_ptr, orig_sp; ++ unsigned long irq_stack_ptr, orig_sp, sdei_stack_ptr; + struct arm64_pt_regs *ptregs; + struct machine_specific *ms = machdep->machspec; + +@@ -2203,7 +2272,8 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame) + + if (machdep->flags & UNW_4_14) { + if ((bt->flags & BT_IRQSTACK) && +- !arm64_on_irq_stack(bt->tc->processor, frame->fp)) { ++ !arm64_on_irq_stack(bt->tc->processor, frame->fp) && ++ !arm64_in_sdei_normal_stack(bt->tc->processor, frame->fp)) { + if (arm64_on_process_stack(bt, frame->fp)) { + arm64_set_process_stack(bt); + +@@ -2243,6 +2313,7 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame) + * orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr); (pt_regs pointer on process stack) + */ + irq_stack_ptr = ms->irq_stacks[bt->tc->processor] + ms->irq_stack_size - 16; ++ sdei_stack_ptr = ms->sdei_stacks[bt->tc->processor] + ms->sdei_stack_size - 16; + + if (frame->sp == irq_stack_ptr) { + orig_sp = GET_STACK_ULONG(irq_stack_ptr - 8); +@@ -2263,6 +2334,25 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame) + frame->fp, INSTACK(frame->fp, bt) ? "" : " (?)"); + return FALSE; + } ++ } else if (frame->sp == sdei_stack_ptr) { ++ orig_sp = GET_STACK_ULONG(sdei_stack_ptr - 8); ++ arm64_set_process_stack(bt); ++ if (INSTACK(orig_sp, bt) && (INSTACK(frame->fp, bt) || (frame->fp == 0))) { ++ ptregs = (struct arm64_pt_regs *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(orig_sp))]; ++ frame->sp = orig_sp; ++ frame->pc = ptregs->pc; ++ bt->bptr = fp; ++ if (CRASHDEBUG(1)) ++ error(INFO, ++ "arm64_unwind_frame: switch stacks: fp: %lx sp: %lx pc: %lx\n", ++ frame->fp, frame->sp, frame->pc); ++ } else { ++ error(WARNING, ++ "arm64_unwind_frame: on IRQ stack: oriq_sp: %lx%s fp: %lx%s\n", ++ orig_sp, INSTACK(orig_sp, bt) ? "" : " (?)", ++ frame->fp, INSTACK(frame->fp, bt) ? "" : " (?)"); ++ return FALSE; ++ } + } + + return TRUE; +@@ -2602,6 +2692,10 @@ arm64_back_trace_cmd(struct bt_info *bt) + arm64_set_irq_stack(bt); + bt->flags |= BT_IRQSTACK; + } ++ if (arm64_in_sdei_normal_stack(bt->tc->processor, bt->bptr)) { ++ arm64_set_sdei_normal_stack(bt); ++ bt->flags |= BT_IRQSTACK; ++ } + stackframe.fp = GET_STACK_ULONG(bt->bptr - 8); + stackframe.pc = GET_STACK_ULONG(bt->bptr); + stackframe.sp = bt->bptr + 8; +@@ -2611,6 +2705,10 @@ arm64_back_trace_cmd(struct bt_info *bt) + arm64_set_irq_stack(bt); + bt->flags |= BT_IRQSTACK; + } ++ if (arm64_in_sdei_normal_stack(bt->tc->processor, bt->hp->esp)) { ++ arm64_set_sdei_normal_stack(bt); ++ bt->flags |= BT_IRQSTACK; ++ } + stackframe.fp = GET_STACK_ULONG(bt->hp->esp - 8); + stackframe.pc = bt->hp->eip ? + bt->hp->eip : GET_STACK_ULONG(bt->hp->esp); +@@ -2621,6 +2719,10 @@ arm64_back_trace_cmd(struct bt_info *bt) + arm64_set_irq_stack(bt); + bt->flags |= BT_IRQSTACK; + } ++ if (arm64_in_sdei_normal_stack(bt->tc->processor, bt->frameptr)) { ++ arm64_set_sdei_normal_stack(bt); ++ bt->flags |= BT_IRQSTACK; ++ } + stackframe.sp = bt->stkptr; + stackframe.pc = bt->instptr; + stackframe.fp = bt->frameptr; +@@ -2682,7 +2784,8 @@ arm64_back_trace_cmd(struct bt_info *bt) + } + + if ((bt->flags & BT_IRQSTACK) && +- !arm64_on_irq_stack(bt->tc->processor, stackframe.fp)) { ++ !arm64_on_irq_stack(bt->tc->processor, stackframe.fp) && ++ !arm64_in_sdei_normal_stack(bt->tc->processor, stackframe.fp)) { + bt->flags &= ~BT_IRQSTACK; + if (arm64_switch_stack(bt, &stackframe, ofp) == USER_MODE) + break; +@@ -2965,6 +3068,79 @@ arm64_in_kdump_text(struct bt_info *bt, struct arm64_stackframe *frame) + } + + static int ++arm64_in_kdump_text_on_sdei_stack(struct bt_info *bt) ++{ ++ int cpu; ++ ulong stackbase; ++ char *stackbuf; ++ ulong *ptr, *start, *base; ++ struct machine_specific *ms; ++ ++ if ((machdep->flags & (IRQ_STACKS|KDUMP_ENABLED)) != (IRQ_STACKS|KDUMP_ENABLED)) ++ return FALSE; ++ ++ ms = machdep->machspec; ++ cpu = bt->tc->processor; ++ stackbase = ms->sdei_stacks[cpu]; ++ stackbuf = GETBUF(ms->sdei_stack_size); ++ ++ if (!readmem(stackbase, KVADDR, stackbuf, ++ ms->sdei_stack_size, "IRQ stack contents", RETURN_ON_ERROR)) { ++ error(INFO, "read of IRQ stack at %lx failed\n", stackbase); ++ FREEBUF(stackbuf); ++ return FALSE; ++ } ++ ++ base = (ulong *)stackbuf; ++ start = (ulong *)(stackbuf + ms->sdei_stack_size); ++ ++ for (ptr = start - 8; ptr >= base; ptr--) { ++ if (bt->flags & BT_OPT_BACK_TRACE) { ++ if ((*ptr >= ms->crash_kexec_start) && ++ (*ptr < ms->crash_kexec_end) && ++ INSTACK(*(ptr - 1), bt)) { ++ bt->bptr = ((ulong)(ptr - 1) - (ulong)base) + stackbase; ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "%lx: %lx (crash_kexec on IRQ stack)\n", ++ bt->bptr, *ptr); ++ FREEBUF(stackbuf); ++ return TRUE; ++ } ++ if ((*ptr >= ms->crash_save_cpu_start) && ++ (*ptr < ms->crash_save_cpu_end) && ++ INSTACK(*(ptr - 1), bt)) { ++ bt->bptr = ((ulong)(ptr - 1) - (ulong)base) + stackbase; ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "%lx: %lx (crash_save_cpu on IRQ stack)\n", ++ bt->bptr, *ptr); ++ FREEBUF(stackbuf); ++ return TRUE; ++ } ++ } else { ++ if ((*ptr >= ms->crash_kexec_start) && (*ptr < ms->crash_kexec_end)) { ++ bt->bptr = ((ulong)ptr - (ulong)base) + stackbase; ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "%lx: %lx (crash_kexec on IRQ stack)\n", ++ bt->bptr, *ptr); ++ FREEBUF(stackbuf); ++ return TRUE; ++ } ++ if ((*ptr >= ms->crash_save_cpu_start) && (*ptr < ms->crash_save_cpu_end)) { ++ bt->bptr = ((ulong)ptr - (ulong)base) + stackbase; ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "%lx: %lx (crash_save_cpu on IRQ stack)\n", ++ bt->bptr, *ptr); ++ FREEBUF(stackbuf); ++ return TRUE; ++ } ++ } ++ } ++ ++ FREEBUF(stackbuf); ++ return FALSE; ++} ++ ++static int + arm64_in_kdump_text_on_irq_stack(struct bt_info *bt) + { + int cpu; +@@ -3111,7 +3287,8 @@ try_kernel: + } + + if (arm64_in_kdump_text(bt, frame) || +- arm64_in_kdump_text_on_irq_stack(bt)) ++ arm64_in_kdump_text_on_irq_stack(bt) || ++ arm64_in_kdump_text_on_sdei_stack(bt)) + bt->flags |= BT_KDUMP_ADJUST; + + return TRUE; +@@ -3804,6 +3981,31 @@ arm64_in_alternate_stack(int cpu, ulong stkptr) + return FALSE; + } + ++static int ++arm64_in_sdei_normal_stack(int cpu, ulong stkptr) ++{ ++ struct machine_specific *ms = machdep->machspec; ++ ++ if (!ms->sdei_stack_size || (cpu >= kt->cpus)) ++ return FALSE; ++ ++ if ((stkptr >= ms->sdei_stacks[cpu]) && ++ (stkptr < (ms->sdei_stacks[cpu] + ms->sdei_stack_size))) ++ return TRUE; ++ ++ return FALSE; ++} ++ ++static void ++arm64_set_sdei_normal_stack(struct bt_info *bt) ++{ ++ struct machine_specific *ms = machdep->machspec; ++ ++ bt->stackbase = ms->sdei_stacks[bt->tc->processor]; ++ bt->stacktop = bt->stackbase + ms->sdei_stack_size; ++ alter_stackbuf(bt); ++} ++ + static void + arm64_set_irq_stack(struct bt_info *bt) + { +diff --git a/defs.h b/defs.h +index 9594950..9cd5ffa 100644 +--- a/defs.h ++++ b/defs.h +@@ -3283,6 +3283,9 @@ struct machine_specific { + ulong irq_stack_size; + ulong *irq_stacks; + char *irq_stackbuf; ++ ulong sdei_stack_size; ++ ulong *sdei_stacks; ++ char *sdei_stackbuf; + ulong __irqentry_text_start; + ulong __irqentry_text_end; + /* for exception vector code */ +-- +2.13.7 + diff --git a/crash.spec b/crash.spec index 4c6b052cf2558c869277d1622a34dfecdc437e50..c5f3711a61f02ee560d64ee1f5f801a200587fc2 100644 --- a/crash.spec +++ b/crash.spec @@ -1,17 +1,16 @@ Name: crash Version: 7.2.9 -Release: 1 +Release: 2 Summary: Linux kernel crash utility. License: GPLv3 URL: https://crash-utility.github.io Source0: https://github.com/crash-utility/crash/archive/%{version}.tar.gz Source1: http://ftp.gnu.org/gnu/gdb/gdb-7.6.tar.gz -#Patch0: lzo_snappy.patch -#Patch1: use_system_readline_v3.patch +Patch0: lzo_snappy.patch +Patch1: use_system_readline_v3.patch -#Patch9000: add-SDEI-stack-resolution.patch -#Patch9001: fix-bitmap_len-calculation-overflow-problem-in-large.patch +Patch9000: add-SDEI-stack-resolution.patch BuildRequires: ncurses-devel zlib-devel lzo-devel snappy-devel BuildRequires: gcc gcc-c++ bison readline-devel @@ -77,6 +76,9 @@ install -D -m 0644 defs.h %{buildroot}%{_includedir}/%{name}/defs.h %{_mandir}/man8/crash.8* %changelog +* Thu Apr 08 2021 shixuantong - 7.2.9-2 +- fix patch issue in upgrade version commit + * Mon Feb 1 2021 liudabo - 7.2.9-1 - Upgrade version to 7.2.9 diff --git a/lzo_snappy.patch b/lzo_snappy.patch new file mode 100644 index 0000000000000000000000000000000000000000..232eb61523aff73d2c93777f37491922f6f7a652 --- /dev/null +++ b/lzo_snappy.patch @@ -0,0 +1,22 @@ +--- crash-7.1.4/diskdump.c.orig ++++ crash-7.1.4/diskdump.c +@@ -23,6 +23,8 @@ + * GNU General Public License for more details. + */ + ++#define LZO ++#define SNAPPY + #include "defs.h" + #include "diskdump.h" + #include "xen_dom0.h" +--- crash-7.1.4/Makefile.orig ++++ crash-7.1.4/Makefile +@@ -228,7 +228,7 @@ all: make_configure + gdb_merge: force + @if [ ! -f ${GDB}/README ]; then \ + make --no-print-directory gdb_unzip; fi +- @echo "${LDFLAGS} -lz -ldl -rdynamic" > ${GDB}/gdb/mergelibs ++ @echo "${LDFLAGS} -lz -llzo2 -lsnappy -ldl -rdynamic" > ${GDB}/gdb/mergelibs + @echo "../../${PROGRAM} ../../${PROGRAM}lib.a" > ${GDB}/gdb/mergeobj + @rm -f ${PROGRAM} + @if [ ! -f ${GDB}/config.status ]; then \ diff --git a/use_system_readline_v3.patch b/use_system_readline_v3.patch new file mode 100644 index 0000000000000000000000000000000000000000..cb5757ed334b79b012b4e9e1a91a1036d4254b8b --- /dev/null +++ b/use_system_readline_v3.patch @@ -0,0 +1,32 @@ +--- crash-7.0.7/cmdline.c.orig ++++ crash-7.0.7/cmdline.c +@@ -44,7 +44,8 @@ static int verify_args_input_file(char * + #define READLINE_LIBRARY + + #include +-#include ++#define vi_mode 0 ++#define emacs_mode 1 + #include + + static void readline_init(void); +--- crash-7.0.7/Makefile.orig ++++ crash-7.0.7/Makefile +@@ -205,7 +205,7 @@ TAR_FILES=${SOURCE_FILES} Makefile ${GPL + ${EXTENSION_SOURCE_FILES} ${MEMORY_DRIVER_FILES} + CSCOPE_FILES=${SOURCE_FILES} + +-READLINE_DIRECTORY=./${GDB}/readline ++READLINE_DIRECTORY=/usr/include/readline + BFD_DIRECTORY=./${GDB}/bfd + GDB_INCLUDE_DIRECTORY=./${GDB}/include + +@@ -233,7 +233,7 @@ gdb_merge: force + @rm -f ${PROGRAM} + @if [ ! -f ${GDB}/config.status ]; then \ + (cd ${GDB}; ./configure ${GDB_CONF_FLAGS} --with-separate-debug-dir=/usr/lib/debug \ +- --with-bugurl="" --with-expat=no --with-python=no --disable-sim; \ ++ --with-bugurl="" --with-expat=no --with-python=no --disable-sim --with-system-readline; \ + make --no-print-directory CRASH_TARGET=${TARGET}; echo ${TARGET} > crash.target) \ + else make --no-print-directory rebuild; fi + @if [ ! -f ${PROGRAM} ]; then \