import CS crash-9.0.0-4.el9
This commit is contained in:
parent
d7229c534e
commit
b55bbe7ebe
@ -1,2 +1,2 @@
|
||||
118c55409a4e026c8052c7cb0020dbc24b5144a1 SOURCES/crash-8.0.6.tar.gz
|
||||
6bf5ee7877a4740835745ed97ce525a00bb2232c SOURCES/gdb-10.2.tar.gz
|
||||
65b1f9838546db98aabf106ba895b25f243d17b3 SOURCES/crash-9.0.0.tar.gz
|
||||
9fd025eefefc88392ad620b4dcb063bcde157bd2 SOURCES/gdb-16.2.tar.gz
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
SOURCES/crash-8.0.6.tar.gz
|
||||
SOURCES/gdb-10.2.tar.gz
|
||||
SOURCES/crash-9.0.0.tar.gz
|
||||
SOURCES/gdb-16.2.tar.gz
|
||||
|
219
SOURCES/0001-Add-blk_mq-shared-tags-support-for-dev-d-D.patch
Normal file
219
SOURCES/0001-Add-blk_mq-shared-tags-support-for-dev-d-D.patch
Normal file
@ -0,0 +1,219 @@
|
||||
From 62486400d35b258e4e3c40c4bf0daedc231f835a Mon Sep 17 00:00:00 2001
|
||||
From: Tao Liu <ltao@redhat.com>
|
||||
Date: Fri, 27 Jun 2025 23:30:59 +1200
|
||||
Subject: [PATCH] Add blk_mq shared tags support for dev -d/-D
|
||||
|
||||
When blk_mq shared tags enabled for devices like scsi, the IO status is
|
||||
incorrect, e.g:
|
||||
|
||||
crash> dev -d
|
||||
MAJOR GENDISK NAME REQUEST_QUEUE TOTAL ASYNC SYNC
|
||||
8 ffff90528df86000 sda ffff9052a3d61800 144 144 0
|
||||
8 ffff905280718c00 sdb ffff9052a3d63c00 48 48 0
|
||||
|
||||
crash> epython rqlist
|
||||
ffff90528e94a5c0 sda is unknown, deadline: 89.992 (90) rq_alloc: 0.196
|
||||
ffff90528e92f700 sda is unknown, deadline: 89.998 (90) rq_alloc: 0.202
|
||||
ffff90528e95ccc0 sda is unknown, deadline: 89.999 (90) rq_alloc: 0.203
|
||||
ffff90528e968bc0 sdb is unknown, deadline: 89.997 (90) rq_alloc: 0.201
|
||||
|
||||
The root cause is: for shared tags case, only the shared tags are put
|
||||
into count. Without this patch, tags of all the hw_ctx are counted,
|
||||
which is incorrect.
|
||||
|
||||
After apply the patch:
|
||||
|
||||
crash> dev -d
|
||||
MAJOR GENDISK NAME REQUEST_QUEUE TOTAL READ WRITE
|
||||
8 ffff90528df86000 sda ffff9052a3d61800 3 3 0
|
||||
8 ffff905280718c00 sdb ffff9052a3d63c00 1 1 0
|
||||
|
||||
This patch makes the following modification:
|
||||
1) blk_mq shared tag support.
|
||||
2) Function renaming: queue_for_each_hw_ctx -> blk_mq_queue_tag_busy_iter,
|
||||
because the latter is more close to the corresponding kernel function.
|
||||
3) Extract a new queue_for_each_hw_ctx() function to be called for both
|
||||
shared-tags case and the hw_ctx case.
|
||||
|
||||
Note:
|
||||
The patch is safe for earlier kernels which have no blk_mq shared tags
|
||||
implemented, because the blk_mq_is_shared_tags() check will exit safely.
|
||||
|
||||
Signed-off-by: Tao Liu <ltao@redhat.com>
|
||||
---
|
||||
defs.h | 3 ++
|
||||
dev.c | 96 ++++++++++++++++++++++++++++++++++++++-----------------
|
||||
symbols.c | 6 ++++
|
||||
3 files changed, 76 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/defs.h b/defs.h
|
||||
index bbd6d4b..4fecb83 100644
|
||||
--- a/defs.h
|
||||
+++ b/defs.h
|
||||
@@ -2271,6 +2271,9 @@ struct offset_table { /* stash of commonly-used offsets */
|
||||
long task_struct_thread_context_x28;
|
||||
long neigh_table_hash_heads;
|
||||
long neighbour_hash;
|
||||
+ long request_queue_tag_set;
|
||||
+ long blk_mq_tag_set_flags;
|
||||
+ long blk_mq_tag_set_shared_tags;
|
||||
};
|
||||
|
||||
struct size_table { /* stash of commonly-used sizes */
|
||||
diff --git a/dev.c b/dev.c
|
||||
index 9d38aef..8391d71 100644
|
||||
--- a/dev.c
|
||||
+++ b/dev.c
|
||||
@@ -4326,6 +4326,12 @@ struct bt_iter_data {
|
||||
#define MQ_RQ_IN_FLIGHT 1
|
||||
#define REQ_OP_BITS 8
|
||||
#define REQ_OP_MASK ((1 << REQ_OP_BITS) - 1)
|
||||
+#define BLK_MQ_F_TAG_HCTX_SHARED (1 << 3)
|
||||
+
|
||||
+static bool blk_mq_is_shared_tags(unsigned int flags)
|
||||
+{
|
||||
+ return flags & BLK_MQ_F_TAG_HCTX_SHARED;
|
||||
+}
|
||||
|
||||
static uint op_is_write(uint op)
|
||||
{
|
||||
@@ -4403,43 +4409,72 @@ static void bt_for_each(ulong q, ulong tags, ulong sbq, uint reserved, uint nr_r
|
||||
sbitmap_for_each_set(&sc, bt_iter, &iter_data);
|
||||
}
|
||||
|
||||
-static void queue_for_each_hw_ctx(ulong q, ulong *hctx, uint cnt, struct diskio *dio)
|
||||
+static bool queue_for_each_hw_ctx(ulong q, ulong blk_mq_tags_ptr,
|
||||
+ bool bitmap_tags_is_ptr, struct diskio *dio)
|
||||
{
|
||||
- uint i;
|
||||
+ uint nr_reserved_tags = 0;
|
||||
+ ulong tags = 0, addr = 0;
|
||||
+ bool ret = FALSE;
|
||||
+
|
||||
+ if (!readmem(blk_mq_tags_ptr, KVADDR, &tags, sizeof(ulong),
|
||||
+ "blk_mq_hw_ctx.tags", RETURN_ON_ERROR))
|
||||
+ goto out;
|
||||
+
|
||||
+ addr = tags + OFFSET(blk_mq_tags_nr_reserved_tags);
|
||||
+ if (!readmem(addr, KVADDR, &nr_reserved_tags, sizeof(uint),
|
||||
+ "blk_mq_tags_nr_reserved_tags", RETURN_ON_ERROR))
|
||||
+ goto out;
|
||||
+
|
||||
+ if (nr_reserved_tags) {
|
||||
+ addr = tags + OFFSET(blk_mq_tags_breserved_tags);
|
||||
+ if (bitmap_tags_is_ptr &&
|
||||
+ !readmem(addr, KVADDR, &addr, sizeof(ulong),
|
||||
+ "blk_mq_tags.bitmap_tags", RETURN_ON_ERROR))
|
||||
+ goto out;
|
||||
+ bt_for_each(q, tags, addr, 1, nr_reserved_tags, dio);
|
||||
+ }
|
||||
+ addr = tags + OFFSET(blk_mq_tags_bitmap_tags);
|
||||
+ if (bitmap_tags_is_ptr &&
|
||||
+ !readmem(addr, KVADDR, &addr, sizeof(ulong),
|
||||
+ "blk_mq_tags.bitmap_tags", RETURN_ON_ERROR))
|
||||
+ goto out;
|
||||
+ bt_for_each(q, tags, addr, 0, nr_reserved_tags, dio);
|
||||
+
|
||||
+ ret = TRUE;
|
||||
+out:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Replica of kernel block/blk-mq-tag.c:blk_mq_queue_tag_busy_iter()
|
||||
+*/
|
||||
+static void blk_mq_queue_tag_busy_iter(ulong q, ulong *hctx, uint cnt,
|
||||
+ struct diskio *dio)
|
||||
+{
|
||||
+ uint i, flags;
|
||||
int bitmap_tags_is_ptr = 0;
|
||||
+ ulong addr = 0;
|
||||
|
||||
if (MEMBER_TYPE("blk_mq_tags", "bitmap_tags") == TYPE_CODE_PTR)
|
||||
bitmap_tags_is_ptr = 1;
|
||||
|
||||
- for (i = 0; i < cnt; i++) {
|
||||
- ulong addr = 0, tags = 0;
|
||||
- uint nr_reserved_tags = 0;
|
||||
+ readmem(q + OFFSET(request_queue_tag_set), KVADDR, &addr,
|
||||
+ sizeof(ulong), "request_queue.tag_set", RETURN_ON_ERROR);
|
||||
|
||||
- /* Tags owned by the block driver */
|
||||
- addr = hctx[i] + OFFSET(blk_mq_hw_ctx_tags);
|
||||
- if (!readmem(addr, KVADDR, &tags, sizeof(ulong),
|
||||
- "blk_mq_hw_ctx.tags", RETURN_ON_ERROR))
|
||||
- break;
|
||||
+ readmem(addr + OFFSET(blk_mq_tag_set_flags), KVADDR,
|
||||
+ &flags, sizeof(uint), "blk_mq_tag_set.flags", RETURN_ON_ERROR);
|
||||
|
||||
- addr = tags + OFFSET(blk_mq_tags_nr_reserved_tags);
|
||||
- if (!readmem(addr, KVADDR, &nr_reserved_tags, sizeof(uint),
|
||||
- "blk_mq_tags_nr_reserved_tags", RETURN_ON_ERROR))
|
||||
- break;
|
||||
+ if (blk_mq_is_shared_tags(flags)) {
|
||||
+ addr = addr + OFFSET(blk_mq_tag_set_shared_tags);
|
||||
+ queue_for_each_hw_ctx(q, addr, bitmap_tags_is_ptr, dio);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- if (nr_reserved_tags) {
|
||||
- addr = tags + OFFSET(blk_mq_tags_breserved_tags);
|
||||
- if (bitmap_tags_is_ptr &&
|
||||
- !readmem(addr, KVADDR, &addr, sizeof(ulong),
|
||||
- "blk_mq_tags.bitmap_tags", RETURN_ON_ERROR))
|
||||
- break;
|
||||
- bt_for_each(q, tags, addr, 1, nr_reserved_tags, dio);
|
||||
- }
|
||||
- addr = tags + OFFSET(blk_mq_tags_bitmap_tags);
|
||||
- if (bitmap_tags_is_ptr &&
|
||||
- !readmem(addr, KVADDR, &addr, sizeof(ulong),
|
||||
- "blk_mq_tags.bitmap_tags", RETURN_ON_ERROR))
|
||||
- break;
|
||||
- bt_for_each(q, tags, addr, 0, nr_reserved_tags, dio);
|
||||
+ for (i = 0; i < cnt; i++) {
|
||||
+ /* Tags owned by the block driver */
|
||||
+ addr = hctx[i] + OFFSET(blk_mq_hw_ctx_tags);
|
||||
+ if (queue_for_each_hw_ctx(q, addr, bitmap_tags_is_ptr, dio) == FALSE)
|
||||
+ return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4489,7 +4524,7 @@ static void get_mq_diskio_from_hw_queues(ulong q, struct diskio *dio)
|
||||
return;
|
||||
}
|
||||
|
||||
- queue_for_each_hw_ctx(q, hctx_array, cnt, dio);
|
||||
+ blk_mq_queue_tag_busy_iter(q, hctx_array, cnt, dio);
|
||||
|
||||
FREEBUF(hctx_array);
|
||||
}
|
||||
@@ -4914,6 +4949,9 @@ void diskio_init(void)
|
||||
MEMBER_SIZE_INIT(class_private_devices, "class_private",
|
||||
"class_devices");
|
||||
MEMBER_OFFSET_INIT(disk_stats_in_flight, "disk_stats", "in_flight");
|
||||
+ MEMBER_OFFSET_INIT(request_queue_tag_set, "request_queue", "tag_set");
|
||||
+ MEMBER_OFFSET_INIT(blk_mq_tag_set_flags, "blk_mq_tag_set", "flags");
|
||||
+ MEMBER_OFFSET_INIT(blk_mq_tag_set_shared_tags, "blk_mq_tag_set", "shared_tags");
|
||||
|
||||
dt->flags |= DISKIO_INIT;
|
||||
}
|
||||
diff --git a/symbols.c b/symbols.c
|
||||
index e30fafe..794519a 100644
|
||||
--- a/symbols.c
|
||||
+++ b/symbols.c
|
||||
@@ -11487,6 +11487,12 @@ dump_offset_table(char *spec, ulong makestruct)
|
||||
OFFSET(blk_mq_tags_nr_reserved_tags));
|
||||
fprintf(fp, " blk_mq_tags_rqs: %ld\n",
|
||||
OFFSET(blk_mq_tags_rqs));
|
||||
+ fprintf(fp, " request_queue_tag_set: %ld\n",
|
||||
+ OFFSET(request_queue_tag_set));
|
||||
+ fprintf(fp, " blk_mq_tag_set_flags: %ld\n",
|
||||
+ OFFSET(blk_mq_tag_set_flags));
|
||||
+ fprintf(fp, " blk_mq_tag_set_shared_tags: %ld\n",
|
||||
+ OFFSET(blk_mq_tag_set_shared_tags));
|
||||
|
||||
fprintf(fp, " subsys_private_subsys: %ld\n", OFFSET(subsys_private_subsys));
|
||||
fprintf(fp, " subsys_private_klist_devices: %ld\n",
|
||||
--
|
||||
2.47.0
|
||||
|
126
SOURCES/0001-vmware_guestdump-Version-7-support.patch
Normal file
126
SOURCES/0001-vmware_guestdump-Version-7-support.patch
Normal file
@ -0,0 +1,126 @@
|
||||
From a18b8a7fb83ae79f5c0698063f26ec8a289cf90b Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <alexey.makhalov@broadcom.com>
|
||||
Date: Wed, 30 Apr 2025 21:54:27 +0000
|
||||
Subject: [PATCH 1/9] vmware_guestdump: Version 7 support
|
||||
|
||||
ESXi 9.0 updated debug.guest format. CPU architecture type was
|
||||
introduced and several fields of the header not used by the crash
|
||||
were moved around. It is version 7 now.
|
||||
|
||||
Make corresponding changes in debug.guest parser and keep it
|
||||
backward compatible with older versions.
|
||||
|
||||
Fix comment and log messages typos as well.
|
||||
|
||||
Signed-off-by: Alexey Makhalov <alexey.makhalov@broadcom.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
vmware_guestdump.c | 48 ++++++++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 44 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/vmware_guestdump.c b/vmware_guestdump.c
|
||||
index 78f37fbf3553..1a6ef9bd070c 100644
|
||||
--- a/vmware_guestdump.c
|
||||
+++ b/vmware_guestdump.c
|
||||
@@ -30,6 +30,7 @@
|
||||
* 2. Number of Virtual CPUs (4 bytes) } - struct guestdumpheader
|
||||
* 3. Reserved gap
|
||||
* 4. Main Memory information - struct mainmeminfo{,_old}
|
||||
+ * 5. Reserved gap #2. Only in v7+
|
||||
* (use get_vcpus_offset() to get total size of guestdumpheader)
|
||||
* vcpus_offset: ---------\
|
||||
* 1. struct vcpu_state1 \
|
||||
@@ -111,6 +112,22 @@ struct vcpu_state2 {
|
||||
uint8_t reserved3[65];
|
||||
} __attribute__((packed));
|
||||
|
||||
+typedef enum {
|
||||
+ CPU_ARCH_AARCH64,
|
||||
+ CPU_ARCH_X86,
|
||||
+} cpu_arch;
|
||||
+
|
||||
+/*
|
||||
+ * Returns the size of reserved gap #2 in the header right after the Main Mem.
|
||||
+ */
|
||||
+static inline long
|
||||
+get_gap2_size(uint32_t version)
|
||||
+{
|
||||
+ if (version == 7)
|
||||
+ return 11;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Returns the size of the guest dump header.
|
||||
*/
|
||||
@@ -128,6 +145,9 @@ get_vcpus_offset(uint32_t version, int mem_holes)
|
||||
return sizeof(struct guestdumpheader) + 14 + sizeof(struct mainmeminfo);
|
||||
case 6: /* ESXi 8.0u2 */
|
||||
return sizeof(struct guestdumpheader) + 15 + sizeof(struct mainmeminfo);
|
||||
+ case 7: /* ESXi 9.0 */
|
||||
+ return sizeof(struct guestdumpheader) + 8 + sizeof(struct mainmeminfo) +
|
||||
+ get_gap2_size(version);
|
||||
|
||||
}
|
||||
return 0;
|
||||
@@ -155,10 +175,10 @@ get_vcpu_gapsize(uint32_t version)
|
||||
*
|
||||
* guestdump (debug.guest) is a simplified version of the *.vmss which does
|
||||
* not contain a full VM state, but minimal guest state, such as a memory
|
||||
- * layout and CPUs state, needed for debugger. is_vmware_guestdump()
|
||||
+ * layout and CPUs state, needed for the debugger. is_vmware_guestdump()
|
||||
* and vmware_guestdump_init() functions parse guestdump header and
|
||||
* populate vmss data structure (from vmware_vmss.c). In result, all
|
||||
- * handlers (except mempry_dump) from vmware_vmss.c can be reused.
|
||||
+ * handlers (except memory_dump) from vmware_vmss.c can be reused.
|
||||
*
|
||||
* debug.guest does not have a dedicated header magic or file format signature
|
||||
* To probe debug.guest we need to perform series of validations. In addition,
|
||||
@@ -225,7 +245,8 @@ is_vmware_guestdump(char *filename)
|
||||
/* vcpu_offset adjustment for mem_holes is required only for version 1. */
|
||||
vcpus_offset = get_vcpus_offset(hdr.version, mmi.mem_holes);
|
||||
} else {
|
||||
- if (fseek(fp, vcpus_offset - sizeof(struct mainmeminfo), SEEK_SET) == -1) {
|
||||
+ if (fseek(fp, vcpus_offset - sizeof(struct mainmeminfo) - get_gap2_size(hdr.version),
|
||||
+ SEEK_SET) == -1) {
|
||||
if (CRASHDEBUG(1))
|
||||
error(INFO, LOGPRX"Failed to fseek '%s': [Error %d] %s\n",
|
||||
filename, errno, strerror(errno));
|
||||
@@ -240,6 +261,25 @@ is_vmware_guestdump(char *filename)
|
||||
fclose(fp);
|
||||
return FALSE;
|
||||
}
|
||||
+
|
||||
+ /* Check CPU architecture field. Next 4 bytes after the Main Mem */
|
||||
+ if (hdr.version >= 7) {
|
||||
+ cpu_arch arch;
|
||||
+ if (fread(&arch, sizeof(cpu_arch), 1, fp) != 1) {
|
||||
+ if (CRASHDEBUG(1))
|
||||
+ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n",
|
||||
+ "CPU arch", filename, errno, strerror(errno));
|
||||
+ fclose(fp);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ if (arch != CPU_ARCH_X86) {
|
||||
+ if (CRASHDEBUG(1))
|
||||
+ error(INFO,
|
||||
+ LOGPRX"Invalid or unsupported CPU architecture: %d\n", arch);
|
||||
+ fclose(fp);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
if (fseek(fp, 0L, SEEK_END) == -1) {
|
||||
if (CRASHDEBUG(1))
|
||||
@@ -300,7 +340,7 @@ vmware_guestdump_init(char *filename, FILE *ofp)
|
||||
|
||||
if (!machine_type("X86") && !machine_type("X86_64")) {
|
||||
error(INFO,
|
||||
- LOGPRX"Invalid or unsupported host architecture for .vmss file: %s\n",
|
||||
+ LOGPRX"Invalid or unsupported host architecture for .guest file: %s\n",
|
||||
MACHINE_TYPE);
|
||||
result = FALSE;
|
||||
goto exit;
|
||||
--
|
||||
2.47.1
|
||||
|
@ -0,0 +1,53 @@
|
||||
From 145cc6a75f24dfce2e644b620b3afb6de04cadfd Mon Sep 17 00:00:00 2001
|
||||
From: Tao Liu <ltao@redhat.com>
|
||||
Date: Wed, 9 Jul 2025 17:41:12 +1200
|
||||
Subject: [PATCH 1/5] x86_64: filter unwanted warning message for "bt -T" cmd
|
||||
|
||||
After patch "x86_64: Add gdb multi-stack unwind support" applied, a
|
||||
warning message is observed for "bt -T" cmd:
|
||||
|
||||
crash> bt -T
|
||||
bt: seek error: kernel virtual address: fffffffffffffffb type: "gdb_readmem_callback"
|
||||
[ffffbaebc60d6fa8] srso_return_thunk at ffffffff82246fa5
|
||||
...
|
||||
|
||||
The root cause is, "bt -T" will set BT_TEXT_SYMBOLS_ALL for bt->flags,
|
||||
and eip is set to be 0 in kernel.c:back_trace(). Later in
|
||||
x86_64_low_budget_back_trace_cmd(), eip - 5, or 0xfffffffffffffffb is
|
||||
used for address disassembly by gdb "x/1i 0x%lx". This address is invalid so
|
||||
the warning message is output.
|
||||
|
||||
In fact, multi-stack unwind isn't designed for "bt -T" and eip = 0 case.
|
||||
To avoid the warning message, let's simply bypass the "bt -T" case for
|
||||
x86_64. Other archs(arm64/ppc64) aren't affected by the issue because
|
||||
the gdb "x/1i 0x%lx" are not applied on those archs.
|
||||
|
||||
After apply the patch:
|
||||
|
||||
crash> bt -T
|
||||
[ffffbaebc60d6fa8] srso_return_thunk at ffffffff82246fa5
|
||||
...
|
||||
|
||||
Signed-off-by: Tao Liu <ltao@redhat.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
x86_64.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/x86_64.c b/x86_64.c
|
||||
index cfefe3f80c4f..d7da536d20d8 100644
|
||||
--- a/x86_64.c
|
||||
+++ b/x86_64.c
|
||||
@@ -3636,7 +3636,8 @@ x86_64_low_budget_back_trace_cmd(struct bt_info *bt_in)
|
||||
level++;
|
||||
}
|
||||
|
||||
- if (is_task_active(bt->task) && bt->flags & BT_DUMPFILE_SEARCH) {
|
||||
+ if (is_task_active(bt->task) && bt->flags & BT_DUMPFILE_SEARCH &&
|
||||
+ !(bt->flags & BT_TEXT_SYMBOLS_ALL)) {
|
||||
if (!extra_stacks_regs[extra_stacks_idx]) {
|
||||
extra_stacks_regs[extra_stacks_idx] =
|
||||
(struct user_regs_bitmap_struct *)
|
||||
--
|
||||
2.50.0
|
||||
|
84
SOURCES/0002-Fix-incorrect-task-state-during-exit.patch
Normal file
84
SOURCES/0002-Fix-incorrect-task-state-during-exit.patch
Normal file
@ -0,0 +1,84 @@
|
||||
From 6eb51d8284aaca9cc882ddb1b9e135c708abbaa4 Mon Sep 17 00:00:00 2001
|
||||
From: Stephen Brennan <stephen.s.brennan@oracle.com>
|
||||
Date: Fri, 2 May 2025 13:18:17 -0700
|
||||
Subject: [PATCH 2/9] Fix incorrect task state during exit
|
||||
|
||||
task_state() assumes that exit_state is a unsigned long, when in
|
||||
reality, it has been declared as an int since 97dc32cdb1b53 ("reduce
|
||||
size of task_struct on 64-bit machines"), in Linux 2.6.22. So on 64-bit
|
||||
machines, task_state() reads 8 bytes rather than 4, and gets the wrong
|
||||
exit_state value by including the next field.
|
||||
|
||||
This has gone unnoticed because directly after exit_state comes
|
||||
exit_code, which is generally zero while the task is alive. When the
|
||||
exit_code is set, exit_state is usually set not long after. Since
|
||||
task_state_string() only checks whether exit_state bits are set, it
|
||||
never notices the presence of the exit code inside of the state.
|
||||
|
||||
But this leaves open a window during the process exit, when the
|
||||
exit_code has been set (in do_exit()), but the exit_state has not (in
|
||||
exit_notify()). In this case, crash reports a state of "??", but in
|
||||
reality, the task is still running -- it's just running the exit()
|
||||
system call. This race window can be long enough to be observed in core
|
||||
dumps, for example if the mmput() takes a long time.
|
||||
|
||||
This should be considered a bug. A task state of "??" or "(unknown)" is
|
||||
frequently of concern when debugging, as it could indicate that the
|
||||
state fields had some sort of corruption, and draw the attention of the
|
||||
debugger. To handle it properly, record the size of exit_state, and read
|
||||
it conditionally as a UINT or ULONG, just like the state. This ensures
|
||||
we retain compatibility with kernel before v2.6.22. Whether that is
|
||||
actually desirable is anybody's guess.
|
||||
|
||||
Reported-by: Jeffery Yoder <jeffery.yoder@oracle.com>
|
||||
Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
defs.h | 1 +
|
||||
task.c | 11 +++++++++--
|
||||
2 files changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/defs.h b/defs.h
|
||||
index 4cf169c85144..2fdb4db56a05 100644
|
||||
--- a/defs.h
|
||||
+++ b/defs.h
|
||||
@@ -2448,6 +2448,7 @@ struct size_table { /* stash of commonly-used sizes */
|
||||
long fred_frame;
|
||||
long vmap_node;
|
||||
long cpumask_t;
|
||||
+ long task_struct_exit_state;
|
||||
};
|
||||
|
||||
struct array_table {
|
||||
diff --git a/task.c b/task.c
|
||||
index 3bafe796381f..e07b479a3bec 100644
|
||||
--- a/task.c
|
||||
+++ b/task.c
|
||||
@@ -306,6 +306,7 @@ task_init(void)
|
||||
MEMBER_SIZE_INIT(task_struct_state, "task_struct", "__state");
|
||||
}
|
||||
MEMBER_OFFSET_INIT(task_struct_exit_state, "task_struct", "exit_state");
|
||||
+ MEMBER_SIZE_INIT(task_struct_exit_state, "task_struct", "exit_state");
|
||||
MEMBER_OFFSET_INIT(task_struct_pid, "task_struct", "pid");
|
||||
MEMBER_OFFSET_INIT(task_struct_comm, "task_struct", "comm");
|
||||
MEMBER_OFFSET_INIT(task_struct_next_task, "task_struct", "next_task");
|
||||
@@ -5965,8 +5966,14 @@ task_state(ulong task)
|
||||
state = ULONG(tt->task_struct + OFFSET(task_struct_state));
|
||||
else
|
||||
state = UINT(tt->task_struct + OFFSET(task_struct_state));
|
||||
- exit_state = VALID_MEMBER(task_struct_exit_state) ?
|
||||
- ULONG(tt->task_struct + OFFSET(task_struct_exit_state)) : 0;
|
||||
+
|
||||
+ if (VALID_MEMBER(task_struct_exit_state)
|
||||
+ && SIZE(task_struct_exit_state) == sizeof(ulong))
|
||||
+ exit_state = ULONG(tt->task_struct + OFFSET(task_struct_exit_state));
|
||||
+ else if (VALID_MEMBER(task_struct_exit_state))
|
||||
+ exit_state = UINT(tt->task_struct + OFFSET(task_struct_exit_state));
|
||||
+ else
|
||||
+ exit_state = 0;
|
||||
|
||||
return (state | exit_state);
|
||||
}
|
||||
--
|
||||
2.47.1
|
||||
|
@ -0,0 +1,51 @@
|
||||
From 6167a55b227db61eb52c2a4f96f44fc559a8b1d0 Mon Sep 17 00:00:00 2001
|
||||
From: Charles Haithcock <chaithco@redhat.com>
|
||||
Date: Fri, 18 Jul 2025 16:14:25 -0600
|
||||
Subject: [PATCH 2/5] doc: Update requirements for building on Fedora
|
||||
|
||||
Attempting to build on Fedora fails with the following error;
|
||||
|
||||
$ make
|
||||
TARGET: RISCV64
|
||||
CRASH: 9.0.0++
|
||||
GDB: 16.2
|
||||
|
||||
Saving 'gdb-16.2.tar.gz'
|
||||
[...]
|
||||
checking for the correct version of gmp.h... no
|
||||
configure: error: Building GDB requires GMP 4.2+, and MPFR 3.1.0+.
|
||||
Try the --with-gmp and/or --with-mpfr options to specify
|
||||
their locations. If you obtained GMP and/or MPFR from a vendor
|
||||
distribution package, make sure that you have installed both the libraries
|
||||
and the header files. They may be located in separate packages.
|
||||
make[2]: *** No targets specified and no makefile found. Stop.
|
||||
|
||||
crash build failed
|
||||
|
||||
make[1]: *** [Makefile:316: gdb_merge] Error 1
|
||||
make: *** [Makefile:307: all] Error 2
|
||||
|
||||
Installing gmp-devel and mpfr-devel fixed this, so this patch updates the
|
||||
requirements for building on Fedora.
|
||||
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
README | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/README b/README
|
||||
index 2e34fbb15f1a..f9824c7240bf 100644
|
||||
--- a/README
|
||||
+++ b/README
|
||||
@@ -73,7 +73,7 @@
|
||||
that is created in the top-level kernel build directory must be saved.
|
||||
|
||||
o Requirements for building:
|
||||
- Fedora: make gcc gcc-c++ ncurses-devel zlib-devel lzo-devel snappy-devel bison wget patch texinfo libzstd-devel
|
||||
+ Fedora: make gcc gcc-c++ ncurses-devel zlib-devel lzo-devel snappy-devel bison wget patch texinfo libzstd-devel gmp-devel mpfr-devel
|
||||
Ubuntu/Debian: make gcc g++ libncurses-dev zlib1g-dev liblzo2-dev libsnappy-dev bison wget patch texinfo libzstd-dev
|
||||
Arch Linux: make gcc ncurses zlib lzo snappy bison wget patch texinfo zstd
|
||||
openSUSE: make gcc gcc-c++ ncurses-devel zlib-devel lzo-devel snappy-devel bison wget patch texinfo libzstd-devel
|
||||
--
|
||||
2.50.0
|
||||
|
211
SOURCES/0003-Add-multi-threads-support-in-crash-target.patch
Normal file
211
SOURCES/0003-Add-multi-threads-support-in-crash-target.patch
Normal file
@ -0,0 +1,211 @@
|
||||
From 099f74640c965cd9c0e3620b9b5a0367b81a4e33 Mon Sep 17 00:00:00 2001
|
||||
From: Tao Liu <ltao@redhat.com>
|
||||
Date: Wed, 25 Jun 2025 16:01:59 +1200
|
||||
Subject: [PATCH 3/9] Add multi-threads support in crash target
|
||||
|
||||
Previously, only one thread is created in crash target by [1]. And this one
|
||||
thread will work as the common container for different tasks whenever
|
||||
"set <pid>" to it. Its tid number is 0 and will never be deleted.
|
||||
|
||||
In order to support multi-stacks, we enable multi-threads in crash
|
||||
target. Each thread will represent one stack, and "info threads" will
|
||||
list all available stacks, "thread <id>" will switch to it.
|
||||
|
||||
Since multi-stacks is task binded, each task switching will trigger
|
||||
a thread delete of those tid number other than 0. In addition, we will
|
||||
pass the tid number to each arch's get_current_task_reg(), in order to
|
||||
retrive the regs value of the specific stack.
|
||||
|
||||
[1]: https://www.mail-archive.com/devel@lists.crash-utility.osci.io/msg01085.html
|
||||
|
||||
Co-developed-by: Alexey Makhalov <alexey.makhalov@broadcom.com>
|
||||
Co-developed-by: Tao Liu <ltao@redhat.com>
|
||||
Signed-off-by: Tao Liu <ltao@redhat.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
arm64.c | 2 +-
|
||||
crash_target.c | 42 +++++++++++++++++++++++++++++++++++++++---
|
||||
defs.h | 3 ++-
|
||||
gdb_interface.c | 6 +++---
|
||||
ppc64.c | 4 ++--
|
||||
x86_64.c | 4 ++--
|
||||
6 files changed, 49 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/arm64.c b/arm64.c
|
||||
index ef4a2b8a6bef..1cdde5f12bd0 100644
|
||||
--- a/arm64.c
|
||||
+++ b/arm64.c
|
||||
@@ -204,7 +204,7 @@ out:
|
||||
|
||||
static int
|
||||
arm64_get_current_task_reg(int regno, const char *name,
|
||||
- int size, void *value)
|
||||
+ int size, void *value, int sid)
|
||||
{
|
||||
struct bt_info bt_info, bt_setup;
|
||||
struct task_context *tc;
|
||||
diff --git a/crash_target.c b/crash_target.c
|
||||
index 5966b7bb4f01..71998ef2d806 100644
|
||||
--- a/crash_target.c
|
||||
+++ b/crash_target.c
|
||||
@@ -27,8 +27,9 @@ void crash_target_init (void);
|
||||
|
||||
extern "C" int gdb_readmem_callback(unsigned long, void *, int, int);
|
||||
extern "C" int crash_get_current_task_reg (int regno, const char *regname,
|
||||
- int regsize, void *val);
|
||||
+ int regsize, void *val, int sid);
|
||||
extern "C" int gdb_change_thread_context (void);
|
||||
+extern "C" int gdb_add_substack (int);
|
||||
extern "C" void crash_get_current_task_info(unsigned long *pid, char **comm);
|
||||
|
||||
/* The crash target. */
|
||||
@@ -66,7 +67,12 @@ public:
|
||||
crash_get_current_task_info(&pid, &comm);
|
||||
return string_printf ("%ld %s", pid, comm);
|
||||
}
|
||||
-
|
||||
+ const char *extra_thread_info (thread_info *tp) override
|
||||
+ {
|
||||
+ static char buf[16] = {0};
|
||||
+ snprintf(buf, sizeof(buf), "stack %ld", tp->ptid.tid());
|
||||
+ return buf;
|
||||
+ }
|
||||
};
|
||||
|
||||
static void supply_registers(struct regcache *regcache, int regno)
|
||||
@@ -79,7 +85,7 @@ static void supply_registers(struct regcache *regcache, int regno)
|
||||
if (regsize > sizeof (regval))
|
||||
error (_("fatal error: buffer size is not enough to fit register value"));
|
||||
|
||||
- if (crash_get_current_task_reg (regno, regname, regsize, (void *)®val))
|
||||
+ if (crash_get_current_task_reg (regno, regname, regsize, (void *)®val, inferior_thread()->ptid.tid()))
|
||||
regcache->raw_supply (regno, regval);
|
||||
else
|
||||
regcache->raw_supply (regno, NULL);
|
||||
@@ -144,7 +150,37 @@ crash_target_init (void)
|
||||
extern "C" int
|
||||
gdb_change_thread_context (void)
|
||||
{
|
||||
+ /* 1st, switch to tid 0 if we are not */
|
||||
+ if (inferior_thread()->ptid.tid()) {
|
||||
+ switch_to_thread (&(current_inferior()->thread_list.front()));
|
||||
+ }
|
||||
+ /* 2nd, delete threads whose tid is not 0 */
|
||||
+ for (thread_info *tp : current_inferior()->threads_safe()) {
|
||||
+ if (tp->ptid.tid() && tp->deletable()) {
|
||||
+ delete_thread_silent(tp);
|
||||
+ current_inferior()->highest_thread_num--;
|
||||
+ }
|
||||
+ }
|
||||
+ /* 3rd, refresh regcache for tid 0 */
|
||||
target_fetch_registers(get_thread_regcache(inferior_thread()), -1);
|
||||
reinit_frame_cache();
|
||||
return TRUE;
|
||||
}
|
||||
+
|
||||
+/* Add a thread for each additional stack. Use stack ID as a thread ID */
|
||||
+extern "C" int
|
||||
+gdb_add_substack (int sid)
|
||||
+{
|
||||
+ thread_info *tp;
|
||||
+ thread_info *current_thread = inferior_thread();
|
||||
+
|
||||
+ ptid_t ptid = ptid_t(CRASH_INFERIOR_PID, 0, sid + 1);
|
||||
+ tp = current_inferior()->find_thread(ptid);
|
||||
+ if (tp == nullptr) {
|
||||
+ tp = add_thread_silent(current_inferior()->process_target(), ptid);
|
||||
+ }
|
||||
+ switch_to_thread (tp);
|
||||
+ target_fetch_registers(get_thread_regcache(tp), -1);
|
||||
+ switch_to_thread (current_thread);
|
||||
+ return TRUE;
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/defs.h b/defs.h
|
||||
index 2fdb4db56a05..bbd6d4bbf8a8 100644
|
||||
--- a/defs.h
|
||||
+++ b/defs.h
|
||||
@@ -1081,7 +1081,7 @@ struct machdep_table {
|
||||
void (*get_irq_affinity)(int);
|
||||
void (*show_interrupts)(int, ulong *);
|
||||
int (*is_page_ptr)(ulong, physaddr_t *);
|
||||
- int (*get_current_task_reg)(int, const char *, int, void *);
|
||||
+ int (*get_current_task_reg)(int, const char *, int, void *, int);
|
||||
int (*is_cpu_prstatus_valid)(int cpu);
|
||||
};
|
||||
|
||||
@@ -8324,5 +8324,6 @@ enum ppc64_regnum {
|
||||
|
||||
/* crash_target.c */
|
||||
extern int gdb_change_thread_context (void);
|
||||
+extern int gdb_add_substack (int);
|
||||
|
||||
#endif /* !GDB_COMMON */
|
||||
diff --git a/gdb_interface.c b/gdb_interface.c
|
||||
index fa2e85ba2e9c..9f76f85f341a 100644
|
||||
--- a/gdb_interface.c
|
||||
+++ b/gdb_interface.c
|
||||
@@ -1076,13 +1076,13 @@ unsigned long crash_get_kaslr_offset(void)
|
||||
|
||||
/* Callbacks for crash_target */
|
||||
int crash_get_current_task_reg (int regno, const char *regname,
|
||||
- int regsize, void *value);
|
||||
+ int regsize, void *value, int sid);
|
||||
int crash_get_current_task_reg (int regno, const char *regname,
|
||||
- int regsize, void *value)
|
||||
+ int regsize, void *value, int sid)
|
||||
{
|
||||
if (!machdep->get_current_task_reg)
|
||||
return FALSE;
|
||||
- return machdep->get_current_task_reg(regno, regname, regsize, value);
|
||||
+ return machdep->get_current_task_reg(regno, regname, regsize, value, sid);
|
||||
}
|
||||
|
||||
/* arm64 kernel lr maybe has patuh */
|
||||
diff --git a/ppc64.c b/ppc64.c
|
||||
index 782107b5b018..7ac12feaee7d 100644
|
||||
--- a/ppc64.c
|
||||
+++ b/ppc64.c
|
||||
@@ -56,7 +56,7 @@ static char * ppc64_check_eframe(struct ppc64_pt_regs *);
|
||||
static void ppc64_print_eframe(char *, struct ppc64_pt_regs *,
|
||||
struct bt_info *);
|
||||
static int ppc64_get_current_task_reg(int regno, const char *name, int size,
|
||||
- void *value);
|
||||
+ void *value, int);
|
||||
static void parse_cmdline_args(void);
|
||||
static int ppc64_paca_percpu_offset_init(int);
|
||||
static void ppc64_init_cpu_info(void);
|
||||
@@ -2512,7 +2512,7 @@ ppc64_print_eframe(char *efrm_str, struct ppc64_pt_regs *regs,
|
||||
|
||||
static int
|
||||
ppc64_get_current_task_reg(int regno, const char *name, int size,
|
||||
- void *value)
|
||||
+ void *value, int sid)
|
||||
{
|
||||
struct bt_info bt_info, bt_setup;
|
||||
struct task_context *tc;
|
||||
diff --git a/x86_64.c b/x86_64.c
|
||||
index d4bbd15d723e..a46fb9d8b72b 100644
|
||||
--- a/x86_64.c
|
||||
+++ b/x86_64.c
|
||||
@@ -126,7 +126,7 @@ 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 *);
|
||||
-static int x86_64_get_current_task_reg(int, const char *, int, void *);
|
||||
+static int x86_64_get_current_task_reg(int, const char *, int, void *, int);
|
||||
static int x86_64_verify_paddr(uint64_t);
|
||||
static void GART_init(void);
|
||||
static void x86_64_exception_stacks_init(void);
|
||||
@@ -9233,7 +9233,7 @@ x86_64_get_kvaddr_ranges(struct vaddr_range *vrp)
|
||||
|
||||
static int
|
||||
x86_64_get_current_task_reg(int regno, const char *name,
|
||||
- int size, void *value)
|
||||
+ int size, void *value, int sid)
|
||||
{
|
||||
struct bt_info bt_info, bt_setup;
|
||||
struct task_context *tc;
|
||||
--
|
||||
2.47.1
|
||||
|
@ -0,0 +1,98 @@
|
||||
From 6642b2729067399696f8f24f29267b3483d895c6 Mon Sep 17 00:00:00 2001
|
||||
From: Tao Liu <ltao@redhat.com>
|
||||
Date: Tue, 8 Jul 2025 13:26:38 +1200
|
||||
Subject: [PATCH 3/5] gdb: Fix a regression for eppic extension on gdb-16.2
|
||||
|
||||
There is a regression found when testing eppic extension on gdb-16.2
|
||||
crash:
|
||||
|
||||
crash> cgroup
|
||||
/root/.eppic/cgroup.c : line 99 : Error: undefined variable 'cgroup_roots'
|
||||
|
||||
The root cause is when doing gdb upgrading, the replacement of
|
||||
gdb_get_datatype() is incorrect:
|
||||
|
||||
The original gdb-10.2 version:
|
||||
|
||||
long value = SYMBOL_VALUE(expr->elts[2].symbol);
|
||||
|
||||
The incorrect gdb-16.2 replacement:
|
||||
|
||||
long value = value_as_long(expr->evaluate());
|
||||
|
||||
According to gdb/tracepoint.c, the correct gdb-16.2 replacement should be:
|
||||
|
||||
symbol *sym;
|
||||
expr::var_value_operation *vvop
|
||||
= (gdb::checked_static_cast<expr::var_value_operation *>
|
||||
(exp->op.get ()));
|
||||
sym = vvop->get_symbol ();
|
||||
long value = sym->value_longest ();
|
||||
|
||||
Otherwise, the value_as_long() will throw an exception when trying to
|
||||
convert a struct into long, such as "cgroup_roots". The reason why this
|
||||
issue only observed on crash extensions, is the faulty code block
|
||||
triggered with "req->tcb", which is a callback for gdb_interface(), and
|
||||
the callback is used by eppic extension, but the normal crash internal calls
|
||||
hardly use it.
|
||||
|
||||
After:
|
||||
crash> cgroup
|
||||
0:/user.slice/user-1000.slice/session-2.scope
|
||||
|
||||
Signed-off-by: Tao Liu <ltao@redhat.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
gdb-16.2.patch | 32 +++++++++++++++++++++++++++++++-
|
||||
1 file changed, 31 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb-16.2.patch b/gdb-16.2.patch
|
||||
index 151e4e2039d9..9d056580b2f7 100644
|
||||
--- a/gdb-16.2.patch
|
||||
+++ b/gdb-16.2.patch
|
||||
@@ -9,7 +9,8 @@
|
||||
# to all subsequent patch applications.
|
||||
|
||||
tar xvzmf gdb-16.2.tar.gz \
|
||||
- gdb-16.2/gdb/symfile.c
|
||||
+ gdb-16.2/gdb/symfile.c \
|
||||
+ gdb-16.2/gdb/symtab.c
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -1952,3 +1953,32 @@ exit 0
|
||||
}
|
||||
|
||||
/* Remember the bfd indexes for the .text, .data, .bss and
|
||||
+--- gdb-16.2/gdb/symtab.c.orig
|
||||
++++ gdb-16.2/gdb/symtab.c
|
||||
+@@ -7690,7 +7690,11 @@
|
||||
+ console("expr->first_opcode(): OP_VAR_VALUE\n");
|
||||
+ type = expr->evaluate_type()->type();
|
||||
+ if (req->tcb) {
|
||||
+- long value = value_as_long(expr->evaluate());
|
||||
++ expr::var_value_operation *vvop
|
||||
++ = (gdb::checked_static_cast<expr::var_value_operation *>
|
||||
++ (expr->op.get ()));
|
||||
++ sym = vvop->get_symbol ();
|
||||
++ long value = sym->value_longest ();
|
||||
+ /* callback with symbol value */
|
||||
+ req->typecode = TYPE_CODE(type);
|
||||
+ req->tcb(EOP_VALUE, req, &value, 0, 0, 0);
|
||||
+@@ -7701,8 +7705,12 @@
|
||||
+ req->length = type->length();
|
||||
+ }
|
||||
+ if (TYPE_CODE(type) == TYPE_CODE_ENUM) {
|
||||
++ expr::var_value_operation *vvop
|
||||
++ = (gdb::checked_static_cast<expr::var_value_operation *>
|
||||
++ (expr->op.get ()));
|
||||
++ sym = vvop->get_symbol ();
|
||||
+ req->typecode = TYPE_CODE(type);
|
||||
+- req->value = value_as_long(expr->evaluate());
|
||||
++ req->value = sym->value_longest ();
|
||||
+ req->tagname = (char *)TYPE_TAG_NAME(type);
|
||||
+ if (!req->tagname) {
|
||||
+ val = expr->evaluate_type();
|
||||
--
|
||||
2.50.0
|
||||
|
174
SOURCES/0004-Call-cmd_bt-silently-after-set-pid.patch
Normal file
174
SOURCES/0004-Call-cmd_bt-silently-after-set-pid.patch
Normal file
@ -0,0 +1,174 @@
|
||||
From d3ef6e456629fc5711708a88872304da5159c1c6 Mon Sep 17 00:00:00 2001
|
||||
From: Tao Liu <ltao@redhat.com>
|
||||
Date: Wed, 25 Jun 2025 16:02:00 +1200
|
||||
Subject: [PATCH 4/9] Call cmd_bt silently after "set pid"
|
||||
|
||||
Cmd bt will list multi-stacks of one task. After we "set <pid>" switch
|
||||
context to one task, we first need a bt call to detect the multi-stacks,
|
||||
however we don't want any console output from it, so a nullfp is used for
|
||||
output receive. The silent bt call is only triggered once as part of task
|
||||
context switch by cmd set.
|
||||
|
||||
A array of user_regs pointers is reserved for each supported arch. If one
|
||||
extra stack found, a user_regs structure will be allocated for storing regs
|
||||
value of the stack.
|
||||
|
||||
Co-developed-by: Alexey Makhalov <alexey.makhalov@broadcom.com>
|
||||
Co-developed-by: Tao Liu <ltao@redhat.com>
|
||||
Signed-off-by: Tao Liu <ltao@redhat.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
arm64.c | 4 ++++
|
||||
crash_target.c | 7 +++++++
|
||||
kernel.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
ppc64.c | 4 ++++
|
||||
task.c | 4 ++--
|
||||
x86_64.c | 3 +++
|
||||
6 files changed, 64 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arm64.c b/arm64.c
|
||||
index 1cdde5f12bd0..829130158902 100644
|
||||
--- a/arm64.c
|
||||
+++ b/arm64.c
|
||||
@@ -126,6 +126,10 @@ struct user_regs_bitmap_struct {
|
||||
ulong bitmap[32];
|
||||
};
|
||||
|
||||
+#define MAX_EXCEPTION_STACKS 7
|
||||
+ulong extra_stacks_idx = 0;
|
||||
+struct user_regs_bitmap_struct *extra_stacks_regs[MAX_EXCEPTION_STACKS] = {0};
|
||||
+
|
||||
static inline bool is_mte_kvaddr(ulong addr)
|
||||
{
|
||||
/* check for ARM64_MTE enabled */
|
||||
diff --git a/crash_target.c b/crash_target.c
|
||||
index 71998ef2d806..ad1480c9188f 100644
|
||||
--- a/crash_target.c
|
||||
+++ b/crash_target.c
|
||||
@@ -31,6 +31,9 @@ extern "C" int crash_get_current_task_reg (int regno, const char *regname,
|
||||
extern "C" int gdb_change_thread_context (void);
|
||||
extern "C" int gdb_add_substack (int);
|
||||
extern "C" void crash_get_current_task_info(unsigned long *pid, char **comm);
|
||||
+#if defined (X86_64) || defined (ARM64) || defined (PPC64)
|
||||
+extern "C" void silent_call_bt(void);
|
||||
+#endif
|
||||
|
||||
/* The crash target. */
|
||||
|
||||
@@ -164,6 +167,10 @@ gdb_change_thread_context (void)
|
||||
/* 3rd, refresh regcache for tid 0 */
|
||||
target_fetch_registers(get_thread_regcache(inferior_thread()), -1);
|
||||
reinit_frame_cache();
|
||||
+#if defined (X86_64) || defined (ARM64) || defined (PPC64)
|
||||
+ /* 4th, invoke bt silently to refresh the additional stacks */
|
||||
+ silent_call_bt();
|
||||
+#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
diff --git a/kernel.c b/kernel.c
|
||||
index b8d3b7999974..e4213d7a663e 100644
|
||||
--- a/kernel.c
|
||||
+++ b/kernel.c
|
||||
@@ -12002,3 +12002,47 @@ int get_linux_banner_from_vmlinux(char *buf, size_t size)
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
+
|
||||
+#if defined(X86_64) || defined(ARM64) || defined(PPC64)
|
||||
+extern ulong extra_stacks_idx;
|
||||
+extern void *extra_stacks_regs[];
|
||||
+void silent_call_bt(void);
|
||||
+void silent_call_bt(void)
|
||||
+{
|
||||
+ jmp_buf main_loop_env_save;
|
||||
+ unsigned long long flags_save = pc->flags;
|
||||
+ FILE *fp_save = fp;
|
||||
+ FILE *error_fp_save = pc->error_fp;
|
||||
+ /* Redirect all cmd_bt() outputs into null */
|
||||
+ fp = pc->nullfp;
|
||||
+ pc->error_fp = pc->nullfp;
|
||||
+
|
||||
+ for (int i = 0; i < extra_stacks_idx; i++) {
|
||||
+ /* Note: GETBUF/FREEBUF is not applicable for extra_stacks_regs,
|
||||
+ because we are reserving extra_stacks_regs by cmd_bt()
|
||||
+ for later use. But GETBUF/FREEBUF is designed for use only
|
||||
+ within one cmd. See process_command_line() -> restore_sanity()
|
||||
+ -> free_all_bufs(). So we use malloc/free instead. */
|
||||
+ free(extra_stacks_regs[i]);
|
||||
+ extra_stacks_regs[i] = NULL;
|
||||
+ }
|
||||
+ /* Prepare args used by cmd_bt() */
|
||||
+ sprintf(pc->command_line, "bt\n");
|
||||
+ argcnt = parse_line(pc->command_line, args);
|
||||
+ optind = 1;
|
||||
+ pc->flags |= RUNTIME;
|
||||
+
|
||||
+ /* Catch error FATAL generated by cmd_bt() if any */
|
||||
+ memcpy(&main_loop_env_save, &pc->main_loop_env, sizeof(jmp_buf));
|
||||
+ if (setjmp(pc->main_loop_env)) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+ cmd_bt();
|
||||
+out:
|
||||
+ /* Restore all */
|
||||
+ memcpy(&pc->main_loop_env, &main_loop_env_save, sizeof(jmp_buf));
|
||||
+ pc->flags = flags_save;
|
||||
+ fp = fp_save;
|
||||
+ pc->error_fp = error_fp_save;
|
||||
+}
|
||||
+#endif
|
||||
diff --git a/ppc64.c b/ppc64.c
|
||||
index 7ac12feaee7d..532eb3fe4a7e 100644
|
||||
--- a/ppc64.c
|
||||
+++ b/ppc64.c
|
||||
@@ -80,6 +80,10 @@ struct user_regs_bitmap_struct {
|
||||
ulong bitmap[32];
|
||||
};
|
||||
|
||||
+#define MAX_EXCEPTION_STACKS 7
|
||||
+ulong extra_stacks_idx = 0;
|
||||
+struct user_regs_bitmap_struct *extra_stacks_regs[MAX_EXCEPTION_STACKS] = {0};
|
||||
+
|
||||
static int is_opal_context(ulong sp, ulong nip)
|
||||
{
|
||||
uint64_t opal_start, opal_end;
|
||||
diff --git a/task.c b/task.c
|
||||
index e07b479a3bec..ec04b556c337 100644
|
||||
--- a/task.c
|
||||
+++ b/task.c
|
||||
@@ -3062,7 +3062,7 @@ sort_context_array(void)
|
||||
curtask = CURRENT_TASK();
|
||||
qsort((void *)tt->context_array, (size_t)tt->running_tasks,
|
||||
sizeof(struct task_context), sort_by_pid);
|
||||
- set_context(curtask, NO_PID, TRUE);
|
||||
+ set_context(curtask, NO_PID, FALSE);
|
||||
|
||||
sort_context_by_task();
|
||||
}
|
||||
@@ -3109,7 +3109,7 @@ sort_context_array_by_last_run(void)
|
||||
curtask = CURRENT_TASK();
|
||||
qsort((void *)tt->context_array, (size_t)tt->running_tasks,
|
||||
sizeof(struct task_context), sort_by_last_run);
|
||||
- set_context(curtask, NO_PID, TRUE);
|
||||
+ set_context(curtask, NO_PID, FALSE);
|
||||
|
||||
sort_context_by_task();
|
||||
}
|
||||
diff --git a/x86_64.c b/x86_64.c
|
||||
index a46fb9d8b72b..ee23d8b5e41e 100644
|
||||
--- a/x86_64.c
|
||||
+++ b/x86_64.c
|
||||
@@ -160,6 +160,9 @@ struct user_regs_bitmap_struct {
|
||||
ulong bitmap[32];
|
||||
};
|
||||
|
||||
+ulong extra_stacks_idx = 0;
|
||||
+struct user_regs_bitmap_struct *extra_stacks_regs[MAX_EXCEPTION_STACKS] = {0};
|
||||
+
|
||||
/*
|
||||
* Do all necessary machine-specific setup here. This is called several
|
||||
* times during initialization.
|
||||
--
|
||||
2.47.1
|
||||
|
@ -0,0 +1,42 @@
|
||||
From 31a69d378efb4319a5b9ef8cf3d7a93030f5c863 Mon Sep 17 00:00:00 2001
|
||||
From: Ming Wang <wangming01@loongson.cn>
|
||||
Date: Mon, 9 Jun 2025 11:03:02 +0800
|
||||
Subject: [PATCH 4/5] Fix crash initialization failure on LoongArch with recent
|
||||
GDB versions
|
||||
|
||||
The crash tool failed to initialize on LoongArch64 when using
|
||||
GDB 16.2 (and likely other recent GDB versions that have enhanced
|
||||
LoongArch support) due to the error:
|
||||
"fatal error: buffer size is not enough to fit register value".
|
||||
|
||||
This occurs in supply_registers() because GDB now correctly
|
||||
reports the size of LoongArch LASX (256-bit) vector registers
|
||||
(xr0-xr31) as 32 bytes. The `regval` buffer in `crash_target.c`
|
||||
was previously fixed at 16 bytes.
|
||||
|
||||
This patch increases the `regval` buffer size to 32 bytes to
|
||||
accommodate the largest LoongArch registers reported by GDB.
|
||||
This allows crash to initialize successfully.
|
||||
|
||||
Signed-off-by: Ming Wang <wangming01@loongson.cn>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
crash_target.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/crash_target.c b/crash_target.c
|
||||
index ad1480c9188f..49c6e88c5140 100644
|
||||
--- a/crash_target.c
|
||||
+++ b/crash_target.c
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
|
||||
static void supply_registers(struct regcache *regcache, int regno)
|
||||
{
|
||||
- gdb_byte regval[16];
|
||||
+ gdb_byte regval[32];
|
||||
struct gdbarch *arch = regcache->arch ();
|
||||
const char *regname = gdbarch_register_name(arch, regno);
|
||||
int regsize = register_size(arch, regno);
|
||||
--
|
||||
2.50.0
|
||||
|
@ -0,0 +1,93 @@
|
||||
From 2c69f93e59c6b2efac5bae9f7891dbe1e0094fdd Mon Sep 17 00:00:00 2001
|
||||
From: Shivang Upadhyay <shivangu@linux.ibm.com>
|
||||
Date: Mon, 21 Jul 2025 13:47:33 +0530
|
||||
Subject: [PATCH 5/5] gdb: Disable DT_DEBUG lookup by GDB inside the vmcore
|
||||
|
||||
Crash with GDB 16.2, the following warnings are printed:
|
||||
|
||||
crash>
|
||||
crash: page excluded: kernel virtual address: c0000000022d6098 type: "gdb_readmem_callback"
|
||||
crash: page excluded: kernel virtual address: c0000000022d6098 type: "gdb_readmem_callback"
|
||||
|
||||
This occurs because the elf_locate_base function in GDB 16.2
|
||||
attempts to read the address of the dynamic linker runtime
|
||||
structure, which is present in the .dynamic section of the
|
||||
executable. However, this section may be excluded from the
|
||||
dump by makedumpfile.
|
||||
|
||||
The repeated calls to elf_locate_base were introduced by gdb
|
||||
commit [1] aebb370 ("gdb, solib-svr4: support namespaces in
|
||||
DSO iteration") via svr4_iterate_over_objfiles_in_search_order.
|
||||
|
||||
To check whether the kernel includes DT_DEBUG information,
|
||||
prints were added inside crash::xfer_partial, which is
|
||||
called through elf_locate_base when reading from vmcore.
|
||||
Even when running crash on /proc/kcore, all output data was
|
||||
zero. This confirms that DT_DEBUG information is never
|
||||
present in the kernel image.
|
||||
|
||||
`mod -S` continues to function correctly after the following
|
||||
patch:
|
||||
|
||||
...
|
||||
crash> mod -S
|
||||
Enable debuginfod for this session? (y or [n])
|
||||
MODULE NAME TEXT_BASE SIZE OBJECT FILE
|
||||
c0080000004a0300 dm_log c008000000480000 196608 XXX/lib/modules/5.14.0-592.el9.ppc64le/kernel/drivers/md/dm-log.ko
|
||||
c0080000006d1100 sd_mod c008000000580000 196608 XXX/lib/modules/5.14.0-592.el9.ppc64le/kernel/drivers/scsi/sd_mod.ko
|
||||
c0080000005c0080 dm_region_hash c0080000005a0000 196608 XXX/lib/modules/5.14.0-592.el9.ppc64le/kernel/drivers/md/dm-region-hash.ko
|
||||
c008000000770700 sg c008000000620000 262144 XXX/lib/modules/5.14.0-592.el9.ppc64le/kernel/drivers/scsi/sg.ko
|
||||
c008000000660500 dm_mirror c008000000640000 196608 XXX/lib/modules/5.14.0-592.el9.ppc64le/kernel/drivers/md/dm-mirror.ko
|
||||
...
|
||||
|
||||
Commit e906eaca2b1a ("Fix the issue of "page excluded"
|
||||
messages flooding") attempted fix this by suppressing these
|
||||
warnings for regular users, but the warnings still appear
|
||||
when crash is started in debug mode.
|
||||
|
||||
To fix this, remove the DT_DEBUG read call, from the
|
||||
elf_locate_base function in GDB that tries to read the
|
||||
.dynamic section, as this information is not useful for
|
||||
debugging kernel images in either dump or live kernel
|
||||
scenarios.
|
||||
|
||||
[1] https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=aebb370
|
||||
|
||||
Cc: Tao liu <ltao@redhat.com>
|
||||
Cc: Lianbo Jiang <lijiang@redhat.com>
|
||||
Cc: Sourabh Jain <sourabhjain@linux.ibm.com>
|
||||
Signed-off-by: shivang.upadhyay <shivangu@linux.ibm.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
gdb-16.2.patch | 18 ++++++++++++++++++
|
||||
1 file changed, 18 insertions(+)
|
||||
|
||||
diff --git a/gdb-16.2.patch b/gdb-16.2.patch
|
||||
index 9d056580b2f7..6767bf7d7bf0 100644
|
||||
--- a/gdb-16.2.patch
|
||||
+++ b/gdb-16.2.patch
|
||||
@@ -1982,3 +1982,21 @@ exit 0
|
||||
req->tagname = (char *)TYPE_TAG_NAME(type);
|
||||
if (!req->tagname) {
|
||||
val = expr->evaluate_type();
|
||||
+--- gdb-16.2/gdb/solib-svr4.c.orig
|
||||
++++ gdb-16.2/gdb/solib-svr4.c
|
||||
+@@ -741,13 +741,13 @@
|
||||
+ return 0;
|
||||
+ return extract_typed_address (pbuf, ptr_type);
|
||||
+ }
|
||||
+-
|
||||
++#ifndef CRASH_MERGE
|
||||
+ /* Find DT_DEBUG. */
|
||||
+ if (gdb_bfd_scan_elf_dyntag (DT_DEBUG, current_program_space->exec_bfd (),
|
||||
+ &dyn_ptr, NULL)
|
||||
+ || scan_dyntag_auxv (DT_DEBUG, &dyn_ptr, NULL))
|
||||
+ return dyn_ptr;
|
||||
+-
|
||||
++#endif
|
||||
+ /* This may be a static executable. Look for the symbol
|
||||
+ conventionally named _r_debug, as a last resort. */
|
||||
+ bound_minimal_symbol msymbol
|
||||
--
|
||||
2.50.0
|
||||
|
237
SOURCES/0005-x86_64-Add-gdb-multi-stack-unwind-support.patch
Normal file
237
SOURCES/0005-x86_64-Add-gdb-multi-stack-unwind-support.patch
Normal file
@ -0,0 +1,237 @@
|
||||
From 7b488818107fff9f92e9778749d0046f2024e6af Mon Sep 17 00:00:00 2001
|
||||
From: Tao Liu <ltao@redhat.com>
|
||||
Date: Wed, 25 Jun 2025 16:02:01 +1200
|
||||
Subject: [PATCH 5/9] x86_64: Add gdb multi-stack unwind support
|
||||
|
||||
Whenever extra stack is found, a user_regs structure is allocated and
|
||||
regs value copied there. Later the values will be retrived by
|
||||
get_current_task_reg() by given the thread's tid, aka the index of
|
||||
stack.
|
||||
|
||||
Co-developed-by: Alexey Makhalov <alexey.makhalov@broadcom.com>
|
||||
Co-developed-by: Tao Liu <ltao@redhat.com>
|
||||
Signed-off-by: Tao Liu <ltao@redhat.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
x86_64.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 125 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/x86_64.c b/x86_64.c
|
||||
index ee23d8b5e41e..cfefe3f80c4f 100644
|
||||
--- a/x86_64.c
|
||||
+++ b/x86_64.c
|
||||
@@ -3508,6 +3508,8 @@ x86_64_exception_RIP_message(struct bt_info *bt, ulong rip)
|
||||
#define STACK_TRANSITION_ERRMSG_I_P \
|
||||
"cannot transition from IRQ stack to current process stack:\n IRQ stack pointer: %lx\n process stack pointer: %lx\n current stack base: %lx\n"
|
||||
|
||||
+#define SET_REG_BITMAP(REGMAP, TYPE, MEMBER) \
|
||||
+ SET_BIT(REGMAP, REG_SEQ(TYPE, MEMBER))
|
||||
/*
|
||||
* Low-budget back tracer -- dump text return addresses, following call chain
|
||||
* when possible, along with any verifiable exception frames.
|
||||
@@ -3528,6 +3530,7 @@ x86_64_low_budget_back_trace_cmd(struct bt_info *bt_in)
|
||||
ulong last_process_stack_eframe;
|
||||
ulong user_mode_eframe;
|
||||
char *rip_symbol;
|
||||
+ char buf[BUFSIZE];
|
||||
|
||||
/*
|
||||
* User may have made a run-time switch.
|
||||
@@ -3551,6 +3554,7 @@ x86_64_low_budget_back_trace_cmd(struct bt_info *bt_in)
|
||||
irq_eframe = 0;
|
||||
last_process_stack_eframe = 0;
|
||||
bt->call_target = NULL;
|
||||
+ extra_stacks_idx = 0;
|
||||
rsp = bt->stkptr;
|
||||
ms = machdep->machspec;
|
||||
|
||||
@@ -3632,6 +3636,90 @@ x86_64_low_budget_back_trace_cmd(struct bt_info *bt_in)
|
||||
level++;
|
||||
}
|
||||
|
||||
+ if (is_task_active(bt->task) && bt->flags & BT_DUMPFILE_SEARCH) {
|
||||
+ if (!extra_stacks_regs[extra_stacks_idx]) {
|
||||
+ extra_stacks_regs[extra_stacks_idx] =
|
||||
+ (struct user_regs_bitmap_struct *)
|
||||
+ malloc(sizeof(struct user_regs_bitmap_struct));
|
||||
+ }
|
||||
+ memset(extra_stacks_regs[extra_stacks_idx], 0,
|
||||
+ sizeof(struct user_regs_bitmap_struct));
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.ip = bt->instptr;
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.sp = bt->stkptr + 8;
|
||||
+ SET_REG_BITMAP(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ x86_64_user_regs_struct, ip);
|
||||
+ SET_REG_BITMAP(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ x86_64_user_regs_struct, sp);
|
||||
+
|
||||
+ /* Sometimes bp is needed for stack unwinding, so we try to get
|
||||
+ it. The bt->instptr usually points to a inst after a call
|
||||
+ inst, let's check the previous call inst. Note the call inst
|
||||
+ len is 5 */
|
||||
+ open_tmpfile2();
|
||||
+ sprintf(buf, "x/1i 0x%lx", bt->instptr - 5);
|
||||
+ gdb_pass_through(buf, pc->tmpfile2, GNU_RETURN_ON_ERROR);
|
||||
+ rewind(pc->tmpfile2);
|
||||
+ fgets(buf, BUFSIZE, pc->tmpfile2);
|
||||
+ if (strstr(buf, "call")) {
|
||||
+ if (strstr(buf, "<relocate_range>") ||
|
||||
+ strstr(buf, "<relocate_kernel>")) {
|
||||
+ /* OK, we are calling relocate_kernel(), which
|
||||
+ * is written in assembly and hasn't changed for
|
||||
+ * years, so we get some extra regs out of it. */
|
||||
+ readmem(bt->stkptr - sizeof(ulong) * 6, KVADDR, buf,
|
||||
+ sizeof(ulong) * 6, "relocate_kernel", FAULT_ON_ERROR);
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.r15 =
|
||||
+ *(ulong *)(buf + sizeof(ulong) * 0);
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.r14 =
|
||||
+ *(ulong *)(buf + sizeof(ulong) * 1);
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.r13 =
|
||||
+ *(ulong *)(buf + sizeof(ulong) * 2);
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.r12 =
|
||||
+ *(ulong *)(buf + sizeof(ulong) * 3);
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.bp =
|
||||
+ *(ulong *)(buf + sizeof(ulong) * 4);
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.bx =
|
||||
+ *(ulong *)(buf + sizeof(ulong) * 5);
|
||||
+ SET_REG_BITMAP(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ x86_64_user_regs_struct, r15);
|
||||
+ SET_REG_BITMAP(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ x86_64_user_regs_struct, r14);
|
||||
+ SET_REG_BITMAP(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ x86_64_user_regs_struct, r13);
|
||||
+ SET_REG_BITMAP(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ x86_64_user_regs_struct, r12);
|
||||
+ SET_REG_BITMAP(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ x86_64_user_regs_struct, bp);
|
||||
+ SET_REG_BITMAP(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ x86_64_user_regs_struct, bx);
|
||||
+ } else {
|
||||
+ /* This is a try-best effort. Usually the call
|
||||
+ inst will result in a next-inst addr pushed
|
||||
+ in and a rbp push of the calling function.
|
||||
+ So we can get rbp here */
|
||||
+ readmem(extra_stacks_regs[extra_stacks_idx]->ur.sp
|
||||
+ - sizeof(ulong) * 2, KVADDR,
|
||||
+ &extra_stacks_regs[extra_stacks_idx]->ur.bp,
|
||||
+ sizeof(ulong), "extra_stacks_regs.bp", FAULT_ON_ERROR);
|
||||
+ if (INSTACK(extra_stacks_regs[extra_stacks_idx]->ur.bp, bt)) {
|
||||
+ SET_REG_BITMAP(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ x86_64_user_regs_struct, bp);
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.ip -= 5;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ close_tmpfile2();
|
||||
+ /*
|
||||
+ * bt->machdep is handled at x86_64_get_stack_frame(), so skip it
|
||||
+ */
|
||||
+ if (!bt->machdep ||
|
||||
+ (extra_stacks_regs[extra_stacks_idx]->ur.sp !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.ip !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.ip)) {
|
||||
+ gdb_add_substack(extra_stacks_idx++);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
if ((estack = x86_64_in_exception_stack(bt, &estack_index))) {
|
||||
in_exception_stack:
|
||||
@@ -4159,6 +4247,7 @@ x86_64_dwarf_back_trace_cmd(struct bt_info *bt_in)
|
||||
last_process_stack_eframe = 0;
|
||||
bt->call_target = NULL;
|
||||
bt->bptr = 0;
|
||||
+ extra_stacks_idx = 0;
|
||||
rsp = bt->stkptr;
|
||||
if (!rsp) {
|
||||
error(INFO, "cannot determine starting stack pointer\n");
|
||||
@@ -4799,6 +4888,31 @@ x86_64_exception_frame(ulong flags, ulong kvaddr, char *local,
|
||||
} else if (machdep->flags & ORC)
|
||||
bt->bptr = rbp;
|
||||
|
||||
+ /*
|
||||
+ * Preserve registers set for each additional in-kernel stack
|
||||
+ */
|
||||
+ if (!(cs & 3) && verified && flags & EFRAME_PRINT &&
|
||||
+ extra_stacks_idx < MAX_EXCEPTION_STACKS &&
|
||||
+ !(bt->flags & BT_EFRAME_SEARCH)) {
|
||||
+ if (!extra_stacks_regs[extra_stacks_idx]) {
|
||||
+ extra_stacks_regs[extra_stacks_idx] = (struct user_regs_bitmap_struct *)
|
||||
+ malloc(sizeof(struct user_regs_bitmap_struct));
|
||||
+ }
|
||||
+ memset(extra_stacks_regs[extra_stacks_idx], 0,
|
||||
+ sizeof(struct user_regs_bitmap_struct));
|
||||
+ memcpy(&extra_stacks_regs[extra_stacks_idx]->ur,
|
||||
+ pt_regs_buf, SIZE(pt_regs));
|
||||
+ for (int i = 0; i < SIZE(pt_regs)/sizeof(long); i++)
|
||||
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap, i);
|
||||
+ if (!bt->machdep ||
|
||||
+ (extra_stacks_regs[extra_stacks_idx]->ur.sp !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.ip !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.ip)) {
|
||||
+ gdb_add_substack(extra_stacks_idx++);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (kvaddr)
|
||||
FREEBUF(pt_regs_buf);
|
||||
|
||||
@@ -5002,9 +5116,6 @@ get_reg_from_inactive_task_frame(struct bt_info *bt, char *reg_name,
|
||||
return reg_value;
|
||||
}
|
||||
|
||||
-#define SET_REG_BITMAP(REGMAP, TYPE, MEMBER) \
|
||||
- SET_BIT(REGMAP, REG_SEQ(TYPE, MEMBER))
|
||||
-
|
||||
/*
|
||||
* Get a stack frame combination of pc and ra from the most relevent spot.
|
||||
*/
|
||||
@@ -9221,7 +9332,8 @@ x86_64_get_kvaddr_ranges(struct vaddr_range *vrp)
|
||||
case R##_REGNUM: \
|
||||
if (!NUM_IN_BITMAP(ur_bitmap->bitmap, \
|
||||
REG_SEQ(x86_64_user_regs_struct, r))) { \
|
||||
- FREEBUF(ur_bitmap); \
|
||||
+ if (!sid) \
|
||||
+ FREEBUF(ur_bitmap); \
|
||||
return FALSE; \
|
||||
} \
|
||||
break;
|
||||
@@ -9256,6 +9368,12 @@ x86_64_get_current_task_reg(int regno, const char *name,
|
||||
if (!tc)
|
||||
return FALSE;
|
||||
|
||||
+ /* Non zero stack ID, use extra stacks regs */
|
||||
+ if (sid && sid <= extra_stacks_idx) {
|
||||
+ ur_bitmap = extra_stacks_regs[sid - 1];
|
||||
+ goto get_sub;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* Task is active, grab CPU's registers
|
||||
*/
|
||||
@@ -9280,6 +9398,7 @@ x86_64_get_current_task_reg(int regno, const char *name,
|
||||
}
|
||||
|
||||
/* Get subset registers from stack frame*/
|
||||
+get_sub:
|
||||
switch (regno) {
|
||||
CHECK_REG_CASE(RAX, ax);
|
||||
CHECK_REG_CASE(RBX, bx);
|
||||
@@ -9341,7 +9460,7 @@ get_all:
|
||||
COPY_REG_CASE(ORIG_RAX, orig_ax);
|
||||
}
|
||||
|
||||
- if (bt_info.need_free) {
|
||||
+ if (!sid && bt_info.need_free) {
|
||||
FREEBUF(ur_bitmap);
|
||||
bt_info.need_free = FALSE;
|
||||
}
|
||||
@@ -9805,4 +9924,4 @@ x86_64_swp_offset(ulong entry)
|
||||
return SWP_OFFSET(entry);
|
||||
}
|
||||
|
||||
-#endif /* X86_64 */
|
||||
+#endif /* X86_64 */
|
||||
--
|
||||
2.47.1
|
||||
|
181
SOURCES/0006-arm64-Add-gdb-multi-stack-unwind-support.patch
Normal file
181
SOURCES/0006-arm64-Add-gdb-multi-stack-unwind-support.patch
Normal file
@ -0,0 +1,181 @@
|
||||
From 08271e45e4ea6263fc2957d1e876becd6cfc1a0d Mon Sep 17 00:00:00 2001
|
||||
From: Tao Liu <ltao@redhat.com>
|
||||
Date: Wed, 25 Jun 2025 16:02:02 +1200
|
||||
Subject: [PATCH 6/9] arm64: Add gdb multi-stack unwind support
|
||||
|
||||
Co-developed-by: Alexey Makhalov <alexey.makhalov@broadcom.com>
|
||||
Co-developed-by: Tao Liu <ltao@redhat.com>
|
||||
Signed-off-by: Tao Liu <ltao@redhat.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
arm64.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 92 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arm64.c b/arm64.c
|
||||
index 829130158902..354d17ab6a19 100644
|
||||
--- a/arm64.c
|
||||
+++ b/arm64.c
|
||||
@@ -226,6 +226,12 @@ arm64_get_current_task_reg(int regno, const char *name,
|
||||
tc = CURRENT_CONTEXT();
|
||||
if (!tc)
|
||||
return FALSE;
|
||||
+
|
||||
+ if (sid && sid <= extra_stacks_idx) {
|
||||
+ ur_bitmap = extra_stacks_regs[extra_stacks_idx - 1];
|
||||
+ goto get_sub;
|
||||
+ }
|
||||
+
|
||||
BZERO(&bt_setup, sizeof(struct bt_info));
|
||||
clone_bt_info(&bt_setup, &bt_info, tc);
|
||||
fill_stackbuf(&bt_info);
|
||||
@@ -241,25 +247,29 @@ arm64_get_current_task_reg(int regno, const char *name,
|
||||
goto get_all;
|
||||
}
|
||||
|
||||
+get_sub:
|
||||
switch (regno) {
|
||||
case X0_REGNUM ... X30_REGNUM:
|
||||
if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
|
||||
REG_SEQ(arm64_pt_regs, regs[0]) + regno - X0_REGNUM)) {
|
||||
- FREEBUF(ur_bitmap);
|
||||
+ if (!sid)
|
||||
+ FREEBUF(ur_bitmap);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case SP_REGNUM:
|
||||
if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
|
||||
REG_SEQ(arm64_pt_regs, sp))) {
|
||||
- FREEBUF(ur_bitmap);
|
||||
+ if (!sid)
|
||||
+ FREEBUF(ur_bitmap);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case PC_REGNUM:
|
||||
if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
|
||||
REG_SEQ(arm64_pt_regs, pc))) {
|
||||
- FREEBUF(ur_bitmap);
|
||||
+ if (!sid)
|
||||
+ FREEBUF(ur_bitmap);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
@@ -287,7 +297,7 @@ get_all:
|
||||
break;
|
||||
}
|
||||
|
||||
- if (bt_info.need_free) {
|
||||
+ if (!sid && bt_info.need_free) {
|
||||
FREEBUF(ur_bitmap);
|
||||
bt_info.need_free = FALSE;
|
||||
}
|
||||
@@ -3680,6 +3690,7 @@ arm64_back_trace_cmd(struct bt_info *bt)
|
||||
int level;
|
||||
ulong exception_frame;
|
||||
FILE *ofp;
|
||||
+ extra_stacks_idx = 0;
|
||||
|
||||
if (bt->flags & BT_OPT_BACK_TRACE) {
|
||||
if (machdep->flags & UNW_4_14) {
|
||||
@@ -3733,6 +3744,35 @@ arm64_back_trace_cmd(struct bt_info *bt)
|
||||
stackframe.fp = bt->frameptr;
|
||||
}
|
||||
|
||||
+ if (is_task_active(bt->task)) {
|
||||
+ if (!extra_stacks_regs[extra_stacks_idx]) {
|
||||
+ extra_stacks_regs[extra_stacks_idx] = (struct user_regs_bitmap_struct *)
|
||||
+ malloc(sizeof(struct user_regs_bitmap_struct));
|
||||
+ }
|
||||
+ memset(extra_stacks_regs[extra_stacks_idx], 0,
|
||||
+ sizeof(struct user_regs_bitmap_struct));
|
||||
+ if (bt->task != tt->panic_task && stackframe.sp) {
|
||||
+ readmem(stackframe.sp - 8, KVADDR, &extra_stacks_regs[extra_stacks_idx]->ur.pc,
|
||||
+ sizeof(ulong), "extra_stacks_regs.pc", RETURN_ON_ERROR);
|
||||
+ readmem(stackframe.sp - 16, KVADDR, &extra_stacks_regs[extra_stacks_idx]->ur.sp,
|
||||
+ sizeof(ulong), "extra_stacks_regs.sp", RETURN_ON_ERROR);
|
||||
+ } else {
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.pc = stackframe.pc;
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.sp = stackframe.sp;
|
||||
+ }
|
||||
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ REG_SEQ(arm64_pt_regs, pc));
|
||||
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ REG_SEQ(arm64_pt_regs, sp));
|
||||
+ if (!bt->machdep ||
|
||||
+ (extra_stacks_regs[extra_stacks_idx]->ur.sp !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.pc !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc)) {
|
||||
+ gdb_add_substack (extra_stacks_idx++);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (bt->flags & BT_TEXT_SYMBOLS) {
|
||||
arm64_print_text_symbols(bt, &stackframe, ofp);
|
||||
if (BT_REFERENCE_FOUND(bt)) {
|
||||
@@ -3854,6 +3894,35 @@ arm64_back_trace_cmd_v2(struct bt_info *bt)
|
||||
stackframe.fp = bt->frameptr;
|
||||
}
|
||||
|
||||
+ if (is_task_active(bt->task)) {
|
||||
+ if (!extra_stacks_regs[extra_stacks_idx]) {
|
||||
+ extra_stacks_regs[extra_stacks_idx] = (struct user_regs_bitmap_struct *)
|
||||
+ malloc(sizeof(struct user_regs_bitmap_struct));
|
||||
+ }
|
||||
+ memset(extra_stacks_regs[extra_stacks_idx], 0,
|
||||
+ sizeof(struct user_regs_bitmap_struct));
|
||||
+ if (bt->task != tt->panic_task && stackframe.sp) {
|
||||
+ readmem(stackframe.sp - 8, KVADDR, &extra_stacks_regs[extra_stacks_idx]->ur.pc,
|
||||
+ sizeof(ulong), "extra_stacks_regs.pc", RETURN_ON_ERROR);
|
||||
+ readmem(stackframe.sp - 16, KVADDR, &extra_stacks_regs[extra_stacks_idx]->ur.sp,
|
||||
+ sizeof(ulong), "extra_stacks_regs.sp", RETURN_ON_ERROR);
|
||||
+ } else {
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.pc = stackframe.pc;
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.sp = stackframe.sp;
|
||||
+ }
|
||||
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ REG_SEQ(arm64_pt_regs, pc));
|
||||
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ REG_SEQ(arm64_pt_regs, sp));
|
||||
+ if (!bt->machdep ||
|
||||
+ (extra_stacks_regs[extra_stacks_idx]->ur.sp !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.pc !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc)) {
|
||||
+ gdb_add_substack (extra_stacks_idx++);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (bt->flags & BT_TEXT_SYMBOLS) {
|
||||
arm64_print_text_symbols(bt, &stackframe, ofp);
|
||||
if (BT_REFERENCE_FOUND(bt)) {
|
||||
@@ -4468,6 +4537,25 @@ arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int mode, FILE *o
|
||||
fprintf(ofp, "ORIG_X0: %016lx SYSCALLNO: %lx",
|
||||
(ulong)regs->orig_x0, (ulong)regs->syscallno);
|
||||
fprintf(ofp, " PSTATE: %08lx\n", (ulong)regs->pstate);
|
||||
+ } else if (!(bt->flags & BT_EFRAME_SEARCH)) {
|
||||
+ if (!extra_stacks_regs[extra_stacks_idx]) {
|
||||
+ extra_stacks_regs[extra_stacks_idx] =
|
||||
+ (struct user_regs_bitmap_struct *)
|
||||
+ malloc(sizeof(struct user_regs_bitmap_struct));
|
||||
+ }
|
||||
+ memset(extra_stacks_regs[extra_stacks_idx], 0,
|
||||
+ sizeof(struct user_regs_bitmap_struct));
|
||||
+ memcpy(&extra_stacks_regs[extra_stacks_idx]->ur, regs,
|
||||
+ sizeof(struct arm64_pt_regs));
|
||||
+ for (int i = 0; i < sizeof(struct arm64_pt_regs)/sizeof(long); i++)
|
||||
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap, i);
|
||||
+ if (!bt->machdep ||
|
||||
+ (extra_stacks_regs[extra_stacks_idx]->ur.sp !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.pc !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc)) {
|
||||
+ gdb_add_substack (extra_stacks_idx++);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.47.1
|
||||
|
180
SOURCES/0007-ppc64-Add-gdb-multi-stack-unwind-support.patch
Normal file
180
SOURCES/0007-ppc64-Add-gdb-multi-stack-unwind-support.patch
Normal file
@ -0,0 +1,180 @@
|
||||
From 0c14080b7d7bacadba3611568bd87b347677fa12 Mon Sep 17 00:00:00 2001
|
||||
From: Tao Liu <ltao@redhat.com>
|
||||
Date: Wed, 25 Jun 2025 16:02:03 +1200
|
||||
Subject: [PATCH 7/9] ppc64: Add gdb multi-stack unwind support
|
||||
|
||||
Please note, there is a known issue which some ppc cannot stack unwind
|
||||
successfully as:
|
||||
|
||||
crash> bt
|
||||
PID: 2 TASK: c000000004797f80 CPU: 0 COMMAND: "kthreadd"
|
||||
#0 [c00000000484fbc0] _end at c00000000484fd70 (unreliable)
|
||||
#1 [c00000000484fd70] __switch_to at c00000000001fabc
|
||||
#2 [c00000000484fdd0] __schedule at c0000000011ca9dc
|
||||
#3 [c00000000484feb0] schedule at c0000000011caeb0
|
||||
#4 [c00000000484ff20] kthreadd at c0000000001af6c4
|
||||
#5 [c00000000484ffe0] start_kernel_thread at c00000000000ded8
|
||||
crash> gdb bt
|
||||
#0 0xc00000000484fd70 in ?? ()
|
||||
gdb: gdb request failed: bt
|
||||
|
||||
This has nothing to do with bt/gdb bt, see root cause in [1][2].
|
||||
|
||||
[1]: https://www.mail-archive.com/devel@lists.crash-utility.osci.io/msg01124.html
|
||||
[2]: https://www.mail-archive.com/devel@lists.crash-utility.osci.io/msg01139.html
|
||||
|
||||
Co-developed-by: Alexey Makhalov <alexey.makhalov@broadcom.com>
|
||||
Co-developed-by: Tao Liu <ltao@redhat.com>
|
||||
Signed-off-by: Tao Liu <ltao@redhat.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
ppc64.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 64 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/ppc64.c b/ppc64.c
|
||||
index 532eb3fe4a7e..d1a506773c93 100644
|
||||
--- a/ppc64.c
|
||||
+++ b/ppc64.c
|
||||
@@ -2053,6 +2053,7 @@ ppc64_back_trace_cmd(struct bt_info *bt)
|
||||
char buf[BUFSIZE];
|
||||
struct gnu_request *req;
|
||||
extern void print_stack_text_syms(struct bt_info *, ulong, ulong);
|
||||
+ extra_stacks_idx = 0;
|
||||
|
||||
bt->flags |= BT_EXCEPTION_FRAME;
|
||||
|
||||
@@ -2071,6 +2072,29 @@ ppc64_back_trace_cmd(struct bt_info *bt)
|
||||
req->pc = bt->instptr;
|
||||
req->sp = bt->stkptr;
|
||||
|
||||
+ if (is_task_active(bt->task)) {
|
||||
+ if (!extra_stacks_regs[extra_stacks_idx]) {
|
||||
+ extra_stacks_regs[extra_stacks_idx] =
|
||||
+ (struct user_regs_bitmap_struct *)
|
||||
+ malloc(sizeof(struct user_regs_bitmap_struct));
|
||||
+ }
|
||||
+ memset(extra_stacks_regs[extra_stacks_idx], 0,
|
||||
+ sizeof(struct user_regs_bitmap_struct));
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.nip = req->pc;
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.gpr[1] = req->sp;
|
||||
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ REG_SEQ(ppc64_pt_regs, nip));
|
||||
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
|
||||
+ REG_SEQ(ppc64_pt_regs, gpr[0]) + 1);
|
||||
+ if (!bt->machdep ||
|
||||
+ (extra_stacks_regs[extra_stacks_idx]->ur.gpr[1] !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.gpr[1] &&
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.nip !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.nip)) {
|
||||
+ gdb_add_substack (extra_stacks_idx++);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (bt->flags &
|
||||
(BT_TEXT_SYMBOLS|BT_TEXT_SYMBOLS_PRINT|BT_TEXT_SYMBOLS_NOPRINT)) {
|
||||
if (!INSTACK(req->sp, bt))
|
||||
@@ -2512,6 +2536,28 @@ ppc64_print_eframe(char *efrm_str, struct ppc64_pt_regs *regs,
|
||||
fprintf(fp, " %s [%lx] exception frame:\n", efrm_str, regs->trap);
|
||||
ppc64_print_regs(regs);
|
||||
ppc64_print_nip_lr(regs, 1);
|
||||
+
|
||||
+ if (!((regs->msr >> MSR_PR_LG) & 0x1) &&
|
||||
+ !(bt->flags & BT_EFRAME_SEARCH)) {
|
||||
+ if (!extra_stacks_regs[extra_stacks_idx]) {
|
||||
+ extra_stacks_regs[extra_stacks_idx] =
|
||||
+ (struct user_regs_bitmap_struct *)
|
||||
+ malloc(sizeof(struct user_regs_bitmap_struct));
|
||||
+ }
|
||||
+ memset(extra_stacks_regs[extra_stacks_idx], 0,
|
||||
+ sizeof(struct user_regs_bitmap_struct));
|
||||
+ memcpy(&extra_stacks_regs[extra_stacks_idx]->ur, regs,
|
||||
+ sizeof(struct ppc64_pt_regs));
|
||||
+ for (int i = 0; i < sizeof(struct ppc64_pt_regs)/sizeof(ulong); i++)
|
||||
+ SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap, i);
|
||||
+ if (!bt->machdep ||
|
||||
+ (extra_stacks_regs[extra_stacks_idx]->ur.gpr[1] !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.gpr[1] &&
|
||||
+ extra_stacks_regs[extra_stacks_idx]->ur.nip !=
|
||||
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.nip)) {
|
||||
+ gdb_add_substack (extra_stacks_idx++);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -2552,6 +2598,12 @@ ppc64_get_current_task_reg(int regno, const char *name, int size,
|
||||
tc = CURRENT_CONTEXT();
|
||||
if (!tc)
|
||||
return FALSE;
|
||||
+
|
||||
+ if (sid && sid <= extra_stacks_idx) {
|
||||
+ ur_bitmap = extra_stacks_regs[sid - 1];
|
||||
+ goto get_sub;
|
||||
+ }
|
||||
+
|
||||
BZERO(&bt_setup, sizeof(struct bt_info));
|
||||
clone_bt_info(&bt_setup, &bt_info, tc);
|
||||
fill_stackbuf(&bt_info);
|
||||
@@ -2570,39 +2622,45 @@ ppc64_get_current_task_reg(int regno, const char *name, int size,
|
||||
goto get_all;
|
||||
}
|
||||
|
||||
+get_sub:
|
||||
switch (regno) {
|
||||
case PPC64_R0_REGNUM ... PPC64_R31_REGNUM:
|
||||
if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
|
||||
REG_SEQ(ppc64_pt_regs, gpr[0]) + regno - PPC64_R0_REGNUM)) {
|
||||
- FREEBUF(ur_bitmap);
|
||||
+ if (!sid)
|
||||
+ FREEBUF(ur_bitmap);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case PPC64_PC_REGNUM:
|
||||
if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
|
||||
REG_SEQ(ppc64_pt_regs, nip))) {
|
||||
- FREEBUF(ur_bitmap);
|
||||
+ if (!sid)
|
||||
+ FREEBUF(ur_bitmap);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case PPC64_MSR_REGNUM:
|
||||
if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
|
||||
REG_SEQ(ppc64_pt_regs, msr))) {
|
||||
- FREEBUF(ur_bitmap);
|
||||
+ if (!sid)
|
||||
+ FREEBUF(ur_bitmap);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case PPC64_LR_REGNUM:
|
||||
if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
|
||||
REG_SEQ(ppc64_pt_regs, link))) {
|
||||
- FREEBUF(ur_bitmap);
|
||||
+ if (!sid)
|
||||
+ FREEBUF(ur_bitmap);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case PPC64_CTR_REGNUM:
|
||||
if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
|
||||
REG_SEQ(ppc64_pt_regs, ctr))) {
|
||||
- FREEBUF(ur_bitmap);
|
||||
+ if (!sid)
|
||||
+ FREEBUF(ur_bitmap);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
@@ -2645,7 +2703,7 @@ get_all:
|
||||
ret = TRUE;
|
||||
break;
|
||||
}
|
||||
- if (bt_info.need_free) {
|
||||
+ if (!sid && bt_info.need_free) {
|
||||
FREEBUF(ur_bitmap);
|
||||
bt_info.need_free = FALSE;
|
||||
}
|
||||
--
|
||||
2.47.1
|
||||
|
@ -0,0 +1,42 @@
|
||||
From e906eaca2b1a77fe9f8ba512484b4e914c303f11 Mon Sep 17 00:00:00 2001
|
||||
From: Lianbo Jiang <lijiang@redhat.com>
|
||||
Date: Wed, 11 Jun 2025 11:19:01 +0800
|
||||
Subject: [PATCH 8/9] Fix the issue of "page excluded" messages flooding
|
||||
|
||||
The current issue is only observed on PPC64le machine when loading crash,
|
||||
E.g:
|
||||
...
|
||||
crash: page excluded: kernel virtual address: c0000000022d6098 type: "gdb_readmem_callback"
|
||||
crash: page excluded: kernel virtual address: c0000000022d6098 type: "gdb_readmem_callback"
|
||||
...
|
||||
crash>
|
||||
|
||||
And this issue can not be reproduced on crash 8, which only occurred
|
||||
after the gdb-16.2 upgrade(see commit dfb2bb55e530).
|
||||
|
||||
So far I haven't found out why it always reads the same address(excluded
|
||||
page) many times, anyway, crash tool should avoid flooding messages firstly,
|
||||
similarly let's use the same debug level(8) such as the read_diskdump()(see
|
||||
diskdump.c).
|
||||
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
memory.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/memory.c b/memory.c
|
||||
index 0d8d89862383..58624bb5f44c 100644
|
||||
--- a/memory.c
|
||||
+++ b/memory.c
|
||||
@@ -2504,7 +2504,7 @@ readmem(ulonglong addr, int memtype, void *buffer, long size,
|
||||
|
||||
case PAGE_EXCLUDED:
|
||||
RETURN_ON_PARTIAL_READ();
|
||||
- if (PRINT_ERROR_MESSAGE)
|
||||
+ if (CRASHDEBUG(8))
|
||||
error(INFO, PAGE_EXCLUDED_ERRMSG, memtype_string(memtype, 0), addr, type);
|
||||
goto readmem_error;
|
||||
|
||||
--
|
||||
2.47.1
|
||||
|
@ -0,0 +1,35 @@
|
||||
From 7e8a2796580d992ed19b2e49b5d555e432303e96 Mon Sep 17 00:00:00 2001
|
||||
From: "k-hagio-ab@nec.com" <k-hagio-ab@nec.com>
|
||||
Date: Tue, 17 Jun 2025 06:08:52 +0000
|
||||
Subject: [PATCH 9/9] Fix "kmem -p" option on Linux 6.16-rc1 and later kernels
|
||||
|
||||
Kernel commit acc53a0b4c156 ("mm: rename page->index to
|
||||
page->__folio_index"), which is contained in Linux 6.16-rc1 and later
|
||||
kernels, renamed the member. Without the patch, the "kmem -p" option
|
||||
fails with the following error:
|
||||
|
||||
kmem: invalid structure member offset: page_index
|
||||
FILE: memory.c LINE: 6016 FUNCTION: dump_mem_map_SPARSEMEM()
|
||||
|
||||
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
|
||||
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||||
---
|
||||
memory.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/memory.c b/memory.c
|
||||
index 58624bb5f44c..400d31a04cd4 100644
|
||||
--- a/memory.c
|
||||
+++ b/memory.c
|
||||
@@ -531,6 +531,8 @@ vm_init(void)
|
||||
ASSIGN_OFFSET(page_mapping) = MEMBER_OFFSET("page", "_mapcount") +
|
||||
STRUCT_SIZE("atomic_t") + sizeof(ulong);
|
||||
MEMBER_OFFSET_INIT(page_index, "page", "index");
|
||||
+ if (INVALID_MEMBER(page_index)) /* 6.16 and later */
|
||||
+ MEMBER_OFFSET_INIT(page_index, "page", "__folio_index");
|
||||
if (INVALID_MEMBER(page_index))
|
||||
ANON_MEMBER_OFFSET_INIT(page_index, "page", "index");
|
||||
MEMBER_OFFSET_INIT(page_buffers, "page", "buffers");
|
||||
--
|
||||
2.47.1
|
||||
|
@ -1,5 +1,5 @@
|
||||
--- crash-8.0.6/Makefile.orig
|
||||
+++ crash-8.0.6/Makefile
|
||||
--- crash-9.0.0/Makefile.orig
|
||||
+++ crash-9.0.0/Makefile
|
||||
@@ -204,7 +204,7 @@ GDB_FLAGS=
|
||||
# TARGET_CFLAGS will be configured automatically by configure
|
||||
TARGET_CFLAGS=
|
||||
@ -18,8 +18,8 @@
|
||||
@echo "../../${PROGRAM} ../../${PROGRAM}lib.a" > ${GDB}/gdb/mergeobj
|
||||
@rm -f ${PROGRAM}
|
||||
@if [ ! -f ${GDB}/config.status ]; then \
|
||||
--- crash-8.0.6/configure.c.orig
|
||||
+++ crash-8.0.6/configure.c
|
||||
--- crash-9.0.0/configure.c.orig
|
||||
+++ crash-9.0.0/configure.c
|
||||
@@ -810,7 +810,8 @@ build_configure(struct supported_gdb_version *sp)
|
||||
fprintf(fp2, "%s\n", sp->GDB);
|
||||
sprintf(target_data.gdb_version, "%s", &sp->GDB[4]);
|
@ -1,5 +1,5 @@
|
||||
--- crash-8.0.6/Makefile.orig
|
||||
+++ crash-8.0.6/Makefile
|
||||
--- crash-9.0.0/Makefile.orig
|
||||
+++ crash-9.0.0/Makefile
|
||||
@@ -256,7 +256,7 @@ all: make_configure
|
||||
gdb_merge: force
|
||||
@if [ ! -f ${GDB}/README ]; then \
|
||||
@ -9,8 +9,8 @@
|
||||
@echo "../../${PROGRAM} ../../${PROGRAM}lib.a" > ${GDB}/gdb/mergeobj
|
||||
@rm -f ${PROGRAM}
|
||||
@if [ ! -f ${GDB}/config.status ]; then \
|
||||
--- crash-8.0.6/diskdump.c.orig
|
||||
+++ crash-8.0.6/diskdump.c
|
||||
--- crash-9.0.0/diskdump.c.orig
|
||||
+++ crash-9.0.0/diskdump.c
|
||||
@@ -23,6 +23,9 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
@ -3,22 +3,37 @@
|
||||
#
|
||||
Summary: Kernel analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles
|
||||
Name: crash
|
||||
Version: 8.0.6
|
||||
Release: 1%{?dist}
|
||||
Version: 9.0.0
|
||||
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
|
||||
Source1: http://ftp.gnu.org/gnu/gdb/gdb-16.2.tar.gz
|
||||
URL: https://crash-utility.github.io
|
||||
ExclusiveOS: Linux
|
||||
ExclusiveArch: %{ix86} ia64 x86_64 ppc ppc64 s390 s390x %{arm} aarch64 ppc64le
|
||||
BuildRequires: ncurses-devel zlib-devel lzo-devel snappy-devel bison texinfo libzstd-devel
|
||||
BuildRequires: gcc gcc-c++
|
||||
BuildRequires: make
|
||||
BuildRequires: make gcc gcc-c++
|
||||
BuildRequires: gmp-devel mpfr-devel
|
||||
Requires: binutils
|
||||
Provides: bundled(libiberty)
|
||||
Provides: bundled(gdb) = 10.2
|
||||
Provides: bundled(gdb) = 16.2
|
||||
Patch0: lzo_snappy_zstd.patch
|
||||
Patch1: crash-8.0.6_build.patch
|
||||
Patch1: crash-9.0.0_build.patch
|
||||
Patch2: 0001-vmware_guestdump-Version-7-support.patch
|
||||
Patch3: 0002-Fix-incorrect-task-state-during-exit.patch
|
||||
Patch4: 0003-Add-multi-threads-support-in-crash-target.patch
|
||||
Patch5: 0004-Call-cmd_bt-silently-after-set-pid.patch
|
||||
Patch6: 0005-x86_64-Add-gdb-multi-stack-unwind-support.patch
|
||||
Patch7: 0006-arm64-Add-gdb-multi-stack-unwind-support.patch
|
||||
Patch8: 0007-ppc64-Add-gdb-multi-stack-unwind-support.patch
|
||||
Patch9: 0008-Fix-the-issue-of-page-excluded-messages-flooding.patch
|
||||
Patch10: 0009-Fix-kmem-p-option-on-Linux-6.16-rc1-and-later-kernel.patch
|
||||
Patch11: 0001-x86_64-filter-unwanted-warning-message-for-bt-T-cmd.patch
|
||||
Patch12: 0002-doc-Update-requirements-for-building-on-Fedora.patch
|
||||
Patch13: 0003-gdb-Fix-a-regression-for-eppic-extension-on-gdb-16.2.patch
|
||||
Patch14: 0004-Fix-crash-initialization-failure-on-LoongArch-with-r.patch
|
||||
Patch15: 0005-gdb-Disable-DT_DEBUG-lookup-by-GDB-inside-the-vmcore.patch
|
||||
Patch16: 0001-Add-blk_mq-shared-tags-support-for-dev-d-D.patch
|
||||
|
||||
%description
|
||||
The core analysis suite is a self-contained tool that can be used to
|
||||
@ -39,7 +54,22 @@ offered by Mission Critical Linux, or the LKCD kernel patch.
|
||||
%prep
|
||||
%setup -n %{name}-%{version} -q
|
||||
%patch -P 0 -p1 -b lzo_snappy_zstd.patch
|
||||
%patch -P 1 -p1 -b crash-8.0.6_build.patch
|
||||
%patch -P 1 -p1 -b crash-9.0.0_build.patch
|
||||
%patch -P 2 -p1
|
||||
%patch -P 3 -p1
|
||||
%patch -P 4 -p1
|
||||
%patch -P 5 -p1
|
||||
%patch -P 6 -p1
|
||||
%patch -P 7 -p1
|
||||
%patch -P 8 -p1
|
||||
%patch -P 9 -p1
|
||||
%patch -P 10 -p1
|
||||
%patch -P 11 -p1
|
||||
%patch -P 12 -p1
|
||||
%patch -P 13 -p1
|
||||
%patch -P 14 -p1
|
||||
%patch -P 15 -p1
|
||||
%patch -P 16 -p1
|
||||
|
||||
%build
|
||||
|
||||
@ -65,6 +95,30 @@ cp -p defs.h %{buildroot}%{_includedir}/crash
|
||||
%{_includedir}/*
|
||||
|
||||
%changelog
|
||||
* Wed Aug 6 2025 Tao Liu <ltao@redhat.com> - 9.0.0-4
|
||||
- Add blk_mq shared tags support for dev -d/-D
|
||||
|
||||
* Mon Jul 28 2025 Lianbo Jiang <lijiang@redhat.com> - 9.0.0-3
|
||||
- x86_64: filter unwanted warning message for "bt -T" cmd
|
||||
- doc: Update requirements for building on Fedora
|
||||
- gdb: Fix a regression for eppic extension on gdb-16.2
|
||||
- Fix crash initialization failure on LoongArch with recent GDB versions
|
||||
- gdb: Disable DT_DEBUG lookup by GDB inside the vmcore
|
||||
|
||||
* Tue Jul 01 2025 Lianbo Jiang <lijiang@redhat.com> - 9.0.0-2
|
||||
- vmware_guestdump: Version 7 support
|
||||
- Fix incorrect task state during exit
|
||||
- Add multi-threads support in crash target
|
||||
- Call cmd_bt silently after "set pid"
|
||||
- x86_64: Add gdb multi-stack unwind support
|
||||
- arm64: Add gdb multi-stack unwind support
|
||||
- ppc64: Add gdb multi-stack unwind support
|
||||
- Fix the issue of "page excluded" messages flooding
|
||||
- Fix "kmem -p" option on Linux 6.16-rc1 and later kernels
|
||||
|
||||
* Mon Apr 28 2025 Lianbo Jiang <lijiang@redhat.com> - 9.0.0-1
|
||||
- Rebase to upstream crash 9.0.0
|
||||
|
||||
* Thu Nov 14 2024 Lianbo Jiang <lijiang@redhat.com> - 8.0.6-1
|
||||
- Rebase to upstream crash 8.0.6
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user