Update to the latest commit <489093c2183f>
Release: crash-8.0.2-4 Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
This commit is contained in:
parent
22c47c372b
commit
f24b8df61c
@ -0,0 +1,80 @@
|
||||
From 92de7c34b1f910abff4d77522f74454ea0263a90 Mon Sep 17 00:00:00 2001
|
||||
From: Lianbo Jiang <lijiang@redhat.com>
|
||||
Date: Mon, 13 Feb 2023 11:12:12 +0800
|
||||
Subject: [PATCH 01/12] Fix for "bt" command printing "bogus exception frame"
|
||||
warning
|
||||
|
||||
Currently, the "bt" command may print a bogus exception frame
|
||||
and the remaining frame will be truncated on x86_64 when using the
|
||||
"virsh send-key <kvm guest> KEY_LEFTALT KEY_SYSRQ KEY_C" command
|
||||
to trigger a panic from the KVM host. For example:
|
||||
|
||||
crash> bt
|
||||
PID: 0 TASK: ffff9e7a47e32f00 CPU: 3 COMMAND: "swapper/3"
|
||||
#0 [ffffba7900118bb8] machine_kexec at ffffffff87e5c2c7
|
||||
#1 [ffffba7900118c08] __crash_kexec at ffffffff87f9500d
|
||||
#2 [ffffba7900118cd0] panic at ffffffff87edfff9
|
||||
#3 [ffffba7900118d50] sysrq_handle_crash at ffffffff883ce2c1
|
||||
...
|
||||
#16 [ffffba7900118fd8] handle_edge_irq at ffffffff87f559f2
|
||||
#17 [ffffba7900118ff0] asm_call_on_stack at ffffffff88800fa2
|
||||
--- <IRQ stack> ---
|
||||
#18 [ffffba790008bda0] asm_call_on_stack at ffffffff88800fa2
|
||||
RIP: ffffffffffffffff RSP: 0000000000000124 RFLAGS: 00000003
|
||||
RAX: 0000000000000000 RBX: 0000000000000001 RCX: 0000000000000000
|
||||
RDX: ffffffff88800c1e RSI: 0000000000000000 RDI: 0000000000000000
|
||||
RBP: 0000000000000001 R8: 0000000000000000 R9: 0000000000000000
|
||||
R10: 0000000000000000 R11: ffffffff88760555 R12: ffffba790008be08
|
||||
R13: ffffffff87f18002 R14: ffff9e7a47e32f00 R15: ffff9e7bb6198e00
|
||||
ORIG_RAX: 0000000000000000 CS: 0003 SS: 0000
|
||||
bt: WARNING: possibly bogus exception frame
|
||||
crash>
|
||||
|
||||
The following related kernel commits cause the current issue, crash
|
||||
needs to adjust the value of irq_eframe_link.
|
||||
|
||||
Related kernel commits:
|
||||
[1] v5.8: 931b94145981 ("x86/entry: Provide helpers for executing on the irqstack")
|
||||
[2] v5.8: fa5e5c409213 ("x86/entry: Use idtentry for interrupts")
|
||||
[3] v5.12: 52d743f3b712 ("x86/softirq: Remove indirection in do_softirq_own_stack()")
|
||||
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
|
||||
---
|
||||
x86_64.c | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
diff --git a/x86_64.c b/x86_64.c
|
||||
index 7a5d6f050c89..5b671bd97775 100644
|
||||
--- a/x86_64.c
|
||||
+++ b/x86_64.c
|
||||
@@ -3938,6 +3938,11 @@ in_exception_stack:
|
||||
if (irq_eframe) {
|
||||
bt->flags |= BT_EXCEPTION_FRAME;
|
||||
i = (irq_eframe - bt->stackbase)/sizeof(ulong);
|
||||
+ if (symbol_exists("asm_common_interrupt")) {
|
||||
+ i -= 1;
|
||||
+ up = (ulong *)(&bt->stackbuf[i*sizeof(ulong)]);
|
||||
+ bt->instptr = *up;
|
||||
+ }
|
||||
x86_64_print_stack_entry(bt, ofp, level, i, bt->instptr);
|
||||
bt->flags &= ~(ulonglong)BT_EXCEPTION_FRAME;
|
||||
cs = x86_64_exception_frame(EFRAME_PRINT|EFRAME_CS, 0,
|
||||
@@ -6521,6 +6526,14 @@ x86_64_irq_eframe_link_init(void)
|
||||
else
|
||||
return;
|
||||
|
||||
+ if (symbol_exists("asm_common_interrupt")) {
|
||||
+ if (symbol_exists("asm_call_on_stack"))
|
||||
+ machdep->machspec->irq_eframe_link = -64;
|
||||
+ else
|
||||
+ machdep->machspec->irq_eframe_link = -32;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (THIS_KERNEL_VERSION < LINUX(2,6,9))
|
||||
return;
|
||||
|
||||
--
|
||||
2.37.1
|
||||
|
143
0030-Fix-kmem-s-S-not-working-properly-on-RHEL8.6-and-lat.patch
Normal file
143
0030-Fix-kmem-s-S-not-working-properly-on-RHEL8.6-and-lat.patch
Normal file
@ -0,0 +1,143 @@
|
||||
From 9253b40a0ecb2d365f89f0a5ebc28a01735c1d24 Mon Sep 17 00:00:00 2001
|
||||
From: "Aureau, Georges (Kernel Tools ERT)" <georges.aureau@hpe.com>
|
||||
Date: Wed, 8 Feb 2023 12:09:03 +0000
|
||||
Subject: [PATCH 02/12] Fix "kmem -s|-S" not working properly on RHEL8.6 and
|
||||
later
|
||||
|
||||
For CONFIG_SLAB_FREELIST_HARDENED, the crash memory.c:freelist_ptr()
|
||||
code is checking for an additional bswap using a simple release test eg.
|
||||
THIS_KERNEL_VERSION >= LINUX(5,7,0), basically checking for RHEL9 and
|
||||
beyond.
|
||||
|
||||
However, for RHEL8.6 and later, we have CONFIG_SLAB_FREELIST_HARDENED=y,
|
||||
and we also have the additional bswap, but the current crash is not
|
||||
handling this case, hence "kmem -s|-S" will not work properly, and free
|
||||
objects will not be counted nor reported properly.
|
||||
|
||||
An example from a RHEL8.6 x86_64 kdump, a kmem cache with a single slab
|
||||
having 42 objects, only the freelist head is seen as free as crash can't
|
||||
walk freelist next pointers, and crash is wrongly reporting 41 allocated
|
||||
objects:
|
||||
|
||||
crash> sys | grep RELEASE
|
||||
RELEASE: 4.18.0-372.9.1.el8.x86_64
|
||||
crash> kmem -s nfs_commit_data
|
||||
CACHE OBJSIZE ALLOCATED TOTAL SLABS SSIZE NAME
|
||||
ffff9ad40c7cb2c0 728 41 42 1 32k nfs_commit_data
|
||||
|
||||
When properly accounting for the additional bswap, we can walk the
|
||||
freelist and find 38 free objects, and crash is now reporting only 4
|
||||
allocated objects:
|
||||
|
||||
crash> kmem -s nfs_commit_data
|
||||
CACHE OBJSIZE ALLOCATED TOTAL SLABS SSIZE NAME
|
||||
ffff9ad40c7cb2c0 728 4 42 1 32k nfs_commit_data
|
||||
|
||||
Signed-off-by: Georges Aureau <georges.aureau@hpe.com>
|
||||
---
|
||||
defs.h | 1 +
|
||||
memory.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 49 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/defs.h b/defs.h
|
||||
index 33a823b7b67c..56d6cf4489c9 100644
|
||||
--- a/defs.h
|
||||
+++ b/defs.h
|
||||
@@ -2638,6 +2638,7 @@ struct vm_table { /* kernel VM-related data */
|
||||
#define SLAB_OVERLOAD_PAGE (0x8000000)
|
||||
#define SLAB_CPU_CACHE (0x10000000)
|
||||
#define SLAB_ROOT_CACHES (0x20000000)
|
||||
+#define FREELIST_PTR_BSWAP (0x40000000)
|
||||
|
||||
#define IS_FLATMEM() (vt->flags & FLATMEM)
|
||||
#define IS_DISCONTIGMEM() (vt->flags & DISCONTIGMEM)
|
||||
diff --git a/memory.c b/memory.c
|
||||
index 5141fbea4b40..e0742c1bd3a4 100644
|
||||
--- a/memory.c
|
||||
+++ b/memory.c
|
||||
@@ -320,6 +320,7 @@ static void dump_per_cpu_offsets(void);
|
||||
static void dump_page_flags(ulonglong);
|
||||
static ulong kmem_cache_nodelists(ulong);
|
||||
static void dump_hstates(void);
|
||||
+static void freelist_ptr_init(void);
|
||||
static ulong freelist_ptr(struct meminfo *, ulong, ulong);
|
||||
static ulong handle_each_vm_area(struct handle_each_vm_area_args *);
|
||||
|
||||
@@ -789,6 +790,8 @@ vm_init(void)
|
||||
MEMBER_OFFSET_INIT(kmem_cache_name, "kmem_cache", "name");
|
||||
MEMBER_OFFSET_INIT(kmem_cache_flags, "kmem_cache", "flags");
|
||||
MEMBER_OFFSET_INIT(kmem_cache_random, "kmem_cache", "random");
|
||||
+ if (VALID_MEMBER(kmem_cache_random))
|
||||
+ freelist_ptr_init();
|
||||
MEMBER_OFFSET_INIT(kmem_cache_cpu_freelist, "kmem_cache_cpu", "freelist");
|
||||
MEMBER_OFFSET_INIT(kmem_cache_cpu_page, "kmem_cache_cpu", "page");
|
||||
if (INVALID_MEMBER(kmem_cache_cpu_page))
|
||||
@@ -13932,6 +13935,8 @@ dump_vm_table(int verbose)
|
||||
fprintf(fp, "%sSLAB_CPU_CACHE", others++ ? "|" : "");\
|
||||
if (vt->flags & SLAB_ROOT_CACHES)
|
||||
fprintf(fp, "%sSLAB_ROOT_CACHES", others++ ? "|" : "");\
|
||||
+ if (vt->flags & FREELIST_PTR_BSWAP)
|
||||
+ fprintf(fp, "%sFREELIST_PTR_BSWAP", others++ ? "|" : "");\
|
||||
if (vt->flags & USE_VMAP_AREA)
|
||||
fprintf(fp, "%sUSE_VMAP_AREA", others++ ? "|" : "");\
|
||||
if (vt->flags & CONFIG_NUMA)
|
||||
@@ -19519,13 +19524,55 @@ count_free_objects(struct meminfo *si, ulong freelist)
|
||||
return c;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * With CONFIG_SLAB_FREELIST_HARDENED, freelist_ptr's are crypted with xor's,
|
||||
+ * and for recent release with an additionnal bswap. Some releases prio to 5.7.0
|
||||
+ * may be using the additionnal bswap. The only easy and reliable way to tell is
|
||||
+ * to inspect assembly code (eg. "__slab_free") for a bswap instruction.
|
||||
+ */
|
||||
+static int
|
||||
+freelist_ptr_bswap_x86(void)
|
||||
+{
|
||||
+ char buf1[BUFSIZE];
|
||||
+ char buf2[BUFSIZE];
|
||||
+ char *arglist[MAXARGS];
|
||||
+ int found;
|
||||
+
|
||||
+ sprintf(buf1, "disassemble __slab_free");
|
||||
+ open_tmpfile();
|
||||
+ if (!gdb_pass_through(buf1, pc->tmpfile, GNU_RETURN_ON_ERROR)) {
|
||||
+ close_tmpfile();
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ rewind(pc->tmpfile);
|
||||
+ found = FALSE;
|
||||
+ while (fgets(buf2, BUFSIZE, pc->tmpfile)) {
|
||||
+ if (parse_line(buf2, arglist) < 3)
|
||||
+ continue;
|
||||
+ if (STREQ(arglist[2], "bswap")) {
|
||||
+ found = TRUE;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ close_tmpfile();
|
||||
+ return found;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+freelist_ptr_init(void)
|
||||
+{
|
||||
+ if (THIS_KERNEL_VERSION >= LINUX(5,7,0) ||
|
||||
+ ((machine_type("X86_64") || machine_type("X86")) && freelist_ptr_bswap_x86()))
|
||||
+ vt->flags |= FREELIST_PTR_BSWAP;
|
||||
+}
|
||||
+
|
||||
static ulong
|
||||
freelist_ptr(struct meminfo *si, ulong ptr, ulong ptr_addr)
|
||||
{
|
||||
if (VALID_MEMBER(kmem_cache_random)) {
|
||||
/* CONFIG_SLAB_FREELIST_HARDENED */
|
||||
|
||||
- if (THIS_KERNEL_VERSION >= LINUX(5,7,0))
|
||||
+ if (vt->flags & FREELIST_PTR_BSWAP)
|
||||
ptr_addr = (sizeof(long) == 8) ? bswap_64(ptr_addr)
|
||||
: bswap_32(ptr_addr);
|
||||
return (ptr ^ si->random ^ ptr_addr);
|
||||
--
|
||||
2.37.1
|
||||
|
106
0031-Fix-for-net-s-option-to-show-IPv6-addresses-on-Linux.patch
Normal file
106
0031-Fix-for-net-s-option-to-show-IPv6-addresses-on-Linux.patch
Normal file
@ -0,0 +1,106 @@
|
||||
From c64a827e0bcab15e86f8fbacec141c2bf4b776ea Mon Sep 17 00:00:00 2001
|
||||
From: Lianbo Jiang <lijiang@redhat.com>
|
||||
Date: Thu, 9 Feb 2023 20:15:46 +0800
|
||||
Subject: [PATCH 03/12] Fix for "net -s" option to show IPv6 addresses on Linux
|
||||
3.13 and later
|
||||
|
||||
Currently, the "net -s" option fails to show IPv6 addresses and ports
|
||||
for the SOURCE-PORT and DESTINATION-PORT columns on Linux 3.13 and later
|
||||
kernels, which have kernel commit efe4208f47f907 ("ipv6: make lookups
|
||||
simpler and faster"). For example:
|
||||
|
||||
crash> net -s
|
||||
PID: 305524 TASK: ffff9bc449895580 CPU: 6 COMMAND: "sshd"
|
||||
FD SOCKET SOCK FAMILY:TYPE SOURCE-PORT DESTINATION-PORT
|
||||
3 ffff9bc446e9a680 ffff9bc4455b5940 UNIX:DGRAM
|
||||
4 ffff9bc446e9c600 ffff9bc3b2b24e00 INET6:STREAM
|
||||
|
||||
With the patch:
|
||||
|
||||
crash> net -s
|
||||
PID: 305524 TASK: ffff9bc449895580 CPU: 6 COMMAND: "sshd"
|
||||
FD SOCKET SOCK FAMILY:TYPE SOURCE-PORT DESTINATION-PORT
|
||||
3 ffff9bc446e9a680 ffff9bc4455b5940 UNIX:DGRAM
|
||||
4 ffff9bc446e9c600 ffff9bc3b2b24e00 INET6:STREAM xxxx:xx:x:xxxx:xxxx:xxxx:xxxx:xxxx-22 yyyy:yy:y:yyyy:yyyy:yyyy:yyyy:yyyy-44870
|
||||
|
||||
Reported-by: Buland Kumar Singh <bsingh@redhat.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
|
||||
---
|
||||
defs.h | 3 +++
|
||||
net.c | 20 +++++++++++++++-----
|
||||
symbols.c | 3 +++
|
||||
3 files changed, 21 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/defs.h b/defs.h
|
||||
index 56d6cf4489c9..ab4f02cc65cf 100644
|
||||
--- a/defs.h
|
||||
+++ b/defs.h
|
||||
@@ -2204,6 +2204,9 @@ struct offset_table { /* stash of commonly-used offsets */
|
||||
long maple_range_64_slot;
|
||||
long maple_metadata_end;
|
||||
long maple_metadata_gap;
|
||||
+ long sock_sk_common;
|
||||
+ long sock_common_skc_v6_daddr;
|
||||
+ long sock_common_skc_v6_rcv_saddr;
|
||||
};
|
||||
|
||||
struct size_table { /* stash of commonly-used sizes */
|
||||
diff --git a/net.c b/net.c
|
||||
index 7c9c8bd9c98d..aa445ab7ee13 100644
|
||||
--- a/net.c
|
||||
+++ b/net.c
|
||||
@@ -199,6 +199,9 @@ net_init(void)
|
||||
MEMBER_OFFSET_INIT(sock_common_skc_family,
|
||||
"sock_common", "skc_family");
|
||||
MEMBER_OFFSET_INIT(sock_sk_type, "sock", "sk_type");
|
||||
+ MEMBER_OFFSET_INIT(sock_sk_common, "sock", "__sk_common");
|
||||
+ MEMBER_OFFSET_INIT(sock_common_skc_v6_daddr, "sock_common", "skc_v6_daddr");
|
||||
+ MEMBER_OFFSET_INIT(sock_common_skc_v6_rcv_saddr, "sock_common", "skc_v6_rcv_saddr");
|
||||
/*
|
||||
* struct inet_sock {
|
||||
* struct sock sk;
|
||||
@@ -1104,12 +1107,19 @@ get_sock_info(ulong sock, char *buf)
|
||||
break;
|
||||
|
||||
case SOCK_V2:
|
||||
- if (INVALID_MEMBER(ipv6_pinfo_rcv_saddr) ||
|
||||
- INVALID_MEMBER(ipv6_pinfo_daddr))
|
||||
+ if (VALID_MEMBER(ipv6_pinfo_rcv_saddr) &&
|
||||
+ VALID_MEMBER(ipv6_pinfo_daddr)) {
|
||||
+ ipv6_rcv_saddr = ipv6_pinfo + OFFSET(ipv6_pinfo_rcv_saddr);
|
||||
+ ipv6_daddr = ipv6_pinfo + OFFSET(ipv6_pinfo_daddr);
|
||||
+ } else if (VALID_MEMBER(sock_sk_common) &&
|
||||
+ VALID_MEMBER(sock_common_skc_v6_daddr) &&
|
||||
+ VALID_MEMBER(sock_common_skc_v6_rcv_saddr)) {
|
||||
+ ipv6_rcv_saddr = sock + OFFSET(sock_sk_common) + OFFSET(sock_common_skc_v6_rcv_saddr);
|
||||
+ ipv6_daddr = sock + OFFSET(sock_sk_common) + OFFSET(sock_common_skc_v6_daddr);
|
||||
+ } else {
|
||||
+ sprintf(&buf[strlen(buf)], "%s", "(cannot get IPv6 addresses)");
|
||||
break;
|
||||
-
|
||||
- ipv6_rcv_saddr = ipv6_pinfo + OFFSET(ipv6_pinfo_rcv_saddr);
|
||||
- ipv6_daddr = ipv6_pinfo + OFFSET(ipv6_pinfo_daddr);
|
||||
+ }
|
||||
|
||||
if (!readmem(ipv6_rcv_saddr, KVADDR, u6_addr16_src, SIZE(in6_addr),
|
||||
"ipv6_rcv_saddr buffer", QUIET|RETURN_ON_ERROR))
|
||||
diff --git a/symbols.c b/symbols.c
|
||||
index e38df8aad0f5..b702b9665ec1 100644
|
||||
--- a/symbols.c
|
||||
+++ b/symbols.c
|
||||
@@ -9818,8 +9818,11 @@ dump_offset_table(char *spec, ulong makestruct)
|
||||
|
||||
fprintf(fp, " sock_sk_type: %ld\n",
|
||||
OFFSET(sock_sk_type));
|
||||
+ fprintf(fp, " sock_sk_common: %ld\n", OFFSET(sock_sk_common));
|
||||
fprintf(fp, " sock_common_skc_family: %ld\n",
|
||||
OFFSET(sock_common_skc_family));
|
||||
+ fprintf(fp, " sock_common_skc_v6_daddr: %ld\n", OFFSET(sock_common_skc_v6_daddr));
|
||||
+ fprintf(fp, " sock_common_skc_v6_rcv_saddr: %ld\n", OFFSET(sock_common_skc_v6_rcv_saddr));
|
||||
fprintf(fp, " socket_alloc_vfs_inode: %ld\n",
|
||||
OFFSET(socket_alloc_vfs_inode));
|
||||
fprintf(fp, " inet_sock_inet: %ld\n",
|
||||
--
|
||||
2.37.1
|
||||
|
@ -0,0 +1,56 @@
|
||||
From 277da34dd5da8c1280d0d0fd7ce50499b31c3a58 Mon Sep 17 00:00:00 2001
|
||||
From: Lianbo Jiang <lijiang@redhat.com>
|
||||
Date: Tue, 14 Feb 2023 22:37:08 +0800
|
||||
Subject: [PATCH 04/12] Fix for "kmem -i" option to not print invalid values
|
||||
for CACHED
|
||||
|
||||
The "kmem -i" option may output a bogus statistics for CACHED, which
|
||||
might be observed when some extreme situations occur in kernel, such as
|
||||
OOM, disk IO errors, etc.
|
||||
|
||||
The following result of calculation may be a negative value, refer to
|
||||
the dump_kmeminfo():
|
||||
page_cache_size = nr_file_pages - swapper_space_nrpages - buffer_pages;
|
||||
|
||||
As a result, the negative value will be converted to unsigned long
|
||||
integer, eventually it overflows and is printed as big integers.
|
||||
|
||||
crash> kmem -i
|
||||
PAGES TOTAL PERCENTAGE
|
||||
TOTAL MEM 255314511 973.9 GB ----
|
||||
FREE 533574 2 GB 0% of TOTAL MEM
|
||||
USED 254780937 971.9 GB 99% of TOTAL MEM
|
||||
SHARED 1713 6.7 MB 0% of TOTAL MEM
|
||||
BUFFERS 374 1.5 MB 0% of TOTAL MEM
|
||||
CACHED -114 70368744177664 GB 72251060080% of TOTAL MEM
|
||||
^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^
|
||||
...
|
||||
|
||||
Let's normalize it to zero with an info message to fix such cornor cases.
|
||||
|
||||
Reported-by: Buland Kumar Singh <bsingh@redhat.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
|
||||
---
|
||||
memory.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/memory.c b/memory.c
|
||||
index e0742c1bd3a4..d9cd616f19de 100644
|
||||
--- a/memory.c
|
||||
+++ b/memory.c
|
||||
@@ -8615,6 +8615,11 @@ dump_kmeminfo(void)
|
||||
page_cache_size = 0;
|
||||
|
||||
|
||||
+ if (page_cache_size < 0) {
|
||||
+ error(INFO, "page_cache_size went negative (%ld), setting to 0\n",
|
||||
+ page_cache_size);
|
||||
+ page_cache_size = 0;
|
||||
+ }
|
||||
pct = (page_cache_size * 100)/totalram_pages;
|
||||
fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL MEM\n",
|
||||
"CACHED", page_cache_size,
|
||||
--
|
||||
2.37.1
|
||||
|
@ -0,0 +1,77 @@
|
||||
From e0e6e4a7ee03b3d00b50a9e4db2f2ea6f7da0da3 Mon Sep 17 00:00:00 2001
|
||||
From: Lianbo Jiang <lijiang@redhat.com>
|
||||
Date: Wed, 15 Feb 2023 16:24:57 +0800
|
||||
Subject: [PATCH 05/12] Fix for "bt" command unnecessarily printing an
|
||||
exception frame
|
||||
|
||||
Kernel commit 7d65f4a65532 ("irq: Consolidate do_softirq() arch overriden
|
||||
implementations") renamed the call_softirq to do_softirq_own_stack, and
|
||||
there is no exception frame also when coming from do_softirq_own_stack.
|
||||
Without the patch, crash may unnecessarily output an exception frame with
|
||||
a warning as below:
|
||||
|
||||
crash> foreach bt
|
||||
...
|
||||
PID: 0 TASK: ffff914f820a8000 CPU: 25 COMMAND: "swapper/25"
|
||||
#0 [fffffe0000504e48] crash_nmi_callback at ffffffffa665d763
|
||||
#1 [fffffe0000504e50] nmi_handle at ffffffffa662a423
|
||||
#2 [fffffe0000504ea8] default_do_nmi at ffffffffa6fe7dc9
|
||||
#3 [fffffe0000504ec8] do_nmi at ffffffffa662a97f
|
||||
#4 [fffffe0000504ef0] end_repeat_nmi at ffffffffa70015e8
|
||||
[exception RIP: clone_endio+172]
|
||||
RIP: ffffffffc005c1ec RSP: ffffa1d403d08e98 RFLAGS: 00000246
|
||||
RAX: 0000000000000000 RBX: ffff915326fba230 RCX: 0000000000000018
|
||||
RDX: ffffffffc0075400 RSI: 0000000000000000 RDI: ffff915326fba230
|
||||
RBP: ffff915326fba1c0 R8: 0000000000001000 R9: ffff915308d6d2a0
|
||||
R10: 000000a97dfe5e10 R11: ffffa1d40038fe98 R12: ffff915302babc40
|
||||
R13: ffff914f94360000 R14: 0000000000000000 R15: 0000000000000000
|
||||
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
|
||||
--- <NMI exception stack> ---
|
||||
#5 [ffffa1d403d08e98] clone_endio at ffffffffc005c1ec [dm_mod]
|
||||
#6 [ffffa1d403d08ed0] blk_update_request at ffffffffa6a96954
|
||||
#7 [ffffa1d403d08f10] scsi_end_request at ffffffffa6c9b968
|
||||
#8 [ffffa1d403d08f48] scsi_io_completion at ffffffffa6c9bb3e
|
||||
#9 [ffffa1d403d08f90] blk_complete_reqs at ffffffffa6aa0e95
|
||||
#10 [ffffa1d403d08fa0] __softirqentry_text_start at ffffffffa72000dc
|
||||
#11 [ffffa1d403d08ff0] do_softirq_own_stack at ffffffffa7000f9a
|
||||
--- <IRQ stack> ---
|
||||
#12 [ffffa1d40038fe70] do_softirq_own_stack at ffffffffa7000f9a
|
||||
[exception RIP: unknown or invalid address]
|
||||
RIP: 0000000000000000 RSP: 0000000000000000 RFLAGS: 00000000
|
||||
RAX: ffffffffa672eae5 RBX: ffffffffa83b34e0 RCX: ffffffffa672eb12
|
||||
RDX: 0000000000000010 RSI: 8b7d6c8869010c00 RDI: 0000000000000085
|
||||
RBP: 0000000000000286 R8: ffff914f820a8000 R9: ffffffffa67a94e0
|
||||
R10: 0000000000000286 R11: ffffffffa66fb4c5 R12: ffffffffa67a898b
|
||||
R13: 0000000000000000 R14: fffffffffffffff8 R15: ffffffffa67a1e68
|
||||
ORIG_RAX: 0000000000000000 CS: 0000 SS: ffffffffa672edff
|
||||
bt: WARNING: possibly bogus exception frame
|
||||
#13 [ffffa1d40038ff30] start_secondary at ffffffffa665fa2c
|
||||
#14 [ffffa1d40038ff50] secondary_startup_64_no_verify at ffffffffa6600116
|
||||
...
|
||||
|
||||
Reported-by: Marco Patalano <mpatalan@redhat.com>
|
||||
---
|
||||
x86_64.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/x86_64.c b/x86_64.c
|
||||
index 5b671bd97775..6cac3936b33d 100644
|
||||
--- a/x86_64.c
|
||||
+++ b/x86_64.c
|
||||
@@ -3825,10 +3825,11 @@ in_exception_stack:
|
||||
up -= 1;
|
||||
bt->instptr = *up;
|
||||
/*
|
||||
- * No exception frame when coming from call_softirq.
|
||||
+ * No exception frame when coming from do_softirq_own_stack
|
||||
+ * or call_softirq.
|
||||
*/
|
||||
if ((sp = value_search(bt->instptr, &offset)) &&
|
||||
- STREQ(sp->name, "call_softirq"))
|
||||
+ (STREQ(sp->name, "do_softirq_own_stack") || STREQ(sp->name, "call_softirq")))
|
||||
irq_eframe = 0;
|
||||
bt->frameptr = 0;
|
||||
done = FALSE;
|
||||
--
|
||||
2.37.1
|
||||
|
@ -0,0 +1,62 @@
|
||||
From 59c19818190dd4b7ae0dc2221586a4ad6f4fe905 Mon Sep 17 00:00:00 2001
|
||||
From: Lianbo Jiang <lijiang@redhat.com>
|
||||
Date: Tue, 21 Feb 2023 11:03:26 +0800
|
||||
Subject: [PATCH 06/12] Fix for "dis" command to correctly display the offset
|
||||
of disassembly code
|
||||
|
||||
For gdb-10.2, the disassembly code may start with "=>", which needs to
|
||||
be stripped when calculating the address. Otherwise, parsing the address
|
||||
will fail because the current code always assumes that it starts with the
|
||||
"0x". For example:
|
||||
|
||||
crash> gdb disassemble 0xffffffffa2317add
|
||||
Dump of assembler code for function native_queued_spin_lock_slowpath:
|
||||
...
|
||||
0xffffffffa2317ad3 <+35>: mov %edx,%eax
|
||||
0xffffffffa2317ad5 <+37>: lock cmpxchg %ecx,(%rdi)
|
||||
=> 0xffffffffa2317ad9 <+41>: cmp %eax,%edx
|
||||
0xffffffffa2317adb <+43>: jne 0xffffffffa2317ac0 ...
|
||||
0xffffffffa2317add <+45>: pop %rbp
|
||||
...
|
||||
|
||||
Without the patch:
|
||||
crash> dis 0xffffffffa2317add -r | tail -5
|
||||
0xffffffffa2317ad3 <native_queued_spin_lock_slowpath+35>: mov %edx,%eax
|
||||
0xffffffffa2317ad5 <native_queued_spin_lock_slowpath+37>: lock cmpxchg %ecx,(%rdi)
|
||||
0xffffffffa2317ad5 <native_queued_spin_lock_slowpath+37>: cmp %eax,%edx
|
||||
^^
|
||||
0xffffffffa2317adb <native_queued_spin_lock_slowpath+43>: jne 0xffffffffa2317ac0 ...
|
||||
0xffffffffa2317add <native_queued_spin_lock_slowpath+45>: pop %rbp
|
||||
|
||||
With the patch:
|
||||
|
||||
crash> dis 0xffffffffa2317add -r | tail -5
|
||||
0xffffffffa2317ad3 <native_queued_spin_lock_slowpath+35>: mov %edx,%eax
|
||||
0xffffffffa2317ad5 <native_queued_spin_lock_slowpath+37>: lock cmpxchg %ecx,(%rdi)
|
||||
0xffffffffa2317ad9 <native_queued_spin_lock_slowpath+41>: cmp %eax,%edx
|
||||
0xffffffffa2317adb <native_queued_spin_lock_slowpath+43>: jne 0xffffffffa2317ac0 ...
|
||||
0xffffffffa2317add <native_queued_spin_lock_slowpath+45>: pop %rbp
|
||||
|
||||
Reported-by: Vernon Lovejoy <vlovejoy@redhat.com>
|
||||
---
|
||||
kernel.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/kernel.c b/kernel.c
|
||||
index a42e6ad7d78c..6e98f5f6f6b1 100644
|
||||
--- a/kernel.c
|
||||
+++ b/kernel.c
|
||||
@@ -2112,6 +2112,10 @@ cmd_dis(void)
|
||||
rewind(pc->tmpfile);
|
||||
|
||||
while (fgets(buf2, BUFSIZE, pc->tmpfile)) {
|
||||
+
|
||||
+ if (STRNEQ(buf2, "=>"))
|
||||
+ shift_string_left(buf2, 2);
|
||||
+
|
||||
strip_beginning_whitespace(buf2);
|
||||
|
||||
if (do_load_module_filter)
|
||||
--
|
||||
2.37.1
|
||||
|
299
0035-x86_64-Fix-bt-command-on-kernels-with-random_kstack_.patch
Normal file
299
0035-x86_64-Fix-bt-command-on-kernels-with-random_kstack_.patch
Normal file
@ -0,0 +1,299 @@
|
||||
From daa43fa5324f2dd232ad72df2c6554646868f3b2 Mon Sep 17 00:00:00 2001
|
||||
From: Kazuhito Hagio <k-hagio-ab@nec.com>
|
||||
Date: Mon, 20 Feb 2023 10:28:53 +0900
|
||||
Subject: [PATCH 07/12] x86_64: Fix "bt" command on kernels with
|
||||
random_kstack_offset=on
|
||||
|
||||
On kernels configured with CONFIG_RANDOMIZE_KSTACK_OFFSET=y and
|
||||
random_kstack_offset=on, a random offset is added to task stacks with
|
||||
__kstack_alloca() at the beginning of do_syscall_64() and other syscall
|
||||
entry functions. This eventually does the following instruction.
|
||||
|
||||
<do_syscall_64+32>: sub %rax,%rsp
|
||||
|
||||
On the other hand, crash uses only a part of data for ORC unwinder to
|
||||
unwind stacks and if an ip value doesn't have a usable ORC data, it
|
||||
caluculates the frame size with parsing the assembly of the function.
|
||||
|
||||
However, crash cannot calculate the frame size correctly with the
|
||||
instruction above, and prints stale return addresses like this:
|
||||
|
||||
crash> bt 1
|
||||
PID: 1 TASK: ffff9c250023b880 CPU: 0 COMMAND: "systemd"
|
||||
#0 [ffffb7e5c001fc80] __schedule at ffffffff91ae2b16
|
||||
#1 [ffffb7e5c001fd00] schedule at ffffffff91ae2ed3
|
||||
#2 [ffffb7e5c001fd18] schedule_hrtimeout_range_clock at ffffffff91ae7ed8
|
||||
#3 [ffffb7e5c001fda8] ep_poll at ffffffff913ef828
|
||||
#4 [ffffb7e5c001fe48] do_epoll_wait at ffffffff913ef943
|
||||
#5 [ffffb7e5c001fe80] __x64_sys_epoll_wait at ffffffff913f0130
|
||||
#6 [ffffb7e5c001fed0] do_syscall_64 at ffffffff91ad7169
|
||||
#7 [ffffb7e5c001fef0] do_syscall_64 at ffffffff91ad7179 <<
|
||||
#8 [ffffb7e5c001ff10] syscall_exit_to_user_mode at ffffffff91adaab2 << stale entries
|
||||
#9 [ffffb7e5c001ff20] do_syscall_64 at ffffffff91ad7179 <<
|
||||
#10 [ffffb7e5c001ff50] entry_SYSCALL_64_after_hwframe at ffffffff91c0009b
|
||||
RIP: 00007f258d9427ae RSP: 00007fffda631d60 RFLAGS: 00000293
|
||||
...
|
||||
|
||||
To fix this, enhance the use of ORC data. The ORC unwinder often uses
|
||||
%rbp value, so keep it from exception frames and inactive task stacks.
|
||||
|
||||
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
|
||||
---
|
||||
defs.h | 1 +
|
||||
symbols.c | 1 +
|
||||
x86_64.c | 118 ++++++++++++++++++++++++++++++++++++++----------------
|
||||
3 files changed, 85 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/defs.h b/defs.h
|
||||
index ab4f02cc65cf..e76af3c78b69 100644
|
||||
--- a/defs.h
|
||||
+++ b/defs.h
|
||||
@@ -2207,6 +2207,7 @@ struct offset_table { /* stash of commonly-used offsets */
|
||||
long sock_sk_common;
|
||||
long sock_common_skc_v6_daddr;
|
||||
long sock_common_skc_v6_rcv_saddr;
|
||||
+ long inactive_task_frame_bp;
|
||||
};
|
||||
|
||||
struct size_table { /* stash of commonly-used sizes */
|
||||
diff --git a/symbols.c b/symbols.c
|
||||
index b702b9665ec1..a974fc9141a0 100644
|
||||
--- a/symbols.c
|
||||
+++ b/symbols.c
|
||||
@@ -8822,6 +8822,7 @@ dump_offset_table(char *spec, ulong makestruct)
|
||||
OFFSET(task_struct_tss_ksp));
|
||||
fprintf(fp, " task_struct_thread_eip: %ld\n",
|
||||
OFFSET(task_struct_thread_eip));
|
||||
+ fprintf(fp, " inactive_task_frame_bp: %ld\n", OFFSET(inactive_task_frame_bp));
|
||||
fprintf(fp, " inactive_task_frame_ret_addr: %ld\n",
|
||||
OFFSET(inactive_task_frame_ret_addr));
|
||||
fprintf(fp, " task_struct_thread_esp: %ld\n",
|
||||
diff --git a/x86_64.c b/x86_64.c
|
||||
index 6cac3936b33d..8e3eb8957af1 100644
|
||||
--- a/x86_64.c
|
||||
+++ b/x86_64.c
|
||||
@@ -122,7 +122,7 @@ static int x86_64_do_not_cache_framesize(struct syment *, ulong);
|
||||
static int x86_64_framesize_cache_func(int, ulong, int *, int, struct syment *);
|
||||
static ulong x86_64_get_framepointer(struct bt_info *, ulong);
|
||||
int search_for_eframe_target_caller(struct bt_info *, ulong, int *);
|
||||
-static int x86_64_get_framesize(struct bt_info *, ulong, ulong);
|
||||
+static int x86_64_get_framesize(struct bt_info *, ulong, ulong, char *);
|
||||
static void x86_64_framesize_debug(struct bt_info *);
|
||||
static void x86_64_get_active_set(void);
|
||||
static int x86_64_get_kvaddr_ranges(struct vaddr_range *);
|
||||
@@ -3642,7 +3642,7 @@ in_exception_stack:
|
||||
bt, ofp);
|
||||
rsp += SIZE(pt_regs); /* guaranteed kernel mode */
|
||||
if (bt->eframe_ip && ((framesize = x86_64_get_framesize(bt,
|
||||
- bt->eframe_ip, rsp)) >= 0))
|
||||
+ bt->eframe_ip, rsp, NULL)) >= 0))
|
||||
rsp += framesize;
|
||||
level++;
|
||||
irq_eframe = 0;
|
||||
@@ -3674,7 +3674,7 @@ in_exception_stack:
|
||||
case BACKTRACE_ENTRY_DISPLAYED:
|
||||
level++;
|
||||
if ((framesize = x86_64_get_framesize(bt,
|
||||
- bt->eframe_ip ? bt->eframe_ip : *up, rsp)) >= 0) {
|
||||
+ bt->eframe_ip ? bt->eframe_ip : *up, rsp, NULL)) >= 0) {
|
||||
rsp += framesize;
|
||||
i += framesize/sizeof(ulong);
|
||||
}
|
||||
@@ -3747,7 +3747,7 @@ in_exception_stack:
|
||||
}
|
||||
|
||||
level++;
|
||||
- if ((framesize = x86_64_get_framesize(bt, bt->instptr, rsp)) >= 0)
|
||||
+ if ((framesize = x86_64_get_framesize(bt, bt->instptr, rsp, NULL)) >= 0)
|
||||
rsp += framesize;
|
||||
}
|
||||
}
|
||||
@@ -3799,7 +3799,7 @@ in_exception_stack:
|
||||
case BACKTRACE_ENTRY_DISPLAYED:
|
||||
level++;
|
||||
if ((framesize = x86_64_get_framesize(bt,
|
||||
- bt->eframe_ip ? bt->eframe_ip : *up, rsp)) >= 0) {
|
||||
+ bt->eframe_ip ? bt->eframe_ip : *up, rsp, NULL)) >= 0) {
|
||||
rsp += framesize;
|
||||
i += framesize/sizeof(ulong);
|
||||
}
|
||||
@@ -3909,24 +3909,34 @@ in_exception_stack:
|
||||
(STREQ(rip_symbol, "thread_return") ||
|
||||
STREQ(rip_symbol, "schedule") ||
|
||||
STREQ(rip_symbol, "__schedule"))) {
|
||||
- if (STREQ(rip_symbol, "__schedule")) {
|
||||
- i = (rsp - bt->stackbase)/sizeof(ulong);
|
||||
- x86_64_print_stack_entry(bt, ofp, level,
|
||||
- i, bt->instptr);
|
||||
- level++;
|
||||
- rsp = __schedule_frame_adjust(rsp, bt);
|
||||
- if (STREQ(closest_symbol(bt->instptr), "schedule"))
|
||||
+ if ((machdep->flags & ORC) && VALID_MEMBER(inactive_task_frame_ret_addr)) {
|
||||
+ /*
|
||||
+ * %rsp should have the address of inactive_task_frame, so
|
||||
+ * skip the registers before ret_addr to adjust rsp.
|
||||
+ */
|
||||
+ if (CRASHDEBUG(1))
|
||||
+ fprintf(fp, "rsp: %lx rbp: %lx\n", rsp, bt->bptr);
|
||||
+ rsp += OFFSET(inactive_task_frame_ret_addr);
|
||||
+ } else {
|
||||
+ if (STREQ(rip_symbol, "__schedule")) {
|
||||
+ i = (rsp - bt->stackbase)/sizeof(ulong);
|
||||
+ x86_64_print_stack_entry(bt, ofp, level,
|
||||
+ i, bt->instptr);
|
||||
+ level++;
|
||||
+ rsp = __schedule_frame_adjust(rsp, bt);
|
||||
+ if (STREQ(closest_symbol(bt->instptr), "schedule"))
|
||||
+ bt->flags |= BT_SCHEDULE;
|
||||
+ } else
|
||||
bt->flags |= BT_SCHEDULE;
|
||||
- } else
|
||||
- bt->flags |= BT_SCHEDULE;
|
||||
-
|
||||
- if (bt->flags & BT_SCHEDULE) {
|
||||
- i = (rsp - bt->stackbase)/sizeof(ulong);
|
||||
- x86_64_print_stack_entry(bt, ofp, level,
|
||||
- i, bt->instptr);
|
||||
- bt->flags &= ~(ulonglong)BT_SCHEDULE;
|
||||
- rsp += sizeof(ulong);
|
||||
- level++;
|
||||
+
|
||||
+ if (bt->flags & BT_SCHEDULE) {
|
||||
+ i = (rsp - bt->stackbase)/sizeof(ulong);
|
||||
+ x86_64_print_stack_entry(bt, ofp, level,
|
||||
+ i, bt->instptr);
|
||||
+ bt->flags &= ~(ulonglong)BT_SCHEDULE;
|
||||
+ rsp += sizeof(ulong);
|
||||
+ level++;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3957,7 +3967,7 @@ in_exception_stack:
|
||||
irq_eframe = 0;
|
||||
bt->flags |= BT_EFRAME_TARGET;
|
||||
if (bt->eframe_ip && ((framesize = x86_64_get_framesize(bt,
|
||||
- bt->eframe_ip, rsp)) >= 0))
|
||||
+ bt->eframe_ip, rsp, NULL)) >= 0))
|
||||
rsp += framesize;
|
||||
bt->flags &= ~BT_EFRAME_TARGET;
|
||||
}
|
||||
@@ -4044,7 +4054,7 @@ in_exception_stack:
|
||||
case BACKTRACE_ENTRY_DISPLAYED:
|
||||
level++;
|
||||
if ((framesize = x86_64_get_framesize(bt,
|
||||
- bt->eframe_ip ? bt->eframe_ip : *up, rsp)) >= 0) {
|
||||
+ bt->eframe_ip ? bt->eframe_ip : *up, rsp, (char *)up)) >= 0) {
|
||||
rsp += framesize;
|
||||
i += framesize/sizeof(ulong);
|
||||
}
|
||||
@@ -4755,7 +4765,8 @@ x86_64_exception_frame(ulong flags, ulong kvaddr, char *local,
|
||||
bt->instptr = rip;
|
||||
bt->stkptr = rsp;
|
||||
bt->bptr = rbp;
|
||||
- }
|
||||
+ } else if (machdep->flags & ORC)
|
||||
+ bt->bptr = rbp;
|
||||
|
||||
if (kvaddr)
|
||||
FREEBUF(pt_regs_buf);
|
||||
@@ -5315,6 +5326,10 @@ x86_64_get_sp(struct bt_info *bt)
|
||||
OFFSET(thread_struct_rsp), KVADDR,
|
||||
&rsp, sizeof(void *),
|
||||
"thread_struct rsp", FAULT_ON_ERROR);
|
||||
+ if ((machdep->flags & ORC) && VALID_MEMBER(inactive_task_frame_bp)) {
|
||||
+ readmem(rsp + OFFSET(inactive_task_frame_bp), KVADDR, &bt->bptr,
|
||||
+ sizeof(void *), "inactive_task_frame.bp", FAULT_ON_ERROR);
|
||||
+ }
|
||||
return rsp;
|
||||
}
|
||||
|
||||
@@ -6421,6 +6436,9 @@ x86_64_ORC_init(void)
|
||||
orc->__stop_orc_unwind = symbol_value("__stop_orc_unwind");
|
||||
orc->orc_lookup = symbol_value("orc_lookup");
|
||||
|
||||
+ MEMBER_OFFSET_INIT(inactive_task_frame_bp, "inactive_task_frame", "bp");
|
||||
+ MEMBER_OFFSET_INIT(inactive_task_frame_ret_addr, "inactive_task_frame", "ret_addr");
|
||||
+
|
||||
machdep->flags |= ORC;
|
||||
}
|
||||
|
||||
@@ -8489,7 +8507,7 @@ search_for_eframe_target_caller(struct bt_info *bt, ulong stkptr, int *framesize
|
||||
(BT_OLD_BACK_TRACE|BT_TEXT_SYMBOLS|BT_TEXT_SYMBOLS_ALL|BT_FRAMESIZE_DISABLE)
|
||||
|
||||
static int
|
||||
-x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp)
|
||||
+x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp, char *stack_ptr)
|
||||
{
|
||||
int c, framesize, instr, arg, max;
|
||||
struct syment *sp;
|
||||
@@ -8590,19 +8608,49 @@ x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp)
|
||||
if ((machdep->flags & ORC) && (korc = orc_find(textaddr))) {
|
||||
if (CRASHDEBUG(1)) {
|
||||
fprintf(fp,
|
||||
- "rsp: %lx textaddr: %lx framesize: %d -> spo: %d bpo: %d spr: %d bpr: %d type: %d %s",
|
||||
- rsp, textaddr, framesize, korc->sp_offset, korc->bp_offset,
|
||||
- korc->sp_reg, korc->bp_reg, korc->type,
|
||||
- (korc->type == ORC_TYPE_CALL) && (korc->sp_reg == ORC_REG_SP) ? "" : "(UNUSED)");
|
||||
+ "rsp: %lx textaddr: %lx -> spo: %d bpo: %d spr: %d bpr: %d type: %d",
|
||||
+ rsp, textaddr, korc->sp_offset, korc->bp_offset,
|
||||
+ korc->sp_reg, korc->bp_reg, korc->type);
|
||||
if (MEMBER_EXISTS("orc_entry", "end"))
|
||||
fprintf(fp, " end: %d", korc->end);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
- if ((korc->type == ORC_TYPE_CALL) && (korc->sp_reg == ORC_REG_SP)) {
|
||||
- framesize = (korc->sp_offset - 8);
|
||||
- return (x86_64_framesize_cache_func(FRAMESIZE_ENTER, textaddr,
|
||||
- &framesize, exception, NULL));
|
||||
+ if (korc->type == ORC_TYPE_CALL) {
|
||||
+ ulong prev_sp = 0, prev_bp = 0;
|
||||
+ framesize = -1;
|
||||
+
|
||||
+ if (korc->sp_reg == ORC_REG_SP) {
|
||||
+ framesize = (korc->sp_offset - 8);
|
||||
+
|
||||
+ /* rsp points to a return address, so +8 to use sp_offset */
|
||||
+ prev_sp = (rsp + 8) + korc->sp_offset;
|
||||
+ if (CRASHDEBUG(1))
|
||||
+ fprintf(fp, "rsp: %lx prev_sp: %lx framesize: %d\n",
|
||||
+ rsp, prev_sp, framesize);
|
||||
+ } else if ((korc->sp_reg == ORC_REG_BP) && bt->bptr) {
|
||||
+ prev_sp = bt->bptr + korc->sp_offset;
|
||||
+ framesize = (prev_sp - (rsp + 8) - 8);
|
||||
+ if (CRASHDEBUG(1))
|
||||
+ fprintf(fp, "rsp: %lx rbp: %lx prev_sp: %lx framesize: %d\n",
|
||||
+ rsp, bt->bptr, prev_sp, framesize);
|
||||
+ }
|
||||
+
|
||||
+ if ((korc->bp_reg == ORC_REG_PREV_SP) && prev_sp) {
|
||||
+ prev_bp = prev_sp + korc->bp_offset;
|
||||
+ if (stack_ptr && INSTACK(prev_bp, bt)) {
|
||||
+ bt->bptr = ULONG(stack_ptr + (prev_bp - rsp));
|
||||
+ if (CRASHDEBUG(1))
|
||||
+ fprintf(fp, "rsp: %lx prev_sp: %lx prev_bp: %lx -> %lx\n",
|
||||
+ rsp, prev_sp, prev_bp, bt->bptr);
|
||||
+ } else
|
||||
+ bt->bptr = 0;
|
||||
+ } else if ((korc->bp_reg != ORC_REG_UNDEFINED))
|
||||
+ bt->bptr = 0;
|
||||
+
|
||||
+ if (framesize >= 0)
|
||||
+ /* Do not cache this, possibly it may be variable. */
|
||||
+ return framesize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8758,7 +8806,7 @@ x86_64_framesize_debug(struct bt_info *bt)
|
||||
if (!bt->hp->eip)
|
||||
error(INFO, "x86_64_framesize_debug: ignoring command\n");
|
||||
else
|
||||
- x86_64_get_framesize(bt, bt->hp->eip, 0);
|
||||
+ x86_64_get_framesize(bt, bt->hp->eip, 0, NULL);
|
||||
break;
|
||||
|
||||
case -3:
|
||||
--
|
||||
2.37.1
|
||||
|
168
0036-Fix-for-search-u-option-failing-in-maple-tree-kernel.patch
Normal file
168
0036-Fix-for-search-u-option-failing-in-maple-tree-kernel.patch
Normal file
@ -0,0 +1,168 @@
|
||||
From d0d6cf868577fdca81c40633fa082dae1794294f Mon Sep 17 00:00:00 2001
|
||||
From: Tao Liu <ltao@redhat.com>
|
||||
Date: Wed, 22 Feb 2023 14:32:09 +0800
|
||||
Subject: [PATCH 08/12] Fix for "search -u" option failing in maple tree kernel
|
||||
|
||||
Kernel with maple tree enabled doesn't have mmap as a member of mm_struct[1],
|
||||
so OFFSET(mm_struct_mmap) case needed to be handled differently for
|
||||
maple tree kernel.
|
||||
|
||||
Before:
|
||||
crash> search -u a
|
||||
|
||||
search: invalid structure member offset: mm_struct_mmap
|
||||
FILE: memory.c LINE: 14255 FUNCTION: address_space_start()
|
||||
|
||||
[crash] error trace: 549500 => 548fff => 5f1c91 => 5f1c13
|
||||
|
||||
5f1c13: OFFSET_verify.part.36+51
|
||||
5f1c91: OFFSET_verify+49
|
||||
548fff: address_space_start+106
|
||||
549500: cmd_search+855
|
||||
|
||||
search: invalid structure member offset: mm_struct_mmap
|
||||
FILE: memory.c LINE: 14255 FUNCTION: address_space_start()
|
||||
|
||||
After:
|
||||
crash> search -u a
|
||||
7ffea63e6440: a
|
||||
|
||||
[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=763ecb035029f500d7e6dc99acd1ad299b7726a1
|
||||
|
||||
Signed-off-by: Tao Liu <ltao@redhat.com>
|
||||
---
|
||||
memory.c | 89 +++++++++++++++++++++++++++++++++++++++++---------------
|
||||
1 file changed, 65 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/memory.c b/memory.c
|
||||
index d9cd616f19de..c4a6ecd18004 100644
|
||||
--- a/memory.c
|
||||
+++ b/memory.c
|
||||
@@ -14245,14 +14245,28 @@ vaddr_type(ulong vaddr, struct task_context *tc)
|
||||
static int
|
||||
address_space_start(struct task_context *tc, ulong *addr)
|
||||
{
|
||||
- ulong vma;
|
||||
+ ulong mm_mt, entry_num, i, vma = 0;
|
||||
char *vma_buf;
|
||||
+ struct list_pair *entry_list;
|
||||
|
||||
if (!tc->mm_struct)
|
||||
return FALSE;
|
||||
|
||||
- fill_mm_struct(tc->mm_struct);
|
||||
- vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap));
|
||||
+ if (INVALID_MEMBER(mm_struct_mmap) && VALID_MEMBER(mm_struct_mm_mt)) {
|
||||
+ mm_mt = tc->mm_struct + OFFSET(mm_struct_mm_mt);
|
||||
+ entry_num = do_maple_tree(mm_mt, MAPLE_TREE_COUNT, NULL);
|
||||
+ entry_list = (struct list_pair *)GETBUF(entry_num * sizeof(struct list_pair));
|
||||
+ do_maple_tree(mm_mt, MAPLE_TREE_GATHER, entry_list);
|
||||
+ for (i = 0; i < entry_num; i++) {
|
||||
+ if (!!(vma = (ulong)entry_list[i].value))
|
||||
+ break;
|
||||
+ }
|
||||
+ FREEBUF(entry_list);
|
||||
+ } else {
|
||||
+ fill_mm_struct(tc->mm_struct);
|
||||
+ vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap));
|
||||
+ }
|
||||
+
|
||||
if (!vma)
|
||||
return FALSE;
|
||||
vma_buf = fill_vma_cache(vma);
|
||||
@@ -15491,6 +15505,30 @@ search_physical(struct searchinfo *si)
|
||||
FREEBUF(pagebuf);
|
||||
}
|
||||
|
||||
+static bool
|
||||
+check_vma(ulong vma, ulong vaddr, ulong *vm_next, ulong *nextvaddr)
|
||||
+{
|
||||
+ char *vma_buf;
|
||||
+ ulong vm_start, vm_end;
|
||||
+
|
||||
+ vma_buf = fill_vma_cache(vma);
|
||||
+
|
||||
+ vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start));
|
||||
+ vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end));
|
||||
+ if (vm_next)
|
||||
+ *vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next));
|
||||
+
|
||||
+ if (vaddr <= vm_start) {
|
||||
+ *nextvaddr = vm_start;
|
||||
+ return TRUE;
|
||||
+ }
|
||||
+
|
||||
+ if ((vaddr > vm_start) && (vaddr < vm_end)) {
|
||||
+ *nextvaddr = vaddr;
|
||||
+ return TRUE;
|
||||
+ }
|
||||
+ return FALSE;
|
||||
+}
|
||||
|
||||
/*
|
||||
* Return the next mapped user virtual address page that comes after
|
||||
@@ -15500,37 +15538,40 @@ static int
|
||||
next_upage(struct task_context *tc, ulong vaddr, ulong *nextvaddr)
|
||||
{
|
||||
ulong vma, total_vm;
|
||||
- char *vma_buf;
|
||||
- ulong vm_start, vm_end;
|
||||
ulong vm_next;
|
||||
+ ulong mm_mt, entry_num, i;
|
||||
+ struct list_pair *entry_list;
|
||||
|
||||
if (!tc->mm_struct)
|
||||
return FALSE;
|
||||
|
||||
- fill_mm_struct(tc->mm_struct);
|
||||
- vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap));
|
||||
+ fill_mm_struct(tc->mm_struct);
|
||||
+ vaddr = VIRTPAGEBASE(vaddr) + PAGESIZE(); /* first possible page */
|
||||
total_vm = ULONG(tt->mm_struct + OFFSET(mm_struct_total_vm));
|
||||
-
|
||||
- if (!vma || (total_vm == 0))
|
||||
+ if (!total_vm)
|
||||
return FALSE;
|
||||
|
||||
- vaddr = VIRTPAGEBASE(vaddr) + PAGESIZE(); /* first possible page */
|
||||
-
|
||||
- for ( ; vma; vma = vm_next) {
|
||||
- vma_buf = fill_vma_cache(vma);
|
||||
-
|
||||
- vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start));
|
||||
- vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end));
|
||||
- vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next));
|
||||
-
|
||||
- if (vaddr <= vm_start) {
|
||||
- *nextvaddr = vm_start;
|
||||
- return TRUE;
|
||||
+ if (INVALID_MEMBER(mm_struct_mmap) && VALID_MEMBER(mm_struct_mm_mt)) {
|
||||
+ mm_mt = tc->mm_struct + OFFSET(mm_struct_mm_mt);
|
||||
+ entry_num = do_maple_tree(mm_mt, MAPLE_TREE_COUNT, NULL);
|
||||
+ entry_list = (struct list_pair *)GETBUF(entry_num * sizeof(struct list_pair));
|
||||
+ do_maple_tree(mm_mt, MAPLE_TREE_GATHER, entry_list);
|
||||
+ for (i = 0; i < entry_num; i++) {
|
||||
+ if (!!(vma = (ulong)entry_list[i].value) &&
|
||||
+ check_vma(vma, vaddr, NULL, nextvaddr)) {
|
||||
+ FREEBUF(entry_list);
|
||||
+ return TRUE;
|
||||
+ }
|
||||
}
|
||||
+ FREEBUF(entry_list);
|
||||
+ } else {
|
||||
+ vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap));
|
||||
|
||||
- if ((vaddr > vm_start) && (vaddr < vm_end)) {
|
||||
- *nextvaddr = vaddr;
|
||||
- return TRUE;
|
||||
+ if (!vma)
|
||||
+ return FALSE;
|
||||
+ for ( ; vma; vma = vm_next) {
|
||||
+ if (check_vma(vma, vaddr, &vm_next, nextvaddr))
|
||||
+ return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.37.1
|
||||
|
258
0037-Enhance-net-command-to-display-IPv6-address-of-netwo.patch
Normal file
258
0037-Enhance-net-command-to-display-IPv6-address-of-netwo.patch
Normal file
@ -0,0 +1,258 @@
|
||||
From 38325fab533751a001b80481cec149213d125abb Mon Sep 17 00:00:00 2001
|
||||
From: Lianbo Jiang <lijiang@redhat.com>
|
||||
Date: Tue, 7 Mar 2023 17:14:25 +0800
|
||||
Subject: [PATCH 09/12] Enhance "net" command to display IPv6 address of
|
||||
network interface
|
||||
|
||||
Currently, the "net" command displays only the IPv4 address of a network
|
||||
interface. Support outputting IPv6 addresses. For example:
|
||||
|
||||
Without the patch:
|
||||
crash> net
|
||||
NET_DEVICE NAME IP ADDRESS(ES)
|
||||
ffff8d01b1205000 lo 127.0.0.1
|
||||
ffff8d0087e40000 eno1 192.168.122.2
|
||||
|
||||
With the patch:
|
||||
crash> net
|
||||
NET_DEVICE NAME IP ADDRESS(ES)
|
||||
ffff8d01b1205000 lo 127.0.0.1, ::1
|
||||
ffff8d0087e40000 eno1 192.168.122.2, xxxx:xx:x:xxxx:xxxx:xxx:xxxx:xxxx, yyyy::yyyy:yyy:yyyy:yyyy
|
||||
|
||||
Also align with longer device names.
|
||||
|
||||
Related kernel commit:
|
||||
502a2ffd7376 ("ipv6: convert idev_list to list macros")
|
||||
|
||||
Reported-by: Buland Kumar Singh <bsingh@redhat.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
|
||||
---
|
||||
defs.h | 6 +++
|
||||
net.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
symbols.c | 6 +++
|
||||
3 files changed, 112 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/defs.h b/defs.h
|
||||
index e76af3c78b69..1f2cf6e0ce01 100644
|
||||
--- a/defs.h
|
||||
+++ b/defs.h
|
||||
@@ -2208,6 +2208,12 @@ struct offset_table { /* stash of commonly-used offsets */
|
||||
long sock_common_skc_v6_daddr;
|
||||
long sock_common_skc_v6_rcv_saddr;
|
||||
long inactive_task_frame_bp;
|
||||
+ long net_device_ip6_ptr;
|
||||
+ long inet6_dev_addr_list;
|
||||
+ long inet6_ifaddr_addr;
|
||||
+ long inet6_ifaddr_if_list;
|
||||
+ long inet6_ifaddr_if_next;
|
||||
+ long in6_addr_in6_u;
|
||||
};
|
||||
|
||||
struct size_table { /* stash of commonly-used sizes */
|
||||
diff --git a/net.c b/net.c
|
||||
index aa445ab7ee13..987dc8934942 100644
|
||||
--- a/net.c
|
||||
+++ b/net.c
|
||||
@@ -71,6 +71,7 @@ static void print_neighbour_q(ulong, int);
|
||||
static void get_netdev_info(ulong, struct devinfo *);
|
||||
static void get_device_name(ulong, char *);
|
||||
static long get_device_address(ulong, char **, long);
|
||||
+static void get_device_ip6_address(ulong, char **, long);
|
||||
static void get_sock_info(ulong, char *);
|
||||
static void dump_arp(void);
|
||||
static void arp_state_to_flags(unsigned char);
|
||||
@@ -114,6 +115,13 @@ net_init(void)
|
||||
net->dev_ip_ptr = MEMBER_OFFSET_INIT(net_device_ip_ptr,
|
||||
"net_device", "ip_ptr");
|
||||
MEMBER_OFFSET_INIT(net_device_dev_list, "net_device", "dev_list");
|
||||
+ MEMBER_OFFSET_INIT(net_device_ip6_ptr, "net_device", "ip6_ptr");
|
||||
+ MEMBER_OFFSET_INIT(inet6_dev_addr_list, "inet6_dev", "addr_list");
|
||||
+ MEMBER_OFFSET_INIT(inet6_ifaddr_addr, "inet6_ifaddr", "addr");
|
||||
+ MEMBER_OFFSET_INIT(inet6_ifaddr_if_list, "inet6_ifaddr", "if_list");
|
||||
+ MEMBER_OFFSET_INIT(inet6_ifaddr_if_next, "inet6_ifaddr", "if_next");
|
||||
+ MEMBER_OFFSET_INIT(in6_addr_in6_u, "in6_addr", "in6_u");
|
||||
+
|
||||
MEMBER_OFFSET_INIT(net_dev_base_head, "net", "dev_base_head");
|
||||
ARRAY_LENGTH_INIT(net->net_device_name_index,
|
||||
net_device_name, "net_device.name", NULL, sizeof(char));
|
||||
@@ -466,7 +474,7 @@ show_net_devices(ulong task)
|
||||
buf = GETBUF(buflen);
|
||||
flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
|
||||
|
||||
- fprintf(fp, "%s NAME IP ADDRESS(ES)\n",
|
||||
+ fprintf(fp, "%s NAME IP ADDRESS(ES)\n",
|
||||
mkstring(upper_case(net->netdevice, buf),
|
||||
flen, CENTER|LJUST, NULL));
|
||||
|
||||
@@ -475,9 +483,10 @@ show_net_devices(ulong task)
|
||||
mkstring(buf, flen, CENTER|RJUST|LONG_HEX, MKSTR(next)));
|
||||
|
||||
get_device_name(next, buf);
|
||||
- fprintf(fp, "%-6s ", buf);
|
||||
+ fprintf(fp, "%-10s ", buf);
|
||||
|
||||
- buflen = get_device_address(next, &buf, buflen);
|
||||
+ get_device_address(next, &buf, buflen);
|
||||
+ get_device_ip6_address(next, &buf, buflen);
|
||||
fprintf(fp, "%s\n", buf);
|
||||
|
||||
readmem(next+net->dev_next, KVADDR, &next,
|
||||
@@ -503,7 +512,7 @@ show_net_devices_v2(ulong task)
|
||||
buf = GETBUF(buflen);
|
||||
flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
|
||||
|
||||
- fprintf(fp, "%s NAME IP ADDRESS(ES)\n",
|
||||
+ fprintf(fp, "%s NAME IP ADDRESS(ES)\n",
|
||||
mkstring(upper_case(net->netdevice, buf),
|
||||
flen, CENTER|LJUST, NULL));
|
||||
|
||||
@@ -528,9 +537,10 @@ show_net_devices_v2(ulong task)
|
||||
MKSTR(ld->list_ptr[i])));
|
||||
|
||||
get_device_name(ld->list_ptr[i], buf);
|
||||
- fprintf(fp, "%-6s ", buf);
|
||||
+ fprintf(fp, "%-10s ", buf);
|
||||
|
||||
- buflen = get_device_address(ld->list_ptr[i], &buf, buflen);
|
||||
+ get_device_address(ld->list_ptr[i], &buf, buflen);
|
||||
+ get_device_ip6_address(ld->list_ptr[i], &buf, buflen);
|
||||
fprintf(fp, "%s\n", buf);
|
||||
}
|
||||
|
||||
@@ -556,7 +566,7 @@ show_net_devices_v3(ulong task)
|
||||
buf = GETBUF(buflen);
|
||||
flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
|
||||
|
||||
- fprintf(fp, "%s NAME IP ADDRESS(ES)\n",
|
||||
+ fprintf(fp, "%s NAME IP ADDRESS(ES)\n",
|
||||
mkstring(upper_case(net->netdevice, buf),
|
||||
flen, CENTER|LJUST, NULL));
|
||||
|
||||
@@ -591,9 +601,10 @@ show_net_devices_v3(ulong task)
|
||||
MKSTR(ld->list_ptr[i])));
|
||||
|
||||
get_device_name(ld->list_ptr[i], buf);
|
||||
- fprintf(fp, "%-6s ", buf);
|
||||
+ fprintf(fp, "%-10s ", buf);
|
||||
|
||||
- buflen = get_device_address(ld->list_ptr[i], &buf, buflen);
|
||||
+ get_device_address(ld->list_ptr[i], &buf, buflen);
|
||||
+ get_device_ip6_address(ld->list_ptr[i], &buf, buflen);
|
||||
fprintf(fp, "%s\n", buf);
|
||||
}
|
||||
|
||||
@@ -925,6 +936,86 @@ get_device_address(ulong devaddr, char **bufp, long buflen)
|
||||
return buflen;
|
||||
}
|
||||
|
||||
+static void
|
||||
+get_device_ip6_address(ulong devaddr, char **bufp, long buflen)
|
||||
+{
|
||||
+ ulong ip6_ptr = 0, pos = 0, bufsize = buflen, addr = 0;
|
||||
+ struct in6_addr ip6_addr;
|
||||
+ char *buf;
|
||||
+ char str[INET6_ADDRSTRLEN] = {0};
|
||||
+ char buffer[INET6_ADDRSTRLEN + 2] = {0};
|
||||
+ uint len = 0;
|
||||
+
|
||||
+ buf = *bufp;
|
||||
+ pos = strlen(buf);
|
||||
+
|
||||
+ readmem(devaddr + OFFSET(net_device_ip6_ptr), KVADDR,
|
||||
+ &ip6_ptr, sizeof(ulong), "ip6_ptr", FAULT_ON_ERROR);
|
||||
+
|
||||
+ if (!ip6_ptr)
|
||||
+ return;
|
||||
+
|
||||
+ /*
|
||||
+ * 502a2ffd7376 ("ipv6: convert idev_list to list macros")
|
||||
+ * v2.6.35-rc1~473^2~733
|
||||
+ */
|
||||
+ if (VALID_MEMBER(inet6_ifaddr_if_list)) {
|
||||
+ struct list_data list_data, *ld;
|
||||
+ ulong cnt = 0, i;
|
||||
+
|
||||
+ ld = &list_data;
|
||||
+ BZERO(ld, sizeof(struct list_data));
|
||||
+ ld->flags |= LIST_ALLOCATE;
|
||||
+ ld->start = ip6_ptr + OFFSET(inet6_dev_addr_list);
|
||||
+ ld->list_head_offset = OFFSET(inet6_ifaddr_if_list);
|
||||
+ cnt = do_list(ld);
|
||||
+
|
||||
+ for (i = 1; i < cnt; i++) {
|
||||
+
|
||||
+ addr = ld->list_ptr[i] + OFFSET(inet6_ifaddr_addr);
|
||||
+ readmem(addr + OFFSET(in6_addr_in6_u), KVADDR, &ip6_addr,
|
||||
+ sizeof(struct in6_addr), "in6_addr.in6_u", FAULT_ON_ERROR);
|
||||
+
|
||||
+ inet_ntop(AF_INET6, (void*)&ip6_addr, str, INET6_ADDRSTRLEN);
|
||||
+ sprintf(buffer, "%s%s", pos ? ", " : "", str);
|
||||
+ len = strlen(buffer);
|
||||
+ if (pos + len >= bufsize) {
|
||||
+ RESIZEBUF(*bufp, bufsize, bufsize + buflen);
|
||||
+ buf = *bufp;
|
||||
+ BZERO(buf + bufsize, buflen);
|
||||
+ bufsize += buflen;
|
||||
+ }
|
||||
+ BCOPY(buffer, &buf[pos], len);
|
||||
+ pos += len;
|
||||
+ }
|
||||
+
|
||||
+ FREEBUF(ld->list_ptr);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ readmem(ip6_ptr + OFFSET(inet6_dev_addr_list), KVADDR,
|
||||
+ &addr, sizeof(void *), "inet6_dev.addr_list", FAULT_ON_ERROR);
|
||||
+
|
||||
+ while (addr) {
|
||||
+ readmem(addr + OFFSET(in6_addr_in6_u), KVADDR, &ip6_addr,
|
||||
+ sizeof(struct in6_addr), "in6_addr.in6_u", FAULT_ON_ERROR);
|
||||
+ inet_ntop(AF_INET6, (void*)&ip6_addr, str, INET6_ADDRSTRLEN);
|
||||
+ sprintf(buffer, "%s%s", pos ? ", " : "", str);
|
||||
+ len = strlen(buffer);
|
||||
+
|
||||
+ if (pos + len >= bufsize) {
|
||||
+ RESIZEBUF(*bufp, bufsize, bufsize + buflen);
|
||||
+ buf = *bufp;
|
||||
+ BZERO(buf + bufsize, buflen);
|
||||
+ bufsize += buflen;
|
||||
+ }
|
||||
+ BCOPY(buffer, &buf[pos], len);
|
||||
+ pos += len;
|
||||
+ readmem(addr + OFFSET(inet6_ifaddr_if_next), KVADDR, &addr,
|
||||
+ sizeof(void *), "inet6_ifaddr.if_next", FAULT_ON_ERROR);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Get the family, type, local and destination address/port pairs.
|
||||
*/
|
||||
diff --git a/symbols.c b/symbols.c
|
||||
index a974fc9141a0..28846d06273c 100644
|
||||
--- a/symbols.c
|
||||
+++ b/symbols.c
|
||||
@@ -9787,6 +9787,7 @@ dump_offset_table(char *spec, ulong makestruct)
|
||||
OFFSET(net_device_addr_len));
|
||||
fprintf(fp, " net_device_ip_ptr: %ld\n",
|
||||
OFFSET(net_device_ip_ptr));
|
||||
+ fprintf(fp, " net_device_ip6_ptr: %ld\n", OFFSET(net_device_ip6_ptr));
|
||||
fprintf(fp, " net_device_dev_list: %ld\n",
|
||||
OFFSET(net_device_dev_list));
|
||||
fprintf(fp, " net_dev_base_head: %ld\n",
|
||||
@@ -9839,6 +9840,11 @@ dump_offset_table(char *spec, ulong makestruct)
|
||||
fprintf(fp, " inet_opt_num: %ld\n",
|
||||
OFFSET(inet_opt_num));
|
||||
|
||||
+ fprintf(fp, " inet6_dev_addr_list: %ld\n", OFFSET(inet6_dev_addr_list));
|
||||
+ fprintf(fp, " inet6_ifaddr_addr: %ld\n", OFFSET(inet6_ifaddr_addr));
|
||||
+ fprintf(fp, " inet6_ifaddr_if_list: %ld\n", OFFSET(inet6_ifaddr_if_list));
|
||||
+ fprintf(fp, " inet6_ifaddr_if_next: %ld\n", OFFSET(inet6_ifaddr_if_next));
|
||||
+ fprintf(fp, " in6_addr_in6_u: %ld\n", OFFSET(in6_addr_in6_u));
|
||||
fprintf(fp, " ipv6_pinfo_rcv_saddr: %ld\n",
|
||||
OFFSET(ipv6_pinfo_rcv_saddr));
|
||||
fprintf(fp, " ipv6_pinfo_daddr: %ld\n",
|
||||
--
|
||||
2.37.1
|
||||
|
1071
0038-Fix-C99-compatibility-issues-in-embedded-copy-of-GDB.patch
Normal file
1071
0038-Fix-C99-compatibility-issues-in-embedded-copy-of-GDB.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,44 @@
|
||||
From 5a652ed0c8db8d4c5891091b747470431054c717 Mon Sep 17 00:00:00 2001
|
||||
From: Lianbo Jiang <lijiang@redhat.com>
|
||||
Date: Wed, 8 Mar 2023 20:22:02 +0800
|
||||
Subject: [PATCH 11/12] Fix for "net -n" option to properly deal with an
|
||||
invalid argument
|
||||
|
||||
The help/man page of the "net" command suggests that "-n" option can
|
||||
accept two kinds of argument: PID or task_struct pointer. However,
|
||||
the "net -n" command accepts an invalid argument and shows the
|
||||
namespace of the current context silently. For example:
|
||||
|
||||
crash> net -n 1000000000
|
||||
NET_DEVICE NAME IP ADDRESS(ES)
|
||||
ffff949dc11d7000 lo 127.0.0.1
|
||||
ffff949dcc01c000 eno49 192.168.122.17
|
||||
|
||||
With the patch, emit an error expectedly.
|
||||
|
||||
crash> net -n 1000000000
|
||||
net: invalid task or pid value: 1000000000
|
||||
|
||||
Reported-by: Buland Kumar Singh <bsingh@redhat.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
net.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/net.c b/net.c
|
||||
index 987dc8934942..18c238be346d 100644
|
||||
--- a/net.c
|
||||
+++ b/net.c
|
||||
@@ -420,6 +420,9 @@ cmd_net(void)
|
||||
case STR_PID:
|
||||
case STR_TASK:
|
||||
task = tc->task;
|
||||
+ break;
|
||||
+ case STR_INVALID:
|
||||
+ error(FATAL, "invalid task or pid value: %s\n", args[optind]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
--
|
||||
2.37.1
|
||||
|
@ -0,0 +1,71 @@
|
||||
From ade71c3ec1d28751c3d6ba1eec71781bdff093d3 Mon Sep 17 00:00:00 2001
|
||||
From: Lianbo Jiang <lijiang@redhat.com>
|
||||
Date: Tue, 7 Mar 2023 19:04:08 +0800
|
||||
Subject: [PATCH 12/12] gdb: Fix an assertion failure in
|
||||
dw2_find_pc_sect_compunit_symtab()
|
||||
|
||||
This is a partial backport patch from gdb commit 834eaf9201c1 ("Fix
|
||||
crash in new DWARF indexer").
|
||||
|
||||
Without the patch, the "dis -rl" option may abort due to an assertion
|
||||
failure in gdb's dw2_find_pc_sect_compunit_symtab():
|
||||
|
||||
crash> dis -rl ffffffff96ad716c
|
||||
dwarf2/read.c:4928: internal-error: compunit_symtab* dw2_find_pc_sect_compunit_symtab(objfile*, bound_minimal_symbol, CORE_ADDR, obj_section*, int): Assertion `result != NULL' failed.
|
||||
A problem internal to GDB has been detected,
|
||||
further debugging may prove unreliable.
|
||||
Quit this debugging session? (y or n) dwarf2/read.c:4928: internal-error: compunit_symtab* dw2_find_pc_sect_compunit_symtab(objfile*, bound_minimal_symbol, CORE_ADDR, obj_section*, int): Assertion `result != NULL' failed.
|
||||
A problem internal to GDB has been detected,
|
||||
further debugging may prove unreliable.
|
||||
Aborted (core dumped)
|
||||
|
||||
Reported-by: Buland Kumar Singh <bsingh@redhat.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
gdb-10.2.patch | 19 +++++++++++++++++--
|
||||
1 file changed, 17 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb-10.2.patch b/gdb-10.2.patch
|
||||
index 5089df9e72e1..835aae9859be 100644
|
||||
--- a/gdb-10.2.patch
|
||||
+++ b/gdb-10.2.patch
|
||||
@@ -4,7 +4,7 @@
|
||||
# that have already been applied. However, if a gdb file has been modified
|
||||
# multiple times, the subsequent patching may fail to recognize that a
|
||||
# given patch has been previously applied, and will attempt to re-apply it.
|
||||
-# To prevent any uninintended consequences, this file also acts as a
|
||||
+# To prevent any unintended consequences, this file also acts as a
|
||||
# shell script that can restore any gdb file to its original state prior
|
||||
# to all subsequent patch applications.
|
||||
|
||||
@@ -12,7 +12,8 @@ tar xvzmf gdb-10.2.tar.gz \
|
||||
gdb-10.2/gdb/symtab.c \
|
||||
gdb-10.2/gdb/printcmd.c \
|
||||
gdb-10.2/gdb/symfile.c \
|
||||
- gdb-10.2/gdb/Makefile.in
|
||||
+ gdb-10.2/gdb/Makefile.in \
|
||||
+ gdb-10.2/gdb/dwarf2/read.c
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -3105,3 +3106,17 @@ exit 0
|
||||
|
||||
m4_include([../../config/override.m4])
|
||||
|
||||
+--- gdb-10.2/gdb/dwarf2/read.c.orig
|
||||
++++ gdb-10.2/gdb/dwarf2/read.c
|
||||
+@@ -4925,7 +4925,10 @@ dw2_find_pc_sect_compunit_symtab (struct objfile *objfile,
|
||||
+ result = recursively_find_pc_sect_compunit_symtab
|
||||
+ (dw2_instantiate_symtab (data, per_objfile, false), pc);
|
||||
+
|
||||
+- gdb_assert (result != NULL);
|
||||
++ if (warn_if_readin && result == nullptr)
|
||||
++ warning (_("(Error: pc %s in address map, but not in symtab.)"),
|
||||
++ paddress (objfile->arch (), pc));
|
||||
++
|
||||
+ return result;
|
||||
+ }
|
||||
+
|
||||
--
|
||||
2.37.1
|
||||
|
159
0041-Fix-kmem-n-option-to-display-memory-blocks-on-Linux-.patch
Normal file
159
0041-Fix-kmem-n-option-to-display-memory-blocks-on-Linux-.patch
Normal file
@ -0,0 +1,159 @@
|
||||
From 489093c2183f4f0365d8957e7275cd88225942ce Mon Sep 17 00:00:00 2001
|
||||
From: Kazuhito Hagio <k-hagio-ab@nec.com>
|
||||
Date: Fri, 10 Mar 2023 02:38:26 +0000
|
||||
Subject: [PATCH] Fix "kmem -n" option to display memory blocks on Linux
|
||||
6.3-rc1 and later
|
||||
|
||||
Kernel commit d2bf38c088e0 ("driver core: remove private pointer from
|
||||
struct bus_type") removed the bus_type.p member, and the "kmem -n"
|
||||
option fails with the following error before displaying memory block
|
||||
information on Linux 6.3-rc1 and later kernels.
|
||||
|
||||
kmem: invalid structure member offset: bus_type_p
|
||||
FILE: memory.c LINE: 17852 FUNCTION: init_memory_block()
|
||||
|
||||
Search bus_kset.list instead for subsys_private of memory subsys.
|
||||
|
||||
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
|
||||
---
|
||||
defs.h | 2 ++
|
||||
memory.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++------
|
||||
symbols.c | 2 ++
|
||||
3 files changed, 61 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/defs.h b/defs.h
|
||||
index 1f2cf6e0ce01..12ad6aaa0998 100644
|
||||
--- a/defs.h
|
||||
+++ b/defs.h
|
||||
@@ -2214,6 +2214,8 @@ struct offset_table { /* stash of commonly-used offsets */
|
||||
long inet6_ifaddr_if_list;
|
||||
long inet6_ifaddr_if_next;
|
||||
long in6_addr_in6_u;
|
||||
+ long kset_kobj;
|
||||
+ long subsys_private_subsys;
|
||||
};
|
||||
|
||||
struct size_table { /* stash of commonly-used sizes */
|
||||
diff --git a/memory.c b/memory.c
|
||||
index c4a6ecd18004..592a5ef49d50 100644
|
||||
--- a/memory.c
|
||||
+++ b/memory.c
|
||||
@@ -17822,6 +17822,13 @@ static void
|
||||
init_memory_block_offset(void)
|
||||
{
|
||||
MEMBER_OFFSET_INIT(bus_type_p, "bus_type", "p");
|
||||
+ if (INVALID_MEMBER(bus_type_p)) {
|
||||
+ MEMBER_OFFSET_INIT(kset_list, "kset", "list");
|
||||
+ MEMBER_OFFSET_INIT(kset_kobj, "kset", "kobj");
|
||||
+ MEMBER_OFFSET_INIT(kobject_name, "kobject", "name");
|
||||
+ MEMBER_OFFSET_INIT(kobject_entry, "kobject", "entry");
|
||||
+ MEMBER_OFFSET_INIT(subsys_private_subsys, "subsys_private", "subsys");
|
||||
+ }
|
||||
MEMBER_OFFSET_INIT(subsys_private_klist_devices,
|
||||
"subsys_private", "klist_devices");
|
||||
MEMBER_OFFSET_INIT(klist_k_list, "klist", "k_list");
|
||||
@@ -17842,15 +17849,60 @@ init_memory_block_offset(void)
|
||||
}
|
||||
|
||||
static void
|
||||
-init_memory_block(struct list_data *ld, int *klistcnt, ulong **klistbuf)
|
||||
+init_memory_block(int *klistcnt, ulong **klistbuf)
|
||||
{
|
||||
- ulong memory_subsys = symbol_value("memory_subsys");
|
||||
ulong private, klist, start;
|
||||
+ struct list_data list_data, *ld;
|
||||
+
|
||||
+ ld = &list_data;
|
||||
+ private = 0;
|
||||
|
||||
init_memory_block_offset();
|
||||
|
||||
- readmem(memory_subsys + OFFSET(bus_type_p), KVADDR, &private,
|
||||
- sizeof(void *), "memory_subsys.private", FAULT_ON_ERROR);
|
||||
+ /*
|
||||
+ * v6.3-rc1
|
||||
+ * d2bf38c088e0 driver core: remove private pointer from struct bus_type
|
||||
+ */
|
||||
+ if (INVALID_MEMBER(bus_type_p)) {
|
||||
+ int i, cnt;
|
||||
+ char buf[32];
|
||||
+ ulong bus_kset, list, name;
|
||||
+
|
||||
+ BZERO(ld, sizeof(struct list_data));
|
||||
+
|
||||
+ get_symbol_data("bus_kset", sizeof(ulong), &bus_kset);
|
||||
+ readmem(bus_kset + OFFSET(kset_list), KVADDR, &list,
|
||||
+ sizeof(ulong), "bus_kset.list", FAULT_ON_ERROR);
|
||||
+
|
||||
+ ld->flags |= LIST_ALLOCATE;
|
||||
+ ld->start = list;
|
||||
+ ld->end = bus_kset + OFFSET(kset_list);
|
||||
+ ld->list_head_offset = OFFSET(kobject_entry);
|
||||
+
|
||||
+ cnt = do_list(ld);
|
||||
+ for (i = 0; i < cnt; i++) {
|
||||
+ readmem(ld->list_ptr[i] + OFFSET(kobject_name), KVADDR, &name,
|
||||
+ sizeof(ulong), "kobject.name", FAULT_ON_ERROR);
|
||||
+ read_string(name, buf, sizeof(buf)-1);
|
||||
+ if (CRASHDEBUG(1))
|
||||
+ fprintf(fp, "kobject: %lx name: %s\n", ld->list_ptr[i], buf);
|
||||
+ if (STREQ(buf, "memory")) {
|
||||
+ /* entry is subsys_private.subsys.kobj. See bus_to_subsys(). */
|
||||
+ private = ld->list_ptr[i] - OFFSET(kset_kobj)
|
||||
+ - OFFSET(subsys_private_subsys);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ FREEBUF(ld->list_ptr);
|
||||
+ } else {
|
||||
+ ulong memory_subsys = symbol_value("memory_subsys");
|
||||
+ readmem(memory_subsys + OFFSET(bus_type_p), KVADDR, &private,
|
||||
+ sizeof(void *), "memory_subsys.private", FAULT_ON_ERROR);
|
||||
+ }
|
||||
+
|
||||
+ if (!private)
|
||||
+ error(FATAL, "cannot determine subsys_private for memory.\n");
|
||||
+
|
||||
klist = private + OFFSET(subsys_private_klist_devices) +
|
||||
OFFSET(klist_k_list);
|
||||
BZERO(ld, sizeof(struct list_data));
|
||||
@@ -17875,7 +17927,6 @@ dump_memory_blocks(int initialize)
|
||||
ulong memory_block, device;
|
||||
ulong *klistbuf;
|
||||
int klistcnt, i;
|
||||
- struct list_data list_data;
|
||||
char mb_hdr[BUFSIZE];
|
||||
char paddr_hdr[BUFSIZE];
|
||||
char buf1[BUFSIZE];
|
||||
@@ -17892,7 +17943,7 @@ dump_memory_blocks(int initialize)
|
||||
if (initialize)
|
||||
return;
|
||||
|
||||
- init_memory_block(&list_data, &klistcnt, &klistbuf);
|
||||
+ init_memory_block(&klistcnt, &klistbuf);
|
||||
|
||||
if ((symbol_exists("memory_block_size_probed")) ||
|
||||
(MEMBER_EXISTS("memory_block", "end_section_nr")))
|
||||
diff --git a/symbols.c b/symbols.c
|
||||
index 28846d06273c..f0721023816d 100644
|
||||
--- a/symbols.c
|
||||
+++ b/symbols.c
|
||||
@@ -10404,6 +10404,7 @@ dump_offset_table(char *spec, ulong makestruct)
|
||||
OFFSET(kobject_entry));
|
||||
fprintf(fp, " kset_list: %ld\n",
|
||||
OFFSET(kset_list));
|
||||
+ fprintf(fp, " kset_kobj: %ld\n", OFFSET(kset_kobj));
|
||||
fprintf(fp, " request_list_count: %ld\n",
|
||||
OFFSET(request_list_count));
|
||||
fprintf(fp, " request_cmd_flags: %ld\n",
|
||||
@@ -10441,6 +10442,7 @@ dump_offset_table(char *spec, ulong makestruct)
|
||||
fprintf(fp, " blk_mq_tags_rqs: %ld\n",
|
||||
OFFSET(blk_mq_tags_rqs));
|
||||
|
||||
+ fprintf(fp, " subsys_private_subsys: %ld\n", OFFSET(subsys_private_subsys));
|
||||
fprintf(fp, " subsys_private_klist_devices: %ld\n",
|
||||
OFFSET(subsys_private_klist_devices));
|
||||
fprintf(fp, " subsystem_kset: %ld\n",
|
||||
--
|
||||
2.37.1
|
||||
|
52
crash.spec
52
crash.spec
@ -4,7 +4,7 @@
|
||||
Summary: Kernel analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles
|
||||
Name: crash
|
||||
Version: 8.0.2
|
||||
Release: 3%{?dist}
|
||||
Release: 4%{?dist}
|
||||
License: GPLv3
|
||||
Source0: https://github.com/crash-utility/crash/archive/crash-%{version}.tar.gz
|
||||
Source1: http://ftp.gnu.org/gnu/gdb/gdb-10.2.tar.gz
|
||||
@ -46,8 +46,20 @@ Patch25: 0025-Add-do_maple_tree-for-maple-tree-operations.patch
|
||||
Patch26: 0026-Introduce-maple-tree-vma-iteration-to-vm_area_dump.patch
|
||||
Patch27: 0027-Update-the-help-text-of-tree-command-for-maple-tree.patch
|
||||
Patch28: 0028-Dump-maple-tree-offset-variables-by-help-o.patch
|
||||
Patch29: crash-8.0.2_build.patch
|
||||
Patch30: crash-8.0.0-5-gdb-cdefs.patch
|
||||
Patch29: 0029-Fix-for-bt-command-printing-bogus-exception-frame-wa.patch
|
||||
Patch30: 0030-Fix-kmem-s-S-not-working-properly-on-RHEL8.6-and-lat.patch
|
||||
Patch31: 0031-Fix-for-net-s-option-to-show-IPv6-addresses-on-Linux.patch
|
||||
Patch32: 0032-Fix-for-kmem-i-option-to-not-print-invalid-values-fo.patch
|
||||
Patch33: 0033-Fix-for-bt-command-unnecessarily-printing-an-excepti.patch
|
||||
Patch34: 0034-Fix-for-dis-command-to-correctly-display-the-offset-.patch
|
||||
Patch35: 0035-x86_64-Fix-bt-command-on-kernels-with-random_kstack_.patch
|
||||
Patch36: 0036-Fix-for-search-u-option-failing-in-maple-tree-kernel.patch
|
||||
Patch37: 0037-Enhance-net-command-to-display-IPv6-address-of-netwo.patch
|
||||
Patch38: 0038-Fix-C99-compatibility-issues-in-embedded-copy-of-GDB.patch
|
||||
Patch39: 0039-Fix-for-net-n-option-to-properly-deal-with-an-invali.patch
|
||||
Patch40: 0040-gdb-Fix-an-assertion-failure-in-dw2_find_pc_sect_com.patch
|
||||
Patch41: 0041-Fix-kmem-n-option-to-display-memory-blocks-on-Linux-.patch
|
||||
Patch42: crash-8.0.2_build.patch
|
||||
|
||||
%description
|
||||
The core analysis suite is a self-contained tool that can be used to
|
||||
@ -96,11 +108,20 @@ offered by Mission Critical Linux, or the LKCD kernel patch.
|
||||
%patch26 -p1
|
||||
%patch27 -p1
|
||||
%patch28 -p1
|
||||
%patch29 -p1 -b crash-8.0.2_build.patch
|
||||
%ifarch ppc64le
|
||||
%patch30 -p1 -b crash-8.0.0-5-gdb-cdefs.patch
|
||||
%endif
|
||||
|
||||
%patch29 -p1
|
||||
%patch30 -p1
|
||||
%patch31 -p1
|
||||
%patch32 -p1
|
||||
%patch33 -p1
|
||||
%patch34 -p1
|
||||
%patch35 -p1
|
||||
%patch36 -p1
|
||||
%patch37 -p1
|
||||
%patch38 -p1
|
||||
%patch39 -p1
|
||||
%patch40 -p1
|
||||
%patch41 -p1
|
||||
%patch42 -p1
|
||||
|
||||
%build
|
||||
|
||||
@ -126,6 +147,21 @@ cp -p defs.h %{buildroot}%{_includedir}/crash
|
||||
%{_includedir}/*
|
||||
|
||||
%changelog
|
||||
* Fri Mar 10 2023 Lianbo Jiang <lijiang@redhat.com> - 8.0.2-4
|
||||
- Fix "kmem -n" option to display memory blocks on Linux 6.3-rc1 and later
|
||||
- gdb: Fix an assertion failure in dw2_find_pc_sect_compunit_symtab()
|
||||
- Fix for "net -n" option to properly deal with an invalid argument
|
||||
- Fix C99 compatibility issues in embedded copy of GDB
|
||||
- Enhance "net" command to display IPv6 address of network interface
|
||||
- Fix for "search -u" option failing in maple tree kernel
|
||||
- x86_64: Fix "bt" command on kernels with random_kstack_offset=on
|
||||
- Fix for "dis" command to correctly display the offset of disassembly code
|
||||
- Fix for "bt" command unnecessarily printing an exception frame
|
||||
- Fix for "kmem -i" option to not print invalid values for CACHED
|
||||
- Fix for "net -s" option to show IPv6 addresses on Linux 3.13 and later
|
||||
- Fix "kmem -s|-S" not working properly on RHEL8.6 and later
|
||||
- Fix for "bt" command printing "bogus exception frame" warning
|
||||
|
||||
* Tue Feb 07 2023 Lianbo Jiang <lijiang@redhat.com> - 8.0.2-3
|
||||
- Update to the latest upstream commit <46344aa2f92b>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user