[PATCH RFC][makedumpfile 00/10] btf/kallsyms based eppic extension for mm page filtering
by Tao Liu
A) This patchset will introduce the following features to makedumpfile:
1) Enable eppic script for memory pages filtering.
2) Enable btf and kallsyms for symbol type and address resolving.
3) Port maple tree data structures and functions, primarily used for
vma iteration.
B) The purpose of the features are:
1) Currently makedumpfile filters mm pages based on page flags, because flags
can help to determine one page's usage. But this page-flag-checking method
lacks of flexibility in certain cases, e.g. if we want to filter those mm
pages occupied by GPU during vmcore dumping due to:
a) GPU may be taking a large memory and contains sensitive data;
b) GPU mm pages have no relations to kernel crash and useless for vmcore
analysis.
But there is no GPU mm page specific flags, and apparently we don't need
to create one just for kdump use. A programmable filtering tool is more
suitable for such cases. In addition, different GPU vendors may use
different ways for mm pages allocating, programmable filtering is better
than hard coding these GPU specific logics into makedumpfile in this case.
2) Currently makedumpfile already contains a programmable filtering tool, aka
eppic script, which allows user to write customized code for data erasing.
However it has the following drawbacks:
a) cannot do mm page filtering.
b) need to access to debuginfo of both kernel and modules, which is not
applicable in the 2nd kernel.
c) Poor performance, making vmcore dumping time unacceptable (See
the following performance testing).
makedumpfile need to resolve the dwarf data from debuginfo, to get symbols
types and addresses. In recent kernel there are dwarf alternatives such
as btf/kallsyms which can be used for this purpose. And btf/kallsyms info
are already packed within vmcore, so we can use it directly.
3) Maple tree data structures are used in recent kernels, such as vma
iteration. So maple tree poring is needed.
With these, this patchset introduces an upgraded eppic, which is based on
btf/kallsyms symbol resolving, and is programmable for mm page filtering.
The following info shows its usage and performance, please note the tests
are performed in 1st kernel:
$ time ./makedumpfile -d 31 -l /var/crash/127.0.0.1-2025-06-10-18\:03\:12/vmcore
/tmp/dwarf.out -x /lib/debug/lib/modules/6.11.8-300.fc41.x86_64/vmlinux
--eppic eppic_scripts/filter_amdgpu_mm_pages.c
real 14m6.894s
user 4m16.900s
sys 9m44.695s
$ time ./makedumpfile -d 31 -l /var/crash/127.0.0.1-2025-06-10-18\:03\:12/vmcore
/tmp/btf.out --eppic eppic_scripts/filter_amdgpu_mm_pages.c
real 0m10.672s
user 0m9.270s
sys 0m1.130s
-rw------- 1 root root 367475074 Jun 10 18:06 btf.out
-rw------- 1 root root 367475074 Jun 10 21:05 dwarf.out
-rw-rw-rw- 1 root root 387181418 Jun 10 18:03 /var/crash/127.0.0.1-2025-06-10-18:03:12/vmcore
C) Discussion:
1) GPU types: Currently only tested with amdgpu's mm page filtering, others
are not tested.
2) Code structure: There are some similar code shared by makedumpfile and
crash, such as maple tree data structure, also I planed to port the
btf/kallsyms code to crash as well, so there are code duplications for
crash & makedumpfile. Since I havn't working on crash poring, code change
on btf/kallsyms is expected. How can we share the code, creating a common
library or keep the duplication as it is?
3) OS: The code can work on rhel-10+/rhel9.5+ on x86_64/arm64/s390/ppc64.
Others are not tested.
D) Testing:
1) If you don't want to create your vmcore, you can find a vmcore which I
created with amdgpu mm pages unfiltered [1], the amdgpu mm pages are
allocated by program [2]. You can use the vmcore in 1st kernel to filter
the amdgpu mm pages by the previous performance testing cmdline. To
verify the pages are filtered in crash:
Unfiltered:
crash> search -c "!QAZXSW@#EDC"
ffff96b7fa800000: !QAZXSW@#EDCXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
ffff96b87c800000: !QAZXSW@#EDCXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
crash> rd ffff96b7fa800000
ffff96b7fa800000: 405753585a415121 !QAZXSW@
crash> rd ffff96b87c800000
ffff96b87c800000: 405753585a415121 !QAZXSW@
Filtered:
crash> search -c "!QAZXSW@#EDC"
crash> rd ffff96b7fa800000
rd: page excluded: kernel virtual address: ffff96b7fa800000 type: "64-bit KVADDR"
crash> rd ffff96b87c800000
rd: page excluded: kernel virtual address: ffff96b87c800000 type: "64-bit KVADDR"
2) You can use eppic_scripts/print_all_vma.c against an ordinary vmcore to
test only btf/kallsyms functions by output all VMAs if no amdgpu
vmcores/machine avaliable.
[1]: https://people.redhat.com/~ltao/core/
[2]: https://gist.github.com/liutgnu/a8cbce1c666452f1530e1410d1f352df
Tao Liu (10):
dwarf_info: Support kernel address randomization
dwarf_info: Fix a infinite recursion bug for search_domain
Add page filtering function
Add btf/kallsyms support for symbol type/address resolving
Export necessary btf/kallsyms functions to eppic extension
Port the maple tree data structures and functions
Supporting main() as the entry of eppic script
Enable page filtering for dwarf eppic
Enable page filtering for btf/kallsyms eppic
Introducing 2 eppic scripts to test the dwarf/btf eppic extension
Makefile | 6 +-
btf.c | 919 +++++++++++++++++++++++++
btf.h | 176 +++++
dwarf_info.c | 15 +-
eppic_maple.c | 431 ++++++++++++
eppic_maple.h | 8 +
eppic_scripts/filter_amdgpu_mm_pages.c | 36 +
eppic_scripts/print_all_vma.c | 29 +
erase_info.c | 123 +++-
erase_info.h | 22 +
extension_btf.c | 218 ++++++
extension_eppic.c | 41 +-
extension_eppic.h | 6 +-
kallsyms.c | 371 ++++++++++
kallsyms.h | 42 ++
makedumpfile.c | 21 +-
makedumpfile.h | 11 +
17 files changed, 2448 insertions(+), 27 deletions(-)
create mode 100644 btf.c
create mode 100644 btf.h
create mode 100644 eppic_maple.c
create mode 100644 eppic_maple.h
create mode 100644 eppic_scripts/filter_amdgpu_mm_pages.c
create mode 100644 eppic_scripts/print_all_vma.c
create mode 100644 extension_btf.c
create mode 100644 kallsyms.c
create mode 100644 kallsyms.h
--
2.47.0
1 week
[PATCH] Support running on X86_64 with RISCV target
by Pnina Feder
Signed-off-by: Pnina Feder <pnina.feder(a)mobileye.com>
---
symbols.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/symbols.c b/symbols.c
index e30fafe..5b42ecf 100644
--- a/symbols.c
+++ b/symbols.c
@@ -4539,7 +4539,7 @@ is_shared_object(char *file)
case EM_X86_64:
if (machine_type("X86_64") || machine_type("ARM64") ||
- machine_type("PPC64"))
+ machine_type("PPC64") || machine_type("RISCV64"))
return TRUE;
break;
--
2.43.0
1 week, 5 days
Re: [PATCH] Revert "Fix the issue of "page excluded" messages flooding"
by lijiang
On Tue, Jul 29, 2025 at 10:33 AM Shivang Upadhyay <shivangu(a)linux.ibm.com>
wrote:
> This reverts commit e906eaca2b1a77fe9f8ba512484b4e914c303f11.
>
>
Please do not revert this one, I added the reason in patch log, and see the
read_diskdump():
if (!page_is_dumpable(pfn)) {
if ((dd->flags & (ZERO_EXCLUDED|ERROR_EXCLUDED)) ==
ERROR_EXCLUDED) {
if (CRASHDEBUG(8))
fprintf(fp, "read_diskdump: PAGE_EXCLUDED: "
"paddr/pfn: %llx/%lx\n",
(ulonglong)paddr, pfn);
return PAGE_EXCLUDED;
}
if (CRASHDEBUG(8))
fprintf(fp, "read_diskdump: zero-fill: "
"paddr/pfn: %llx/%lx\n",
(ulonglong)paddr, pfn);
memset(bufptr, 0, cnt);
return cnt;
}
For debugging, we can set debug 8 to identify issues.
Thanks
Lianbo
> This above commit adjusted the log level of the missing page warning to
> a debug levels only. However, these log can be useful in identifying
> issues with dump-generating tools like makedumpfile. This revert will
> increase their visibility back to normal.
>
> The underlying issue was resolved by commit 2c69f93 ("gdb: disable
> dt_debug lookup by gdb inside the vmcore").
>
> Cc: Lianbo Jiang <lijiang(a)redhat.com>
> Cc: Sourabh Jain <sourabhjain(a)linux.ibm.com>
> Signed-off-by: Shivang Upadhyay <shivangu(a)linux.ibm.com>
> ---
> memory.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/memory.c b/memory.c
> index 400d31a..5cb8b58 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -2506,7 +2506,7 @@ readmem(ulonglong addr, int memtype, void *buffer,
> long size,
>
> case PAGE_EXCLUDED:
> RETURN_ON_PARTIAL_READ();
> - if (CRASHDEBUG(8))
> + if (PRINT_ERROR_MESSAGE)
> error(INFO, PAGE_EXCLUDED_ERRMSG,
> memtype_string(memtype, 0), addr, type);
> goto readmem_error;
>
> --
> 2.50.0
>
>
2 weeks
[PATCH RFC] help: Add 'help -l' to show memory layout
by Rongwei Wang
From: Rongwei Wang <rongwei.wrw(a)gmail.com>
'help -m' can show most of variables which
relates to memory layout, e.g. userspace_top,
page_offset, vmalloc_start_addr, etc. They
aren't a visual way to show a memory layout
for kernel space.
This patch provides 'help -l' to show memory
layout in a table-based way, usage likes:
crash> help -l
+---------------------------------------------------------+
|xxxxxxxxxxxxxxxxxxx gap (size: 8.0 MB) xxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
+---------------------------------------------------------+
| FIXMAP |
| (0xffffffffff578000 - 0xffffffffff7ff000 size: 2.5 MB) |
+---------------------------------------------------------+
|xxxxxxxxxxxxxxxxxxx gap (size: 5.5 MB) xxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
+---------------------------------------------------------+
| Module Area |
| (0xffffffffa0000000 - 0xffffffffff000000 size: 1.5 GB) |
+---------------------------------------------------------+
|xxxxxxxxxxxxxxxxxx gap (size: 451.9 MB) xxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
+---------------------------------------------------------+
| kernel image |
| (0xffffffff81000000 - 0xffffffff83c26000 size: 44.1 MB) |
+---------------------------------------------------------+
|xxxxxxxxxxxxxxxxxx gap (size: 21.0 TB) xxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
+---------------------------------------------------------+
| Vmemmap Area |
| (0xffffea0000000000 - 0xffffeaffffffffff size: 1.0 TB) |
+---------------------------------------------------------+
|xxxxxxxxxxxxxxxxxxx gap (size: 1.0 TB) xxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
+---------------------------------------------------------+
| Vmalloc/Vfree Area |
| (0xffffc90000000000 - 0xffffe8ffffffffff size: 32.0 TB) |
+---------------------------------------------------------+
|xxxxxxxxxxxxxxxxxx gap (size: 512.0 GB) xxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
+---------------------------------------------------------+
| Linear Mapping Area |
| (0xffff888000000000 - 0xffffc87fffffffff size: 64.0 TB) |
+---------------------------------------------------------+
| Kernel Space Offset |
| (0xffff800000000000 - 0xffff887fffffffff size: 8.5 TB) |
+---------------------------------------------------------+
|xxxxxxxxxxxxxxx gap (size: 16776960.0 TB) xxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
+---------------------------------------------------------+
| User Space |
| (size: 128.0 TB) |
+---------------------------------------------------------+
Signed-off-by: Rongwei Wang <rongwei.wrw(a)gmail.com>
---
defs.h | 14 +-
help.c | 7 +-
memory.c | 11 ++
x86_64.c | 388 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 418 insertions(+), 2 deletions(-)
diff --git a/defs.h b/defs.h
index bbd6d4b..66b1c8e 100644
--- a/defs.h
+++ b/defs.h
@@ -4097,12 +4097,23 @@ typedef signed int s32;
#define __PHYSICAL_MASK_SHIFT_5LEVEL 52
#define __PHYSICAL_MASK_SHIFT (machdep->machspec->physical_mask_shift)
#define __PHYSICAL_MASK ((1UL << __PHYSICAL_MASK_SHIFT) - 1)
-#define __VIRTUAL_MASK_SHIFT 48
+#define __VIRTUAL_MASK_SHIFT 47
#define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1)
#define PAGE_SHIFT 12
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PHYSICAL_PAGE_MASK (~(PAGE_SIZE-1) & __PHYSICAL_MASK )
+
+#define KASAN_SHADOW_OFFSET 0xdffffc0000000000
+#define KASAN_SHADOW_SCALE_SHIFT 3
+
+#define KASAN_SHADOW_START (KASAN_SHADOW_OFFSET + \
+ ((-1UL << __VIRTUAL_MASK_SHIFT) >> \
+ KASAN_SHADOW_SCALE_SHIFT))
+#define KASAN_SHADOW_END (KASAN_SHADOW_START + \
+ (1ULL << (__VIRTUAL_MASK_SHIFT - \
+ KASAN_SHADOW_SCALE_SHIFT)))
+
#define _PAGE_BIT_NX 63
#define _PAGE_PRESENT 0x001
#define _PAGE_RW 0x002
@@ -5908,6 +5919,7 @@ int phys_to_page(physaddr_t, ulong *);
int generic_get_kvaddr_ranges(struct vaddr_range *);
int l1_cache_size(void);
int dumpfile_memory(int);
+void dump_memory_layout(void);
#define DUMPFILE_MEM_USED (1)
#define DUMPFILE_FREE_MEM (2)
#define DUMPFILE_MEM_DUMP (3)
diff --git a/help.c b/help.c
index 5d61e0d..cd54744 100644
--- a/help.c
+++ b/help.c
@@ -538,7 +538,7 @@ cmd_help(void)
oflag = 0;
while ((c = getopt(argcnt, args,
- "efNDdmM:ngcaBbHhkKsvVoptTzLOr")) != EOF) {
+ "efNDdmM:ngcaBbHhkKsvVoptTzLOrl")) != EOF) {
switch(c)
{
case 'e':
@@ -666,6 +666,7 @@ cmd_help(void)
fprintf(fp, " -v - vm_table\n");
fprintf(fp, " -V - vm_table (verbose)\n");
fprintf(fp, " -z - help options\n");
+ fprintf(fp, " -l - show memory layout\n");
return;
case 'L':
@@ -676,6 +677,10 @@ cmd_help(void)
dump_registers();
return;
+ case 'l':
+ dump_memory_layout();
+ return;
+
default:
argerrs++;
break;
diff --git a/memory.c b/memory.c
index 400d31a..55ed2f1 100644
--- a/memory.c
+++ b/memory.c
@@ -17657,6 +17657,17 @@ dumpfile_memory(int cmd)
return retval;
}
+#ifdef X86_64
+extern void x86_64_dump_memory_layout(void);
+#endif
+
+void dump_memory_layout(void)
+{
+#ifdef X86_64
+ x86_64_dump_memory_layout();
+#endif
+}
+
/*
* Functions for sparse mem support
*/
diff --git a/x86_64.c b/x86_64.c
index d7da536..b4d2821 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -1151,6 +1151,394 @@ x86_64_dump_machdep_table(ulong arg)
fprintf(fp, "excpetion_functions_orig\n");
}
+#define MAX_LAYOUT 32
+#define MAX_COL_LAYOUT 60
+struct mem_segment {
+ char name[64];
+ char desc[128];
+ unsigned long start;
+ unsigned long end;
+ int width;
+ char fill_char;
+};
+
+struct mem_layout {
+ int count;
+ int capacity;
+ struct mem_segment segs[MAX_LAYOUT];
+};
+
+char* format_bytes(unsigned long bytes, char* buffer, int buffer_size)
+{
+ const char* units[] = {"B", "KB", "MB", "GB", "TB"};
+ int i = 0;
+ double readable_size = (double)bytes;
+
+ /* Handle the edge case of zero bytes */
+ if (bytes == 0) {
+ snprintf(buffer, buffer_size, "0 B");
+ return buffer;
+ }
+
+ /* Handle negative values if necessary, though size is typically non-negative */
+ if (bytes < 0) {
+ snprintf(buffer, buffer_size, "Invalid size");
+ return buffer;
+ }
+
+ while (readable_size >= 1024 && i < (sizeof(units) / sizeof(units[0]) - 1)) {
+ readable_size /= 1024;
+ i++;
+ }
+
+ memset(buffer, '\0', buffer_size);
+ snprintf(buffer, buffer_size, "%.1f %s", readable_size, units[i]);
+
+ return buffer;
+}
+
+int compare_segments(const void *a, const void *b)
+{
+ const struct mem_segment *seg_a = (const struct mem_segment *)a;
+ const struct mem_segment *seg_b = (const struct mem_segment *)b;
+
+ if (seg_a->start > seg_b->start) return -1;
+ if (seg_a->start < seg_b->start) return 1;
+ return 0;
+}
+
+void* make_layout(struct mem_layout *layout, int max_row, int max_col)
+{
+ int col = MAX_COL_LAYOUT;
+ int row = max_row + 1;
+ char *layout_raw;
+ int i,j;
+ unsigned int cursor = 0;
+ int idx = 0;
+
+ if (max_col > col)
+ col = max_col;
+
+ layout_raw = (char *)malloc(row * col * sizeof(char));
+ memset(layout_raw, ' ', row * col * sizeof(char));
+ for (i=0; i<layout->count; i++) {
+ int center_bias = 0;
+ char fill = layout->segs[i].fill_char;
+
+ memset(layout_raw+cursor, '-', col);
+ layout_raw[cursor] = layout_raw[cursor+col-2] = '+';
+ layout_raw[cursor+col-1] = '\n';
+ cursor += col; /* next row */
+
+ memset(layout_raw+cursor, fill, col);
+ layout_raw[cursor] = '|';
+ layout_raw[cursor+col-2] = '|';
+ layout_raw[cursor+col-1] = '\n';
+ center_bias = (col - strlen(layout->segs[i].name)) / 2;
+ memcpy(layout_raw + cursor + center_bias, layout->segs[i].name,
+ strlen(layout->segs[i].name));
+ cursor += col; /* next row */
+
+ if (strlen(layout->segs[i].desc) != 0) {
+ memset(layout_raw+cursor, fill, col);
+ layout_raw[cursor] = '|';
+ layout_raw[cursor+col-2] = '|';
+ layout_raw[cursor+col-1] = '\n';
+
+ center_bias = (col - strlen(layout->segs[i].desc)) / 2;
+ memcpy(layout_raw + cursor + center_bias, layout->segs[i].desc,
+ strlen(layout->segs[i].desc));
+
+ cursor += col; /* next row */
+ } else {
+ /* It's a gap area. */
+ int width = layout->segs[i].width;
+
+ while(width--) {
+ memset(layout_raw+cursor, fill, col);
+ layout_raw[cursor] = '|';
+ layout_raw[cursor+col-2] = '|';
+ layout_raw[cursor+col-1] = '\n';
+ cursor += col; /* next row */
+ }
+ }
+
+ if (i == (layout->count - 1)) {
+ /* last line */
+ memset(layout_raw+cursor, '-', col);
+ layout_raw[cursor] = layout_raw[cursor+col-2] = '+';
+ layout_raw[cursor+col-1] = '\n';
+ layout_raw[cursor+col] = '\0';
+ }
+ }
+
+ return layout_raw;
+}
+
+void print_layout(struct mem_layout *layout)
+{
+ int max_col = 0;
+ int max_row = 0;
+ struct mem_segment *segs = layout->segs;
+ struct mem_segment seg;
+ int i, j;
+ char *layout_raw;
+ char *string;
+
+ if (layout == NULL)
+ return;
+
+ /* calculate the max col which can includes all 'desc' */
+ for (i=0; i<layout->count; i++) {
+ int col = 0;
+ int cursor = 0;
+ int row = 1; /* the minimal row */
+
+ seg = segs[i];
+ col = strlen(seg.name);
+
+ max_col = (max_col >= col) ?: col;
+ /* The gap area has no desc. */
+ if (seg.desc[0] != '\0') {
+ col = strlen(seg.desc);
+ row += 1;
+ max_col = (max_col >= col) ?: col;
+ } else
+ row += segs[i].width;
+
+ max_row += row;
+ }
+ /* add border line */
+ max_row += layout->count + 1;
+ max_col + 3;
+
+ layout_raw = make_layout(layout, max_row, max_col);
+ fprintf(fp, "%s", layout_raw);
+ free(layout_raw);
+}
+
+#define __round_mask(x, y) ((__typeof__(x))((y)-1))
+#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y) ((x) & ~__round_mask(x, y))
+
+/*
+ * table-based memory layout:
+ *
+ * +---------------------------------------------------------+
+ * |xxxxxxxxxxxxxxxxxxx gap (size: 8.0 MB) xxxxxxxxxxxxxxxxxx|
+ * +---------------------------------------------------------+
+ * | FIXMAP |
+ * | (0xffffffffff578000 - 0xffffffffff7ff000 size: 2.5 MB) |
+ * +---------------------------------------------------------+
+ * |xxxxxxxxxxxxxxxxxxx gap (size: 5.5 MB) xxxxxxxxxxxxxxxxxx|
+ * +---------------------------------------------------------+
+ * | Module Area |
+ * | (0xffffffffa0000000 - 0xffffffffff000000 size: 1.5 GB) |
+ * +---------------------------------------------------------+
+ * |xxxxxxxxxxxxxxxxxx gap (size: 451.9 MB) xxxxxxxxxxxxxxxxx|
+ * +---------------------------------------------------------+
+ * | kernel image |
+ * | (0xffffffff81000000 - 0xffffffff83c26000 size: 44.1 MB) |
+ * +---------------------------------------------------------+
+ * |xxxxxxxxxxxxxxxxxx gap (size: 21.0 TB) xxxxxxxxxxxxxxxxxx|
+ * |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
+ * |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
+ * +---------------------------------------------------------+
+ * | Vmemmap Area |
+ * | (0xffffea0000000000 - 0xffffeaffffffffff size: 1.0 TB) |
+ * +---------------------------------------------------------+
+ * |xxxxxxxxxxxxxxxxxxx gap (size: 1.0 TB) xxxxxxxxxxxxxxxxxx|
+ * |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
+ * +---------------------------------------------------------+
+ * | Vmalloc/Vfree Area |
+ * | (0xffffc90000000000 - 0xffffe8ffffffffff size: 32.0 TB) |
+ * +---------------------------------------------------------+
+ * |xxxxxxxxxxxxxxxxxx gap (size: 512.0 GB) xxxxxxxxxxxxxxxxx|
+ * +---------------------------------------------------------+
+ * | Linear Mapping Area |
+ * | (0xffff888000000000 - 0xffffc87fffffffff size: 64.0 TB) |
+ * +---------------------------------------------------------+
+ * | Kernel Space Offset |
+ * | (0xffff800000000000 - 0xffff887fffffffff size: 8.5 TB) |
+ * +---------------------------------------------------------+
+ * |xxxxxxxxxxxxxxx gap (size: 16776960.0 TB) xxxxxxxxxxxxxxx|
+ * |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
+ * |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
+ * +---------------------------------------------------------+
+ * | User Space |
+ * | (size: 128.0 TB) |
+ * +---------------------------------------------------------+
+ *
+ * kernel space:
+ * _end, _text
+ * vmemmap_end: ms->vmemmap_end
+ * vmemmap_vaddr: ms->vmemmap_vaddr
+ * vmalloc_end: ms->vmalloc_end
+ * vmalloc_start_addr: ms->vmalloc_start_addr
+ * page_offset_base: ms->page_offset
+ *
+ * user space:
+ * userspace_top: ms->userspace_top
+ *
+ */
+void x86_64_dump_memory_layout(void)
+{
+ struct mem_layout *layout = NULL;
+ ulong text_start, text_end;
+ struct machine_specific *ms = machdep->machspec;
+ int i, next_idx;
+ char size_buf[20];
+ long value = 0;
+
+ layout = malloc(sizeof(struct mem_layout));
+ if (layout == NULL || layout->count == 0) {
+ printf("Layout is empty, nothing to print.\n");
+ return;
+ }
+
+ /* Create a temporary copy to sort for printing, preserving the original order. */
+ struct mem_segment *sorted_segments = layout->segs;
+ if(!sorted_segments) {
+ perror("Failed to allocate memory for sorting");
+ return;
+ }
+
+ if (!symbol_exists("_text"))
+ return;
+ else
+ text_start = symbol_value("_text");
+
+ if (!symbol_exists("_end"))
+ return;
+ else
+ text_end = symbol_value("_end");
+
+ snprintf(sorted_segments[0].name, 64, "kernel image");
+ snprintf(sorted_segments[0].desc, 64, "(0x%lx - 0x%lx size: %s)",
+ text_start, text_end,
+ format_bytes(text_end - text_start + 1, size_buf, 20));
+ sorted_segments[0].start = text_start;
+ sorted_segments[0].end = text_end;
+ sorted_segments[0].fill_char = ' ';
+
+ snprintf(sorted_segments[1].name, 64, "Vmemmap Area");
+ snprintf(sorted_segments[1].desc, 64, "(0x%lx - 0x%lx size: %s)",
+ (ulong)ms->vmemmap_vaddr, (ulong)ms->vmemmap_end,
+ format_bytes(ms->vmemmap_end - ms->vmemmap_vaddr + 1, size_buf, 20));
+ sorted_segments[1].start = (ulong)ms->vmemmap_vaddr;
+ sorted_segments[1].end = (ulong)ms->vmemmap_end;
+ sorted_segments[1].fill_char = ' ';
+
+ snprintf(sorted_segments[2].name, 64, "Module Area");
+ snprintf(sorted_segments[2].desc, 64, "(0x%lx - 0x%lx size: %s)",
+ (ulong)ms->modules_vaddr,(ulong)ms->modules_end,
+ format_bytes(ms->modules_end - ms->modules_vaddr + 1, size_buf, 20));
+ sorted_segments[2].start = (ulong)ms->modules_vaddr;
+ sorted_segments[2].end = (ulong)ms->modules_end;
+ sorted_segments[2].fill_char = ' ';
+
+ snprintf(sorted_segments[3].name, 64, "Vmalloc/Vfree Area");
+ snprintf(sorted_segments[3].desc, 64, "(0x%lx - 0x%lx size: %s)",
+ (ulong)ms->vmalloc_start_addr, (ulong)ms->vmalloc_end,
+ format_bytes(ms->vmalloc_end - ms->vmalloc_start_addr + 1, size_buf, 20));
+ sorted_segments[3].start = (ulong)ms->vmalloc_start_addr;
+ sorted_segments[3].end = (ulong)ms->vmalloc_end;
+ sorted_segments[3].fill_char = ' ';
+
+ snprintf(sorted_segments[4].name, 64, "Linear Mapping Area");
+ sorted_segments[4].start = (ulong)ms->page_offset;
+ sorted_segments[4].end = (ulong)ms->page_offset + (1UL << machdep->max_physmem_bits) - 1;
+ sorted_segments[4].fill_char = ' ';
+ snprintf(sorted_segments[4].desc, 64, "(0x%lx - 0x%lx size: %s)",
+ sorted_segments[4].start, sorted_segments[4].end,
+ format_bytes(1UL << machdep->max_physmem_bits, size_buf, 20));
+
+ snprintf(sorted_segments[5].name, 64, "User Space");
+ snprintf(sorted_segments[5].desc, 64, "(size: %s)",
+ format_bytes((ulong)ms->userspace_top, size_buf, 20));
+ sorted_segments[5].start = 0UL;
+ sorted_segments[5].end = (ulong)ms->userspace_top - 1;
+ sorted_segments[5].fill_char = ' ';
+
+ snprintf(sorted_segments[6].name, 64, "Kernel Space Offset");
+ sorted_segments[6].start = -1UL - (1UL << __VIRTUAL_MASK_SHIFT) + 1;
+ sorted_segments[6].end = (ulong)ms->page_offset - 1;
+ sorted_segments[6].fill_char = ' ';
+ snprintf(sorted_segments[6].desc, 64, "(0x%lx - 0x%lx size: %s)",
+ sorted_segments[6].start, sorted_segments[6].end,
+ format_bytes(sorted_segments[6].end - sorted_segments[6].start + 1, size_buf, 20));
+
+ layout->count = 7;
+ if (kernel_symbol_exists("kasan_init")) {
+ snprintf(sorted_segments[7].name, 64, "KASAN");
+ sorted_segments[7].start = KASAN_SHADOW_START;
+ sorted_segments[7].end = KASAN_SHADOW_END;
+ sorted_segments[7].fill_char = ' ';
+ snprintf(sorted_segments[7].desc, 64, "(0x%lx - 0x%lx size: %s)",
+ sorted_segments[7].start, sorted_segments[7].end,
+ format_bytes(sorted_segments[7].end - sorted_segments[7].start + 1, size_buf, 20));
+ layout->count++;
+ }
+
+ if (enumerator_value("__end_of_permanent_fixed_addresses", &value)) {
+ unsigned fixaddr_size = 0;
+ int idx = layout->count;
+
+ fixaddr_size = value << PAGE_SHIFT;
+
+ snprintf(sorted_segments[7].name, 64, "FIXMAP");
+ sorted_segments[idx].end = round_up(VSYSCALL_START + PAGE_SIZE, 1 << PMD_SHIFT) - PAGE_SIZE;
+ sorted_segments[idx].start = sorted_segments[idx].end - fixaddr_size;
+
+ sorted_segments[idx].fill_char = ' ';
+ snprintf(sorted_segments[idx].desc, 64, "(0x%lx - 0x%lx size: %s)",
+ sorted_segments[idx].start, sorted_segments[idx].end,
+ format_bytes(sorted_segments[idx].end - sorted_segments[idx].start + 1, size_buf, 20));
+ layout->count++;
+ }
+
+ /* Sort segments from highest address to lowest. */
+ qsort(sorted_segments, layout->count, sizeof(struct mem_segment), compare_segments);
+
+ next_idx = layout->count;
+ /* Insert gap area */
+ for (i=0; i<layout->count; i++) {
+ unsigned long prev_start;
+ unsigned long end = sorted_segments[i].end;
+
+ if (i == 0)
+ prev_start = -1UL;
+ else
+ prev_start = sorted_segments[i-1].start;
+
+ if (prev_start == (end + 1))
+ continue;
+
+ if ((prev_start - end) >= (8UL * 1024 * 1024 * 1024 * 1024))
+ sorted_segments[next_idx].width = 3;
+ else if ((prev_start - end) >= (1UL * 1024 * 1024 * 1024 * 1024))
+ sorted_segments[next_idx].width = 2;
+ else
+ sorted_segments[next_idx].width = 1;
+
+ sorted_segments[next_idx].start = end + 1;
+ sorted_segments[next_idx].end = (i == 0) ? prev_start : prev_start - 1;
+ sorted_segments[next_idx].fill_char = 'x';
+ snprintf(sorted_segments[next_idx].name, 64, " gap (size: %s) ",
+ format_bytes(sorted_segments[next_idx].end - sorted_segments[next_idx].start + 1,
+ size_buf, 20));
+ sorted_segments[next_idx].desc[0] = '\0';
+
+ next_idx++;
+ }
+
+ layout->count = next_idx;
+ qsort(sorted_segments, layout->count, sizeof(struct mem_segment), compare_segments);
+
+ print_layout(layout);
+ free(layout);
+}
+
/*
* Gather the cpu_pda array info, updating any smp-related items that
* were possibly bypassed or improperly initialized in kernel_init().
--
2.39.3
2 weeks, 3 days
[PATCH] vmcoreinfo: read vmcoreinfo using 'vmcoreinfo_data' when unavailable in elf note
by Aditya Gupta
Few vmcores don't have vmcoreinfo elf note, such as those created using
virsh-dump.
On architectures such as PowerPC64, vmcoreinfo is mandatory to fetch the
first_vmalloc_address, for vmcores of upstream linux, since crash-utility commit:
commit 5b24e363a898 ("get vmalloc start address from vmcoreinfo")
Try reading from the 'vmcoreinfo_data' symbol instead, if the vmcoreinfo
crash tries to read in case of diskdump/netdump is empty/missing.
The approach to read 'vmcoreinfo_data' was used for a live kernel, which can be
reused in the case of missing vmcoreinfo note also, as the
'vmcoreinfo_data' symbol is available with vmcore too
Note though, till GDB interface is not initialised, reading from
vmcoreinfo_data symbol is not done, so behaviour is same as previously
with no vmcoreinfo (only till GDB interface is not initialised)
Hence rename 'vmcoreinfo_read_string' in kernel.c to
'vmcoreinfo_read_from_memory', and use it in netdump.c and diskdump.c
too.
Reported-by: Anushree Mathur <anushree.mathur(a)linux.ibm.com>
Reported-by: Kowshik Jois <kowsjois(a)linux.ibm.com>
Tested-by: Anushree Mathur <anushree.mathur(a)linux.ibm.com>
Tested-by: Kowshik Jois <kowsjois(a)linux.ibm.com>
Signed-off-by: Aditya Gupta <adityag(a)linux.ibm.com>
---
defs.h | 1 +
diskdump.c | 18 ++++++++++++++++++
kernel.c | 17 ++++++++++++-----
netdump.c | 19 +++++++++++++++++++
4 files changed, 50 insertions(+), 5 deletions(-)
diff --git a/defs.h b/defs.h
index 2fdb4db56a05..fbd09e19103f 100644
--- a/defs.h
+++ b/defs.h
@@ -6213,6 +6213,7 @@ void dump_kernel_table(int);
void dump_bt_info(struct bt_info *, char *where);
void dump_log(int);
void parse_kernel_version(char *);
+char *vmcoreinfo_read_from_memory(const char *);
#define LOG_LEVEL(v) ((v) & 0x07)
#define SHOW_LOG_LEVEL (0x1)
diff --git a/diskdump.c b/diskdump.c
index ce3cbb7b12dd..3be56248c7a9 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -1041,6 +1041,13 @@ pfn_to_pos(ulong pfn)
return desc_pos;
}
+/**
+ * Check if vmcoreinfo in vmcore is missing/empty
+ */
+static bool is_vmcoreinfo_empty(void)
+{
+ return (dd->sub_header_kdump->size_vmcoreinfo == 0);
+}
/*
* Determine whether a file is a diskdump creation, and if TRUE,
@@ -1088,6 +1095,17 @@ is_diskdump(char *file)
pc->read_vmcoreinfo = vmcoreinfo_read_string;
+ /*
+ * vmcoreinfo can be empty in case of dump collected via virsh-dump
+ *
+ * check if vmcoreinfo is not available in vmcore, and try to read
+ * the vmcoreinfo from memory, using "vmcoreinfo_data" symbol
+ */
+ if (is_vmcoreinfo_empty()) {
+ error(WARNING, "vmcoreinfo is empty, will read from symbols\n");
+ pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
+ }
+
if ((pc->flags2 & GET_LOG) && KDUMP_CMPRS_VALID()) {
pc->dfd = dd->dfd;
pc->readmem = read_diskdump;
diff --git a/kernel.c b/kernel.c
index b8d3b7999974..b296487ea036 100644
--- a/kernel.c
+++ b/kernel.c
@@ -99,7 +99,6 @@ static ulong dump_audit_skb_queue(ulong);
static ulong __dump_audit(char *);
static void dump_audit(void);
static void dump_printk_safe_seq_buf(int);
-static char *vmcoreinfo_read_string(const char *);
static void check_vmcoreinfo(void);
static int is_pvops_xen(void);
static int get_linux_banner_from_vmlinux(char *, size_t);
@@ -11892,8 +11891,8 @@ dump_printk_safe_seq_buf(int msg_flags)
* Returns a string (that has to be freed by the caller) that contains the
* value for key or NULL if the key has not been found.
*/
-static char *
-vmcoreinfo_read_string(const char *key)
+char *
+vmcoreinfo_read_from_memory(const char *key)
{
char *buf, *value_string, *p1, *p2;
size_t value_length;
@@ -11903,6 +11902,14 @@ vmcoreinfo_read_string(const char *key)
buf = value_string = NULL;
+ if (!(pc->flags & GDB_INIT)) {
+ /*
+ * GDB interface hasn't been initialised yet, so can't
+ * access vmcoreinfo_data
+ */
+ return NULL;
+ }
+
switch (get_symbol_type("vmcoreinfo_data", NULL, NULL))
{
case TYPE_CODE_PTR:
@@ -11958,10 +11965,10 @@ check_vmcoreinfo(void)
switch (get_symbol_type("vmcoreinfo_data", NULL, NULL))
{
case TYPE_CODE_PTR:
- pc->read_vmcoreinfo = vmcoreinfo_read_string;
+ pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
break;
case TYPE_CODE_ARRAY:
- pc->read_vmcoreinfo = vmcoreinfo_read_string;
+ pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
break;
}
}
diff --git a/netdump.c b/netdump.c
index c7ff009e7f90..c9f0e4eaa580 100644
--- a/netdump.c
+++ b/netdump.c
@@ -111,6 +111,14 @@ map_cpus_to_prstatus(void)
FREEBUF(nt_ptr);
}
+/**
+ * Check if vmcoreinfo in vmcore is missing/empty
+ */
+static bool is_vmcoreinfo_empty(void)
+{
+ return (nd->size_vmcoreinfo == 0);
+}
+
/*
* Determine whether a file is a netdump/diskdump/kdump creation,
* and if TRUE, initialize the vmcore_data structure.
@@ -464,6 +472,17 @@ is_netdump(char *file, ulong source_query)
pc->read_vmcoreinfo = vmcoreinfo_read_string;
+ /*
+ * vmcoreinfo can be empty in case of dump collected via virsh-dump
+ *
+ * check if vmcoreinfo is not available in vmcore, and try to read
+ * the vmcoreinfo from memory, using "vmcoreinfo_data" symbol
+ */
+ if (is_vmcoreinfo_empty()) {
+ error(WARNING, "vmcoreinfo is empty, will read from symbols\n");
+ pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
+ }
+
if ((source_query == KDUMP_LOCAL) &&
(pc->flags2 & GET_OSRELEASE))
kdump_get_osrelease();
--
2.49.0
2 weeks, 4 days
Re: [PATCH v2] Disable DT_DEBUG lookup by GDB inside the vmcore
by Tao Liu
Hi Shivang,
Sorry for the late. LGTM, so ack.
Thanks,
Tao Liu
On Mon, Jul 21, 2025 at 8:18 PM Shivang Upadhyay <shivangu(a)linux.ibm.com> wrote:
>
> 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(a)redhat.com>
> Cc: Lianbo Jiang <lijiang(a)redhat.com>
> Cc: Sourabh Jain <sourabhjain(a)linux.ibm.com>
> Signed-off-by: shivang.upadhyay <shivangu(a)linux.ibm.com>
> ---
> gdb-16.2.patch | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/gdb-16.2.patch b/gdb-16.2.patch
> index 151e4e2..7b79cdf 100644
> --- a/gdb-16.2.patch
> +++ b/gdb-16.2.patch
> @@ -1952,3 +1952,19 @@ exit 0
> }
>
> /* Remember the bfd indexes for the .text, .data, .bss and
> +--- gdb-16.2/gdb/solib-svr4.c.orig
> ++++ gdb-16.2/gdb/solib-svr4.c
> +@@ -742,11 +742,13 @@ elf_locate_base (void)
> + 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. */
> --
> 2.50.0
>
2 weeks, 5 days
[Crash-utility][PATCH] Fix crash initialization failure on LoongArch with recent GDB versions
by Ming Wang
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(a)loongson.cn>
---
crash_target.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crash_target.c b/crash_target.c
index 5966b7b..d93d58c 100644
--- a/crash_target.c
+++ b/crash_target.c
@@ -71,7 +71,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.41.3
2 weeks, 5 days
Re: [PATCH] Fix a regression for eppic extension on gdb-16.2
by lijiang
Hi, Tao
On Wed, Jul 9, 2025 at 1:42 PM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Tue, 8 Jul 2025 13:26:38 +1200
> From: Tao Liu <ltao(a)redhat.com>
> Subject: [Crash-utility] [PATCH] Fix a regression for eppic extension
> on gdb-16.2
> To: devel(a)lists.crash-utility.osci.io
> Cc: Tao Liu <ltao(a)redhat.com>
> Message-ID: <20250708012638.97698-1-ltao(a)redhat.com>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> 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(a)redhat.com>
> ---
> gdb-16.2.patch | 29 +++++++++++++++++++++++++++++
> 1 file changed, 29 insertions(+)
>
> diff --git a/gdb-16.2.patch b/gdb-16.2.patch
> index 151e4e2..eb620f7 100644
> --- a/gdb-16.2.patch
> +++ b/gdb-16.2.patch
>
Can you help to add the gdb-16.2/gdb/symtab.c to gdb-16.2.patch, and it
looks like this:
# 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
In addition, also please add a prefix "gdb: " to patch title, E.g:
gdb: Fix a regression for eppic extension on gdb-16.2
Other changes are fine to me. So: Ack(with the above change)
Thanks
Lianbo
> @@ -1952,3 +1952,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.47.0
>
2 weeks, 5 days
[PATCH] Update requirements for building on Fedora
by Charles Haithcock
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.
---
README | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README b/README
index 2e34fbb..f9824c7 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
2 weeks, 5 days
Re: [PATCH] x86_64: filter unwanted warning message for "bt -T" cmd
by Lianbo Jiang
Hi, Tao
Thank you for the patch.
On 7/9/25 13:41, devel-request(a)lists.crash-utility.osci.io wrote:
> Date: Wed, 9 Jul 2025 17:41:12 +1200
> From: Tao Liu<ltao(a)redhat.com>
> Subject: [Crash-utility] [PATCH] x86_64: filter unwanted warning
> message for "bt -T" cmd
> To:devel@lists.crash-utility.osci.io
> Cc: Tao Liu<ltao(a)redhat.com>
> Message-ID:<20250709054112.145454-1-ltao(a)redhat.com>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> 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.
For the patch: Ack.
Thanks
Lianbo
> After apply the patch:
>
> crash> bt -T
> [ffffbaebc60d6fa8] srso_return_thunk at ffffffff82246fa5
> ...
>
> Signed-off-by: Tao Liu<ltao(a)redhat.com>
> ---
> x86_64.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/x86_64.c b/x86_64.c
> index cfefe3f..d7da536 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.47.0
2 weeks, 5 days