Kernel analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1485 lines
46 KiB

commit 5cbb2fd8c20c46793095522059b1efc8232df926
Author: Dave Anderson <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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, &notes_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 <anderson@redhat.com>
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; i<kt->cpus; 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;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;
}
/*
@@ -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 <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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 <anderson@redhat.com>
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, &note,
+ 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 <anderson@redhat.com>
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, &note,
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 <anderson@redhat.com>
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);