diff --git a/.crash.metadata b/.crash.metadata index d8e3943..5b8318b 100644 --- a/.crash.metadata +++ b/.crash.metadata @@ -1 +1 @@ -c972d50634ae15fac036bd1f8f9f84d87a54acba SOURCES/crash-7.2.6.tar.gz +194a82c2cd9d45478559947fe767fd42be5a668f SOURCES/crash-7.2.7.tar.gz diff --git a/.gitignore b/.gitignore index ee5c871..d5365b1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/crash-7.2.6.tar.gz +SOURCES/crash-7.2.7.tar.gz diff --git a/SOURCES/github_105a3e13_to_b5c2359f.patch b/SOURCES/github_105a3e13_to_b5c2359f.patch new file mode 100644 index 0000000..6c907b5 --- /dev/null +++ b/SOURCES/github_105a3e13_to_b5c2359f.patch @@ -0,0 +1,1123 @@ +commit 105a3e13167665dde5d3c12bf76ef9c916e82d0e +Author: Dave Anderson +Date: Thu Oct 10 14:07:22 2019 -0400 + + Fix for Linux 5.4-rc1 and later kernels that contain commit + 688fcbfc06e4fdfbb7e1d5a942a1460fe6379d2d, titled "mm/vmalloc: + modify struct vmap_area to reduce its size". Without the + patch "kmem -v" will display nothing; other architectures + that utilize the vmap_area_list to determine the base of + mapped/vmalloc address space will fail. + (anderson@redhat.com) + +diff --git a/memory.c b/memory.c +index 3a8b998..fe82fac 100644 +--- a/memory.c ++++ b/memory.c +@@ -401,9 +401,10 @@ vm_init(void) + STRUCT_SIZE_INIT(vmap_area, "vmap_area"); + if (VALID_MEMBER(vmap_area_va_start) && + VALID_MEMBER(vmap_area_va_end) && +- VALID_MEMBER(vmap_area_flags) && + VALID_MEMBER(vmap_area_list) && + VALID_MEMBER(vmap_area_vm) && ++ (VALID_MEMBER(vmap_area_flags) || ++ (OFFSET(vmap_area_vm) == MEMBER_OFFSET("vmap_area", "purge_list"))) && + kernel_symbol_exists("vmap_area_list")) + vt->flags |= USE_VMAP_AREA; + +@@ -8742,7 +8743,7 @@ static void + dump_vmap_area(struct meminfo *vi) + { + int i, cnt; +- ulong start, end, vm_struct, flags; ++ ulong start, end, vm_struct, flags, vm; + struct list_data list_data, *ld; + char *vmap_area_buf; + ulong size, pcheck, count, verified; +@@ -8790,9 +8791,15 @@ dump_vmap_area(struct meminfo *vi) + readmem(ld->list_ptr[i], KVADDR, vmap_area_buf, + SIZE(vmap_area), "vmap_area struct", FAULT_ON_ERROR); + +- flags = ULONG(vmap_area_buf + OFFSET(vmap_area_flags)); +- if (flags != VM_VM_AREA) +- continue; ++ if (VALID_MEMBER(vmap_area_flags)) { ++ flags = ULONG(vmap_area_buf + OFFSET(vmap_area_flags)); ++ if (flags != VM_VM_AREA) ++ continue; ++ } else { ++ vm = ULONG(vmap_area_buf + OFFSET(vmap_area_vm)); ++ if (!vm) ++ continue; ++ } + start = ULONG(vmap_area_buf + OFFSET(vmap_area_va_start)); + end = ULONG(vmap_area_buf + OFFSET(vmap_area_va_end)); + vm_struct = ULONG(vmap_area_buf + OFFSET(vmap_area_vm)); + +commit 82ce13bceb1082a7c53c1bda71e17ca9c2a5cbc4 +Author: Dave Anderson +Date: Fri Oct 11 11:14:28 2019 -0400 + + Fix for Linux 5.4-rc1 and later kernels that contain commit/merge + e0703556644a531e50b5dc61b9f6ea83af5f6604, titled "Merge tag 'modules- + for-v5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux + which introduces symbol namespaces. Without the patch, and depending + upon the architecture: + (1) the kernel module symbol list will contain garbage entries + (2) the session fails during session initialization with a dump of + the internal buffer allocation stats followed by the message + "crash: cannot allocate any more memory!" + (3) the session fails during session initialization with a + segmentation violation. + (anderson@redhat.com) + +diff --git a/defs.h b/defs.h +index 32bd147..502e7c2 100644 +--- a/defs.h ++++ b/defs.h +@@ -2694,6 +2694,7 @@ struct symbol_table_data { + ulong saved_command_line_vmlinux; + ulong pti_init_vmlinux; + ulong kaiser_init_vmlinux; ++ int kernel_symbol_type; + }; + + /* flags for st */ +diff --git a/symbols.c b/symbols.c +index 3ce8692..7af5e69 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -1607,39 +1607,100 @@ union kernel_symbol { + unsigned long value; + const char *name; + } v1; +- /* kernel 4.19 introduced relative symbol positionning */ ++ /* kernel 4.19 introduced relative symbol positioning */ + struct kernel_symbol_v2 { + int value_offset; + int name_offset; + } v2; ++ /* kernel 5.4 introduced symbol namespaces */ ++ struct kernel_symbol_v3 { ++ int value_offset; ++ int name_offset; ++ int namespace_offset; ++ } v3; ++ struct kernel_symbol_v4 { ++ unsigned long value; ++ const char *name; ++ const char *namespace; ++ } v4; + }; + ++static size_t ++kernel_symbol_type_init(void) ++{ ++ if (MEMBER_EXISTS("kernel_symbol", "value") && ++ MEMBER_EXISTS("kernel_symbol", "name")) { ++ if (MEMBER_EXISTS("kernel_symbol", "namespace")) { ++ st->kernel_symbol_type = 4; ++ return (sizeof(struct kernel_symbol_v4)); ++ } else { ++ st->kernel_symbol_type = 1; ++ return (sizeof(struct kernel_symbol_v1)); ++ } ++ } ++ if (MEMBER_EXISTS("kernel_symbol", "value_offset") && ++ MEMBER_EXISTS("kernel_symbol", "name_offset")) { ++ if (MEMBER_EXISTS("kernel_symbol", "namespace_offset")) { ++ st->kernel_symbol_type = 3; ++ return (sizeof(struct kernel_symbol_v3)); ++ } else { ++ st->kernel_symbol_type = 2; ++ return (sizeof(struct kernel_symbol_v2)); ++ } ++ } ++ ++ error(FATAL, "kernel_symbol data structure has changed\n"); ++ ++ return 0; ++} ++ + static ulong + modsym_name(ulong syms, union kernel_symbol *modsym, int i) + { +- if (VALID_MEMBER(kernel_symbol_value)) ++ switch (st->kernel_symbol_type) ++ { ++ case 1: + return (ulong)modsym->v1.name; ++ case 2: ++ return (syms + i * sizeof(struct kernel_symbol_v2) + ++ offsetof(struct kernel_symbol_v2, name_offset) + ++ modsym->v2.name_offset); ++ case 3: ++ return (syms + i * sizeof(struct kernel_symbol_v3) + ++ offsetof(struct kernel_symbol_v3, name_offset) + ++ modsym->v3.name_offset); ++ case 4: ++ return (ulong)modsym->v4.name; ++ } + +- return syms + i * sizeof(struct kernel_symbol_v2) + +- offsetof(struct kernel_symbol_v2, name_offset) + +- modsym->v2.name_offset; ++ return 0; + } + + static ulong + modsym_value(ulong syms, union kernel_symbol *modsym, int i) + { +- if (VALID_MEMBER(kernel_symbol_value)) ++ switch (st->kernel_symbol_type) ++ { ++ case 1: + return (ulong)modsym->v1.value; ++ case 2: ++ return (syms + i * sizeof(struct kernel_symbol_v2) + ++ offsetof(struct kernel_symbol_v2, value_offset) + ++ modsym->v2.value_offset); ++ case 3: ++ return (syms + i * sizeof(struct kernel_symbol_v3) + ++ offsetof(struct kernel_symbol_v3, value_offset) + ++ modsym->v3.value_offset); ++ case 4: ++ return (ulong)modsym->v4.value; ++ } + +- return syms + i * sizeof(struct kernel_symbol_v2) + +- offsetof(struct kernel_symbol_v2, value_offset) + +- modsym->v2.value_offset; ++ return 0; + } + + void + store_module_symbols_v2(ulong total, int mods_installed) + { +- + int i, m; + ulong mod, mod_next; + char *mod_name; +@@ -1675,12 +1736,7 @@ store_module_symbols_v2(ulong total, int mods_installed) + "re-initialization of module symbols not implemented yet!\n"); + } + +- MEMBER_OFFSET_INIT(kernel_symbol_value, "kernel_symbol", "value"); +- if (VALID_MEMBER(kernel_symbol_value)) { +- kernel_symbol_size = sizeof(struct kernel_symbol_v1); +- } else { +- kernel_symbol_size = sizeof(struct kernel_symbol_v2); +- } ++ kernel_symbol_size = kernel_symbol_type_init(); + + if ((st->ext_module_symtable = (struct syment *) + calloc(total, sizeof(struct syment))) == NULL) +@@ -3418,6 +3474,8 @@ dump_symbol_table(void) + fprintf(fp, "\n"); + } else + fprintf(fp, "(none)\n"); ++ ++ fprintf(fp, " kernel_symbol_type: v%d\n", st->kernel_symbol_type); + } + + + +commit c1ac656508ad064ef0ef222acb73621ae0bf4f00 +Author: Dave Anderson +Date: Tue Oct 15 11:21:55 2019 -0400 + + Fix for the "timer -r" option on Linux 5.4-rc1 and later kernels + that contain commit 511885d7061eda3eb1faf3f57dcc936ff75863f1, titled + "lib/timerqueue: Rely on rbtree semantics for next timer". Without + the patch, the option fails with the following error "timer: invalid + structure member offset: timerqueue_head_next". + (k-hagio@ab.jp.nec.com) + +diff --git a/defs.h b/defs.h +index 502e7c2..efa40b9 100644 +--- a/defs.h ++++ b/defs.h +@@ -2073,6 +2073,8 @@ struct offset_table { /* stash of commonly-used offsets */ + long cpu_context_save_r7; + long dentry_d_sb; + long device_private_knode_class; ++ long timerqueue_head_rb_root; ++ long rb_root_cached_rb_leftmost; + }; + + struct size_table { /* stash of commonly-used sizes */ +diff --git a/kernel.c b/kernel.c +index 375e1b4..c4cb001 100644 +--- a/kernel.c ++++ b/kernel.c +@@ -783,7 +783,13 @@ kernel_init() + MEMBER_OFFSET_INIT(timerqueue_node_expires, + "timerqueue_node", "expires"); + MEMBER_OFFSET_INIT(timerqueue_node_node, +- "timerqueue_node_node", "node"); ++ "timerqueue_node", "node"); ++ if (INVALID_MEMBER(timerqueue_head_next)) { ++ MEMBER_OFFSET_INIT(timerqueue_head_rb_root, ++ "timerqueue_head", "rb_root"); ++ MEMBER_OFFSET_INIT(rb_root_cached_rb_leftmost, ++ "rb_root_cached", "rb_leftmost"); ++ } + } + MEMBER_OFFSET_INIT(hrtimer_softexpires, "hrtimer", "_softexpires"); + MEMBER_OFFSET_INIT(hrtimer_function, "hrtimer", "function"); +@@ -7647,11 +7653,17 @@ next_one: + readmem((ulong)(base + OFFSET(hrtimer_clock_base_first)), + KVADDR, &curr, sizeof(curr), "hrtimer_clock_base first", + FAULT_ON_ERROR); +- else ++ else if (VALID_MEMBER(timerqueue_head_next)) + readmem((ulong)(base + OFFSET(hrtimer_clock_base_active) + + OFFSET(timerqueue_head_next)), + KVADDR, &curr, sizeof(curr), "hrtimer_clock base", + FAULT_ON_ERROR); ++ else ++ readmem((ulong)(base + OFFSET(hrtimer_clock_base_active) + ++ OFFSET(timerqueue_head_rb_root) + ++ OFFSET(rb_root_cached_rb_leftmost)), ++ KVADDR, &curr, sizeof(curr), ++ "hrtimer_clock_base active", FAULT_ON_ERROR); + + while (curr && i < next) { + curr = rb_next(curr); +diff --git a/symbols.c b/symbols.c +index 7af5e69..eb88ca1 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -10032,6 +10032,8 @@ dump_offset_table(char *spec, ulong makestruct) + OFFSET(rb_node_rb_left)); + fprintf(fp, " rb_node_rb_right: %ld\n", + OFFSET(rb_node_rb_right)); ++ fprintf(fp, " rb_root_cached_rb_leftmost: %ld\n", ++ OFFSET(rb_root_cached_rb_leftmost)); + + fprintf(fp, " x8664_pda_pcurrent: %ld\n", + OFFSET(x8664_pda_pcurrent)); +@@ -10388,6 +10390,8 @@ dump_offset_table(char *spec, ulong makestruct) + OFFSET(hrtimer_function)); + fprintf(fp, " timerqueue_head_next: %ld\n", + OFFSET(timerqueue_head_next)); ++ fprintf(fp, " timerqueue_head_rb_root: %ld\n", ++ OFFSET(timerqueue_head_rb_root)); + fprintf(fp, " timerqueue_node_expires: %ld\n", + OFFSET(timerqueue_node_expires)); + fprintf(fp, " timerqueue_node_node: %ld\n", + +commit e13fe8ba5a0b9c54edea103a309e9879784d9b94 +Author: Dave Anderson +Date: Tue Oct 15 16:29:30 2019 -0400 + + Fix for a "[-Wstringop-truncation]" compiler warning emitted when + symbols.c is built in a Fedora Rawhide environment with gcc-9.0.1 + or later. + (anderson@redhat.com) + +diff --git a/symbols.c b/symbols.c +index eb88ca1..55199fc 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -8174,8 +8174,10 @@ parse_for_member_extended(struct datatype_member *dm, + */ + + if (current && p && (p - p1 < BUFSIZE)) { +- strncpy(current->field_name, p1, p - p1); ++// strncpy(current->field_name, p1, p - p1); (NOTE: gcc-9.0.1 emits [-Wstringop-truncation] warning) + current->field_len = p - p1; ++ memcpy(current->field_name, p1, current->field_len); ++ current->field_name[current->field_len] = '\0'; + } + + if ( p && (*s_e != '{' || (*s_e == '{' && buf[len] == '}') )) { + +commit 9937878cce2fc049283d833685cb939caca462ca +Author: Dave Anderson +Date: Thu Oct 17 12:00:23 2019 -0400 + + Fix for the "kmem -n" option on Linux-5.4-rc1 and later kernels that + contain commit b6c88d3b9d38f9448e0fcf44847a075ea81d5ca2, titled + "drivers/base/memory.c: don't store end_section_nr in memory blocks". + Without the patch, the command option fails with the error message + "kmem: invalid structure member offset: memory_block_end_section_nr". + (msys.mizuma@gmail.com) + +diff --git a/help.c b/help.c +index a5218a7..cfd46c3 100644 +--- a/help.c ++++ b/help.c +@@ -7177,7 +7177,7 @@ char *help_kmem[] = { + " 6 ffff88003d4d90c0 ffffea0000000000 ffffea0000c00000 PM 196608", + " 7 ffff88003d4d90e0 ffffea0000000000 ffffea0000e00000 PM 229376", + " ", +-" MEM_BLOCK NAME PHYSICAL RANGE STATE SECTIONS", ++" MEM_BLOCK NAME PHYSICAL RANGE STATE START_SECTION_NO", + " ffff88003a707c00 memory0 0 - 7ffffff ONLINE 0", + " ffff88003a6e0000 memory1 8000000 - fffffff ONLINE 1", + " ffff88003a6e1000 memory2 10000000 - 17ffffff ONLINE 2", +diff --git a/memory.c b/memory.c +index fe82fac..0a79838 100644 +--- a/memory.c ++++ b/memory.c +@@ -17402,20 +17402,18 @@ fill_memory_block_name(ulong memblock, char *name) + } + + static void +-fill_memory_block_srange(ulong start_sec, ulong end_sec, char *srange) ++fill_memory_block_srange(ulong start_sec, char *srange) + { + memset(srange, 0, sizeof(*srange) * BUFSIZE); + +- if (start_sec == end_sec) +- sprintf(srange, "%lu", start_sec); +- else +- sprintf(srange, "%lu-%lu", start_sec, end_sec); ++ sprintf(srange, "%lu", start_sec); + } + + static void + print_memory_block(ulong memory_block) + { +- ulong start_sec, end_sec, start_pfn, end_pfn, nid; ++ ulong start_sec, end_sec, nid; ++ ulong memblock_size, mbs, start_addr, end_addr; + char statebuf[BUFSIZE]; + char srangebuf[BUFSIZE]; + char name[BUFSIZE]; +@@ -17430,15 +17428,25 @@ print_memory_block(ulong memory_block) + readmem(memory_block + OFFSET(memory_block_start_section_nr), KVADDR, + &start_sec, sizeof(void *), "memory_block start_section_nr", + FAULT_ON_ERROR); +- readmem(memory_block + OFFSET(memory_block_end_section_nr), KVADDR, +- &end_sec, sizeof(void *), "memory_block end_section_nr", +- FAULT_ON_ERROR); + +- start_pfn = section_nr_to_pfn(start_sec); +- end_pfn = section_nr_to_pfn(end_sec + 1); ++ start_addr = pfn_to_phys(section_nr_to_pfn(start_sec)); ++ ++ if (symbol_exists("memory_block_size_probed")) { ++ memblock_size = symbol_value("memory_block_size_probed"); ++ readmem(memblock_size, KVADDR, ++ &mbs, sizeof(ulong), "memory_block_size_probed", ++ FAULT_ON_ERROR); ++ end_addr = start_addr + mbs - 1; ++ } else { ++ readmem(memory_block + OFFSET(memory_block_end_section_nr), KVADDR, ++ &end_sec, sizeof(void *), "memory_block end_section_nr", ++ FAULT_ON_ERROR); ++ end_addr = pfn_to_phys(section_nr_to_pfn(end_sec + 1)) - 1; ++ } ++ + fill_memory_block_state(memory_block, statebuf); + fill_memory_block_name(memory_block, name); +- fill_memory_block_srange(start_sec, end_sec, srangebuf); ++ fill_memory_block_srange(start_sec, srangebuf); + + if (MEMBER_EXISTS("memory_block", "nid")) { + readmem(memory_block + OFFSET(memory_block_nid), KVADDR, &nid, +@@ -17448,9 +17456,9 @@ print_memory_block(ulong memory_block) + MKSTR(memory_block)), + mkstring(buf2, 12, CENTER, name), + mkstring(buf3, PADDR_PRLEN, RJUST|LONG_HEX, +- MKSTR(pfn_to_phys(start_pfn))), ++ MKSTR(start_addr)), + mkstring(buf4, PADDR_PRLEN, LJUST|LONG_HEX, +- MKSTR(pfn_to_phys(end_pfn) - 1)), ++ MKSTR(end_addr)), + mkstring(buf5, strlen("NODE"), CENTER|LONG_DEC, + MKSTR(nid)), + mkstring(buf6, strlen("CANCEL_OFFLINE"), LJUST, +@@ -17462,9 +17470,9 @@ print_memory_block(ulong memory_block) + MKSTR(memory_block)), + mkstring(buf2, 10, CENTER, name), + mkstring(buf3, PADDR_PRLEN, RJUST|LONG_HEX, +- MKSTR(pfn_to_phys(start_pfn))), ++ MKSTR(start_addr)), + mkstring(buf4, PADDR_PRLEN, LJUST|LONG_HEX, +- MKSTR(pfn_to_phys(end_pfn) - 1)), ++ MKSTR(end_addr)), + mkstring(buf5, strlen("CANCEL_OFFLINE"), LJUST, + statebuf), + mkstring(buf6, 12, LJUST, srangebuf)); +@@ -17552,14 +17560,14 @@ dump_memory_blocks(int initialize) + mkstring(buf3, PADDR_PRLEN*2 + 2, CENTER, "PHYSICAL RANGE"), + mkstring(buf4, strlen("NODE"), CENTER, "NODE"), + mkstring(buf5, strlen("CANCEL_OFFLINE"), LJUST, "STATE"), +- mkstring(buf6, 12, LJUST, "SECTIONS")); ++ mkstring(buf6, 12, LJUST, "START_SECTION_NO")); + else + sprintf(mb_hdr, "\n%s %s %s %s %s\n", + mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "MEM_BLOCK"), + mkstring(buf2, 10, CENTER, "NAME"), + mkstring(buf3, PADDR_PRLEN*2, CENTER, "PHYSICAL RANGE"), + mkstring(buf4, strlen("CANCEL_OFFLINE"), LJUST, "STATE"), +- mkstring(buf5, 12, LJUST, "SECTIONS")); ++ mkstring(buf5, 12, LJUST, "START_SECTION_NO")); + fprintf(fp, "%s", mb_hdr); + + for (i = 0; i < klistcnt; i++) { + +commit 1f9e0ac5d0b43004639e304f718177ff4c82343b +Author: Dave Anderson +Date: Sat Oct 19 16:43:16 2019 -0400 + + Fix for Linux 4.19.5 and later 4.19-based x86_64 kernels which + are NOT configured with CONFIG_RANDOMIZE_BASE and have backported + kernel commit d52888aa2753e3063a9d3a0c9f72f94aa9809c15, titled + "x86/mm: Move LDT remap out of KASLR region on 5-level paging", + which modified the 4-level and 5-level paging PAGE_OFFSET values. + Without this patch, the crash session fails during initialization + with the error message "crash: seek error: kernel virtual address: +
type: "tss_struct ist array". + (anderson@redhat.com) + +diff --git a/x86_64.c b/x86_64.c +index d57b602..c7967bd 100644 +--- a/x86_64.c ++++ b/x86_64.c +@@ -382,7 +382,7 @@ x86_64_init(int when) + + case POST_GDB: + if (!(machdep->flags & RANDOMIZED) && +- ((THIS_KERNEL_VERSION >= LINUX(4,20,0)) || ++ ((THIS_KERNEL_VERSION >= LINUX(4,19,5)) || + ((THIS_KERNEL_VERSION >= LINUX(4,14,84)) && + (THIS_KERNEL_VERSION < LINUX(4,15,0))))) { + machdep->machspec->page_offset = machdep->flags & VM_5LEVEL ? + +commit 1d2bc0c65792d15f94ebfd97c22da620b74634fa +Author: Dave Anderson +Date: Mon Oct 21 11:46:01 2019 -0400 + + Additional fix for the "kmem -n" option on Linux-5.4-rc1 and later + kernels that contain commit b6c88d3b9d38f9448e0fcf44847a075ea81d5ca2, + titled "drivers/base/memory.c: don't store end_section_nr in memory + blocks". The initial fix only addressed the x86_64 architecture; + this incremental patch addresses the other architectures. + (msys.mizuma@gmail.com) + +diff --git a/help.c b/help.c +index cfd46c3..2b2285b 100644 +--- a/help.c ++++ b/help.c +@@ -7177,15 +7177,15 @@ char *help_kmem[] = { + " 6 ffff88003d4d90c0 ffffea0000000000 ffffea0000c00000 PM 196608", + " 7 ffff88003d4d90e0 ffffea0000000000 ffffea0000e00000 PM 229376", + " ", +-" MEM_BLOCK NAME PHYSICAL RANGE STATE START_SECTION_NO", +-" ffff88003a707c00 memory0 0 - 7ffffff ONLINE 0", +-" ffff88003a6e0000 memory1 8000000 - fffffff ONLINE 1", +-" ffff88003a6e1000 memory2 10000000 - 17ffffff ONLINE 2", +-" ffff88003a6e1400 memory3 18000000 - 1fffffff ONLINE 3", +-" ffff88003a6e1800 memory4 20000000 - 27ffffff ONLINE 4", +-" ffff88003a6e0400 memory5 28000000 - 2fffffff ONLINE 5", +-" ffff88003a6e0800 memory6 30000000 - 37ffffff ONLINE 6", +-" ffff88003a6e0c00 memory7 38000000 - 3fffffff ONLINE 7", ++" MEM_BLOCK NAME PHYSICAL RANGE STATE START_SECTION_NO", ++" ffff88003a707c00 memory0 0 - 7ffffff ONLINE 0", ++" ffff88003a6e0000 memory1 8000000 - fffffff ONLINE 1", ++" ffff88003a6e1000 memory2 10000000 - 17ffffff ONLINE 2", ++" ffff88003a6e1400 memory3 18000000 - 1fffffff ONLINE 3", ++" ffff88003a6e1800 memory4 20000000 - 27ffffff ONLINE 4", ++" ffff88003a6e0400 memory5 28000000 - 2fffffff ONLINE 5", ++" ffff88003a6e0800 memory6 30000000 - 37ffffff ONLINE 6", ++" ffff88003a6e0c00 memory7 38000000 - 3fffffff ONLINE 7", + + "\n Translate a page structure's flags field contents:\n", + " %s> kmem -g 4080", +diff --git a/memory.c b/memory.c +index 0a79838..f36685b 100644 +--- a/memory.c ++++ b/memory.c +@@ -17401,6 +17401,23 @@ fill_memory_block_name(ulong memblock, char *name) + read_string(value, name, BUFSIZE-1); + } + ++static void ++fill_memory_block_parange(ulong saddr, ulong eaddr, char *parange) ++{ ++ char buf1[BUFSIZE]; ++ char buf2[BUFSIZE]; ++ ++ memset(parange, 0, sizeof(*parange) * BUFSIZE); ++ ++ if (eaddr == ULLONG_MAX) ++ sprintf(parange, "%s", ++ mkstring(buf1, PADDR_PRLEN*2 + 3, CENTER|LONG_HEX, MKSTR(saddr))); ++ else ++ sprintf(parange, "%s - %s", ++ mkstring(buf1, PADDR_PRLEN, RJUST|LONG_HEX, MKSTR(saddr)), ++ mkstring(buf2, PADDR_PRLEN, RJUST|LONG_HEX, MKSTR(eaddr))); ++} ++ + static void + fill_memory_block_srange(ulong start_sec, char *srange) + { +@@ -17413,14 +17430,13 @@ static void + print_memory_block(ulong memory_block) + { + ulong start_sec, end_sec, nid; +- ulong memblock_size, mbs, start_addr, end_addr; ++ ulong memblock_size, mbs, start_addr, end_addr = ULLONG_MAX; + char statebuf[BUFSIZE]; + char srangebuf[BUFSIZE]; ++ char parangebuf[BUFSIZE]; + char name[BUFSIZE]; + char buf1[BUFSIZE]; + char buf2[BUFSIZE]; +- char buf3[BUFSIZE]; +- char buf4[BUFSIZE]; + char buf5[BUFSIZE]; + char buf6[BUFSIZE]; + char buf7[BUFSIZE]; +@@ -17437,7 +17453,7 @@ print_memory_block(ulong memory_block) + &mbs, sizeof(ulong), "memory_block_size_probed", + FAULT_ON_ERROR); + end_addr = start_addr + mbs - 1; +- } else { ++ } else if (MEMBER_EXISTS("memory_block", "end_section_nr")) { + readmem(memory_block + OFFSET(memory_block_end_section_nr), KVADDR, + &end_sec, sizeof(void *), "memory_block end_section_nr", + FAULT_ON_ERROR); +@@ -17446,34 +17462,29 @@ print_memory_block(ulong memory_block) + + fill_memory_block_state(memory_block, statebuf); + fill_memory_block_name(memory_block, name); ++ fill_memory_block_parange(start_addr, end_addr, parangebuf); + fill_memory_block_srange(start_sec, srangebuf); + + if (MEMBER_EXISTS("memory_block", "nid")) { + readmem(memory_block + OFFSET(memory_block_nid), KVADDR, &nid, + sizeof(void *), "memory_block nid", FAULT_ON_ERROR); +- fprintf(fp, " %s %s %s - %s %s %s %s\n", ++ fprintf(fp, " %s %s %s %s %s %s\n", + mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX, + MKSTR(memory_block)), + mkstring(buf2, 12, CENTER, name), +- mkstring(buf3, PADDR_PRLEN, RJUST|LONG_HEX, +- MKSTR(start_addr)), +- mkstring(buf4, PADDR_PRLEN, LJUST|LONG_HEX, +- MKSTR(end_addr)), ++ parangebuf, + mkstring(buf5, strlen("NODE"), CENTER|LONG_DEC, + MKSTR(nid)), +- mkstring(buf6, strlen("CANCEL_OFFLINE"), LJUST, ++ mkstring(buf6, strlen("OFFLINE"), LJUST, + statebuf), + mkstring(buf7, 12, LJUST, srangebuf)); + } else +- fprintf(fp, " %s %s %s - %s %s %s\n", ++ fprintf(fp, " %s %s %s %s %s\n", + mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX, + MKSTR(memory_block)), + mkstring(buf2, 10, CENTER, name), +- mkstring(buf3, PADDR_PRLEN, RJUST|LONG_HEX, +- MKSTR(start_addr)), +- mkstring(buf4, PADDR_PRLEN, LJUST|LONG_HEX, +- MKSTR(end_addr)), +- mkstring(buf5, strlen("CANCEL_OFFLINE"), LJUST, ++ parangebuf, ++ mkstring(buf5, strlen("OFFLINE"), LJUST, + statebuf), + mkstring(buf6, 12, LJUST, srangebuf)); + } +@@ -17537,6 +17548,7 @@ dump_memory_blocks(int initialize) + int klistcnt, i; + struct list_data list_data; + char mb_hdr[BUFSIZE]; ++ char paddr_hdr[BUFSIZE]; + char buf1[BUFSIZE]; + char buf2[BUFSIZE]; + char buf3[BUFSIZE]; +@@ -17553,20 +17565,26 @@ dump_memory_blocks(int initialize) + + init_memory_block(&list_data, &klistcnt, &klistbuf); + ++ if ((symbol_exists("memory_block_size_probed")) || ++ (MEMBER_EXISTS("memory_block", "end_section_nr"))) ++ sprintf(paddr_hdr, "%s", "PHYSICAL RANGE"); ++ else ++ sprintf(paddr_hdr, "%s", "PHYSICAL START"); ++ + if (MEMBER_EXISTS("memory_block", "nid")) +- sprintf(mb_hdr, "\n%s %s %s %s %s %s\n", ++ sprintf(mb_hdr, "\n%s %s %s %s %s %s\n", + mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "MEM_BLOCK"), + mkstring(buf2, 10, CENTER, "NAME"), +- mkstring(buf3, PADDR_PRLEN*2 + 2, CENTER, "PHYSICAL RANGE"), ++ mkstring(buf3, PADDR_PRLEN*2 + 2, CENTER, paddr_hdr), + mkstring(buf4, strlen("NODE"), CENTER, "NODE"), +- mkstring(buf5, strlen("CANCEL_OFFLINE"), LJUST, "STATE"), ++ mkstring(buf5, strlen("OFFLINE"), LJUST, "STATE"), + mkstring(buf6, 12, LJUST, "START_SECTION_NO")); + else +- sprintf(mb_hdr, "\n%s %s %s %s %s\n", ++ sprintf(mb_hdr, "\n%s %s %s %s %s\n", + mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "MEM_BLOCK"), + mkstring(buf2, 10, CENTER, "NAME"), +- mkstring(buf3, PADDR_PRLEN*2, CENTER, "PHYSICAL RANGE"), +- mkstring(buf4, strlen("CANCEL_OFFLINE"), LJUST, "STATE"), ++ mkstring(buf3, PADDR_PRLEN*2, CENTER, paddr_hdr), ++ mkstring(buf4, strlen("OFFLINE"), LJUST, "STATE"), + mkstring(buf5, 12, LJUST, "START_SECTION_NO")); + fprintf(fp, "%s", mb_hdr); + + +commit 869f3b24fc3f1dd236b58e1cff86fb4e68da76cf +Author: Dave Anderson +Date: Tue Oct 22 16:42:57 2019 -0400 + + In the unlikely event that the panic task in a dumpfile cannot be + determined by the normal means, scan the kernel log buffer for panic + keywords, and if found, generate the panic task from the CPU number + that is specified following the panic message. + (chenqiwu@xiaomi.com) + +diff --git a/task.c b/task.c +index 829c794..8dd2b96 100644 +--- a/task.c ++++ b/task.c +@@ -48,6 +48,9 @@ static void show_tgid_list(ulong); + static int compare_start_time(const void *, const void *); + static int start_time_timespec(void); + static ulonglong convert_start_time(ulonglong, ulonglong); ++static ulong search_panic_task_by_cpu(char *); ++static ulong search_panic_task_by_keywords(char *, int *); ++static ulong get_log_panic_task(void); + static ulong get_dumpfile_panic_task(void); + static ulong get_active_set_panic_task(void); + static void populate_panic_threads(void); +@@ -132,6 +135,23 @@ static struct sched_policy_info { + { ULONG_MAX, NULL } + }; + ++enum PANIC_TASK_FOUND_RESULT { ++ FOUND_NO_PANIC_KEYWORD, ++ FOUND_PANIC_KEYWORD, ++ FOUND_PANIC_TASK ++}; ++ ++const char *panic_keywords[] = { ++ "Unable to handle kernel", ++ "BUG: unable to handle kernel", ++ "Kernel BUG at", ++ "kernel BUG at", ++ "Bad mode in", ++ "Oops", ++ "Kernel panic", ++ NULL, ++}; ++ + /* + * Figure out how much space will be required to hold the task context + * data, malloc() it, and call refresh_task_table() to fill it up. +@@ -6116,8 +6136,8 @@ get_panic_ksp(struct bt_info *bt, ulong *ksp) + + /* + * Look for kcore's storage information for the system's panic state. +- * If it's not there (somebody else's dump format?), look through all the +- * stack traces for evidence of panic. ++ * If it's not there (somebody else's dump format?), look through all ++ * the stack traces or the log buffer for evidence of panic. + */ + static ulong + get_panic_context(void) +@@ -6321,6 +6341,13 @@ get_panicmsg(char *buf) + break; + } + } ++ rewind(pc->tmpfile); ++ while (!msg_found && fgets(buf, BUFSIZE, pc->tmpfile)) { ++ if (strstr(buf, "Bad mode in ")) { ++ msg_found = TRUE; ++ break; ++ } ++ } + + close_tmpfile(); + +@@ -7401,6 +7428,8 @@ panic_search(void) + + close_tmpfile(); + ++ pc->curcmd = pc->program_name; ++ + if (!found && (dietask > (NO_TASK+1)) && task_has_cpu(dietask, NULL)) { + lasttask = dietask; + found = TRUE; +@@ -7410,9 +7439,16 @@ panic_search(void) + error(WARNING, "multiple active tasks have called die\n\n"); + + if (CRASHDEBUG(1) && found) +- error(INFO, "panic_search: %lx (via foreach bt)\n", ++ error(INFO, "panic_search: %lx (via foreach bt)\n", + lasttask); + ++ if (!found) { ++ if (CRASHDEBUG(1)) ++ error(INFO, "panic_search: failed (via foreach bt)\n"); ++ if ((lasttask = get_log_panic_task())) ++ found = TRUE; ++ } ++ + found_panic_task: + populate_panic_threads(); + +@@ -7430,11 +7466,114 @@ found_panic_task: + } + + if (CRASHDEBUG(1)) +- error(INFO, "panic_search: failed (via foreach bt)\n"); ++ error(INFO, "panic_search: failed\n"); + + return NULL; + } + ++static ulong ++search_panic_task_by_cpu(char *buf) ++{ ++ int crashing_cpu; ++ char *p1, *p2; ++ ulong task = NO_TASK; ++ ++ p1 = NULL; ++ ++ if ((p1 = strstr(buf, "CPU: "))) ++ p1 += strlen("CPU: "); ++ else if (STRNEQ(buf, "CPU ")) ++ p1 = buf + strlen("CPU "); ++ ++ if (p1) { ++ p2 = p1; ++ while (!whitespace(*p2) && (*p2 != '\n')) ++ p2++; ++ *p2 = NULLCHAR; ++ crashing_cpu = dtol(p1, RETURN_ON_ERROR, NULL); ++ if ((crashing_cpu >= 0) && in_cpu_map(ONLINE_MAP, crashing_cpu)) { ++ task = tt->active_set[crashing_cpu]; ++ if (CRASHDEBUG(1)) ++ error(WARNING, ++ "get_log_panic_task: active_set[%d]: %lx\n", ++ crashing_cpu, tt->active_set[crashing_cpu]); ++ } ++ } ++ return task; ++} ++ ++static ulong ++search_panic_task_by_keywords(char *buf, int *found_flag) ++{ ++ char *p; ++ int i = 0; ++ ulong task; ++ ++ while (panic_keywords[i]) { ++ if ((p = strstr(buf, panic_keywords[i]))) { ++ if ((task = search_panic_task_by_cpu(p))) { ++ *found_flag = FOUND_PANIC_TASK; ++ return task; ++ } else { ++ *found_flag = FOUND_PANIC_KEYWORD; ++ return NO_TASK; ++ } ++ } ++ i++; ++ } ++ *found_flag = FOUND_NO_PANIC_KEYWORD; ++ return NO_TASK; ++} ++ ++/* ++ * Search for the panic task by seeking panic keywords from kernel log buffer. ++ * The panic keyword is generally followed by printing out the stack trace info ++ * of the panicking task. We can determine the panic task by finding the first ++ * instance of "CPU: " or "CPU " following the panic keywords. ++ */ ++static ulong ++get_log_panic_task(void) ++{ ++ int found_flag = FOUND_NO_PANIC_KEYWORD; ++ int found_panic_keyword = FALSE; ++ ulong task = NO_TASK; ++ char buf[BUFSIZE]; ++ ++ if (!get_active_set()) ++ goto fail; ++ ++ BZERO(buf, BUFSIZE); ++ open_tmpfile(); ++ dump_log(SHOW_LOG_TEXT); ++ rewind(pc->tmpfile); ++ while (fgets(buf, BUFSIZE, pc->tmpfile)) { ++ if (!found_panic_keyword) { ++ task = search_panic_task_by_keywords(buf, &found_flag); ++ switch (found_flag) { ++ case FOUND_PANIC_TASK: ++ goto found_panic_task; ++ case FOUND_PANIC_KEYWORD: ++ found_panic_keyword = TRUE; ++ continue; ++ default: ++ continue; ++ } ++ } else { ++ task = search_panic_task_by_cpu(buf); ++ if (task) ++ goto found_panic_task; ++ } ++ } ++ ++found_panic_task: ++ close_tmpfile(); ++fail: ++ if (CRASHDEBUG(1) && !task) ++ error(WARNING, "cannot determine the panic task from kernel log buffer\n"); ++ ++ return task; ++} ++ + /* + * Get the panic task from the appropriate dumpfile handler. + */ + +commit 6a466f8afbb0dcdf4ddc5ef37aec6d343c2636c6 +Author: Dave Anderson +Date: Mon Nov 4 11:56:28 2019 -0500 + + Adjust a crash-7.1.8 patch for support of /proc/kcore as the live + memory source in Linux 4.8 and later x86_64 kernels configured with + CONFIG_RANDOMIZE_BASE, which randomizes the unity-mapping PAGE_OFFSET + value. Since the problem only arises before the determination of the + randomized PAGE_OFFSET value, restrict the patch such that it only + takes effect during session initialization. + (anderson@redhat.com) + +diff --git a/netdump.c b/netdump.c +index 55b64e6..fdaecf3 100644 +--- a/netdump.c ++++ b/netdump.c +@@ -4269,7 +4269,8 @@ read_proc_kcore(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr) + * If KASLR, the PAGE_OFFSET may be unknown early on, so try + * the (hopefully) mapped kernel address first. + */ +- if ((pc->curcmd_flags & MEMTYPE_KVADDR) && (kvaddr != addr)) { ++ if (!(pc->flags & RUNTIME) && ++ (pc->curcmd_flags & MEMTYPE_KVADDR) && (kvaddr != addr)) { + pc->curcmd_flags &= ~MEMTYPE_KVADDR; + for (i = 0; i < pkd->segments; i++) { + lp64 = pkd->load64 + i; + +commit c0bbd8fae4271159aee9e643350781909484c92f +Author: Dave Anderson +Date: Fri Nov 8 14:00:56 2019 -0500 + + Add support for extended numbering support in ELF dumpfiles to handle + more than PN_XNUM (0xffff) program headers. If the real number of + program header table entries is equal to or greater than PN_XNUM, the + e_phnum field of the ELF header is set to PN_XNUM, and the actual + number is set in the sh_info field of the section header at index 0. + (k-hagio@ab.jp.nec.com) + +diff --git a/netdump.c b/netdump.c +index fdaecf3..3ced87c 100644 +--- a/netdump.c ++++ b/netdump.c +@@ -28,12 +28,13 @@ static struct vmcore_data *nd = &vmcore_data; + static struct proc_kcore_data proc_kcore_data = { 0 }; + static struct proc_kcore_data *pkd = &proc_kcore_data; + static void netdump_print(char *, ...); +-static size_t resize_elf_header(int, char *, char **, ulong); ++static size_t resize_elf_header(int, char *, char **, char **, ulong); + static void dump_Elf32_Ehdr(Elf32_Ehdr *); + static void dump_Elf32_Phdr(Elf32_Phdr *, int); + static size_t dump_Elf32_Nhdr(Elf32_Off offset, int); + static void dump_Elf64_Ehdr(Elf64_Ehdr *); + static void dump_Elf64_Phdr(Elf64_Phdr *, int); ++static void dump_Elf64_Shdr(Elf64_Shdr *shdr); + static size_t dump_Elf64_Nhdr(Elf64_Off offset, int); + static void get_netdump_regs_32(struct bt_info *, ulong *, ulong *); + static void get_netdump_regs_ppc(struct bt_info *, ulong *, ulong *); +@@ -116,7 +117,7 @@ is_netdump(char *file, ulong source_query) + Elf32_Phdr *load32; + Elf64_Ehdr *elf64; + Elf64_Phdr *load64; +- char *eheader; ++ char *eheader, *sect0; + char buf[BUFSIZE]; + size_t size, len, tot; + Elf32_Off offset32; +@@ -330,7 +331,8 @@ is_netdump(char *file, ulong source_query) + goto bailout; + } + +- if (!(size = resize_elf_header(fd, file, &eheader, format))) ++ sect0 = NULL; ++ if (!(size = resize_elf_header(fd, file, &eheader, §0, format))) + goto bailout; + + nd->ndfd = fd; +@@ -372,7 +374,17 @@ is_netdump(char *file, ulong source_query) + case KDUMP_ELF64: + nd->header_size = size; + nd->elf64 = (Elf64_Ehdr *)&nd->elf_header[0]; +- nd->num_pt_load_segments = nd->elf64->e_phnum - 1; ++ ++ /* ++ * Extended Numbering support ++ * See include/uapi/linux/elf.h and elf(5) for more information ++ */ ++ if (nd->elf64->e_phnum == PN_XNUM) { ++ nd->sect0_64 = (Elf64_Shdr *)sect0; ++ nd->num_pt_load_segments = nd->sect0_64->sh_info - 1; ++ } else ++ nd->num_pt_load_segments = nd->elf64->e_phnum - 1; ++ + if ((nd->pt_load_segments = (struct pt_load_segment *) + malloc(sizeof(struct pt_load_segment) * + nd->num_pt_load_segments)) == NULL) { +@@ -432,7 +444,8 @@ bailout: + */ + + static size_t +-resize_elf_header(int fd, char *file, char **eheader_ptr, ulong format) ++resize_elf_header(int fd, char *file, char **eheader_ptr, char **sect0_ptr, ++ ulong format) + { + int i; + char buf[BUFSIZE]; +@@ -462,7 +475,44 @@ resize_elf_header(int fd, char *file, char **eheader_ptr, ulong format) + + case NETDUMP_ELF64: + case KDUMP_ELF64: +- num_pt_load_segments = elf64->e_phnum - 1; ++ /* ++ * Extended Numbering support ++ * See include/uapi/linux/elf.h and elf(5) for more information ++ */ ++ if (elf64->e_phnum == PN_XNUM) { ++ Elf64_Shdr *shdr64; ++ ++ shdr64 = (Elf64_Shdr *)malloc(sizeof(*shdr64)); ++ if (!shdr64) { ++ fprintf(stderr, ++ "cannot malloc a section header buffer\n"); ++ return 0; ++ } ++ if (FLAT_FORMAT()) { ++ if (!read_flattened_format(fd, elf64->e_shoff, ++ shdr64, elf64->e_shentsize)) ++ return 0; ++ } else { ++ if (lseek(fd, elf64->e_shoff, SEEK_SET) != ++ elf64->e_shoff) { ++ sprintf(buf, "%s: section header lseek", ++ file); ++ perror(buf); ++ return 0; ++ } ++ if (read(fd, shdr64, elf64->e_shentsize) != ++ elf64->e_shentsize) { ++ sprintf(buf, "%s: section header read", ++ file); ++ perror(buf); ++ return 0; ++ } ++ } ++ num_pt_load_segments = shdr64->sh_info - 1; ++ *sect0_ptr = (char *)shdr64; ++ } else ++ num_pt_load_segments = elf64->e_phnum - 1; ++ + header_size = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) + + (sizeof(Elf64_Phdr) * num_pt_load_segments); + break; +@@ -1168,6 +1218,7 @@ netdump_memory_dump(FILE *fp) + netdump_print(" elf64: %lx\n", nd->elf64); + netdump_print(" notes64: %lx\n", nd->notes64); + netdump_print(" load64: %lx\n", nd->load64); ++ netdump_print(" sect0_64: %lx\n", nd->sect0_64); + netdump_print(" nt_prstatus: %lx\n", nd->nt_prstatus); + netdump_print(" nt_prpsinfo: %lx\n", nd->nt_prpsinfo); + netdump_print(" nt_taskstruct: %lx\n", nd->nt_taskstruct); +@@ -1252,6 +1303,8 @@ netdump_memory_dump(FILE *fp) + dump_Elf64_Phdr(nd->notes64, ELFREAD); + for (i = 0; i < nd->num_pt_load_segments; i++) + dump_Elf64_Phdr(nd->load64 + i, ELFREAD); ++ if (nd->sect0_64) ++ dump_Elf64_Shdr(nd->sect0_64); + offset64 = nd->notes64->p_offset; + for (tot = 0; tot < nd->notes64->p_filesz; tot += len) { + if (!(len = dump_Elf64_Nhdr(offset64, ELFREAD))) +@@ -1763,6 +1816,32 @@ dump_Elf64_Phdr(Elf64_Phdr *prog, int store_pt_load_data) + netdump_print(" p_align: %lld\n", prog->p_align); + } + ++static void ++dump_Elf64_Shdr(Elf64_Shdr *shdr) ++{ ++ netdump_print("Elf64_Shdr:\n"); ++ netdump_print(" sh_name: %x\n", shdr->sh_name); ++ netdump_print(" sh_type: %x ", shdr->sh_type); ++ switch (shdr->sh_type) ++ { ++ case SHT_NULL: ++ netdump_print("(SHT_NULL)\n"); ++ break; ++ default: ++ netdump_print("\n"); ++ break; ++ } ++ netdump_print(" sh_flags: %lx\n", shdr->sh_flags); ++ netdump_print(" sh_addr: %lx\n", shdr->sh_addr); ++ netdump_print(" sh_offset: %lx\n", shdr->sh_offset); ++ netdump_print(" sh_size: %lx\n", shdr->sh_size); ++ netdump_print(" sh_link: %x\n", shdr->sh_link); ++ netdump_print(" sh_info: %x (%u)\n", shdr->sh_info, ++ shdr->sh_info); ++ netdump_print(" sh_addralign: %lx\n", shdr->sh_addralign); ++ netdump_print(" sh_entsize: %lx\n", shdr->sh_entsize); ++} ++ + /* + * VMCOREINFO + * +diff --git a/netdump.h b/netdump.h +index ad1fc77..7fa04f7 100644 +--- a/netdump.h ++++ b/netdump.h +@@ -61,6 +61,7 @@ struct vmcore_data { + Elf64_Ehdr *elf64; + Elf64_Phdr *notes64; + Elf64_Phdr *load64; ++ Elf64_Shdr *sect0_64; + void *nt_prstatus; + void *nt_prpsinfo; + void *nt_taskstruct; + +commit b5c2359f9f7347a2efa4896fa134dbf128601ca8 +Author: Dave Anderson +Date: Fri Nov 8 14:32:53 2019 -0500 + + Fix for a "warning: large integer implicitly truncated to unsigned + type [-Woverflow]" compiler message generated on 32-bit architectures + as a result of the "Additional fix for the kmem -n option" patch + above. + (anderson@redhat.com) + +diff --git a/memory.c b/memory.c +index f36685b..4f7b6a0 100644 +--- a/memory.c ++++ b/memory.c +@@ -17430,7 +17430,7 @@ static void + print_memory_block(ulong memory_block) + { + ulong start_sec, end_sec, nid; +- ulong memblock_size, mbs, start_addr, end_addr = ULLONG_MAX; ++ ulong memblock_size, mbs, start_addr, end_addr = (ulong)ULLONG_MAX; + char statebuf[BUFSIZE]; + char srangebuf[BUFSIZE]; + char parangebuf[BUFSIZE]; diff --git a/SOURCES/github_5cbb2fd8_to_6c1c8ac6.patch b/SOURCES/github_5cbb2fd8_to_6c1c8ac6.patch new file mode 100644 index 0000000..305ccee --- /dev/null +++ b/SOURCES/github_5cbb2fd8_to_6c1c8ac6.patch @@ -0,0 +1,1485 @@ +commit 5cbb2fd8c20c46793095522059b1efc8232df926 +Author: Dave Anderson +Date: Wed Nov 13 11:29:14 2019 -0500 + + Add support for handling openSUSE vmlinux files which will be shipped + in .xz compressed format. Without the patch, only gzip and bzip2 + formats are supported. + (jirislaby@gmail.com) + +diff --git a/symbols.c b/symbols.c +index 55199fc..7e1bca7 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -3655,6 +3655,7 @@ is_compressed_kernel(char *file, char **tmp) + + #define GZIP (1) + #define BZIP2 (2) ++#define XZ (3) + + #define FNAME (1 << 3) + +@@ -3704,6 +3705,19 @@ is_compressed_kernel(char *file, char **tmp) + type = BZIP2; + } + ++ if (!memcmp(header, "\xfd""7zXZ", 6)) { ++ if (!STRNEQ(basename(file), "vmlinux") && ++ !(st->flags & FORCE_DEBUGINFO)) { ++ error(INFO, "%s: compressed file name does not start " ++ "with \"vmlinux\"\n", file); ++ error(CONT, ++ "Use \"-f %s\" on command line to override.\n\n", ++ file); ++ return FALSE; ++ } ++ type = XZ; ++ } ++ + if (!type) + return FALSE; + +@@ -3739,6 +3753,12 @@ is_compressed_kernel(char *file, char **tmp) + "/bin/bunzip2" : "/usr/bin/bunzip2", + file, tempname); + break; ++ case XZ: ++ sprintf(command, "%s -c %s > %s", ++ file_exists("/bin/unxz", NULL) ? ++ "/bin/unxz" : "/usr/bin/unxz", ++ file, tempname); ++ break; + } + if (system(command) < 0) { + please_wait_done(); + +commit babd7ae62d4e8fd6f93fd30b88040d9376522aa3 +Author: Dave Anderson +Date: Fri Nov 15 09:55:34 2019 -0500 + + Fix for the determination of the ARM64 page size on Linux 4.4 and + earlier kernels that do not have vmcoreinfo data. Without the patch, + the crash session fails during initialization with the error message + "crash: "cannot determine page size". + (chenqiwu@xiaomi.com) + +diff --git a/arm64.c b/arm64.c +index 5ee5f1a..af7147d 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -179,17 +179,16 @@ arm64_init(int when) + + } + ++ /* ++ * This code section will only be executed if the kernel is ++ * earlier than Linux 4.4 (if there is no vmcoreinfo) ++ */ + if (!machdep->pagesize && + kernel_symbol_exists("swapper_pg_dir") && + kernel_symbol_exists("idmap_pg_dir")) { +- if (kernel_symbol_exists("tramp_pg_dir")) +- value = symbol_value("tramp_pg_dir"); +- else if (kernel_symbol_exists("reserved_ttbr0")) +- value = symbol_value("reserved_ttbr0"); +- else +- value = symbol_value("swapper_pg_dir"); ++ value = symbol_value("swapper_pg_dir") - ++ symbol_value("idmap_pg_dir"); + +- value -= symbol_value("idmap_pg_dir"); + /* + * idmap_pg_dir is 2 pages prior to 4.1, + * and 3 pages thereafter. Only 4K and 64K + +commit bfd9a651f9426d86250295ac875d7e33d8de2a97 +Author: Dave Anderson +Date: Tue Nov 19 10:19:55 2019 -0500 + + Determine the ARM64 kernel's "vabits_actual" value by reading the + new TCR_EL1.T1SZ vmcoreinfo entry. + (bhsharma@redhat.com) + +diff --git a/arm64.c b/arm64.c +index af7147d..0834913 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -3856,8 +3856,17 @@ arm64_calc_VA_BITS(void) + } else if (ACTIVE()) + error(FATAL, "cannot determine VA_BITS_ACTUAL: please use /proc/kcore\n"); + else { +- if ((string = pc->read_vmcoreinfo("NUMBER(VA_BITS_ACTUAL)"))) { +- value = atol(string); ++ if ((string = pc->read_vmcoreinfo("NUMBER(tcr_el1_t1sz)"))) { ++ /* See ARMv8 ARM for the description of ++ * TCR_EL1.T1SZ and how it can be used ++ * to calculate the vabits_actual ++ * supported by underlying kernel. ++ * ++ * Basically: ++ * vabits_actual = 64 - T1SZ; ++ */ ++ value = 64 - strtoll(string, NULL, 0); ++ fprintf(fp, "vmcoreinfo : vabits_actual: %ld\n", value); + free(string); + machdep->machspec->VA_BITS_ACTUAL = value; + machdep->machspec->VA_BITS = value; + +commit f1c71de4ef66508108c5929e79e21a85b147787b +Author: Dave Anderson +Date: Wed Nov 20 11:59:00 2019 -0500 + + Fix to determine the ARM64 kernel's "vabits_actual" value from the + ELF header of a dumpfile created with the "snap.so" extension module. + (anderson@redhat.com) + +diff --git a/netdump.c b/netdump.c +index 3ced87c..406416a 100644 +--- a/netdump.c ++++ b/netdump.c +@@ -1887,7 +1887,7 @@ vmcoreinfo_read_string(const char *key) + sprintf(value, "%ld", nd->arch_data2 & 0xffffffff); + return value; + } +- if (STREQ(key, "NUMBER(VA_BITS_ACTUAL)") && nd->arch_data2) { ++ if (STREQ(key, "NUMBER(tcr_el1_t1sz)") && nd->arch_data2) { + value = calloc(VADDR_PRLEN+1, sizeof(char)); + sprintf(value, "%lld", ((ulonglong)nd->arch_data2 >> 32) & 0xffffffff); + pc->read_vmcoreinfo = no_vmcoreinfo; + +commit b259940b228cc7025904f9b7372348b56f73a4d2 +Author: Dave Anderson +Date: Thu Nov 21 09:27:52 2019 -0500 + + Fix two typos in the examples section of the "help bt" display, which + mistakenly show "bf -f" and "bf -FF" instead of "bt -f" and "bt -FF". + (austindh.kim@gmail.com) + +diff --git a/help.c b/help.c +index 2b2285b..eed249b 100644 +--- a/help.c ++++ b/help.c +@@ -2117,7 +2117,7 @@ char *help_bt[] = { + " The following three examples show the difference in the display of", + " the same stack frame's contents using -f, -F, and -FF:", + " ", +-" %s> bf -f", ++" %s> bt -f", + " ...", + " #4 [ffff810072b47f10] vfs_write at ffffffff800789d8", + " ffff810072b47f18: ffff81007e020380 ffff81007e2c2880 ", +@@ -2133,7 +2133,7 @@ char *help_bt[] = { + " ffff810072b47f38: 00002b141825d000 sys_write+69 ", + " #5 [ffff810072b47f40] sys_write at ffffffff80078f75", + " ...", +-" %s> bf -FF", ++" %s> bt -FF", + " ...", + " #4 [ffff810072b47f10] vfs_write at ffffffff800789d8", + " ffff810072b47f18: [ffff81007e020380:files_cache] [ffff81007e2c2880:filp]", + +commit 5171ef5a7e85805f61ef98b15801da06648a8e39 +Author: Dave Anderson +Date: Fri Nov 22 13:39:40 2019 -0500 + + Similar to ARM64, the X86_64, PPC64 and S390x architectures will use + the exported value of MAX_PHYSMEM_BITS from the vmcoreinfo data as + the preferred method if it is available. + (anderson@redhat.com) + +diff --git a/ppc64.c b/ppc64.c +index 0936551..f368bf8 100644 +--- a/ppc64.c ++++ b/ppc64.c +@@ -225,6 +225,13 @@ static int ppc64_is_vmaddr(ulong addr) + static int set_ppc64_max_physmem_bits(void) + { + int dimension; ++ char *string; ++ ++ if ((string = pc->read_vmcoreinfo("NUMBER(MAX_PHYSMEM_BITS)"))) { ++ machdep->max_physmem_bits = atol(string); ++ free(string); ++ return 0; ++ } + + get_array_length("mem_section", &dimension, 0); + +diff --git a/s390x.c b/s390x.c +index 0055890..4a1a466 100644 +--- a/s390x.c ++++ b/s390x.c +@@ -240,6 +240,13 @@ static int + set_s390x_max_physmem_bits(void) + { + int array_len, dimension; ++ char *string; ++ ++ if ((string = pc->read_vmcoreinfo("NUMBER(MAX_PHYSMEM_BITS)"))) { ++ machdep->max_physmem_bits = atol(string); ++ free(string); ++ return TRUE; ++ } + + machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_OLD; + +diff --git a/x86_64.c b/x86_64.c +index c7967bd..a4138ed 100644 +--- a/x86_64.c ++++ b/x86_64.c +@@ -665,7 +665,10 @@ x86_64_init(int when) + } + machdep->section_size_bits = _SECTION_SIZE_BITS; + if (!machdep->max_physmem_bits) { +- if (machdep->flags & VM_5LEVEL) ++ if ((string = pc->read_vmcoreinfo("NUMBER(MAX_PHYSMEM_BITS)"))) { ++ machdep->max_physmem_bits = atol(string); ++ free(string); ++ } else if (machdep->flags & VM_5LEVEL) + machdep->max_physmem_bits = + _MAX_PHYSMEM_BITS_5LEVEL; + else if (THIS_KERNEL_VERSION >= LINUX(2,6,31)) + +commit 6664cb3f4ea2eac1b6d482e541b56d7792a4be04 +Author: Dave Anderson +Date: Tue Nov 26 12:18:02 2019 -0500 + + If an S390X kernel crashes before vmcoreinfo initialization, there is + no way to extract the KASLR offset for such early dumps. In a new + S390X kernel patch, the KASLR offset will be stored in the lowcore + memory during early boot and then overwritten after vmcoreinfo is + initialized. This patch allows crash to identify the KASLR offset + that is stored in the lowcore memory. + (zaslonko@linux.ibm.com) + +diff --git a/s390x.c b/s390x.c +index 4a1a466..8840cc7 100644 +--- a/s390x.c ++++ b/s390x.c +@@ -46,6 +46,8 @@ + + #define S390X_PSW_MASK_PSTATE 0x0001000000000000UL + ++#define S390X_LC_VMCORE_INFO 0xe0c ++ + /* + * Flags for Region and Segment table entries. + */ +@@ -460,6 +462,8 @@ static void s390x_check_live(void) + void + s390x_init(int when) + { ++ ulong s390x_lc_kaslr; ++ + switch (when) + { + case SETUP_ENV: +@@ -486,6 +490,24 @@ s390x_init(int when) + machdep->verify_paddr = generic_verify_paddr; + machdep->get_kvaddr_ranges = s390x_get_kvaddr_ranges; + machdep->ptrs_per_pgd = PTRS_PER_PGD; ++ if (DUMPFILE() && !(kt->flags & RELOC_SET)) { ++ /* Read the value from well-known lowcore location*/ ++ if (readmem(S390X_LC_VMCORE_INFO, PHYSADDR, &s390x_lc_kaslr, ++ sizeof(s390x_lc_kaslr), "s390x_lc_kaslr", ++ QUIET|RETURN_ON_ERROR)) { ++ /* Check for explicit kaslr offset flag */ ++ if (s390x_lc_kaslr & 0x1UL) { ++ /* Drop the last bit to get an offset value */ ++ s390x_lc_kaslr &= ~(0x1UL); ++ /* Make sure the offset is aligned by 0x1000 */ ++ if (s390x_lc_kaslr && !(s390x_lc_kaslr & 0xfff)) { ++ kt->relocate = s390x_lc_kaslr * (-1); ++ kt->flags |= RELOC_SET; ++ kt->flags2 |= KASLR; ++ } ++ } ++ } ++ } + break; + + case PRE_GDB: + +commit b265bad21cdb394b230431360605551b02fc5053 +Author: Dave Anderson +Date: Sun Dec 1 14:06:59 2019 -0500 + + Fix for a crash-7.2.7 regression that determined the value of the + ARM64 kernel SECTION_SIZE_BITS by reading the in-kernel configuration + data if there is no VMCOREINFO data available. In that case, without + the patch, a double-free exception may occur. + (anderson@redhat.com) + +diff --git a/arm64.c b/arm64.c +index 0834913..233029d 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -1073,10 +1073,8 @@ arm64_get_section_size_bits(void) + free(string); + } else if (kt->ikconfig_flags & IKCONFIG_AVAIL) { + if ((ret = get_kernel_config("CONFIG_MEMORY_HOTPLUG", NULL)) == IKCONFIG_Y) { +- if ((ret = get_kernel_config("CONFIG_HOTPLUG_SIZE_BITS", &string)) == IKCONFIG_STR) { ++ if ((ret = get_kernel_config("CONFIG_HOTPLUG_SIZE_BITS", &string)) == IKCONFIG_STR) + machdep->section_size_bits = atol(string); +- free(string); +- } + } + } + + +commit e13b51a59645fd8c3884082b157a0b494cf77ec6 +Author: Dave Anderson +Date: Sun Dec 1 14:18:41 2019 -0500 + + Fix for segmentation violation if the gdb_readmem_callback() function + gets called from other than a crash command, such as from an epython + command from the mypkdump.so extension module. + (anderson@redhat.com) + +diff --git a/gdb_interface.c b/gdb_interface.c +index 608da86..562d2ac 100644 +--- a/gdb_interface.c ++++ b/gdb_interface.c +@@ -1,8 +1,8 @@ + /* gdb_interface.c - core analysis suite + * + * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. +- * Copyright (C) 2002-2015,2018 David Anderson +- * Copyright (C) 2002-2015,2018 Red Hat, Inc. All rights reserved. ++ * Copyright (C) 2002-2015,2018-2019 David Anderson ++ * Copyright (C) 2002-2015,2018-2019 Red Hat, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -831,6 +831,11 @@ gdb_readmem_callback(ulong addr, void *buf, int len, int write) + if (write) + return FALSE; + ++ if (!(pc->cur_req)) { ++ return(readmem(addr, KVADDR, buf, len, ++ "gdb_readmem_callback", RETURN_ON_ERROR)); ++ } ++ + if (pc->cur_req->flags & GNU_NO_READMEM) + return TRUE; + + +commit da4a22029aa55fa55200d52f98866fce48ba720e +Author: Dave Anderson +Date: Tue Dec 3 11:41:19 2019 -0500 + + Fix for the "dis -s" option when running against kernels that have + been configured with CONFIG_RANDOMIZE_BASE=y (KASLR). Without the + patch, the command option indicates that the FILE and LINE numbers + are "(unknown)", and that "source code is not available". + (anderson@redhat.com) + +diff --git a/kernel.c b/kernel.c +index c4cb001..80486ba 100644 +--- a/kernel.c ++++ b/kernel.c +@@ -1459,12 +1459,20 @@ list_source_code(struct gnu_request *req, int count_entered) + char *argv[MAXARGS]; + struct syment *sp; + ulong remaining, offset; ++ struct load_module *lm; + char *p1; + + sp = value_search(req->addr, &offset); + if (!sp || !is_symbol_text(sp)) + error(FATAL, "%lx: not a kernel text address\n", req->addr); + ++ if (module_symbol(req->addr, NULL, &lm, NULL, 0)) { ++ if (!(lm->mod_flags & MOD_LOAD_SYMS)) ++ error(FATAL, "%s: module source code is not available\n", lm->mod_name); ++ get_line_number(req->addr, buf1, FALSE); ++ } else if (kt->flags2 & KASLR) ++ req->addr -= (kt->relocate * -1); ++ + sprintf(buf1, "list *0x%lx", req->addr); + open_tmpfile(); + if (!gdb_pass_through(buf1, pc->tmpfile, GNU_RETURN_ON_ERROR)) { + +commit 4e4e5859731da650d3520150d7ea2ef07094c7af +Author: Dave Anderson +Date: Thu Dec 12 12:08:11 2019 -0500 + + Fix for newer Xen hypervisors, which fail during initialization with + the error message "crash: cannot resolve init_tss". This is caused + by a change in the Xen hypervisor with commit 78884406256, from + 4.12.0-rc5-763-g7888440625. In that patch the tss_struct structure + was renamed to tss64 and the tss_page structure was introduced, + which contains a single tss64. Now tss information is accessible + via the symbol "per_cpu__tss_page". + (dietmar.hahn@ts.fujitsu.com) + +diff --git a/x86.c b/x86.c +index 88562b6..de0d3d3 100644 +--- a/x86.c ++++ b/x86.c +@@ -5600,18 +5600,18 @@ x86_get_stackbase_hyper(ulong task) + + if (symbol_exists("init_tss")) { + init_tss = symbol_value("init_tss"); +- init_tss += XEN_HYPER_SIZE(tss_struct) * pcpu; ++ init_tss += XEN_HYPER_SIZE(tss) * pcpu; + } else { + init_tss = symbol_value("per_cpu__init_tss"); + init_tss = xen_hyper_per_cpu(init_tss, pcpu); + } + +- buf = GETBUF(XEN_HYPER_SIZE(tss_struct)); ++ buf = GETBUF(XEN_HYPER_SIZE(tss)); + if (!readmem(init_tss, KVADDR, buf, +- XEN_HYPER_SIZE(tss_struct), "init_tss", RETURN_ON_ERROR)) { ++ XEN_HYPER_SIZE(tss), "init_tss", RETURN_ON_ERROR)) { + error(FATAL, "cannot read init_tss.\n"); + } +- esp = ULONG(buf + XEN_HYPER_OFFSET(tss_struct_esp0)); ++ esp = ULONG(buf + XEN_HYPER_OFFSET(tss_esp0)); + FREEBUF(buf); + base = esp & (~(STACKSIZE() - 1)); + +@@ -5745,8 +5745,8 @@ x86_init_hyper(int when) + #endif + XEN_HYPER_STRUCT_SIZE_INIT(cpu_time, "cpu_time"); + XEN_HYPER_STRUCT_SIZE_INIT(cpuinfo_x86, "cpuinfo_x86"); +- XEN_HYPER_STRUCT_SIZE_INIT(tss_struct, "tss_struct"); +- XEN_HYPER_MEMBER_OFFSET_INIT(tss_struct_esp0, "tss_struct", "esp0"); ++ XEN_HYPER_STRUCT_SIZE_INIT(tss, "tss_struct"); ++ XEN_HYPER_MEMBER_OFFSET_INIT(tss_esp0, "tss_struct", "esp0"); + XEN_HYPER_MEMBER_OFFSET_INIT(cpu_time_local_tsc_stamp, "cpu_time", "local_tsc_stamp"); + XEN_HYPER_MEMBER_OFFSET_INIT(cpu_time_stime_local_stamp, "cpu_time", "stime_local_stamp"); + XEN_HYPER_MEMBER_OFFSET_INIT(cpu_time_stime_master_stamp, "cpu_time", "stime_master_stamp"); +diff --git a/x86_64.c b/x86_64.c +index a4138ed..4f1a6d7 100644 +--- a/x86_64.c ++++ b/x86_64.c +@@ -7973,13 +7973,23 @@ x86_64_init_hyper(int when) + + case POST_GDB: + XEN_HYPER_STRUCT_SIZE_INIT(cpuinfo_x86, "cpuinfo_x86"); +- XEN_HYPER_STRUCT_SIZE_INIT(tss_struct, "tss_struct"); +- if (MEMBER_EXISTS("tss_struct", "__blh")) { +- XEN_HYPER_ASSIGN_OFFSET(tss_struct_rsp0) = MEMBER_OFFSET("tss_struct", "__blh") + sizeof(short unsigned int); ++ if (symbol_exists("per_cpu__tss_page")) { ++ XEN_HYPER_STRUCT_SIZE_INIT(tss, "tss64"); ++ XEN_HYPER_ASSIGN_OFFSET(tss_rsp0) = ++ MEMBER_OFFSET("tss64", "rsp0"); ++ XEN_HYPER_MEMBER_OFFSET_INIT(tss_ist, "tss64", "ist"); + } else { +- XEN_HYPER_ASSIGN_OFFSET(tss_struct_rsp0) = MEMBER_OFFSET("tss_struct", "rsp0"); ++ XEN_HYPER_STRUCT_SIZE_INIT(tss, "tss_struct"); ++ XEN_HYPER_MEMBER_OFFSET_INIT(tss_ist, "tss_struct", "ist"); ++ if (MEMBER_EXISTS("tss_struct", "__blh")) { ++ XEN_HYPER_ASSIGN_OFFSET(tss_rsp0) = ++ MEMBER_OFFSET("tss_struct", "__blh") + ++ sizeof(short unsigned int); ++ } else { ++ XEN_HYPER_ASSIGN_OFFSET(tss_rsp0) = ++ MEMBER_OFFSET("tss_struct", "rsp0"); ++ } + } +- XEN_HYPER_MEMBER_OFFSET_INIT(tss_struct_ist, "tss_struct", "ist"); + if (symbol_exists("cpu_data")) { + xht->cpu_data_address = symbol_value("cpu_data"); + } +diff --git a/xen_hyper.c b/xen_hyper.c +index f2f00e6..1030c0a 100644 +--- a/xen_hyper.c ++++ b/xen_hyper.c +@@ -338,33 +338,35 @@ xen_hyper_x86_pcpu_init(void) + if((xhpct->pcpu_struct = malloc(XEN_HYPER_SIZE(cpu_info))) == NULL) { + error(FATAL, "cannot malloc pcpu struct space.\n"); + } +- + /* get physical cpu context */ + xen_hyper_alloc_pcpu_context_space(XEN_HYPER_MAX_CPUS()); + if (symbol_exists("per_cpu__init_tss")) { + init_tss_base = symbol_value("per_cpu__init_tss"); + flag = TRUE; ++ } else if (symbol_exists("per_cpu__tss_page")) { ++ init_tss_base = symbol_value("per_cpu__tss_page"); ++ flag = TRUE; + } else { + init_tss_base = symbol_value("init_tss"); + flag = FALSE; + } +- buf = GETBUF(XEN_HYPER_SIZE(tss_struct)); ++ buf = GETBUF(XEN_HYPER_SIZE(tss)); + for_cpu_indexes(i, cpuid) + { + if (flag) + init_tss = xen_hyper_per_cpu(init_tss_base, cpuid); + else + init_tss = init_tss_base + +- XEN_HYPER_SIZE(tss_struct) * cpuid; ++ XEN_HYPER_SIZE(tss) * cpuid; + if (!readmem(init_tss, KVADDR, buf, +- XEN_HYPER_SIZE(tss_struct), "init_tss", RETURN_ON_ERROR)) { ++ XEN_HYPER_SIZE(tss), "init_tss", RETURN_ON_ERROR)) { + error(FATAL, "cannot read init_tss.\n"); + } + if (machine_type("X86")) { +- sp = ULONG(buf + XEN_HYPER_OFFSET(tss_struct_esp0)); ++ sp = ULONG(buf + XEN_HYPER_OFFSET(tss_esp0)); + } else if (machine_type("X86_64")) { +- sp = ULONG(buf + XEN_HYPER_OFFSET(tss_struct_rsp0)); +- } else ++ sp = ULONG(buf + XEN_HYPER_OFFSET(tss_rsp0)); ++ } else + sp = 0; + cpu_info = XEN_HYPER_GET_CPU_INFO(sp); + if (CRASHDEBUG(1)) { +@@ -1777,10 +1779,10 @@ xen_hyper_store_pcpu_context_tss(struct xen_hyper_pcpu_context *pcc, + + pcc->init_tss = init_tss; + if (machine_type("X86")) { +- pcc->sp.esp0 = ULONG(tss + XEN_HYPER_OFFSET(tss_struct_esp0)); ++ pcc->sp.esp0 = ULONG(tss + XEN_HYPER_OFFSET(tss_esp0)); + } else if (machine_type("X86_64")) { +- pcc->sp.rsp0 = ULONG(tss + XEN_HYPER_OFFSET(tss_struct_rsp0)); +- ist_p = (uint64_t *)(tss + XEN_HYPER_OFFSET(tss_struct_ist)); ++ pcc->sp.rsp0 = ULONG(tss + XEN_HYPER_OFFSET(tss_rsp0)); ++ ist_p = (uint64_t *)(tss + XEN_HYPER_OFFSET(tss_ist)); + for (i = 0; i < XEN_HYPER_TSS_IST_MAX; i++, ist_p++) { + pcc->ist[i] = ULONG(ist_p); + } +diff --git a/xen_hyper_defs.h b/xen_hyper_defs.h +index b871bdd..acf910a 100644 +--- a/xen_hyper_defs.h ++++ b/xen_hyper_defs.h +@@ -598,7 +598,7 @@ struct xen_hyper_size_table { + long scheduler; + long shared_info; + long timer; +- long tss_struct; ++ long tss; + long vcpu; + long vcpu_runstate_info; + long xen_crash_xen_regs_t; /* elf note v2 */ +@@ -727,9 +727,9 @@ struct xen_hyper_offset_table { + long timer_heap_offset; + long timer_killed; + /* tss */ +- long tss_struct_rsp0; +- long tss_struct_esp0; +- long tss_struct_ist; ++ long tss_rsp0; ++ long tss_esp0; ++ long tss_ist; + /* vcpu */ + long vcpu_vcpu_id; + long vcpu_processor; +diff --git a/xen_hyper_dump_tables.c b/xen_hyper_dump_tables.c +index eb646b6..0360d25 100644 +--- a/xen_hyper_dump_tables.c ++++ b/xen_hyper_dump_tables.c +@@ -636,8 +636,8 @@ xen_hyper_dump_xen_hyper_size_table(char *spec, ulong makestruct) + (buf, "%ld\n", xen_hyper_size_table.shared_info)); + XEN_HYPER_PRI(fp, len, "timer: ", buf, flag, + (buf, "%ld\n", xen_hyper_size_table.timer)); +- XEN_HYPER_PRI(fp, len, "tss_struct: ", buf, flag, +- (buf, "%ld\n", xen_hyper_size_table.tss_struct)); ++ XEN_HYPER_PRI(fp, len, "tss: ", buf, flag, ++ (buf, "%ld\n", xen_hyper_size_table.tss)); + XEN_HYPER_PRI(fp, len, "vcpu: ", buf, flag, + (buf, "%ld\n", xen_hyper_size_table.vcpu)); + XEN_HYPER_PRI(fp, len, "vcpu_runstate_info: ", buf, flag, +@@ -868,9 +868,9 @@ xen_hyper_dump_xen_hyper_offset_table(char *spec, ulong makestruct) + (buf, "%ld\n", xen_hyper_offset_table.timer_killed)); + + XEN_HYPER_PRI(fp, len, "tss_struct_rsp0: ", buf, flag, +- (buf, "%ld\n", xen_hyper_offset_table.tss_struct_rsp0)); ++ (buf, "%ld\n", xen_hyper_offset_table.tss_rsp0)); + XEN_HYPER_PRI(fp, len, "tss_struct_esp0: ", buf, flag, +- (buf, "%ld\n", xen_hyper_offset_table.tss_struct_esp0)); ++ (buf, "%ld\n", xen_hyper_offset_table.tss_esp0)); + + XEN_HYPER_PRI(fp, len, "vcpu_vcpu_id: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.vcpu_vcpu_id)); + +commit c408862daff0b07f0d98a1c309febcf6590ccf0c +Author: Dave Anderson +Date: Sun Dec 15 12:24:13 2019 -0500 + + When accessing the ARM64 kernel's "crash_notes" array, continue to + read the per-cpu NT_PRSTATUS note contents if an invalid note is + encountered. Without the patch, if an invalid note is found, all + other notes were ignored, and subsequent "bt" attempts on the active + tasks would fail. + (chenqiwu@xiaomi.com, anderson@redhat.com) + +diff --git a/arm64.c b/arm64.c +index 233029d..1b024a4 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -81,7 +81,7 @@ static int arm64_on_irq_stack(int, ulong); + static void arm64_set_irq_stack(struct bt_info *); + static void arm64_set_process_stack(struct bt_info *); + static int arm64_get_kvaddr_ranges(struct vaddr_range *); +-static int arm64_get_crash_notes(void); ++static void arm64_get_crash_notes(void); + static void arm64_calc_VA_BITS(void); + static int arm64_is_uvaddr(ulong, struct task_context *); + +@@ -465,11 +465,8 @@ arm64_init(int when) + * of the crash. We need this information to extract correct + * backtraces from the panic task. + */ +- if (!LIVE() && !arm64_get_crash_notes()) +- error(WARNING, +- "cannot retrieve registers for active task%s\n\n", +- kt->cpus > 1 ? "s" : ""); +- ++ if (!LIVE()) ++ arm64_get_crash_notes(); + break; + + case LOG_ONLY: +@@ -3578,7 +3575,7 @@ arm64_get_smp_cpus(void) + /* + * Retrieve task registers for the time of the crash. + */ +-static int ++static void + arm64_get_crash_notes(void) + { + struct machine_specific *ms = machdep->machspec; +@@ -3587,10 +3584,10 @@ arm64_get_crash_notes(void) + ulong offset; + char *buf, *p; + ulong *notes_ptrs; +- ulong i; ++ ulong i, found; + + if (!symbol_exists("crash_notes")) +- return FALSE; ++ return; + + crash_notes = symbol_value("crash_notes"); + +@@ -3602,9 +3599,9 @@ arm64_get_crash_notes(void) + */ + if (!readmem(crash_notes, KVADDR, ¬es_ptrs[kt->cpus-1], + sizeof(notes_ptrs[kt->cpus-1]), "crash_notes", RETURN_ON_ERROR)) { +- error(WARNING, "cannot read crash_notes\n"); ++ error(WARNING, "cannot read \"crash_notes\"\n"); + FREEBUF(notes_ptrs); +- return FALSE; ++ return; + } + + if (symbol_exists("__per_cpu_offset")) { +@@ -3620,12 +3617,11 @@ arm64_get_crash_notes(void) + if (!(ms->panic_task_regs = calloc((size_t)kt->cpus, sizeof(struct arm64_pt_regs)))) + error(FATAL, "cannot calloc panic_task_regs space\n"); + +- for (i = 0; i < kt->cpus; i++) { +- ++ for (i = found = 0; i < kt->cpus; i++) { + if (!readmem(notes_ptrs[i], KVADDR, buf, SIZE(note_buf), + "note_buf_t", RETURN_ON_ERROR)) { +- error(WARNING, "failed to read note_buf_t\n"); +- goto fail; ++ error(WARNING, "cpu %d: cannot read NT_PRSTATUS note\n", i); ++ continue; + } + + /* +@@ -3655,19 +3651,24 @@ arm64_get_crash_notes(void) + note->n_descsz == notesz) + BCOPY((char *)note, buf, notesz); + } else { +- error(WARNING, +- "cannot find NT_PRSTATUS note for cpu: %d\n", i); ++ error(WARNING, "cpu %d: cannot find NT_PRSTATUS note\n", i); + continue; + } + } + ++ /* ++ * Check the sanity of NT_PRSTATUS note only for each online cpu. ++ * If this cpu has invalid note, continue to find the crash notes ++ * for other online cpus. ++ */ + if (note->n_type != NT_PRSTATUS) { +- error(WARNING, "invalid note (n_type != NT_PRSTATUS)\n"); +- goto fail; ++ error(WARNING, "cpu %d: invalid NT_PRSTATUS note (n_type != NT_PRSTATUS)\n", i); ++ continue; + } +- if (p[0] != 'C' || p[1] != 'O' || p[2] != 'R' || p[3] != 'E') { +- error(WARNING, "invalid note (name != \"CORE\"\n"); +- goto fail; ++ ++ if (!STRNEQ(p, "CORE")) { ++ error(WARNING, "cpu %d: invalid NT_PRSTATUS note (name != \"CORE\")\n", i); ++ continue; + } + + /* +@@ -3680,18 +3681,17 @@ arm64_get_crash_notes(void) + + BCOPY(p + OFFSET(elf_prstatus_pr_reg), &ms->panic_task_regs[i], + sizeof(struct arm64_pt_regs)); ++ ++ found++; + } + + FREEBUF(buf); + FREEBUF(notes_ptrs); +- return TRUE; + +-fail: +- FREEBUF(buf); +- FREEBUF(notes_ptrs); +- free(ms->panic_task_regs); +- ms->panic_task_regs = NULL; +- return FALSE; ++ if (!found) { ++ free(ms->panic_task_regs); ++ ms->panic_task_regs = NULL; ++ } + } + + static void + +commit 63df9c067de0b2017f50f5d236954890bbb42fe3 +Author: Dave Anderson +Date: Mon Dec 16 11:28:46 2019 -0500 + + When accessing the 32-bit ARM kernel's "crash_notes" array, continue + to read the per-cpu NT_PRSTATUS note contents if an invalid note is + encountered. Without the patch, if an invalid note is found, all + other notes were ignored, and subsequent "bt" attempts on the active + tasks would fail. + (chenqiwu@xiaomi.com, anderson@redhat.com) + +diff --git a/arm.c b/arm.c +index b05b0b3..e52d29f 100644 +--- a/arm.c ++++ b/arm.c +@@ -26,7 +26,7 @@ + #include "defs.h" + + static void arm_parse_cmdline_args(void); +-static int arm_get_crash_notes(void); ++static void arm_get_crash_notes(void); + static int arm_verify_symbol(const char *, ulong, char); + static int arm_is_module_addr(ulong); + static int arm_is_kvaddr(ulong); +@@ -348,10 +348,8 @@ arm_init(int when) + * of the crash. We need this information to extract correct + * backtraces from the panic task. + */ +- if (!ACTIVE() && !arm_get_crash_notes()) +- error(WARNING, +- "cannot retrieve registers for active task%s\n\n", +- kt->cpus > 1 ? "s" : ""); ++ if (!ACTIVE()) ++ arm_get_crash_notes(); + + if (init_unwind_tables()) { + if (CRASHDEBUG(1)) +@@ -543,7 +541,7 @@ arm_parse_cmdline_args(void) + /* + * Retrieve task registers for the time of the crash. + */ +-static int ++static void + arm_get_crash_notes(void) + { + struct machine_specific *ms = machdep->machspec; +@@ -552,10 +550,10 @@ arm_get_crash_notes(void) + ulong offset; + char *buf, *p; + ulong *notes_ptrs; +- ulong i; ++ ulong i, found; + + if (!symbol_exists("crash_notes")) +- return FALSE; ++ return; + + crash_notes = symbol_value("crash_notes"); + +@@ -570,11 +568,10 @@ arm_get_crash_notes(void) + RETURN_ON_ERROR)) { + error(WARNING, "cannot read crash_notes\n"); + FREEBUF(notes_ptrs); +- return FALSE; ++ return; + } + + if (symbol_exists("__per_cpu_offset")) { +- + /* Add __per_cpu_offset for each cpu to form the pointer to the notes */ + for (i = 0; icpus; i++) + notes_ptrs[i] = notes_ptrs[kt->cpus-1] + kt->__per_cpu_offset[i]; +@@ -585,12 +582,11 @@ arm_get_crash_notes(void) + if (!(panic_task_regs = calloc((size_t)kt->cpus, sizeof(*panic_task_regs)))) + error(FATAL, "cannot calloc panic_task_regs space\n"); + +- for (i=0;icpus;i++) { +- ++ for (i = found = 0; icpus; i++) { + if (!readmem(notes_ptrs[i], KVADDR, buf, SIZE(note_buf), "note_buf_t", + RETURN_ON_ERROR)) { +- error(WARNING, "failed to read note_buf_t\n"); +- goto fail; ++ error(WARNING, "cpu %d: cannot read NT_PRSTATUS note\n", i); ++ continue; + } + + /* +@@ -620,19 +616,23 @@ arm_get_crash_notes(void) + note->n_descsz == notesz) + BCOPY((char *)note, buf, notesz); + } else { +- error(WARNING, +- "cannot find NT_PRSTATUS note for cpu: %d\n", i); ++ error(WARNING, "cpu %d: cannot find NT_PRSTATUS note\n", i); + continue; + } + } +- ++ /* ++ * Check the sanity of NT_PRSTATUS note only for each online cpu. ++ * If this cpu has invalid note, continue to find the crash notes ++ * for other online cpus. ++ */ + if (note->n_type != NT_PRSTATUS) { +- error(WARNING, "invalid note (n_type != NT_PRSTATUS)\n"); +- goto fail; ++ error(WARNING, "cpu %d: invalid NT_PRSTATUS note (n_type != NT_PRSTATUS)\n", i); ++ continue; + } +- if (p[0] != 'C' || p[1] != 'O' || p[2] != 'R' || p[3] != 'E') { +- error(WARNING, "invalid note (name != \"CORE\"\n"); +- goto fail; ++ ++ if (!STRNEQ(p, "CORE")) { ++ error(WARNING, "cpu %d: invalid NT_PRSTATUS note (name != \"CORE\")\n", i); ++ continue; + } + + /* +@@ -646,6 +646,7 @@ arm_get_crash_notes(void) + BCOPY(p + OFFSET(elf_prstatus_pr_reg), &panic_task_regs[i], + sizeof(panic_task_regs[i])); + ++ found++; + } + + /* +@@ -656,13 +657,10 @@ arm_get_crash_notes(void) + + FREEBUF(buf); + FREEBUF(notes_ptrs); +- return TRUE; +- +-fail: +- FREEBUF(buf); +- FREEBUF(notes_ptrs); +- free(panic_task_regs); +- return FALSE; ++ if (!found) { ++ free(panic_task_regs); ++ ms->crash_task_regs = NULL; ++ } + } + + /* + +commit af7f78dc501b8acf7fee3f924f69e93513d0a74b +Author: Dave Anderson +Date: Fri Dec 20 14:33:11 2019 -0500 + + Fix for the "log -a" option. The kernel's sk_buff.len field is a + 32-bit unsigned int, but crash was reading its 32-bit value into a + 64-bit unsigned long stack variable. All extra bits that pre-existed + in the upper 32-bits of the stack variable were passed along as part + of a buffer size request; if the upper 32-bit bits were non-zero, + then the command would fail with a dump of the internal buffer + allocation stats followed by the message "log: cannot allocate any + more memory!". + (anderson@redhat.com) + +diff --git a/kernel.c b/kernel.c +index 80486ba..68ee282 100644 +--- a/kernel.c ++++ b/kernel.c +@@ -11284,7 +11284,8 @@ dump_audit_skb_queue(ulong audit_skb_queue) + + p = skb_buff_head_next; + do { +- ulong data, len, data_len; ++ ulong data, data_len; ++ uint len; + uint16_t nlmsg_type; + char *buf = NULL; + +@@ -11295,7 +11296,7 @@ dump_audit_skb_queue(ulong audit_skb_queue) + KVADDR, + &len, + SIZE(sk_buff_len), +- "sk_buff.data", ++ "sk_buff.len", + FAULT_ON_ERROR); + + data_len = len - roundup(SIZE(nlmsghdr), NLMSG_ALIGNTO); + +commit 5e975dd8c817ea6aea35e1e15b83c378aee9c136 +Author: Dave Anderson +Date: Tue Dec 24 08:43:52 2019 -0500 + + When determining the ARM64 kernel's "vabits_actual" value by reading + the new TCR_EL1.T1SZ vmcoreinfo entry, display its value during + session initialization only when invoking crash with "-d1" or larger + -d debug value. + (anderson@redhat.com) + +diff --git a/arm64.c b/arm64.c +index 1b024a4..6c2c58f 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -3864,7 +3864,8 @@ arm64_calc_VA_BITS(void) + * vabits_actual = 64 - T1SZ; + */ + value = 64 - strtoll(string, NULL, 0); +- fprintf(fp, "vmcoreinfo : vabits_actual: %ld\n", value); ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "vmcoreinfo : vabits_actual: %ld\n", value); + free(string); + machdep->machspec->VA_BITS_ACTUAL = value; + machdep->machspec->VA_BITS = value; + +commit 0ab7ac3bea5deaa3da894247ffab9ef2433c1b9b +Author: Dave Anderson +Date: Tue Jan 7 09:34:38 2020 -0500 + + Update copyright to 2020 in crash version output. + +diff --git a/help.c b/help.c +index eed249b..a481850 100644 +--- a/help.c ++++ b/help.c +@@ -1,8 +1,8 @@ + /* help.c - core analysis suite + * + * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. +- * Copyright (C) 2002-2019 David Anderson +- * Copyright (C) 2002-2019 Red Hat, Inc. All rights reserved. ++ * Copyright (C) 2002-2020 David Anderson ++ * Copyright (C) 2002-2020 Red Hat, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -8269,7 +8269,7 @@ display_version(void) + static + char *version_info[] = { + +-"Copyright (C) 2002-2019 Red Hat, Inc.", ++"Copyright (C) 2002-2020 Red Hat, Inc.", + "Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation", + "Copyright (C) 1999-2006 Hewlett-Packard Co", + "Copyright (C) 2005, 2006, 2011, 2012 Fujitsu Limited", + +commit 08b01834641b0a387c86adf651c660df0fe37ae1 +Author: Dave Anderson +Date: Tue Jan 7 11:07:12 2020 -0500 + + Fix for ARM64 when running against Linux 5.5-rc1 and later kernels + that contain commit b6e43c0e3129ffe87e65c85f20fcbdf0eb86fba0, titled + "arm64: remove __exception annotations". Without the patch, the + ARM64 crash session fails during initialization with the error + message "crash: cannot resolve __exception_text_start". + (anderson@redhat.com) + +diff --git a/arm64.c b/arm64.c +index 6c2c58f..7662d71 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -1,8 +1,8 @@ + /* + * arm64.c - core analysis suite + * +- * Copyright (C) 2012-2019 David Anderson +- * Copyright (C) 2012-2019 Red Hat, Inc. All rights reserved. ++ * Copyright (C) 2012-2020 David Anderson ++ * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -1644,10 +1644,11 @@ arm64_stackframe_init(void) + machdep->machspec->kern_eframe_offset = SIZE(pt_regs); + } + +- machdep->machspec->__exception_text_start = +- symbol_value("__exception_text_start"); +- machdep->machspec->__exception_text_end = +- symbol_value("__exception_text_end"); ++ if ((sp1 = kernel_symbol_search("__exception_text_start")) && ++ (sp2 = kernel_symbol_search("__exception_text_end"))) { ++ machdep->machspec->__exception_text_start = sp1->value; ++ machdep->machspec->__exception_text_end = sp2->value; ++ } + if ((sp1 = kernel_symbol_search("__irqentry_text_start")) && + (sp2 = kernel_symbol_search("__irqentry_text_end"))) { + machdep->machspec->__irqentry_text_start = sp1->value; +@@ -1856,20 +1857,38 @@ arm64_eframe_search(struct bt_info *bt) + return count; + } + ++static char *arm64_exception_functions[] = { ++ "do_undefinstr", ++ "do_sysinstr", ++ "do_debug_exception", ++ "do_mem_abort", ++ "do_el0_irq_bp_hardening", ++ "do_sp_pc_abort", ++ NULL ++}; ++ + static int + arm64_in_exception_text(ulong ptr) + { + struct machine_specific *ms = machdep->machspec; +- +- if ((ptr >= ms->__exception_text_start) && +- (ptr < ms->__exception_text_end)) +- return TRUE; ++ char *name, **func; + + if (ms->__irqentry_text_start && ms->__irqentry_text_end && + ((ptr >= ms->__irqentry_text_start) && + (ptr < ms->__irqentry_text_end))) + return TRUE; + ++ if (ms->__exception_text_start && ms->__exception_text_end) { ++ if ((ptr >= ms->__exception_text_start) && ++ (ptr < ms->__exception_text_end)) ++ return TRUE; ++ } else if ((name = closest_symbol(ptr))) { /* Linux 5.5 and later */ ++ for (func = &arm64_exception_functions[0]; *func; func++) { ++ if (STREQ(name, *func)) ++ return TRUE; ++ } ++ } ++ + return FALSE; + } + + +commit 7c2d41e1b25e9fec50d525361bcfa29bdaa410b2 +Author: Dave Anderson +Date: Wed Jan 8 14:28:39 2020 -0500 + + Fix for support of ELF format kdump vmcores from S390X KASLR kernels. + Without the patch, the crash session fails during initialization with + the error message "crash: vmlinux and vmcore do not match!". + (anderson@redhat.com) + +diff --git a/symbols.c b/symbols.c +index 7e1bca7..82ac549 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -1,8 +1,8 @@ + /* symbols.c - core analysis suite + * + * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. +- * Copyright (C) 2002-2019 David Anderson +- * Copyright (C) 2002-2019 Red Hat, Inc. All rights reserved. ++ * Copyright (C) 2002-2020 David Anderson ++ * Copyright (C) 2002-2020 Red Hat, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -597,6 +597,11 @@ kaslr_init(void) + !machine_type("S390X")) || (kt->flags & RELOC_SET)) + return; + ++ if ((string = pc->read_vmcoreinfo("SYMBOL(_stext)"))) { ++ kt->vmcoreinfo._stext_SYMBOL = htol(string, RETURN_ON_ERROR, NULL); ++ free(string); ++ } ++ + /* + * --kaslr=auto + */ +@@ -609,8 +614,7 @@ kaslr_init(void) + st->_stext_vmlinux = UNINITIALIZED; + } + +- if (machine_type("S390X") && /* Linux 5.2 */ +- (symbol_value_from_proc_kallsyms("__kaslr_offset") != BADVAL)) { ++ if (machine_type("S390X")) { + kt->flags2 |= (RELOC_AUTO|KASLR); + st->_stext_vmlinux = UNINITIALIZED; + } +@@ -622,12 +626,6 @@ kaslr_init(void) + kt->flags2 |= KASLR_CHECK; + } + } else if (KDUMP_DUMPFILE() || DISKDUMP_DUMPFILE()) { +- if ((string = pc->read_vmcoreinfo("SYMBOL(_stext)"))) { +- kt->vmcoreinfo._stext_SYMBOL = +- htol(string, RETURN_ON_ERROR, NULL); +- free(string); +- } +- + /* Linux 3.14 */ + if ((string = pc->read_vmcoreinfo("KERNELOFFSET"))) { + free(string); + +commit 6e033fe099f8faea8fe284b9f7c08da7bc3af7a7 +Author: Dave Anderson +Date: Thu Jan 16 11:46:10 2020 -0500 + + Fix for support of S390X standalone dumpfiles and LKCD dumpfiles that + were taken from S390X KASLR kernels. + (zaslonko@linux.ibm.com) + +diff --git a/defs.h b/defs.h +index efa40b9..88a47d6 100644 +--- a/defs.h ++++ b/defs.h +@@ -6267,6 +6267,8 @@ void get_s390_panicmsg(char *); + /* + * s390x.c + */ ++ulong get_stext_relocated_s390x(void); ++ + #ifdef S390X + void s390x_init(int); + void s390x_dump_machdep_table(ulong); +diff --git a/s390x.c b/s390x.c +index 8840cc7..e030f93 100644 +--- a/s390x.c ++++ b/s390x.c +@@ -455,6 +455,78 @@ static void s390x_check_live(void) + pc->flags2 |= LIVE_DUMP; + } + ++static char * ++vmcoreinfo_read_string_s390x(const char *vmcoreinfo, const char *key) ++{ ++ char *value_string = NULL; ++ size_t value_length; ++ char keybuf[128]; ++ char *p1, *p2; ++ ++ sprintf(keybuf, "%s=", key); ++ ++ if ((p1 = strstr(vmcoreinfo, keybuf))) { ++ p2 = p1 + strlen(keybuf); ++ p1 = strstr(p2, "\n"); ++ value_length = p1-p2; ++ value_string = calloc(value_length + 1, sizeof(char)); ++ strncpy(value_string, p2, value_length); ++ value_string[value_length] = NULLCHAR; ++ } ++ ++ return value_string; ++} ++ ++/* ++ * Read _stext symbol from vmcoreinfo when lowcore vmcoreinfo pointer is present ++ * in the dump (can be relevant for s390 and lkcd dump formats). ++ */ ++ulong get_stext_relocated_s390x(void) ++{ ++ char *_stext_string, *vmcoreinfo; ++ Elf64_Nhdr note; ++ char str[128]; ++ ulong val = 0; ++ ulong addr; ++ ++ if (!readmem(S390X_LC_VMCORE_INFO, PHYSADDR, &addr, ++ sizeof(addr), "s390x vmcoreinfo ptr", ++ QUIET|RETURN_ON_ERROR)) ++ return 0; ++ if (addr == 0 || addr & 0x1) ++ return 0; ++ if (!readmem(addr, PHYSADDR, ¬e, ++ sizeof(note), "Elf64_Nhdr vmcoreinfo", ++ QUIET|RETURN_ON_ERROR)) ++ return 0; ++ memset(str, 0, sizeof(str)); ++ if (!readmem(addr + sizeof(note), PHYSADDR, str, ++ note.n_namesz, "VMCOREINFO", ++ QUIET|RETURN_ON_ERROR)) ++ return 0; ++ if (memcmp(str, "VMCOREINFO", sizeof("VMCOREINFO")) != 0) ++ return 0; ++ if ((vmcoreinfo = malloc(note.n_descsz + 1)) == NULL) { ++ error(INFO, "s390x: cannot malloc vmcoreinfo buffer\n"); ++ return 0; ++ } ++ addr = addr + sizeof(note) + note.n_namesz + 1; ++ if (!readmem(addr, PHYSADDR, vmcoreinfo, ++ note.n_descsz, "s390x vmcoreinfo", ++ QUIET|RETURN_ON_ERROR)) { ++ free(vmcoreinfo); ++ return 0; ++ } ++ vmcoreinfo[note.n_descsz] = 0; ++ if ((_stext_string = vmcoreinfo_read_string_s390x(vmcoreinfo, ++ "SYMBOL(_stext)"))) { ++ val = htol(_stext_string, RETURN_ON_ERROR, NULL); ++ free(_stext_string); ++ } ++ free(vmcoreinfo); ++ return val; ++} ++ + /* + * Do all necessary machine-specific setup here. This is called several + * times during initialization. +@@ -1948,4 +2020,10 @@ s390x_get_kvaddr_ranges(struct vaddr_range *vrp) + + return cnt; + } +-#endif ++#else ++#include "defs.h" ++ulong get_stext_relocated_s390x(void) ++{ ++ return 0; ++} ++#endif /* S390X */ +diff --git a/symbols.c b/symbols.c +index 82ac549..6df3358 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -614,7 +614,9 @@ kaslr_init(void) + st->_stext_vmlinux = UNINITIALIZED; + } + +- if (machine_type("S390X")) { ++ if (machine_type("S390X")) { ++ if (!kt->vmcoreinfo._stext_SYMBOL) ++ kt->vmcoreinfo._stext_SYMBOL = get_stext_relocated_s390x(); + kt->flags2 |= (RELOC_AUTO|KASLR); + st->_stext_vmlinux = UNINITIALIZED; + } + +commit c6b19715495221dca52a57690419f9df9777573d +Author: Dave Anderson +Date: Fri Jan 17 13:34:53 2020 -0500 + + Rework the previous patch for support of S390X standalone dumpfiles + and LKCD dumpfiles that were taken from S390X KASLR kernels to avoid + calling an s390x-specific function from generic code. + (zaslonko@linux.ibm.com) + +diff --git a/defs.h b/defs.h +index 88a47d6..efa40b9 100644 +--- a/defs.h ++++ b/defs.h +@@ -6267,8 +6267,6 @@ void get_s390_panicmsg(char *); + /* + * s390x.c + */ +-ulong get_stext_relocated_s390x(void); +- + #ifdef S390X + void s390x_init(int); + void s390x_dump_machdep_table(ulong); +diff --git a/s390x.c b/s390x.c +index e030f93..c07d283 100644 +--- a/s390x.c ++++ b/s390x.c +@@ -478,53 +478,72 @@ vmcoreinfo_read_string_s390x(const char *vmcoreinfo, const char *key) + } + + /* +- * Read _stext symbol from vmcoreinfo when lowcore vmcoreinfo pointer is present +- * in the dump (can be relevant for s390 and lkcd dump formats). ++ * Check the value in well-known lowcore location and process it as either ++ * an explicit KASLR offset (early dump case) or as vmcoreinfo pointer to ++ * read the relocated _stext symbol value (important for s390 and lkcd dump ++ * formats). + */ +-ulong get_stext_relocated_s390x(void) ++static void s390x_check_kaslr(void) + { + char *_stext_string, *vmcoreinfo; + Elf64_Nhdr note; + char str[128]; +- ulong val = 0; + ulong addr; + ++ /* Read the value from well-known lowcore location*/ + if (!readmem(S390X_LC_VMCORE_INFO, PHYSADDR, &addr, + sizeof(addr), "s390x vmcoreinfo ptr", + QUIET|RETURN_ON_ERROR)) +- return 0; +- if (addr == 0 || addr & 0x1) +- return 0; ++ return; ++ if (addr == 0) ++ return; ++ /* Check for explicit kaslr offset flag */ ++ if (addr & 0x1UL) { ++ /* Drop the last bit to get an offset value */ ++ addr &= ~(0x1UL); ++ /* Make sure the offset is aligned by 0x1000 */ ++ if (addr && !(addr & 0xfff)) { ++ kt->relocate = addr * (-1); ++ kt->flags |= RELOC_SET; ++ kt->flags2 |= KASLR; ++ } ++ return; ++ } ++ /* Use the addr value as vmcoreinfo pointer */ + if (!readmem(addr, PHYSADDR, ¬e, + sizeof(note), "Elf64_Nhdr vmcoreinfo", + QUIET|RETURN_ON_ERROR)) +- return 0; ++ return; + memset(str, 0, sizeof(str)); + if (!readmem(addr + sizeof(note), PHYSADDR, str, + note.n_namesz, "VMCOREINFO", + QUIET|RETURN_ON_ERROR)) +- return 0; ++ return; + if (memcmp(str, "VMCOREINFO", sizeof("VMCOREINFO")) != 0) +- return 0; ++ return; + if ((vmcoreinfo = malloc(note.n_descsz + 1)) == NULL) { +- error(INFO, "s390x: cannot malloc vmcoreinfo buffer\n"); +- return 0; ++ error(INFO, "s390x_check_kaslr: cannot malloc vmcoreinfo buffer\n"); ++ return; + } + addr = addr + sizeof(note) + note.n_namesz + 1; + if (!readmem(addr, PHYSADDR, vmcoreinfo, + note.n_descsz, "s390x vmcoreinfo", + QUIET|RETURN_ON_ERROR)) { + free(vmcoreinfo); +- return 0; ++ return; + } +- vmcoreinfo[note.n_descsz] = 0; ++ vmcoreinfo[note.n_descsz] = NULLCHAR; ++ /* ++ * Read relocated _stext symbol value and store it in the kernel_table ++ * for further processing within derive_kaslr_offset(). ++ */ + if ((_stext_string = vmcoreinfo_read_string_s390x(vmcoreinfo, + "SYMBOL(_stext)"))) { +- val = htol(_stext_string, RETURN_ON_ERROR, NULL); ++ kt->vmcoreinfo._stext_SYMBOL = htol(_stext_string, ++ RETURN_ON_ERROR, NULL); + free(_stext_string); + } + free(vmcoreinfo); +- return val; + } + + /* +@@ -534,8 +553,6 @@ ulong get_stext_relocated_s390x(void) + void + s390x_init(int when) + { +- ulong s390x_lc_kaslr; +- + switch (when) + { + case SETUP_ENV: +@@ -562,24 +579,8 @@ s390x_init(int when) + machdep->verify_paddr = generic_verify_paddr; + machdep->get_kvaddr_ranges = s390x_get_kvaddr_ranges; + machdep->ptrs_per_pgd = PTRS_PER_PGD; +- if (DUMPFILE() && !(kt->flags & RELOC_SET)) { +- /* Read the value from well-known lowcore location*/ +- if (readmem(S390X_LC_VMCORE_INFO, PHYSADDR, &s390x_lc_kaslr, +- sizeof(s390x_lc_kaslr), "s390x_lc_kaslr", +- QUIET|RETURN_ON_ERROR)) { +- /* Check for explicit kaslr offset flag */ +- if (s390x_lc_kaslr & 0x1UL) { +- /* Drop the last bit to get an offset value */ +- s390x_lc_kaslr &= ~(0x1UL); +- /* Make sure the offset is aligned by 0x1000 */ +- if (s390x_lc_kaslr && !(s390x_lc_kaslr & 0xfff)) { +- kt->relocate = s390x_lc_kaslr * (-1); +- kt->flags |= RELOC_SET; +- kt->flags2 |= KASLR; +- } +- } +- } +- } ++ if (DUMPFILE() && !(kt->flags & RELOC_SET)) ++ s390x_check_kaslr(); + break; + + case PRE_GDB: +@@ -2020,10 +2021,4 @@ s390x_get_kvaddr_ranges(struct vaddr_range *vrp) + + return cnt; + } +-#else +-#include "defs.h" +-ulong get_stext_relocated_s390x(void) +-{ +- return 0; +-} + #endif /* S390X */ +diff --git a/symbols.c b/symbols.c +index 6df3358..f04e8b5 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -597,7 +597,8 @@ kaslr_init(void) + !machine_type("S390X")) || (kt->flags & RELOC_SET)) + return; + +- if ((string = pc->read_vmcoreinfo("SYMBOL(_stext)"))) { ++ if (!kt->vmcoreinfo._stext_SYMBOL && ++ (string = pc->read_vmcoreinfo("SYMBOL(_stext)"))) { + kt->vmcoreinfo._stext_SYMBOL = htol(string, RETURN_ON_ERROR, NULL); + free(string); + } +@@ -615,8 +616,6 @@ kaslr_init(void) + } + + if (machine_type("S390X")) { +- if (!kt->vmcoreinfo._stext_SYMBOL) +- kt->vmcoreinfo._stext_SYMBOL = get_stext_relocated_s390x(); + kt->flags2 |= (RELOC_AUTO|KASLR); + st->_stext_vmlinux = UNINITIALIZED; + } + +commit 6c1c8ac6b3c877e6facd6f2807ba721ddbc4597b +Author: Dave Anderson +Date: Wed Jan 29 11:10:26 2020 -0500 + + Fix for a gcc-10 compilation error. Without the patch, the build of + the crash library fails with a stream of error messages indicating + "multiple definition of 'diskdump_flags'" + (anderson@redhat.com) + +diff --git a/defs.h b/defs.h +index efa40b9..ac24a5d 100644 +--- a/defs.h ++++ b/defs.h +@@ -1,8 +1,8 @@ + /* defs.h - core analysis suite + * + * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. +- * Copyright (C) 2002-2019 David Anderson +- * Copyright (C) 2002-2019 Red Hat, Inc. All rights reserved. ++ * Copyright (C) 2002-2020 David Anderson ++ * Copyright (C) 2002-2020 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002 Silicon Graphics, Inc. + * + * This program is free software; you can redistribute it and/or modify +@@ -6447,7 +6447,7 @@ FILE *set_diskdump_fp(FILE *); + void get_diskdump_regs(struct bt_info *, ulong *, ulong *); + int diskdump_phys_base(unsigned long *); + int diskdump_set_phys_base(unsigned long); +-ulong *diskdump_flags; ++extern ulong *diskdump_flags; + int is_partial_diskdump(void); + int get_dump_level(void); + int dumpfile_is_split(void); diff --git a/SOURCES/github_b1a6e13a_p_regression.patch b/SOURCES/github_b1a6e13a_p_regression.patch deleted file mode 100644 index be51417..0000000 --- a/SOURCES/github_b1a6e13a_p_regression.patch +++ /dev/null @@ -1,28 +0,0 @@ -commit b1a6e13a93661dfae7df15fe32862bddf4026c80 -Author: Dave Anderson -Date: Tue May 21 14:09:13 2019 -0400 - - Fix for a crash-7.2.6 regression to the "p" command. Without the - patch, a gdb pass-through command construct such as: - p ((struct zone *)0xffff901e3ffda000)->min_slab_pages - gets parsed incorrectly, and the "-" is mistaken for an argument - option, and each of the subsequent characters are marked as an - "invalid option". - (dwysocha@redhat.com) - -diff --git a/tools.c b/tools.c -index eceea90..2d95c3a 100644 ---- a/tools.c -+++ b/tools.c -@@ -246,8 +246,10 @@ next: - break; - } - } -- if (expression == 0) -+ if (expression == 0) { - i++; -+ continue; -+ } - } - - if (str[i] != NULLCHAR && str[i] != '\n') { diff --git a/SOURCES/github_bf48dd4e_arm64_devmem_read_error.patch b/SOURCES/github_bf48dd4e_arm64_devmem_read_error.patch deleted file mode 100644 index d3982cd..0000000 --- a/SOURCES/github_bf48dd4e_arm64_devmem_read_error.patch +++ /dev/null @@ -1,26 +0,0 @@ -commit bf48dd4e9926515345cad06c1bfce49d7a057a26 -Author: Dave Anderson -Date: Mon Jun 10 14:12:52 2019 -0400 - - Fix for Linux 4.16 and later ARM64 kernels that contain kernel commit - fa2a8445b1d3810c52f2a6b3a006456bd1aacb7e, titled "arm64: allow ID map - to be extended to 52 bits", and which have been configured with both - CONFIG_DEVMEM=y and CONFIG_STRICT_DEVMEM=y. Without the patch, an - inconsequential error message indicating "crash: read error: kernel - virtual address:
type: idmap_ptrs_per_pgd" is displayed - during initialization. - (anderson@redhat.com) - -diff --git a/arm64.c b/arm64.c -index 5b82263..6b34b5f 100644 ---- a/arm64.c -+++ b/arm64.c -@@ -283,7 +283,7 @@ arm64_init(int when) - case 65536: - if (kernel_symbol_exists("idmap_ptrs_per_pgd") && - readmem(symbol_value("idmap_ptrs_per_pgd"), KVADDR, -- &value, sizeof(ulong), "idmap_ptrs_per_pgd", RETURN_ON_ERROR)) -+ &value, sizeof(ulong), "idmap_ptrs_per_pgd", QUIET|RETURN_ON_ERROR)) - machdep->ptrs_per_pgd = value; - - if (machdep->machspec->VA_BITS > PGDIR_SHIFT_L3_64K) { diff --git a/SPECS/crash.spec b/SPECS/crash.spec index b38e9f6..a0c8969 100644 --- a/SPECS/crash.spec +++ b/SPECS/crash.spec @@ -3,8 +3,8 @@ # Summary: Kernel analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles Name: crash -Version: 7.2.6 -Release: 2%{?dist} +Version: 7.2.7 +Release: 3%{?dist} License: GPLv3 Group: Development/Debuggers Source: http://people.redhat.com/anderson/crash-%{version}.tar.gz @@ -16,8 +16,8 @@ BuildRequires: ncurses-devel zlib-devel lzo-devel bison snappy-devel Requires: binutils Patch0: lzo_snappy.patch Patch1: rhel8_build.patch -Patch2: github_bf48dd4e_arm64_devmem_read_error.patch -Patch3: github_b1a6e13a_p_regression.patch +Patch2: github_105a3e13_to_b5c2359f.patch +Patch3: github_5cbb2fd8_to_6c1c8ac6.patch %description The core analysis suite is a self-contained tool that can be used to @@ -40,8 +40,8 @@ offered by Mission Critical Linux, or the LKCD kernel patch. %setup -n %{name}-%{version} -q %patch0 -p1 -b lzo_snappy.patch %patch1 -p1 -b rhel8_build.patch -%patch2 -p1 -b github_bf48dd4e_arm64_devmem_read_error.patch -%patch3 -p1 -b github_b1a6e13a_p_regression.patch +%patch2 -p1 -b github_105a3e13_to_b5c2359f.patch +%patch3 -p1 -b github_5cbb2fd8_to_6c1c8ac6.patch %build make RPMPKG="%{version}-%{release}" CFLAGS="%{optflags}" @@ -70,6 +70,20 @@ rm -rf %{buildroot} %{_includedir}/* %changelog +* Mon Feb 3 2020 Dave Anderson - 7.2.7-3 +- Rebase to github commit 6c1c8ac6 + Resolves: rhbz#1738619 +- Fix "log -a" option + Resolves: rhbz#1785537 +- Fix for ELF kdump vmcores form s390x KASLR kernels + Resolves: rhbz#1786996 + +* Mon Nov 11 2019 Dave Anderson - 7.2.7-2 +- Rebase to latest upstream sources + Resolves: rhbz#1738619 +- Support for KASLR on s390x + Resolves: rhbz# 1753172 + * Mon Jun 10 2019 Dave Anderson - 7.2.6-2 - Fix "p" command regression Resolves: rhbz#1718417