diff --git a/0017-vmware-Improve-output-when-we-fail-to-read-vmware-vm.patch b/0017-vmware-Improve-output-when-we-fail-to-read-vmware-vm.patch new file mode 100644 index 0000000..f1a41c7 --- /dev/null +++ b/0017-vmware-Improve-output-when-we-fail-to-read-vmware-vm.patch @@ -0,0 +1,133 @@ +From b76e116c50ffc228ebc08eb8de35019320679257 Mon Sep 17 00:00:00 2001 +From: Dave Wysochanski +Date: Thu, 6 Jul 2023 10:53:18 -0400 +Subject: [PATCH 1/4] vmware: Improve output when we fail to read vmware 'vmsn' + file + +Today if crash fails to read some structure in a vmware 'vmsn' file, +it will throw an "No such file or directory" message. Such a generic +message does not give any clue as to the problem, but instead sounds +like the file may not exist when it does, for example: + $ crash ./vmcore.vmsn ./vmlinux + + crash 8.0.3 + ... + + crash: vmw: Failed to read './vmcore.vmsn': [Error 2] No such file or directory + + crash: ./vmcore.vmsn: initialization failed + + $ ls -l ./vmcore.vmsn + -rwxrwxrwx. 7 myuser mygroup 12128999 Jul 4 07:21 ./vmcore.vmsn + +Improve the above error message so we at least know which portion +of the file crash had difficulty reading. After this patch, the +above error looks like: + crash: vmw: Failed to read 'cptgroupdesc' from file './vmcore.vmsn': [Error 2] No such file or directory + +Signed-off-by: Dave Wysochanski +Signed-off-by: Lianbo Jiang +--- + vmware_guestdump.c | 8 ++++---- + vmware_vmss.c | 24 ++++++++++++------------ + 2 files changed, 16 insertions(+), 16 deletions(-) + +diff --git a/vmware_guestdump.c b/vmware_guestdump.c +index cf818e588a60..5be26c8e2e90 100644 +--- a/vmware_guestdump.c ++++ b/vmware_guestdump.c +@@ -117,8 +117,8 @@ is_vmware_guestdump(char *filename) + } + + if (fread(&hdr, sizeof(struct guestdumpheader), 1, fp) != 1) { +- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n", +- filename, errno, strerror(errno)); ++ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n", ++ "guestdumpheader", filename, errno, strerror(errno)); + fclose(fp); + return FALSE; + } +@@ -204,8 +204,8 @@ vmware_guestdump_init(char *filename, FILE *ofp) + + for (i = 0; i < vmss.num_vcpus; i++) { + if (fread(&vs, sizeof(struct vcpu_state), 1, fp) != 1) { +- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n", +- filename, errno, strerror(errno)); ++ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n", ++ "vcpu_state", filename, errno, strerror(errno)); + result = FALSE; + goto exit; + } +diff --git a/vmware_vmss.c b/vmware_vmss.c +index f6c5f32ea4c0..8121ab64a99a 100644 +--- a/vmware_vmss.c ++++ b/vmware_vmss.c +@@ -39,8 +39,8 @@ is_vmware_vmss(char *filename) + } + + if (fread(&hdr, sizeof(cptdumpheader), 1, fp) != 1) { +- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n", +- filename, errno, strerror(errno)); ++ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n", ++ "cptdumpheader", filename, errno, strerror(errno)); + fclose(fp); + return FALSE; + } +@@ -86,8 +86,8 @@ vmware_vmss_init(char *filename, FILE *ofp) + } + + if (fread(&hdr, sizeof(cptdumpheader), 1, fp) != 1) { +- error(INFO, LOGPRX"Failed to read '%s': %s [Error %d] %s\n", +- filename, errno, strerror(errno)); ++ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n", ++ "cptdumpheader", filename, errno, strerror(errno)); + result = FALSE; + goto exit; + } +@@ -112,8 +112,8 @@ vmware_vmss_init(char *filename, FILE *ofp) + } + + if (fread(grps, sizeof(cptgroupdesc), grpsize, fp) != grpsize) { +- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n", +- filename, errno, strerror(errno)); ++ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n", ++ "cptgroupdesc", filename, errno, strerror(errno)); + result = FALSE; + goto exit; + } +@@ -225,8 +225,8 @@ vmware_vmss_init(char *filename, FILE *ofp) + idx[0] < vmss.num_vcpus) { + int cpu = idx[0]; + if (fread(vmss.regs64[cpu], VMW_GPREGS_SIZE, 1, fp) != 1) { +- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n", +- filename, errno, strerror(errno)); ++ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n", ++ name, filename, errno, strerror(errno)); + break; + } + DEBUG_PARSE_PRINT((ofp, "\n")); +@@ -237,8 +237,8 @@ vmware_vmss_init(char *filename, FILE *ofp) + int cpu = idx[0]; + DEBUG_PARSE_PRINT((ofp, "\t=> ")); + if (fread(&vmss.regs64[cpu]->cr[0], VMW_CR64_SIZE, 1, fp) != 1) { +- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n", +- filename, errno, strerror(errno)); ++ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n", ++ name, filename, errno, strerror(errno)); + break; + } + for (j = 0; j < VMW_CR64_SIZE / 8; j++) +@@ -257,8 +257,8 @@ vmware_vmss_init(char *filename, FILE *ofp) + break; + } + if (fread(&idtr, sizeof(idtr), 1, fp) != 1) { +- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n", +- filename, errno, strerror(errno)); ++ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n", ++ name, filename, errno, strerror(errno)); + break; + } + DEBUG_PARSE_PRINT((ofp, "\n")); +-- +2.37.1 + diff --git a/0018-Exclude-zero-entries-from-do_maple_tree-return-value.patch b/0018-Exclude-zero-entries-from-do_maple_tree-return-value.patch new file mode 100644 index 0000000..543a988 --- /dev/null +++ b/0018-Exclude-zero-entries-from-do_maple_tree-return-value.patch @@ -0,0 +1,33 @@ +From d17d51a92a3a1c1cce1e646c38fe52ca99406cf9 Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Fri, 7 Jul 2023 15:17:18 +0900 +Subject: [PATCH 2/4] Exclude zero entries from do_maple_tree() return value + +While the return value of do_radix_tree() and do_xarray() does not +contain NULL entries, do_maple_tree()'s one contains NULL entries. + +Make this behavior consistent with the previous tree functions to make +replacement easier, especially for the following patch. + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + maple_tree.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/maple_tree.c b/maple_tree.c +index 807c17f7dfa0..eccd273105a6 100644 +--- a/maple_tree.c ++++ b/maple_tree.c +@@ -287,7 +287,7 @@ static void do_mt_entry(ulong entry, ulong min, ulong max, uint depth, + static struct req_entry **e = NULL; + struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL; + +- if (ops->entry) ++ if (ops->entry && entry) + ops->entry(entry, entry, path, max, ops->private); + + if (!td) +-- +2.37.1 + diff --git a/0019-Fix-irq-a-s-options-on-Linux-6.5-rc1-and-later.patch b/0019-Fix-irq-a-s-options-on-Linux-6.5-rc1-and-later.patch new file mode 100644 index 0000000..c7455ad --- /dev/null +++ b/0019-Fix-irq-a-s-options-on-Linux-6.5-rc1-and-later.patch @@ -0,0 +1,198 @@ +From 38d35bd1423ccafd0b8be0744155ce59ef3034ff Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Wed, 12 Jul 2023 17:55:29 +0900 +Subject: [PATCH 3/4] Fix "irq [-a|-s]" options on Linux 6.5-rc1 and later + +Kernel commit 721255b982 ("genirq: Use a maple tree for interrupt +descriptor management"), which is contained in Linux 6.5-rc1 and later +kernels, replaced irq_desc_tree with a maple tree sparse_irqs. + +Without the patch, "irq [-a|-s]" options fail with an error, e.g. the +following on x86_64, on kernels configured with CONFIG_SPARSE_IRQ=y. + + crash> irq + irq: x86_64_dump_irq: irq_desc[] or irq_desc_tree do not exist? + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + defs.h | 2 ++ + ia64.c | 3 ++- + kernel.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- + symbols.c | 1 + + x86_64.c | 9 ++++++--- + 5 files changed, 59 insertions(+), 7 deletions(-) + +diff --git a/defs.h b/defs.h +index 26afe232cc3e..358f365585cf 100644 +--- a/defs.h ++++ b/defs.h +@@ -676,6 +676,7 @@ struct new_utsname { + #define IRQ_DESC_TREE_XARRAY (0x80ULL) + #define KMOD_PAX (0x100ULL) + #define KMOD_MEMORY (0x200ULL) ++#define IRQ_DESC_TREE_MAPLE (0x400ULL) + + #define XEN() (kt->flags & ARCH_XEN) + #define OPENVZ() (kt->flags & ARCH_OPENVZ) +@@ -2222,6 +2223,7 @@ struct offset_table { /* stash of commonly-used offsets */ + long module_mem; + long module_memory_base; + long module_memory_size; ++ long irq_data_irq; + }; + + struct size_table { /* stash of commonly-used sizes */ +diff --git a/ia64.c b/ia64.c +index 2e1d15fe6042..d3e0a3b01869 100644 +--- a/ia64.c ++++ b/ia64.c +@@ -791,7 +791,8 @@ ia64_back_trace_cmd(struct bt_info *bt) + static void + ia64_dump_irq(int irq) + { +- if (symbol_exists("irq_desc") || symbol_exists("_irq_desc") || ++ if (kernel_symbol_exists("sparse_irqs") || ++ symbol_exists("irq_desc") || symbol_exists("_irq_desc") || + kernel_symbol_exists("irq_desc_ptrs")) { + machdep->dump_irq = generic_dump_irq; + return(generic_dump_irq(irq)); +diff --git a/kernel.c b/kernel.c +index 0fc77c19f12a..546eed95eebd 100644 +--- a/kernel.c ++++ b/kernel.c +@@ -541,7 +541,10 @@ kernel_init() + MEMBER_OFFSET_INIT(irqaction_dev_id, "irqaction", "dev_id"); + MEMBER_OFFSET_INIT(irqaction_next, "irqaction", "next"); + +- if (kernel_symbol_exists("irq_desc_tree")) { ++ /* 6.5 and later: CONFIG_SPARSE_IRQ */ ++ if (kernel_symbol_exists("sparse_irqs")) ++ kt->flags2 |= IRQ_DESC_TREE_MAPLE; ++ else if (kernel_symbol_exists("irq_desc_tree")) { + get_symbol_type("irq_desc_tree", NULL, &req); + if (STREQ(req.type_tag_name, "xarray")) { + kt->flags2 |= IRQ_DESC_TREE_XARRAY; +@@ -554,6 +557,7 @@ kernel_init() + } + STRUCT_SIZE_INIT(irq_data, "irq_data"); + if (VALID_STRUCT(irq_data)) { ++ MEMBER_OFFSET_INIT(irq_data_irq, "irq_data", "irq"); + MEMBER_OFFSET_INIT(irq_data_chip, "irq_data", "chip"); + MEMBER_OFFSET_INIT(irq_data_affinity, "irq_data", "affinity"); + MEMBER_OFFSET_INIT(irq_desc_irq_data, "irq_desc", "irq_data"); +@@ -6180,6 +6184,8 @@ dump_kernel_table(int verbose) + fprintf(fp, "%sIRQ_DESC_TREE_RADIX", others++ ? "|" : ""); + if (kt->flags2 & IRQ_DESC_TREE_XARRAY) + fprintf(fp, "%sIRQ_DESC_TREE_XARRAY", others++ ? "|" : ""); ++ if (kt->flags2 & IRQ_DESC_TREE_MAPLE) ++ fprintf(fp, "%sIRQ_DESC_TREE_MAPLE", others++ ? "|" : ""); + if (kt->flags2 & KMOD_PAX) + fprintf(fp, "%sKMOD_PAX", others++ ? "|" : ""); + if (kt->flags2 & KMOD_MEMORY) +@@ -6652,6 +6658,45 @@ get_irq_desc_addr(int irq) + readmem(ptr, KVADDR, &addr, + sizeof(void *), "irq_desc_ptrs entry", + FAULT_ON_ERROR); ++ } else if (kt->flags2 & IRQ_DESC_TREE_MAPLE) { ++ unsigned int i; ++ ++ if (kt->highest_irq && (irq > kt->highest_irq)) ++ return addr; ++ ++ cnt = do_maple_tree(symbol_value("sparse_irqs"), MAPLE_TREE_COUNT, NULL); ++ ++ len = sizeof(struct list_pair) * (cnt+1); ++ lp = (struct list_pair *)GETBUF(len); ++ lp[0].index = cnt; /* maxcount */ ++ ++ cnt = do_maple_tree(symbol_value("sparse_irqs"), MAPLE_TREE_GATHER, lp); ++ ++ /* ++ * NOTE: We cannot use lp.index like Radix Tree or XArray because ++ * it's not an absolute index and just counter in Maple Tree. ++ */ ++ if (kt->highest_irq == 0) { ++ readmem((ulong)lp[cnt-1].value + ++ OFFSET(irq_desc_irq_data) + OFFSET(irq_data_irq), ++ KVADDR, &kt->highest_irq, sizeof(int), "irq_data.irq", ++ FAULT_ON_ERROR); ++ } ++ ++ for (c = 0; c < cnt; c++) { ++ readmem((ulong)lp[c].value + ++ OFFSET(irq_desc_irq_data) + OFFSET(irq_data_irq), ++ KVADDR, &i, sizeof(int), "irq_data.irq", FAULT_ON_ERROR); ++ if (i == irq) { ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "index: %d value: %lx\n", ++ i, (ulong)lp[c].value); ++ addr = (ulong)lp[c].value; ++ break; ++ } ++ } ++ FREEBUF(lp); ++ + } else if (kt->flags2 & (IRQ_DESC_TREE_RADIX|IRQ_DESC_TREE_XARRAY)) { + if (kt->highest_irq && (irq > kt->highest_irq)) + return addr; +@@ -6700,8 +6745,8 @@ get_irq_desc_addr(int irq) + FREEBUF(lp); + } else { + error(FATAL, +- "neither irq_desc, _irq_desc, irq_desc_ptrs " +- "or irq_desc_tree symbols exist\n"); ++ "neither irq_desc, _irq_desc, irq_desc_ptrs, " ++ "irq_desc_tree or sparse_irqs symbols exist\n"); + } + + return addr; +diff --git a/symbols.c b/symbols.c +index 82529a6785c9..876be7aea90e 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -10375,6 +10375,7 @@ dump_offset_table(char *spec, ulong makestruct) + OFFSET(irq_desc_t_kstat_irqs)); + fprintf(fp, " irq_desc_t_affinity: %ld\n", + OFFSET(irq_desc_t_affinity)); ++ fprintf(fp, " irq_data_irq: %ld\n", OFFSET(irq_data_irq)); + fprintf(fp, " irq_data_chip: %ld\n", + OFFSET(irq_data_chip)); + fprintf(fp, " irq_data_affinity: %ld\n", +diff --git a/x86_64.c b/x86_64.c +index 87e87ae6e1e8..42ade4817ad9 100644 +--- a/x86_64.c ++++ b/x86_64.c +@@ -5391,7 +5391,8 @@ get_x86_64_frame(struct bt_info *bt, ulong *getpc, ulong *getsp) + static void + x86_64_dump_irq(int irq) + { +- if (symbol_exists("irq_desc") || ++ if (kernel_symbol_exists("sparse_irqs") || ++ symbol_exists("irq_desc") || + kernel_symbol_exists("irq_desc_ptrs") || + kernel_symbol_exists("irq_desc_tree")) { + machdep->dump_irq = generic_dump_irq; +@@ -5405,7 +5406,8 @@ x86_64_dump_irq(int irq) + static void + x86_64_get_irq_affinity(int irq) + { +- if (symbol_exists("irq_desc") || ++ if (kernel_symbol_exists("sparse_irqs") || ++ symbol_exists("irq_desc") || + kernel_symbol_exists("irq_desc_ptrs") || + kernel_symbol_exists("irq_desc_tree")) { + machdep->get_irq_affinity = generic_get_irq_affinity; +@@ -5419,7 +5421,8 @@ x86_64_get_irq_affinity(int irq) + static void + x86_64_show_interrupts(int irq, ulong *cpus) + { +- if (symbol_exists("irq_desc") || ++ if (kernel_symbol_exists("sparse_irqs") || ++ symbol_exists("irq_desc") || + kernel_symbol_exists("irq_desc_ptrs") || + kernel_symbol_exists("irq_desc_tree")) { + machdep->show_interrupts = generic_show_interrupts; +-- +2.37.1 + diff --git a/0020-Fix-segmentation-fault-by-tree-s-option-with-Maple-T.patch b/0020-Fix-segmentation-fault-by-tree-s-option-with-Maple-T.patch new file mode 100644 index 0000000..efb9310 --- /dev/null +++ b/0020-Fix-segmentation-fault-by-tree-s-option-with-Maple-T.patch @@ -0,0 +1,53 @@ +From f0b59524624b83d634b3fa8ab4ab3acf9ccce9df Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Mon, 10 Jul 2023 15:05:36 +0900 +Subject: [PATCH 4/4] Fix segmentation fault by "tree -s" option with Maple + Tree + +Without the patch, do_mt_entry() can call dump_struct_members_for_tree() +with a NULL entry, and parse_for_member_extended() will cause a +segmentation fault during strncpy(). + +This is caused by "tree -t maple -s struct.member.member" style multiple +level member access: + + crash> tree -t maple -s irq_desc.irq_data.irq sparse_irqs + ffff936980188400 + irq_data.irq = 0, + ffff93698018be00 + irq_data.irq = 1, + ... + ffff936980f38e00 + irq_data.irq = 19, + Segmentation fault (core dumped) + + (gdb) bt + #0 0x00007faaf8e51635 in __strncpy_avx2 () from /lib64/libc.so.6 + #1 0x00000000005e5927 in parse_for_member_extended (dm=dm@entry=0x7ffcb9e6d860, ... + #2 0x0000000000603c45 in dump_struct_member (s=s@entry=0x128cde0 ... + #3 0x0000000000513cf5 in dump_struct_members_for_tree (td=td@entry=0x7ffcb9e6eeb0, ... + #4 0x0000000000651f15 in do_mt_entry (entry=0, min=min@entry=20, max=max@entry=119, ... + ... + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + maple_tree.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/maple_tree.c b/maple_tree.c +index eccd273105a6..8c804d0cb80d 100644 +--- a/maple_tree.c ++++ b/maple_tree.c +@@ -313,7 +313,7 @@ static void do_mt_entry(ulong entry, ulong min, ulong max, uint depth, + fprintf(fp, " index: %ld position: %s/%u\n", + ++(*global_index), path, index); + +- if (td->structname) { ++ if (td->structname && entry) { + if (td->flags & TREE_STRUCT_RADIX_10) + print_radix = 10; + else if (td->flags & TREE_STRUCT_RADIX_16) +-- +2.37.1 + diff --git a/crash.spec b/crash.spec index b16569c..6eb3691 100644 --- a/crash.spec +++ b/crash.spec @@ -35,6 +35,10 @@ Patch14: 0013-Support-module-memory-layout-change-on-Linux-6.4.patch Patch15: 0014-Fix-failure-of-gathering-task-table-on-Linux-6.5-rc1.patch Patch16: 0015-Fix-compilation-error-due-to-new-strlcpy-function-th.patch Patch17: 0016-Fix-irq-a-option-on-Linux-6.0-and-later.patch +Patch18: 0017-vmware-Improve-output-when-we-fail-to-read-vmware-vm.patch +Patch19: 0018-Exclude-zero-entries-from-do_maple_tree-return-value.patch +Patch20: 0019-Fix-irq-a-s-options-on-Linux-6.5-rc1-and-later.patch +Patch21: 0020-Fix-segmentation-fault-by-tree-s-option-with-Maple-T.patch %description The core analysis suite is a self-contained tool that can be used to @@ -72,6 +76,10 @@ offered by Mission Critical Linux, or the LKCD kernel patch. %patch15 -p1 %patch16 -p1 %patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 %build