[PATCH] arm64: Fix broken/incomplete gdb backtrace and unify output format
by lipengfei28@xiaomi.com
From 4d832a33ebd80bd109cc5a47f98c6b35fdcbd956 Mon Sep 17 00:00:00 2001
From: lipengfei28 <lipengfei28(a)xiaomi.com>
Date: Fri, 23 Jan 2026 16:24:07 +0800
Subject: [PATCH] arm64: Fix broken/incomplete gdb backtrace and unify output
format
This patch fixes multiple issues with 'gdb bt' on ARM64, where the backtrace
would be interrupted, contain garbage threads, or display fragmented output.
1. Fix Out-of-Bounds Read in Exception Frame Handling:
In `arm64_print_exception_frame`, the code previously used `memcpy` to copy
`sizeof(struct arm64_pt_regs)` bytes from a `struct arm64_stackframe *` source.
Since `stackframe` is significantly smaller than `pt_regs`, this caused an
out-of-bounds read, populating the GDB thread registers with stack garbage
(often resulting in invalid addresses like -3/0xff...fd).
This is fixed by manually copying only the valid registers (PC, SP, FP, etc.)
and properly initializing the bitmap.
2. Bridge the Gap Between IRQ and Process Stacks:
Previously, GDB unwinding would stop at `call_on_irq_stack` because it could
not automatically unwind through the assembly trampoline back to the process
stack.
Modified `arm64_switch_stack` (and the overflow variant) to "peek" one frame
ahead (reading the saved FP/PC of the caller) before registering the new
GDB substack. This effectively bridges the discontinuity, allowing GDB to
show frames like `do_interrupt_handler` that were previously missing.
3. Unify and Format GDB Output:
Modified `gdb_interface.c` to:
- Strip "Thread <id>" headers to present a continuous backtrace similar to
the native `crash bt`.
- Renumber stack frames sequentially (e.g., #0 to #30) instead of resetting
at each stack switch.
- Add indentation/alignment for frames where GDB omits the address (e.g.,
inline functions) to improve readability.
4. Prevent Invalid Thread Creation:
Added checks to ensure a GDB substack is only created if the Program Counter
(PC) is non-zero, preventing the display of "corrupt" or empty threads.
Tested on: Android 6.x ARM64
Signed-off-by: lipengfei28 <lipengfei28(a)xiaomi.com>
---
arm64.c | 117 +++++++++++++++++++++++++++++++++++++------
gdb_interface.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 229 insertions(+), 18 deletions(-)
diff --git a/arm64.c b/arm64.c
index c125655..f842739 100644
--- a/arm64.c
+++ b/arm64.c
@@ -3026,6 +3026,9 @@ static char *arm64_exception_functions[] = {
"do_el0_irq_bp_hardening",
"do_sp_pc_abort",
"handle_bad_stack",
+ "el1h_64_sync",
+ "el1h_64_irq",
+ "el1h_64_error",
NULL
};
@@ -3123,6 +3126,11 @@ arm64_print_stackframe_entry(struct bt_info *bt, int level, struct arm64_stackfr
fprintf(ofp, "\n");
+ if (STREQ(name, "el1h_64_irq") || STREQ(name, "el1h_64_sync"))
+ if (arm64_is_kernel_exception_frame(bt, frame->sp)) {
+ arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+ }
+
if (bt->flags & BT_LINE_NUMBERS) {
get_line_number(branch_pc, buf, FALSE);
if (strlen(buf))
@@ -3775,11 +3783,12 @@ arm64_back_trace_cmd(struct bt_info *bt)
REG_SEQ(arm64_pt_regs, pc));
SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
REG_SEQ(arm64_pt_regs, sp));
- if (!bt->machdep ||
+ if (extra_stacks_regs[extra_stacks_idx]->ur.pc &&
+ (!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)) {
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
gdb_add_substack (extra_stacks_idx++);
}
}
@@ -3925,11 +3934,12 @@ arm64_back_trace_cmd_v2(struct bt_info *bt)
REG_SEQ(arm64_pt_regs, pc));
SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
REG_SEQ(arm64_pt_regs, sp));
- if (!bt->machdep ||
+ if (extra_stacks_regs[extra_stacks_idx]->ur.pc &&
+ (!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)) {
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
gdb_add_substack (extra_stacks_idx++);
}
}
@@ -4263,8 +4273,40 @@ arm64_switch_stack(struct bt_info *bt, struct arm64_stackframe *frame, FILE *ofp
if (frame->fp == 0)
return USER_MODE;
- if (!(machdep->flags & UNW_4_14))
+ if (!(machdep->flags & UNW_4_14)) {
arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+ } else {
+ 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));
+ struct user_regs_bitmap_struct *ur_ptr = extra_stacks_regs[extra_stacks_idx];
+
+ ulong next_fp = GET_STACK_ULONG(frame->fp);
+ ulong next_pc = GET_STACK_ULONG(frame->fp + 8);
+ ulong next_sp = frame->fp + 16;
+
+ if (is_kernel_text(next_pc | ms->CONFIG_ARM64_KERNELPACMASK))
+ next_pc |= ms->CONFIG_ARM64_KERNELPACMASK;
+
+ ur_ptr->ur.pc = next_pc;
+ ur_ptr->ur.sp = next_sp;
+ ur_ptr->ur.regs[29] = next_fp;
+
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, pc));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, sp));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, regs[0]) + 29);
+
+ if (ur_ptr->ur.pc &&
+ (!bt->machdep ||
+ (ur_ptr->ur.sp !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+ ur_ptr->ur.pc !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+ gdb_add_substack (extra_stacks_idx++);
+ }
+ }
return KERNEL_MODE;
}
@@ -4300,8 +4342,40 @@ arm64_switch_stack_from_overflow(struct bt_info *bt, struct arm64_stackframe *fr
if (frame->fp == 0)
return USER_MODE;
- if (!(machdep->flags & UNW_4_14))
+ if (!(machdep->flags & UNW_4_14)) {
arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+ } else {
+ 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));
+ struct user_regs_bitmap_struct *ur_ptr = extra_stacks_regs[extra_stacks_idx];
+
+ ulong next_fp = GET_STACK_ULONG(frame->fp);
+ ulong next_pc = GET_STACK_ULONG(frame->fp + 8);
+ ulong next_sp = frame->fp + 16;
+
+ if (is_kernel_text(next_pc | ms->CONFIG_ARM64_KERNELPACMASK))
+ next_pc |= ms->CONFIG_ARM64_KERNELPACMASK;
+
+ ur_ptr->ur.pc = next_pc;
+ ur_ptr->ur.sp = next_sp;
+ ur_ptr->ur.regs[29] = next_fp;
+
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, pc));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, sp));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, regs[0]) + 29);
+
+ if (ur_ptr->ur.pc &&
+ (!bt->machdep ||
+ (ur_ptr->ur.sp !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+ ur_ptr->ur.pc !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+ gdb_add_substack (extra_stacks_idx++);
+ }
+ }
return KERNEL_MODE;
}
@@ -4556,16 +4630,27 @@ arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int mode, FILE *o
}
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++);
+ {
+ struct user_regs_bitmap_struct *ur_ptr = extra_stacks_regs[extra_stacks_idx];
+ int i;
+
+ ur_ptr->ur.pc = regs->pc;
+ ur_ptr->ur.sp = regs->sp;
+ ur_ptr->ur.pstate = regs->pstate;
+ for (i = 0; i < 31; i++)
+ ur_ptr->ur.regs[i] = regs->regs[i];
+
+ for (i = 0; i < 34; i++)
+ SET_BIT(ur_ptr->bitmap, i);
+
+ if (ur_ptr->ur.pc &&
+ (!bt->machdep ||
+ (ur_ptr->ur.sp !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+ ur_ptr->ur.pc !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+ gdb_add_substack (extra_stacks_idx++);
+ }
}
}
}
diff --git a/gdb_interface.c b/gdb_interface.c
index 9f76f85..d14144e 100644
--- a/gdb_interface.c
+++ b/gdb_interface.c
@@ -16,6 +16,7 @@
*/
#include "defs.h"
+#include <ctype.h>
#if !defined(GDB_10_2) && !defined(GDB_16_2)
static void exit_after_gdb_info(void);
@@ -779,22 +780,53 @@ strip_redirection(char *buf)
/*
* Command for passing strings directly to gdb.
*/
+static void format_and_print_gdb_bt(FILE *input_fp);
+
void
cmd_gdb(void)
{
char buf[BUFSIZE];
char **argv;
+ int i;
argv = STREQ(args[0], "gdb") ? &args[1] : &args[0];
if (*argv == NULL)
cmd_usage(pc->curcmd, SYNOPSIS);
+ if (STREQ(*argv, "bt")) {
+ FILE *tmp_fp;
+
+ if ((tmp_fp = tmpfile()) == NULL) {
+ error(FATAL, "cannot create temporary file for GDB output\n");
+ }
+
+ strcpy(buf, "thread apply all bt");
+ /* Append any arguments that were passed to 'bt' */
+ /* args[0] is "gdb", args[1] is "bt", so options start at index 2 */
+ for (i = 2; i < argcnt; i++) {
+ strcat(buf, " ");
+ strcat(buf, args[i]);
+ }
+
+ if (!gdb_pass_through(buf, tmp_fp, GNU_RETURN_ON_ERROR)) {
+ fclose(tmp_fp);
+ error(INFO, "gdb request failed: %s\n", buf);
+ return;
+ }
+
+ rewind(tmp_fp);
+ format_and_print_gdb_bt(tmp_fp);
+
+ fclose(tmp_fp);
+ return;
+ }
+
if (STREQ(*argv, "set") && argv[1]) {
/*
* Intercept set commands in case something has to be done
- * here or elsewhere.
- */
+ * here or elsewhere.
+ */
if (STREQ(argv[1], "gdb")) {
cmd_set();
return;
@@ -821,6 +853,100 @@ cmd_gdb(void)
}
}
+#define MAX_BT_LINES 1024
+#define MAX_THREAD_BLOCKS 64
+
+/*
+ * Helper function to parse 'thread apply all bt' output, reverse the
+ * thread blocks, and print the result.
+ */
+static void format_and_print_gdb_bt(FILE *input_fp)
+{
+ char *lines[MAX_BT_LINES];
+ int line_count = 0;
+ int thread_starts[MAX_THREAD_BLOCKS];
+ int thread_count = 0;
+ char line_buffer[BUFSIZE];
+ int i, j;
+ int global_frame_cnt = 0;
+
+ // Read all lines into memory
+ while (fgets(line_buffer, BUFSIZE, input_fp) && line_count < MAX_BT_LINES) {
+ if (strstr(line_buffer, "Thread ") == line_buffer) {
+ if (thread_count < MAX_THREAD_BLOCKS) {
+ thread_starts[thread_count++] = line_count;
+ }
+ }
+ lines[line_count] = strdup(line_buffer);
+ if (!lines[line_count]) {
+ error(FATAL, "strdup failed while reading gdb output\n");
+ }
+ line_count++;
+ }
+
+ if (thread_count == 0) { // If no threads, just print everything as is.
+ for (i = 0; i < line_count; i++) {
+ fputs(lines[i], fp);
+ }
+ } else {
+ // Iterate threads in reverse order to fix the display order
+ for (i = thread_count - 1; i >= 0; i--) {
+ int start_line = thread_starts[i];
+ int end_line = (i == thread_count - 1) ? line_count : thread_starts[i+1];
+
+ // Print thread frames, stripping header and renumbering
+ for (j = start_line; j < end_line; j++) {
+ char *line = lines[j];
+ // Skip "Thread " line
+ if (strncmp(line, "Thread ", 7) == 0) continue;
+ // Skip "Backtrace stopped" or similar noise if desired,
+ // but usually GDB prints "Backtrace stopped" at the very end.
+ // We'll keep it for info unless it's in the middle of our merge.
+ // Actually, duplicate frames or stops might appear.
+ // For now, simple renumbering.
+
+ char *ptr = line;
+ while (*ptr == ' ' || *ptr == '\t') ptr++;
+
+ if (*ptr == '#') {
+ // Frame line: #0 0x...
+ char *rest = ptr + 1;
+ while (isdigit(*rest)) rest++; // Skip old number
+
+ // Parse content to check for address
+ char *p = rest;
+ while (*p == ' ' || *p == '\t') p++;
+
+ int has_addr = (strncmp(p, "0x", 2) == 0);
+
+ // Print number
+ fprintf(fp, "#%-3d", global_frame_cnt++);
+
+ // Align if address is missing
+ if (!has_addr) {
+ // Align function name with frames that have addresses
+ // 64-bit: 0x... (18 chars) + " in " (4 chars) = 22 chars
+ // 32-bit: 0x... (10 chars) + " in " (4 chars) = 14 chars
+ int width = (machdep->bits == 64) ? 22 : 14;
+ for (int k = 0; k < width; k++) fputc(' ', fp);
+ }
+
+ fputs(rest, fp);
+ } else {
+ // Other lines (e.g. variable info, code)
+ fputs(line, fp);
+ }
+ }
+ }
+ }
+
+ // Cleanup
+ for (i = 0; i < line_count; i++) {
+ free(lines[i]);
+ }
+}
+
+
/*
* The gdb target_xfer_memory() has a hook installed to re-route
* all memory accesses back here; reads of 1 or 4 bytes come primarily
--
2.34.1
1 week, 6 days
[PATCH] arm64: fix gdb register feeding for exception frames and stack switching
by Li Pengfei
From: lipengfei28 <lipengfei28(a)xiaomi.com>
On ARM64, crash’s gdb bt relies on feeding a register snapshot (PC/SP/FP,
etc.) into gdb and letting gdb unwind from there. Before this change, the
register snapshot handling across exception frames / stack switching could be
broken in several ways, leading to truncated backtraces, garbage substacks, or
invalid addresses (e.g. -3 / 0xff...fd) showing up in gdb output.
Fixes included in this patch:
Fix out-of-bounds read when populating gdb registers from an exception frame
In arm64_print_exception_frame(), the previous code copied
sizeof(struct arm64_pt_regs) bytes from a smaller stackframe-derived
buffer, which could read past valid data and poison the gdb registers.
Replace this with explicit field/register assignment and initialize the
bitmap accordingly.
Improve unwinding across IRQ/overflow stack transitions on newer kernels
When switching stacks (IRQ / overflow), gdb may stop at the trampoline (e.g.
call_on_irq_stack) because the discontinuity prevents it from recovering
the caller frame automatically. For UNW_4_14+, “peek” one frame ahead by
reading the saved FP/PC from the current frame, and register that as the
next gdb substack, so gdb can continue unwinding on the process stack.
Avoid creating invalid/empty substacks
Only add a gdb substack when the recovered PC is non-zero, preventing bogus
threads from being created.
This patch only changes ARM64 unwinding/register setup logic. It does not try
to reformat or merge gdb output.
Tested on: Android Linux 6.x, arm64
Signed-off-by: lipengfei28 <lipengfei28(a)xiaomi.com>
---
arm64.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 130 insertions(+), 18 deletions(-)
diff --git a/arm64.c b/arm64.c
index c125655..59fcda9 100644
--- a/arm64.c
+++ b/arm64.c
@@ -228,7 +228,7 @@ arm64_get_current_task_reg(int regno, const char *name,
return FALSE;
if (sid && sid <= extra_stacks_idx) {
- ur_bitmap = extra_stacks_regs[extra_stacks_idx - 1];
+ ur_bitmap = extra_stacks_regs[sid - 1];
goto get_sub;
}
@@ -3026,6 +3026,9 @@ static char *arm64_exception_functions[] = {
"do_el0_irq_bp_hardening",
"do_sp_pc_abort",
"handle_bad_stack",
+ "el1h_64_sync",
+ "el1h_64_irq",
+ "el1h_64_error",
NULL
};
@@ -3123,6 +3126,11 @@ arm64_print_stackframe_entry(struct bt_info *bt, int level, struct arm64_stackfr
fprintf(ofp, "\n");
+ if (STREQ(name, "el1h_64_irq") || STREQ(name, "el1h_64_sync"))
+ if (arm64_is_kernel_exception_frame(bt, frame->sp)) {
+ arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+ }
+
if (bt->flags & BT_LINE_NUMBERS) {
get_line_number(branch_pc, buf, FALSE);
if (strlen(buf))
@@ -3775,11 +3783,13 @@ arm64_back_trace_cmd(struct bt_info *bt)
REG_SEQ(arm64_pt_regs, pc));
SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
REG_SEQ(arm64_pt_regs, sp));
- if (!bt->machdep ||
+ if (extra_stacks_regs[extra_stacks_idx]->ur.pc &&
+ (bt->task != tt->panic_task) &&
+ (!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)) {
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
gdb_add_substack (extra_stacks_idx++);
}
}
@@ -3925,11 +3935,13 @@ arm64_back_trace_cmd_v2(struct bt_info *bt)
REG_SEQ(arm64_pt_regs, pc));
SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
REG_SEQ(arm64_pt_regs, sp));
- if (!bt->machdep ||
+ if (extra_stacks_regs[extra_stacks_idx]->ur.pc &&
+ (bt->task != tt->panic_task) &&
+ (!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)) {
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
gdb_add_substack (extra_stacks_idx++);
}
}
@@ -4232,6 +4244,46 @@ arm64_in_kdump_text_on_irq_stack(struct bt_info *bt)
return FALSE;
}
+static void
+arm64_gdb_add_next_frame_substack(struct bt_info *bt, const struct arm64_stackframe *frame)
+{
+ struct machine_specific *ms = machdep->machspec;
+ struct user_regs_bitmap_struct *ur_ptr;
+ ulong next_fp, next_pc, next_sp;
+
+ 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));
+ ur_ptr = extra_stacks_regs[extra_stacks_idx];
+
+ next_fp = GET_STACK_ULONG(frame->fp);
+ next_pc = GET_STACK_ULONG(frame->fp + 8);
+ next_sp = frame->fp + 16;
+
+ if (is_kernel_text(next_pc | ms->CONFIG_ARM64_KERNELPACMASK))
+ next_pc |= ms->CONFIG_ARM64_KERNELPACMASK;
+
+ ur_ptr->ur.pc = next_pc;
+ ur_ptr->ur.sp = next_sp;
+ ur_ptr->ur.regs[29] = next_fp;
+
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, pc));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, sp));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, regs[0]) + 29);
+
+ if (ur_ptr->ur.pc &&
+ (!bt->machdep ||
+ (ur_ptr->ur.sp !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+ ur_ptr->ur.pc !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+ gdb_add_substack(extra_stacks_idx++);
+ }
+}
+
static int
arm64_switch_stack(struct bt_info *bt, struct arm64_stackframe *frame, FILE *ofp)
{
@@ -4263,12 +4315,55 @@ arm64_switch_stack(struct bt_info *bt, struct arm64_stackframe *frame, FILE *ofp
if (frame->fp == 0)
return USER_MODE;
- if (!(machdep->flags & UNW_4_14))
+ if (!(machdep->flags & UNW_4_14)) {
arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+ } else {
+ arm64_gdb_add_next_frame_substack(bt, frame);
+ }
return KERNEL_MODE;
}
+static void
+arm64_gdb_add_next_frame_substack(struct bt_info *bt, const struct arm64_stackframe *frame)
+{
+ struct machine_specific *ms = machdep->machspec;
+ struct user_regs_bitmap_struct *ur_ptr;
+ ulong next_fp, next_pc, next_sp;
+
+ 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));
+ ur_ptr = extra_stacks_regs[extra_stacks_idx];
+
+ next_fp = GET_STACK_ULONG(frame->fp);
+ next_pc = GET_STACK_ULONG(frame->fp + 8);
+ next_sp = frame->fp + 16;
+
+ if (is_kernel_text(next_pc | ms->CONFIG_ARM64_KERNELPACMASK))
+ next_pc |= ms->CONFIG_ARM64_KERNELPACMASK;
+
+ ur_ptr->ur.pc = next_pc;
+ ur_ptr->ur.sp = next_sp;
+ ur_ptr->ur.regs[29] = next_fp;
+
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, pc));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, sp));
+ SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, regs[0]) + 29);
+
+ if (ur_ptr->ur.pc &&
+ (!bt->machdep ||
+ (ur_ptr->ur.sp !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+ ur_ptr->ur.pc !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+ gdb_add_substack(extra_stacks_idx++);
+ }
+}
+
static int
arm64_switch_stack_from_overflow(struct bt_info *bt, struct arm64_stackframe *frame, FILE *ofp)
{
@@ -4278,6 +4373,11 @@ arm64_switch_stack_from_overflow(struct bt_info *bt, struct arm64_stackframe *fr
char buf[BUFSIZE];
struct machine_specific *ms = machdep->machspec;
+ 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));
+ }
+
if (bt->flags & BT_FULL) {
stacktop = ms->overflow_stacks[bt->tc->processor] + ms->overflow_stack_size;
words = (stacktop - bt->bptr) / sizeof(ulong);
@@ -4300,8 +4400,11 @@ arm64_switch_stack_from_overflow(struct bt_info *bt, struct arm64_stackframe *fr
if (frame->fp == 0)
return USER_MODE;
- if (!(machdep->flags & UNW_4_14))
+ if (!(machdep->flags & UNW_4_14)) {
arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+ } else {
+ arm64_gdb_add_next_frame_substack(bt, frame);
+ }
return KERNEL_MODE;
}
@@ -4556,17 +4659,26 @@ arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int mode, FILE *o
}
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++);
- }
+ struct user_regs_bitmap_struct *ur_ptr = extra_stacks_regs[extra_stacks_idx];
+ int i;
+
+ ur_ptr->ur.pc = regs->pc;
+ ur_ptr->ur.sp = regs->sp;
+ ur_ptr->ur.pstate = regs->pstate;
+ for (i = 0; i < 31; i++)
+ ur_ptr->ur.regs[i] = regs->regs[i];
+
+ for (i = 0; i < 34; i++)
+ SET_BIT(ur_ptr->bitmap, i);
+
+ if (ur_ptr->ur.pc &&
+ (!bt->machdep ||
+ (ur_ptr->ur.sp !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+ ur_ptr->ur.pc !=
+ ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+ gdb_add_substack(extra_stacks_idx++);
+ }
}
}
--
2.34.1
3 weeks, 5 days
[PATCH v5 0/5] xarray: add large folio support
by Huang Shijie
The linux kernel supports the large folio for page cache by default.
But the current CRASH does not support the large folio.
So we may meet the errors when we detected the large folio sometimes,
such as in the email:
https://www.spinics.net/linux/fedora/redhat-crash-utility/msg11238.html
------------------------------
files: page_to_nid: invalid page: 0
files: page_to_nid: invalid page: 0
files: page_to_nid: invalid page: 0
files: page_to_nid: invalid page: 10
files: page_to_nid: invalid page: 10
files: page_to_nid: invalid page: 10
files: page_to_nid: invalid page: 20
files: page_to_nid: invalid page: 20
files: page_to_nid: invalid page: 20
files: page_to_nid: invalid page: 30
files: page_to_nid: invalid page: 30
files: page_to_nid: invalid page: 30
files: page_to_nid: invalid page: 40
files: page_to_nid: invalid page: 40
files: page_to_nid: invalid page: 40
files: page_to_nid: invalid page: 50
files: page_to_nid: invalid page: 50
files: page_to_nid: invalid page: 50
files: page_to_nid: invalid page: 60
files: page_to_nid: invalid page: 60
------------------------------
The patch 1 converts the ipcs.c to unix format. Please use following
commands for patch 1:
#git am 1.patch
#git apply --reject 1.patch
#git add -u
#git am --continue
The patches(2,3,4) are used to add large folio support for CRASH.
The patch 5 is newly version of an old patch:
it add "files -n" command.
v4-->v5:
Add a new patch to convert ipcs.c to unix format.
Rebased the patch set again.
v3-->v4:
Fixes the BPF bug by:
1.) patch 1: Add a new type for do_xarray_info
2.) patch 3: Check XARRAY_TYPE_PAGE_CACHE for
do_xarray_count()/do_xarray_dump()/do_xarray_dump_cb()
v2-->v3:
Rewrited the folio_order() in patch 2 to work with different
kernel versions.
v1-->v2:
1.) Rebase the kernel to later 7.0-rc1(merge window)
2.) Fixed a bug in the patch 3, the latest kernel supports folios
whose page order is bigger then 5:
"xarray: add large folio support"
Huang Shijie (5):
change to unix format for ipcs.c
xarray: add a new parameter for do_xarray
add folio_order function
xarray: add large folio support
add "files -n" command for an inode
bpf.c | 8 +-
defs.h | 14 +-
dev.c | 4 +-
diskdump.c | 10 +-
filesys.c | 94 ++-
help.c | 24 +-
ipcs.c | 2325 ++++++++++++++++++++++++++--------------------------
kernel.c | 4 +-
memory.c | 74 +-
symbols.c | 6 +
task.c | 4 +-
tools.c | 16 +-
12 files changed, 1390 insertions(+), 1193 deletions(-)
--
2.43.0
1 month
Re: [PATCH v5 3/5] add folio_order function
by Lianbo Jiang
On 3/18/26 8:24 PM, devel-request(a)lists.crash-utility.osci.io wrote:
> Date: Wed, 18 Mar 2026 20:23:38 +0800
> From: Huang Shijie<huangsj(a)hygon.cn>
> Subject: [Crash-utility] [PATCH v5 3/5] add folio_order function
> To:<ltao(a)redhat.com>,<k-hagio-ab(a)nec.com>,<lijiang(a)redhat.com>
> Cc:devel@lists.crash-utility.osci.io,zhongyuan@hygon.cn,
> fangbaoshun@hygon.cn,yingzhiwei@hygon.cn,1537577747(a)qq.com, Huang
> Shijie<huangsj(a)hygon.cn>
> Message-ID:<20260318122340.53291-4-huangsj(a)hygon.cn>
> Content-Type: text/plain
>
> The folio_order() was introduced to kernel at v5.16, but the first
> large folio support patch is in v5.17:
> 6795801366da "xfs: Support large folios"
>
> The folio_order() keeps the same logic as kernel code
> in different versions:
> 1.) In kernel v5.17, folio_order() uses page[1].compound_order to
> get the folio order.
>
> 2.) In kernel v6.1, the following patch introduces _folio_order:
> c3a15bff46cb5149 "mm: reimplement folio_order() and folio_nr_pages()"
>
> folio_order() uses _folio_order to get the folio order.
>
> 3.) In kernel v6.6, the following patch replaces the _folio_order with _flags_1:
> ebc1baf5c9b46c22 "mm: free up a word in the first tail page"
>
> folio_order() uses _flags_1 to get the folio order.
>
> This patch will be used in later patches.
>
> Signed-off-by: Huang Shijie<huangsj(a)hygon.cn>
> ---
> defs.h | 8 +++++++
> memory.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> symbols.c | 6 +++++
> 3 files changed, 84 insertions(+)
>
> diff --git a/defs.h b/defs.h
> index 8f6784e..e832ea6 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -2290,6 +2290,9 @@ struct offset_table { /* stash of commonly-used offsets */
> long bpf_ringbuf_nr_pages;
> long hrtimer_clock_base_index;
> long klp_patch_list;
> + long page_compound_order;
> + long folio__folio_order;
> + long folio__flags_1;
> };
>
> struct size_table { /* stash of commonly-used sizes */
> @@ -2469,6 +2472,9 @@ struct size_table { /* stash of commonly-used sizes */
> long cpumask_t;
> long task_struct_exit_state;
> long bpf_ringbuf_map;
> + long page_compound_order;
> + long folio__folio_order;
> + long folio__flags_1;
> };
>
> struct array_table {
> @@ -6008,6 +6014,8 @@ ulong do_xarray(ulong, int, struct list_pair *, int);
> #define XARRAY_TAG_MASK (3UL)
> #define XARRAY_TAG_INTERNAL (2UL)
>
> +int folio_order(ulong folio);
> +
> int file_dump(ulong, ulong, ulong, int, int);
> #define DUMP_FULL_NAME 0x1
> #define DUMP_INODE_ONLY 0x2
> diff --git a/memory.c b/memory.c
> index 17423a5..3b272ad 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -547,6 +547,13 @@ vm_init(void)
> MEMBER_OFFSET_INIT(page_freelist, "page", "freelist");
> MEMBER_OFFSET_INIT(page_page_type, "page", "page_type");
>
> + MEMBER_OFFSET_INIT(page_compound_order, "page", "compound_order");
> + MEMBER_SIZE_INIT(page_compound_order, "page", "compound_order");
> + MEMBER_OFFSET_INIT(folio__folio_order, "folio", "_folio_order");
> + MEMBER_SIZE_INIT(folio__folio_order, "folio", "_folio_order");
> + MEMBER_OFFSET_INIT(folio__flags_1, "folio", "_flags_1");
> + MEMBER_SIZE_INIT(folio__flags_1, "folio", "_flags_1");
> +
> MEMBER_OFFSET_INIT(mm_struct_pgd, "mm_struct", "pgd");
>
> MEMBER_OFFSET_INIT(swap_info_struct_swap_file,
> @@ -20426,6 +20433,69 @@ static unsigned int oo_objects(ulong oo)
> return (oo & ((1 << 16) - 1));
> }
>
> +/*
> + * The folio_order() was introduced to kernel at v5.16, but the first
> + * large folio support patch is in v5.17:
> + * 6795801366da "xfs: Support large folios"
> + *
> + * 1.) In kernel v5.17, folio_order() uses page[1].compound_order to
> + * get the folio order.
> + *
> + * 2.) In kernel v6.1, the following patch introduces _folio_order:
> + * c3a15bff46cb5149 "mm: reimplement folio_order() and folio_nr_pages()"
> + *
> + * folio_order() uses _folio_order to get the folio order.
> + *
> + * 3.) In kernel v6.6, the following patch replaces the _folio_order with _flags_1:
> + * ebc1baf5c9b46c22 "mm: free up a word in the first tail page"
> + *
> + * folio_order() uses _flags_1 to get the folio order.
> + */
For this check condition, It's not very good to use kernel version.
Let's investigate if there is a better way to handle this issue.
Lianbo
> +int
> +folio_order(ulong folio)
> +{
> + ulong v = 0;
> + int PG_head = 16;
> +
> + if (THIS_KERNEL_VERSION < LINUX(5,17,0))
> + return 0;
> +
> + if (THIS_KERNEL_VERSION < LINUX(6,1,0)) {
> + readmem(folio + OFFSET(page_flags), KVADDR, &v, sizeof(ulong),
> + "folio.page.flags", FAULT_ON_ERROR);
> + if (!(v & (1 << PG_head)))
> + return 0;
> +
> + readmem(folio + SIZE(page) + OFFSET(page_compound_order), KVADDR, &v,
> + SIZE(page_compound_order), "page[1].compound_order", FAULT_ON_ERROR);
> +
> + return v;
> + } else if (THIS_KERNEL_VERSION < LINUX(6,6,0)) {
> + readmem(folio + OFFSET(page_flags), KVADDR, &v, sizeof(ulong),
> + "folio.page.flags", FAULT_ON_ERROR);
> + if (!(v & (1 << PG_head)))
> + return 0;
> +
> + readmem(folio + OFFSET(folio__folio_order), KVADDR, &v,
> + SIZE(folio__folio_order), "folio->_folio_order", FAULT_ON_ERROR);
> +
> + return v;
> + } else {
> + /* The PG_head changes to bit 6 at kernel v6.6 */
> + PG_head = 6;
> +
> + readmem(folio + OFFSET(page_flags), KVADDR, &v, sizeof(ulong),
> + "folio.page.flags", FAULT_ON_ERROR);
> + if (!(v & (1 << PG_head)))
> + return 0;
> +
> + readmem(folio + OFFSET(folio__flags_1), KVADDR, &v,
> + SIZE(folio__flags_1), "folio->_flags_1", FAULT_ON_ERROR);
> +
> + return v & 0xff;
> + }
> +}
> +
> #ifdef NOT_USED
> ulong
> slab_to_kmem_cache_node(struct meminfo *si, ulong slab_page)
> diff --git a/symbols.c b/symbols.c
> index e6865ca..08c07e9 100644
> --- a/symbols.c
> +++ b/symbols.c
> @@ -10451,6 +10451,9 @@ dump_offset_table(char *spec, ulong makestruct)
> fprintf(fp, " page_private: %ld\n", OFFSET(page_private));
> fprintf(fp, " page_page_type: %ld\n",
> OFFSET(page_page_type));
> + fprintf(fp, " page_compound_order: %ld\n", OFFSET(page_compound_order));
> + fprintf(fp, " folio__folio_order: %ld\n", OFFSET(folio__folio_order));
> + fprintf(fp, " folio__flags_1: %ld\n", OFFSET(folio__flags_1));
>
> fprintf(fp, " trace_print_flags_mask: %ld\n",
> OFFSET(trace_print_flags_mask));
> @@ -11961,6 +11964,9 @@ dump_offset_table(char *spec, ulong makestruct)
> fprintf(fp, "\n size_table:\n");
> fprintf(fp, " page: %ld\n", SIZE(page));
> fprintf(fp, " page_flags: %ld\n", SIZE(page_flags));
> + fprintf(fp, " page_compound_order: %ld\n", SIZE(page_compound_order));
> + fprintf(fp, " folio__folio_order: %ld\n", SIZE(folio__folio_order));
> + fprintf(fp, " folio__flags_1: %ld\n", SIZE(folio__flags_1));
> fprintf(fp, " trace_print_flags: %ld\n", SIZE(trace_print_flags));
> fprintf(fp, " free_area_struct: %ld\n",
> SIZE(free_area_struct));
> -- 2.43.0
1 month
[PATCH 0/1] struct: add -F source-file scoping for duplicate datatype names
by chahuan
When different source files define same-name struct/union tags, crash may
resolve an unintended candidate because default type lookup depends on symbol
lookup order/context.
This series adds `struct/union -F <file_name>` to constrain datatype lookup to
the compilation-unit scope matched by the requested source file.
For example, this avoids ambiguity for duplicate tags such as
`arm_smmu_device` defined in both `arm-smmu.c` and `arm-smmu-v3.c`.
Implementation summary:
- Parse `-F` in `struct`/`union` command path and propagate `source_file` in
gdb requests.
- In gdb-side patch code, map source file -> unique scope block
(`objfile -> compunit -> filetabs -> blockvector`), prefer `STATIC_BLOCK`
and fallback to `GLOBAL_BLOCK`.
- Apply the scope temporarily for the request and restore previous scope
automatically afterward.
- If file match is missing or ambiguous, fail explicitly instead of choosing a
random candidate.
- Note: `-F` may add a small lookup-time overhead due to extra scope scanning
and symbol-table expansion needed for deterministic file-scoped matching.
Compatibility:
- Existing behavior is unchanged when `-F` is not used.
- Existing `STRUCT_SIZE/MEMBER_OFFSET/...` call paths remain compatible.
- For external/plugin callers that need file-scoped lookup with minimal changes,
expose two helper APIs:
- `char *set_temporary_datatype_filename(const char *source_file);`
- `void restore_datatype_filename(char *saved_source_file);`
chahuan (1):
struct: add -F source-file scoping for duplicate datatype names
cmdline.c | 1 +
defs.h | 4 ++
gdb-16.2.patch | 166 ++++++++++++++++++++++++++++++++++++++++++++++--
gdb_interface.c | 6 ++
help.c | 8 ++-
symbols.c | 31 ++++++++-
6 files changed, 206 insertions(+), 10 deletions(-)
--
2.43.0
1 month
[PATCH v2] RISC-V: improve error message for search command failure
by Austin Kim
The search command currently fails on RISC-V based vmcores
without providing specific details, only printing a generic 'invalid' message.
This patch enhances the debug output by including the specific virtual address
(before)
crash> search ffffffd8c2b42280
invalid
(after)
crash> search ffffffd8c2b42280
invalid for ffffffd800000000 address
Signed-off-by: Austin Kim <austindh.kim(a)gmail.com>
---
riscv64.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/riscv64.c b/riscv64.c
index eceae70..ee9d4e3 100644
--- a/riscv64.c
+++ b/riscv64.c
@@ -687,7 +687,7 @@ riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
return TRUE;
no_page:
- fprintf(fp, "invalid\n");
+ fprintf(fp, "invalid for %lx address\n", vaddr);
return FALSE;
}
@@ -1279,7 +1279,7 @@ riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
return TRUE;
no_page:
- fprintf(fp, "invalid\n");
+ fprintf(fp, "invalid for %lx address\n", vaddr);
return FALSE;
}
@@ -1368,7 +1368,7 @@ riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
return TRUE;
no_page:
- fprintf(fp, "invalid\n");
+ fprintf(fp, "invalid for %lx address\n", vaddr);
return FALSE;
}
--
2.34.1
1 month, 2 weeks
[PATCH] fix eheader overflow
by Bruno Faccini
crash-utility live session fails solid with a SEGV, where it seems
that with some (new ?) Kernels and configurations /proc/kcore
exposes a first “Note” program-header along with a big number of
other headers (particularly when direct-map area generated from
physical memory map have a lot of entries), causing eheader[]
overflow (a stack underflow in fact since it is an automatic
variable!) because the whole size exceeds MAX_KCORE_ELF_HEADER_SIZE.
This problem still occur with latest utility version, and the
following patch has been proven to fix.
Signed-off-by: Bruno Faccini <bfaccini(a)nvidia.com>
diff --git a/netdump.c b/netdump.c
index 452ef72..7697613 100644
--- a/netdump.c
+++ b/netdump.c
@@ -4664,7 +4664,12 @@ proc_kcore_init_32(FILE *fp, int kcore_fd)
clean_exit(1);
}
- BCOPY(&eheader[0], &pkd->elf_header[0], pkd->header_size);
+ if (read(fd, pkd->elf_header, pkd->header_size) != pkd->header_size) {
+ sprintf(buf, "/proc/kcore: read");
+ perror(buf);
+ goto bailout;
+ }
+
pkd->notes32 = (Elf32_Phdr *)&pkd->elf_header[elf32->e_phoff];
pkd->load32 = pkd->notes32 + 1;
pkd->flags |= KCORE_ELF32;
@@ -4738,7 +4743,12 @@ proc_kcore_init_64(FILE *fp, int kcore_fd)
clean_exit(1);
}
- BCOPY(&eheader[0], &pkd->elf_header[0], pkd->header_size);
+ if (read(fd, pkd->elf_header, pkd->header_size) != pkd->header_size) {
+ sprintf(buf, "/proc/kcore: read");
+ perror(buf);
+ goto bailout;
+ }
+
pkd->notes64 = (Elf64_Phdr *)&pkd->elf_header[elf64->e_phoff];
pkd->load64 = pkd->notes64 + 1;
pkd->flags |= KCORE_ELF64;
1 month, 2 weeks
[PATCH] RISC-V: improve error message for search command failure
by Austin Kim
The search command currently fails on RISC-V based vmcores
without providing specific details, only printing a generic 'invalid' message.
This patch enhances the debug output by including the specific virtual address
(before)
crash> search ffffffd8c2b42280
invalid
(after)
crash> search ffffffd8c2b42280
invalid for ffffffd800000000 address
Note: Work is in progress to fix the search command on RISC-V based vmcores.
Signed-off-by: Austin Kim <austindh.kim(a)gmail.com>
---
riscv64.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/riscv64.c b/riscv64.c
index eceae70..0b1aebd 100644
--- a/riscv64.c
+++ b/riscv64.c
@@ -687,7 +687,7 @@ riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
return TRUE;
no_page:
- fprintf(fp, "invalid\n");
+ fprintf(fp, "invalid for %lx address\n", vaddr);
return FALSE;
}
--
2.34.1
2 months, 1 week
Re: [PATCH 1/1] Fix cross-compilation of eppic.so and snapper.so
by lijiang
Hi, Petr
Thank you for the patch.
On Wed, Mar 18, 2026 at 11:36 AM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Thu, 12 Mar 2026 21:17:22 +0100
> From: Petr Tesařík <petr(a)tesarici.cz> (by way of Petr Tesařík
> <petr(a)tesarici.cz>)
> Subject: [Crash-utility] [PATCH 1/1] Fix cross-compilation of eppic.so
> and snapper.so
> To: devel(a)lists.crash-utility.osci.io
> Cc: Jianyun Gao <jianyungao89(a)gmail.com>
> Message-ID: <20260312211722.4cab3d5a(a)meshulam.tesarici.cz>
> Content-Type: text/plain; charset=US-ASCII
>
> When cross-compiling, the extension modules must be built for the
> target architecture, not the host architecture.
>
> Do not hard-code "gcc" (which is usually the host compiler), but
> use $(CC) to pick the right compiler.
>
> I got an error after applying the current patch:
$ make CROSS_COMPILE=aarch64-linux-gnu- extensions
aarch64-linux-gnu-gcc -Wall -g -shared -rdynamic -o dminfo.so dminfo.c
-fPIC -DARM64 -DGDB_16_2
aarch64-linux-gnu-gcc -Wall -g -shared -rdynamic -o echo.so echo.c -fPIC
-DARM64 -DGDB_16_2
cd eppic/libeppic && make
bison -peppic -v -t -d eppic.y
eppic.y: warning: 135 shift/reduce conflicts [-Wconflicts-sr]
eppic.y: warning: 22 reduce/reduce conflicts [-Wconflicts-rr]
eppic.y: note: rerun with option '-Wcounterexamples' to generate conflict
counterexamples
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_util.o eppic_util.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_node.o eppic_node.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_var.o eppic_var.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_func.o eppic_func.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_str.o eppic_str.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_op.o eppic_op.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_num.o eppic_num.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_stat.o eppic_stat.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_builtin.o eppic_builtin.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_type.o eppic_type.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_case.o eppic_case.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_api.o eppic_api.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_member.o eppic_member.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_alloc.o eppic_alloc.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_define.o eppic_define.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_input.o eppic_input.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_print.o eppic_print.c
bison -peppicpp -v -t -d eppicpp.y
eppicpp.y: warning: 23 shift/reduce conflicts [-Wconflicts-sr]
eppicpp.y: note: rerun with option '-Wcounterexamples' to generate conflict
counterexamples
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c eppicpp.tab.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c eppic.tab.c
flex -L -Peppic -t eppic.l > lex.eppic.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c lex.eppic.c
flex -Peppicpp -t eppicpp.l > lex.eppicpp.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c lex.eppicpp.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -o mkbaseop
mkbaseop.c
./mkbaseop > baseops.c
/bin/sh: 1: ./mkbaseop: Exec format error
make[5]: [Makefile:71: baseops.o] Error 126 (ignored)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Did I miss anything else?
...
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c baseops.c
ar cur libeppic.a eppic_util.o eppic_node.o eppic_var.o eppic_func.o
eppic_str.o eppic_op.o eppic_num.o eppic_stat.o eppic_builtin.o
eppic_type.o eppic_case.o eppic_api.o eppic_member.o eppic_alloc.o
eppic_define.o eppic_input.o eppic_print.o eppicpp.tab.o eppic.tab.o
lex.eppic.o lex.eppicpp.o baseops.o
ar: `u' modifier ignored since `D' is the default (see `U')
aarch64-linux-gnu-gcc -g -O0 -Ieppic/libeppic -I.. -nostartfiles -shared
-rdynamic -o eppic.so eppic/applications/crash/eppic.c -fPIC -DARM64
-DGDB_16_2 -Leppic/libeppic -leppic
aarch64-linux-gnu-gcc -Wall -g -I. -shared -rdynamic -o snap.so snap.c
-fPIC -DARM64 -DGDB_16_2
Thanks
Lianbo
> Signed-off-by: Petr Tesarik <ptesarik(a)suse.com>
> ---
> extensions/eppic.mk | 2 +-
> extensions/snap.mk | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/extensions/eppic.mk b/extensions/eppic.mk
> index 9435793..b51a84b 100644
> --- a/extensions/eppic.mk
> +++ b/extensions/eppic.mk
> @@ -68,7 +68,7 @@ lib-eppic:
> cd eppic/libeppic && make
>
> eppic.so: ../defs.h $(APPFILE) lib-eppic
> - gcc -g -O0 -Ieppic/libeppic -I.. -nostartfiles -shared -rdynamic
> -o eppic.so $(APPFILE) -fPIC $(TARGET_FLAGS) $(GDB_FLAGS) -Leppic/libeppic
> -leppic
> + $(CC) -g -O0 -Ieppic/libeppic -I.. -nostartfiles -shared -rdynamic
> -o eppic.so $(APPFILE) -fPIC $(TARGET_FLAGS) $(GDB_FLAGS) -Leppic/libeppic
> -leppic
>
> clean:
> if [ -d eppic/libeppic ]; \
> diff --git a/extensions/snap.mk b/extensions/snap.mk
> index 2fb4ed6..ac3f723 100644
> --- a/extensions/snap.mk
> +++ b/extensions/snap.mk
> @@ -47,4 +47,4 @@ endif
> all: snap.so
>
> snap.so: $(INCDIR)/defs.h snap.c
> - gcc -Wall -g -I$(INCDIR) -shared -rdynamic -o snap.so snap.c -fPIC
> -D$(TARGET) $(TARGET_CFLAGS) $(GDB_FLAGS)
> + $(CC) -Wall -g -I$(INCDIR) -shared -rdynamic -o snap.so snap.c
> -fPIC -D$(TARGET) $(TARGET_CFLAGS) $(GDB_FLAGS)
> --
> 2.53.0
>
2 months, 2 weeks
[PATCH v4 0/4] xarray: add large folio support
by Huang Shijie
The linux kernel supports the large folio for page cache by default.
But the current CRASH does not support the large folio.
So we may meet the errors when we detected the large folio sometimes,
such as in the email:
https://www.spinics.net/linux/fedora/redhat-crash-utility/msg11238.html
------------------------------
files: page_to_nid: invalid page: 0
files: page_to_nid: invalid page: 0
files: page_to_nid: invalid page: 0
files: page_to_nid: invalid page: 10
files: page_to_nid: invalid page: 10
files: page_to_nid: invalid page: 10
files: page_to_nid: invalid page: 20
files: page_to_nid: invalid page: 20
files: page_to_nid: invalid page: 20
files: page_to_nid: invalid page: 30
files: page_to_nid: invalid page: 30
files: page_to_nid: invalid page: 30
files: page_to_nid: invalid page: 40
files: page_to_nid: invalid page: 40
files: page_to_nid: invalid page: 40
files: page_to_nid: invalid page: 50
files: page_to_nid: invalid page: 50
files: page_to_nid: invalid page: 50
files: page_to_nid: invalid page: 60
files: page_to_nid: invalid page: 60
------------------------------
The first 3 patches are used to add large folio support for CRASH.
The last patch is newly version of an old patch:
it add "files -n" command.
v3->>v4:
Fixes the BPF bug by:
1.) patch 1: Add a new type for do_xarray_info
2.) patch 3: Check XARRAY_TYPE_PAGE_CACHE for
do_xarray_count()/do_xarray_dump()/do_xarray_dump_cb()
v2-->v3:
Rewrited the folio_order() in patch 2 to work with different
kernel versions.
v1-->v2:
1.) Rebase the kernel to later 7.0-rc1(merge window)
2.) Fixed a bug in the patch 3, the latest kernel supports folios
whose page order is bigger then 5:
"xarray: add large folio support"
Huang Shijie (4):
xarray: add a new parameter for do_xarray
add folio_order function
xarray: add large folio support
add "files -n" command for an inode
bpf.c | 8 ++---
defs.h | 14 +++++++-
dev.c | 4 +--
diskdump.c | 10 ++++--
filesys.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++-------
help.c | 24 +++++++++++++-
ipcs.c | 4 +--
kernel.c | 4 +--
memory.c | 74 ++++++++++++++++++++++++++++++++++++++++--
symbols.c | 6 ++++
task.c | 4 +--
tools.c | 16 ++++++++--
12 files changed, 230 insertions(+), 32 deletions(-)
--
2.43.0
2 months, 3 weeks