diff --git a/.gitignore b/.gitignore index 0a407bd..4d89d06 100644 --- a/.gitignore +++ b/.gitignore @@ -47,5 +47,6 @@ crash-5.0.6.tar.gz /crash-8.0.0.tar.gz /crash-8.0.1.tar.gz /crash-8.0.2.tar.gz +/crash-8.0.3.tar.gz /gdb-7.6.tar.gz /gdb-10.2.tar.gz diff --git a/0001-ps-Provide-an-option-to-display-no-header-line.patch b/0001-ps-Provide-an-option-to-display-no-header-line.patch deleted file mode 100644 index 0b6bd07..0000000 --- a/0001-ps-Provide-an-option-to-display-no-header-line.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 9f1256958d2b18953b4c8b244d88c023048a964f Mon Sep 17 00:00:00 2001 -From: Aaron Tomlin -Date: Tue, 29 Nov 2022 14:05:26 +0000 -Subject: [PATCH 01/28] ps: Provide an option to display no header line - -One might often find it useful to redirect/or filter the output -generated by the 'ps' command. This simple patch provides an option -(i.e. '-H') to display no header line so it does not need to be -considered e.g. - -crash> ps -u -H | head -5 - 1 0 1 ffff956e8028d280 IN 0.0 174276 9272 systemd - 1067 1 2 ffff956e81380000 IN 0.1 59480 15788 systemd-journal - 1080 1 0 ffff956e8d152940 IN 0.0 36196 3548 systemd-udevd - 1278 1 6 ffff956e8aa60000 IN 0.0 17664 3072 systemd-oomd - 1366 1 7 ffff956e88548000 IN 0.0 10868 2328 dbus-broker-lau - -Signed-off-by: Aaron Tomlin -Signed-off-by: Lianbo Jiang ---- - help.c | 3 ++- - task.c | 6 +++++- - 2 files changed, 7 insertions(+), 2 deletions(-) - -diff --git a/help.c b/help.c -index 99214c1590fa..14981cd01d48 100644 ---- a/help.c -+++ b/help.c -@@ -1379,7 +1379,7 @@ NULL - char *help_ps[] = { - "ps", - "display process status information", --"[-k|-u|-G|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S|-A]\n [pid | task | command] ...", -+"[-k|-u|-G|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S|-A|-H]\n [pid | task | command] ...", - " This command displays process status for selected, or all, processes" , - " in the system. If no arguments are entered, the process data is", - " is displayed for all processes. Specific processes may be selected", -@@ -1458,6 +1458,7 @@ char *help_ps[] = { - " -r display resource limits (rlimits) of selected, or all, tasks.", - " -S display a summary consisting of the number of tasks in a task state.", - " -A display only the active task on each cpu.", -+" -H display no header line.", - "\nEXAMPLES", - " Show the process status of all current tasks:\n", - " %s> ps", -diff --git a/task.c b/task.c -index db2abc8106a2..88941c7b0e4d 100644 ---- a/task.c -+++ b/task.c -@@ -3504,7 +3504,7 @@ cmd_ps(void) - cpuspec = NULL; - flag = 0; - -- while ((c = getopt(argcnt, args, "ASgstcpkuGlmarC:y:")) != EOF) { -+ while ((c = getopt(argcnt, args, "HASgstcpkuGlmarC:y:")) != EOF) { - switch(c) - { - case 'k': -@@ -3615,6 +3615,10 @@ cmd_ps(void) - flag |= PS_ACTIVE; - break; - -+ case 'H': -+ flag |= PS_NO_HEADER; -+ break; -+ - default: - argerrs++; - break; --- -2.37.1 - diff --git a/0002-arm64-fix-backtraces-of-KASAN-kernel-dumpfile-trunca.patch b/0002-arm64-fix-backtraces-of-KASAN-kernel-dumpfile-trunca.patch deleted file mode 100644 index fe5d2b3..0000000 --- a/0002-arm64-fix-backtraces-of-KASAN-kernel-dumpfile-trunca.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 5f27639196c3240810fbf30d367da0063a6612ff Mon Sep 17 00:00:00 2001 -From: Ding Hui -Date: Thu, 1 Dec 2022 15:01:45 +0800 -Subject: [PATCH 02/28] arm64: fix backtraces of KASAN kernel dumpfile - truncated - -We met "bt" command on KASAN kernel vmcore display truncated backtraces -like this: - - crash> bt - PID: 4131 TASK: ffff8001521df000 CPU: 3 COMMAND: "bash" - #0 [ffff2000224b0cb0] machine_kexec_prepare at ffff2000200bff4c - -After digging the root cause, it turns out that arm64_in_kdump_text() -found wrong bt->bptr at "machine_kexec" branch. - -Disassemble machine_kexec() of KASAN vmlinux (gcc 7.3.0): - - crash> dis -x machine_kexec - 0xffff2000200bff50 : stp x29, x30, [sp,#-208]! - 0xffff2000200bff54 : mov x29, sp - 0xffff2000200bff58 : stp x19, x20, [sp,#16] - 0xffff2000200bff5c : str x24, [sp,#56] - 0xffff2000200bff60 : str x26, [sp,#72] - 0xffff2000200bff64 : mov x2, #0x8ab3 - 0xffff2000200bff68 : add x1, x29, #0x70 - 0xffff2000200bff6c : lsr x1, x1, #3 - 0xffff2000200bff70 : movk x2, #0x41b5, lsl #16 - 0xffff2000200bff74 : mov x19, #0x200000000000 - 0xffff2000200bff78 : adrp x3, 0xffff2000224b0000 - 0xffff2000200bff7c : movk x19, #0xdfff, lsl #48 - 0xffff2000200bff80 : add x3, x3, #0xcb0 - 0xffff2000200bff84 : add x4, x1, x19 - 0xffff2000200bff88 : stp x2, x3, [x29,#112] - 0xffff2000200bff8c : adrp x2, 0xffff2000200bf000 - 0xffff2000200bff90 : add x2, x2, #0xf50 - 0xffff2000200bff94 : str x2, [x29,#128] - 0xffff2000200bff98 : mov w2, #0xf1f1f1f1 - 0xffff2000200bff9c : str w2, [x1,x19] - 0xffff2000200bffa0 : mov w2, #0xf200 - 0xffff2000200bffa4 : mov w1, #0xf3f3f3f3 - 0xffff2000200bffa8 : movk w2, #0xf2f2, lsl #16 - 0xffff2000200bffac : stp w2, w1, [x4,#4] - -We notice that: -1. machine_kexec() start address is 0xffff2000200bff50 -2. the instruction at machine_kexec+0x44 stores the same value - 0xffff2000200bff50 (comes from 0xffff2000200bf000 + 0xf50) - into stack postion [x29,#128]. - -When arm64_in_kdump_text() searches for LR from stack, it met -0xffff2000200bff50 firstly, so got wrong bt->bptr. - -We know that the real LR is always greater than the start address -of a function, so let's fix it by changing the search conditon to -(*ptr > xxx_start) && (*ptr < xxx_end). - -Signed-off-by: Ding Hui -Signed-off-by: Lianbo Jiang ---- - arm64.c | 18 +++++++++--------- - 1 file changed, 9 insertions(+), 9 deletions(-) - -diff --git a/arm64.c b/arm64.c -index c3e26a371a61..7e8a7db1fcc4 100644 ---- a/arm64.c -+++ b/arm64.c -@@ -3479,7 +3479,7 @@ arm64_in_kdump_text(struct bt_info *bt, struct arm64_stackframe *frame) - ms = machdep->machspec; - for (ptr = start - 8; ptr >= base; ptr--) { - if (bt->flags & BT_OPT_BACK_TRACE) { -- if ((*ptr >= ms->crash_kexec_start) && -+ if ((*ptr > ms->crash_kexec_start) && - (*ptr < ms->crash_kexec_end) && - INSTACK(*(ptr - 1), bt)) { - bt->bptr = ((ulong)(ptr - 1) - (ulong)base) -@@ -3488,7 +3488,7 @@ arm64_in_kdump_text(struct bt_info *bt, struct arm64_stackframe *frame) - fprintf(fp, "%lx: %lx (crash_kexec)\n", bt->bptr, *ptr); - return TRUE; - } -- if ((*ptr >= ms->crash_save_cpu_start) && -+ if ((*ptr > ms->crash_save_cpu_start) && - (*ptr < ms->crash_save_cpu_end) && - INSTACK(*(ptr - 1), bt)) { - bt->bptr = ((ulong)(ptr - 1) - (ulong)base) -@@ -3498,14 +3498,14 @@ arm64_in_kdump_text(struct bt_info *bt, struct arm64_stackframe *frame) - return TRUE; - } - } else { -- if ((*ptr >= ms->machine_kexec_start) && (*ptr < ms->machine_kexec_end)) { -+ if ((*ptr > ms->machine_kexec_start) && (*ptr < ms->machine_kexec_end)) { - bt->bptr = ((ulong)ptr - (ulong)base) - + task_to_stackbase(bt->tc->task); - if (CRASHDEBUG(1)) - fprintf(fp, "%lx: %lx (machine_kexec)\n", bt->bptr, *ptr); - return TRUE; - } -- if ((*ptr >= ms->crash_kexec_start) && (*ptr < ms->crash_kexec_end)) { -+ if ((*ptr > ms->crash_kexec_start) && (*ptr < ms->crash_kexec_end)) { - /* - * Stash the first crash_kexec frame in case the machine_kexec - * frame is not found. -@@ -3519,7 +3519,7 @@ arm64_in_kdump_text(struct bt_info *bt, struct arm64_stackframe *frame) - } - continue; - } -- if ((*ptr >= ms->crash_save_cpu_start) && (*ptr < ms->crash_save_cpu_end)) { -+ if ((*ptr > ms->crash_save_cpu_start) && (*ptr < ms->crash_save_cpu_end)) { - bt->bptr = ((ulong)ptr - (ulong)base) - + task_to_stackbase(bt->tc->task); - if (CRASHDEBUG(1)) -@@ -3566,7 +3566,7 @@ arm64_in_kdump_text_on_irq_stack(struct bt_info *bt) - - for (ptr = start - 8; ptr >= base; ptr--) { - if (bt->flags & BT_OPT_BACK_TRACE) { -- if ((*ptr >= ms->crash_kexec_start) && -+ if ((*ptr > ms->crash_kexec_start) && - (*ptr < ms->crash_kexec_end) && - INSTACK(*(ptr - 1), bt)) { - bt->bptr = ((ulong)(ptr - 1) - (ulong)base) + stackbase; -@@ -3576,7 +3576,7 @@ arm64_in_kdump_text_on_irq_stack(struct bt_info *bt) - FREEBUF(stackbuf); - return TRUE; - } -- if ((*ptr >= ms->crash_save_cpu_start) && -+ if ((*ptr > ms->crash_save_cpu_start) && - (*ptr < ms->crash_save_cpu_end) && - INSTACK(*(ptr - 1), bt)) { - bt->bptr = ((ulong)(ptr - 1) - (ulong)base) + stackbase; -@@ -3587,7 +3587,7 @@ arm64_in_kdump_text_on_irq_stack(struct bt_info *bt) - return TRUE; - } - } else { -- if ((*ptr >= ms->crash_kexec_start) && (*ptr < ms->crash_kexec_end)) { -+ if ((*ptr > ms->crash_kexec_start) && (*ptr < ms->crash_kexec_end)) { - bt->bptr = ((ulong)ptr - (ulong)base) + stackbase; - if (CRASHDEBUG(1)) - fprintf(fp, "%lx: %lx (crash_kexec on IRQ stack)\n", -@@ -3595,7 +3595,7 @@ arm64_in_kdump_text_on_irq_stack(struct bt_info *bt) - FREEBUF(stackbuf); - return TRUE; - } -- if ((*ptr >= ms->crash_save_cpu_start) && (*ptr < ms->crash_save_cpu_end)) { -+ if ((*ptr > ms->crash_save_cpu_start) && (*ptr < ms->crash_save_cpu_end)) { - bt->bptr = ((ulong)ptr - (ulong)base) + stackbase; - if (CRASHDEBUG(1)) - fprintf(fp, "%lx: %lx (crash_save_cpu on IRQ stack)\n", --- -2.37.1 - diff --git a/0003-arm64-handle-vabits_actual-symbol-missing-case.patch b/0003-arm64-handle-vabits_actual-symbol-missing-case.patch deleted file mode 100644 index 1aea6ff..0000000 --- a/0003-arm64-handle-vabits_actual-symbol-missing-case.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 141e75f3c11cc9342f11418e0bec86877424bef8 Mon Sep 17 00:00:00 2001 -From: Pavankumar Kondeti -Date: Thu, 8 Dec 2022 09:55:07 +0530 -Subject: [PATCH 03/28] arm64: handle vabits_actual symbol missing case - -After kernel commit 0d9b1ffefabe ("arm64: mm: make vabits_actual -a build time constant if possible") introduced in Linux v5.19, -the crash will not find vabits_actual symbol if VA_BITS <= 48. -Add a fallback option to initialize VA_BITS based on the user -supplied machdep option. - -Tested ramdumps loading in both 6.0 and 5.15 kernels. - -Signed-off-by: Pavankumar Kondeti -Signed-off-by: Lianbo Jiang ---- - arm64.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arm64.c b/arm64.c -index 7e8a7db1fcc4..56fb841f43f8 100644 ---- a/arm64.c -+++ b/arm64.c -@@ -4671,6 +4671,10 @@ arm64_calc_VA_BITS(void) - return; - } else if (arm64_set_va_bits_by_tcr()) { - return; -+ } else if (machdep->machspec->VA_BITS_ACTUAL) { -+ machdep->machspec->VA_BITS = machdep->machspec->VA_BITS_ACTUAL; -+ machdep->machspec->VA_START = _VA_START(machdep->machspec->VA_BITS_ACTUAL); -+ return; - } - - if (!(sp = symbol_search("swapper_pg_dir")) && --- -2.37.1 - diff --git a/0004-EPPIC-extension-support-for-crash-8.x-gdb-10.x.patch b/0004-EPPIC-extension-support-for-crash-8.x-gdb-10.x.patch deleted file mode 100644 index 18107d1..0000000 --- a/0004-EPPIC-extension-support-for-crash-8.x-gdb-10.x.patch +++ /dev/null @@ -1,479 +0,0 @@ -From 2f1085df4dc9c197be9a7a6828a381785058c7b7 Mon Sep 17 00:00:00 2001 -From: Luc Chouinard -Date: Fri, 9 Dec 2022 11:19:17 -0800 -Subject: [PATCH 04/28] EPPIC extension support for crash-8.x + gdb-10.x - -The previous version of the interface between eppic and crash/gdb was -messy and not portable. This new version uses a clean interface with -execution through the standard gnu_request and gdb command funnel. - -Signed-off-by: Luc Chouinard -Signed-off-by: Lianbo Jiang ---- - defs.h | 20 +++ - extensions/eppic.mk | 80 ++++++------ - gdb-10.2.patch | 302 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 364 insertions(+), 38 deletions(-) - -diff --git a/defs.h b/defs.h -index afdcf6c4ac20..67c9df2130a6 100644 ---- a/defs.h -+++ b/defs.h -@@ -4768,6 +4768,23 @@ static inline unsigned int __const_hweight8(unsigned long w) - - #endif /* !GDB_COMMON */ - -+typedef enum drill_ops_s { -+ EOP_MEMBER_SIZES, -+ EOP_MEMBER_NAME, -+ EOP_POINTER, -+ EOP_TYPEDEF, -+ EOP_INT, -+ EOP_VALUE, -+ EOP_ARRAY, -+ EOP_UNION, -+ EOP_ENUM, -+ EOP_ENUMVAL, -+ EOP_STRUCT, -+ EOP_FUNCTION, -+ EOP_DONE, -+ EOP_OOPS -+} drill_ops_t; -+ - /* - * Common request structure for BFD or GDB data or commands. - */ -@@ -4818,6 +4835,9 @@ struct gnu_request { - char *member_target_type_name; - char *member_target_type_tag_name; - char *type_tag_name; -+ /* callback function for 3rd party symbol and type (EPPIC for now) */ -+ void *priv; -+ int (*tcb)(drill_ops_t, struct gnu_request *, const void *, const void *, const void *, const void *); - }; - - /* -diff --git a/extensions/eppic.mk b/extensions/eppic.mk -index b9c046b710ad..943579346ece 100644 ---- a/extensions/eppic.mk -+++ b/extensions/eppic.mk -@@ -11,64 +11,68 @@ - - TARGET_FLAGS = -D$(TARGET) - ifeq ($(TARGET), PPC64) -- TARGET_FLAGS += -m64 -+ TARGET_FLAGS += -m64 - endif - ifeq ($(TARGET), ARM) -- TARGET_FLAGS += -m32 -+ TARGET_FLAGS += -m32 - endif - ifeq ($(TARGET), MIPS) -- TARGET_FLAGS += -m32 -+ TARGET_FLAGS += -m32 - endif - ifeq ($(TARGET), X86) -- TARGET_FLAGS += -m32 -+ TARGET_FLAGS += -m32 - endif - - APPFILE=eppic/applications/crash/eppic.c - GIT := $(shell which git 2> /dev/null) -+# crash 8 with gdb 10 uses new third party callback (tcb) API -+EPPIC_BRANCH=v5.0 - - all: -- @if [ -f /usr/bin/flex ] && [ -f /usr/bin/bison ]; then \ -- if [ -f ../$(GDB)/crash.target ]; \ -- then \ -- if [ ! -f $(APPFILE) ]; \ -- then \ -- if [ -f "$(GIT)" ]; \ -- then \ -- if [ -n "$(EPPIC_GIT_URL)" ]; then \ -- git clone $(EPPIC_GIT_OPTIONS) $(EPPIC_GIT_URL) eppic; \ -- else \ -- if ping -c 1 -W 5 github.com >/dev/null ; then \ -- git clone $(EPPIC_GIT_OPTIONS) https://github.com/lucchouina/eppic.git eppic; \ -- fi; \ -- fi; \ -- else \ -- if [ ! -f "$(GIT)" ]; then \ -- echo "eppic.so: git command is needed for pulling eppic extension code"; \ -- fi; \ -- fi; \ -- fi; \ -- if [ -f $(APPFILE) ]; \ -- then \ -- make -f eppic.mk eppic.so; \ -- else \ -- echo "eppic.so: failed to pull eppic code from git repo"; \ -- fi; \ -- else \ -- echo "eppic.so: build failed: requires the crash $(GDB) module"; \ -- fi ;\ -+ @if [ -f /usr/bin/flex ] && [ -f /usr/bin/bison ]; \ -+ then \ -+ if [ -f ../$(GDB)/crash.target ]; \ -+ then \ -+ if [ ! -f $(APPFILE) ]; \ -+ then \ -+ if [ -f "$(GIT)" ]; \ -+ then \ -+ if [ -n "$(EPPIC_GIT_URL)" ]; \ -+ then \ -+ git clone $(EPPIC_GIT_OPTIONS) $(EPPIC_GIT_URL) eppic; \ -+ else \ -+ if ping -c 1 -W 5 github.com >/dev/null ; then \ -+ git clone -b $(EPPIC_BRANCH) $(EPPIC_GIT_OPTIONS) https://github.com/lucchouina/eppic.git eppic; \ -+ fi; \ -+ fi; \ -+ else \ -+ if [ ! -f "$(GIT)" ]; then \ -+ echo "eppic.so: git command is needed for pulling eppic extension code"; \ -+ fi; \ -+ fi; \ -+ fi; \ -+ if [ -f $(APPFILE) ]; \ -+ then \ -+ make -f eppic.mk eppic.so; \ -+ else \ -+ echo "eppic.so: failed to pull eppic code from git repo"; \ -+ fi; \ -+ else \ -+ echo "eppic.so: build failed: requires the crash $(GDB) module"; \ -+ fi ;\ - else \ -- echo "eppic.so: build failed: requires /usr/bin/flex and /usr/bin/bison"; \ -- fi -+ echo "eppic.so: build failed: requires /usr/bin/flex and /usr/bin/bison"; \ -+ fi - - lib-eppic: - cd eppic/libeppic && make -- -+ - eppic.so: ../defs.h $(APPFILE) lib-eppic -- gcc -g -Ieppic/libeppic -I../$(GDB)/gdb -I../$(GDB)/bfd -I../$(GDB)/include -I../$(GDB)/gdb/config -I../$(GDB)/gdb/common -I../$(GDB) -nostartfiles -shared -rdynamic -o eppic.so $(APPFILE) -fPIC $(TARGET_FLAGS) $(GDB_FLAGS) -Leppic/libeppic -leppic -+ gcc -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 ]; \ - then \ -- cd eppic/libeppic && make -i clean; \ -+ cd eppic/libeppic && make -i clean; \ - fi - rm -f eppic.so -diff --git a/gdb-10.2.patch b/gdb-10.2.patch -index 91edfb338445..7055f6e0fb0b 100644 ---- a/gdb-10.2.patch -+++ b/gdb-10.2.patch -@@ -1737,3 +1737,305 @@ exit 0 - struct field *nextfield; - short nfields; - struct type *typedef_type, *target_type; -+--- gdb-10.2/gdb/symtab.c.orig -++++ gdb-10.2/gdb/symtab.c -+@@ -6913,7 +6913,7 @@ -+ #include "../../defs.h" -+ -+ static void get_member_data(struct gnu_request *, struct type *, long, int); -+-static void dump_enum(struct type *, struct gnu_request *); -++static void walk_enum(struct type *, struct gnu_request *); -+ static void eval_enum(struct type *, struct gnu_request *); -+ static void gdb_get_line_number(struct gnu_request *); -+ static void gdb_get_datatype(struct gnu_request *); -+@@ -7122,6 +7122,79 @@ -+ -+ -+ /* -++ * Follow the type linkage for full member and value type resolution, with callback -++ */ -++static void drillDownType(struct gnu_request *req, struct type *type) -++{ -++ while (type) -++ { -++ /* check out for stub types and pull in the definition instead */ -++ if (TYPE_STUB(type) && TYPE_TAG_NAME(type)) { -++ struct symbol *sym; -++ sym = lookup_symbol(TYPE_TAG_NAME(type), 0, STRUCT_DOMAIN, 0).symbol; -++ if (sym) -++ type = sym->type; -++ } -++ switch (TYPE_CODE(type)) { -++ drill_ops_t op; -++ long l1, l2; -++ int typecode; -++ -++ case TYPE_CODE_PTR: -++ req->tcb(EOP_POINTER, req, 0, 0, 0, 0); -++ break; -++ -++ case TYPE_CODE_TYPEDEF: -++ req->is_typedef = 1; -++ req->typecode = TYPE_CODE(type); -++ if (!req->tcb(EOP_TYPEDEF, req, TYPE_NAME(type), 0, 0, 0)) -++ return; -++ break; -++ -++ case TYPE_CODE_FUNC: -++ req->tcb(EOP_FUNCTION, req, 0, 0, 0, 0); -++ break; -++ -++ case TYPE_CODE_ARRAY: -++ l1 = TYPE_LENGTH (type); -++ l2 = TYPE_LENGTH (check_typedef(TYPE_TARGET_TYPE (type))); -++ req->tcb(EOP_ARRAY, req, &l1, &l2, 0, 0); -++ break; -++ -++ case TYPE_CODE_VOID: -++ case TYPE_CODE_INT: -++ case TYPE_CODE_BOOL: -++ l1 = TYPE_LENGTH(type); -++ req->tcb(EOP_INT, req, &l1, 0, 0, 0); -++ break; -++ -++ case TYPE_CODE_UNION: -++ op = EOP_UNION; -++ goto label; -++ -++ case TYPE_CODE_ENUM: -++ op = EOP_ENUM; -++ goto label; -++ -++ case TYPE_CODE_STRUCT: -++ op = EOP_STRUCT; -++ goto label; -++ -++ default: -++ typecode = TYPE_CODE(type); -++ req->tcb(EOP_OOPS, req, &typecode, "Unknown typecode", 0, 0); -++ return; /* not reached */ -++ -++ label: -++ l1 = TYPE_LENGTH(type); -++ req->tcb(op, req, &l1, type, TYPE_TAG_NAME(type), 0); -++ } -++ type = TYPE_TARGET_TYPE(type); -++ } -++ req->tcb(EOP_DONE, req, 0, 0, 0, 0); -++} -++ -++/* -+ * General purpose routine for determining datatypes. -+ */ -+ -+@@ -7149,10 +7222,8 @@ -+ if (req->member) -+ get_member_data(req, sym->type, 0, 1); -+ -+- if (TYPE_CODE(sym->type) == TYPE_CODE_ENUM) { -+- if (req->flags & GNU_PRINT_ENUMERATORS) -+- dump_enum(sym->type, req); -+- } -++ if (TYPE_CODE(sym->type) == TYPE_CODE_ENUM) -++ walk_enum(sym->type, req); -+ -+ return; -+ } -+@@ -7172,17 +7243,25 @@ -+ if (gdb_CRASHDEBUG(2)) -+ console("expr->elts[0].opcode: OP_VAR_VALUE\n"); -+ type = expr.get()->elts[2].symbol->type; -+- if (req->flags & GNU_VAR_LENGTH_TYPECODE) { -++ if (req->tcb) { -++ long value = SYMBOL_VALUE(expr->elts[2].symbol); -++ /* callback with symbol value */ -+ req->typecode = TYPE_CODE(type); -+- req->length = TYPE_LENGTH(type); -+- } -+- if (TYPE_CODE(type) == TYPE_CODE_ENUM) { -+- req->typecode = TYPE_CODE(type); -+- req->value = SYMBOL_VALUE(expr.get()->elts[2].symbol); -+- req->tagname = (char *)TYPE_TAG_NAME(type); -+- if (!req->tagname) { -+- val = evaluate_type(expr.get()); -+- eval_enum(value_type(val), req); -++ req->tcb(EOP_VALUE, req, &value, 0, 0, 0); -++ drillDownType(req, type); -++ } else { -++ if (req->flags & GNU_VAR_LENGTH_TYPECODE) { -++ req->typecode = TYPE_CODE(type); -++ req->length = TYPE_LENGTH(type); -++ } -++ if (TYPE_CODE(type) == TYPE_CODE_ENUM) { -++ req->typecode = TYPE_CODE(type); -++ req->value = SYMBOL_VALUE(expr->elts[2].symbol); -++ req->tagname = (char *)TYPE_TAG_NAME(type); -++ if (!req->tagname) { -++ val = evaluate_type(expr.get()); -++ eval_enum(value_type(val), req); -++ } -+ } -+ } -+ break; -+@@ -7192,26 +7271,21 @@ -+ console("expr->elts[0].opcode: OP_TYPE\n"); -+ type = expr.get()->elts[1].type; -+ -+- req->typecode = TYPE_CODE(type); -+- req->length = TYPE_LENGTH(type); -+- -+- if (TYPE_CODE(type) == TYPE_CODE_TYPEDEF) { -+- req->is_typedef = TYPE_CODE_TYPEDEF; -+- if ((typedef_type = check_typedef(type))) { -+- req->typecode = TYPE_CODE(typedef_type); -+- req->length = TYPE_LENGTH(typedef_type); -+- type = typedef_type; -+- } -+- } -+- -+- if (TYPE_CODE(type) == TYPE_CODE_ENUM) { -+- if (req->is_typedef) -+- if (req->flags & GNU_PRINT_ENUMERATORS) { -+- if (req->is_typedef) -+- fprintf_filtered(gdb_stdout, -+- "typedef "); -+- dump_enum(type, req); -++ if (req->tcb) { -++ drillDownType(req, type); -++ } else { -++ req->typecode = TYPE_CODE(type); -++ req->length = TYPE_LENGTH(type); -++ if (TYPE_CODE(type) == TYPE_CODE_TYPEDEF) { -++ req->is_typedef = TYPE_CODE_TYPEDEF; -++ if ((typedef_type = check_typedef(type))) { -++ req->typecode = TYPE_CODE(typedef_type); -++ req->length = TYPE_LENGTH(typedef_type); -++ type = typedef_type; -++ } -+ } -++ if (TYPE_CODE(type) == TYPE_CODE_ENUM) -++ walk_enum(type, req); -+ } -+ -+ if (req->member) -+@@ -7233,36 +7307,38 @@ -+ * identifier, each on its own line. -+ */ -+ static void -+-dump_enum(struct type *type, struct gnu_request *req) -++walk_enum(struct type *type, struct gnu_request *req) -+ { -+ int i; -+- int len; -++ int len, print = (req->flags & GNU_PRINT_ENUMERATORS); -+ long long lastval; -+ -+- len = TYPE_NFIELDS (type); -+- lastval = 0; -+- if (TYPE_TAG_NAME(type)) -+- fprintf_filtered(gdb_stdout, -+- "enum %s {\n", TYPE_TAG_NAME (type)); -+- else -+- fprintf_filtered(gdb_stdout, "enum {\n"); -++ if (print) { -++ if (req->is_typedef) -++ fprintf_filtered(gdb_stdout, "typedef "); -++ if (TYPE_TAG_NAME(type)) -++ fprintf_filtered(gdb_stdout, "enum %s {\n", TYPE_TAG_NAME (type)); -++ else -++ fprintf_filtered(gdb_stdout, "enum {\n"); -++ } -+ -++ len = TYPE_NFIELDS (type); -+ for (i = 0; i < len; i++) { -+- fprintf_filtered(gdb_stdout, " %s", -+- TYPE_FIELD_NAME (type, i)); -+- if (lastval != TYPE_FIELD_ENUMVAL (type, i)) { -+- fprintf_filtered (gdb_stdout, " = %s", -+- plongest(TYPE_FIELD_ENUMVAL (type, i))); -+- lastval = TYPE_FIELD_ENUMVAL (type, i); -+- } else -++ if (print) -++ fprintf_filtered(gdb_stdout, " %s", TYPE_FIELD_NAME (type, i)); -++ lastval = TYPE_FIELD_ENUMVAL (type, i); -++ if (print) { -+ fprintf_filtered(gdb_stdout, " = %s", plongest(lastval)); -+- fprintf_filtered(gdb_stdout, "\n"); -+- lastval++; -++ fprintf_filtered(gdb_stdout, "\n"); -++ } else if (req->tcb) -++ req->tcb(EOP_ENUMVAL, req, TYPE_FIELD_NAME (type, i), &lastval, 0, 0); -++ } -++ if (print) { -++ if (TYPE_TAG_NAME(type)) -++ fprintf_filtered(gdb_stdout, "};\n"); -++ else -++ fprintf_filtered(gdb_stdout, "} %s;\n", req->name); -+ } -+- if (TYPE_TAG_NAME(type)) -+- fprintf_filtered(gdb_stdout, "};\n"); -+- else -+- fprintf_filtered(gdb_stdout, "} %s;\n", req->name); -+ } -+ -+ /* -+@@ -7320,26 +7396,43 @@ -+ } -+ -+ for (i = 0; i < nfields; i++) { -+- if (STREQ(req->member, nextfield->name)) { -+- req->member_offset = offset + nextfield->loc.bitpos; -+- req->member_length = TYPE_LENGTH(nextfield->type()); -+- req->member_typecode = TYPE_CODE(nextfield->type()); -+- req->member_main_type_name = (char *)TYPE_NAME(nextfield->type()); -+- req->member_main_type_tag_name = (char *)TYPE_TAG_NAME(nextfield->type()); -+- target_type = TYPE_TARGET_TYPE(nextfield->type()); -+- if (target_type) { -+- req->member_target_type_name = (char *)TYPE_NAME(target_type); -+- req->member_target_type_tag_name = (char *)TYPE_TAG_NAME(target_type); -+- } -+- if ((req->member_typecode == TYPE_CODE_TYPEDEF) && -+- (typedef_type = check_typedef(nextfield->type()))) -+- req->member_length = TYPE_LENGTH(typedef_type); -+- return; -+- } else if (*nextfield->name == 0) { /* Anonymous struct/union */ -++ if (*nextfield->name == 0) { /* Anonymous struct/union */ -+ get_member_data(req, nextfield->type(), -+ offset + nextfield->loc.bitpos, 0); -+ if (req->member_offset != -1) -+ return; -++ } else { -++ /* callback may be just looking for a specific member name */ -++ if (req->tcb) { -++ if (req->tcb(EOP_MEMBER_NAME, req, nextfield->name, 0, 0, 0)) { -++ long bitpos = FIELD_BITPOS(*nextfield); -++ long bitsize = FIELD_BITSIZE(*nextfield); -++ long len = TYPE_LENGTH(nextfield->type()); -++ long byteOffset; -++ offset += nextfield->loc.bitpos; -++ byteOffset = offset/8; -++ console("EOP_MEMBER_SIZES\n"); -++ req->tcb(EOP_MEMBER_SIZES, req, &byteOffset, &len, &bitpos, &bitsize); -++ /* callback with full type info */ -++ drillDownType(req, nextfield->type()); -++ } -++ } else if (STREQ(req->member, nextfield->name)) { -++ req->member_offset = offset + nextfield->loc.bitpos; -++ req->member_length = TYPE_LENGTH(nextfield->type()); -++ req->member_typecode = TYPE_CODE(nextfield->type()); -++ req->member_main_type_name = (char *)TYPE_NAME(nextfield->type()); -++ req->member_main_type_tag_name = (char *)TYPE_TAG_NAME(nextfield->type()); -++ target_type = TYPE_TARGET_TYPE(nextfield->type()); -++ if (target_type) { -++ req->member_target_type_name = (char *)TYPE_NAME(target_type); -++ req->member_target_type_tag_name = (char *)TYPE_TAG_NAME(target_type); -++ } -++ if ((req->member_typecode == TYPE_CODE_TYPEDEF) && -++ (typedef_type = check_typedef(nextfield->type()))) { -++ req->member_length = TYPE_LENGTH(typedef_type); -++ } -++ return; -++ } -+ } -+ nextfield++; -+ } --- -2.37.1 - diff --git a/0005-x86_64-Fix-for-move-of-per-cpu-variables-into-struct.patch b/0005-x86_64-Fix-for-move-of-per-cpu-variables-into-struct.patch deleted file mode 100644 index cd1fdd5..0000000 --- a/0005-x86_64-Fix-for-move-of-per-cpu-variables-into-struct.patch +++ /dev/null @@ -1,144 +0,0 @@ -From df1f0cba729fa0e0d8a63220769c42cc9033acc1 Mon Sep 17 00:00:00 2001 -From: Kazuhito Hagio -Date: Wed, 7 Dec 2022 09:46:56 +0900 -Subject: [PATCH 05/28] x86_64: Fix for move of per-cpu variables into struct - pcpu_hot - -The following kernel commits, which are contained in Linux 6.2-rc1 and -later kernels, introduced struct pcpu_hot and moved several per-cpu -variables into it. - - d7b6d709a76a x86/percpu: Move irq_stack variables next to current_task - 7443b296e699 x86/percpu: Move cpu_number next to current_task - e57ef2ed97c1 x86: Put hot per CPU variables into a struct - -Without the patch, crash fails to start session with the following -error: - - $ crash vmlinux vmcore - ... - bt: invalid size request: 0 type: "stack contents" - bt: read of stack at 0 failed - - -Signed-off-by: Kazuhito Hagio -Signed-off-by: Lianbo Jiang ---- - x86_64.c | 44 +++++++++++++++++++++++++++++++++----------- - 1 file changed, 33 insertions(+), 11 deletions(-) - -diff --git a/x86_64.c b/x86_64.c -index 74bd1bbde41c..7a5d6f050c89 100644 ---- a/x86_64.c -+++ b/x86_64.c -@@ -1290,12 +1290,15 @@ x86_64_per_cpu_init(void) - { - int i, cpus, cpunumber; - struct machine_specific *ms; -- struct syment *irq_sp, *curr_sp, *cpu_sp, *hardirq_stack_ptr_sp; -+ struct syment *irq_sp, *curr_sp, *cpu_sp, *hardirq_stack_ptr_sp, *pcpu_sp; - ulong hardirq_stack_ptr; - ulong __per_cpu_load = 0; -+ long hardirq_addr = 0, cpu_addr = 0, curr_addr = 0; - - ms = machdep->machspec; - -+ pcpu_sp = per_cpu_symbol_search("pcpu_hot"); -+ - hardirq_stack_ptr_sp = per_cpu_symbol_search("hardirq_stack_ptr"); - irq_sp = per_cpu_symbol_search("per_cpu__irq_stack_union"); - cpu_sp = per_cpu_symbol_search("per_cpu__cpu_number"); -@@ -1324,7 +1327,7 @@ x86_64_per_cpu_init(void) - return; - } - -- if (!cpu_sp || (!irq_sp && !hardirq_stack_ptr_sp)) -+ if (!pcpu_sp && (!cpu_sp || (!irq_sp && !hardirq_stack_ptr_sp))) - return; - - if (MEMBER_EXISTS("irq_stack_union", "irq_stack")) -@@ -1337,10 +1340,21 @@ x86_64_per_cpu_init(void) - if (kernel_symbol_exists("__per_cpu_load")) - __per_cpu_load = symbol_value("__per_cpu_load"); - -+ if (pcpu_sp) { -+ hardirq_addr = pcpu_sp->value + MEMBER_OFFSET("pcpu_hot", "hardirq_stack_ptr"); -+ cpu_addr = pcpu_sp->value + MEMBER_OFFSET("pcpu_hot", "cpu_number"); -+ curr_addr = pcpu_sp->value + MEMBER_OFFSET("pcpu_hot", "current_task"); -+ } else { -+ if (hardirq_stack_ptr_sp) -+ hardirq_addr = hardirq_stack_ptr_sp->value; -+ cpu_addr = cpu_sp->value; -+ curr_addr = curr_sp->value; -+ } -+ - for (i = cpus = 0; i < NR_CPUS; i++) { - if (__per_cpu_load && kt->__per_cpu_offset[i] == __per_cpu_load) - break; -- if (!readmem(cpu_sp->value + kt->__per_cpu_offset[i], -+ if (!readmem(cpu_addr + kt->__per_cpu_offset[i], - KVADDR, &cpunumber, sizeof(int), - "cpu number (per_cpu)", QUIET|RETURN_ON_ERROR)) - break; -@@ -1349,8 +1363,8 @@ x86_64_per_cpu_init(void) - break; - cpus++; - -- if (hardirq_stack_ptr_sp) { -- if (!readmem(hardirq_stack_ptr_sp->value + kt->__per_cpu_offset[i], -+ if (pcpu_sp || hardirq_stack_ptr_sp) { -+ if (!readmem(hardirq_addr + kt->__per_cpu_offset[i], - KVADDR, &hardirq_stack_ptr, sizeof(void *), - "hardirq_stack_ptr (per_cpu)", QUIET|RETURN_ON_ERROR)) - continue; -@@ -1373,13 +1387,13 @@ x86_64_per_cpu_init(void) - else - kt->cpus = cpus; - -- if (DUMPFILE() && curr_sp) { -+ if (DUMPFILE() && (pcpu_sp || curr_sp)) { - if ((ms->current = calloc(kt->cpus, sizeof(ulong))) == NULL) - error(FATAL, - "cannot calloc %d x86_64 current pointers!\n", - kt->cpus); - for (i = 0; i < kt->cpus; i++) -- if (!readmem(curr_sp->value + kt->__per_cpu_offset[i], -+ if (!readmem(curr_addr + kt->__per_cpu_offset[i], - KVADDR, &ms->current[i], sizeof(ulong), - "current_task (per_cpu)", RETURN_ON_ERROR)) - continue; -@@ -5625,11 +5639,19 @@ x86_64_get_smp_cpus(void) - char *cpu_pda_buf; - ulong level4_pgt, cpu_pda_addr; - struct syment *sp; -- ulong __per_cpu_load = 0; -+ ulong __per_cpu_load = 0, cpu_addr; - - if (!VALID_STRUCT(x8664_pda)) { -- if (!(sp = per_cpu_symbol_search("per_cpu__cpu_number")) || -- !(kt->flags & PER_CPU_OFF)) -+ -+ if (!(kt->flags & PER_CPU_OFF)) -+ return 1; -+ -+ if ((sp = per_cpu_symbol_search("pcpu_hot")) && -+ (cpu_addr = MEMBER_OFFSET("pcpu_hot", "cpu_number")) != INVALID_OFFSET) -+ cpu_addr += sp->value; -+ else if ((sp = per_cpu_symbol_search("per_cpu__cpu_number"))) -+ cpu_addr = sp->value; -+ else - return 1; - - if (kernel_symbol_exists("__per_cpu_load")) -@@ -5638,7 +5660,7 @@ x86_64_get_smp_cpus(void) - for (i = cpus = 0; i < NR_CPUS; i++) { - if (__per_cpu_load && kt->__per_cpu_offset[i] == __per_cpu_load) - break; -- if (!readmem(sp->value + kt->__per_cpu_offset[i], -+ if (!readmem(cpu_addr + kt->__per_cpu_offset[i], - KVADDR, &cpunumber, sizeof(int), - "cpu number (per_cpu)", QUIET|RETURN_ON_ERROR)) - break; --- -2.37.1 - diff --git a/0006-Fix-for-mm_struct.rss_stat-conversion-into-percpu_co.patch b/0006-Fix-for-mm_struct.rss_stat-conversion-into-percpu_co.patch deleted file mode 100644 index b35160f..0000000 --- a/0006-Fix-for-mm_struct.rss_stat-conversion-into-percpu_co.patch +++ /dev/null @@ -1,163 +0,0 @@ -From f182d08bab202dddf20b742fef6cc2bda0a56d6c Mon Sep 17 00:00:00 2001 -From: Kazuhito Hagio -Date: Thu, 15 Dec 2022 11:31:38 +0900 -Subject: [PATCH 06/28] Fix for mm_struct.rss_stat conversion into - percpu_counter - -Kernel commit f1a7941243c1 ("mm: convert mm's rss stats into -percpu_counter"), which is contained in Linux 6.2-rc1 and later -kernels, changed mm_struct.rss_stat from struct mm_rss_stat into an -array of struct percpu_counter. - -Without the patch, "ps" and several commands fail with the following -error message: - - ps: invalid structure member offset: mm_rss_stat_count - FILE: memory.c LINE: 4724 FUNCTION: get_task_mem_usage() - -Signed-off-by: Kazuhito Hagio -Signed-off-by: Lianbo Jiang ---- - defs.h | 3 +++ - kernel.c | 2 ++ - memory.c | 14 +++++++++++++- - symbols.c | 6 ++++-- - tools.c | 28 ++++++++++++++++++++++++++++ - 5 files changed, 50 insertions(+), 3 deletions(-) - -diff --git a/defs.h b/defs.h -index 67c9df2130a6..04476b3ff62e 100644 ---- a/defs.h -+++ b/defs.h -@@ -2181,6 +2181,7 @@ struct offset_table { /* stash of commonly-used offsets */ - long blk_mq_tags_nr_reserved_tags; - long blk_mq_tags_rqs; - long request_queue_hctx_table; -+ long percpu_counter_counters; - }; - - struct size_table { /* stash of commonly-used sizes */ -@@ -2351,6 +2352,7 @@ struct size_table { /* stash of commonly-used sizes */ - long sbitmap_queue; - long sbq_wait_state; - long blk_mq_tags; -+ long percpu_counter; - }; - - struct array_table { -@@ -5325,6 +5327,7 @@ struct rb_node *rb_right(struct rb_node *, struct rb_node *); - struct rb_node *rb_left(struct rb_node *, struct rb_node *); - struct rb_node *rb_next(struct rb_node *); - struct rb_node *rb_last(struct rb_root *); -+long percpu_counter_sum_positive(ulong fbc); - - /* - * symbols.c -diff --git a/kernel.c b/kernel.c -index aa030e8097ea..a42e6ad7d78c 100644 ---- a/kernel.c -+++ b/kernel.c -@@ -316,6 +316,8 @@ kernel_init() - } - - MEMBER_OFFSET_INIT(percpu_counter_count, "percpu_counter", "count"); -+ MEMBER_OFFSET_INIT(percpu_counter_counters, "percpu_counter", "counters"); -+ STRUCT_SIZE_INIT(percpu_counter, "percpu_counter"); - - if (STRUCT_EXISTS("runqueue")) { - rqstruct = "runqueue"; -diff --git a/memory.c b/memory.c -index 9c15c1b745ef..9d003713534b 100644 ---- a/memory.c -+++ b/memory.c -@@ -4713,7 +4713,7 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm) - /* - * Latest kernels have mm_struct.mm_rss_stat[]. - */ -- if (VALID_MEMBER(mm_struct_rss_stat)) { -+ if (VALID_MEMBER(mm_struct_rss_stat) && VALID_MEMBER(mm_rss_stat_count)) { - long anonpages, filepages, count; - - anonpages = tt->anonpages; -@@ -4737,6 +4737,18 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm) - (anonpages * sizeof(long))); - if (count > 0) - rss += count; -+ -+ } else if (VALID_MEMBER(mm_struct_rss_stat)) { -+ /* 6.2: struct percpu_counter rss_stat[NR_MM_COUNTERS] */ -+ ulong fbc; -+ -+ fbc = tc->mm_struct + OFFSET(mm_struct_rss_stat) + -+ (tt->filepages * SIZE(percpu_counter)); -+ rss += percpu_counter_sum_positive(fbc); -+ -+ fbc = tc->mm_struct + OFFSET(mm_struct_rss_stat) + -+ (tt->anonpages * SIZE(percpu_counter)); -+ rss += percpu_counter_sum_positive(fbc); - } - - /* Check whether SPLIT_RSS_COUNTING is enabled */ -diff --git a/symbols.c b/symbols.c -index 42c4eb400044..e279cfa68490 100644 ---- a/symbols.c -+++ b/symbols.c -@@ -10633,8 +10633,8 @@ dump_offset_table(char *spec, ulong makestruct) - OFFSET(ktime_t_nsec)); - fprintf(fp, " atomic_t_counter: %ld\n", - OFFSET(atomic_t_counter)); -- fprintf(fp, " percpu_counter_count: %ld\n", -- OFFSET(percpu_counter_count)); -+ fprintf(fp, " percpu_counter_count: %ld\n", OFFSET(percpu_counter_count)); -+ fprintf(fp, " percpu_counter_counters: %ld\n", OFFSET(percpu_counter_counters)); - fprintf(fp, " sk_buff_head_next: %ld\n", - OFFSET(sk_buff_head_next)); - fprintf(fp, " sk_buff_head_qlen: %ld\n", -@@ -11028,6 +11028,8 @@ dump_offset_table(char *spec, ulong makestruct) - fprintf(fp, " sbq_wait_state: %ld\n", SIZE(sbq_wait_state)); - fprintf(fp, " blk_mq_tags: %ld\n", SIZE(blk_mq_tags)); - -+ fprintf(fp, " percpu_counter: %ld\n", SIZE(percpu_counter)); -+ - fprintf(fp, "\n array_table:\n"); - /* - * Use get_array_length() for those fields not set up at init-time; -diff --git a/tools.c b/tools.c -index 39306c18c98f..5f86771f5327 100644 ---- a/tools.c -+++ b/tools.c -@@ -6902,3 +6902,31 @@ rb_last(struct rb_root *root) - - return node; - } -+ -+long -+percpu_counter_sum_positive(ulong fbc) -+{ -+ int i, count; -+ ulong addr; -+ long ret; -+ -+ if (INVALID_MEMBER(percpu_counter_count)) -+ return 0; -+ -+ readmem(fbc + OFFSET(percpu_counter_count), KVADDR, &ret, -+ sizeof(long long), "percpu_counter.count", FAULT_ON_ERROR); -+ -+ if (INVALID_MEMBER(percpu_counter_counters)) /* !CONFIG_SMP */ -+ return (ret < 0) ? 0 : ret; -+ -+ readmem(fbc + OFFSET(percpu_counter_counters), KVADDR, &addr, -+ sizeof(void *), "percpu_counter.counters", FAULT_ON_ERROR); -+ -+ for (i = 0; i < kt->cpus; i++) { -+ readmem(addr + kt->__per_cpu_offset[i], KVADDR, &count, -+ sizeof(int), "percpu_counter.counters count", FAULT_ON_ERROR); -+ ret += count; -+ } -+ -+ return (ret < 0) ? 0 : ret; -+} --- -2.37.1 - diff --git a/0007-Fix-mount-command-to-appropriately-display-the-mount.patch b/0007-Fix-mount-command-to-appropriately-display-the-mount.patch deleted file mode 100644 index 0988428..0000000 --- a/0007-Fix-mount-command-to-appropriately-display-the-mount.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 88a4910d95d43a01151ad1d570035b96893bc7f1 Mon Sep 17 00:00:00 2001 -From: Lianbo Jiang -Date: Wed, 21 Dec 2022 17:09:08 +0800 -Subject: [PATCH 07/28] Fix "mount" command to appropriately display the mount - dumps - -Recently the following failure has been observed on some vmcores when -using the mount command: - - crash> mount - MOUNT SUPERBLK TYPE DEVNAME DIRNAME - ffff97a4818a3480 ffff979500013800 rootfs none / - ffff97e4846ca700 ffff97e484653000 sysfs sysfs /sys - ... - ffff97b484753420 0 mount: invalid kernel virtual address: 0 type: "super_block buffer" - -The kernel virtual address of the super_block is zero when the mount -command fails with the vfsmnt address 0xffff97b484753420. And the -remaining mount information will be discarded. That is not expected. - -Check the address and skip it with a warning, if this is an invalid -kernel virtual address, that can avoid truncating the remaining mount -dumps. - -Reported-by: Dave Wysochanski -Signed-off-by: Lianbo Jiang ---- - filesys.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/filesys.c b/filesys.c -index c2ea78de821d..d64b54a9b822 100644 ---- a/filesys.c -+++ b/filesys.c -@@ -1491,6 +1491,10 @@ show_mounts(ulong one_vfsmount, int flags, struct task_context *namespace_contex - } - - sbp = ULONG(vfsmount_buf + OFFSET(vfsmount_mnt_sb)); -+ if (!IS_KVADDR(sbp)) { -+ error(WARNING, "cannot get super_block from vfsmnt: 0x%lx\n", *vfsmnt); -+ continue; -+ } - - if (flags) - fprintf(fp, "%s", mount_hdr); --- -2.37.1 - diff --git a/0008-Add-RISCV64-framework-code-support.patch b/0008-Add-RISCV64-framework-code-support.patch deleted file mode 100644 index 71e427f..0000000 --- a/0008-Add-RISCV64-framework-code-support.patch +++ /dev/null @@ -1,692 +0,0 @@ -From 12c31560000adaaf3539f2bcdffff51ec05df447 Mon Sep 17 00:00:00 2001 -From: Xianting Tian -Date: Thu, 20 Oct 2022 09:50:06 +0800 -Subject: [PATCH 08/28] Add RISCV64 framework code support - -This patch mainly added some environment configurations, macro definitions, -specific architecture structures and some function declarations supported -by the RISCV64 architecture. - -We can use the build command to get the simplest version crash tool: - make target=RISCV64 -j2 - -Co-developed-by: Lifang Xia -Signed-off-by: Xianting Tian -Signed-off-by: Lianbo Jiang ---- - Makefile | 7 +- - README | 6 +- - configure.c | 43 ++++++++++++- - defs.h | 154 +++++++++++++++++++++++++++++++++++++++++++- - diskdump.c | 11 +++- - help.c | 6 +- - lkcd_vmdump_v1.h | 8 +-- - lkcd_vmdump_v2_v3.h | 8 +-- - netdump.c | 9 ++- - ramdump.c | 2 + - riscv64.c | 54 ++++++++++++++++ - symbols.c | 10 +++ - 12 files changed, 294 insertions(+), 24 deletions(-) - create mode 100644 riscv64.c - -diff --git a/Makefile b/Makefile -index 79aef1769444..1506dd426bc7 100644 ---- a/Makefile -+++ b/Makefile -@@ -64,7 +64,7 @@ CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \ - kernel.c test.c gdb_interface.c configure.c net.c dev.c bpf.c \ - printk.c \ - alpha.c x86.c ppc.c ia64.c s390.c s390x.c s390dbf.c ppc64.c x86_64.c \ -- arm.c arm64.c mips.c mips64.c sparc64.c \ -+ arm.c arm64.c mips.c mips64.c riscv64.c sparc64.c \ - extensions.c remote.c va_server.c va_server_v1.c symbols.c cmdline.c \ - lkcd_common.c lkcd_v1.c lkcd_v2_v3.c lkcd_v5.c lkcd_v7.c lkcd_v8.c\ - lkcd_fix_mem.c s390_dump.c lkcd_x86_trace.c \ -@@ -84,7 +84,7 @@ OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \ - build_data.o kernel.o test.o gdb_interface.o net.o dev.o bpf.o \ - printk.o \ - alpha.o x86.o ppc.o ia64.o s390.o s390x.o s390dbf.o ppc64.o x86_64.o \ -- arm.o arm64.o mips.o mips64.o sparc64.o \ -+ arm.o arm64.o mips.o mips64.o riscv64.o sparc64.o \ - extensions.o remote.o va_server.o va_server_v1.o symbols.o cmdline.o \ - lkcd_common.o lkcd_v1.o lkcd_v2_v3.o lkcd_v5.o lkcd_v7.o lkcd_v8.o \ - lkcd_fix_mem.o s390_dump.o netdump.o diskdump.o makedumpfile.o xendump.o \ -@@ -438,6 +438,9 @@ mips.o: ${GENERIC_HFILES} ${REDHAT_HFILES} mips.c - mips64.o: ${GENERIC_HFILES} ${REDHAT_HFILES} mips64.c - ${CC} -c ${CRASH_CFLAGS} mips64.c ${WARNING_OPTIONS} ${WARNING_ERROR} - -+riscv64.o: ${GENERIC_HFILES} ${REDHAT_HFILES} riscv64.c -+ ${CC} -c ${CRASH_CFLAGS} riscv64.c ${WARNING_OPTIONS} ${WARNING_ERROR} -+ - sparc64.o: ${GENERIC_HFILES} ${REDHAT_HFILES} sparc64.c - ${CC} -c ${CRASH_CFLAGS} sparc64.c ${WARNING_OPTIONS} ${WARNING_ERROR} - -diff --git a/README b/README -index 1f98fbf71df0..9850a29714b2 100644 ---- a/README -+++ b/README -@@ -37,8 +37,8 @@ - These are the current prerequisites: - - o At this point, x86, ia64, x86_64, ppc64, ppc, arm, arm64, alpha, mips, -- mips64, s390 and s390x-based kernels are supported. Other architectures -- may be addressed in the future. -+ mips64, riscv64, s390 and s390x-based kernels are supported. Other -+ architectures may be addressed in the future. - - o One size fits all -- the utility can be run on any Linux kernel version - version dating back to 2.2.5-15. A primary design goal is to always -@@ -98,6 +98,8 @@ - arm64 dumpfiles may be built by typing "make target=ARM64". - o On an x86_64 host, an x86_64 binary that can be used to analyze - ppc64le dumpfiles may be built by typing "make target=PPC64". -+ o On an x86_64 host, an x86_64 binary that can be used to analyze -+ riscv64 dumpfiles may be built by typing "make target=RISCV64". - - Traditionally when vmcores are compressed via the makedumpfile(8) facility - the libz compression library is used, and by default the crash utility -diff --git a/configure.c b/configure.c -index 51888519c18c..08b52be85e8d 100644 ---- a/configure.c -+++ b/configure.c -@@ -107,6 +107,7 @@ void add_extra_lib(char *); - #undef MIPS - #undef SPARC64 - #undef MIPS64 -+#undef RISCV64 - - #define UNKNOWN 0 - #define X86 1 -@@ -122,6 +123,7 @@ void add_extra_lib(char *); - #define MIPS 11 - #define SPARC64 12 - #define MIPS64 13 -+#define RISCV64 14 - - #define TARGET_X86 "TARGET=X86" - #define TARGET_ALPHA "TARGET=ALPHA" -@@ -136,6 +138,7 @@ void add_extra_lib(char *); - #define TARGET_MIPS "TARGET=MIPS" - #define TARGET_MIPS64 "TARGET=MIPS64" - #define TARGET_SPARC64 "TARGET=SPARC64" -+#define TARGET_RISCV64 "TARGET=RISCV64" - - #define TARGET_CFLAGS_X86 "TARGET_CFLAGS=-D_FILE_OFFSET_BITS=64" - #define TARGET_CFLAGS_ALPHA "TARGET_CFLAGS=" -@@ -158,6 +161,8 @@ void add_extra_lib(char *); - #define TARGET_CFLAGS_MIPS_ON_X86_64 "TARGET_CFLAGS=-m32 -D_FILE_OFFSET_BITS=64" - #define TARGET_CFLAGS_MIPS64 "TARGET_CFLAGS=" - #define TARGET_CFLAGS_SPARC64 "TARGET_CFLAGS=" -+#define TARGET_CFLAGS_RISCV64 "TARGET_CFLAGS=" -+#define TARGET_CFLAGS_RISCV64_ON_X86_64 "TARGET_CFLAGS=" - - #define GDB_TARGET_DEFAULT "GDB_CONF_FLAGS=" - #define GDB_TARGET_ARM_ON_X86 "GDB_CONF_FLAGS=--target=arm-elf-linux" -@@ -168,6 +173,7 @@ void add_extra_lib(char *); - #define GDB_TARGET_PPC64_ON_X86_64 "GDB_CONF_FLAGS=--target=powerpc64le-unknown-linux-gnu" - #define GDB_TARGET_MIPS_ON_X86 "GDB_CONF_FLAGS=--target=mipsel-elf-linux" - #define GDB_TARGET_MIPS_ON_X86_64 "GDB_CONF_FLAGS=--target=mipsel-elf-linux CFLAGS=-m32 CXXFLAGS=-m32" -+#define GDB_TARGET_RISCV64_ON_X86_64 "GDB_CONF_FLAGS=--target=riscv64-unknown-linux-gnu" - - /* - * The original plan was to allow the use of a particular version -@@ -404,6 +410,9 @@ get_current_configuration(struct supported_gdb_version *sp) - #ifdef __sparc_v9__ - target_data.target = SPARC64; - #endif -+#if defined(__riscv) && (__riscv_xlen == 64) -+ target_data.target = RISCV64; -+#endif - - set_initial_target(sp); - -@@ -457,6 +466,12 @@ get_current_configuration(struct supported_gdb_version *sp) - if ((target_data.initial_gdb_target != UNKNOWN) && - (target_data.host != target_data.initial_gdb_target)) - arch_mismatch(sp); -+ } else if ((target_data.target == X86_64) && -+ (name_to_target((char *)target_data.target_as_param) == RISCV64)) { -+ /* -+ * Build an RISCV64 crash binary on an X86_64 host. -+ */ -+ target_data.target = RISCV64; - } else { - fprintf(stderr, - "\ntarget=%s is not supported on the %s host architecture\n\n", -@@ -497,6 +512,14 @@ get_current_configuration(struct supported_gdb_version *sp) - (target_data.target != MIPS64)) - arch_mismatch(sp); - -+ if ((target_data.initial_gdb_target == RISCV64) && -+ (target_data.target != RISCV64)) { -+ if (target_data.target == X86_64) -+ target_data.target = RISCV64; -+ else -+ arch_mismatch(sp); -+ } -+ - if ((target_data.initial_gdb_target == X86) && - (target_data.target != X86)) { - if (target_data.target == X86_64) -@@ -660,6 +683,9 @@ show_configuration(void) - case SPARC64: - printf("TARGET: SPARC64\n"); - break; -+ case RISCV64: -+ printf("TARGET: RISCV64\n"); -+ break; - } - - if (strlen(target_data.program)) { -@@ -777,6 +803,14 @@ build_configure(struct supported_gdb_version *sp) - target = TARGET_SPARC64; - target_CFLAGS = TARGET_CFLAGS_SPARC64; - break; -+ case RISCV64: -+ target = TARGET_RISCV64; -+ if (target_data.host == X86_64) { -+ target_CFLAGS = TARGET_CFLAGS_RISCV64_ON_X86_64; -+ gdb_conf_flags = GDB_TARGET_RISCV64_ON_X86_64; -+ } else -+ target_CFLAGS = TARGET_CFLAGS_RISCV64; -+ break; - } - - ldflags = get_extra_flags("LDFLAGS.extra", NULL); -@@ -1374,7 +1408,7 @@ make_spec_file(struct supported_gdb_version *sp) - printf("Vendor: Red Hat, Inc.\n"); - printf("Packager: Dave Anderson \n"); - printf("ExclusiveOS: Linux\n"); -- printf("ExclusiveArch: %%{ix86} alpha ia64 ppc ppc64 ppc64pseries ppc64iseries x86_64 s390 s390x arm aarch64 ppc64le mips mipsel mips64el sparc64\n"); -+ printf("ExclusiveArch: %%{ix86} alpha ia64 ppc ppc64 ppc64pseries ppc64iseries x86_64 s390 s390x arm aarch64 ppc64le mips mipsel mips64el sparc64 riscv64\n"); - printf("Buildroot: %%{_tmppath}/%%{name}-root\n"); - printf("BuildRequires: ncurses-devel zlib-devel bison\n"); - printf("Requires: binutils\n"); -@@ -1613,6 +1647,8 @@ set_initial_target(struct supported_gdb_version *sp) - target_data.initial_gdb_target = MIPS; - else if (strncmp(buf, "SPARC64", strlen("SPARC64")) == 0) - target_data.initial_gdb_target = SPARC64; -+ else if (strncmp(buf, "RISCV64", strlen("RISCV64")) == 0) -+ target_data.initial_gdb_target = RISCV64; - } - - char * -@@ -1633,6 +1669,7 @@ target_to_name(int target) - case MIPS: return("MIPS"); - case MIPS64: return("MIPS64"); - case SPARC64: return("SPARC64"); -+ case RISCV64: return("RISCV64"); - } - - return "UNKNOWN"; -@@ -1697,6 +1734,10 @@ name_to_target(char *name) - return MIPS64; - else if (strncmp(name, "sparc64", strlen("sparc64")) == 0) - return SPARC64; -+ else if (strncmp(name, "RISCV64", strlen("RISCV64")) == 0) -+ return RISCV64; -+ else if (strncmp(name, "riscv64", strlen("riscv64")) == 0) -+ return RISCV64; - - return UNKNOWN; - } -diff --git a/defs.h b/defs.h -index 04476b3ff62e..7702ab050f26 100644 ---- a/defs.h -+++ b/defs.h -@@ -76,7 +76,7 @@ - #if !defined(X86) && !defined(X86_64) && !defined(ALPHA) && !defined(PPC) && \ - !defined(IA64) && !defined(PPC64) && !defined(S390) && !defined(S390X) && \ - !defined(ARM) && !defined(ARM64) && !defined(MIPS) && !defined(MIPS64) && \ -- !defined(SPARC64) -+ !defined(RISCV64) && !defined(SPARC64) - #ifdef __alpha__ - #define ALPHA - #endif -@@ -118,6 +118,9 @@ - #ifdef __sparc_v9__ - #define SPARC64 - #endif -+#if defined(__riscv) && (__riscv_xlen == 64) -+#define RISCV64 -+#endif - #endif - - #ifdef X86 -@@ -159,6 +162,9 @@ - #ifdef SPARC64 - #define NR_CPUS (4096) - #endif -+#ifdef RISCV64 -+#define NR_CPUS (256) -+#endif - - #define NR_DEVICE_DUMPS (64) - -@@ -3486,6 +3492,63 @@ struct arm64_stackframe { - #define _MAX_PHYSMEM_BITS 48 - #endif /* MIPS64 */ - -+#ifdef RISCV64 -+#define _64BIT_ -+#define MACHINE_TYPE "RISCV64" -+ -+/* -+ * Direct memory mapping -+ */ -+#define PTOV(X) \ -+ (((unsigned long)(X)+(machdep->kvbase)) - machdep->machspec->phys_base) -+#define VTOP(X) ({ \ -+ ulong _X = X; \ -+ (THIS_KERNEL_VERSION >= LINUX(5,13,0) && \ -+ (_X) >= machdep->machspec->kernel_link_addr) ? \ -+ (((unsigned long)(_X)-(machdep->machspec->kernel_link_addr)) + \ -+ machdep->machspec->phys_base): \ -+ (((unsigned long)(_X)-(machdep->kvbase)) + \ -+ machdep->machspec->phys_base); \ -+ }) -+#define PAGEBASE(X) (((ulong)(X)) & (ulong)machdep->pagemask) -+ -+/* -+ * Stack size order -+ */ -+#define THREAD_SIZE_ORDER 2 -+ -+#define PAGE_OFFSET (machdep->machspec->page_offset) -+#define VMALLOC_START (machdep->machspec->vmalloc_start_addr) -+#define VMALLOC_END (machdep->machspec->vmalloc_end) -+#define VMEMMAP_VADDR (machdep->machspec->vmemmap_vaddr) -+#define VMEMMAP_END (machdep->machspec->vmemmap_end) -+#define MODULES_VADDR (machdep->machspec->modules_vaddr) -+#define MODULES_END (machdep->machspec->modules_end) -+#define IS_VMALLOC_ADDR(X) riscv64_IS_VMALLOC_ADDR((ulong)(X)) -+ -+/* from arch/riscv/include/asm/pgtable.h */ -+#define __SWP_TYPE_SHIFT 6 -+#define __SWP_TYPE_BITS 5 -+#define __SWP_TYPE_MASK ((1UL << __SWP_TYPE_BITS) - 1) -+#define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) -+ -+#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS) -+ -+#define SWP_TYPE(entry) (((entry) >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK) -+#define SWP_OFFSET(entry) ((entry) >> __SWP_OFFSET_SHIFT) -+#define __swp_type(entry) SWP_TYPE(entry) -+#define __swp_offset(entry) SWP_OFFSET(entry) -+ -+#define TIF_SIGPENDING (THIS_KERNEL_VERSION >= LINUX(2,6,23) ? 1 : 2) -+ -+/* from arch/riscv/include/asm/sparsemem.h */ -+#define _SECTION_SIZE_BITS 27 -+#define _MAX_PHYSMEM_BITS 56 /* 56-bit physical address supported */ -+#define PHYS_MASK_SHIFT _MAX_PHYSMEM_BITS -+#define PHYS_MASK (((1UL) << PHYS_MASK_SHIFT) - 1) -+ -+#endif /* RISCV64 */ -+ - #ifdef X86 - #define _32BIT_ - #define MACHINE_TYPE "X86" -@@ -4534,6 +4597,10 @@ struct machine_specific { - #define MAX_HEXADDR_STRLEN (16) - #define UVADDR_PRLEN (16) - #endif -+#ifdef RISCV64 -+#define MAX_HEXADDR_STRLEN (16) -+#define UVADDR_PRLEN (16) -+#endif - - #define BADADDR ((ulong)(-1)) - #define BADVAL ((ulong)(-1)) -@@ -5149,6 +5216,9 @@ void dump_build_data(void); - #ifdef MIPS64 - #define machdep_init(X) mips64_init(X) - #endif -+#ifdef RISCV64 -+#define machdep_init(X) riscv64_init(X) -+#endif - #ifdef SPARC64 - #define machdep_init(X) sparc64_init(X) - #endif -@@ -5630,6 +5700,9 @@ void display_help_screen(char *); - #ifdef SPARC64 - #define dump_machdep_table(X) sparc64_dump_machdep_table(X) - #endif -+#ifdef RISCV64 -+#define dump_machdep_table(X) riscv64_dump_machdep_table(X) -+#endif - extern char *help_pointer[]; - extern char *help_alias[]; - extern char *help_ascii[]; -@@ -6707,6 +6780,85 @@ struct machine_specific { - - #endif /* MIPS64 */ - -+/* -+ * riscv64.c -+ */ -+void riscv64_display_regs_from_elf_notes(int, FILE *); -+ -+#ifdef RISCV64 -+void riscv64_init(int); -+void riscv64_dump_machdep_table(ulong); -+int riscv64_IS_VMALLOC_ADDR(ulong); -+ -+#define display_idt_table() \ -+ error(FATAL, "-d option is not applicable to RISCV64 architecture\n") -+ -+/* from arch/riscv/include/asm/ptrace.h */ -+struct riscv64_register { -+ ulong regs[36]; -+}; -+ -+struct riscv64_pt_regs { -+ ulong badvaddr; -+ ulong cause; -+ ulong epc; -+}; -+ -+struct riscv64_unwind_frame { -+ ulong fp; -+ ulong sp; -+ ulong pc; -+}; -+ -+#define KSYMS_START (0x1) -+ -+struct machine_specific { -+ ulong phys_base; -+ ulong page_offset; -+ ulong vmalloc_start_addr; -+ ulong vmalloc_end; -+ ulong vmemmap_vaddr; -+ ulong vmemmap_end; -+ ulong modules_vaddr; -+ ulong modules_end; -+ ulong kernel_link_addr; -+ -+ ulong _page_present; -+ ulong _page_read; -+ ulong _page_write; -+ ulong _page_exec; -+ ulong _page_user; -+ ulong _page_global; -+ ulong _page_accessed; -+ ulong _page_dirty; -+ ulong _page_soft; -+ -+ ulong _pfn_shift; -+ -+ struct riscv64_register *crash_task_regs; -+}; -+/* from arch/riscv/include/asm/pgtable-bits.h */ -+#define _PAGE_PRESENT (machdep->machspec->_page_present) -+#define _PAGE_READ (machdep->machspec->_page_read) -+#define _PAGE_WRITE (machdep->machspec->_page_write) -+#define _PAGE_EXEC (machdep->machspec->_page_exec) -+#define _PAGE_USER (machdep->machspec->_page_user) -+#define _PAGE_GLOBAL (machdep->machspec->_page_global) -+#define _PAGE_ACCESSED (machdep->machspec->_page_accessed) -+#define _PAGE_DIRTY (machdep->machspec->_page_dirty) -+#define _PAGE_SOFT (machdep->machspec->_page_soft) -+#define _PAGE_SEC (machdep->machspec->_page_sec) -+#define _PAGE_SHARE (machdep->machspec->_page_share) -+#define _PAGE_BUF (machdep->machspec->_page_buf) -+#define _PAGE_CACHE (machdep->machspec->_page_cache) -+#define _PAGE_SO (machdep->machspec->_page_so) -+#define _PAGE_SPECIAL _PAGE_SOFT -+#define _PAGE_TABLE _PAGE_PRESENT -+#define _PAGE_PROT_NONE _PAGE_READ -+#define _PAGE_PFN_SHIFT 10 -+ -+#endif /* RISCV64 */ -+ - /* - * sparc64.c - */ -diff --git a/diskdump.c b/diskdump.c -index 2c1f9be55c1f..28503bc286f8 100644 ---- a/diskdump.c -+++ b/diskdump.c -@@ -622,6 +622,9 @@ restart: - else if (STRNEQ(header->utsname.machine, "aarch64") && - machine_type_mismatch(file, "ARM64", NULL, 0)) - goto err; -+ else if (STRNEQ(header->utsname.machine, "riscv64") && -+ machine_type_mismatch(file, "RISCV64", NULL, 0)) -+ goto err; - - if (header->block_size != block_size) { - block_size = header->block_size; -@@ -780,6 +783,8 @@ restart: - dd->machine_type = EM_AARCH64; - else if (machine_type("SPARC64")) - dd->machine_type = EM_SPARCV9; -+ else if (machine_type("RISCV64")) -+ dd->machine_type = EM_RISCV; - else { - error(INFO, "%s: unsupported machine type: %s\n", - DISKDUMP_VALID() ? "diskdump" : "compressed kdump", -@@ -1751,7 +1756,8 @@ dump_note_offsets(FILE *fp) - qemu = FALSE; - if (machine_type("X86_64") || machine_type("S390X") || - machine_type("ARM64") || machine_type("PPC64") || -- machine_type("SPARC64") || machine_type("MIPS64")) { -+ machine_type("SPARC64") || machine_type("MIPS64") || -+ machine_type("RISCV64")) { - note64 = (void *)dd->notes_buf + tot; - len = sizeof(Elf64_Nhdr); - if (STRNEQ((char *)note64 + len, "QEMU")) -@@ -2558,7 +2564,8 @@ dump_registers_for_compressed_kdump(void) - if (!KDUMP_CMPRS_VALID() || (dd->header->header_version < 4) || - !(machine_type("X86") || machine_type("X86_64") || - machine_type("ARM64") || machine_type("PPC64") || -- machine_type("MIPS") || machine_type("MIPS64"))) -+ machine_type("MIPS") || machine_type("MIPS64") || -+ machine_type("RISCV64"))) - error(FATAL, "-r option not supported for this dumpfile\n"); - - if (machine_type("ARM64") && (kt->cpus != dd->num_prstatus_notes)) -diff --git a/help.c b/help.c -index 14981cd01d48..367500fc280d 100644 ---- a/help.c -+++ b/help.c -@@ -9513,8 +9513,8 @@ char *README[] = { - " These are the current prerequisites: ", - "", - " o At this point, x86, ia64, x86_64, ppc64, ppc, arm, arm64, alpha, mips,", --" mips64, s390 and s390x-based kernels are supported. Other architectures", --" may be addressed in the future.", -+" mips64, riscv64, s390 and s390x-based kernels are supported. Other", -+" architectures may be addressed in the future.", - "", - " o One size fits all -- the utility can be run on any Linux kernel version", - " version dating back to 2.2.5-15. A primary design goal is to always", -@@ -9573,6 +9573,8 @@ README_ENTER_DIRECTORY, - " arm64 dumpfiles may be built by typing \"make target=ARM64\".", - " o On an x86_64 host, an x86_64 binary that can be used to analyze", - " ppc64le dumpfiles may be built by typing \"make target=PPC64\".", -+" o On an x86_64 host, an x86_64 binary that can be used to analyze", -+" riscv64 dumpfiles may be built by typing \"make target=RISCV64\".", - "", - " Traditionally when vmcores are compressed via the makedumpfile(8) facility", - " the libz compression library is used, and by default the crash utility", -diff --git a/lkcd_vmdump_v1.h b/lkcd_vmdump_v1.h -index 4933427fc755..98ee09495869 100644 ---- a/lkcd_vmdump_v1.h -+++ b/lkcd_vmdump_v1.h -@@ -114,14 +114,8 @@ typedef struct _dump_header_s { - struct new_utsname dh_utsname; - - /* the dump registers */ --#ifndef IA64 --#ifndef S390 --#ifndef S390X --#ifndef ARM64 -+#if !defined(IA64) && !defined(S390) && !defined(S390X) && !defined(ARM64) && !defined(RISCV64) - struct pt_regs dh_regs; --#endif --#endif --#endif - #endif - - /* the address of the current task */ -diff --git a/lkcd_vmdump_v2_v3.h b/lkcd_vmdump_v2_v3.h -index 984c2c25e3c6..ef3067f88e1e 100644 ---- a/lkcd_vmdump_v2_v3.h -+++ b/lkcd_vmdump_v2_v3.h -@@ -37,7 +37,7 @@ - - #if defined(ARM) || defined(X86) || defined(PPC) || defined(S390) || \ - defined(S390X) || defined(ARM64) || defined(MIPS) || \ -- defined(MIPS64) || defined(SPARC64) -+ defined(MIPS64) || defined(SPARC64) || defined(RISCV64) - - /* - * Kernel header file for Linux crash dumps. -@@ -84,13 +84,9 @@ typedef struct _dump_header_asm_s { - uint32_t dha_eip; - - /* the dump registers */ --#ifndef S390 --#ifndef S390X --#ifndef ARM64 -+#if !defined(S390) && !defined(S390X) && !defined(ARM64) && !defined(RISCV64) - struct pt_regs dha_regs; - #endif --#endif --#endif - - } dump_header_asm_t; - -diff --git a/netdump.c b/netdump.c -index ff273b4fdfab..4ec12a073af6 100644 ---- a/netdump.c -+++ b/netdump.c -@@ -300,6 +300,12 @@ is_netdump(char *file, ulong source_query) - goto bailout; - break; - -+ case EM_RISCV: -+ if (machine_type_mismatch(file, "RISCV64", NULL, -+ source_query)) -+ goto bailout; -+ break; -+ - default: - if (machine_type_mismatch(file, "(unknown)", NULL, - source_query)) -@@ -2935,7 +2941,8 @@ dump_registers_for_elf_dumpfiles(void) - - if (!(machine_type("X86") || machine_type("X86_64") || - machine_type("ARM64") || machine_type("PPC64") || -- machine_type("MIPS") || machine_type("MIPS64"))) -+ machine_type("MIPS") || machine_type("MIPS64") || -+ machine_type("RISCV64"))) - error(FATAL, "-r option not supported for this dumpfile\n"); - - if (NETDUMP_DUMPFILE()) { -diff --git a/ramdump.c b/ramdump.c -index a206fcbbab3c..d2bd7ffb0b4b 100644 ---- a/ramdump.c -+++ b/ramdump.c -@@ -188,6 +188,8 @@ char *ramdump_to_elf(void) - e_machine = EM_MIPS; - else if (machine_type("X86_64")) - e_machine = EM_X86_64; -+ else if (machine_type("RISCV64")) -+ e_machine = EM_RISCV; - else - error(FATAL, "ramdump: unsupported machine type: %s\n", - MACHINE_TYPE); -diff --git a/riscv64.c b/riscv64.c -new file mode 100644 -index 000000000000..4f858a418a8c ---- /dev/null -+++ b/riscv64.c -@@ -0,0 +1,54 @@ -+/* riscv64.c - core analysis suite -+ * -+ * Copyright (C) 2022 Alibaba Group Holding Limited. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+#include "defs.h" -+#ifdef RISCV64 -+ -+#include -+ -+void -+riscv64_dump_machdep_table(ulong arg) -+{ -+} -+ -+/* -+ * Include both vmalloc'd and module address space as VMALLOC space. -+ */ -+int -+riscv64_IS_VMALLOC_ADDR(ulong vaddr) -+{ -+ return ((vaddr >= VMALLOC_START && vaddr <= VMALLOC_END) || -+ (vaddr >= VMEMMAP_VADDR && vaddr <= VMEMMAP_END) || -+ (vaddr >= MODULES_VADDR && vaddr <= MODULES_END)); -+} -+ -+void -+riscv64_init(int when) -+{ -+} -+ -+void -+riscv64_display_regs_from_elf_notes(int cpu, FILE *ofp) -+{ -+} -+ -+#else /* !RISCV64 */ -+ -+void -+riscv64_display_regs_from_elf_notes(int cpu, FILE *ofp) -+{ -+ return; -+} -+ -+#endif /* !RISCV64 */ -diff --git a/symbols.c b/symbols.c -index e279cfa68490..cb5b508dcc50 100644 ---- a/symbols.c -+++ b/symbols.c -@@ -3743,6 +3743,11 @@ is_kernel(char *file) - goto bailout; - break; - -+ case EM_RISCV: -+ if (machine_type_mismatch(file, "RISCV64", NULL, 0)) -+ goto bailout; -+ break; -+ - default: - if (machine_type_mismatch(file, "(unknown)", NULL, 0)) - goto bailout; -@@ -4002,6 +4007,11 @@ is_shared_object(char *file) - if (machine_type("MIPS64")) - return TRUE; - break; -+ -+ case EM_RISCV: -+ if (machine_type("RISCV64")) -+ return TRUE; -+ break; - } - - if (CRASHDEBUG(1)) --- -2.37.1 - diff --git a/0009-RISCV64-Make-crash-tool-enter-command-line-and-suppo.patch b/0009-RISCV64-Make-crash-tool-enter-command-line-and-suppo.patch deleted file mode 100644 index cda9ec7..0000000 --- a/0009-RISCV64-Make-crash-tool-enter-command-line-and-suppo.patch +++ /dev/null @@ -1,1287 +0,0 @@ -From e7119d2225e1db3c460285880ea39b69d362178e Mon Sep 17 00:00:00 2001 -From: Xianting Tian -Date: Thu, 20 Oct 2022 09:50:07 +0800 -Subject: [PATCH 09/28] RISCV64: Make crash tool enter command line and support - some commands - -1. Add riscv64_init() implementation, do all necessary machine-specific setup, - which will be called multiple times during initialization. -2. Add riscv64 sv39/48/57 pagetable macro definitions, the function of converting - virtual address to a physical address via 4K page table. - For 2M and 1G pagesize, they will be implemented in the future(currently not supported). -3. Add the implementation of the vtop command, which is used to convert a - virtual address to a physical address(call the functions defined in 2). -4. Add the implementation to get virtual memory layout, va_bits, phys_ram_base - from vmcoreinfo. As these configurations changes from time to time, we sent - a Linux kernel patch to export these configurations, which can simplify the - development of crash tool. - The kernel commit: 649d6b1019a2 ("RISC-V: Add arch_crash_save_vmcoreinfo") -5. Add riscv64_get_smp_cpus() implementation, get the number of cpus. -6. Add riscv64_get_page_size() implementation, get page size. -And so on. - -With this patch, we can enter crash command line, and run "vtop", "mod", "rd", -"*", "p", "kmem" ... - -Tested on QEMU RISCV64 end and SoC platform of T-head Xuantie 910 CPU. - - KERNEL: vmlinux - DUMPFILE: vmcore - CPUS: 1 - DATE: Fri Jul 15 10:24:25 CST 2022 - UPTIME: 00:00:33 -LOAD AVERAGE: 0.05, 0.01, 0.00 - TASKS: 41 - NODENAME: buildroot - RELEASE: 5.18.9 - VERSION: #30 SMP Fri Jul 15 09:47:03 CST 2022 - MACHINE: riscv64 (unknown Mhz) - MEMORY: 1 GB - PANIC: "Kernel panic - not syncing: sysrq triggered crash" - PID: 113 - COMMAND: "sh" - TASK: ff60000002269600 [THREAD_INFO: ff60000002269600] - CPU: 0 - STATE: TASK_RUNNING (PANIC) - -crash> p mem_map -mem_map = $1 = (struct page *) 0xff6000003effbf00 - -crash> p /x *(struct page *) 0xff6000003effbf00 -$5 = { - flags = 0x1000, - { - { - { - lru = { - next = 0xff6000003effbf08, - prev = 0xff6000003effbf08 - }, - { - __filler = 0xff6000003effbf08, - mlock_count = 0x3effbf08 - } - }, - mapping = 0x0, - index = 0x0, - private = 0x0 - }, - -crash> mod - MODULE NAME BASE SIZE OBJECT FILE -ffffffff0113e740 nvme_core ffffffff01133000 98304 (not loaded) [CONFIG_KALLSYMS] -ffffffff011542c0 nvme ffffffff0114c000 61440 (not loaded) [CONFIG_KALLSYMS] - -crash> rd ffffffff0113e740 8 -ffffffff0113e740: 0000000000000000 ffffffff810874f8 .........t...... -ffffffff0113e750: ffffffff011542c8 726f635f656d766e .B......nvme_cor -ffffffff0113e760: 0000000000000065 0000000000000000 e............... -ffffffff0113e770: 0000000000000000 0000000000000000 ................ - -crash> vtop ffffffff0113e740 -VIRTUAL PHYSICAL -ffffffff0113e740 8254d740 - - PGD: ffffffff810e9ff8 => 2ffff001 - P4D: 0000000000000000 => 000000002fffec01 - PUD: 00005605c2957470 => 0000000020949801 - PMD: 00007fff7f1750c0 => 0000000020947401 - PTE: 0 => 209534e7 - PAGE: 000000008254d000 - - PTE PHYSICAL FLAGS -209534e7 8254d000 (PRESENT|READ|WRITE|GLOBAL|ACCESSED|DIRTY) - - PAGE PHYSICAL MAPPING INDEX CNT FLAGS -ff6000003f0777d8 8254d000 0 0 1 0 - -Tested-by: Yixun Lan -Signed-off-by: Xianting Tian -Signed-off-by: Lianbo Jiang ---- - defs.h | 97 ++++++ - diskdump.c | 10 + - riscv64.c | 994 +++++++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 1101 insertions(+) - -diff --git a/defs.h b/defs.h -index 7702ab050f26..0cff47e30ae9 100644 ---- a/defs.h -+++ b/defs.h -@@ -3496,6 +3496,85 @@ struct arm64_stackframe { - #define _64BIT_ - #define MACHINE_TYPE "RISCV64" - -+typedef struct { ulong pgd; } pgd_t; -+typedef struct { ulong p4d; } p4d_t; -+typedef struct { ulong pud; } pud_t; -+typedef struct { ulong pmd; } pmd_t; -+typedef struct { ulong pte; } pte_t; -+typedef signed int s32; -+ -+/* arch/riscv/include/asm/pgtable-64.h */ -+#define PGD_SHIFT_L3 (30) -+#define PGD_SHIFT_L4 (39) -+#define PGD_SHIFT_L5 (48) -+ -+#define P4D_SHIFT (39) -+#define PUD_SHIFT (30) -+#define PMD_SHIFT (21) -+ -+#define PTRS_PER_PGD (512) -+#define PTRS_PER_P4D (512) -+#define PTRS_PER_PUD (512) -+#define PTRS_PER_PMD (512) -+#define PTRS_PER_PTE (512) -+ -+/* -+ * Mask for bit 0~53(PROT and PPN) of PTE -+ * 63 6261 60 54 53 10 9 8 7 6 5 4 3 2 1 0 -+ * N PBMT Reserved P P N RSW D A G U X W R V -+ */ -+#define PTE_PFN_PROT_MASK 0x3FFFFFFFFFFFFF -+ -+/* -+ * 3-levels / 4K pages -+ * -+ * sv39 -+ * PGD | PMD | PTE | OFFSET | -+ * 9 | 9 | 9 | 12 | -+ */ -+#define pgd_index_l3_4k(addr) (((addr) >> PGD_SHIFT_L3) & (PTRS_PER_PGD - 1)) -+#define pmd_index_l3_4k(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) -+#define pte_index_l3_4k(addr) (((addr) >> PAGESHIFT()) & (PTRS_PER_PTE - 1)) -+ -+/* -+ * 4-levels / 4K pages -+ * -+ * sv48 -+ * PGD | PUD | PMD | PTE | OFFSET | -+ * 9 | 9 | 9 | 9 | 12 | -+ */ -+#define pgd_index_l4_4k(addr) (((addr) >> PGD_SHIFT_L4) & (PTRS_PER_PGD - 1)) -+#define pud_index_l4_4k(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) -+#define pmd_index_l4_4k(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) -+#define pte_index_l4_4k(addr) (((addr) >> PAGESHIFT()) & (PTRS_PER_PTE - 1)) -+ -+/* -+ * 5-levels / 4K pages -+ * -+ * sv57 -+ * PGD | P4D | PUD | PMD | PTE | OFFSET | -+ * 9 | 9 | 9 | 9 | 9 | 12 | -+ */ -+#define pgd_index_l5_4k(addr) (((addr) >> PGD_SHIFT_L5) & (PTRS_PER_PGD - 1)) -+#define p4d_index_l5_4k(addr) (((addr) >> P4D_SHIFT) & (PTRS_PER_P4D - 1)) -+#define pud_index_l5_4k(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) -+#define pmd_index_l5_4k(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) -+#define pte_index_l5_4k(addr) (((addr) >> PAGESHIFT()) & (PTRS_PER_PTE - 1)) -+ -+#define VM_L3_4K (0x2) -+#define VM_L3_2M (0x4) -+#define VM_L3_1G (0x8) -+#define VM_L4_4K (0x10) -+#define VM_L4_2M (0x20) -+#define VM_L4_1G (0x40) -+#define VM_L5_4K (0x80) -+#define VM_L5_2M (0x100) -+#define VM_L5_1G (0x200) -+ -+#define VM_FLAGS (VM_L3_4K | VM_L3_2M | VM_L3_1G | \ -+ VM_L4_4K | VM_L4_2M | VM_L4_1G | \ -+ VM_L5_4K | VM_L5_2M | VM_L5_1G) -+ - /* - * Direct memory mapping - */ -@@ -3547,6 +3626,14 @@ struct arm64_stackframe { - #define PHYS_MASK_SHIFT _MAX_PHYSMEM_BITS - #define PHYS_MASK (((1UL) << PHYS_MASK_SHIFT) - 1) - -+#define IS_LAST_P4D_READ(p4d) ((ulong)(p4d) == machdep->machspec->last_p4d_read) -+#define FILL_P4D(P4D, TYPE, SIZE) \ -+ if (!IS_LAST_P4D_READ(P4D)) { \ -+ readmem((ulonglong)((ulong)(P4D)), TYPE, machdep->machspec->p4d, \ -+ SIZE, "p4d page", FAULT_ON_ERROR); \ -+ machdep->machspec->last_p4d_read = (ulong)(P4D); \ -+ } -+ - #endif /* RISCV64 */ - - #ifdef X86 -@@ -6834,6 +6921,10 @@ struct machine_specific { - ulong _page_soft; - - ulong _pfn_shift; -+ ulong va_bits; -+ char *p4d; -+ ulong last_p4d_read; -+ ulong struct_page_size; - - struct riscv64_register *crash_task_regs; - }; -@@ -6857,6 +6948,12 @@ struct machine_specific { - #define _PAGE_PROT_NONE _PAGE_READ - #define _PAGE_PFN_SHIFT 10 - -+/* from 'struct pt_regs' definitions of RISC-V arch */ -+#define RISCV64_REGS_EPC 0 -+#define RISCV64_REGS_RA 1 -+#define RISCV64_REGS_SP 2 -+#define RISCV64_REGS_FP 8 -+ - #endif /* RISCV64 */ - - /* -diff --git a/diskdump.c b/diskdump.c -index 28503bc286f8..cf5f5d9ec59b 100644 ---- a/diskdump.c -+++ b/diskdump.c -@@ -1531,6 +1531,12 @@ get_diskdump_regs_mips(struct bt_info *bt, ulong *eip, ulong *esp) - machdep->get_stack_frame(bt, eip, esp); - } - -+static void -+get_diskdump_regs_riscv64(struct bt_info *bt, ulong *eip, ulong *esp) -+{ -+ machdep->get_stack_frame(bt, eip, esp); -+} -+ - static void - get_diskdump_regs_sparc64(struct bt_info *bt, ulong *eip, ulong *esp) - { -@@ -1610,6 +1616,10 @@ get_diskdump_regs(struct bt_info *bt, ulong *eip, ulong *esp) - get_diskdump_regs_sparc64(bt, eip, esp); - break; - -+ case EM_RISCV: -+ get_diskdump_regs_riscv64(bt, eip, esp); -+ break; -+ - default: - error(FATAL, "%s: unsupported machine type: %s\n", - DISKDUMP_VALID() ? "diskdump" : "compressed kdump", -diff --git a/riscv64.c b/riscv64.c -index 4f858a418a8c..d8de3d56e1b7 100644 ---- a/riscv64.c -+++ b/riscv64.c -@@ -16,10 +16,314 @@ - #ifdef RISCV64 - - #include -+#include -+ -+static ulong riscv64_get_page_size(void); -+static int riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, -+ physaddr_t *paddr, int verbose); -+static int riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, -+ physaddr_t *paddr, int verbose); -+static int riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, -+ physaddr_t *paddr, int verbose); -+static void riscv64_page_type_init(void); -+static int riscv64_is_kvaddr(ulong vaddr); -+static int riscv64_is_uvaddr(ulong vaddr, struct task_context *tc); -+static int riscv64_uvtop(struct task_context *tc, ulong vaddr, -+ physaddr_t *paddr, int verbose); -+static int riscv64_kvtop(struct task_context *tc, ulong kvaddr, -+ physaddr_t *paddr, int verbose); -+static void riscv64_cmd_mach(void); -+static int riscv64_translate_pte(ulong, void *, ulonglong); -+static int riscv64_init_active_task_regs(void); -+static int riscv64_get_crash_notes(void); -+static int riscv64_get_elf_notes(void); -+static void riscv64_get_va_range(struct machine_specific *ms); -+static void riscv64_get_va_bits(struct machine_specific *ms); -+static void riscv64_get_struct_page_size(struct machine_specific *ms); -+ -+#define REG_FMT "%016lx" -+#define SZ_2G 0x80000000 -+ -+/* -+ * Holds registers during the crash. -+ */ -+static struct riscv64_register *panic_task_regs; -+ -+/* from arch/riscv/include/asm/stacktrace.h */ -+struct stackframe { -+ ulong fp; -+ ulong ra; -+}; -+ -+static struct machine_specific riscv64_machine_specific = { -+ ._page_present = (1 << 0), -+ ._page_read = (1 << 1), -+ ._page_write = (1 << 2), -+ ._page_exec = (1 << 3), -+ ._page_user = (1 << 4), -+ ._page_global = (1 << 5), -+ ._page_accessed = (1 << 6), -+ ._page_dirty = (1 << 7), -+ ._page_soft = (1 << 8), -+ -+ .va_bits = 0, -+ .struct_page_size = 0, -+}; -+ -+static void -+pt_level_alloc(char **lvl, char *name) -+{ -+ size_t sz = PAGESIZE(); -+ void *pointer = malloc(sz); -+ -+ if (!pointer) -+ error(FATAL, name); -+ *lvl = pointer; -+} -+ -+static ulong -+riscv64_get_page_size(void) -+{ -+ return memory_page_size(); -+} -+ -+static ulong -+riscv64_vmalloc_start(void) -+{ -+ return ((ulong)VMALLOC_START); -+} -+ -+/* Get the size of struct page {} */ -+static void riscv64_get_struct_page_size(struct machine_specific *ms) -+{ -+ char *string; -+ -+ string = pc->read_vmcoreinfo("SIZE(page)"); -+ if (string) { -+ ms->struct_page_size = atol(string); -+ free(string); -+ } -+} -+ -+static void -+riscv64_cmd_mach(void) -+{ -+ /* TODO: */ -+} -+ -+static int -+riscv64_verify_symbol(const char *name, ulong value, char type) -+{ -+ /* TODO: */ -+ return TRUE; -+} - - void - riscv64_dump_machdep_table(ulong arg) - { -+ /* TODO: */ -+} -+ -+static ulong -+riscv64_processor_speed(void) -+{ -+ /* TODO: */ -+ return 0; -+} -+ -+static unsigned long riscv64_get_kernel_version(void) -+{ -+ char *string; -+ char buf[BUFSIZE]; -+ char *p1, *p2; -+ -+ if (THIS_KERNEL_VERSION) -+ return THIS_KERNEL_VERSION; -+ -+ string = pc->read_vmcoreinfo("OSRELEASE"); -+ if (string) { -+ strcpy(buf, string); -+ -+ p1 = p2 = buf; -+ while (*p2 != '.') -+ p2++; -+ *p2 = NULLCHAR; -+ kt->kernel_version[0] = atoi(p1); -+ -+ p1 = ++p2; -+ while (*p2 != '.') -+ p2++; -+ *p2 = NULLCHAR; -+ kt->kernel_version[1] = atoi(p1); -+ -+ p1 = ++p2; -+ while ((*p2 >= '0') && (*p2 <= '9')) -+ p2++; -+ *p2 = NULLCHAR; -+ kt->kernel_version[2] = atoi(p1); -+ free(string); -+ } -+ return THIS_KERNEL_VERSION; -+} -+ -+static void -+riscv64_get_phys_ram_base(struct machine_specific *ms) -+{ -+ unsigned long kernel_version = riscv64_get_kernel_version(); -+ -+ /* -+ * phys_ram_base is defined in Linux kernel since 5.14. -+ */ -+ if (kernel_version >= LINUX(5,14,0)) { -+ char *string; -+ if ((string = pc->read_vmcoreinfo("NUMBER(phys_ram_base)"))) { -+ ms->phys_base = atol(string); -+ free(string); -+ } else -+ error(FATAL, "cannot read phys_ram_base\n"); -+ } else -+ /* -+ * For qemu rv64 env and hardware platform, default phys base -+ * may different, eg, -+ * hardware platform: 0x200000 -+ * qemu rv64 env: 0x80200000 -+ * -+ * But we only can set one default value, in this case, qemu -+ * rv64 env may can't work. -+ */ -+ ms->phys_base = 0x200000; -+} -+ -+static void riscv64_get_va_bits(struct machine_specific *ms) -+{ -+ unsigned long kernel_version = riscv64_get_kernel_version(); -+ -+ /* -+ * VA_BITS is defined in Linux kernel since 5.17. So we use the -+ * default va bits 39 when Linux version < 5.17. -+ */ -+ if (kernel_version >= LINUX(5,17,0)) { -+ char *string; -+ if ((string = pc->read_vmcoreinfo("NUMBER(VA_BITS)"))) { -+ ms->va_bits = atol(string); -+ free(string); -+ } -+ } else -+ ms->va_bits = 39; -+} -+ -+static void riscv64_get_va_range(struct machine_specific *ms) -+{ -+ unsigned long kernel_version = riscv64_get_kernel_version(); -+ char *string; -+ -+ if ((string = pc->read_vmcoreinfo("NUMBER(PAGE_OFFSET)"))) { -+ ms->page_offset = htol(string, QUIET, NULL); -+ free(string); -+ } else -+ goto error; -+ -+ if ((string = pc->read_vmcoreinfo("NUMBER(VMALLOC_START)"))) { -+ ms->vmalloc_start_addr = htol(string, QUIET, NULL); -+ free(string); -+ } else -+ goto error; -+ -+ if ((string = pc->read_vmcoreinfo("NUMBER(VMALLOC_END)"))) { -+ ms->vmalloc_end = htol(string, QUIET, NULL); -+ free(string); -+ } else -+ goto error; -+ -+ if ((string = pc->read_vmcoreinfo("NUMBER(VMEMMAP_START)"))) { -+ ms->vmemmap_vaddr = htol(string, QUIET, NULL); -+ free(string); -+ } else -+ goto error; -+ -+ if ((string = pc->read_vmcoreinfo("NUMBER(VMEMMAP_END)"))) { -+ ms->vmemmap_end = htol(string, QUIET, NULL); -+ free(string); -+ } else -+ goto error; -+ -+ if ((string = pc->read_vmcoreinfo("NUMBER(KERNEL_LINK_ADDR)"))) { -+ ms->kernel_link_addr = htol(string, QUIET, NULL); -+ free(string); -+ } else -+ goto error; -+ -+ /* -+ * From Linux 5.13, the kernel mapping is moved to the last 2GB -+ * of the address space, modules use the 2GB memory range right -+ * before the kernel. Before Linux 5.13, modules area is embedded -+ * in vmalloc area. -+ * -+ */ -+ if (kernel_version >= LINUX(5,13,0)) { -+ if ((string = pc->read_vmcoreinfo("NUMBER(MODULES_VADDR)"))) { -+ ms->modules_vaddr = htol(string, QUIET, NULL); -+ free(string); -+ } else -+ goto error; -+ -+ if ((string = pc->read_vmcoreinfo("NUMBER(MODULES_END)"))) { -+ ms->modules_end = htol(string, QUIET, NULL); -+ free(string); -+ } else -+ goto error; -+ } else { -+ ms->modules_vaddr = ms->vmalloc_start_addr; -+ ms->modules_end = ms->vmalloc_end; -+ } -+ -+ if (CRASHDEBUG(1)) { -+ fprintf(fp, "vmemmap : 0x%lx - 0x%lx\n", -+ ms->vmemmap_vaddr, ms->vmemmap_end); -+ fprintf(fp, "vmalloc : 0x%lx - 0x%lx\n", -+ ms->vmalloc_start_addr, ms->vmalloc_end); -+ fprintf(fp, "mudules : 0x%lx - 0x%lx\n", -+ ms->modules_vaddr, ms->modules_end); -+ fprintf(fp, "lowmem : 0x%lx -\n", ms->page_offset); -+ fprintf(fp, "kernel link addr : 0x%lx\n", -+ ms->kernel_link_addr); -+ } -+ return; -+error: -+ error(FATAL, "cannot get vm layout\n"); -+} -+ -+static int -+riscv64_is_kvaddr(ulong vaddr) -+{ -+ if (IS_VMALLOC_ADDR(vaddr)) -+ return TRUE; -+ -+ return (vaddr >= machdep->kvbase); -+} -+ -+static int -+riscv64_is_uvaddr(ulong vaddr, struct task_context *unused) -+{ -+ if (IS_VMALLOC_ADDR(vaddr)) -+ return FALSE; -+ -+ return (vaddr < machdep->kvbase); -+} -+ -+static int -+riscv64_is_task_addr(ulong task) -+{ -+ if (tt->flags & THREAD_INFO) -+ return IS_KVADDR(task); -+ -+ return (IS_KVADDR(task) && ALIGNED_STACK_OFFSET(task) == 0); -+} -+ -+static int -+riscv64_get_smp_cpus(void) -+{ -+ return (get_cpus_present() > 0) ? get_cpus_present() : kt->cpus; - } - - /* -@@ -33,11 +337,701 @@ riscv64_IS_VMALLOC_ADDR(ulong vaddr) - (vaddr >= MODULES_VADDR && vaddr <= MODULES_END)); - } - -+/* -+ * Translate a PTE, returning TRUE if the page is present. -+ * If a physaddr pointer is passed in, don't print anything. -+ */ -+static int -+riscv64_translate_pte(ulong pte, void *physaddr, ulonglong unused) -+{ -+ char ptebuf[BUFSIZE]; -+ char physbuf[BUFSIZE]; -+ char buf[BUFSIZE]; -+ int page_present; -+ int len1, len2, others; -+ ulong paddr; -+ -+ paddr = PTOB(pte >> _PAGE_PFN_SHIFT); -+ page_present = !!(pte & _PAGE_PRESENT); -+ -+ if (physaddr) { -+ *(ulong *)physaddr = paddr; -+ return page_present; -+ } -+ -+ sprintf(ptebuf, "%lx", pte); -+ len1 = MAX(strlen(ptebuf), strlen("PTE")); -+ fprintf(fp, "%s ", mkstring(buf, len1, CENTER | LJUST, "PTE")); -+ -+ if (!page_present) -+ return page_present; -+ -+ sprintf(physbuf, "%lx", paddr); -+ len2 = MAX(strlen(physbuf), strlen("PHYSICAL")); -+ fprintf(fp, "%s ", mkstring(buf, len2, CENTER | LJUST, "PHYSICAL")); -+ -+ fprintf(fp, "FLAGS\n"); -+ fprintf(fp, "%s %s ", -+ mkstring(ptebuf, len1, CENTER | RJUST, NULL), -+ mkstring(physbuf, len2, CENTER | RJUST, NULL)); -+ -+ fprintf(fp, "("); -+ others = 0; -+ -+#define CHECK_PAGE_FLAG(flag) \ -+ if ((_PAGE_##flag) && (pte & _PAGE_##flag)) \ -+ fprintf(fp, "%s" #flag, others++ ? "|" : "") -+ if (pte) { -+ CHECK_PAGE_FLAG(PRESENT); -+ CHECK_PAGE_FLAG(READ); -+ CHECK_PAGE_FLAG(WRITE); -+ CHECK_PAGE_FLAG(EXEC); -+ CHECK_PAGE_FLAG(USER); -+ CHECK_PAGE_FLAG(GLOBAL); -+ CHECK_PAGE_FLAG(ACCESSED); -+ CHECK_PAGE_FLAG(DIRTY); -+ CHECK_PAGE_FLAG(SOFT); -+ } else { -+ fprintf(fp, "no mapping"); -+ } -+ -+ fprintf(fp, ")\n"); -+ -+ return page_present; -+} -+ -+static void -+riscv64_page_type_init(void) -+{ -+ ulong va_bits = machdep->machspec->va_bits; -+ -+ /* -+ * For RISCV64 arch, any level of PTE may be a leaf PTE, -+ * so in addition to 4KiB pages, -+ * Sv39 supports 2 MiB megapages, 1 GiB gigapages; -+ * Sv48 supports 2 MiB megapages, 1 GiB gigapages, 512 GiB terapages; -+ * Sv57 supports 2 MiB megapages, 1 GiB gigapages, 512 GiB terapages, and 256 TiB petapages. -+ * -+ * refs to riscv-privileged spec. -+ * -+ * We just support 4KiB, 2MiB, 1GiB now. -+ */ -+ switch (machdep->pagesize) -+ { -+ case 0x1000: // 4 KiB -+ machdep->flags |= (va_bits == 57 ? VM_L5_4K : -+ (va_bits == 48 ? VM_L4_4K : VM_L3_4K)); -+ break; -+ case 0x200000: // 2 MiB -+ /* TODO: */ -+ case 0x40000000: // 1 GiB -+ /* TODO: */ -+ default: -+ if (machdep->pagesize) -+ error(FATAL, "invalid/unsupported page size: %d\n", -+ machdep->pagesize); -+ else -+ error(FATAL, "cannot determine page size\n"); -+ } -+} -+ -+static int -+riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) -+{ -+ ulong *pgd_ptr, pgd_val; -+ ulong pmd_val; -+ ulong pte_val, pte_pfn; -+ ulong pt_phys; -+ -+ /* PGD */ -+ pgd_ptr = pgd + pgd_index_l3_4k(vaddr); -+ FILL_PGD(pgd, KVADDR, PAGESIZE()); -+ pgd_val = ULONG(machdep->pgd + PAGEOFFSET(pgd_ptr)); -+ if (verbose) -+ fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val); -+ if (!pgd_val) -+ goto no_page; -+ pgd_val &= PTE_PFN_PROT_MASK; -+ pt_phys = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); -+ -+ /* PMD */ -+ FILL_PMD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); -+ pmd_val = ULONG(machdep->pmd + PAGEOFFSET(sizeof(pmd_t) * -+ pmd_index_l3_4k(vaddr))); -+ if (verbose) -+ fprintf(fp, " PMD: %016lx => %016lx\n", pt_phys, pmd_val); -+ if (!pmd_val) -+ goto no_page; -+ pmd_val &= PTE_PFN_PROT_MASK; -+ pt_phys = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); -+ -+ /* PTE */ -+ FILL_PTBL(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); -+ pte_val = ULONG(machdep->ptbl + PAGEOFFSET(sizeof(pte_t) * -+ pte_index_l3_4k(vaddr))); -+ if (verbose) -+ fprintf(fp, " PTE: %lx => %lx\n", pt_phys, pte_val); -+ if (!pte_val) -+ goto no_page; -+ pte_val &= PTE_PFN_PROT_MASK; -+ pte_pfn = pte_val >> _PAGE_PFN_SHIFT; -+ -+ if (!(pte_val & _PAGE_PRESENT)) { -+ if (verbose) { -+ fprintf(fp, "\n"); -+ riscv64_translate_pte((ulong)pte_val, 0, 0); -+ } -+ fprintf(fp, " PAGE: %016lx not present\n\n", PAGEBASE(*paddr)); -+ return FALSE; -+ } -+ -+ *paddr = PTOB(pte_pfn) + PAGEOFFSET(vaddr); -+ -+ if (verbose) { -+ fprintf(fp, " PAGE: %016lx\n\n", PAGEBASE(*paddr)); -+ riscv64_translate_pte(pte_val, 0, 0); -+ } -+ -+ return TRUE; -+no_page: -+ fprintf(fp, "invalid\n"); -+ return FALSE; -+} -+ -+static int -+riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) -+{ -+ ulong *pgd_ptr, pgd_val; -+ ulong pud_val; -+ ulong pmd_val; -+ ulong pte_val, pte_pfn; -+ ulong pt_phys; -+ -+ /* PGD */ -+ pgd_ptr = pgd + pgd_index_l4_4k(vaddr); -+ FILL_PGD(pgd, KVADDR, PAGESIZE()); -+ pgd_val = ULONG(machdep->pgd + PAGEOFFSET(pgd_ptr)); -+ if (verbose) -+ fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val); -+ if (!pgd_val) -+ goto no_page; -+ pgd_val &= PTE_PFN_PROT_MASK; -+ pt_phys = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); -+ -+ /* PUD */ -+ FILL_PUD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); -+ pud_val = ULONG(machdep->pud + PAGEOFFSET(sizeof(pud_t) * -+ pud_index_l4_4k(vaddr))); -+ if (verbose) -+ fprintf(fp, " PUD: %016lx => %016lx\n", pt_phys, pud_val); -+ if (!pud_val) -+ goto no_page; -+ pud_val &= PTE_PFN_PROT_MASK; -+ pt_phys = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); -+ -+ /* PMD */ -+ FILL_PMD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); -+ pmd_val = ULONG(machdep->pmd + PAGEOFFSET(sizeof(pmd_t) * -+ pmd_index_l4_4k(vaddr))); -+ if (verbose) -+ fprintf(fp, " PMD: %016lx => %016lx\n", pt_phys, pmd_val); -+ if (!pmd_val) -+ goto no_page; -+ pmd_val &= PTE_PFN_PROT_MASK; -+ pt_phys = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); -+ -+ /* PTE */ -+ FILL_PTBL(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); -+ pte_val = ULONG(machdep->ptbl + PAGEOFFSET(sizeof(pte_t) * -+ pte_index_l4_4k(vaddr))); -+ if (verbose) -+ fprintf(fp, " PTE: %lx => %lx\n", pt_phys, pte_val); -+ if (!pte_val) -+ goto no_page; -+ pte_val &= PTE_PFN_PROT_MASK; -+ pte_pfn = pte_val >> _PAGE_PFN_SHIFT; -+ -+ if (!(pte_val & _PAGE_PRESENT)) { -+ if (verbose) { -+ fprintf(fp, "\n"); -+ riscv64_translate_pte((ulong)pte_val, 0, 0); -+ } -+ fprintf(fp, " PAGE: %016lx not present\n\n", PAGEBASE(*paddr)); -+ return FALSE; -+ } -+ -+ *paddr = PTOB(pte_pfn) + PAGEOFFSET(vaddr); -+ -+ if (verbose) { -+ fprintf(fp, " PAGE: %016lx\n\n", PAGEBASE(*paddr)); -+ riscv64_translate_pte(pte_val, 0, 0); -+ } -+ -+ return TRUE; -+no_page: -+ fprintf(fp, "invalid\n"); -+ return FALSE; -+} -+ -+static int -+riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) -+{ -+ ulong *pgd_ptr, pgd_val; -+ ulong p4d_val; -+ ulong pud_val; -+ ulong pmd_val; -+ ulong pte_val, pte_pfn; -+ ulong pt_phys; -+ -+ /* PGD */ -+ pgd_ptr = pgd + pgd_index_l5_4k(vaddr); -+ FILL_PGD(pgd, KVADDR, PAGESIZE()); -+ pgd_val = ULONG(machdep->pgd + PAGEOFFSET(pgd_ptr)); -+ if (verbose) -+ fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val); -+ if (!pgd_val) -+ goto no_page; -+ pgd_val &= PTE_PFN_PROT_MASK; -+ pt_phys = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); -+ -+ /* P4D */ -+ FILL_P4D(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); -+ p4d_val = ULONG(machdep->machspec->p4d + PAGEOFFSET(sizeof(p4d_t) * -+ p4d_index_l5_4k(vaddr))); -+ if (verbose) -+ fprintf(fp, " P4D: %016lx => %016lx\n", pt_phys, p4d_val); -+ if (!p4d_val) -+ goto no_page; -+ p4d_val &= PTE_PFN_PROT_MASK; -+ pt_phys = (p4d_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); -+ -+ /* PUD */ -+ FILL_PUD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); -+ pud_val = ULONG(machdep->pud + PAGEOFFSET(sizeof(pud_t) * -+ pud_index_l5_4k(vaddr))); -+ if (verbose) -+ fprintf(fp, " PUD: %016lx => %016lx\n", pt_phys, pud_val); -+ if (!pud_val) -+ goto no_page; -+ pud_val &= PTE_PFN_PROT_MASK; -+ pt_phys = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); -+ -+ /* PMD */ -+ FILL_PMD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); -+ pmd_val = ULONG(machdep->pmd + PAGEOFFSET(sizeof(pmd_t) * -+ pmd_index_l4_4k(vaddr))); -+ if (verbose) -+ fprintf(fp, " PMD: %016lx => %016lx\n", pt_phys, pmd_val); -+ if (!pmd_val) -+ goto no_page; -+ pmd_val &= PTE_PFN_PROT_MASK; -+ pt_phys = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); -+ -+ /* PTE */ -+ FILL_PTBL(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); -+ pte_val = ULONG(machdep->ptbl + PAGEOFFSET(sizeof(pte_t) * -+ pte_index_l4_4k(vaddr))); -+ if (verbose) -+ fprintf(fp, " PTE: %lx => %lx\n", pt_phys, pte_val); -+ if (!pte_val) -+ goto no_page; -+ pte_val &= PTE_PFN_PROT_MASK; -+ pte_pfn = pte_val >> _PAGE_PFN_SHIFT; -+ -+ if (!(pte_val & _PAGE_PRESENT)) { -+ if (verbose) { -+ fprintf(fp, "\n"); -+ riscv64_translate_pte((ulong)pte_val, 0, 0); -+ } -+ printf("!_PAGE_PRESENT\n"); -+ return FALSE; -+ } -+ -+ *paddr = PTOB(pte_pfn) + PAGEOFFSET(vaddr); -+ -+ if (verbose) { -+ fprintf(fp, " PAGE: %016lx\n\n", PAGEBASE(*paddr)); -+ riscv64_translate_pte(pte_val, 0, 0); -+ } -+ -+ return TRUE; -+no_page: -+ fprintf(fp, "invalid\n"); -+ return FALSE; -+} -+ -+static int -+riscv64_init_active_task_regs(void) -+{ -+ int retval; -+ -+ retval = riscv64_get_crash_notes(); -+ if (retval == TRUE) -+ return retval; -+ -+ return riscv64_get_elf_notes(); -+} -+ -+/* -+ * Retrieve task registers for the time of the crash. -+ */ -+static int -+riscv64_get_crash_notes(void) -+{ -+ struct machine_specific *ms = machdep->machspec; -+ ulong crash_notes; -+ Elf64_Nhdr *note; -+ ulong offset; -+ char *buf, *p; -+ ulong *notes_ptrs; -+ ulong i; -+ -+ /* -+ * crash_notes contains per cpu memory for storing cpu states -+ * in case of system crash. -+ */ -+ if (!symbol_exists("crash_notes")) -+ return FALSE; -+ -+ crash_notes = symbol_value("crash_notes"); -+ -+ notes_ptrs = (ulong *)GETBUF(kt->cpus*sizeof(notes_ptrs[0])); -+ -+ /* -+ * Read crash_notes for the first CPU. crash_notes are in standard ELF -+ * note format. -+ */ -+ if (!readmem(crash_notes, KVADDR, ¬es_ptrs[kt->cpus-1], -+ sizeof(notes_ptrs[kt->cpus-1]), "crash_notes", -+ RETURN_ON_ERROR)) { -+ error(WARNING, "cannot read crash_notes\n"); -+ FREEBUF(notes_ptrs); -+ return FALSE; -+ } -+ -+ if (symbol_exists("__per_cpu_offset")) { -+ -+ /* -+ * Add __per_cpu_offset for each cpu to form the pointer to the notes -+ */ -+ for (i = 0; i < kt->cpus; i++) -+ notes_ptrs[i] = notes_ptrs[kt->cpus-1] + kt->__per_cpu_offset[i]; -+ } -+ -+ buf = GETBUF(SIZE(note_buf)); -+ -+ if (!(panic_task_regs = calloc((size_t)kt->cpus, sizeof(*panic_task_regs)))) -+ error(FATAL, "cannot calloc panic_task_regs space\n"); -+ -+ for (i = 0; i < kt->cpus; i++) { -+ -+ if (!readmem(notes_ptrs[i], KVADDR, buf, SIZE(note_buf), "note_buf_t", -+ RETURN_ON_ERROR)) { -+ error(WARNING, -+ "cannot find NT_PRSTATUS note for cpu: %d\n", i); -+ goto fail; -+ } -+ -+ /* -+ * Do some sanity checks for this note before reading registers from it. -+ */ -+ note = (Elf64_Nhdr *)buf; -+ p = buf + sizeof(Elf64_Nhdr); -+ -+ /* -+ * dumpfiles created with qemu won't have crash_notes, but there will -+ * be elf notes; dumpfiles created by kdump do not create notes for -+ * offline cpus. -+ */ -+ if (note->n_namesz == 0 && (DISKDUMP_DUMPFILE() || KDUMP_DUMPFILE())) { -+ if (DISKDUMP_DUMPFILE()) -+ note = diskdump_get_prstatus_percpu(i); -+ else if (KDUMP_DUMPFILE()) -+ note = netdump_get_prstatus_percpu(i); -+ if (note) { -+ /* -+ * SIZE(note_buf) accounts for a "final note", which is a -+ * trailing empty elf note header. -+ */ -+ long notesz = SIZE(note_buf) - sizeof(Elf64_Nhdr); -+ -+ if (sizeof(Elf64_Nhdr) + roundup(note->n_namesz, 4) + -+ note->n_descsz == notesz) -+ BCOPY((char *)note, buf, notesz); -+ } else { -+ error(WARNING, -+ "cannot find NT_PRSTATUS note for cpu: %d\n", i); -+ continue; -+ } -+ } -+ -+ /* -+ * Check the sanity of NT_PRSTATUS note only for each online cpu. -+ */ -+ if (note->n_type != NT_PRSTATUS) { -+ error(WARNING, "invalid NT_PRSTATUS note (n_type != NT_PRSTATUS)\n"); -+ goto fail; -+ } -+ if (!STRNEQ(p, "CORE")) { -+ error(WARNING, "invalid NT_PRSTATUS note (name != \"CORE\"\n"); -+ goto fail; -+ } -+ -+ /* -+ * Find correct location of note data. This contains elf_prstatus -+ * structure which has registers etc. for the crashed task. -+ */ -+ offset = sizeof(Elf64_Nhdr); -+ offset = roundup(offset + note->n_namesz, 4); -+ p = buf + offset; /* start of elf_prstatus */ -+ -+ BCOPY(p + OFFSET(elf_prstatus_pr_reg), &panic_task_regs[i], -+ sizeof(panic_task_regs[i])); -+ } -+ -+ /* -+ * And finally we have the registers for the crashed task. This is -+ * used later on when dumping backtrace. -+ */ -+ ms->crash_task_regs = panic_task_regs; -+ -+ FREEBUF(buf); -+ FREEBUF(notes_ptrs); -+ return TRUE; -+ -+fail: -+ FREEBUF(buf); -+ FREEBUF(notes_ptrs); -+ free(panic_task_regs); -+ return FALSE; -+} -+ -+static int -+riscv64_get_elf_notes(void) -+{ -+ struct machine_specific *ms = machdep->machspec; -+ int i; -+ -+ if (!DISKDUMP_DUMPFILE() && !KDUMP_DUMPFILE()) -+ return FALSE; -+ -+ panic_task_regs = calloc(kt->cpus, sizeof(*panic_task_regs)); -+ if (!panic_task_regs) -+ error(FATAL, "cannot calloc panic_task_regs space\n"); -+ -+ for (i = 0; i < kt->cpus; i++) { -+ Elf64_Nhdr *note = NULL; -+ size_t len; -+ -+ if (DISKDUMP_DUMPFILE()) -+ note = diskdump_get_prstatus_percpu(i); -+ else if (KDUMP_DUMPFILE()) -+ note = netdump_get_prstatus_percpu(i); -+ -+ if (!note) { -+ error(WARNING, -+ "cannot find NT_PRSTATUS note for cpu: %d\n", i); -+ continue; -+ } -+ -+ len = sizeof(Elf64_Nhdr); -+ len = roundup(len + note->n_namesz, 4); -+ -+ BCOPY((char *)note + len + OFFSET(elf_prstatus_pr_reg), -+ &panic_task_regs[i], sizeof(panic_task_regs[i])); -+ } -+ -+ ms->crash_task_regs = panic_task_regs; -+ -+ return TRUE; -+} -+ -+/* -+ * Translates a user virtual address to its physical address. -+ */ -+static int -+riscv64_uvtop(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, int verbose) -+{ -+ ulong mm, active_mm; -+ ulong *pgd; -+ -+ if (!tc) -+ error(FATAL, "current context invalid\n"); -+ -+ *paddr = 0; -+ -+ if (is_kernel_thread(tc->task) && IS_KVADDR(uvaddr)) { -+ readmem(tc->task + OFFSET(task_struct_active_mm), -+ KVADDR, &active_mm, sizeof(void *), -+ "task active_mm contents", FAULT_ON_ERROR); -+ -+ if (!active_mm) -+ error(FATAL, -+ "no active_mm for this kernel thread\n"); -+ -+ readmem(active_mm + OFFSET(mm_struct_pgd), -+ KVADDR, &pgd, sizeof(long), -+ "mm_struct pgd", FAULT_ON_ERROR); -+ } else { -+ if ((mm = task_mm(tc->task, TRUE))) -+ pgd = ULONG_PTR(tt->mm_struct + OFFSET(mm_struct_pgd)); -+ else -+ readmem(tc->mm_struct + OFFSET(mm_struct_pgd), -+ KVADDR, &pgd, sizeof(long), "mm_struct pgd", -+ FAULT_ON_ERROR); -+ } -+ -+ switch (machdep->flags & VM_FLAGS) -+ { -+ case VM_L3_4K: -+ return riscv64_vtop_3level_4k(pgd, uvaddr, paddr, verbose); -+ case VM_L4_4K: -+ return riscv64_vtop_4level_4k(pgd, uvaddr, paddr, verbose); -+ case VM_L5_4K: -+ return riscv64_vtop_5level_4k(pgd, uvaddr, paddr, verbose); -+ default: -+ return FALSE; -+ } -+} -+ -+static int -+riscv64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbose) -+{ -+ ulong kernel_pgd; -+ -+ if (!IS_KVADDR(kvaddr)) -+ return FALSE; -+ -+ if (!vt->vmalloc_start) { -+ *paddr = VTOP(kvaddr); -+ return TRUE; -+ } -+ -+ if (!IS_VMALLOC_ADDR(kvaddr)) { -+ *paddr = VTOP(kvaddr); -+ if (!verbose) -+ return TRUE; -+ } -+ -+ kernel_pgd = vt->kernel_pgd[0]; -+ *paddr = 0; -+ -+ switch (machdep->flags & VM_FLAGS) -+ { -+ case VM_L3_4K: -+ return riscv64_vtop_3level_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose); -+ case VM_L4_4K: -+ return riscv64_vtop_4level_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose); -+ case VM_L5_4K: -+ return riscv64_vtop_5level_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose); -+ default: -+ return FALSE; -+ } -+} -+ - void - riscv64_init(int when) - { -+ switch (when) { -+ case SETUP_ENV: -+ machdep->process_elf_notes = process_elf64_notes; -+ break; -+ -+ case PRE_SYMTAB: -+ machdep->verify_symbol = riscv64_verify_symbol; -+ machdep->machspec = &riscv64_machine_specific; -+ if (pc->flags & KERNEL_DEBUG_QUERY) -+ return; -+ -+ machdep->verify_paddr = generic_verify_paddr; -+ machdep->ptrs_per_pgd = PTRS_PER_PGD; -+ break; -+ -+ case PRE_GDB: -+ machdep->pagesize = riscv64_get_page_size(); -+ machdep->pageshift = ffs(machdep->pagesize) - 1; -+ machdep->pageoffset = machdep->pagesize - 1; -+ machdep->pagemask = ~((ulonglong)machdep->pageoffset); -+ machdep->stacksize = machdep->pagesize << THREAD_SIZE_ORDER; -+ -+ riscv64_get_phys_ram_base(machdep->machspec); -+ riscv64_get_struct_page_size(machdep->machspec); -+ riscv64_get_va_bits(machdep->machspec); -+ riscv64_get_va_range(machdep->machspec); -+ -+ pt_level_alloc(&machdep->pgd, "cannot malloc pgd space."); -+ pt_level_alloc(&machdep->machspec->p4d, "cannot malloc p4d space."); -+ pt_level_alloc(&machdep->pud, "cannot malloc pud space."); -+ pt_level_alloc(&machdep->pmd, "cannot malloc pmd space."); -+ pt_level_alloc(&machdep->ptbl, "cannot malloc ptbl space."); -+ -+ machdep->last_pgd_read = 0; -+ machdep->machspec->last_p4d_read = 0; -+ machdep->last_pud_read = 0; -+ machdep->last_pmd_read = 0; -+ machdep->last_ptbl_read = 0; -+ -+ machdep->kvbase = machdep->machspec->page_offset; -+ machdep->identity_map_base = machdep->kvbase; -+ machdep->is_kvaddr = riscv64_is_kvaddr; -+ machdep->is_uvaddr = riscv64_is_uvaddr; -+ machdep->uvtop = riscv64_uvtop; -+ machdep->kvtop = riscv64_kvtop; -+ machdep->cmd_mach = riscv64_cmd_mach; -+ -+ machdep->vmalloc_start = riscv64_vmalloc_start; -+ machdep->processor_speed = riscv64_processor_speed; -+ machdep->get_stackbase = generic_get_stackbase; -+ machdep->get_stacktop = generic_get_stacktop; -+ machdep->translate_pte = riscv64_translate_pte; -+ machdep->memory_size = generic_memory_size; -+ machdep->is_task_addr = riscv64_is_task_addr; -+ machdep->get_smp_cpus = riscv64_get_smp_cpus; -+ machdep->value_to_symbol = generic_machdep_value_to_symbol; -+ machdep->show_interrupts = generic_show_interrupts; -+ machdep->get_irq_affinity = generic_get_irq_affinity; -+ machdep->init_kernel_pgd = NULL; /* pgd set by symbol_value("swapper_pg_dir") */ -+ break; -+ -+ case POST_GDB: -+ machdep->section_size_bits = _SECTION_SIZE_BITS; -+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS; -+ riscv64_page_type_init(); -+ -+ if (!machdep->hz) -+ machdep->hz = 250; -+ -+ if (symbol_exists("irq_desc")) -+ ARRAY_LENGTH_INIT(machdep->nr_irqs, irq_desc, -+ "irq_desc", NULL, 0); -+ else if (kernel_symbol_exists("nr_irqs")) -+ get_symbol_data("nr_irqs", sizeof(unsigned int), -+ &machdep->nr_irqs); -+ -+ MEMBER_OFFSET_INIT(elf_prstatus_pr_reg, "elf_prstatus", -+ "pr_reg"); -+ -+ STRUCT_SIZE_INIT(note_buf, "note_buf_t"); -+ break; -+ -+ case POST_VM: -+ /* -+ * crash_notes contains machine specific information about the -+ * crash. In particular, it contains CPU registers at the time -+ * of the crash. We need this information to extract correct -+ * backtraces from the panic task. -+ */ -+ if (!ACTIVE() && !riscv64_init_active_task_regs()) -+ error(WARNING, -+ "cannot retrieve registers for active task%s\n\n", -+ kt->cpus > 1 ? "s" : ""); -+ break; -+ } - } - -+/* -+ * 'help -r' command output -+ */ - void - riscv64_display_regs_from_elf_notes(int cpu, FILE *ofp) - { --- -2.37.1 - diff --git a/0010-RISCV64-Add-dis-command-support.patch b/0010-RISCV64-Add-dis-command-support.patch deleted file mode 100644 index 8bfe368..0000000 --- a/0010-RISCV64-Add-dis-command-support.patch +++ /dev/null @@ -1,44 +0,0 @@ -From b410e14f7865e8c0e28cf2fb7a0092e3a8735645 Mon Sep 17 00:00:00 2001 -From: Xianting Tian -Date: Thu, 20 Oct 2022 09:50:08 +0800 -Subject: [PATCH 10/28] RISCV64: Add 'dis' command support - -Use generic_dis_filter() function to support dis command implementation. - -With this patch, we can get the disassembled code, -crash> dis __crash_kexec -0xffffffff80088580 <__crash_kexec>: addi sp,sp,-352 -0xffffffff80088582 <__crash_kexec+2>: sd s0,336(sp) -0xffffffff80088584 <__crash_kexec+4>: sd s1,328(sp) -0xffffffff80088586 <__crash_kexec+6>: sd s2,320(sp) -0xffffffff80088588 <__crash_kexec+8>: addi s0,sp,352 -0xffffffff8008858a <__crash_kexec+10>: sd ra,344(sp) -0xffffffff8008858c <__crash_kexec+12>: sd s3,312(sp) -0xffffffff8008858e <__crash_kexec+14>: sd s4,304(sp) -0xffffffff80088590 <__crash_kexec+16>: auipc s2,0x1057 -0xffffffff80088594 <__crash_kexec+20>: addi s2,s2,-1256 -0xffffffff80088598 <__crash_kexec+24>: ld a5,0(s2) -0xffffffff8008859c <__crash_kexec+28>: mv s1,a0 -0xffffffff8008859e <__crash_kexec+30>: auipc a0,0xfff - -Signed-off-by: Xianting Tian -Signed-off-by: Lianbo Jiang ---- - riscv64.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/riscv64.c b/riscv64.c -index d8de3d56e1b7..1e20a09a81ae 100644 ---- a/riscv64.c -+++ b/riscv64.c -@@ -988,6 +988,7 @@ riscv64_init(int when) - machdep->is_task_addr = riscv64_is_task_addr; - machdep->get_smp_cpus = riscv64_get_smp_cpus; - machdep->value_to_symbol = generic_machdep_value_to_symbol; -+ machdep->dis_filter = generic_dis_filter; - machdep->show_interrupts = generic_show_interrupts; - machdep->get_irq_affinity = generic_get_irq_affinity; - machdep->init_kernel_pgd = NULL; /* pgd set by symbol_value("swapper_pg_dir") */ --- -2.37.1 - diff --git a/0011-RISCV64-Add-irq-command-support.patch b/0011-RISCV64-Add-irq-command-support.patch deleted file mode 100644 index 769355a..0000000 --- a/0011-RISCV64-Add-irq-command-support.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 67216c741c4ebe8494f74f1ceabff9cdafb67883 Mon Sep 17 00:00:00 2001 -From: Xianting Tian -Date: Thu, 20 Oct 2022 09:50:09 +0800 -Subject: [PATCH 11/28] RISCV64: Add irq command support - -With the patch, we can get the irq info, -crash> irq - IRQ IRQ_DESC/_DATA IRQACTION NAME - 0 (unused) (unused) - 1 ff60000001329600 ff60000001d17180 "101000.rtc" - 2 ff60000001329800 ff60000001d17680 "ttyS0" - 3 ff60000001329a00 ff60000001c33c00 "virtio0" - 4 ff60000001329c00 ff60000001c33f80 "virtio1" - 5 ff6000000120f400 ff60000001216000 "riscv-timer" - -Signed-off-by: Xianting Tian -Signed-off-by: Lianbo Jiang ---- - riscv64.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/riscv64.c b/riscv64.c -index 1e20a09a81ae..2355daca7aac 100644 ---- a/riscv64.c -+++ b/riscv64.c -@@ -989,6 +989,7 @@ riscv64_init(int when) - machdep->get_smp_cpus = riscv64_get_smp_cpus; - machdep->value_to_symbol = generic_machdep_value_to_symbol; - machdep->dis_filter = generic_dis_filter; -+ machdep->dump_irq = generic_dump_irq; - machdep->show_interrupts = generic_show_interrupts; - machdep->get_irq_affinity = generic_get_irq_affinity; - machdep->init_kernel_pgd = NULL; /* pgd set by symbol_value("swapper_pg_dir") */ --- -2.37.1 - diff --git a/0012-RISCV64-Add-bt-command-support.patch b/0012-RISCV64-Add-bt-command-support.patch deleted file mode 100644 index e005aa3..0000000 --- a/0012-RISCV64-Add-bt-command-support.patch +++ /dev/null @@ -1,413 +0,0 @@ -From 0d9fcbe3803c684fbfee893837a94d3c8f377805 Mon Sep 17 00:00:00 2001 -From: Xianting Tian -Date: Thu, 20 Oct 2022 09:50:10 +0800 -Subject: [PATCH 12/28] RISCV64: Add 'bt' command support - -1, Add the implementation to get stack frame from active & inactive - task's stack. -2, Add 'bt -l' command support get a line number associated with a - current pc address. -3, Add 'bt -f' command support to display all stack data contained - in a frame - -With the patch, we can get the backtrace, -crash> bt -PID: 113 TASK: ff6000000226c200 CPU: 0 COMMAND: "sh" - #0 [ff20000010333b90] riscv_crash_save_regs at ffffffff800078f8 - #1 [ff20000010333cf0] panic at ffffffff806578c6 - #2 [ff20000010333d50] sysrq_reset_seq_param_set at ffffffff8038c03c - #3 [ff20000010333da0] __handle_sysrq at ffffffff8038c604 - #4 [ff20000010333e00] write_sysrq_trigger at ffffffff8038cae4 - #5 [ff20000010333e20] proc_reg_write at ffffffff801b7ee8 - #6 [ff20000010333e40] vfs_write at ffffffff80152bb2 - #7 [ff20000010333e80] ksys_write at ffffffff80152eda - #8 [ff20000010333ed0] sys_write at ffffffff80152f52 - -crash> bt -l -PID: 113 TASK: ff6000000226c200 CPU: 0 COMMAND: "sh" - #0 [ff20000010333b90] riscv_crash_save_regs at ffffffff800078f8 - /buildroot/qemu_riscv64_virt_defconfig/build/linux-custom/arch/riscv/kernel/crash_save_regs.S: 47 - #1 [ff20000010333cf0] panic at ffffffff806578c6 - /buildroot/qemu_riscv64_virt_defconfig/build/linux-custom/kernel/panic.c: 276 - ... ... - -crash> bt -f -PID: 113 TASK: ff6000000226c200 CPU: 0 COMMAND: "sh" - #0 [ff20000010333b90] riscv_crash_save_regs at ffffffff800078f8 - [PC: ffffffff800078f8 RA: ffffffff806578c6 SP: ff20000010333b90 SIZE: 352] - ff20000010333b90: ff20000010333bb0 ffffffff800078f8 - ff20000010333ba0: ffffffff8008862c ff20000010333b90 - ff20000010333bb0: ffffffff810dde38 ff6000000226c200 - ff20000010333bc0: ffffffff8032be68 0720072007200720 - ... ... - -Signed-off-by: Xianting Tian -Signed-off-by: Lianbo Jiang ---- - netdump.c | 13 +++ - riscv64.c | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 296 insertions(+) - -diff --git a/netdump.c b/netdump.c -index 4ec12a073af6..01af1458d6e8 100644 ---- a/netdump.c -+++ b/netdump.c -@@ -42,6 +42,7 @@ static void get_netdump_regs_ppc64(struct bt_info *, ulong *, ulong *); - static void get_netdump_regs_arm(struct bt_info *, ulong *, ulong *); - static void get_netdump_regs_arm64(struct bt_info *, ulong *, ulong *); - static void get_netdump_regs_mips(struct bt_info *, ulong *, ulong *); -+static void get_netdump_regs_riscv(struct bt_info *, ulong *, ulong *); - static void check_dumpfile_size(char *); - static int proc_kcore_init_32(FILE *, int); - static int proc_kcore_init_64(FILE *, int); -@@ -2675,6 +2676,10 @@ get_netdump_regs(struct bt_info *bt, ulong *eip, ulong *esp) - return get_netdump_regs_mips(bt, eip, esp); - break; - -+ case EM_RISCV: -+ get_netdump_regs_riscv(bt, eip, esp); -+ break; -+ - default: - error(FATAL, - "support for ELF machine type %d not available\n", -@@ -2931,6 +2936,8 @@ display_regs_from_elf_notes(int cpu, FILE *ofp) - mips_display_regs_from_elf_notes(cpu, ofp); - } else if (machine_type("MIPS64")) { - mips64_display_regs_from_elf_notes(cpu, ofp); -+ } else if (machine_type("RISCV64")) { -+ riscv64_display_regs_from_elf_notes(cpu, ofp); - } - } - -@@ -3877,6 +3884,12 @@ get_netdump_regs_mips(struct bt_info *bt, ulong *eip, ulong *esp) - machdep->get_stack_frame(bt, eip, esp); - } - -+static void -+get_netdump_regs_riscv(struct bt_info *bt, ulong *eip, ulong *esp) -+{ -+ machdep->get_stack_frame(bt, eip, esp); -+} -+ - int - is_partial_netdump(void) - { -diff --git a/riscv64.c b/riscv64.c -index 2355daca7aac..4c9b35bb93f2 100644 ---- a/riscv64.c -+++ b/riscv64.c -@@ -33,6 +33,17 @@ static int riscv64_uvtop(struct task_context *tc, ulong vaddr, - static int riscv64_kvtop(struct task_context *tc, ulong kvaddr, - physaddr_t *paddr, int verbose); - static void riscv64_cmd_mach(void); -+static void riscv64_stackframe_init(void); -+static void riscv64_back_trace_cmd(struct bt_info *bt); -+static int riscv64_get_dumpfile_stack_frame(struct bt_info *bt, -+ ulong *nip, ulong *ksp); -+static void riscv64_get_stack_frame(struct bt_info *bt, ulong *pcp, -+ ulong *spp); -+static int riscv64_get_frame(struct bt_info *bt, ulong *pcp, -+ ulong *spp); -+static void riscv64_display_full_frame(struct bt_info *bt, -+ struct riscv64_unwind_frame *current, -+ struct riscv64_unwind_frame *previous); - static int riscv64_translate_pte(ulong, void *, ulonglong); - static int riscv64_init_active_task_regs(void); - static int riscv64_get_crash_notes(void); -@@ -498,6 +509,275 @@ no_page: - return FALSE; - } - -+/* -+ * 'bt -f' command output -+ * Display all stack data contained in a frame -+ */ -+static void -+riscv64_display_full_frame(struct bt_info *bt, struct riscv64_unwind_frame *current, -+ struct riscv64_unwind_frame *previous) -+{ -+ int i, u_idx; -+ ulong *up; -+ ulong words, addr; -+ char buf[BUFSIZE]; -+ -+ if (previous->sp < current->sp) -+ return; -+ -+ if (!(INSTACK(previous->sp, bt) && INSTACK(current->sp, bt))) -+ return; -+ -+ words = (previous->sp - current->sp) / sizeof(ulong) + 1; -+ addr = current->sp; -+ u_idx = (current->sp - bt->stackbase) / sizeof(ulong); -+ -+ for (i = 0; i < words; i++, u_idx++) { -+ if (!(i & 1)) -+ fprintf(fp, "%s %lx: ", i ? "\n" : "", addr); -+ -+ up = (ulong *)(&bt->stackbuf[u_idx*sizeof(ulong)]); -+ fprintf(fp, "%s ", format_stack_entry(bt, buf, *up, 0)); -+ addr += sizeof(ulong); -+ } -+ fprintf(fp, "\n"); -+} -+ -+static void -+riscv64_stackframe_init(void) -+{ -+ long task_struct_thread = MEMBER_OFFSET("task_struct", "thread"); -+ -+ /* from arch/riscv/include/asm/processor.h */ -+ long thread_reg_ra = MEMBER_OFFSET("thread_struct", "ra"); -+ long thread_reg_sp = MEMBER_OFFSET("thread_struct", "sp"); -+ long thread_reg_fp = MEMBER_OFFSET("thread_struct", "s"); -+ -+ if ((task_struct_thread == INVALID_OFFSET) || -+ (thread_reg_ra == INVALID_OFFSET) || -+ (thread_reg_sp == INVALID_OFFSET) || -+ (thread_reg_fp == INVALID_OFFSET) ) -+ error(FATAL, -+ "cannot determine thread_struct offsets\n"); -+ -+ ASSIGN_OFFSET(task_struct_thread_context_pc) = -+ task_struct_thread + thread_reg_ra; -+ ASSIGN_OFFSET(task_struct_thread_context_sp) = -+ task_struct_thread + thread_reg_sp; -+ ASSIGN_OFFSET(task_struct_thread_context_fp) = -+ task_struct_thread + thread_reg_fp; -+} -+ -+static void -+riscv64_dump_backtrace_entry(struct bt_info *bt, struct syment *sym, -+ struct riscv64_unwind_frame *current, -+ struct riscv64_unwind_frame *previous, int level) -+{ -+ const char *name = sym ? sym->name : "(invalid)"; -+ struct load_module *lm; -+ char *name_plus_offset = NULL; -+ struct syment *symp; -+ ulong symbol_offset; -+ char buf[BUFSIZE]; -+ -+ if (bt->flags & BT_SYMBOL_OFFSET) { -+ symp = value_search(current->pc, &symbol_offset); -+ -+ if (symp && symbol_offset) -+ name_plus_offset = -+ value_to_symstr(current->pc, buf, bt->radix); -+ } -+ -+ fprintf(fp, "%s#%d [%016lx] %s at %016lx", -+ level < 10 ? " " : "", -+ level, -+ current->sp, -+ name_plus_offset ? name_plus_offset : name, -+ current->pc); -+ -+ if (module_symbol(current->pc, NULL, &lm, NULL, 0)) -+ fprintf(fp, " [%s]", lm->mod_name); -+ -+ fprintf(fp, "\n"); -+ -+ /* -+ * 'bt -l', get a line number associated with a current pc address. -+ */ -+ if (bt->flags & BT_LINE_NUMBERS) { -+ get_line_number(current->pc, buf, FALSE); -+ if (strlen(buf)) -+ fprintf(fp, " %s\n", buf); -+ } -+ -+ /* bt -f */ -+ if (bt->flags & BT_FULL) { -+ fprintf(fp, " " -+ "[PC: %016lx RA: %016lx SP: %016lx SIZE: %ld]\n", -+ current->pc, -+ previous->pc, -+ current->sp, -+ previous->sp - current->sp); -+ riscv64_display_full_frame(bt, current, previous); -+ } -+} -+ -+/* -+ * Unroll a kernel stack. -+ */ -+static void -+riscv64_back_trace_cmd(struct bt_info *bt) -+{ -+ struct riscv64_unwind_frame current, previous; -+ struct stackframe curr_frame; -+ int level = 0; -+ -+ if (bt->flags & BT_REGS_NOT_FOUND) -+ return; -+ -+ current.pc = bt->instptr; -+ current.sp = bt->stkptr; -+ current.fp = bt->frameptr; -+ -+ if (!INSTACK(current.sp, bt)) -+ return; -+ -+ for (;;) { -+ struct syment *symbol = NULL; -+ struct stackframe *frameptr; -+ ulong low, high; -+ ulong offset; -+ -+ if (CRASHDEBUG(8)) -+ fprintf(fp, "level %d pc %#lx sp %lx fp 0x%lx\n", -+ level, current.pc, current.sp, current.fp); -+ -+ /* Validate frame pointer */ -+ low = current.sp + sizeof(struct stackframe); -+ high = bt->stacktop; -+ if (current.fp < low || current.fp > high || current.fp & 0x7) { -+ if (CRASHDEBUG(8)) -+ fprintf(fp, "fp 0x%lx sp 0x%lx low 0x%lx high 0x%lx\n", -+ current.fp, current.sp, low, high); -+ return; -+ } -+ -+ symbol = value_search(current.pc, &offset); -+ if (!symbol) -+ return; -+ -+ frameptr = (struct stackframe *)current.fp - 1; -+ if (!readmem((ulong)frameptr, KVADDR, &curr_frame, -+ sizeof(curr_frame), "get stack frame", RETURN_ON_ERROR)) -+ return; -+ -+ previous.pc = curr_frame.ra; -+ previous.fp = curr_frame.fp; -+ previous.sp = current.fp; -+ -+ riscv64_dump_backtrace_entry(bt, symbol, ¤t, &previous, level++); -+ -+ current.pc = previous.pc; -+ current.fp = previous.fp; -+ current.sp = previous.sp; -+ -+ if (CRASHDEBUG(8)) -+ fprintf(fp, "next %d pc %#lx sp %#lx fp %lx\n", -+ level, current.pc, current.sp, current.fp); -+ } -+} -+ -+/* -+ * Get a stack frame combination of pc and ra from the most relevant spot. -+ */ -+static void -+riscv64_get_stack_frame(struct bt_info *bt, ulong *pcp, ulong *spp) -+{ -+ ulong ksp = 0, nip = 0; -+ int ret = 0; -+ -+ if (DUMPFILE() && is_task_active(bt->task)) -+ ret = riscv64_get_dumpfile_stack_frame(bt, &nip, &ksp); -+ else -+ ret = riscv64_get_frame(bt, &nip, &ksp); -+ -+ if (!ret) -+ error(WARNING, "cannot determine starting stack frame for task %lx\n", -+ bt->task); -+ -+ if (pcp) -+ *pcp = nip; -+ if (spp) -+ *spp = ksp; -+} -+ -+/* -+ * Get the starting point for the active cpu in a diskdump. -+ */ -+static int -+riscv64_get_dumpfile_stack_frame(struct bt_info *bt, ulong *nip, ulong *ksp) -+{ -+ const struct machine_specific *ms = machdep->machspec; -+ struct riscv64_register *regs; -+ ulong epc, sp; -+ -+ if (!ms->crash_task_regs) { -+ bt->flags |= BT_REGS_NOT_FOUND; -+ return FALSE; -+ } -+ -+ /* -+ * We got registers for panic task from crash_notes. Just return them. -+ */ -+ regs = &ms->crash_task_regs[bt->tc->processor]; -+ epc = regs->regs[RISCV64_REGS_EPC]; -+ sp = regs->regs[RISCV64_REGS_SP]; -+ -+ /* -+ * Set stack frame ptr. -+ */ -+ bt->frameptr = regs->regs[RISCV64_REGS_FP]; -+ -+ if (nip) -+ *nip = epc; -+ if (ksp) -+ *ksp = sp; -+ -+ bt->machdep = regs; -+ -+ return TRUE; -+} -+ -+/* -+ * Do the work for riscv64_get_stack_frame() for non-active tasks. -+ * Get SP and PC values for idle tasks. -+ */ -+static int -+riscv64_get_frame(struct bt_info *bt, ulong *pcp, ulong *spp) -+{ -+ if (!bt->tc || !(tt->flags & THREAD_INFO)) -+ return FALSE; -+ -+ if (!readmem(bt->task + OFFSET(task_struct_thread_context_pc), -+ KVADDR, pcp, sizeof(*pcp), -+ "thread_struct.ra", -+ RETURN_ON_ERROR)) -+ return FALSE; -+ -+ if (!readmem(bt->task + OFFSET(task_struct_thread_context_sp), -+ KVADDR, spp, sizeof(*spp), -+ "thread_struct.sp", -+ RETURN_ON_ERROR)) -+ return FALSE; -+ -+ if (!readmem(bt->task + OFFSET(task_struct_thread_context_fp), -+ KVADDR, &bt->frameptr, sizeof(bt->frameptr), -+ "thread_struct.fp", -+ RETURN_ON_ERROR)) -+ return FALSE; -+ -+ return TRUE; -+} -+ - static int - riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) - { -@@ -978,6 +1258,8 @@ riscv64_init(int when) - machdep->uvtop = riscv64_uvtop; - machdep->kvtop = riscv64_kvtop; - machdep->cmd_mach = riscv64_cmd_mach; -+ machdep->get_stack_frame = riscv64_get_stack_frame; -+ machdep->back_trace = riscv64_back_trace_cmd; - - machdep->vmalloc_start = riscv64_vmalloc_start; - machdep->processor_speed = riscv64_processor_speed; -@@ -998,6 +1280,7 @@ riscv64_init(int when) - case POST_GDB: - machdep->section_size_bits = _SECTION_SIZE_BITS; - machdep->max_physmem_bits = _MAX_PHYSMEM_BITS; -+ riscv64_stackframe_init(); - riscv64_page_type_init(); - - if (!machdep->hz) --- -2.37.1 - diff --git a/0013-RISCV64-Add-help-r-command-support.patch b/0013-RISCV64-Add-help-r-command-support.patch deleted file mode 100644 index 6eb5c51..0000000 --- a/0013-RISCV64-Add-help-r-command-support.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 5cfcdb4ebcb159c1c47b7c1805cd9b274ca27ff5 Mon Sep 17 00:00:00 2001 -From: Xianting Tian -Date: Thu, 20 Oct 2022 09:50:11 +0800 -Subject: [PATCH 13/28] RISCV64: Add 'help -r' command support - -Add support form printing out the registers from the dump file. - -With the patch, we can get the regs, -crash> help -r -CPU 0: -epc : 00ffffffa5537400 ra : ffffffff80088620 sp : ff2000001039bb90 - gp : ffffffff810dde38 tp : ff60000002269600 t0 : ffffffff8032be5c - t1 : 0720072007200720 t2 : 666666666666663c s0 : ff2000001039bcf0 - s1 : 0000000000000000 a0 : ff2000001039bb98 a1 : 0000000000000001 - a2 : 0000000000000010 a3 : 0000000000000000 a4 : 0000000000000000 - a5 : ff60000001c7d000 a6 : 000000000000003c a7 : ffffffff8035c998 - s2 : ffffffff810df0a8 s3 : ffffffff810df718 s4 : ff2000001039bb98 - s5 : 0000000000000000 s6 : 0000000000000007 s7 : ffffffff80c4a468 - s8 : 00fffffffde45410 s9 : 0000000000000007 s10: 00aaaaaad1640700 - s11: 0000000000000001 t3 : ff60000001218f00 t4 : ff60000001218f00 - t5 : ff60000001218000 t6 : ff2000001039b988 - -Signed-off-by: Xianting Tian -Signed-off-by: Lianbo Jiang ---- - riscv64.c | 38 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - -diff --git a/riscv64.c b/riscv64.c -index 4c9b35bb93f2..6d1d3b5f36d1 100644 ---- a/riscv64.c -+++ b/riscv64.c -@@ -1320,6 +1320,44 @@ riscv64_init(int when) - void - riscv64_display_regs_from_elf_notes(int cpu, FILE *ofp) - { -+ const struct machine_specific *ms = machdep->machspec; -+ struct riscv64_register *regs; -+ -+ if (!ms->crash_task_regs) { -+ error(INFO, "registers not collected for cpu %d\n", cpu); -+ return; -+ } -+ -+ regs = &ms->crash_task_regs[cpu]; -+ if (!regs->regs[RISCV64_REGS_SP] && !regs->regs[RISCV64_REGS_EPC]) { -+ error(INFO, "registers not collected for cpu %d\n", cpu); -+ return; -+ } -+ -+ /* Print riscv64 32 regs */ -+ fprintf(ofp, -+ "epc : " REG_FMT " ra : " REG_FMT " sp : " REG_FMT "\n" -+ " gp : " REG_FMT " tp : " REG_FMT " t0 : " REG_FMT "\n" -+ " t1 : " REG_FMT " t2 : " REG_FMT " s0 : " REG_FMT "\n" -+ " s1 : " REG_FMT " a0 : " REG_FMT " a1 : " REG_FMT "\n" -+ " a2 : " REG_FMT " a3 : " REG_FMT " a4 : " REG_FMT "\n" -+ " a5 : " REG_FMT " a6 : " REG_FMT " a7 : " REG_FMT "\n" -+ " s2 : " REG_FMT " s3 : " REG_FMT " s4 : " REG_FMT "\n" -+ " s5 : " REG_FMT " s6 : " REG_FMT " s7 : " REG_FMT "\n" -+ " s8 : " REG_FMT " s9 : " REG_FMT " s10: " REG_FMT "\n" -+ " s11: " REG_FMT " t3 : " REG_FMT " t4 : " REG_FMT "\n" -+ " t5 : " REG_FMT " t6 : " REG_FMT "\n", -+ regs->regs[0], regs->regs[1], regs->regs[2], -+ regs->regs[3], regs->regs[4], regs->regs[5], -+ regs->regs[6], regs->regs[7], regs->regs[8], -+ regs->regs[9], regs->regs[10], regs->regs[11], -+ regs->regs[12], regs->regs[13], regs->regs[14], -+ regs->regs[15], regs->regs[16], regs->regs[17], -+ regs->regs[18], regs->regs[19], regs->regs[20], -+ regs->regs[21], regs->regs[22], regs->regs[23], -+ regs->regs[24], regs->regs[25], regs->regs[26], -+ regs->regs[27], regs->regs[28], regs->regs[29], -+ regs->regs[30], regs->regs[31]); - } - - #else /* !RISCV64 */ --- -2.37.1 - diff --git a/0014-RISCV64-Add-help-m-M-command-support.patch b/0014-RISCV64-Add-help-m-M-command-support.patch deleted file mode 100644 index 439c0cc..0000000 --- a/0014-RISCV64-Add-help-m-M-command-support.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 6c281cd355c904ddb82cbb49278b925d2ed13365 Mon Sep 17 00:00:00 2001 -From: Xianting Tian -Date: Thu, 20 Oct 2022 09:50:12 +0800 -Subject: [PATCH 14/28] RISCV64: Add 'help -m/M' command support - -Add riscv64_dump_machdep_table() implementation, display machdep_table. - -crash> help -m - flags: 80 () - kvbase: ff60000000000000 - identity_map_base: ff60000000000000 - pagesize: 4096 - pageshift: 12 - pagemask: fffffffffffff000 - pageoffset: fff - pgdir_shift: 48 - ptrs_per_pgd: 512 - ptrs_per_pte: 512 - stacksize: 16384 - hz: 250 - memsize: 1071644672 (0x3fe00000) - bits: 64 - back_trace: riscv64_back_trace_cmd() - processor_speed: riscv64_processor_speed() - uvtop: riscv64_uvtop() - kvtop: riscv64_kvtop() - get_stack_frame: riscv64_get_stack_frame() - get_stackbase: generic_get_stackbase() - get_stacktop: generic_get_stacktop() - translate_pte: riscv64_translate_pte() - memory_size: generic_memory_size() - vmalloc_start: riscv64_vmalloc_start() - is_task_addr: riscv64_is_task_addr() - verify_symbol: riscv64_verify_symbol() - dis_filter: generic_dis_filter() - dump_irq: generic_dump_irq() - show_interrupts: generic_show_interrupts() - get_irq_affinity: generic_get_irq_affinity() - cmd_mach: riscv64_cmd_mach() - get_smp_cpus: riscv64_get_smp_cpus() - is_kvaddr: riscv64_is_kvaddr() - is_uvaddr: riscv64_is_uvaddr() - verify_paddr: generic_verify_paddr() - init_kernel_pgd: NULL - value_to_symbol: generic_machdep_value_to_symbol() - line_number_hooks: NULL - last_pgd_read: ffffffff810e9000 - last_p4d_read: 81410000 - last_pud_read: 81411000 - last_pmd_read: 81412000 - last_ptbl_read: 81415000 - pgd: 560d586f3ab0 - p4d: 560d586f4ac0 - pud: 560d586f5ad0 - pmd: 560d586f6ae0 - ptbl: 560d586f7af0 - section_size_bits: 27 - max_physmem_bits: 56 - sections_per_root: 0 - machspec: 560d57d204a0 - -Signed-off-by: Xianting Tian -Signed-off-by: Lianbo Jiang ---- - riscv64.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 59 insertions(+), 1 deletion(-) - -diff --git a/riscv64.c b/riscv64.c -index 6d1d3b5f36d1..5e8c7d12227c 100644 ---- a/riscv64.c -+++ b/riscv64.c -@@ -132,7 +132,65 @@ riscv64_verify_symbol(const char *name, ulong value, char type) - void - riscv64_dump_machdep_table(ulong arg) - { -- /* TODO: */ -+ int others = 0; -+ -+ fprintf(fp, " flags: %lx (", machdep->flags); -+ if (machdep->flags & KSYMS_START) -+ fprintf(fp, "%sKSYMS_START", others++ ? "|" : ""); -+ fprintf(fp, ")\n"); -+ -+ fprintf(fp, " kvbase: %lx\n", machdep->kvbase); -+ fprintf(fp, " identity_map_base: %lx\n", machdep->identity_map_base); -+ fprintf(fp, " pagesize: %d\n", machdep->pagesize); -+ fprintf(fp, " pageshift: %d\n", machdep->pageshift); -+ fprintf(fp, " pagemask: %llx\n", machdep->pagemask); -+ fprintf(fp, " pageoffset: %lx\n", machdep->pageoffset); -+ fprintf(fp, " pgdir_shift: %ld\n", machdep->machspec->va_bits - 9); -+ fprintf(fp, " ptrs_per_pgd: %u\n", PTRS_PER_PGD); -+ fprintf(fp, " ptrs_per_pte: %d\n", PTRS_PER_PTE); -+ fprintf(fp, " stacksize: %ld\n", machdep->stacksize); -+ fprintf(fp, " hz: %d\n", machdep->hz); -+ fprintf(fp, " memsize: %ld (0x%lx)\n", -+ machdep->memsize, machdep->memsize); -+ fprintf(fp, " bits: %d\n", machdep->bits); -+ fprintf(fp, " back_trace: riscv64_back_trace_cmd()\n"); -+ fprintf(fp, " processor_speed: riscv64_processor_speed()\n"); -+ fprintf(fp, " uvtop: riscv64_uvtop()\n"); -+ fprintf(fp, " kvtop: riscv64_kvtop()\n"); -+ fprintf(fp, " get_stack_frame: riscv64_get_stack_frame()\n"); -+ fprintf(fp, " get_stackbase: generic_get_stackbase()\n"); -+ fprintf(fp, " get_stacktop: generic_get_stacktop()\n"); -+ fprintf(fp, " translate_pte: riscv64_translate_pte()\n"); -+ fprintf(fp, " memory_size: generic_memory_size()\n"); -+ fprintf(fp, " vmalloc_start: riscv64_vmalloc_start()\n"); -+ fprintf(fp, " is_task_addr: riscv64_is_task_addr()\n"); -+ fprintf(fp, " verify_symbol: riscv64_verify_symbol()\n"); -+ fprintf(fp, " dis_filter: generic_dis_filter()\n"); -+ fprintf(fp, " dump_irq: generic_dump_irq()\n"); -+ fprintf(fp, " show_interrupts: generic_show_interrupts()\n"); -+ fprintf(fp, " get_irq_affinity: generic_get_irq_affinity()\n"); -+ fprintf(fp, " cmd_mach: riscv64_cmd_mach()\n"); -+ fprintf(fp, " get_smp_cpus: riscv64_get_smp_cpus()\n"); -+ fprintf(fp, " is_kvaddr: riscv64_is_kvaddr()\n"); -+ fprintf(fp, " is_uvaddr: riscv64_is_uvaddr()\n"); -+ fprintf(fp, " verify_paddr: generic_verify_paddr()\n"); -+ fprintf(fp, " init_kernel_pgd: NULL\n"); -+ fprintf(fp, " value_to_symbol: generic_machdep_value_to_symbol()\n"); -+ fprintf(fp, " line_number_hooks: NULL\n"); -+ fprintf(fp, " last_pgd_read: %lx\n", machdep->last_pgd_read); -+ fprintf(fp, " last_p4d_read: %lx\n", machdep->machspec->last_p4d_read); -+ fprintf(fp, " last_pud_read: %lx\n", machdep->last_pud_read); -+ fprintf(fp, " last_pmd_read: %lx\n", machdep->last_pmd_read); -+ fprintf(fp, " last_ptbl_read: %lx\n", machdep->last_ptbl_read); -+ fprintf(fp, " pgd: %lx\n", (ulong)machdep->pgd); -+ fprintf(fp, " p4d: %lx\n", (ulong)machdep->machspec->p4d); -+ fprintf(fp, " pud: %lx\n", (ulong)machdep->pud); -+ fprintf(fp, " pmd: %lx\n", (ulong)machdep->pmd); -+ fprintf(fp, " ptbl: %lx\n", (ulong)machdep->ptbl); -+ fprintf(fp, " section_size_bits: %ld\n", machdep->section_size_bits); -+ fprintf(fp, " max_physmem_bits: %ld\n", machdep->max_physmem_bits); -+ fprintf(fp, " sections_per_root: %ld\n", machdep->sections_per_root); -+ fprintf(fp, " machspec: %lx\n", (ulong)machdep->machspec); - } - - static ulong --- -2.37.1 - diff --git a/0015-RISCV64-Add-mach-command-support.patch b/0015-RISCV64-Add-mach-command-support.patch deleted file mode 100644 index 443a0ff..0000000 --- a/0015-RISCV64-Add-mach-command-support.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 3f4714967961c2ca8b70dccb938a5258b6572d2b Mon Sep 17 00:00:00 2001 -From: Xianting Tian -Date: Thu, 20 Oct 2022 09:50:13 +0800 -Subject: [PATCH 15/28] RISCV64: Add 'mach' command support - -With the patch we can get some basic machine state information, -crash> mach - MACHINE TYPE: riscv64 - MEMORY SIZE: 1 GB - CPUS: 1 - PROCESSOR SPEED: (unknown) - HZ: 250 - PAGE SIZE: 4096 - KERNEL STACK SIZE: 16384 - -Signed-off-by: Xianting Tian -Signed-off-by: Lianbo Jiang ---- - riscv64.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 44 insertions(+), 1 deletion(-) - -diff --git a/riscv64.c b/riscv64.c -index 5e8c7d12227c..ff77e41b9407 100644 ---- a/riscv64.c -+++ b/riscv64.c -@@ -116,10 +116,53 @@ static void riscv64_get_struct_page_size(struct machine_specific *ms) - } - } - -+/* -+ * "mach" command output. -+ */ -+static void -+riscv64_display_machine_stats(void) -+{ -+ struct new_utsname *uts; -+ char buf[BUFSIZE]; -+ ulong mhz; -+ -+ uts = &kt->utsname; -+ -+ fprintf(fp, " MACHINE TYPE: %s\n", uts->machine); -+ fprintf(fp, " MEMORY SIZE: %s\n", get_memory_size(buf)); -+ fprintf(fp, " CPUS: %d\n", get_cpus_to_display()); -+ fprintf(fp, " PROCESSOR SPEED: "); -+ if ((mhz = machdep->processor_speed())) -+ fprintf(fp, "%ld Mhz\n", mhz); -+ else -+ fprintf(fp, "(unknown)\n"); -+ fprintf(fp, " HZ: %d\n", machdep->hz); -+ fprintf(fp, " PAGE SIZE: %d\n", PAGESIZE()); -+ fprintf(fp, " KERNEL STACK SIZE: %ld\n", STACKSIZE()); -+} -+ - static void - riscv64_cmd_mach(void) - { -- /* TODO: */ -+ int c; -+ -+ while ((c = getopt(argcnt, args, "cmo")) != EOF) { -+ switch (c) { -+ case 'c': -+ case 'm': -+ case 'o': -+ option_not_supported(c); -+ break; -+ default: -+ argerrs++; -+ break; -+ } -+ } -+ -+ if (argerrs) -+ cmd_usage(pc->curcmd, SYNOPSIS); -+ -+ riscv64_display_machine_stats(); - } - - static int --- -2.37.1 - diff --git a/0016-RISCV64-Add-the-implementation-of-symbol-verify.patch b/0016-RISCV64-Add-the-implementation-of-symbol-verify.patch deleted file mode 100644 index 21f4bbb..0000000 --- a/0016-RISCV64-Add-the-implementation-of-symbol-verify.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0d5ad129252a18a46d1818a68ed22b35c5234289 Mon Sep 17 00:00:00 2001 -From: Xianting Tian -Date: Thu, 20 Oct 2022 09:50:14 +0800 -Subject: [PATCH 16/28] RISCV64: Add the implementation of symbol verify - -Verify the symbol to accept or reject a symbol from the kernel namelist. - -Signed-off-by: Xianting Tian -Signed-off-by: Lianbo Jiang ---- - riscv64.c | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - -diff --git a/riscv64.c b/riscv64.c -index ff77e41b9407..6b9a68840d4c 100644 ---- a/riscv64.c -+++ b/riscv64.c -@@ -165,10 +165,23 @@ riscv64_cmd_mach(void) - riscv64_display_machine_stats(); - } - -+/* -+ * Accept or reject a symbol from the kernel namelist. -+ */ - static int - riscv64_verify_symbol(const char *name, ulong value, char type) - { -- /* TODO: */ -+ if (CRASHDEBUG(8) && name && strlen(name)) -+ fprintf(fp, "%08lx %s\n", value, name); -+ -+ if (!(machdep->flags & KSYMS_START)) { -+ if (STREQ(name, "_text") || STREQ(name, "_stext")) -+ machdep->flags |= KSYMS_START; -+ -+ return (name && strlen(name) && !STRNEQ(name, "__func__.") && -+ !STRNEQ(name, "__crc_")); -+ } -+ - return TRUE; - } - --- -2.37.1 - diff --git a/0017-SLUB-Fix-for-offset-change-of-struct-slab-members-on.patch b/0017-SLUB-Fix-for-offset-change-of-struct-slab-members-on.patch deleted file mode 100644 index 19fcb60..0000000 --- a/0017-SLUB-Fix-for-offset-change-of-struct-slab-members-on.patch +++ /dev/null @@ -1,149 +0,0 @@ -From d83df2fb66cd77877d365fda32cd45c531796599 Mon Sep 17 00:00:00 2001 -From: Kazuhito Hagio -Date: Fri, 16 Dec 2022 14:03:46 +0900 -Subject: [PATCH 17/28] SLUB: Fix for offset change of struct slab members on - Linux 6.2-rc1 - -The following kernel commits split slab info from struct page into -struct slab in Linux 5.17. - - d122019bf061 ("mm: Split slab into its own type") - 07f910f9b729 ("mm: Remove slab from struct page") - -Crash commit 5f390ed811b0 followed the change for SLUB, but crash still -uses the offset of page.lru inappropriately. Luckily, it could work -because it was the same value as the offset of slab.slab_list until -Linux 6.1. - -However, kernel commit 130d4df57390 ("mm/sl[au]b: rearrange struct slab -fields to allow larger rcu_head") in Linux 6.2-rc1 changed the offset of -slab.slab_list. As a result, without the patch, "kmem -s|-S" options -print the following errors and fail to print values correctly for -kernels configured with CONFIG_SLUB. - - crash> kmem -S filp - CACHE OBJSIZE ALLOCATED TOTAL SLABS SSIZE NAME - kmem: filp: partial list slab: ffffcc650405ab88 invalid page.inuse: -1 - ffff8fa0401eca00 232 1267 1792 56 8k filp - ... - KMEM_CACHE_NODE NODE SLABS PARTIAL PER-CPU - ffff8fa0401cb8c0 0 56 24 8 - NODE 0 PARTIAL: - SLAB MEMORY NODE TOTAL ALLOCATED FREE - kmem: filp: invalid partial list slab pointer: ffffcc650405ab88 - -Signed-off-by: Kazuhito Hagio -Signed-off-by: Lianbo Jiang ---- - defs.h | 1 + - memory.c | 16 ++++++++++------ - symbols.c | 1 + - 3 files changed, 12 insertions(+), 6 deletions(-) - -diff --git a/defs.h b/defs.h -index 0cff47e30ae9..d3d837631632 100644 ---- a/defs.h -+++ b/defs.h -@@ -2188,6 +2188,7 @@ struct offset_table { /* stash of commonly-used offsets */ - long blk_mq_tags_rqs; - long request_queue_hctx_table; - long percpu_counter_counters; -+ long slab_slab_list; - }; - - struct size_table { /* stash of commonly-used sizes */ -diff --git a/memory.c b/memory.c -index 9d003713534b..d05737cc1429 100644 ---- a/memory.c -+++ b/memory.c -@@ -781,6 +781,8 @@ vm_init(void) - if (INVALID_MEMBER(page_slab)) - MEMBER_OFFSET_INIT(page_slab, "slab", "slab_cache"); - -+ MEMBER_OFFSET_INIT(slab_slab_list, "slab", "slab_list"); -+ - MEMBER_OFFSET_INIT(page_slab_page, "page", "slab_page"); - if (INVALID_MEMBER(page_slab_page)) - ANON_MEMBER_OFFSET_INIT(page_slab_page, "page", "slab_page"); -@@ -19474,6 +19476,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) - { - ulong next, last, list_head, flags; - int first; -+ long list_off = VALID_MEMBER(slab_slab_list) ? OFFSET(slab_slab_list) : OFFSET(page_lru); - - if (!node_ptr) - return; -@@ -19487,7 +19490,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) - next == list_head ? " (empty)\n" : ""); - first = 0; - while (next != list_head) { -- si->slab = last = next - OFFSET(page_lru); -+ si->slab = last = next - list_off; - if (first++ == 0) - fprintf(fp, " %s", slab_hdr); - -@@ -19510,7 +19513,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) - - if (!IS_KVADDR(next) || - ((next != list_head) && -- !is_page_ptr(next - OFFSET(page_lru), NULL))) { -+ !is_page_ptr(next - list_off, NULL))) { - error(INFO, - "%s: partial list slab: %lx invalid page.lru.next: %lx\n", - si->curname, last, next); -@@ -19537,7 +19540,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) - next == list_head ? " (empty)\n" : ""); - first = 0; - while (next != list_head) { -- si->slab = next - OFFSET(page_lru); -+ si->slab = next - list_off; - if (first++ == 0) - fprintf(fp, " %s", slab_hdr); - -@@ -19754,6 +19757,7 @@ count_partial(ulong node, struct meminfo *si, ulong *free) - short inuse, objects; - ulong total_inuse; - ulong count = 0; -+ long list_off = VALID_MEMBER(slab_slab_list) ? OFFSET(slab_slab_list) : OFFSET(page_lru); - - count = 0; - total_inuse = 0; -@@ -19765,12 +19769,12 @@ count_partial(ulong node, struct meminfo *si, ulong *free) - hq_open(); - - while (next != list_head) { -- if (!readmem(next - OFFSET(page_lru) + OFFSET(page_inuse), -+ if (!readmem(next - list_off + OFFSET(page_inuse), - KVADDR, &inuse, sizeof(ushort), "page.inuse", RETURN_ON_ERROR)) { - hq_close(); - return -1; - } -- last = next - OFFSET(page_lru); -+ last = next - list_off; - - if (inuse == -1) { - error(INFO, -@@ -19796,7 +19800,7 @@ count_partial(ulong node, struct meminfo *si, ulong *free) - } - if (!IS_KVADDR(next) || - ((next != list_head) && -- !is_page_ptr(next - OFFSET(page_lru), NULL))) { -+ !is_page_ptr(next - list_off, NULL))) { - error(INFO, "%s: partial list slab: %lx invalid page.lru.next: %lx\n", - si->curname, last, next); - break; -diff --git a/symbols.c b/symbols.c -index cb5b508dcc50..33e68d520a72 100644 ---- a/symbols.c -+++ b/symbols.c -@@ -9710,6 +9710,7 @@ dump_offset_table(char *spec, ulong makestruct) - OFFSET(slab_inuse)); - fprintf(fp, " slab_free: %ld\n", - OFFSET(slab_free)); -+ fprintf(fp, " slab_slab_list: %ld\n", OFFSET(slab_slab_list)); - - fprintf(fp, " kmem_cache_size: %ld\n", - OFFSET(kmem_cache_size)); --- -2.37.1 - diff --git a/0018-Fix-for-kmem-i-to-display-correct-SLAB-statistics-on.patch b/0018-Fix-for-kmem-i-to-display-correct-SLAB-statistics-on.patch deleted file mode 100644 index 893076e..0000000 --- a/0018-Fix-for-kmem-i-to-display-correct-SLAB-statistics-on.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 41d4b85ea50efc733df65ec8421a74be10e47987 Mon Sep 17 00:00:00 2001 -From: Lianbo Jiang -Date: Fri, 23 Dec 2022 18:42:35 +0800 -Subject: [PATCH 18/28] Fix for "kmem -i" to display correct SLAB statistics on - Linux 5.9 and later - -Kernel commit d42f3245c7e2 ("mm: memcg: convert vmstat slab counters to -bytes"), which is contained in Linux v5.9-rc1 and later kernels, renamed -NR_SLAB_{RECLAIMABLE,UNRECLAIMABLE} to NR_SLAB_{RECLAIMABLE,UNRECLAIMABLE}_B. - -Without the patch, "kmem -i" command will display incorrect SLAB -statistics: - - crash> kmem -i | grep -e PAGES -e SLAB - PAGES TOTAL PERCENTAGE - SLAB 89458 349.4 MB 0% of TOTAL MEM - ^^^^^ ^^^^^ - -With the patch, the actual result is: - crash> kmem -i | grep -e PAGES -e SLAB - PAGES TOTAL PERCENTAGE - SLAB 261953 1023.3 MB 0% of TOTAL MEM - -Reported-by: Buland Kumar Singh -Signed-off-by: Lianbo Jiang -Signed-off-by: Kazuhito Hagio ---- - memory.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/memory.c b/memory.c -index d05737cc1429..625a94b7d7d4 100644 ---- a/memory.c -+++ b/memory.c -@@ -8388,6 +8388,11 @@ dump_kmeminfo(void) - get_slabs = nr_slab; - if (dump_vm_stat("NR_SLAB_UNRECLAIMABLE", &nr_slab, 0)) - get_slabs += nr_slab; -+ } else if (dump_vm_stat("NR_SLAB_RECLAIMABLE_B", &nr_slab, 0)) { -+ /* 5.9 and later */ -+ get_slabs = nr_slab; -+ if (dump_vm_stat("NR_SLAB_UNRECLAIMABLE_B", &nr_slab, 0)) -+ get_slabs += nr_slab; - } - } - --- -2.37.1 - diff --git a/0019-Fix-build-failure-due-to-no-EM_RISCV-with-glibc-2.23.patch b/0019-Fix-build-failure-due-to-no-EM_RISCV-with-glibc-2.23.patch deleted file mode 100644 index 6f35fbb..0000000 --- a/0019-Fix-build-failure-due-to-no-EM_RISCV-with-glibc-2.23.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 4cf7c714e3cc97e6d41a9b1fdd48f5199f632a4d Mon Sep 17 00:00:00 2001 -From: Kazuhito Hagio -Date: Tue, 27 Dec 2022 09:53:46 +0900 -Subject: [PATCH 19/28] Fix build failure due to no EM_RISCV with glibc-2.23 - and earlier - -With glibc-2.23 and earlier (e.g. RHEL7), crash build fails with errors -like this due to EM_RISCV undeclared: - - $ make -j 24 warn - TARGET: X86_64 - CRASH: 8.0.2++ - GDB: 10.2 - ... - symbols.c: In function 'is_kernel': - symbols.c:3746:8: error: 'EM_RISCV' undeclared (first use in this function) - case EM_RISCV: - ^ - ... - -Define EM_RISCV as 243 [1][2] if not defined. - -[1] https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=94e73c95d9b5 -[2] http://www.sco.com/developers/gabi/latest/ch4.eheader.html - -Signed-off-by: Kazuhito Hagio -Signed-off-by: Lianbo Jiang ---- - defs.h | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/defs.h b/defs.h -index d3d837631632..08ac4dc96a92 100644 ---- a/defs.h -+++ b/defs.h -@@ -3493,6 +3493,10 @@ struct arm64_stackframe { - #define _MAX_PHYSMEM_BITS 48 - #endif /* MIPS64 */ - -+#ifndef EM_RISCV -+#define EM_RISCV 243 -+#endif -+ - #ifdef RISCV64 - #define _64BIT_ - #define MACHINE_TYPE "RISCV64" --- -2.37.1 - diff --git a/0020-gdb-Fix-an-assertion-failure-in-the-gdb-s-copy_type.patch b/0020-gdb-Fix-an-assertion-failure-in-the-gdb-s-copy_type.patch deleted file mode 100644 index 6f83e15..0000000 --- a/0020-gdb-Fix-an-assertion-failure-in-the-gdb-s-copy_type.patch +++ /dev/null @@ -1,74 +0,0 @@ -From a053a1442dff4eecd17aee089502feac922a7af7 Mon Sep 17 00:00:00 2001 -From: Lianbo Jiang -Date: Mon, 26 Dec 2022 21:03:17 +0800 -Subject: [PATCH 20/28] gdb: Fix an assertion failure in the gdb's copy_type() - -This is a backported patch from gdb. Without the patch, the following -crash command may abort due to an assertion failure in the gdb's -copy_type(): - - crash> px __per_cpu_start:0 - gdbtypes.c:5505: internal-error: type* copy_type(const type*): Assertion `TYPE_OBJFILE_OWNED (type)' failed. - A problem internal to GDB has been detected, - further debugging may prove unreliable. - Quit this debugging session? (y or n) - -The gdb commit 8e2da1651879 ("Fix assertion failure in copy_type") -solved the current issue. - -Reported-by: Buland Kumar Singh -Signed-off-by: Lianbo Jiang ---- - gdb-10.2.patch | 39 +++++++++++++++++++++++++++++++++++++++ - 1 file changed, 39 insertions(+) - -diff --git a/gdb-10.2.patch b/gdb-10.2.patch -index 7055f6e0fb0b..aa34743501ad 100644 ---- a/gdb-10.2.patch -+++ b/gdb-10.2.patch -@@ -2039,3 +2039,42 @@ exit 0 - } - nextfield++; - } -+--- gdb-10.2/gdb/gdbtypes.c.orig -++++ gdb-10.2/gdb/gdbtypes.c -+@@ -5492,27 +5492,25 @@ copy_type_recursive (struct objfile *objfile, -+ } -+ -+ /* Make a copy of the given TYPE, except that the pointer & reference -+- types are not preserved. -+- -+- This function assumes that the given type has an associated objfile. -+- This objfile is used to allocate the new type. */ -++ types are not preserved. */ -+ -+ struct type * -+ copy_type (const struct type *type) -+ { -+- struct type *new_type; -+- -+- gdb_assert (TYPE_OBJFILE_OWNED (type)); -++ struct type *new_type = alloc_type_copy (type); -+ -+- new_type = alloc_type_copy (type); -+ TYPE_INSTANCE_FLAGS (new_type) = TYPE_INSTANCE_FLAGS (type); -+ TYPE_LENGTH (new_type) = TYPE_LENGTH (type); -+ memcpy (TYPE_MAIN_TYPE (new_type), TYPE_MAIN_TYPE (type), -+ sizeof (struct main_type)); -+ if (type->main_type->dyn_prop_list != NULL) -+- new_type->main_type->dyn_prop_list -+- = copy_dynamic_prop_list (&TYPE_OBJFILE (type) -> objfile_obstack, -+- type->main_type->dyn_prop_list); -++ { -++ struct obstack *storage = (TYPE_OBJFILE_OWNED (type) -++ ? &TYPE_OBJFILE (type)->objfile_obstack -++ : gdbarch_obstack (TYPE_OWNER (type).gdbarch)); -++ new_type->main_type->dyn_prop_list -++ = copy_dynamic_prop_list (storage, type->main_type->dyn_prop_list); -++ } -+ -+ return new_type; -+ } --- -2.37.1 - diff --git a/0021-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.1-and-later.patch b/0021-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.1-and-later.patch deleted file mode 100644 index a187e07..0000000 --- a/0021-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.1-and-later.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 120d6e89fc14eb7f1c9a3106305c7066730f36b8 Mon Sep 17 00:00:00 2001 -From: Kazuhito Hagio -Date: Thu, 5 Jan 2023 17:18:51 +0900 -Subject: [PATCH 21/28] SLAB: Fix for "kmem -s|-S" options on Linux 6.1 and - later - -Kernel commit e36ce448a08d ("mm/slab: use kmalloc_node() for off slab -freelist_idx_t array allocation"), which is contained in Linux 6.1 and -later kernels, removed kmem_cache.freelist_cache member on kernels -configured with CONFIG_SLAB=y. - -Without the patch, crash does not set SLAB_OVERLOAD_PAGE and -"kmem -s|-S" options fail with the following error: - - kmem: invalid structure member offset: slab_list - FILE: memory.c LINE: 12156 FUNCTION: verify_slab_v2() - -Use kmem_cache.freelist_size instead, which was introduced together -with kmem_cache.freelist_cache by kernel commit 8456a648cf44. - -Signed-off-by: Kazuhito Hagio -Signed-off-by: Lianbo Jiang ---- - memory.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/memory.c b/memory.c -index 625a94b7d7d4..71ded688206f 100644 ---- a/memory.c -+++ b/memory.c -@@ -535,8 +535,11 @@ vm_init(void) - /* - * slab: overload struct slab over struct page - * https://lkml.org/lkml/2013/10/16/155 -+ * -+ * commit e36ce448a08d removed kmem_cache.freelist_cache in 6.1, -+ * so use freelist_size instead. - */ -- if (MEMBER_EXISTS("kmem_cache", "freelist_cache")) { -+ if (MEMBER_EXISTS("kmem_cache", "freelist_size")) { - vt->flags |= SLAB_OVERLOAD_PAGE; - ANON_MEMBER_OFFSET_INIT(page_s_mem, "page", "s_mem"); - ANON_MEMBER_OFFSET_INIT(page_freelist, "page", "freelist"); --- -2.37.1 - diff --git a/0022-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.2-rc1-and-l.patch b/0022-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.2-rc1-and-l.patch deleted file mode 100644 index 67f8deb..0000000 --- a/0022-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.2-rc1-and-l.patch +++ /dev/null @@ -1,233 +0,0 @@ -From ac96e17d1de51016ee1a983e68c7e840ff55ab8d Mon Sep 17 00:00:00 2001 -From: Kazuhito Hagio -Date: Thu, 5 Jan 2023 17:36:42 +0900 -Subject: [PATCH 22/28] SLAB: Fix for "kmem -s|-S" options on Linux 6.2-rc1 and - later - -Kernel commit 130d4df57390 ("mm/sl[au]b: rearrange struct slab fields to -allow larger rcu_head"), which is contained in Linux 6.2-rc1 and later -kernels, changed the offset of slab.slab_list and now it's not equal to -the offset of page.lru. - -Without the patch, "kmem -s|-S" options print errors and zeros for slab -counters like this for kernels configured with CONFIG_SLAB=y. - - crash> kmem -s - CACHE OBJSIZE ALLOCATED TOTAL SLABS SSIZE NAME - kmem: rpc_inode_cache: partial list: page/slab: fffff31ac4125190 bad active counter: 99476865 - kmem: rpc_inode_cache: partial list: page/slab: fffff31ac4125190 bad s_mem pointer: 100000003 - kmem: rpc_inode_cache: full list: page/slab: fffff31ac4125150 bad active counter: 99476225 - kmem: rpc_inode_cache: full list: page/slab: fffff31ac4125150 bad active counter: 99476225 - kmem: rpc_inode_cache: full list: page/slab: fffff31ac4125150 bad s_mem pointer: 100000005 - ffff930202adfb40 704 0 0 0 4k rpc_inode_cache - ... - -Signed-off-by: Kazuhito Hagio -Signed-off-by: Lianbo Jiang ---- - memory.c | 45 +++++++++++++++++++++++++-------------------- - 1 file changed, 25 insertions(+), 20 deletions(-) - -diff --git a/memory.c b/memory.c -index 71ded688206f..156de2f7b5a3 100644 ---- a/memory.c -+++ b/memory.c -@@ -78,6 +78,7 @@ struct meminfo { /* general purpose memory information structure */ - int *freelist; - int freelist_index_size; - ulong random; -+ ulong list_offset; - }; - - /* -@@ -553,6 +554,8 @@ vm_init(void) - MEMBER_OFFSET_INIT(page_freelist, "slab", "freelist"); - if (INVALID_MEMBER(page_active)) - MEMBER_OFFSET_INIT(page_active, "slab", "active"); -+ -+ MEMBER_OFFSET_INIT(slab_slab_list, "slab", "slab_list"); - } - - if (!VALID_STRUCT(kmem_slab_s) && VALID_STRUCT(slab_s)) { -@@ -10767,6 +10770,8 @@ dump_kmem_cache_percpu_v2(struct meminfo *si) - if (vt->flags & SLAB_OVERLOAD_PAGE) { - si->freelist = si->kmem_bufctl; - si->freelist_index_size = slab_freelist_index_size(); -+ si->list_offset = VALID_MEMBER(slab_slab_list) ? -+ OFFSET(slab_slab_list) : OFFSET(page_lru); - } - for (i = 0; i < vt->kmem_max_cpus; i++) - si->cpudata[i] = (ulong *) -@@ -11983,7 +11988,7 @@ do_slab_chain_slab_overload_page(long cmd, struct meminfo *si) - } - last = si->slab; - -- readmem(si->slab - OFFSET(page_lru), KVADDR, page_buf, -+ readmem(si->slab - si->list_offset, KVADDR, page_buf, - SIZE(page), "page (slab) buffer", - FAULT_ON_ERROR); - -@@ -11996,8 +12001,7 @@ do_slab_chain_slab_overload_page(long cmd, struct meminfo *si) - - si->num_slabs++; - -- si->slab = ULONG(page_buf + -- OFFSET(page_lru)); -+ si->slab = ULONG(page_buf + si->list_offset); - - /* - * Check for slab transition. (Tony Dziedzic) -@@ -12024,11 +12028,11 @@ do_slab_chain_slab_overload_page(long cmd, struct meminfo *si) - case SLAB_WALKTHROUGH: - if (si->flags & SLAB_OVERLOAD_PAGE_PTR) { - specified_slab = si->spec_addr; -- si->slab = si->spec_addr + OFFSET(page_lru); -+ si->slab = si->spec_addr + si->list_offset; - } else { - specified_slab = si->slab; - if (si->slab) -- si->slab += OFFSET(page_lru); -+ si->slab += si->list_offset; - } - si->flags |= (SLAB_WALKTHROUGH|SLAB_FIRST_NODE); - si->flags &= ~SLAB_GET_COUNTS; -@@ -12082,7 +12086,7 @@ do_slab_chain_slab_overload_page(long cmd, struct meminfo *si) - if (si->slab == slab_chains[s]) - continue; - -- readmem(si->slab - OFFSET(page_lru), KVADDR, page_buf, -+ readmem(si->slab - si->list_offset, KVADDR, page_buf, - SIZE(page), "page (slab) buffer", - FAULT_ON_ERROR); - -@@ -12242,7 +12246,7 @@ verify_slab_overload_page(struct meminfo *si, ulong last, int s) - - errcnt = 0; - -- if (!readmem(si->slab - OFFSET(page_lru), KVADDR, page_buf, -+ if (!readmem(si->slab - si->list_offset, KVADDR, page_buf, - SIZE(page), "page (slab) buffer", QUIET|RETURN_ON_ERROR)) { - error(INFO, "%s: %s list: bad slab pointer: %lx\n", - si->curname, list, si->slab); -@@ -12250,7 +12254,7 @@ verify_slab_overload_page(struct meminfo *si, ulong last, int s) - return FALSE; - } - -- list_head = (struct kernel_list_head *)(page_buf + OFFSET(page_lru)); -+ list_head = (struct kernel_list_head *)(page_buf + si->list_offset); - if (!IS_KVADDR((ulong)list_head->next) || - !accessible((ulong)list_head->next)) { - error(INFO, "%s: %s list: page/slab: %lx bad next pointer: %lx\n", -@@ -12569,7 +12573,7 @@ dump_slab_overload_page(struct meminfo *si) - int tmp; - ulong slab_overload_page, freelist; - -- slab_overload_page = si->slab - OFFSET(page_lru); -+ slab_overload_page = si->slab - si->list_offset; - - readmem(slab_overload_page + OFFSET(page_s_mem), - KVADDR, &si->s_mem, sizeof(ulong), -@@ -12796,12 +12800,12 @@ gather_slab_free_list_slab_overload_page(struct meminfo *si) - - if (CRASHDEBUG(1)) - fprintf(fp, "slab page: %lx active: %ld si->c_num: %ld\n", -- si->slab - OFFSET(page_lru), si->s_inuse, si->c_num); -+ si->slab - si->list_offset, si->s_inuse, si->c_num); - - if (si->s_inuse == si->c_num ) - return; - -- slab_overload_page = si->slab - OFFSET(page_lru); -+ slab_overload_page = si->slab - si->list_offset; - readmem(slab_overload_page + OFFSET(page_freelist), - KVADDR, &freelist, sizeof(void *), "page freelist", - FAULT_ON_ERROR); -@@ -13099,7 +13103,7 @@ dump_slab_objects_percpu(struct meminfo *si) - - if ((si->flags & ADDRESS_SPECIFIED) && - (vt->flags & SLAB_OVERLOAD_PAGE)) { -- readmem(si->slab - OFFSET(page_lru) + OFFSET(page_freelist), -+ readmem(si->slab - si->list_offset + OFFSET(page_freelist), - KVADDR, &freelist, sizeof(ulong), "page.freelist", - FAULT_ON_ERROR); - -@@ -18713,6 +18717,9 @@ dump_kmem_cache_slub(struct meminfo *si) - - si->cache_buf = GETBUF(SIZE(kmem_cache)); - -+ si->list_offset = VALID_MEMBER(slab_slab_list) ? -+ OFFSET(slab_slab_list) : OFFSET(page_lru); -+ - if (VALID_MEMBER(page_objects) && - OFFSET(page_objects) == OFFSET(page_inuse)) - si->flags |= SLAB_BITFIELD; -@@ -19484,7 +19491,6 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) - { - ulong next, last, list_head, flags; - int first; -- long list_off = VALID_MEMBER(slab_slab_list) ? OFFSET(slab_slab_list) : OFFSET(page_lru); - - if (!node_ptr) - return; -@@ -19498,7 +19504,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) - next == list_head ? " (empty)\n" : ""); - first = 0; - while (next != list_head) { -- si->slab = last = next - list_off; -+ si->slab = last = next - si->list_offset; - if (first++ == 0) - fprintf(fp, " %s", slab_hdr); - -@@ -19521,7 +19527,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) - - if (!IS_KVADDR(next) || - ((next != list_head) && -- !is_page_ptr(next - list_off, NULL))) { -+ !is_page_ptr(next - si->list_offset, NULL))) { - error(INFO, - "%s: partial list slab: %lx invalid page.lru.next: %lx\n", - si->curname, last, next); -@@ -19548,7 +19554,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) - next == list_head ? " (empty)\n" : ""); - first = 0; - while (next != list_head) { -- si->slab = next - list_off; -+ si->slab = next - si->list_offset; - if (first++ == 0) - fprintf(fp, " %s", slab_hdr); - -@@ -19765,7 +19771,6 @@ count_partial(ulong node, struct meminfo *si, ulong *free) - short inuse, objects; - ulong total_inuse; - ulong count = 0; -- long list_off = VALID_MEMBER(slab_slab_list) ? OFFSET(slab_slab_list) : OFFSET(page_lru); - - count = 0; - total_inuse = 0; -@@ -19777,12 +19782,12 @@ count_partial(ulong node, struct meminfo *si, ulong *free) - hq_open(); - - while (next != list_head) { -- if (!readmem(next - list_off + OFFSET(page_inuse), -+ if (!readmem(next - si->list_offset + OFFSET(page_inuse), - KVADDR, &inuse, sizeof(ushort), "page.inuse", RETURN_ON_ERROR)) { - hq_close(); - return -1; - } -- last = next - list_off; -+ last = next - si->list_offset; - - if (inuse == -1) { - error(INFO, -@@ -19808,7 +19813,7 @@ count_partial(ulong node, struct meminfo *si, ulong *free) - } - if (!IS_KVADDR(next) || - ((next != list_head) && -- !is_page_ptr(next - list_off, NULL))) { -+ !is_page_ptr(next - si->list_offset, NULL))) { - error(INFO, "%s: partial list slab: %lx invalid page.lru.next: %lx\n", - si->curname, last, next); - break; --- -2.37.1 - diff --git a/0023-Port-the-maple-tree-data-structures-and-functions.patch b/0023-Port-the-maple-tree-data-structures-and-functions.patch deleted file mode 100644 index 96994be..0000000 --- a/0023-Port-the-maple-tree-data-structures-and-functions.patch +++ /dev/null @@ -1,633 +0,0 @@ -From 872cad2d63b3a07f65323fe80a7abb29ea276b44 Mon Sep 17 00:00:00 2001 -From: Tao Liu -Date: Tue, 10 Jan 2023 14:56:27 +0800 -Subject: [PATCH 23/28] Port the maple tree data structures and functions - -There have been two ways to iterate vm_area_struct until Linux 6.0: - 1) by rbtree, aka vma.vm_rb; - 2) by linked list, aka vma.vm_{next,prev}. -However with the maple tree patches[1][2] in Linux 6.1, vm_rb and -vm_{next,prev} are removed from vm_area_struct. The vm_area_dump() -in crash mainly uses the linked list for vma iteration, which will -not work for this case. So the maple tree iteration needs to be -ported to crash. - -For crash, currently it only iteratively reads the maple tree, -no more rcu safe or maple tree modification features needed. -So we only port a subset of kernel maple tree features. -In addition, we need to modify the ported kernel source code, -making it compatible with crash. - -This patch deals with the two issues: - 1) Poring mt_dump() function and all its dependencies from - kernel source to crash, to enable crash maple tree iteration, - 2) adapting the ported code with crash. - -[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=524e00b36e8c547f5582eef3fb645a8d9fc5e3df -[2]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=763ecb035029f500d7e6dc99acd1ad299b7726a1 - -Signed-off-by: Tao Liu -Signed-off-by: Lianbo Jiang ---- - Makefile | 10 +- - defs.h | 19 +++ - maple_tree.c | 407 +++++++++++++++++++++++++++++++++++++++++++++++++++ - maple_tree.h | 82 +++++++++++ - 4 files changed, 515 insertions(+), 3 deletions(-) - create mode 100644 maple_tree.c - create mode 100644 maple_tree.h - -diff --git a/Makefile b/Makefile -index 1506dd426bc7..102597f735b2 100644 ---- a/Makefile -+++ b/Makefile -@@ -59,6 +59,7 @@ IBM_HFILES=ibm_common.h - SADUMP_HFILES=sadump.h - UNWIND_HFILES=unwind.h unwind_i.h rse.h unwind_x86.h unwind_x86_64.h - VMWARE_HFILES=vmware_vmss.h -+MAPLE_TREE_HFILES=maple_tree.h - - CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \ - kernel.c test.c gdb_interface.c configure.c net.c dev.c bpf.c \ -@@ -73,12 +74,12 @@ CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \ - xen_hyper.c xen_hyper_command.c xen_hyper_global_data.c \ - xen_hyper_dump_tables.c kvmdump.c qemu.c qemu-load.c sadump.c ipcs.c \ - ramdump.c vmware_vmss.c vmware_guestdump.c \ -- xen_dom0.c kaslr_helper.c sbitmap.c -+ xen_dom0.c kaslr_helper.c sbitmap.c maple_tree.c - - SOURCE_FILES=${CFILES} ${GENERIC_HFILES} ${MCORE_HFILES} \ - ${REDHAT_CFILES} ${REDHAT_HFILES} ${UNWIND_HFILES} \ - ${LKCD_DUMP_HFILES} ${LKCD_TRACE_HFILES} ${LKCD_OBSOLETE_HFILES}\ -- ${IBM_HFILES} ${SADUMP_HFILES} ${VMWARE_HFILES} -+ ${IBM_HFILES} ${SADUMP_HFILES} ${VMWARE_HFILES} ${MAPLE_TREE_HFILES} - - OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \ - build_data.o kernel.o test.o gdb_interface.o net.o dev.o bpf.o \ -@@ -93,7 +94,7 @@ OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \ - xen_hyper.o xen_hyper_command.o xen_hyper_global_data.o \ - xen_hyper_dump_tables.o kvmdump.o qemu.o qemu-load.o sadump.o ipcs.o \ - ramdump.o vmware_vmss.o vmware_guestdump.o \ -- xen_dom0.o kaslr_helper.o sbitmap.o -+ xen_dom0.o kaslr_helper.o sbitmap.o maple_tree.o - - MEMORY_DRIVER_FILES=memory_driver/Makefile memory_driver/crash.c memory_driver/README - -@@ -539,6 +540,9 @@ kaslr_helper.o: ${GENERIC_HFILES} kaslr_helper.c - bpf.o: ${GENERIC_HFILES} bpf.c - ${CC} -c ${CRASH_CFLAGS} bpf.c ${WARNING_OPTIONS} ${WARNING_ERROR} - -+maple_tree.o: ${GENERIC_HFILES} ${MAPLE_TREE_HFILES} maple_tree.c -+ ${CC} -c ${CRASH_CFLAGS} maple_tree.c ${WARNING_OPTIONS} ${WARNING_ERROR} -+ - ${PROGRAM}: force - @$(MAKE) all - -diff --git a/defs.h b/defs.h -index 08ac4dc96a92..46bfd4a67e64 100644 ---- a/defs.h -+++ b/defs.h -@@ -2189,6 +2189,21 @@ struct offset_table { /* stash of commonly-used offsets */ - long request_queue_hctx_table; - long percpu_counter_counters; - long slab_slab_list; -+ long mm_struct_mm_mt; -+ long maple_tree_ma_root; -+ long maple_tree_ma_flags; -+ long maple_node_parent; -+ long maple_node_ma64; -+ long maple_node_mr64; -+ long maple_node_slot; -+ long maple_arange_64_pivot; -+ long maple_arange_64_slot; -+ long maple_arange_64_gap; -+ long maple_arange_64_meta; -+ long maple_range_64_pivot; -+ long maple_range_64_slot; -+ long maple_metadata_end; -+ long maple_metadata_gap; - }; - - struct size_table { /* stash of commonly-used sizes */ -@@ -2360,6 +2375,8 @@ struct size_table { /* stash of commonly-used sizes */ - long sbq_wait_state; - long blk_mq_tags; - long percpu_counter; -+ long maple_tree; -+ long maple_node; - }; - - struct array_table { -@@ -5742,6 +5759,8 @@ int file_dump(ulong, ulong, ulong, int, int); - int same_file(char *, char *); - int cleanup_memory_driver(void); - -+void maple_init(void); -+int do_mptree(struct tree_data *); - - /* - * help.c -diff --git a/maple_tree.c b/maple_tree.c -new file mode 100644 -index 000000000000..474faeda6252 ---- /dev/null -+++ b/maple_tree.c -@@ -0,0 +1,407 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Maple Tree implementation -+ * Copyright (c) 2018-2022 Oracle Corporation -+ * Authors: Liam R. Howlett -+ * Matthew Wilcox -+ * -+ * The following are copied and modified from lib/maple_tree.c -+ */ -+ -+#include "maple_tree.h" -+#include "defs.h" -+ -+unsigned char *mt_slots = NULL; -+unsigned char *mt_pivots = NULL; -+ulong mt_max[4] = {0}; -+ -+#define MAPLE_BUFSIZE 512 -+ -+static inline ulong mte_to_node(ulong maple_enode_entry) -+{ -+ return maple_enode_entry & ~MAPLE_NODE_MASK; -+} -+ -+static inline enum maple_type mte_node_type(ulong maple_enode_entry) -+{ -+ return (maple_enode_entry >> MAPLE_NODE_TYPE_SHIFT) & -+ MAPLE_NODE_TYPE_MASK; -+} -+ -+static inline ulong mt_slot(void **slots, unsigned char offset) -+{ -+ return (ulong)slots[offset]; -+} -+ -+static inline bool ma_is_leaf(const enum maple_type type) -+{ -+ return type < maple_range_64; -+} -+ -+/*************** For cmd_tree ********************/ -+ -+struct maple_tree_ops { -+ void (*entry)(ulong node, ulong slot, const char *path, -+ ulong index, void *private); -+ void *private; -+ bool is_td; -+}; -+ -+static const char spaces[] = " "; -+ -+static void do_mt_range64(ulong, ulong, ulong, uint, char *, ulong *, -+ struct maple_tree_ops *); -+static void do_mt_arange64(ulong, ulong, ulong, uint, char *, ulong *, -+ struct maple_tree_ops *); -+static void do_mt_entry(ulong, ulong, ulong, uint, uint, char *, ulong *, -+ struct maple_tree_ops *); -+static void do_mt_node(ulong, ulong, ulong, uint, char *, ulong *, -+ struct maple_tree_ops *); -+struct req_entry *fill_member_offsets(char *); -+void dump_struct_members_fast(struct req_entry *, int, ulong); -+void dump_struct_members_for_tree(struct tree_data *, int, ulong); -+ -+static void mt_dump_range(ulong min, ulong max, uint depth) -+{ -+ if (min == max) -+ fprintf(fp, "%.*s%lu: ", depth * 2, spaces, min); -+ else -+ fprintf(fp, "%.*s%lu-%lu: ", depth * 2, spaces, min, max); -+} -+ -+static inline bool mt_is_reserved(ulong entry) -+{ -+ return (entry < MAPLE_RESERVED_RANGE) && xa_is_internal(entry); -+} -+ -+static inline bool mte_is_leaf(ulong maple_enode_entry) -+{ -+ return ma_is_leaf(mte_node_type(maple_enode_entry)); -+} -+ -+static uint mt_height(char *mt_buf) -+{ -+ return (UINT(mt_buf + OFFSET(maple_tree_ma_flags)) & -+ MT_FLAGS_HEIGHT_MASK) -+ >> MT_FLAGS_HEIGHT_OFFSET; -+} -+ -+static void dump_mt_range64(char *mr64_buf) -+{ -+ int i; -+ -+ fprintf(fp, " contents: "); -+ for (i = 0; i < mt_slots[maple_range_64] - 1; i++) -+ fprintf(fp, "%p %lu ", -+ VOID_PTR(mr64_buf + OFFSET(maple_range_64_slot) -+ + sizeof(void *) * i), -+ ULONG(mr64_buf + OFFSET(maple_range_64_pivot) -+ + sizeof(ulong) * i)); -+ fprintf(fp, "%p\n", VOID_PTR(mr64_buf + OFFSET(maple_range_64_slot) -+ + sizeof(void *) * i)); -+} -+ -+static void dump_mt_arange64(char *ma64_buf) -+{ -+ int i; -+ -+ fprintf(fp, " contents: "); -+ for (i = 0; i < mt_slots[maple_arange_64]; i++) -+ fprintf(fp, "%lu ", ULONG(ma64_buf + OFFSET(maple_arange_64_gap) -+ + sizeof(ulong) * i)); -+ -+ fprintf(fp, "| %02X %02X| ", -+ UCHAR(ma64_buf + OFFSET(maple_arange_64_meta) + -+ OFFSET(maple_metadata_end)), -+ UCHAR(ma64_buf + OFFSET(maple_arange_64_meta) + -+ OFFSET(maple_metadata_gap))); -+ -+ for (i = 0; i < mt_slots[maple_arange_64] - 1; i++) -+ fprintf(fp, "%p %lu ", -+ VOID_PTR(ma64_buf + OFFSET(maple_arange_64_slot) + -+ sizeof(void *) * i), -+ ULONG(ma64_buf + OFFSET(maple_arange_64_pivot) + -+ sizeof(ulong) * i)); -+ fprintf(fp, "%p\n", VOID_PTR(ma64_buf + OFFSET(maple_arange_64_slot) + -+ sizeof(void *) * i)); -+} -+ -+static void dump_mt_entry(ulong entry, ulong min, ulong max, uint depth) -+{ -+ mt_dump_range(min, max, depth); -+ -+ if (xa_is_value(entry)) -+ fprintf(fp, "value %ld (0x%lx) [0x%lx]\n", xa_to_value(entry), -+ xa_to_value(entry), entry); -+ else if (xa_is_zero(entry)) -+ fprintf(fp, "zero (%ld)\n", xa_to_internal(entry)); -+ else if (mt_is_reserved(entry)) -+ fprintf(fp, "UNKNOWN ENTRY (0x%lx)\n", entry); -+ else -+ fprintf(fp, "0x%lx\n", entry); -+} -+ -+static void dump_mt_node(ulong maple_node, char *node_data, uint type, -+ ulong min, ulong max, uint depth) -+{ -+ mt_dump_range(min, max, depth); -+ -+ fprintf(fp, "node 0x%lx depth %d type %d parent %p", -+ maple_node, depth, type, -+ maple_node ? VOID_PTR(node_data + OFFSET(maple_node_parent)) : -+ NULL); -+} -+ -+static void do_mt_range64(ulong entry, ulong min, ulong max, -+ uint depth, char *path, ulong *global_index, -+ struct maple_tree_ops *ops) -+{ -+ ulong maple_node_m_node = mte_to_node(entry); -+ char node_buf[MAPLE_BUFSIZE]; -+ bool leaf = mte_is_leaf(entry); -+ ulong first = min, last; -+ int i; -+ int len = strlen(path); -+ struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL; -+ char *mr64_buf; -+ -+ if (SIZE(maple_node) > MAPLE_BUFSIZE) -+ error(FATAL, "MAPLE_BUFSIZE should be larger than maple_node struct"); -+ -+ readmem(maple_node_m_node, KVADDR, node_buf, SIZE(maple_node), -+ "mt_dump_range64 read maple_node", FAULT_ON_ERROR); -+ -+ mr64_buf = node_buf + OFFSET(maple_node_mr64); -+ -+ for (i = 0; i < mt_slots[maple_range_64]; i++) { -+ last = max; -+ -+ if (i < (mt_slots[maple_range_64] - 1)) -+ last = ULONG(mr64_buf + OFFSET(maple_range_64_pivot) + -+ sizeof(ulong) * i); -+ -+ else if (!VOID_PTR(mr64_buf + OFFSET(maple_range_64_slot) + -+ sizeof(void *) * i) && -+ max != mt_max[mte_node_type(entry)]) -+ break; -+ if (last == 0 && i > 0) -+ break; -+ if (leaf) -+ do_mt_entry(mt_slot((void **)(mr64_buf + -+ OFFSET(maple_range_64_slot)), i), -+ first, last, depth + 1, i, path, global_index, ops); -+ else if (VOID_PTR(mr64_buf + OFFSET(maple_range_64_slot) + -+ sizeof(void *) * i)) { -+ sprintf(path + len, "/%d", i); -+ do_mt_node(mt_slot((void **)(mr64_buf + -+ OFFSET(maple_range_64_slot)), i), -+ first, last, depth + 1, path, global_index, ops); -+ } -+ -+ if (last == max) -+ break; -+ if (last > max) { -+ fprintf(fp, "node %p last (%lu) > max (%lu) at pivot %d!\n", -+ mr64_buf, last, max, i); -+ break; -+ } -+ first = last + 1; -+ } -+} -+ -+static void do_mt_arange64(ulong entry, ulong min, ulong max, -+ uint depth, char *path, ulong *global_index, -+ struct maple_tree_ops *ops) -+{ -+ ulong maple_node_m_node = mte_to_node(entry); -+ char node_buf[MAPLE_BUFSIZE]; -+ bool leaf = mte_is_leaf(entry); -+ ulong first = min, last; -+ int i; -+ int len = strlen(path); -+ struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL; -+ char *ma64_buf; -+ -+ if (SIZE(maple_node) > MAPLE_BUFSIZE) -+ error(FATAL, "MAPLE_BUFSIZE should be larger than maple_node struct"); -+ -+ readmem(maple_node_m_node, KVADDR, node_buf, SIZE(maple_node), -+ "mt_dump_arange64 read maple_node", FAULT_ON_ERROR); -+ -+ ma64_buf = node_buf + OFFSET(maple_node_ma64); -+ -+ for (i = 0; i < mt_slots[maple_arange_64]; i++) { -+ last = max; -+ -+ if (i < (mt_slots[maple_arange_64] - 1)) -+ last = ULONG(ma64_buf + OFFSET(maple_arange_64_pivot) + -+ sizeof(ulong) * i); -+ else if (!VOID_PTR(ma64_buf + OFFSET(maple_arange_64_slot) + -+ sizeof(void *) * i)) -+ break; -+ if (last == 0 && i > 0) -+ break; -+ -+ if (leaf) -+ do_mt_entry(mt_slot((void **)(ma64_buf + -+ OFFSET(maple_arange_64_slot)), i), -+ first, last, depth + 1, i, path, global_index, ops); -+ else if (VOID_PTR(ma64_buf + OFFSET(maple_arange_64_slot) + -+ sizeof(void *) * i)) { -+ sprintf(path + len, "/%d", i); -+ do_mt_node(mt_slot((void **)(ma64_buf + -+ OFFSET(maple_arange_64_slot)), i), -+ first, last, depth + 1, path, global_index, ops); -+ } -+ -+ if (last == max) -+ break; -+ if (last > max) { -+ fprintf(fp, "node %p last (%lu) > max (%lu) at pivot %d!\n", -+ ma64_buf, last, max, i); -+ break; -+ } -+ first = last + 1; -+ } -+} -+ -+static void do_mt_entry(ulong entry, ulong min, ulong max, uint depth, -+ uint index, char *path, ulong *global_index, -+ struct maple_tree_ops *ops) -+{ -+ int print_radix = 0, i; -+ static struct req_entry **e = NULL; -+ struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL; -+ -+ if (!td) -+ return; -+} -+ -+static void do_mt_node(ulong entry, ulong min, ulong max, -+ uint depth, char *path, ulong *global_index, -+ struct maple_tree_ops *ops) -+{ -+ ulong maple_node = mte_to_node(entry); -+ uint type = mte_node_type(entry); -+ uint i; -+ char node_buf[MAPLE_BUFSIZE]; -+ struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL; -+ -+ if (SIZE(maple_node) > MAPLE_BUFSIZE) -+ error(FATAL, "MAPLE_BUFSIZE should be larger than maple_node struct"); -+ -+ readmem(maple_node, KVADDR, node_buf, SIZE(maple_node), -+ "mt_dump_node read maple_node", FAULT_ON_ERROR); -+ -+ switch (type) { -+ case maple_dense: -+ for (i = 0; i < mt_slots[maple_dense]; i++) { -+ if (min + i > max) -+ fprintf(fp, "OUT OF RANGE: "); -+ do_mt_entry(mt_slot((void **)(node_buf + OFFSET(maple_node_slot)), i), -+ min + i, min + i, depth, i, path, global_index, ops); -+ } -+ break; -+ case maple_leaf_64: -+ case maple_range_64: -+ do_mt_range64(entry, min, max, depth, path, global_index, ops); -+ break; -+ case maple_arange_64: -+ do_mt_arange64(entry, min, max, depth, path, global_index, ops); -+ break; -+ default: -+ fprintf(fp, " UNKNOWN TYPE\n"); -+ } -+} -+ -+static int do_maple_tree_traverse(ulong ptr, int is_root, -+ struct maple_tree_ops *ops) -+{ -+ char path[BUFSIZE] = {0}; -+ char tree_buf[MAPLE_BUFSIZE]; -+ ulong entry; -+ struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL; -+ ulong global_index = 0; -+ -+ if (SIZE(maple_tree) > MAPLE_BUFSIZE) -+ error(FATAL, "MAPLE_BUFSIZE should be larger than maple_tree struct"); -+ -+ if (!is_root) { -+ strcpy(path, "direct"); -+ do_mt_node(ptr, 0, mt_max[mte_node_type(ptr)], -+ 0, path, &global_index, ops); -+ } else { -+ readmem(ptr, KVADDR, tree_buf, SIZE(maple_tree), -+ "mt_dump read maple_tree", FAULT_ON_ERROR); -+ entry = ULONG(tree_buf + OFFSET(maple_tree_ma_root)); -+ -+ if (!xa_is_node(entry)) -+ do_mt_entry(entry, 0, 0, 0, 0, path, &global_index, ops); -+ else if (entry) { -+ strcpy(path, "root"); -+ do_mt_node(entry, 0, mt_max[mte_node_type(entry)], 0, -+ path, &global_index, ops); -+ } -+ } -+ return 0; -+} -+ -+int do_mptree(struct tree_data *td) -+{ -+ struct maple_tree_ops ops = { -+ .entry = NULL, -+ .private = td, -+ .is_td = true, -+ }; -+ -+ int is_root = !(td->flags & TREE_NODE_POINTER); -+ -+ do_maple_tree_traverse(td->start, is_root, &ops); -+ -+ return 0; -+} -+ -+/***********************************************/ -+void maple_init(void) -+{ -+ int array_len; -+ -+ STRUCT_SIZE_INIT(maple_tree, "maple_tree"); -+ STRUCT_SIZE_INIT(maple_node, "maple_node"); -+ -+ MEMBER_OFFSET_INIT(maple_tree_ma_root, "maple_tree", "ma_root"); -+ MEMBER_OFFSET_INIT(maple_tree_ma_flags, "maple_tree", "ma_flags"); -+ -+ MEMBER_OFFSET_INIT(maple_node_parent, "maple_node", "parent"); -+ MEMBER_OFFSET_INIT(maple_node_ma64, "maple_node", "ma64"); -+ MEMBER_OFFSET_INIT(maple_node_mr64, "maple_node", "mr64"); -+ MEMBER_OFFSET_INIT(maple_node_slot, "maple_node", "slot"); -+ -+ MEMBER_OFFSET_INIT(maple_arange_64_pivot, "maple_arange_64", "pivot"); -+ MEMBER_OFFSET_INIT(maple_arange_64_slot, "maple_arange_64", "slot"); -+ MEMBER_OFFSET_INIT(maple_arange_64_gap, "maple_arange_64", "gap"); -+ MEMBER_OFFSET_INIT(maple_arange_64_meta, "maple_arange_64", "meta"); -+ -+ MEMBER_OFFSET_INIT(maple_range_64_pivot, "maple_range_64", "pivot"); -+ MEMBER_OFFSET_INIT(maple_range_64_slot, "maple_range_64", "slot"); -+ -+ MEMBER_OFFSET_INIT(maple_metadata_end, "maple_metadata", "end"); -+ MEMBER_OFFSET_INIT(maple_metadata_gap, "maple_metadata", "gap"); -+ -+ array_len = get_array_length("mt_slots", NULL, sizeof(char)); -+ mt_slots = calloc(array_len, sizeof(char)); -+ readmem(symbol_value("mt_slots"), KVADDR, mt_slots, -+ array_len * sizeof(char), "maple_init read mt_slots", -+ RETURN_ON_ERROR); -+ -+ array_len = get_array_length("mt_pivots", NULL, sizeof(char)); -+ mt_pivots = calloc(array_len, sizeof(char)); -+ readmem(symbol_value("mt_pivots"), KVADDR, mt_pivots, -+ array_len * sizeof(char), "maple_init read mt_pivots", -+ RETURN_ON_ERROR); -+ -+ mt_max[maple_dense] = mt_slots[maple_dense]; -+ mt_max[maple_leaf_64] = ULONG_MAX; -+ mt_max[maple_range_64] = ULONG_MAX; -+ mt_max[maple_arange_64] = ULONG_MAX; -+} -diff --git a/maple_tree.h b/maple_tree.h -new file mode 100644 -index 000000000000..f53d5aaffd2e ---- /dev/null -+++ b/maple_tree.h -@@ -0,0 +1,82 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+#ifndef _MAPLE_TREE_H -+#define _MAPLE_TREE_H -+/* -+ * Maple Tree - An RCU-safe adaptive tree for storing ranges -+ * Copyright (c) 2018-2022 Oracle -+ * Authors: Liam R. Howlett -+ * Matthew Wilcox -+ * -+ * eXtensible Arrays -+ * Copyright (c) 2017 Microsoft Corporation -+ * Author: Matthew Wilcox -+ * -+ * See Documentation/core-api/xarray.rst for how to use the XArray. -+ */ -+#include -+#include -+#include -+ -+/* -+ * The following are copied and modified from include/linux/maple_tree.h -+ */ -+ -+enum maple_type { -+ maple_dense, -+ maple_leaf_64, -+ maple_range_64, -+ maple_arange_64, -+}; -+ -+#define MAPLE_NODE_MASK 255UL -+ -+#define MT_FLAGS_HEIGHT_OFFSET 0x02 -+#define MT_FLAGS_HEIGHT_MASK 0x7C -+ -+#define MAPLE_NODE_TYPE_MASK 0x0F -+#define MAPLE_NODE_TYPE_SHIFT 0x03 -+ -+#define MAPLE_RESERVED_RANGE 4096 -+ -+/* -+ * The following are copied and modified from include/linux/xarray.h -+ */ -+ -+#define XA_ZERO_ENTRY xa_mk_internal(257) -+ -+static inline ulong xa_mk_internal(ulong v) -+{ -+ return (v << 2) | 2; -+} -+ -+static inline bool xa_is_internal(ulong entry) -+{ -+ return (entry & 3) == 2; -+} -+ -+static inline bool xa_is_node(ulong entry) -+{ -+ return xa_is_internal(entry) && entry > 4096; -+} -+ -+static inline bool xa_is_value(ulong entry) -+{ -+ return entry & 1; -+} -+ -+static inline bool xa_is_zero(ulong entry) -+{ -+ return entry == XA_ZERO_ENTRY; -+} -+ -+static inline unsigned long xa_to_internal(ulong entry) -+{ -+ return entry >> 2; -+} -+ -+static inline unsigned long xa_to_value(ulong entry) -+{ -+ return entry >> 1; -+} -+ -+#endif /* _MAPLE_TREE_H */ --- -2.37.1 - diff --git a/0024-Add-maple-tree-support-to-tree-command.patch b/0024-Add-maple-tree-support-to-tree-command.patch deleted file mode 100644 index c0c64ff..0000000 --- a/0024-Add-maple-tree-support-to-tree-command.patch +++ /dev/null @@ -1,335 +0,0 @@ -From 16a696762cbfe6a40312840fee2297f05fdefb21 Mon Sep 17 00:00:00 2001 -From: Tao Liu -Date: Tue, 10 Jan 2023 14:56:28 +0800 -Subject: [PATCH 24/28] Add maple tree support to "tree" command - -The maple tree is a new data structure for crash, so "tree" command -needs to support it for users to dump and view the content of maple -trees. This patch achieves this by using ported mt_dump() and its -related functions from kernel and adapting them with "tree" command. - -Also introduce a new -v arg specifically for dumping the complete -content of a maple tree: - - crash> tree -t maple 0xffff9034c006aec0 -v - - maple_tree(ffff9034c006aec0) flags 309, height 2 root 0xffff9034de70041e - - 0-18446744073709551615: node 0xffff9034de700400 depth 0 type 3 parent 0xffff9034c006aec1 contents:... - 0-140112331583487: node 0xffff9034c01e8800 depth 1 type 1 parent 0xffff9034de700406 contents:... - 0-94643156942847: (nil) - 94643156942848-94643158024191: 0xffff9035131754c0 - 94643158024192-94643160117247: (nil) - ... - -The existing options of "tree" command can work as well: - - crash> tree -t maple -r mm_struct.mm_mt 0xffff9034c006aec0 -p - ffff9035131754c0 - index: 1 position: root/0/1 - ffff9035131751c8 - index: 2 position: root/0/3 - ffff9035131757b8 - index: 3 position: root/0/4 - ... - - crash> tree -t maple 0xffff9034c006aec0 -p -x -s vm_area_struct.vm_start,vm_end - ffff9035131754c0 - index: 1 position: root/0/1 - vm_start = 0x5613d3c00000, - vm_end = 0x5613d3d08000, - ffff9035131751c8 - index: 2 position: root/0/3 - vm_start = 0x5613d3f07000, - vm_end = 0x5613d3f0b000, - ffff9035131757b8 - index: 3 position: root/0/4 - vm_start = 0x5613d3f0b000, - vm_end = 0x5613d3f14000, - .... - -Signed-off-by: Tao Liu -Signed-off-by: Lianbo Jiang ---- - defs.h | 1 + - maple_tree.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ - tools.c | 67 +++++++++++++++++++++++++++++++++++++++------------- - 3 files changed, 114 insertions(+), 17 deletions(-) - -diff --git a/defs.h b/defs.h -index 46bfd4a67e64..f98e18937949 100644 ---- a/defs.h -+++ b/defs.h -@@ -2713,6 +2713,7 @@ struct tree_data { - #define TREE_PARSE_MEMBER (VERBOSE << 7) - #define TREE_READ_MEMBER (VERBOSE << 8) - #define TREE_LINEAR_ORDER (VERBOSE << 9) -+#define TREE_STRUCT_VERBOSE (VERBOSE << 10) - - #define ALIAS_RUNTIME (1) - #define ALIAS_RCLOCAL (2) -diff --git a/maple_tree.c b/maple_tree.c -index 474faeda6252..471136f3eb1d 100644 ---- a/maple_tree.c -+++ b/maple_tree.c -@@ -173,6 +173,10 @@ static void do_mt_range64(ulong entry, ulong min, ulong max, - - mr64_buf = node_buf + OFFSET(maple_node_mr64); - -+ if (td && td->flags & TREE_STRUCT_VERBOSE) { -+ dump_mt_range64(mr64_buf); -+ } -+ - for (i = 0; i < mt_slots[maple_range_64]; i++) { - last = max; - -@@ -230,6 +234,10 @@ static void do_mt_arange64(ulong entry, ulong min, ulong max, - - ma64_buf = node_buf + OFFSET(maple_node_ma64); - -+ if (td && td->flags & TREE_STRUCT_VERBOSE) { -+ dump_mt_arange64(ma64_buf); -+ } -+ - for (i = 0; i < mt_slots[maple_arange_64]; i++) { - last = max; - -@@ -275,6 +283,51 @@ static void do_mt_entry(ulong entry, ulong min, ulong max, uint depth, - - if (!td) - return; -+ -+ if (!td->count && td->structname_args) { -+ /* -+ * Retrieve all members' info only once (count == 0) -+ * After last iteration all memory will be freed up -+ */ -+ e = (struct req_entry **)GETBUF(sizeof(*e) * td->structname_args); -+ for (i = 0; i < td->structname_args; i++) -+ e[i] = fill_member_offsets(td->structname[i]); -+ } -+ -+ td->count++; -+ -+ if (td->flags & TREE_STRUCT_VERBOSE) { -+ dump_mt_entry(entry, min, max, depth); -+ } else if (td->flags & VERBOSE && entry) -+ fprintf(fp, "%lx\n", entry); -+ if (td->flags & TREE_POSITION_DISPLAY && entry) -+ fprintf(fp, " index: %ld position: %s/%u\n", -+ ++(*global_index), path, index); -+ -+ if (td->structname) { -+ if (td->flags & TREE_STRUCT_RADIX_10) -+ print_radix = 10; -+ else if (td->flags & TREE_STRUCT_RADIX_16) -+ print_radix = 16; -+ else -+ print_radix = 0; -+ -+ for (i = 0; i < td->structname_args; i++) { -+ switch (count_chars(td->structname[i], '.')) { -+ case 0: -+ dump_struct(td->structname[i], entry, print_radix); -+ break; -+ default: -+ if (td->flags & TREE_PARSE_MEMBER) -+ dump_struct_members_for_tree(td, i, entry); -+ else if (td->flags & TREE_READ_MEMBER) -+ dump_struct_members_fast(e[i], print_radix, entry); -+ } -+ } -+ } -+ -+ if (e) -+ FREEBUF(e); - } - - static void do_mt_node(ulong entry, ulong min, ulong max, -@@ -293,6 +346,10 @@ static void do_mt_node(ulong entry, ulong min, ulong max, - readmem(maple_node, KVADDR, node_buf, SIZE(maple_node), - "mt_dump_node read maple_node", FAULT_ON_ERROR); - -+ if (td && td->flags & TREE_STRUCT_VERBOSE) { -+ dump_mt_node(maple_node, node_buf, type, min, max, depth); -+ } -+ - switch (type) { - case maple_dense: - for (i = 0; i < mt_slots[maple_dense]; i++) { -@@ -335,6 +392,12 @@ static int do_maple_tree_traverse(ulong ptr, int is_root, - "mt_dump read maple_tree", FAULT_ON_ERROR); - entry = ULONG(tree_buf + OFFSET(maple_tree_ma_root)); - -+ if (td && td->flags & TREE_STRUCT_VERBOSE) { -+ fprintf(fp, "maple_tree(%lx) flags %X, height %u root 0x%lx\n\n", -+ ptr, UINT(tree_buf + OFFSET(maple_tree_ma_flags)), -+ mt_height(tree_buf), entry); -+ } -+ - if (!xa_is_node(entry)) - do_mt_entry(entry, 0, 0, 0, 0, path, &global_index, ops); - else if (entry) { -diff --git a/tools.c b/tools.c -index 5f86771f5327..c2cfa7e280bc 100644 ---- a/tools.c -+++ b/tools.c -@@ -30,7 +30,7 @@ static void dealloc_hq_entry(struct hq_entry *); - static void show_options(void); - static void dump_struct_members(struct list_data *, int, ulong); - static void rbtree_iteration(ulong, struct tree_data *, char *); --static void dump_struct_members_for_tree(struct tree_data *, int, ulong); -+void dump_struct_members_for_tree(struct tree_data *, int, ulong); - - struct req_entry { - char *arg, *name, **member; -@@ -40,8 +40,8 @@ struct req_entry { - }; - - static void print_value(struct req_entry *, unsigned int, ulong, unsigned int); --static struct req_entry *fill_member_offsets(char *); --static void dump_struct_members_fast(struct req_entry *, int, ulong); -+struct req_entry *fill_member_offsets(char *); -+void dump_struct_members_fast(struct req_entry *, int, ulong); - - FILE * - set_error(char *target) -@@ -3666,7 +3666,7 @@ dump_struct_members_fast(struct req_entry *e, int radix, ulong p) - } - } - --static struct req_entry * -+struct req_entry * - fill_member_offsets(char *arg) - { - int j; -@@ -4307,6 +4307,7 @@ dump_struct_members(struct list_data *ld, int idx, ulong next) - #define RADIXTREE_REQUEST (0x1) - #define RBTREE_REQUEST (0x2) - #define XARRAY_REQUEST (0x4) -+#define MAPLE_REQUEST (0x8) - - void - cmd_tree() -@@ -4317,6 +4318,7 @@ cmd_tree() - struct datatype_member struct_member, *sm; - struct syment *sp; - ulong value; -+ char *type_name = NULL; - - type_flag = 0; - root_offset = 0; -@@ -4324,25 +4326,33 @@ cmd_tree() - td = &tree_data; - BZERO(td, sizeof(struct tree_data)); - -- while ((c = getopt(argcnt, args, "xdt:r:o:s:S:plN")) != EOF) { -+ while ((c = getopt(argcnt, args, "xdt:r:o:s:S:plNv")) != EOF) { - switch (c) - { - case 't': -- if (type_flag & (RADIXTREE_REQUEST|RBTREE_REQUEST|XARRAY_REQUEST)) { -+ if (type_flag & (RADIXTREE_REQUEST|RBTREE_REQUEST|XARRAY_REQUEST|MAPLE_REQUEST)) { - error(INFO, "multiple tree types may not be entered\n"); - cmd_usage(pc->curcmd, SYNOPSIS); - } - - if (STRNEQ(optarg, "ra")) -- if (MEMBER_EXISTS("radix_tree_root", "xa_head")) -+ if (MEMBER_EXISTS("radix_tree_root", "xa_head")) { - type_flag = XARRAY_REQUEST; -- else -+ type_name = "Xarrays"; -+ } else { - type_flag = RADIXTREE_REQUEST; -- else if (STRNEQ(optarg, "rb")) -+ type_name = "radix trees"; -+ } -+ else if (STRNEQ(optarg, "rb")) { - type_flag = RBTREE_REQUEST; -- else if (STRNEQ(optarg, "x")) -+ type_name = "rbtrees"; -+ } else if (STRNEQ(optarg, "x")) { - type_flag = XARRAY_REQUEST; -- else { -+ type_name = "Xarrays"; -+ } else if (STRNEQ(optarg, "m")) { -+ type_flag = MAPLE_REQUEST; -+ type_name = "maple trees"; -+ } else { - error(INFO, "invalid tree type: %s\n", optarg); - cmd_usage(pc->curcmd, SYNOPSIS); - } -@@ -4417,6 +4427,9 @@ cmd_tree() - "-d and -x are mutually exclusive\n"); - td->flags |= TREE_STRUCT_RADIX_10; - break; -+ case 'v': -+ td->flags |= TREE_STRUCT_VERBOSE; -+ break; - default: - argerrs++; - break; -@@ -4426,13 +4439,17 @@ cmd_tree() - if (argerrs) - cmd_usage(pc->curcmd, SYNOPSIS); - -- if ((type_flag & (XARRAY_REQUEST|RADIXTREE_REQUEST)) && (td->flags & TREE_LINEAR_ORDER)) -- error(FATAL, "-l option is not applicable to %s\n", -- type_flag & RADIXTREE_REQUEST ? "radix trees" : "Xarrays"); -+ if ((type_flag & (XARRAY_REQUEST|RADIXTREE_REQUEST|MAPLE_REQUEST)) && -+ (td->flags & TREE_LINEAR_ORDER)) -+ error(FATAL, "-l option is not applicable to %s\n", type_name); - -- if ((type_flag & (XARRAY_REQUEST|RADIXTREE_REQUEST)) && (td->flags & TREE_NODE_OFFSET_ENTERED)) -- error(FATAL, "-o option is not applicable to %s\n", -- type_flag & RADIXTREE_REQUEST ? "radix trees" : "Xarrays"); -+ if ((type_flag & (XARRAY_REQUEST|RADIXTREE_REQUEST|MAPLE_REQUEST)) && -+ (td->flags & TREE_NODE_OFFSET_ENTERED)) -+ error(FATAL, "-o option is not applicable to %s\n", type_name); -+ -+ if ((type_flag & (RBTREE_REQUEST|XARRAY_REQUEST|RADIXTREE_REQUEST)) && -+ (td->flags & TREE_STRUCT_VERBOSE)) -+ error(FATAL, "-v option is not applicable to %s\n", type_name); - - if ((td->flags & TREE_ROOT_OFFSET_ENTERED) && - (td->flags & TREE_NODE_POINTER)) -@@ -4506,12 +4523,26 @@ next_arg: - if (td->flags & TREE_STRUCT_RADIX_16) - fprintf(fp, "%sTREE_STRUCT_RADIX_16", - others++ ? "|" : ""); -+ if (td->flags & TREE_PARSE_MEMBER) -+ fprintf(fp, "%sTREE_PARSE_MEMBER", -+ others++ ? "|" : ""); -+ if (td->flags & TREE_READ_MEMBER) -+ fprintf(fp, "%sTREE_READ_MEMBER", -+ others++ ? "|" : ""); -+ if (td->flags & TREE_LINEAR_ORDER) -+ fprintf(fp, "%sTREE_LINEAR_ORDER", -+ others++ ? "|" : ""); -+ if (td->flags & TREE_STRUCT_VERBOSE) -+ fprintf(fp, "%sTREE_STRUCT_VERBOSE", -+ others++ ? "|" : ""); - fprintf(fp, ")\n"); - fprintf(fp, " type: "); - if (type_flag & RADIXTREE_REQUEST) - fprintf(fp, "radix\n"); - else if (type_flag & XARRAY_REQUEST) - fprintf(fp, "xarray\n"); -+ else if (type_flag & MAPLE_REQUEST) -+ fprintf(fp, "maple\n"); - else - fprintf(fp, "red-black%s", - type_flag & RBTREE_REQUEST ? -@@ -4532,6 +4563,8 @@ next_arg: - do_rdtree(td); - else if (type_flag & XARRAY_REQUEST) - do_xatree(td); -+ else if (type_flag & MAPLE_REQUEST) -+ do_mptree(td); - else - do_rbtree(td); - hq_close(); --- -2.37.1 - diff --git a/0025-Add-do_maple_tree-for-maple-tree-operations.patch b/0025-Add-do_maple_tree-for-maple-tree-operations.patch deleted file mode 100644 index 370f1ef..0000000 --- a/0025-Add-do_maple_tree-for-maple-tree-operations.patch +++ /dev/null @@ -1,205 +0,0 @@ -From 222176a0a6c14b6a1cdcebb8dda020ccb17b90f8 Mon Sep 17 00:00:00 2001 -From: Tao Liu -Date: Tue, 10 Jan 2023 14:56:29 +0800 -Subject: [PATCH 25/28] Add do_maple_tree() for maple tree operations - -do_maple_tree() is similar to do_radix_tree() and do_xarray(), which -takes the same do_maple_tree_traverse entry as tree command. - -Signed-off-by: Tao Liu -Signed-off-by: Lianbo Jiang ---- - defs.h | 6 +++ - maple_tree.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 151 insertions(+) - -diff --git a/defs.h b/defs.h -index f98e18937949..33a823b7b67c 100644 ---- a/defs.h -+++ b/defs.h -@@ -5762,6 +5762,12 @@ int cleanup_memory_driver(void); - - void maple_init(void); - int do_mptree(struct tree_data *); -+ulong do_maple_tree(ulong, int, struct list_pair *); -+#define MAPLE_TREE_COUNT (1) -+#define MAPLE_TREE_SEARCH (2) -+#define MAPLE_TREE_DUMP (3) -+#define MAPLE_TREE_GATHER (4) -+#define MAPLE_TREE_DUMP_CB (5) - - /* - * help.c -diff --git a/maple_tree.c b/maple_tree.c -index 471136f3eb1d..807c17f7dfa0 100644 ---- a/maple_tree.c -+++ b/maple_tree.c -@@ -40,6 +40,12 @@ static inline bool ma_is_leaf(const enum maple_type type) - - /*************** For cmd_tree ********************/ - -+struct do_maple_tree_info { -+ ulong maxcount; -+ ulong count; -+ void *data; -+}; -+ - struct maple_tree_ops { - void (*entry)(ulong node, ulong slot, const char *path, - ulong index, void *private); -@@ -281,6 +287,9 @@ static void do_mt_entry(ulong entry, ulong min, ulong max, uint depth, - static struct req_entry **e = NULL; - struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL; - -+ if (ops->entry) -+ ops->entry(entry, entry, path, max, ops->private); -+ - if (!td) - return; - -@@ -424,6 +433,142 @@ int do_mptree(struct tree_data *td) - return 0; - } - -+/************* For do_maple_tree *****************/ -+static void do_maple_tree_count(ulong node, ulong slot, const char *path, -+ ulong index, void *private) -+{ -+ struct do_maple_tree_info *info = private; -+ info->count++; -+} -+ -+static void do_maple_tree_search(ulong node, ulong slot, const char *path, -+ ulong index, void *private) -+{ -+ struct do_maple_tree_info *info = private; -+ struct list_pair *lp = info->data; -+ -+ if (lp->index == index) { -+ lp->value = (void *)slot; -+ info->count = 1; -+ } -+} -+ -+static void do_maple_tree_dump(ulong node, ulong slot, const char *path, -+ ulong index, void *private) -+{ -+ struct do_maple_tree_info *info = private; -+ fprintf(fp, "[%lu] %lx\n", index, slot); -+ info->count++; -+} -+ -+static void do_maple_tree_gather(ulong node, ulong slot, const char *path, -+ ulong index, void *private) -+{ -+ struct do_maple_tree_info *info = private; -+ struct list_pair *lp = info->data; -+ -+ if (info->maxcount) { -+ lp[info->count].index = index; -+ lp[info->count].value = (void *)slot; -+ -+ info->count++; -+ info->maxcount--; -+ } -+} -+ -+static void do_maple_tree_dump_cb(ulong node, ulong slot, const char *path, -+ ulong index, void *private) -+{ -+ struct do_maple_tree_info *info = private; -+ struct list_pair *lp = info->data; -+ int (*cb)(ulong) = lp->value; -+ -+ /* Caller defined operation */ -+ if (!cb(slot)) { -+ error(FATAL, "do_maple_tree: callback " -+ "operation failed: entry: %ld item: %lx\n", -+ info->count, slot); -+ } -+ info->count++; -+} -+ -+/* -+ * do_maple_tree argument usage: -+ * -+ * root: Address of a maple_tree_root structure -+ * -+ * flag: MAPLE_TREE_COUNT - Return the number of entries in the tree. -+ * MAPLE_TREE_SEARCH - Search for an entry at lp->index; if found, -+ * store the entry in lp->value and return a count of 1; otherwise -+ * return a count of 0. -+ * MAPLE_TREE_DUMP - Dump all existing index/value pairs. -+ * MAPLE_TREE_GATHER - Store all existing index/value pairs in the -+ * passed-in array of list_pair structs starting at lp, -+ * returning the count of entries stored; the caller can/should -+ * limit the number of returned entries by putting the array size -+ * (max count) in the lp->index field of the first structure -+ * in the passed-in array. -+ * MAPLE_TREE_DUMP_CB - Similar with MAPLE_TREE_DUMP, but for each -+ * maple tree entry, a user defined callback at lp->value will -+ * be invoked. -+ * -+ * lp: Unused by MAPLE_TREE_COUNT and MAPLE_TREE_DUMP. -+ * A pointer to a list_pair structure for MAPLE_TREE_SEARCH. -+ * A pointer to an array of list_pair structures for -+ * MAPLE_TREE_GATHER; the dimension (max count) of the array may -+ * be stored in the index field of the first structure to avoid -+ * any chance of an overrun. -+ * For MAPLE_TREE_DUMP_CB, the lp->value must be initialized as a -+ * callback function. The callback prototype must be: int (*)(ulong); -+ */ -+ulong -+do_maple_tree(ulong root, int flag, struct list_pair *lp) -+{ -+ struct do_maple_tree_info info = { -+ .count = 0, -+ .data = lp, -+ }; -+ struct maple_tree_ops ops = { -+ .private = &info, -+ .is_td = false, -+ }; -+ -+ switch (flag) -+ { -+ case MAPLE_TREE_COUNT: -+ ops.entry = do_maple_tree_count; -+ break; -+ -+ case MAPLE_TREE_SEARCH: -+ ops.entry = do_maple_tree_search; -+ break; -+ -+ case MAPLE_TREE_DUMP: -+ ops.entry = do_maple_tree_dump; -+ break; -+ -+ case MAPLE_TREE_GATHER: -+ if (!(info.maxcount = lp->index)) -+ info.maxcount = (ulong)(-1); /* caller beware */ -+ -+ ops.entry = do_maple_tree_gather; -+ break; -+ -+ case MAPLE_TREE_DUMP_CB: -+ if (lp->value == NULL) { -+ error(FATAL, "do_maple_tree: need set callback function"); -+ } -+ ops.entry = do_maple_tree_dump_cb; -+ break; -+ -+ default: -+ error(FATAL, "do_maple_tree: invalid flag: %lx\n", flag); -+ } -+ -+ do_maple_tree_traverse(root, true, &ops); -+ return info.count; -+} -+ - /***********************************************/ - void maple_init(void) - { --- -2.37.1 - diff --git a/0026-Introduce-maple-tree-vma-iteration-to-vm_area_dump.patch b/0026-Introduce-maple-tree-vma-iteration-to-vm_area_dump.patch deleted file mode 100644 index 7a41a99..0000000 --- a/0026-Introduce-maple-tree-vma-iteration-to-vm_area_dump.patch +++ /dev/null @@ -1,455 +0,0 @@ -From 9efc1f68a44f6fe521e64efe4a3dc36e9ba0bbc1 Mon Sep 17 00:00:00 2001 -From: Tao Liu -Date: Tue, 10 Jan 2023 14:56:30 +0800 -Subject: [PATCH 26/28] Introduce maple tree vma iteration to vm_area_dump() - -Since memory.c:vm_area_dump() will iterate all vma, this patch mainly -introduces maple tree vma iteration to it. - -We extract the code which handles each vma into a function. If -mm_struct_mmap exist, aka the linked list of vma iteration available, -we goto the original way; if not and mm_struct_mm_mt exist, aka -maple tree is available, then we goto the maple tree vma iteration. - -Signed-off-by: Tao Liu -Signed-off-by: Lianbo Jiang ---- - Makefile | 2 +- - memory.c | 321 +++++++++++++++++++++++++++++++++---------------------- - 2 files changed, 193 insertions(+), 130 deletions(-) - -diff --git a/Makefile b/Makefile -index 102597f735b2..a94a243c243e 100644 ---- a/Makefile -+++ b/Makefile -@@ -355,7 +355,7 @@ filesys.o: ${GENERIC_HFILES} filesys.c - help.o: ${GENERIC_HFILES} help.c - ${CC} -c ${CRASH_CFLAGS} help.c ${WARNING_OPTIONS} ${WARNING_ERROR} - --memory.o: ${GENERIC_HFILES} memory.c -+memory.o: ${GENERIC_HFILES} ${MAPLE_TREE_HFILES} memory.c - ${CC} -c ${CRASH_CFLAGS} memory.c ${WARNING_OPTIONS} ${WARNING_ERROR} - - test.o: ${GENERIC_HFILES} test.c -diff --git a/memory.c b/memory.c -index 156de2f7b5a3..5141fbea4b40 100644 ---- a/memory.c -+++ b/memory.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include "maple_tree.h" - - struct meminfo { /* general purpose memory information structure */ - ulong cache; /* used by the various memory searching/dumping */ -@@ -137,6 +138,27 @@ struct searchinfo { - char buf[BUFSIZE]; - }; - -+struct handle_each_vm_area_args { -+ ulong task; -+ ulong flag; -+ ulong vaddr; -+ struct reference *ref; -+ char *vma_header; -+ char *buf1; -+ char *buf2; -+ char *buf3; -+ char *buf4; -+ char *buf5; -+ ulong vma; -+ char **vma_buf; -+ struct task_mem_usage *tm; -+ int *found; -+ int *single_vma_found; -+ unsigned int radix; -+ struct task_context *tc; -+ ulong *single_vma; -+}; -+ - static char *memtype_string(int, int); - static char *error_handle_string(ulong); - static void collect_page_member_data(char *, struct meminfo *); -@@ -299,6 +321,7 @@ static void dump_page_flags(ulonglong); - static ulong kmem_cache_nodelists(ulong); - static void dump_hstates(void); - static ulong freelist_ptr(struct meminfo *, ulong, ulong); -+static ulong handle_each_vm_area(struct handle_each_vm_area_args *); - - /* - * Memory display modes specific to this file. -@@ -363,6 +386,10 @@ vm_init(void) - - MEMBER_OFFSET_INIT(task_struct_mm, "task_struct", "mm"); - MEMBER_OFFSET_INIT(mm_struct_mmap, "mm_struct", "mmap"); -+ MEMBER_OFFSET_INIT(mm_struct_mm_mt, "mm_struct", "mm_mt"); -+ if (VALID_MEMBER(mm_struct_mm_mt)) { -+ maple_init(); -+ } - MEMBER_OFFSET_INIT(mm_struct_pgd, "mm_struct", "pgd"); - MEMBER_OFFSET_INIT(mm_struct_rss, "mm_struct", "rss"); - if (!VALID_MEMBER(mm_struct_rss)) -@@ -3874,7 +3901,7 @@ bailout: - * for references -- and only then does a display - */ - --#define PRINT_VM_DATA() \ -+#define PRINT_VM_DATA(buf4, buf5, tm) \ - { \ - fprintf(fp, "%s %s ", \ - mkstring(buf4, VADDR_PRLEN, CENTER|LJUST, "MM"), \ -@@ -3896,9 +3923,9 @@ bailout: - mkstring(buf5, 8, CENTER|LJUST, NULL)); \ - } - --#define PRINT_VMA_DATA() \ -+#define PRINT_VMA_DATA(buf1, buf2, buf3, buf4, vma) \ - fprintf(fp, "%s%s%s%s%s %6llx%s%s\n", \ -- mkstring(buf4, VADDR_PRLEN, CENTER|LJUST|LONG_HEX, MKSTR(vma)), \ -+ mkstring(buf4, VADDR_PRLEN, CENTER|LJUST|LONG_HEX, MKSTR(vma)),\ - space(MINSPACE), \ - mkstring(buf2, UVADDR_PRLEN, RJUST|LONG_HEX, MKSTR(vm_start)), \ - space(MINSPACE), \ -@@ -3925,18 +3952,137 @@ bailout: - (DO_REF_SEARCH(X) && (string_exists(S)) && FILENAME_COMPONENT((S),(X)->str)) - #define VM_REF_FOUND(X) ((X) && ((X)->cmdflags & VM_REF_HEADER)) - --ulong --vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) -+static ulong handle_each_vm_area(struct handle_each_vm_area_args *args) - { -- struct task_context *tc; -- ulong vma; -+ char *dentry_buf, *file_buf; - ulong vm_start; - ulong vm_end; -- ulong vm_next, vm_mm; -- char *dentry_buf, *vma_buf, *file_buf; -+ ulong vm_mm; - ulonglong vm_flags; - ulong vm_file, inode; - ulong dentry, vfsmnt; -+ -+ if ((args->flag & PHYSADDR) && !DO_REF_SEARCH(args->ref)) -+ fprintf(fp, "%s", args->vma_header); -+ -+ inode = 0; -+ BZERO(args->buf1, BUFSIZE); -+ *(args->vma_buf) = fill_vma_cache(args->vma); -+ -+ vm_mm = ULONG(*(args->vma_buf) + OFFSET(vm_area_struct_vm_mm)); -+ vm_end = ULONG(*(args->vma_buf) + OFFSET(vm_area_struct_vm_end)); -+ vm_start = ULONG(*(args->vma_buf) + OFFSET(vm_area_struct_vm_start)); -+ vm_flags = get_vm_flags(*(args->vma_buf)); -+ vm_file = ULONG(*(args->vma_buf) + OFFSET(vm_area_struct_vm_file)); -+ -+ if (args->flag & PRINT_SINGLE_VMA) { -+ if (args->vma != *(args->single_vma)) -+ return 0; -+ fprintf(fp, "%s", args->vma_header); -+ *(args->single_vma_found) = TRUE; -+ } -+ -+ if (args->flag & PRINT_VMA_STRUCTS) { -+ dump_struct("vm_area_struct", args->vma, args->radix); -+ return 0; -+ } -+ -+ if (vm_file && !(args->flag & VERIFY_ADDR)) { -+ file_buf = fill_file_cache(vm_file); -+ dentry = ULONG(file_buf + OFFSET(file_f_dentry)); -+ dentry_buf = NULL; -+ if (dentry) { -+ dentry_buf = fill_dentry_cache(dentry); -+ if (VALID_MEMBER(file_f_vfsmnt)) { -+ vfsmnt = ULONG(file_buf + OFFSET(file_f_vfsmnt)); -+ get_pathname(dentry, args->buf1, BUFSIZE, 1, vfsmnt); -+ } else -+ get_pathname(dentry, args->buf1, BUFSIZE, 1, 0); -+ } -+ if ((args->flag & PRINT_INODES) && dentry) -+ inode = ULONG(dentry_buf + OFFSET(dentry_d_inode)); -+ } -+ -+ if (!(args->flag & UVADDR) || ((args->flag & UVADDR) && -+ ((args->vaddr >= vm_start) && (args->vaddr < vm_end)))) { -+ *(args->found) = TRUE; -+ -+ if (args->flag & VERIFY_ADDR) -+ return args->vma; -+ -+ if (DO_REF_SEARCH(args->ref)) { -+ if (VM_REF_CHECK_HEXVAL(args->ref, args->vma) || -+ VM_REF_CHECK_HEXVAL(args->ref, (ulong)vm_flags) || -+ VM_REF_CHECK_STRING(args->ref, args->buf1)) { -+ if (!(args->ref->cmdflags & VM_REF_HEADER)) { -+ print_task_header(fp, args->tc, 0); -+ PRINT_VM_DATA(args->buf4, args->buf5, args->tm); -+ args->ref->cmdflags |= VM_REF_HEADER; -+ } -+ if (!(args->ref->cmdflags & VM_REF_VMA) || -+ (args->ref->cmdflags & VM_REF_PAGE)) { -+ fprintf(fp, "%s", args->vma_header); -+ args->ref->cmdflags |= VM_REF_VMA; -+ args->ref->cmdflags &= ~VM_REF_PAGE; -+ args->ref->ref1 = args->vma; -+ } -+ PRINT_VMA_DATA(args->buf1, args->buf2, -+ args->buf3, args->buf4, args->vma); -+ } -+ -+ if (vm_area_page_dump(args->vma, args->task, -+ vm_start, vm_end, vm_mm, args->ref)) { -+ if (!(args->ref->cmdflags & VM_REF_HEADER)) { -+ print_task_header(fp, args->tc, 0); -+ PRINT_VM_DATA(args->buf4, args->buf5, args->tm); -+ args->ref->cmdflags |= VM_REF_HEADER; -+ } -+ if (!(args->ref->cmdflags & VM_REF_VMA) || -+ (args->ref->ref1 != args->vma)) { -+ fprintf(fp, "%s", args->vma_header); -+ PRINT_VMA_DATA(args->buf1, args->buf2, -+ args->buf3, args->buf4, args->vma); -+ args->ref->cmdflags |= VM_REF_VMA; -+ args->ref->ref1 = args->vma; -+ } -+ -+ args->ref->cmdflags |= VM_REF_DISPLAY; -+ vm_area_page_dump(args->vma, args->task, -+ vm_start, vm_end, vm_mm, args->ref); -+ args->ref->cmdflags &= ~VM_REF_DISPLAY; -+ } -+ -+ return 0; -+ } -+ -+ if (inode) { -+ fprintf(fp, "%lx%s%s%s%s%s%6llx%s%lx %s\n", -+ args->vma, space(MINSPACE), -+ mkstring(args->buf2, UVADDR_PRLEN, RJUST|LONG_HEX, -+ MKSTR(vm_start)), space(MINSPACE), -+ mkstring(args->buf3, UVADDR_PRLEN, RJUST|LONG_HEX, -+ MKSTR(vm_end)), space(MINSPACE), -+ vm_flags, space(MINSPACE), inode, args->buf1); -+ } else { -+ PRINT_VMA_DATA(args->buf1, args->buf2, -+ args->buf3, args->buf4, args->vma); -+ -+ if (args->flag & (PHYSADDR|PRINT_SINGLE_VMA)) -+ vm_area_page_dump(args->vma, args->task, -+ vm_start, vm_end, vm_mm, args->ref); -+ } -+ -+ if (args->flag & UVADDR) -+ return args->vma; -+ } -+ return 0; -+} -+ -+ulong -+vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) -+{ -+ struct task_context *tc; -+ ulong vma; - ulong single_vma; - unsigned int radix; - int single_vma_found; -@@ -3948,6 +4094,10 @@ vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) - char buf4[BUFSIZE]; - char buf5[BUFSIZE]; - char vma_header[BUFSIZE]; -+ char *vma_buf; -+ int i; -+ ulong mm_mt, entry_num; -+ struct list_pair *entry_list; - - tc = task_to_context(task); - tm = &task_mem_usage; -@@ -3981,14 +4131,14 @@ vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) - if (VM_REF_CHECK_HEXVAL(ref, tm->mm_struct_addr) || - VM_REF_CHECK_HEXVAL(ref, tm->pgd_addr)) { - print_task_header(fp, tc, 0); -- PRINT_VM_DATA(); -+ PRINT_VM_DATA(buf4, buf5, tm); - fprintf(fp, "\n"); - return (ulong)NULL; - } - - if (!(flag & (UVADDR|PRINT_MM_STRUCT|PRINT_VMA_STRUCTS|PRINT_SINGLE_VMA)) && - !DO_REF_SEARCH(ref)) -- PRINT_VM_DATA(); -+ PRINT_VM_DATA(buf4, buf5, tm); - - if (!tm->mm_struct_addr) { - if (pc->curcmd_flags & MM_STRUCT_FORCE) { -@@ -4012,9 +4162,6 @@ vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) - return (ulong)NULL; - } - -- readmem(tm->mm_struct_addr + OFFSET(mm_struct_mmap), KVADDR, -- &vma, sizeof(void *), "mm_struct mmap", FAULT_ON_ERROR); -- - sprintf(vma_header, "%s%s%s%s%s FLAGS%sFILE\n", - mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "VMA"), - space(MINSPACE), -@@ -4027,125 +4174,41 @@ vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) - !DO_REF_SEARCH(ref)) - fprintf(fp, "%s", vma_header); - -- for (found = FALSE; vma; vma = vm_next) { -- -- if ((flag & PHYSADDR) && !DO_REF_SEARCH(ref)) -- fprintf(fp, "%s", vma_header); -- -- inode = 0; -- BZERO(buf1, BUFSIZE); -- vma_buf = fill_vma_cache(vma); -- -- vm_mm = ULONG(vma_buf + OFFSET(vm_area_struct_vm_mm)); -- vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end)); -- vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next)); -- vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start)); -- vm_flags = get_vm_flags(vma_buf); -- vm_file = ULONG(vma_buf + OFFSET(vm_area_struct_vm_file)); -- -- if (flag & PRINT_SINGLE_VMA) { -- if (vma != single_vma) -- continue; -- fprintf(fp, "%s", vma_header); -- single_vma_found = TRUE; -- } -- -- if (flag & PRINT_VMA_STRUCTS) { -- dump_struct("vm_area_struct", vma, radix); -- continue; -- } -+ found = FALSE; - -- if (vm_file && !(flag & VERIFY_ADDR)) { -- file_buf = fill_file_cache(vm_file); -- dentry = ULONG(file_buf + OFFSET(file_f_dentry)); -- dentry_buf = NULL; -- if (dentry) { -- dentry_buf = fill_dentry_cache(dentry); -- if (VALID_MEMBER(file_f_vfsmnt)) { -- vfsmnt = ULONG(file_buf + -- OFFSET(file_f_vfsmnt)); -- get_pathname(dentry, buf1, BUFSIZE, -- 1, vfsmnt); -- } else { -- get_pathname(dentry, buf1, BUFSIZE, -- 1, 0); -- } -- } -- if ((flag & PRINT_INODES) && dentry) { -- inode = ULONG(dentry_buf + -- OFFSET(dentry_d_inode)); -+ struct handle_each_vm_area_args args = { -+ .task = task, .flag = flag, .vaddr = vaddr, -+ .ref = ref, .tc = tc, .radix = radix, -+ .tm = tm, .buf1 = buf1, .buf2 = buf2, -+ .buf3 = buf3, .buf4 = buf4, .buf5 = buf5, -+ .vma_header = vma_header, .single_vma = &single_vma, -+ .single_vma_found = &single_vma_found, .found = &found, -+ .vma_buf = &vma_buf, -+ }; -+ -+ if (INVALID_MEMBER(mm_struct_mmap) && VALID_MEMBER(mm_struct_mm_mt)) { -+ mm_mt = tm->mm_struct_addr + OFFSET(mm_struct_mm_mt); -+ entry_num = do_maple_tree(mm_mt, MAPLE_TREE_COUNT, NULL); -+ entry_list = (struct list_pair *)GETBUF(entry_num * sizeof(struct list_pair)); -+ do_maple_tree(mm_mt, MAPLE_TREE_GATHER, entry_list); -+ -+ for (i = 0; i < entry_num; i++) { -+ if (!!(args.vma = (ulong)entry_list[i].value) && -+ handle_each_vm_area(&args)) { -+ FREEBUF(entry_list); -+ return args.vma; - } - } -- -- if (!(flag & UVADDR) || ((flag & UVADDR) && -- ((vaddr >= vm_start) && (vaddr < vm_end)))) { -- found = TRUE; -- -- if (flag & VERIFY_ADDR) -- return vma; -- -- if (DO_REF_SEARCH(ref)) { -- if (VM_REF_CHECK_HEXVAL(ref, vma) || -- VM_REF_CHECK_HEXVAL(ref, (ulong)vm_flags) || -- VM_REF_CHECK_STRING(ref, buf1)) { -- if (!(ref->cmdflags & VM_REF_HEADER)) { -- print_task_header(fp, tc, 0); -- PRINT_VM_DATA(); -- ref->cmdflags |= VM_REF_HEADER; -- } -- if (!(ref->cmdflags & VM_REF_VMA) || -- (ref->cmdflags & VM_REF_PAGE)) { -- fprintf(fp, "%s", vma_header); -- ref->cmdflags |= VM_REF_VMA; -- ref->cmdflags &= ~VM_REF_PAGE; -- ref->ref1 = vma; -- } -- PRINT_VMA_DATA(); -- } -- -- if (vm_area_page_dump(vma, task, -- vm_start, vm_end, vm_mm, ref)) { -- if (!(ref->cmdflags & VM_REF_HEADER)) { -- print_task_header(fp, tc, 0); -- PRINT_VM_DATA(); -- ref->cmdflags |= VM_REF_HEADER; -- } -- if (!(ref->cmdflags & VM_REF_VMA) || -- (ref->ref1 != vma)) { -- fprintf(fp, "%s", vma_header); -- PRINT_VMA_DATA(); -- ref->cmdflags |= VM_REF_VMA; -- ref->ref1 = vma; -- } -- -- ref->cmdflags |= VM_REF_DISPLAY; -- vm_area_page_dump(vma, task, -- vm_start, vm_end, vm_mm, ref); -- ref->cmdflags &= ~VM_REF_DISPLAY; -- } -- -- continue; -- } -- -- if (inode) { -- fprintf(fp, "%lx%s%s%s%s%s%6llx%s%lx %s\n", -- vma, space(MINSPACE), -- mkstring(buf2, UVADDR_PRLEN, RJUST|LONG_HEX, -- MKSTR(vm_start)), space(MINSPACE), -- mkstring(buf3, UVADDR_PRLEN, RJUST|LONG_HEX, -- MKSTR(vm_end)), space(MINSPACE), -- vm_flags, space(MINSPACE), inode, buf1); -- } else { -- PRINT_VMA_DATA(); -- -- if (flag & (PHYSADDR|PRINT_SINGLE_VMA)) -- vm_area_page_dump(vma, task, -- vm_start, vm_end, vm_mm, ref); -- } -- -- if (flag & UVADDR) -+ FREEBUF(entry_list); -+ } else { -+ readmem(tm->mm_struct_addr + OFFSET(mm_struct_mmap), KVADDR, -+ &vma, sizeof(void *), "mm_struct mmap", FAULT_ON_ERROR); -+ while (vma) { -+ args.vma = vma; -+ if (handle_each_vm_area(&args)) - return vma; -- } -+ vma = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next)); -+ } - } - - if (flag & VERIFY_ADDR) --- -2.37.1 - diff --git a/0027-Update-the-help-text-of-tree-command-for-maple-tree.patch b/0027-Update-the-help-text-of-tree-command-for-maple-tree.patch deleted file mode 100644 index 8bc6e10..0000000 --- a/0027-Update-the-help-text-of-tree-command-for-maple-tree.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 49f6c2095d82700b7845ad9a09cb6942cc114b52 Mon Sep 17 00:00:00 2001 -From: Tao Liu -Date: Tue, 10 Jan 2023 14:56:31 +0800 -Subject: [PATCH 27/28] Update the help text of "tree" command for maple tree - -Signed-off-by: Tao Liu -Signed-off-by: Lianbo Jiang ---- - help.c | 86 +++++++++++++++++++++++++++++++++++++++++++--------------- - 1 file changed, 64 insertions(+), 22 deletions(-) - -diff --git a/help.c b/help.c -index 367500fc280d..56a9d8274525 100644 ---- a/help.c -+++ b/help.c -@@ -6307,19 +6307,20 @@ NULL - - char *help_tree[] = { - "tree", --"display radix tree, XArray or red-black tree", --"[-t [radix|xarray|rbtree]] [-r offset] [-[s|S] struct[.member[,member]]]\n -[x|d] [-o offset] [-l] [-p] [-N] start", --" This command dumps the contents of a radix tree, an XAarray, or a red-black", --" tree. The arguments are as follows:\n", -+"display radix tree, XArray, red-black tree or maple tree", -+"[-t [radix|xarray|rbtree|maple]] [-r offset] [-[s|S] struct[.member[,member]]]\n" -+" -[x|d] [-o offset] [-l] [-p] [-v] [-N] start", -+" This command dumps the contents of a radix tree, an XAarray, a red-black", -+" tree, or a maple tree. The arguments are as follows:\n", - " -t type The type of tree to dump; the type string can be one of ", --" \"radix\", \"rbtree\", or \"xarray\", or alternatively, \"ra\",", --" \"rb\" or \"x\" are acceptable. If not specified, rbtree is the", --" default type.", -+" \"radix\", \"rbtree\", \"xarray\", or \"maple\", or alternatively,", -+" \"ra\", \"rb\", \"x\" or \"m\" are acceptable. If not specified,", -+" rbtree is the default type.", - " -r offset If the \"start\" argument is the address of a data structure that", --" contains an radix_tree_root, xarray or rb_root structure, then this", --" is the offset to that structure member. If the offset is non-zero,", --" then this option is required. The offset may be entered in either", --" of two manners:", -+" contains an radix_tree_root, maple_tree, xarray or rb_root", -+" structure, then this is the offset to that structure member. If", -+" the offset is non-zero, then this option is required. The offset", -+" may be entered in either of two manners:", - " 1. In \"structure.member\" format.", - " 2. A number of bytes.", - " -o offset For red-black trees only, the offset of the rb_node within its ", -@@ -6348,25 +6349,26 @@ char *help_tree[] = { - " -p Display the node's position information, showing the relationship", - " between it and the root. For red-black trees, a position that", - " indicates \"root/l/r\" means that the node is the right child", --" of the left child of the root node. For radix trees and xarrays,", --" the index, the height, and the slot index values are shown with", --" respect to the root.", -+" of the left child of the root node. For radix trees, xarrays and", -+" maple trees, the index, the height, and the slot index values are", -+" shown with respect to the root.", - " -x Override default output format with hexadecimal format.", - " -d Override default output format with decimal format.", -+" -v For maple trees only, dump the contents of each maple tree node.", - " ", - " The meaning of the \"start\" argument, which can be expressed either in", - " hexadecimal format or symbolically, depends upon whether the -N option", - " is prepended:", - " ", --" start The address of a radix_tree_root, xarray or rb_root structure, or", --" the address of a structure containing the radix_tree_root, xarray", --" or rb_root structure; if the latter, then the \"-r offset\" option", --" must be used if the member offset of the root structure is ", --" non-zero.", -+" start The address of a radix_tree_root, maple_tree, xarray or rb_root", -+" structure, or the address of a structure containing the", -+" radix_tree_root, maple_tree, xarray or rb_root structure; if the", -+" latter, then the \"-r offset\" option must be used if the member", -+" offset of the root structure is non-zero.", - " ", --" -N start The address of a radix_tree_node, xa_node or rb_node structure,", --" bypassing the radix_tree_root, xarray, or rb_root that points", --" to it.", -+" -N start The address of a radix_tree_node, maple_node, xa_node or rb_node", -+" structure, bypassing the radix_tree_root, maple_tree, xarray, or", -+" rb_root that points to it.", - "", - "\nEXAMPLES", - " The vmap_area_root is a standalone rb_root structure. Display the ", -@@ -6703,6 +6705,46 @@ char *help_tree[] = { - " _refcount = {", - " counter = 0x1", - " }", -+"", -+" The -v option is introduced specifically for dumping the complete content of", -+" maple tree:", -+"", -+" %s> tree -t maple 0xffff9034c006aec0 -v", -+"", -+" maple_tree(ffff9034c006aec0) flags 309, height 2 root 0xffff9034de70041e", -+"", -+" 0-18446744073709551615: node 0xffff9034de700400 depth 0 type 3 parent ...", -+" 0-140112331583487: node 0xffff9034c01e8800 depth 1 type 1 parent ...", -+" 0-94643156942847: 0x0", -+" 94643156942848-94643158024191: 0xffff9035131754c0", -+" 94643158024192-94643160117247: 0x0", -+" ...", -+"", -+" The existing options can work as well for maple tree:", -+"", -+" %s> tree -t maple -r mm_struct.mm_mt 0xffff9034c006aec0 -p", -+" ffff9035131754c0", -+" index: 1 position: root/0/1", -+" ffff9035131751c8", -+" index: 2 position: root/0/3", -+" ffff9035131757b8", -+" index: 3 position: root/0/4", -+" ...", -+"", -+" %s> tree -t maple 0xffff9034c006aec0 -p -x -s vm_area_struct.vm_start,vm_end", -+" ffff9035131754c0", -+" index: 1 position: root/0/1", -+" vm_start = 0x5613d3c00000,", -+" vm_end = 0x5613d3d08000,", -+" ffff9035131751c8", -+" index: 2 position: root/0/3", -+" vm_start = 0x5613d3f07000,", -+" vm_end = 0x5613d3f0b000,", -+" ffff9035131757b8", -+" index: 3 position: root/0/4", -+" vm_start = 0x5613d3f0b000,", -+" vm_end = 0x5613d3f14000,", -+" ....", - NULL - }; - --- -2.37.1 - diff --git a/0028-Dump-maple-tree-offset-variables-by-help-o.patch b/0028-Dump-maple-tree-offset-variables-by-help-o.patch deleted file mode 100644 index 3c1bae8..0000000 --- a/0028-Dump-maple-tree-offset-variables-by-help-o.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 46344aa2f92b07ded52cf9841f8db24dd7fe67d7 Mon Sep 17 00:00:00 2001 -From: Tao Liu -Date: Tue, 10 Jan 2023 14:56:32 +0800 -Subject: [PATCH 28/28] Dump maple tree offset variables by "help -o" - -In the previous patches, some variables are added to offset_table and -size_table, print them out with "help -o" command. - -Signed-off-by: Tao Liu -Signed-off-by: Lianbo Jiang ---- - symbols.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/symbols.c b/symbols.c -index 33e68d520a72..e38df8aad0f5 100644 ---- a/symbols.c -+++ b/symbols.c -@@ -10766,6 +10766,21 @@ dump_offset_table(char *spec, ulong makestruct) - OFFSET(sbq_wait_state_wait_cnt)); - fprintf(fp, " sbq_wait_state_wait: %ld\n", - OFFSET(sbq_wait_state_wait)); -+ fprintf(fp, " mm_struct_mm_mt: %ld\n", OFFSET(mm_struct_mm_mt)); -+ fprintf(fp, " maple_tree_ma_root: %ld\n", OFFSET(maple_tree_ma_root)); -+ fprintf(fp, " maple_tree_ma_flags: %ld\n", OFFSET(maple_tree_ma_flags)); -+ fprintf(fp, " maple_node_parent: %ld\n", OFFSET(maple_node_parent)); -+ fprintf(fp, " maple_node_ma64: %ld\n", OFFSET(maple_node_ma64)); -+ fprintf(fp, " maple_node_mr64: %ld\n", OFFSET(maple_node_mr64)); -+ fprintf(fp, " maple_node_slot: %ld\n", OFFSET(maple_node_slot)); -+ fprintf(fp, " maple_arange_64_pivot: %ld\n", OFFSET(maple_arange_64_pivot)); -+ fprintf(fp, " maple_arange_64_slot: %ld\n", OFFSET(maple_arange_64_slot)); -+ fprintf(fp, " maple_arange_64_gap: %ld\n", OFFSET(maple_arange_64_gap)); -+ fprintf(fp, " maple_arange_64_meta: %ld\n", OFFSET(maple_arange_64_meta)); -+ fprintf(fp, " maple_range_64_pivot: %ld\n", OFFSET(maple_range_64_pivot)); -+ fprintf(fp, " maple_range_64_slot: %ld\n", OFFSET(maple_range_64_slot)); -+ fprintf(fp, " maple_metadata_end: %ld\n", OFFSET(maple_metadata_end)); -+ fprintf(fp, " maple_metadata_gap: %ld\n", OFFSET(maple_metadata_gap)); - - fprintf(fp, "\n size_table:\n"); - fprintf(fp, " page: %ld\n", SIZE(page)); -@@ -11038,6 +11053,8 @@ dump_offset_table(char *spec, ulong makestruct) - fprintf(fp, " sbitmap_queue: %ld\n", SIZE(sbitmap_queue)); - fprintf(fp, " sbq_wait_state: %ld\n", SIZE(sbq_wait_state)); - fprintf(fp, " blk_mq_tags: %ld\n", SIZE(blk_mq_tags)); -+ fprintf(fp, " maple_tree: %ld\n", SIZE(maple_tree)); -+ fprintf(fp, " maple_node: %ld\n", SIZE(maple_node)); - - fprintf(fp, " percpu_counter: %ld\n", SIZE(percpu_counter)); - --- -2.37.1 - diff --git a/0029-Fix-for-bt-command-printing-bogus-exception-frame-wa.patch b/0029-Fix-for-bt-command-printing-bogus-exception-frame-wa.patch deleted file mode 100644 index ac943fd..0000000 --- a/0029-Fix-for-bt-command-printing-bogus-exception-frame-wa.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 92de7c34b1f910abff4d77522f74454ea0263a90 Mon Sep 17 00:00:00 2001 -From: Lianbo Jiang -Date: Mon, 13 Feb 2023 11:12:12 +0800 -Subject: [PATCH 01/12] Fix for "bt" command printing "bogus exception frame" - warning - -Currently, the "bt" command may print a bogus exception frame -and the remaining frame will be truncated on x86_64 when using the -"virsh send-key KEY_LEFTALT KEY_SYSRQ KEY_C" command -to trigger a panic from the KVM host. For example: - - crash> bt - PID: 0 TASK: ffff9e7a47e32f00 CPU: 3 COMMAND: "swapper/3" - #0 [ffffba7900118bb8] machine_kexec at ffffffff87e5c2c7 - #1 [ffffba7900118c08] __crash_kexec at ffffffff87f9500d - #2 [ffffba7900118cd0] panic at ffffffff87edfff9 - #3 [ffffba7900118d50] sysrq_handle_crash at ffffffff883ce2c1 - ... - #16 [ffffba7900118fd8] handle_edge_irq at ffffffff87f559f2 - #17 [ffffba7900118ff0] asm_call_on_stack at ffffffff88800fa2 - --- --- - #18 [ffffba790008bda0] asm_call_on_stack at ffffffff88800fa2 - RIP: ffffffffffffffff RSP: 0000000000000124 RFLAGS: 00000003 - RAX: 0000000000000000 RBX: 0000000000000001 RCX: 0000000000000000 - RDX: ffffffff88800c1e RSI: 0000000000000000 RDI: 0000000000000000 - RBP: 0000000000000001 R8: 0000000000000000 R9: 0000000000000000 - R10: 0000000000000000 R11: ffffffff88760555 R12: ffffba790008be08 - R13: ffffffff87f18002 R14: ffff9e7a47e32f00 R15: ffff9e7bb6198e00 - ORIG_RAX: 0000000000000000 CS: 0003 SS: 0000 - bt: WARNING: possibly bogus exception frame - crash> - -The following related kernel commits cause the current issue, crash -needs to adjust the value of irq_eframe_link. - -Related kernel commits: -[1] v5.8: 931b94145981 ("x86/entry: Provide helpers for executing on the irqstack") -[2] v5.8: fa5e5c409213 ("x86/entry: Use idtentry for interrupts") -[3] v5.12: 52d743f3b712 ("x86/softirq: Remove indirection in do_softirq_own_stack()") - -Signed-off-by: Lianbo Jiang -Signed-off-by: Kazuhito Hagio ---- - x86_64.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/x86_64.c b/x86_64.c -index 7a5d6f050c89..5b671bd97775 100644 ---- a/x86_64.c -+++ b/x86_64.c -@@ -3938,6 +3938,11 @@ in_exception_stack: - if (irq_eframe) { - bt->flags |= BT_EXCEPTION_FRAME; - i = (irq_eframe - bt->stackbase)/sizeof(ulong); -+ if (symbol_exists("asm_common_interrupt")) { -+ i -= 1; -+ up = (ulong *)(&bt->stackbuf[i*sizeof(ulong)]); -+ bt->instptr = *up; -+ } - x86_64_print_stack_entry(bt, ofp, level, i, bt->instptr); - bt->flags &= ~(ulonglong)BT_EXCEPTION_FRAME; - cs = x86_64_exception_frame(EFRAME_PRINT|EFRAME_CS, 0, -@@ -6521,6 +6526,14 @@ x86_64_irq_eframe_link_init(void) - else - return; - -+ if (symbol_exists("asm_common_interrupt")) { -+ if (symbol_exists("asm_call_on_stack")) -+ machdep->machspec->irq_eframe_link = -64; -+ else -+ machdep->machspec->irq_eframe_link = -32; -+ return; -+ } -+ - if (THIS_KERNEL_VERSION < LINUX(2,6,9)) - return; - --- -2.37.1 - diff --git a/0030-Fix-kmem-s-S-not-working-properly-on-RHEL8.6-and-lat.patch b/0030-Fix-kmem-s-S-not-working-properly-on-RHEL8.6-and-lat.patch deleted file mode 100644 index e23607d..0000000 --- a/0030-Fix-kmem-s-S-not-working-properly-on-RHEL8.6-and-lat.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 9253b40a0ecb2d365f89f0a5ebc28a01735c1d24 Mon Sep 17 00:00:00 2001 -From: "Aureau, Georges (Kernel Tools ERT)" -Date: Wed, 8 Feb 2023 12:09:03 +0000 -Subject: [PATCH 02/12] Fix "kmem -s|-S" not working properly on RHEL8.6 and - later - -For CONFIG_SLAB_FREELIST_HARDENED, the crash memory.c:freelist_ptr() -code is checking for an additional bswap using a simple release test eg. -THIS_KERNEL_VERSION >= LINUX(5,7,0), basically checking for RHEL9 and -beyond. - -However, for RHEL8.6 and later, we have CONFIG_SLAB_FREELIST_HARDENED=y, -and we also have the additional bswap, but the current crash is not -handling this case, hence "kmem -s|-S" will not work properly, and free -objects will not be counted nor reported properly. - -An example from a RHEL8.6 x86_64 kdump, a kmem cache with a single slab -having 42 objects, only the freelist head is seen as free as crash can't -walk freelist next pointers, and crash is wrongly reporting 41 allocated -objects: - - crash> sys | grep RELEASE - RELEASE: 4.18.0-372.9.1.el8.x86_64 - crash> kmem -s nfs_commit_data - CACHE OBJSIZE ALLOCATED TOTAL SLABS SSIZE NAME - ffff9ad40c7cb2c0 728 41 42 1 32k nfs_commit_data - -When properly accounting for the additional bswap, we can walk the -freelist and find 38 free objects, and crash is now reporting only 4 -allocated objects: - - crash> kmem -s nfs_commit_data - CACHE OBJSIZE ALLOCATED TOTAL SLABS SSIZE NAME - ffff9ad40c7cb2c0 728 4 42 1 32k nfs_commit_data - -Signed-off-by: Georges Aureau ---- - defs.h | 1 + - memory.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 49 insertions(+), 1 deletion(-) - -diff --git a/defs.h b/defs.h -index 33a823b7b67c..56d6cf4489c9 100644 ---- a/defs.h -+++ b/defs.h -@@ -2638,6 +2638,7 @@ struct vm_table { /* kernel VM-related data */ - #define SLAB_OVERLOAD_PAGE (0x8000000) - #define SLAB_CPU_CACHE (0x10000000) - #define SLAB_ROOT_CACHES (0x20000000) -+#define FREELIST_PTR_BSWAP (0x40000000) - - #define IS_FLATMEM() (vt->flags & FLATMEM) - #define IS_DISCONTIGMEM() (vt->flags & DISCONTIGMEM) -diff --git a/memory.c b/memory.c -index 5141fbea4b40..e0742c1bd3a4 100644 ---- a/memory.c -+++ b/memory.c -@@ -320,6 +320,7 @@ static void dump_per_cpu_offsets(void); - static void dump_page_flags(ulonglong); - static ulong kmem_cache_nodelists(ulong); - static void dump_hstates(void); -+static void freelist_ptr_init(void); - static ulong freelist_ptr(struct meminfo *, ulong, ulong); - static ulong handle_each_vm_area(struct handle_each_vm_area_args *); - -@@ -789,6 +790,8 @@ vm_init(void) - MEMBER_OFFSET_INIT(kmem_cache_name, "kmem_cache", "name"); - MEMBER_OFFSET_INIT(kmem_cache_flags, "kmem_cache", "flags"); - MEMBER_OFFSET_INIT(kmem_cache_random, "kmem_cache", "random"); -+ if (VALID_MEMBER(kmem_cache_random)) -+ freelist_ptr_init(); - MEMBER_OFFSET_INIT(kmem_cache_cpu_freelist, "kmem_cache_cpu", "freelist"); - MEMBER_OFFSET_INIT(kmem_cache_cpu_page, "kmem_cache_cpu", "page"); - if (INVALID_MEMBER(kmem_cache_cpu_page)) -@@ -13932,6 +13935,8 @@ dump_vm_table(int verbose) - fprintf(fp, "%sSLAB_CPU_CACHE", others++ ? "|" : "");\ - if (vt->flags & SLAB_ROOT_CACHES) - fprintf(fp, "%sSLAB_ROOT_CACHES", others++ ? "|" : "");\ -+ if (vt->flags & FREELIST_PTR_BSWAP) -+ fprintf(fp, "%sFREELIST_PTR_BSWAP", others++ ? "|" : "");\ - if (vt->flags & USE_VMAP_AREA) - fprintf(fp, "%sUSE_VMAP_AREA", others++ ? "|" : "");\ - if (vt->flags & CONFIG_NUMA) -@@ -19519,13 +19524,55 @@ count_free_objects(struct meminfo *si, ulong freelist) - return c; - } - -+/* -+ * With CONFIG_SLAB_FREELIST_HARDENED, freelist_ptr's are crypted with xor's, -+ * and for recent release with an additionnal bswap. Some releases prio to 5.7.0 -+ * may be using the additionnal bswap. The only easy and reliable way to tell is -+ * to inspect assembly code (eg. "__slab_free") for a bswap instruction. -+ */ -+static int -+freelist_ptr_bswap_x86(void) -+{ -+ char buf1[BUFSIZE]; -+ char buf2[BUFSIZE]; -+ char *arglist[MAXARGS]; -+ int found; -+ -+ sprintf(buf1, "disassemble __slab_free"); -+ open_tmpfile(); -+ if (!gdb_pass_through(buf1, pc->tmpfile, GNU_RETURN_ON_ERROR)) { -+ close_tmpfile(); -+ return FALSE; -+ } -+ rewind(pc->tmpfile); -+ found = FALSE; -+ while (fgets(buf2, BUFSIZE, pc->tmpfile)) { -+ if (parse_line(buf2, arglist) < 3) -+ continue; -+ if (STREQ(arglist[2], "bswap")) { -+ found = TRUE; -+ break; -+ } -+ } -+ close_tmpfile(); -+ return found; -+} -+ -+static void -+freelist_ptr_init(void) -+{ -+ if (THIS_KERNEL_VERSION >= LINUX(5,7,0) || -+ ((machine_type("X86_64") || machine_type("X86")) && freelist_ptr_bswap_x86())) -+ vt->flags |= FREELIST_PTR_BSWAP; -+} -+ - static ulong - freelist_ptr(struct meminfo *si, ulong ptr, ulong ptr_addr) - { - if (VALID_MEMBER(kmem_cache_random)) { - /* CONFIG_SLAB_FREELIST_HARDENED */ - -- if (THIS_KERNEL_VERSION >= LINUX(5,7,0)) -+ if (vt->flags & FREELIST_PTR_BSWAP) - ptr_addr = (sizeof(long) == 8) ? bswap_64(ptr_addr) - : bswap_32(ptr_addr); - return (ptr ^ si->random ^ ptr_addr); --- -2.37.1 - diff --git a/0031-Fix-for-net-s-option-to-show-IPv6-addresses-on-Linux.patch b/0031-Fix-for-net-s-option-to-show-IPv6-addresses-on-Linux.patch deleted file mode 100644 index 9042371..0000000 --- a/0031-Fix-for-net-s-option-to-show-IPv6-addresses-on-Linux.patch +++ /dev/null @@ -1,106 +0,0 @@ -From c64a827e0bcab15e86f8fbacec141c2bf4b776ea Mon Sep 17 00:00:00 2001 -From: Lianbo Jiang -Date: Thu, 9 Feb 2023 20:15:46 +0800 -Subject: [PATCH 03/12] Fix for "net -s" option to show IPv6 addresses on Linux - 3.13 and later - -Currently, the "net -s" option fails to show IPv6 addresses and ports -for the SOURCE-PORT and DESTINATION-PORT columns on Linux 3.13 and later -kernels, which have kernel commit efe4208f47f907 ("ipv6: make lookups -simpler and faster"). For example: - - crash> net -s - PID: 305524 TASK: ffff9bc449895580 CPU: 6 COMMAND: "sshd" - FD SOCKET SOCK FAMILY:TYPE SOURCE-PORT DESTINATION-PORT - 3 ffff9bc446e9a680 ffff9bc4455b5940 UNIX:DGRAM - 4 ffff9bc446e9c600 ffff9bc3b2b24e00 INET6:STREAM - -With the patch: - - crash> net -s - PID: 305524 TASK: ffff9bc449895580 CPU: 6 COMMAND: "sshd" - FD SOCKET SOCK FAMILY:TYPE SOURCE-PORT DESTINATION-PORT - 3 ffff9bc446e9a680 ffff9bc4455b5940 UNIX:DGRAM - 4 ffff9bc446e9c600 ffff9bc3b2b24e00 INET6:STREAM xxxx:xx:x:xxxx:xxxx:xxxx:xxxx:xxxx-22 yyyy:yy:y:yyyy:yyyy:yyyy:yyyy:yyyy-44870 - -Reported-by: Buland Kumar Singh -Signed-off-by: Lianbo Jiang -Signed-off-by: Kazuhito Hagio ---- - defs.h | 3 +++ - net.c | 20 +++++++++++++++----- - symbols.c | 3 +++ - 3 files changed, 21 insertions(+), 5 deletions(-) - -diff --git a/defs.h b/defs.h -index 56d6cf4489c9..ab4f02cc65cf 100644 ---- a/defs.h -+++ b/defs.h -@@ -2204,6 +2204,9 @@ struct offset_table { /* stash of commonly-used offsets */ - long maple_range_64_slot; - long maple_metadata_end; - long maple_metadata_gap; -+ long sock_sk_common; -+ long sock_common_skc_v6_daddr; -+ long sock_common_skc_v6_rcv_saddr; - }; - - struct size_table { /* stash of commonly-used sizes */ -diff --git a/net.c b/net.c -index 7c9c8bd9c98d..aa445ab7ee13 100644 ---- a/net.c -+++ b/net.c -@@ -199,6 +199,9 @@ net_init(void) - MEMBER_OFFSET_INIT(sock_common_skc_family, - "sock_common", "skc_family"); - MEMBER_OFFSET_INIT(sock_sk_type, "sock", "sk_type"); -+ MEMBER_OFFSET_INIT(sock_sk_common, "sock", "__sk_common"); -+ MEMBER_OFFSET_INIT(sock_common_skc_v6_daddr, "sock_common", "skc_v6_daddr"); -+ MEMBER_OFFSET_INIT(sock_common_skc_v6_rcv_saddr, "sock_common", "skc_v6_rcv_saddr"); - /* - * struct inet_sock { - * struct sock sk; -@@ -1104,12 +1107,19 @@ get_sock_info(ulong sock, char *buf) - break; - - case SOCK_V2: -- if (INVALID_MEMBER(ipv6_pinfo_rcv_saddr) || -- INVALID_MEMBER(ipv6_pinfo_daddr)) -+ if (VALID_MEMBER(ipv6_pinfo_rcv_saddr) && -+ VALID_MEMBER(ipv6_pinfo_daddr)) { -+ ipv6_rcv_saddr = ipv6_pinfo + OFFSET(ipv6_pinfo_rcv_saddr); -+ ipv6_daddr = ipv6_pinfo + OFFSET(ipv6_pinfo_daddr); -+ } else if (VALID_MEMBER(sock_sk_common) && -+ VALID_MEMBER(sock_common_skc_v6_daddr) && -+ VALID_MEMBER(sock_common_skc_v6_rcv_saddr)) { -+ ipv6_rcv_saddr = sock + OFFSET(sock_sk_common) + OFFSET(sock_common_skc_v6_rcv_saddr); -+ ipv6_daddr = sock + OFFSET(sock_sk_common) + OFFSET(sock_common_skc_v6_daddr); -+ } else { -+ sprintf(&buf[strlen(buf)], "%s", "(cannot get IPv6 addresses)"); - break; -- -- ipv6_rcv_saddr = ipv6_pinfo + OFFSET(ipv6_pinfo_rcv_saddr); -- ipv6_daddr = ipv6_pinfo + OFFSET(ipv6_pinfo_daddr); -+ } - - if (!readmem(ipv6_rcv_saddr, KVADDR, u6_addr16_src, SIZE(in6_addr), - "ipv6_rcv_saddr buffer", QUIET|RETURN_ON_ERROR)) -diff --git a/symbols.c b/symbols.c -index e38df8aad0f5..b702b9665ec1 100644 ---- a/symbols.c -+++ b/symbols.c -@@ -9818,8 +9818,11 @@ dump_offset_table(char *spec, ulong makestruct) - - fprintf(fp, " sock_sk_type: %ld\n", - OFFSET(sock_sk_type)); -+ fprintf(fp, " sock_sk_common: %ld\n", OFFSET(sock_sk_common)); - fprintf(fp, " sock_common_skc_family: %ld\n", - OFFSET(sock_common_skc_family)); -+ fprintf(fp, " sock_common_skc_v6_daddr: %ld\n", OFFSET(sock_common_skc_v6_daddr)); -+ fprintf(fp, " sock_common_skc_v6_rcv_saddr: %ld\n", OFFSET(sock_common_skc_v6_rcv_saddr)); - fprintf(fp, " socket_alloc_vfs_inode: %ld\n", - OFFSET(socket_alloc_vfs_inode)); - fprintf(fp, " inet_sock_inet: %ld\n", --- -2.37.1 - diff --git a/0032-Fix-for-kmem-i-option-to-not-print-invalid-values-fo.patch b/0032-Fix-for-kmem-i-option-to-not-print-invalid-values-fo.patch deleted file mode 100644 index 2c4eb2d..0000000 --- a/0032-Fix-for-kmem-i-option-to-not-print-invalid-values-fo.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 277da34dd5da8c1280d0d0fd7ce50499b31c3a58 Mon Sep 17 00:00:00 2001 -From: Lianbo Jiang -Date: Tue, 14 Feb 2023 22:37:08 +0800 -Subject: [PATCH 04/12] Fix for "kmem -i" option to not print invalid values - for CACHED - -The "kmem -i" option may output a bogus statistics for CACHED, which -might be observed when some extreme situations occur in kernel, such as -OOM, disk IO errors, etc. - -The following result of calculation may be a negative value, refer to -the dump_kmeminfo(): - page_cache_size = nr_file_pages - swapper_space_nrpages - buffer_pages; - -As a result, the negative value will be converted to unsigned long -integer, eventually it overflows and is printed as big integers. - - crash> kmem -i - PAGES TOTAL PERCENTAGE - TOTAL MEM 255314511 973.9 GB ---- - FREE 533574 2 GB 0% of TOTAL MEM - USED 254780937 971.9 GB 99% of TOTAL MEM - SHARED 1713 6.7 MB 0% of TOTAL MEM - BUFFERS 374 1.5 MB 0% of TOTAL MEM - CACHED -114 70368744177664 GB 72251060080% of TOTAL MEM - ^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^ - ... - -Let's normalize it to zero with an info message to fix such cornor cases. - -Reported-by: Buland Kumar Singh -Signed-off-by: Lianbo Jiang -Signed-off-by: Kazuhito Hagio ---- - memory.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/memory.c b/memory.c -index e0742c1bd3a4..d9cd616f19de 100644 ---- a/memory.c -+++ b/memory.c -@@ -8615,6 +8615,11 @@ dump_kmeminfo(void) - page_cache_size = 0; - - -+ if (page_cache_size < 0) { -+ error(INFO, "page_cache_size went negative (%ld), setting to 0\n", -+ page_cache_size); -+ page_cache_size = 0; -+ } - pct = (page_cache_size * 100)/totalram_pages; - fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL MEM\n", - "CACHED", page_cache_size, --- -2.37.1 - diff --git a/0033-Fix-for-bt-command-unnecessarily-printing-an-excepti.patch b/0033-Fix-for-bt-command-unnecessarily-printing-an-excepti.patch deleted file mode 100644 index a946471..0000000 --- a/0033-Fix-for-bt-command-unnecessarily-printing-an-excepti.patch +++ /dev/null @@ -1,77 +0,0 @@ -From e0e6e4a7ee03b3d00b50a9e4db2f2ea6f7da0da3 Mon Sep 17 00:00:00 2001 -From: Lianbo Jiang -Date: Wed, 15 Feb 2023 16:24:57 +0800 -Subject: [PATCH 05/12] Fix for "bt" command unnecessarily printing an - exception frame - -Kernel commit 7d65f4a65532 ("irq: Consolidate do_softirq() arch overriden -implementations") renamed the call_softirq to do_softirq_own_stack, and -there is no exception frame also when coming from do_softirq_own_stack. -Without the patch, crash may unnecessarily output an exception frame with -a warning as below: - - crash> foreach bt - ... - PID: 0 TASK: ffff914f820a8000 CPU: 25 COMMAND: "swapper/25" - #0 [fffffe0000504e48] crash_nmi_callback at ffffffffa665d763 - #1 [fffffe0000504e50] nmi_handle at ffffffffa662a423 - #2 [fffffe0000504ea8] default_do_nmi at ffffffffa6fe7dc9 - #3 [fffffe0000504ec8] do_nmi at ffffffffa662a97f - #4 [fffffe0000504ef0] end_repeat_nmi at ffffffffa70015e8 - [exception RIP: clone_endio+172] - RIP: ffffffffc005c1ec RSP: ffffa1d403d08e98 RFLAGS: 00000246 - RAX: 0000000000000000 RBX: ffff915326fba230 RCX: 0000000000000018 - RDX: ffffffffc0075400 RSI: 0000000000000000 RDI: ffff915326fba230 - RBP: ffff915326fba1c0 R8: 0000000000001000 R9: ffff915308d6d2a0 - R10: 000000a97dfe5e10 R11: ffffa1d40038fe98 R12: ffff915302babc40 - R13: ffff914f94360000 R14: 0000000000000000 R15: 0000000000000000 - ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 - --- --- - #5 [ffffa1d403d08e98] clone_endio at ffffffffc005c1ec [dm_mod] - #6 [ffffa1d403d08ed0] blk_update_request at ffffffffa6a96954 - #7 [ffffa1d403d08f10] scsi_end_request at ffffffffa6c9b968 - #8 [ffffa1d403d08f48] scsi_io_completion at ffffffffa6c9bb3e - #9 [ffffa1d403d08f90] blk_complete_reqs at ffffffffa6aa0e95 - #10 [ffffa1d403d08fa0] __softirqentry_text_start at ffffffffa72000dc - #11 [ffffa1d403d08ff0] do_softirq_own_stack at ffffffffa7000f9a - --- --- - #12 [ffffa1d40038fe70] do_softirq_own_stack at ffffffffa7000f9a - [exception RIP: unknown or invalid address] - RIP: 0000000000000000 RSP: 0000000000000000 RFLAGS: 00000000 - RAX: ffffffffa672eae5 RBX: ffffffffa83b34e0 RCX: ffffffffa672eb12 - RDX: 0000000000000010 RSI: 8b7d6c8869010c00 RDI: 0000000000000085 - RBP: 0000000000000286 R8: ffff914f820a8000 R9: ffffffffa67a94e0 - R10: 0000000000000286 R11: ffffffffa66fb4c5 R12: ffffffffa67a898b - R13: 0000000000000000 R14: fffffffffffffff8 R15: ffffffffa67a1e68 - ORIG_RAX: 0000000000000000 CS: 0000 SS: ffffffffa672edff - bt: WARNING: possibly bogus exception frame - #13 [ffffa1d40038ff30] start_secondary at ffffffffa665fa2c - #14 [ffffa1d40038ff50] secondary_startup_64_no_verify at ffffffffa6600116 - ... - -Reported-by: Marco Patalano ---- - x86_64.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/x86_64.c b/x86_64.c -index 5b671bd97775..6cac3936b33d 100644 ---- a/x86_64.c -+++ b/x86_64.c -@@ -3825,10 +3825,11 @@ in_exception_stack: - up -= 1; - bt->instptr = *up; - /* -- * No exception frame when coming from call_softirq. -+ * No exception frame when coming from do_softirq_own_stack -+ * or call_softirq. - */ - if ((sp = value_search(bt->instptr, &offset)) && -- STREQ(sp->name, "call_softirq")) -+ (STREQ(sp->name, "do_softirq_own_stack") || STREQ(sp->name, "call_softirq"))) - irq_eframe = 0; - bt->frameptr = 0; - done = FALSE; --- -2.37.1 - diff --git a/0034-Fix-for-dis-command-to-correctly-display-the-offset-.patch b/0034-Fix-for-dis-command-to-correctly-display-the-offset-.patch deleted file mode 100644 index 653e7de..0000000 --- a/0034-Fix-for-dis-command-to-correctly-display-the-offset-.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 59c19818190dd4b7ae0dc2221586a4ad6f4fe905 Mon Sep 17 00:00:00 2001 -From: Lianbo Jiang -Date: Tue, 21 Feb 2023 11:03:26 +0800 -Subject: [PATCH 06/12] Fix for "dis" command to correctly display the offset - of disassembly code - -For gdb-10.2, the disassembly code may start with "=>", which needs to -be stripped when calculating the address. Otherwise, parsing the address -will fail because the current code always assumes that it starts with the -"0x". For example: - - crash> gdb disassemble 0xffffffffa2317add - Dump of assembler code for function native_queued_spin_lock_slowpath: - ... - 0xffffffffa2317ad3 <+35>: mov %edx,%eax - 0xffffffffa2317ad5 <+37>: lock cmpxchg %ecx,(%rdi) - => 0xffffffffa2317ad9 <+41>: cmp %eax,%edx - 0xffffffffa2317adb <+43>: jne 0xffffffffa2317ac0 ... - 0xffffffffa2317add <+45>: pop %rbp - ... - -Without the patch: - crash> dis 0xffffffffa2317add -r | tail -5 - 0xffffffffa2317ad3 : mov %edx,%eax - 0xffffffffa2317ad5 : lock cmpxchg %ecx,(%rdi) - 0xffffffffa2317ad5 : cmp %eax,%edx - ^^ - 0xffffffffa2317adb : jne 0xffffffffa2317ac0 ... - 0xffffffffa2317add : pop %rbp - -With the patch: - - crash> dis 0xffffffffa2317add -r | tail -5 - 0xffffffffa2317ad3 : mov %edx,%eax - 0xffffffffa2317ad5 : lock cmpxchg %ecx,(%rdi) - 0xffffffffa2317ad9 : cmp %eax,%edx - 0xffffffffa2317adb : jne 0xffffffffa2317ac0 ... - 0xffffffffa2317add : pop %rbp - -Reported-by: Vernon Lovejoy ---- - kernel.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/kernel.c b/kernel.c -index a42e6ad7d78c..6e98f5f6f6b1 100644 ---- a/kernel.c -+++ b/kernel.c -@@ -2112,6 +2112,10 @@ cmd_dis(void) - rewind(pc->tmpfile); - - while (fgets(buf2, BUFSIZE, pc->tmpfile)) { -+ -+ if (STRNEQ(buf2, "=>")) -+ shift_string_left(buf2, 2); -+ - strip_beginning_whitespace(buf2); - - if (do_load_module_filter) --- -2.37.1 - diff --git a/0035-x86_64-Fix-bt-command-on-kernels-with-random_kstack_.patch b/0035-x86_64-Fix-bt-command-on-kernels-with-random_kstack_.patch deleted file mode 100644 index 4b560bd..0000000 --- a/0035-x86_64-Fix-bt-command-on-kernels-with-random_kstack_.patch +++ /dev/null @@ -1,299 +0,0 @@ -From daa43fa5324f2dd232ad72df2c6554646868f3b2 Mon Sep 17 00:00:00 2001 -From: Kazuhito Hagio -Date: Mon, 20 Feb 2023 10:28:53 +0900 -Subject: [PATCH 07/12] x86_64: Fix "bt" command on kernels with - random_kstack_offset=on - -On kernels configured with CONFIG_RANDOMIZE_KSTACK_OFFSET=y and -random_kstack_offset=on, a random offset is added to task stacks with -__kstack_alloca() at the beginning of do_syscall_64() and other syscall -entry functions. This eventually does the following instruction. - - : sub %rax,%rsp - -On the other hand, crash uses only a part of data for ORC unwinder to -unwind stacks and if an ip value doesn't have a usable ORC data, it -caluculates the frame size with parsing the assembly of the function. - -However, crash cannot calculate the frame size correctly with the -instruction above, and prints stale return addresses like this: - - crash> bt 1 - PID: 1 TASK: ffff9c250023b880 CPU: 0 COMMAND: "systemd" - #0 [ffffb7e5c001fc80] __schedule at ffffffff91ae2b16 - #1 [ffffb7e5c001fd00] schedule at ffffffff91ae2ed3 - #2 [ffffb7e5c001fd18] schedule_hrtimeout_range_clock at ffffffff91ae7ed8 - #3 [ffffb7e5c001fda8] ep_poll at ffffffff913ef828 - #4 [ffffb7e5c001fe48] do_epoll_wait at ffffffff913ef943 - #5 [ffffb7e5c001fe80] __x64_sys_epoll_wait at ffffffff913f0130 - #6 [ffffb7e5c001fed0] do_syscall_64 at ffffffff91ad7169 - #7 [ffffb7e5c001fef0] do_syscall_64 at ffffffff91ad7179 << - #8 [ffffb7e5c001ff10] syscall_exit_to_user_mode at ffffffff91adaab2 << stale entries - #9 [ffffb7e5c001ff20] do_syscall_64 at ffffffff91ad7179 << - #10 [ffffb7e5c001ff50] entry_SYSCALL_64_after_hwframe at ffffffff91c0009b - RIP: 00007f258d9427ae RSP: 00007fffda631d60 RFLAGS: 00000293 - ... - -To fix this, enhance the use of ORC data. The ORC unwinder often uses -%rbp value, so keep it from exception frames and inactive task stacks. - -Signed-off-by: Kazuhito Hagio ---- - defs.h | 1 + - symbols.c | 1 + - x86_64.c | 118 ++++++++++++++++++++++++++++++++++++++---------------- - 3 files changed, 85 insertions(+), 35 deletions(-) - -diff --git a/defs.h b/defs.h -index ab4f02cc65cf..e76af3c78b69 100644 ---- a/defs.h -+++ b/defs.h -@@ -2207,6 +2207,7 @@ struct offset_table { /* stash of commonly-used offsets */ - long sock_sk_common; - long sock_common_skc_v6_daddr; - long sock_common_skc_v6_rcv_saddr; -+ long inactive_task_frame_bp; - }; - - struct size_table { /* stash of commonly-used sizes */ -diff --git a/symbols.c b/symbols.c -index b702b9665ec1..a974fc9141a0 100644 ---- a/symbols.c -+++ b/symbols.c -@@ -8822,6 +8822,7 @@ dump_offset_table(char *spec, ulong makestruct) - OFFSET(task_struct_tss_ksp)); - fprintf(fp, " task_struct_thread_eip: %ld\n", - OFFSET(task_struct_thread_eip)); -+ fprintf(fp, " inactive_task_frame_bp: %ld\n", OFFSET(inactive_task_frame_bp)); - fprintf(fp, " inactive_task_frame_ret_addr: %ld\n", - OFFSET(inactive_task_frame_ret_addr)); - fprintf(fp, " task_struct_thread_esp: %ld\n", -diff --git a/x86_64.c b/x86_64.c -index 6cac3936b33d..8e3eb8957af1 100644 ---- a/x86_64.c -+++ b/x86_64.c -@@ -122,7 +122,7 @@ static int x86_64_do_not_cache_framesize(struct syment *, ulong); - static int x86_64_framesize_cache_func(int, ulong, int *, int, struct syment *); - static ulong x86_64_get_framepointer(struct bt_info *, ulong); - int search_for_eframe_target_caller(struct bt_info *, ulong, int *); --static int x86_64_get_framesize(struct bt_info *, ulong, ulong); -+static int x86_64_get_framesize(struct bt_info *, ulong, ulong, char *); - static void x86_64_framesize_debug(struct bt_info *); - static void x86_64_get_active_set(void); - static int x86_64_get_kvaddr_ranges(struct vaddr_range *); -@@ -3642,7 +3642,7 @@ in_exception_stack: - bt, ofp); - rsp += SIZE(pt_regs); /* guaranteed kernel mode */ - if (bt->eframe_ip && ((framesize = x86_64_get_framesize(bt, -- bt->eframe_ip, rsp)) >= 0)) -+ bt->eframe_ip, rsp, NULL)) >= 0)) - rsp += framesize; - level++; - irq_eframe = 0; -@@ -3674,7 +3674,7 @@ in_exception_stack: - case BACKTRACE_ENTRY_DISPLAYED: - level++; - if ((framesize = x86_64_get_framesize(bt, -- bt->eframe_ip ? bt->eframe_ip : *up, rsp)) >= 0) { -+ bt->eframe_ip ? bt->eframe_ip : *up, rsp, NULL)) >= 0) { - rsp += framesize; - i += framesize/sizeof(ulong); - } -@@ -3747,7 +3747,7 @@ in_exception_stack: - } - - level++; -- if ((framesize = x86_64_get_framesize(bt, bt->instptr, rsp)) >= 0) -+ if ((framesize = x86_64_get_framesize(bt, bt->instptr, rsp, NULL)) >= 0) - rsp += framesize; - } - } -@@ -3799,7 +3799,7 @@ in_exception_stack: - case BACKTRACE_ENTRY_DISPLAYED: - level++; - if ((framesize = x86_64_get_framesize(bt, -- bt->eframe_ip ? bt->eframe_ip : *up, rsp)) >= 0) { -+ bt->eframe_ip ? bt->eframe_ip : *up, rsp, NULL)) >= 0) { - rsp += framesize; - i += framesize/sizeof(ulong); - } -@@ -3909,24 +3909,34 @@ in_exception_stack: - (STREQ(rip_symbol, "thread_return") || - STREQ(rip_symbol, "schedule") || - STREQ(rip_symbol, "__schedule"))) { -- if (STREQ(rip_symbol, "__schedule")) { -- i = (rsp - bt->stackbase)/sizeof(ulong); -- x86_64_print_stack_entry(bt, ofp, level, -- i, bt->instptr); -- level++; -- rsp = __schedule_frame_adjust(rsp, bt); -- if (STREQ(closest_symbol(bt->instptr), "schedule")) -+ if ((machdep->flags & ORC) && VALID_MEMBER(inactive_task_frame_ret_addr)) { -+ /* -+ * %rsp should have the address of inactive_task_frame, so -+ * skip the registers before ret_addr to adjust rsp. -+ */ -+ if (CRASHDEBUG(1)) -+ fprintf(fp, "rsp: %lx rbp: %lx\n", rsp, bt->bptr); -+ rsp += OFFSET(inactive_task_frame_ret_addr); -+ } else { -+ if (STREQ(rip_symbol, "__schedule")) { -+ i = (rsp - bt->stackbase)/sizeof(ulong); -+ x86_64_print_stack_entry(bt, ofp, level, -+ i, bt->instptr); -+ level++; -+ rsp = __schedule_frame_adjust(rsp, bt); -+ if (STREQ(closest_symbol(bt->instptr), "schedule")) -+ bt->flags |= BT_SCHEDULE; -+ } else - bt->flags |= BT_SCHEDULE; -- } else -- bt->flags |= BT_SCHEDULE; -- -- if (bt->flags & BT_SCHEDULE) { -- i = (rsp - bt->stackbase)/sizeof(ulong); -- x86_64_print_stack_entry(bt, ofp, level, -- i, bt->instptr); -- bt->flags &= ~(ulonglong)BT_SCHEDULE; -- rsp += sizeof(ulong); -- level++; -+ -+ if (bt->flags & BT_SCHEDULE) { -+ i = (rsp - bt->stackbase)/sizeof(ulong); -+ x86_64_print_stack_entry(bt, ofp, level, -+ i, bt->instptr); -+ bt->flags &= ~(ulonglong)BT_SCHEDULE; -+ rsp += sizeof(ulong); -+ level++; -+ } - } - } - -@@ -3957,7 +3967,7 @@ in_exception_stack: - irq_eframe = 0; - bt->flags |= BT_EFRAME_TARGET; - if (bt->eframe_ip && ((framesize = x86_64_get_framesize(bt, -- bt->eframe_ip, rsp)) >= 0)) -+ bt->eframe_ip, rsp, NULL)) >= 0)) - rsp += framesize; - bt->flags &= ~BT_EFRAME_TARGET; - } -@@ -4044,7 +4054,7 @@ in_exception_stack: - case BACKTRACE_ENTRY_DISPLAYED: - level++; - if ((framesize = x86_64_get_framesize(bt, -- bt->eframe_ip ? bt->eframe_ip : *up, rsp)) >= 0) { -+ bt->eframe_ip ? bt->eframe_ip : *up, rsp, (char *)up)) >= 0) { - rsp += framesize; - i += framesize/sizeof(ulong); - } -@@ -4755,7 +4765,8 @@ x86_64_exception_frame(ulong flags, ulong kvaddr, char *local, - bt->instptr = rip; - bt->stkptr = rsp; - bt->bptr = rbp; -- } -+ } else if (machdep->flags & ORC) -+ bt->bptr = rbp; - - if (kvaddr) - FREEBUF(pt_regs_buf); -@@ -5315,6 +5326,10 @@ x86_64_get_sp(struct bt_info *bt) - OFFSET(thread_struct_rsp), KVADDR, - &rsp, sizeof(void *), - "thread_struct rsp", FAULT_ON_ERROR); -+ if ((machdep->flags & ORC) && VALID_MEMBER(inactive_task_frame_bp)) { -+ readmem(rsp + OFFSET(inactive_task_frame_bp), KVADDR, &bt->bptr, -+ sizeof(void *), "inactive_task_frame.bp", FAULT_ON_ERROR); -+ } - return rsp; - } - -@@ -6421,6 +6436,9 @@ x86_64_ORC_init(void) - orc->__stop_orc_unwind = symbol_value("__stop_orc_unwind"); - orc->orc_lookup = symbol_value("orc_lookup"); - -+ MEMBER_OFFSET_INIT(inactive_task_frame_bp, "inactive_task_frame", "bp"); -+ MEMBER_OFFSET_INIT(inactive_task_frame_ret_addr, "inactive_task_frame", "ret_addr"); -+ - machdep->flags |= ORC; - } - -@@ -8489,7 +8507,7 @@ search_for_eframe_target_caller(struct bt_info *bt, ulong stkptr, int *framesize - (BT_OLD_BACK_TRACE|BT_TEXT_SYMBOLS|BT_TEXT_SYMBOLS_ALL|BT_FRAMESIZE_DISABLE) - - static int --x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp) -+x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp, char *stack_ptr) - { - int c, framesize, instr, arg, max; - struct syment *sp; -@@ -8590,19 +8608,49 @@ x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp) - if ((machdep->flags & ORC) && (korc = orc_find(textaddr))) { - if (CRASHDEBUG(1)) { - fprintf(fp, -- "rsp: %lx textaddr: %lx framesize: %d -> spo: %d bpo: %d spr: %d bpr: %d type: %d %s", -- rsp, textaddr, framesize, korc->sp_offset, korc->bp_offset, -- korc->sp_reg, korc->bp_reg, korc->type, -- (korc->type == ORC_TYPE_CALL) && (korc->sp_reg == ORC_REG_SP) ? "" : "(UNUSED)"); -+ "rsp: %lx textaddr: %lx -> spo: %d bpo: %d spr: %d bpr: %d type: %d", -+ rsp, textaddr, korc->sp_offset, korc->bp_offset, -+ korc->sp_reg, korc->bp_reg, korc->type); - if (MEMBER_EXISTS("orc_entry", "end")) - fprintf(fp, " end: %d", korc->end); - fprintf(fp, "\n"); - } - -- if ((korc->type == ORC_TYPE_CALL) && (korc->sp_reg == ORC_REG_SP)) { -- framesize = (korc->sp_offset - 8); -- return (x86_64_framesize_cache_func(FRAMESIZE_ENTER, textaddr, -- &framesize, exception, NULL)); -+ if (korc->type == ORC_TYPE_CALL) { -+ ulong prev_sp = 0, prev_bp = 0; -+ framesize = -1; -+ -+ if (korc->sp_reg == ORC_REG_SP) { -+ framesize = (korc->sp_offset - 8); -+ -+ /* rsp points to a return address, so +8 to use sp_offset */ -+ prev_sp = (rsp + 8) + korc->sp_offset; -+ if (CRASHDEBUG(1)) -+ fprintf(fp, "rsp: %lx prev_sp: %lx framesize: %d\n", -+ rsp, prev_sp, framesize); -+ } else if ((korc->sp_reg == ORC_REG_BP) && bt->bptr) { -+ prev_sp = bt->bptr + korc->sp_offset; -+ framesize = (prev_sp - (rsp + 8) - 8); -+ if (CRASHDEBUG(1)) -+ fprintf(fp, "rsp: %lx rbp: %lx prev_sp: %lx framesize: %d\n", -+ rsp, bt->bptr, prev_sp, framesize); -+ } -+ -+ if ((korc->bp_reg == ORC_REG_PREV_SP) && prev_sp) { -+ prev_bp = prev_sp + korc->bp_offset; -+ if (stack_ptr && INSTACK(prev_bp, bt)) { -+ bt->bptr = ULONG(stack_ptr + (prev_bp - rsp)); -+ if (CRASHDEBUG(1)) -+ fprintf(fp, "rsp: %lx prev_sp: %lx prev_bp: %lx -> %lx\n", -+ rsp, prev_sp, prev_bp, bt->bptr); -+ } else -+ bt->bptr = 0; -+ } else if ((korc->bp_reg != ORC_REG_UNDEFINED)) -+ bt->bptr = 0; -+ -+ if (framesize >= 0) -+ /* Do not cache this, possibly it may be variable. */ -+ return framesize; - } - } - -@@ -8758,7 +8806,7 @@ x86_64_framesize_debug(struct bt_info *bt) - if (!bt->hp->eip) - error(INFO, "x86_64_framesize_debug: ignoring command\n"); - else -- x86_64_get_framesize(bt, bt->hp->eip, 0); -+ x86_64_get_framesize(bt, bt->hp->eip, 0, NULL); - break; - - case -3: --- -2.37.1 - diff --git a/0036-Fix-for-search-u-option-failing-in-maple-tree-kernel.patch b/0036-Fix-for-search-u-option-failing-in-maple-tree-kernel.patch deleted file mode 100644 index a3d88e4..0000000 --- a/0036-Fix-for-search-u-option-failing-in-maple-tree-kernel.patch +++ /dev/null @@ -1,168 +0,0 @@ -From d0d6cf868577fdca81c40633fa082dae1794294f Mon Sep 17 00:00:00 2001 -From: Tao Liu -Date: Wed, 22 Feb 2023 14:32:09 +0800 -Subject: [PATCH 08/12] Fix for "search -u" option failing in maple tree kernel - -Kernel with maple tree enabled doesn't have mmap as a member of mm_struct[1], -so OFFSET(mm_struct_mmap) case needed to be handled differently for -maple tree kernel. - -Before: -crash> search -u a - -search: invalid structure member offset: mm_struct_mmap - FILE: memory.c LINE: 14255 FUNCTION: address_space_start() - -[crash] error trace: 549500 => 548fff => 5f1c91 => 5f1c13 - - 5f1c13: OFFSET_verify.part.36+51 - 5f1c91: OFFSET_verify+49 - 548fff: address_space_start+106 - 549500: cmd_search+855 - -search: invalid structure member offset: mm_struct_mmap - FILE: memory.c LINE: 14255 FUNCTION: address_space_start() - -After: -crash> search -u a -7ffea63e6440: a - -[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=763ecb035029f500d7e6dc99acd1ad299b7726a1 - -Signed-off-by: Tao Liu ---- - memory.c | 89 +++++++++++++++++++++++++++++++++++++++++--------------- - 1 file changed, 65 insertions(+), 24 deletions(-) - -diff --git a/memory.c b/memory.c -index d9cd616f19de..c4a6ecd18004 100644 ---- a/memory.c -+++ b/memory.c -@@ -14245,14 +14245,28 @@ vaddr_type(ulong vaddr, struct task_context *tc) - static int - address_space_start(struct task_context *tc, ulong *addr) - { -- ulong vma; -+ ulong mm_mt, entry_num, i, vma = 0; - char *vma_buf; -+ struct list_pair *entry_list; - - if (!tc->mm_struct) - return FALSE; - -- fill_mm_struct(tc->mm_struct); -- vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap)); -+ if (INVALID_MEMBER(mm_struct_mmap) && VALID_MEMBER(mm_struct_mm_mt)) { -+ mm_mt = tc->mm_struct + OFFSET(mm_struct_mm_mt); -+ entry_num = do_maple_tree(mm_mt, MAPLE_TREE_COUNT, NULL); -+ entry_list = (struct list_pair *)GETBUF(entry_num * sizeof(struct list_pair)); -+ do_maple_tree(mm_mt, MAPLE_TREE_GATHER, entry_list); -+ for (i = 0; i < entry_num; i++) { -+ if (!!(vma = (ulong)entry_list[i].value)) -+ break; -+ } -+ FREEBUF(entry_list); -+ } else { -+ fill_mm_struct(tc->mm_struct); -+ vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap)); -+ } -+ - if (!vma) - return FALSE; - vma_buf = fill_vma_cache(vma); -@@ -15491,6 +15505,30 @@ search_physical(struct searchinfo *si) - FREEBUF(pagebuf); - } - -+static bool -+check_vma(ulong vma, ulong vaddr, ulong *vm_next, ulong *nextvaddr) -+{ -+ char *vma_buf; -+ ulong vm_start, vm_end; -+ -+ vma_buf = fill_vma_cache(vma); -+ -+ vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start)); -+ vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end)); -+ if (vm_next) -+ *vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next)); -+ -+ if (vaddr <= vm_start) { -+ *nextvaddr = vm_start; -+ return TRUE; -+ } -+ -+ if ((vaddr > vm_start) && (vaddr < vm_end)) { -+ *nextvaddr = vaddr; -+ return TRUE; -+ } -+ return FALSE; -+} - - /* - * Return the next mapped user virtual address page that comes after -@@ -15500,37 +15538,40 @@ static int - next_upage(struct task_context *tc, ulong vaddr, ulong *nextvaddr) - { - ulong vma, total_vm; -- char *vma_buf; -- ulong vm_start, vm_end; - ulong vm_next; -+ ulong mm_mt, entry_num, i; -+ struct list_pair *entry_list; - - if (!tc->mm_struct) - return FALSE; - -- fill_mm_struct(tc->mm_struct); -- vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap)); -+ fill_mm_struct(tc->mm_struct); -+ vaddr = VIRTPAGEBASE(vaddr) + PAGESIZE(); /* first possible page */ - total_vm = ULONG(tt->mm_struct + OFFSET(mm_struct_total_vm)); -- -- if (!vma || (total_vm == 0)) -+ if (!total_vm) - return FALSE; - -- vaddr = VIRTPAGEBASE(vaddr) + PAGESIZE(); /* first possible page */ -- -- for ( ; vma; vma = vm_next) { -- vma_buf = fill_vma_cache(vma); -- -- vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start)); -- vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end)); -- vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next)); -- -- if (vaddr <= vm_start) { -- *nextvaddr = vm_start; -- return TRUE; -+ if (INVALID_MEMBER(mm_struct_mmap) && VALID_MEMBER(mm_struct_mm_mt)) { -+ mm_mt = tc->mm_struct + OFFSET(mm_struct_mm_mt); -+ entry_num = do_maple_tree(mm_mt, MAPLE_TREE_COUNT, NULL); -+ entry_list = (struct list_pair *)GETBUF(entry_num * sizeof(struct list_pair)); -+ do_maple_tree(mm_mt, MAPLE_TREE_GATHER, entry_list); -+ for (i = 0; i < entry_num; i++) { -+ if (!!(vma = (ulong)entry_list[i].value) && -+ check_vma(vma, vaddr, NULL, nextvaddr)) { -+ FREEBUF(entry_list); -+ return TRUE; -+ } - } -+ FREEBUF(entry_list); -+ } else { -+ vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap)); - -- if ((vaddr > vm_start) && (vaddr < vm_end)) { -- *nextvaddr = vaddr; -- return TRUE; -+ if (!vma) -+ return FALSE; -+ for ( ; vma; vma = vm_next) { -+ if (check_vma(vma, vaddr, &vm_next, nextvaddr)) -+ return TRUE; - } - } - --- -2.37.1 - diff --git a/0037-Enhance-net-command-to-display-IPv6-address-of-netwo.patch b/0037-Enhance-net-command-to-display-IPv6-address-of-netwo.patch deleted file mode 100644 index 717ce96..0000000 --- a/0037-Enhance-net-command-to-display-IPv6-address-of-netwo.patch +++ /dev/null @@ -1,258 +0,0 @@ -From 38325fab533751a001b80481cec149213d125abb Mon Sep 17 00:00:00 2001 -From: Lianbo Jiang -Date: Tue, 7 Mar 2023 17:14:25 +0800 -Subject: [PATCH 09/12] Enhance "net" command to display IPv6 address of - network interface - -Currently, the "net" command displays only the IPv4 address of a network -interface. Support outputting IPv6 addresses. For example: - -Without the patch: - crash> net - NET_DEVICE NAME IP ADDRESS(ES) - ffff8d01b1205000 lo 127.0.0.1 - ffff8d0087e40000 eno1 192.168.122.2 - -With the patch: - crash> net - NET_DEVICE NAME IP ADDRESS(ES) - ffff8d01b1205000 lo 127.0.0.1, ::1 - ffff8d0087e40000 eno1 192.168.122.2, xxxx:xx:x:xxxx:xxxx:xxx:xxxx:xxxx, yyyy::yyyy:yyy:yyyy:yyyy - -Also align with longer device names. - -Related kernel commit: -502a2ffd7376 ("ipv6: convert idev_list to list macros") - -Reported-by: Buland Kumar Singh -Signed-off-by: Lianbo Jiang -Signed-off-by: Kazuhito Hagio ---- - defs.h | 6 +++ - net.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++----- - symbols.c | 6 +++ - 3 files changed, 112 insertions(+), 9 deletions(-) - -diff --git a/defs.h b/defs.h -index e76af3c78b69..1f2cf6e0ce01 100644 ---- a/defs.h -+++ b/defs.h -@@ -2208,6 +2208,12 @@ struct offset_table { /* stash of commonly-used offsets */ - long sock_common_skc_v6_daddr; - long sock_common_skc_v6_rcv_saddr; - long inactive_task_frame_bp; -+ long net_device_ip6_ptr; -+ long inet6_dev_addr_list; -+ long inet6_ifaddr_addr; -+ long inet6_ifaddr_if_list; -+ long inet6_ifaddr_if_next; -+ long in6_addr_in6_u; - }; - - struct size_table { /* stash of commonly-used sizes */ -diff --git a/net.c b/net.c -index aa445ab7ee13..987dc8934942 100644 ---- a/net.c -+++ b/net.c -@@ -71,6 +71,7 @@ static void print_neighbour_q(ulong, int); - static void get_netdev_info(ulong, struct devinfo *); - static void get_device_name(ulong, char *); - static long get_device_address(ulong, char **, long); -+static void get_device_ip6_address(ulong, char **, long); - static void get_sock_info(ulong, char *); - static void dump_arp(void); - static void arp_state_to_flags(unsigned char); -@@ -114,6 +115,13 @@ net_init(void) - net->dev_ip_ptr = MEMBER_OFFSET_INIT(net_device_ip_ptr, - "net_device", "ip_ptr"); - MEMBER_OFFSET_INIT(net_device_dev_list, "net_device", "dev_list"); -+ MEMBER_OFFSET_INIT(net_device_ip6_ptr, "net_device", "ip6_ptr"); -+ MEMBER_OFFSET_INIT(inet6_dev_addr_list, "inet6_dev", "addr_list"); -+ MEMBER_OFFSET_INIT(inet6_ifaddr_addr, "inet6_ifaddr", "addr"); -+ MEMBER_OFFSET_INIT(inet6_ifaddr_if_list, "inet6_ifaddr", "if_list"); -+ MEMBER_OFFSET_INIT(inet6_ifaddr_if_next, "inet6_ifaddr", "if_next"); -+ MEMBER_OFFSET_INIT(in6_addr_in6_u, "in6_addr", "in6_u"); -+ - MEMBER_OFFSET_INIT(net_dev_base_head, "net", "dev_base_head"); - ARRAY_LENGTH_INIT(net->net_device_name_index, - net_device_name, "net_device.name", NULL, sizeof(char)); -@@ -466,7 +474,7 @@ show_net_devices(ulong task) - buf = GETBUF(buflen); - flen = MAX(VADDR_PRLEN, strlen(net->netdevice)); - -- fprintf(fp, "%s NAME IP ADDRESS(ES)\n", -+ fprintf(fp, "%s NAME IP ADDRESS(ES)\n", - mkstring(upper_case(net->netdevice, buf), - flen, CENTER|LJUST, NULL)); - -@@ -475,9 +483,10 @@ show_net_devices(ulong task) - mkstring(buf, flen, CENTER|RJUST|LONG_HEX, MKSTR(next))); - - get_device_name(next, buf); -- fprintf(fp, "%-6s ", buf); -+ fprintf(fp, "%-10s ", buf); - -- buflen = get_device_address(next, &buf, buflen); -+ get_device_address(next, &buf, buflen); -+ get_device_ip6_address(next, &buf, buflen); - fprintf(fp, "%s\n", buf); - - readmem(next+net->dev_next, KVADDR, &next, -@@ -503,7 +512,7 @@ show_net_devices_v2(ulong task) - buf = GETBUF(buflen); - flen = MAX(VADDR_PRLEN, strlen(net->netdevice)); - -- fprintf(fp, "%s NAME IP ADDRESS(ES)\n", -+ fprintf(fp, "%s NAME IP ADDRESS(ES)\n", - mkstring(upper_case(net->netdevice, buf), - flen, CENTER|LJUST, NULL)); - -@@ -528,9 +537,10 @@ show_net_devices_v2(ulong task) - MKSTR(ld->list_ptr[i]))); - - get_device_name(ld->list_ptr[i], buf); -- fprintf(fp, "%-6s ", buf); -+ fprintf(fp, "%-10s ", buf); - -- buflen = get_device_address(ld->list_ptr[i], &buf, buflen); -+ get_device_address(ld->list_ptr[i], &buf, buflen); -+ get_device_ip6_address(ld->list_ptr[i], &buf, buflen); - fprintf(fp, "%s\n", buf); - } - -@@ -556,7 +566,7 @@ show_net_devices_v3(ulong task) - buf = GETBUF(buflen); - flen = MAX(VADDR_PRLEN, strlen(net->netdevice)); - -- fprintf(fp, "%s NAME IP ADDRESS(ES)\n", -+ fprintf(fp, "%s NAME IP ADDRESS(ES)\n", - mkstring(upper_case(net->netdevice, buf), - flen, CENTER|LJUST, NULL)); - -@@ -591,9 +601,10 @@ show_net_devices_v3(ulong task) - MKSTR(ld->list_ptr[i]))); - - get_device_name(ld->list_ptr[i], buf); -- fprintf(fp, "%-6s ", buf); -+ fprintf(fp, "%-10s ", buf); - -- buflen = get_device_address(ld->list_ptr[i], &buf, buflen); -+ get_device_address(ld->list_ptr[i], &buf, buflen); -+ get_device_ip6_address(ld->list_ptr[i], &buf, buflen); - fprintf(fp, "%s\n", buf); - } - -@@ -925,6 +936,86 @@ get_device_address(ulong devaddr, char **bufp, long buflen) - return buflen; - } - -+static void -+get_device_ip6_address(ulong devaddr, char **bufp, long buflen) -+{ -+ ulong ip6_ptr = 0, pos = 0, bufsize = buflen, addr = 0; -+ struct in6_addr ip6_addr; -+ char *buf; -+ char str[INET6_ADDRSTRLEN] = {0}; -+ char buffer[INET6_ADDRSTRLEN + 2] = {0}; -+ uint len = 0; -+ -+ buf = *bufp; -+ pos = strlen(buf); -+ -+ readmem(devaddr + OFFSET(net_device_ip6_ptr), KVADDR, -+ &ip6_ptr, sizeof(ulong), "ip6_ptr", FAULT_ON_ERROR); -+ -+ if (!ip6_ptr) -+ return; -+ -+ /* -+ * 502a2ffd7376 ("ipv6: convert idev_list to list macros") -+ * v2.6.35-rc1~473^2~733 -+ */ -+ if (VALID_MEMBER(inet6_ifaddr_if_list)) { -+ struct list_data list_data, *ld; -+ ulong cnt = 0, i; -+ -+ ld = &list_data; -+ BZERO(ld, sizeof(struct list_data)); -+ ld->flags |= LIST_ALLOCATE; -+ ld->start = ip6_ptr + OFFSET(inet6_dev_addr_list); -+ ld->list_head_offset = OFFSET(inet6_ifaddr_if_list); -+ cnt = do_list(ld); -+ -+ for (i = 1; i < cnt; i++) { -+ -+ addr = ld->list_ptr[i] + OFFSET(inet6_ifaddr_addr); -+ readmem(addr + OFFSET(in6_addr_in6_u), KVADDR, &ip6_addr, -+ sizeof(struct in6_addr), "in6_addr.in6_u", FAULT_ON_ERROR); -+ -+ inet_ntop(AF_INET6, (void*)&ip6_addr, str, INET6_ADDRSTRLEN); -+ sprintf(buffer, "%s%s", pos ? ", " : "", str); -+ len = strlen(buffer); -+ if (pos + len >= bufsize) { -+ RESIZEBUF(*bufp, bufsize, bufsize + buflen); -+ buf = *bufp; -+ BZERO(buf + bufsize, buflen); -+ bufsize += buflen; -+ } -+ BCOPY(buffer, &buf[pos], len); -+ pos += len; -+ } -+ -+ FREEBUF(ld->list_ptr); -+ return; -+ } -+ -+ readmem(ip6_ptr + OFFSET(inet6_dev_addr_list), KVADDR, -+ &addr, sizeof(void *), "inet6_dev.addr_list", FAULT_ON_ERROR); -+ -+ while (addr) { -+ readmem(addr + OFFSET(in6_addr_in6_u), KVADDR, &ip6_addr, -+ sizeof(struct in6_addr), "in6_addr.in6_u", FAULT_ON_ERROR); -+ inet_ntop(AF_INET6, (void*)&ip6_addr, str, INET6_ADDRSTRLEN); -+ sprintf(buffer, "%s%s", pos ? ", " : "", str); -+ len = strlen(buffer); -+ -+ if (pos + len >= bufsize) { -+ RESIZEBUF(*bufp, bufsize, bufsize + buflen); -+ buf = *bufp; -+ BZERO(buf + bufsize, buflen); -+ bufsize += buflen; -+ } -+ BCOPY(buffer, &buf[pos], len); -+ pos += len; -+ readmem(addr + OFFSET(inet6_ifaddr_if_next), KVADDR, &addr, -+ sizeof(void *), "inet6_ifaddr.if_next", FAULT_ON_ERROR); -+ } -+} -+ - /* - * Get the family, type, local and destination address/port pairs. - */ -diff --git a/symbols.c b/symbols.c -index a974fc9141a0..28846d06273c 100644 ---- a/symbols.c -+++ b/symbols.c -@@ -9787,6 +9787,7 @@ dump_offset_table(char *spec, ulong makestruct) - OFFSET(net_device_addr_len)); - fprintf(fp, " net_device_ip_ptr: %ld\n", - OFFSET(net_device_ip_ptr)); -+ fprintf(fp, " net_device_ip6_ptr: %ld\n", OFFSET(net_device_ip6_ptr)); - fprintf(fp, " net_device_dev_list: %ld\n", - OFFSET(net_device_dev_list)); - fprintf(fp, " net_dev_base_head: %ld\n", -@@ -9839,6 +9840,11 @@ dump_offset_table(char *spec, ulong makestruct) - fprintf(fp, " inet_opt_num: %ld\n", - OFFSET(inet_opt_num)); - -+ fprintf(fp, " inet6_dev_addr_list: %ld\n", OFFSET(inet6_dev_addr_list)); -+ fprintf(fp, " inet6_ifaddr_addr: %ld\n", OFFSET(inet6_ifaddr_addr)); -+ fprintf(fp, " inet6_ifaddr_if_list: %ld\n", OFFSET(inet6_ifaddr_if_list)); -+ fprintf(fp, " inet6_ifaddr_if_next: %ld\n", OFFSET(inet6_ifaddr_if_next)); -+ fprintf(fp, " in6_addr_in6_u: %ld\n", OFFSET(in6_addr_in6_u)); - fprintf(fp, " ipv6_pinfo_rcv_saddr: %ld\n", - OFFSET(ipv6_pinfo_rcv_saddr)); - fprintf(fp, " ipv6_pinfo_daddr: %ld\n", --- -2.37.1 - diff --git a/0038-Fix-C99-compatibility-issues-in-embedded-copy-of-GDB.patch b/0038-Fix-C99-compatibility-issues-in-embedded-copy-of-GDB.patch deleted file mode 100644 index e83632f..0000000 --- a/0038-Fix-C99-compatibility-issues-in-embedded-copy-of-GDB.patch +++ /dev/null @@ -1,1071 +0,0 @@ -From 57dda56af5c78da5e79cc4a83839e86d3ff6ab43 Mon Sep 17 00:00:00 2001 -From: Florian Weimer -Date: Tue, 14 Feb 2023 08:06:39 +0100 -Subject: [PATCH 10/12] Fix C99 compatibility issues in embedded copy of GDB - -These issues have been fixed in upstream GDB already: - -In the file bfd/elf-bfd.h, startswith is now used in stead of -strncmp. libiberty was fixed via an import from GCC. Readline -8.1 has been imported and has these issues fixed upstream. - -While at it, also update the bundled copy of in -gnulib. This header file unfortunately shadows the glibc version, -causing build failures on ppc64le if it is too old. - -Related GDB commits: -0075c53724f7 Impport libiberty commit: 885b6660c17f from gcc mainline. -b4f26d541aa7 Import GNU Readline 8.1 -9c9d63b15ad5 gnulib: update to 776af40e0 -3f3328b816ee Use startswith more for strncmp function calls. - -Related glibc commit: -2337e04e21ba cdefs: Limit definition of fortification macros - -Related gnulib commit: -afeeb21058d1 libc-config: fix include problem on older Debian - -Signed-off-by: Florian Weimer -Signed-off-by: Kazuhito Hagio ---- - gdb-10.2.patch | 1027 ++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 1027 insertions(+) - -diff --git a/gdb-10.2.patch b/gdb-10.2.patch -index aa34743501ad..5089df9e72e1 100644 ---- a/gdb-10.2.patch -+++ b/gdb-10.2.patch -@@ -2078,3 +2078,1030 @@ exit 0 - - return new_type; - } -+--- gdb-10.2/bfd/elf-bfd.h.orig -++++ gdb-10.2/bfd/elf-bfd.h -+@@ -27,6 +27,8 @@ -+ #include "elf/internal.h" -+ #include "bfdlink.h" -+ -++#include -++ -+ #ifdef __cplusplus -+ extern "C" { -+ #endif -+--- gdb-10.2/gnulib/import/cdefs.h.orig -++++ gdb-10.2/gnulib/import/cdefs.h -+@@ -1,17 +1,18 @@ -+-/* Copyright (C) 1992-2020 Free Software Foundation, Inc. -++/* Copyright (C) 1992-2023 Free Software Foundation, Inc. -++ Copyright The GNU Toolchain Authors. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+- modify it under the terms of the GNU General Public -++ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+- version 3 of the License, or (at your option) any later version. -++ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+- General Public License for more details. -++ Lesser General Public License for more details. -+ -+- You should have received a copy of the GNU General Public -++ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+@@ -25,16 +26,38 @@ -+ -+ /* The GNU libc does not support any K&R compilers or the traditional mode -+ of ISO C compilers anymore. Check for some of the combinations not -+- anymore supported. */ -+-#if defined __GNUC__ && !defined __STDC__ -+-# error "You need a ISO C conforming compiler to use the glibc headers" -++ supported anymore. */ -++#if defined __GNUC__ && !defined __STDC__ && !defined __cplusplus -++# error "You need a ISO C or C++ conforming compiler to use the glibc headers" -+ #endif -+ -+ /* Some user header file might have defined this before. */ -+ #undef __P -+ #undef __PMT -+ -+-#ifdef __GNUC__ -++/* Compilers that lack __has_attribute may object to -++ #if defined __has_attribute && __has_attribute (...) -++ even though they do not need to evaluate the right-hand side of the &&. -++ Similarly for __has_builtin, etc. */ -++#if (defined __has_attribute \ -++ && (!defined __clang_minor__ \ -++ || 3 < __clang_major__ + (5 <= __clang_minor__))) -++# define __glibc_has_attribute(attr) __has_attribute (attr) -++#else -++# define __glibc_has_attribute(attr) 0 -++#endif -++#ifdef __has_builtin -++# define __glibc_has_builtin(name) __has_builtin (name) -++#else -++# define __glibc_has_builtin(name) 0 -++#endif -++#ifdef __has_extension -++# define __glibc_has_extension(ext) __has_extension (ext) -++#else -++# define __glibc_has_extension(ext) 0 -++#endif -++ -++#if defined __GNUC__ || defined __clang__ -+ -+ /* All functions, except those with callbacks or those that -+ synchronize memory, are leaf functions. */ -+@@ -47,21 +70,26 @@ -+ # endif -+ -+ /* GCC can always grok prototypes. For C++ programs we add throw() -+- to help it optimize the function calls. But this works only with -+- gcc 2.8.x and egcs. For gcc 3.2 and up we even mark C functions -++ to help it optimize the function calls. But this only works with -++ gcc 2.8.x and egcs. For gcc 3.4 and up we even mark C functions -+ as non-throwing using a function attribute since programs can use -+ the -fexceptions options for C code as well. */ -+-# if !defined __cplusplus && __GNUC_PREREQ (3, 3) -++# if !defined __cplusplus \ -++ && (__GNUC_PREREQ (3, 4) || __glibc_has_attribute (__nothrow__)) -+ # define __THROW __attribute__ ((__nothrow__ __LEAF)) -+ # define __THROWNL __attribute__ ((__nothrow__)) -+ # define __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct -+ # define __NTHNL(fct) __attribute__ ((__nothrow__)) fct -+ # else -+-# if defined __cplusplus && __GNUC_PREREQ (2,8) -+-# define __THROW throw () -+-# define __THROWNL throw () -+-# define __NTH(fct) __LEAF_ATTR fct throw () -+-# define __NTHNL(fct) fct throw () -++# if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major >= 4) -++# if __cplusplus >= 201103L -++# define __THROW noexcept (true) -++# else -++# define __THROW throw () -++# endif -++# define __THROWNL __THROW -++# define __NTH(fct) __LEAF_ATTR fct __THROW -++# define __NTHNL(fct) fct __THROW -+ # else -+ # define __THROW -+ # define __THROWNL -+@@ -70,7 +98,7 @@ -+ # endif -+ # endif -+ -+-#else /* Not GCC. */ -++#else /* Not GCC or clang. */ -+ -+ # if (defined __cplusplus \ -+ || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) -+@@ -83,16 +111,7 @@ -+ # define __THROWNL -+ # define __NTH(fct) fct -+ -+-#endif /* GCC. */ -+- -+-/* Compilers that are not clang may object to -+- #if defined __clang__ && __has_extension(...) -+- even though they do not need to evaluate the right-hand side of the &&. */ -+-#if defined __clang__ && defined __has_extension -+-# define __glibc_clang_has_extension(ext) __has_extension (ext) -+-#else -+-# define __glibc_clang_has_extension(ext) 0 -+-#endif -++#endif /* GCC || clang. */ -+ -+ /* These two macros are not used in glibc anymore. They are kept here -+ only because some other projects expect the macros to be defined. */ -+@@ -123,14 +142,70 @@ -+ #define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1) -+ #define __bos0(ptr) __builtin_object_size (ptr, 0) -+ -++/* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available. */ -++#if __USE_FORTIFY_LEVEL == 3 && (__glibc_clang_prereq (9, 0) \ -++ || __GNUC_PREREQ (12, 0)) -++# define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0) -++# define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1) -++#else -++# define __glibc_objsize0(__o) __bos0 (__o) -++# define __glibc_objsize(__o) __bos (__o) -++#endif -++ -++#if __USE_FORTIFY_LEVEL > 0 -++/* Compile time conditions to choose between the regular, _chk and _chk_warn -++ variants. These conditions should get evaluated to constant and optimized -++ away. */ -++ -++#define __glibc_safe_len_cond(__l, __s, __osz) ((__l) <= (__osz) / (__s)) -++#define __glibc_unsigned_or_positive(__l) \ -++ ((__typeof (__l)) 0 < (__typeof (__l)) -1 \ -++ || (__builtin_constant_p (__l) && (__l) > 0)) -++ -++/* Length is known to be safe at compile time if the __L * __S <= __OBJSZ -++ condition can be folded to a constant and if it is true, or unknown (-1) */ -++#define __glibc_safe_or_unknown_len(__l, __s, __osz) \ -++ ((__builtin_constant_p (__osz) && (__osz) == (__SIZE_TYPE__) -1) \ -++ || (__glibc_unsigned_or_positive (__l) \ -++ && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ -++ (__s), (__osz))) \ -++ && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), (__s), (__osz)))) -++ -++/* Conversely, we know at compile time that the length is unsafe if the -++ __L * __S <= __OBJSZ condition can be folded to a constant and if it is -++ false. */ -++#define __glibc_unsafe_len(__l, __s, __osz) \ -++ (__glibc_unsigned_or_positive (__l) \ -++ && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ -++ __s, __osz)) \ -++ && !__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz)) -++ -++/* Fortify function f. __f_alias, __f_chk and __f_chk_warn must be -++ declared. */ -++ -++#define __glibc_fortify(f, __l, __s, __osz, ...) \ -++ (__glibc_safe_or_unknown_len (__l, __s, __osz) \ -++ ? __ ## f ## _alias (__VA_ARGS__) \ -++ : (__glibc_unsafe_len (__l, __s, __osz) \ -++ ? __ ## f ## _chk_warn (__VA_ARGS__, __osz) \ -++ : __ ## f ## _chk (__VA_ARGS__, __osz))) -++ -++/* Fortify function f, where object size argument passed to f is the number of -++ elements and not total size. */ -++ -++#define __glibc_fortify_n(f, __l, __s, __osz, ...) \ -++ (__glibc_safe_or_unknown_len (__l, __s, __osz) \ -++ ? __ ## f ## _alias (__VA_ARGS__) \ -++ : (__glibc_unsafe_len (__l, __s, __osz) \ -++ ? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s)) \ -++ : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s)))) -++#endif -++ -+ #if __GNUC_PREREQ (4,3) -+-# define __warndecl(name, msg) \ -+- extern void name (void) __attribute__((__warning__ (msg))) -+ # define __warnattr(msg) __attribute__((__warning__ (msg))) -+ # define __errordecl(name, msg) \ -+ extern void name (void) __attribute__((__error__ (msg))) -+ #else -+-# define __warndecl(name, msg) extern void name (void) -+ # define __warnattr(msg) -+ # define __errordecl(name, msg) extern void name (void) -+ #endif -+@@ -142,8 +217,8 @@ -+ #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L && !defined __HP_cc -+ # define __flexarr [] -+ # define __glibc_c99_flexarr_available 1 -+-#elif __GNUC_PREREQ (2,97) -+-/* GCC 2.97 supports C99 flexible array members as an extension, -++#elif __GNUC_PREREQ (2,97) || defined __clang__ -++/* GCC 2.97 and clang support C99 flexible array members as an extension, -+ even when in C89 mode or compiling C++ (any version). */ -+ # define __flexarr [] -+ # define __glibc_c99_flexarr_available 1 -+@@ -169,7 +244,7 @@ -+ Example: -+ int __REDIRECT(setpgrp, (__pid_t pid, __pid_t pgrp), setpgid); */ -+ -+-#if defined __GNUC__ && __GNUC__ >= 2 -++#if (defined __GNUC__ && __GNUC__ >= 2) || (__clang_major__ >= 4) -+ -+ # define __REDIRECT(name, proto, alias) name proto __asm__ (__ASMNAME (#alias)) -+ # ifdef __cplusplus -+@@ -194,17 +269,17 @@ -+ */ -+ #endif -+ -+-/* GCC has various useful declarations that can be made with the -+- `__attribute__' syntax. All of the ways we use this do fine if -+- they are omitted for compilers that don't understand it. */ -+-#if !defined __GNUC__ || __GNUC__ < 2 -++/* GCC and clang have various useful declarations that can be made with -++ the '__attribute__' syntax. All of the ways we use this do fine if -++ they are omitted for compilers that don't understand it. */ -++#if !(defined __GNUC__ || defined __clang__) -+ # define __attribute__(xyz) /* Ignore */ -+ #endif -+ -+ /* At some point during the gcc 2.96 development the `malloc' attribute -+ for functions was introduced. We don't want to use it unconditionally -+ (although this would be possible) since it generates warnings. */ -+-#if __GNUC_PREREQ (2,96) -++#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__malloc__) -+ # define __attribute_malloc__ __attribute__ ((__malloc__)) -+ #else -+ # define __attribute_malloc__ /* Ignore */ -+@@ -219,26 +294,41 @@ -+ # define __attribute_alloc_size__(params) /* Ignore. */ -+ #endif -+ -++/* Tell the compiler which argument to an allocation function -++ indicates the alignment of the allocation. */ -++#if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__alloc_align__) -++# define __attribute_alloc_align__(param) \ -++ __attribute__ ((__alloc_align__ param)) -++#else -++# define __attribute_alloc_align__(param) /* Ignore. */ -++#endif -++ -+ /* At some point during the gcc 2.96 development the `pure' attribute -+ for functions was introduced. We don't want to use it unconditionally -+ (although this would be possible) since it generates warnings. */ -+-#if __GNUC_PREREQ (2,96) -++#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__pure__) -+ # define __attribute_pure__ __attribute__ ((__pure__)) -+ #else -+ # define __attribute_pure__ /* Ignore */ -+ #endif -+ -+ /* This declaration tells the compiler that the value is constant. */ -+-#if __GNUC_PREREQ (2,5) -++#if __GNUC_PREREQ (2,5) || __glibc_has_attribute (__const__) -+ # define __attribute_const__ __attribute__ ((__const__)) -+ #else -+ # define __attribute_const__ /* Ignore */ -+ #endif -+ -++#if __GNUC_PREREQ (2,7) || __glibc_has_attribute (__unused__) -++# define __attribute_maybe_unused__ __attribute__ ((__unused__)) -++#else -++# define __attribute_maybe_unused__ /* Ignore */ -++#endif -++ -+ /* At some point during the gcc 3.1 development the `used' attribute -+ for functions was introduced. We don't want to use it unconditionally -+ (although this would be possible) since it generates warnings. */ -+-#if __GNUC_PREREQ (3,1) -++#if __GNUC_PREREQ (3,1) || __glibc_has_attribute (__used__) -+ # define __attribute_used__ __attribute__ ((__used__)) -+ # define __attribute_noinline__ __attribute__ ((__noinline__)) -+ #else -+@@ -247,7 +337,7 @@ -+ #endif -+ -+ /* Since version 3.2, gcc allows marking deprecated functions. */ -+-#if __GNUC_PREREQ (3,2) -++#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__deprecated__) -+ # define __attribute_deprecated__ __attribute__ ((__deprecated__)) -+ #else -+ # define __attribute_deprecated__ /* Ignore */ -+@@ -256,8 +346,8 @@ -+ /* Since version 4.5, gcc also allows one to specify the message printed -+ when a deprecated function is used. clang claims to be gcc 4.2, but -+ may also support this feature. */ -+-#if __GNUC_PREREQ (4,5) || \ -+- __glibc_clang_has_extension (__attribute_deprecated_with_message__) -++#if __GNUC_PREREQ (4,5) \ -++ || __glibc_has_extension (__attribute_deprecated_with_message__) -+ # define __attribute_deprecated_msg__(msg) \ -+ __attribute__ ((__deprecated__ (msg))) -+ #else -+@@ -270,7 +360,7 @@ -+ If several `format_arg' attributes are given for the same function, in -+ gcc-3.0 and older, all but the last one are ignored. In newer gccs, -+ all designated arguments are considered. */ -+-#if __GNUC_PREREQ (2,8) -++#if __GNUC_PREREQ (2,8) || __glibc_has_attribute (__format_arg__) -+ # define __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x))) -+ #else -+ # define __attribute_format_arg__(x) /* Ignore */ -+@@ -280,7 +370,7 @@ -+ attribute for functions was introduced. We don't want to use it -+ unconditionally (although this would be possible) since it -+ generates warnings. */ -+-#if __GNUC_PREREQ (2,97) -++#if __GNUC_PREREQ (2,97) || __glibc_has_attribute (__format__) -+ # define __attribute_format_strfmon__(a,b) \ -+ __attribute__ ((__format__ (__strfmon__, a, b))) -+ #else -+@@ -288,19 +378,33 @@ -+ #endif -+ -+ /* The nonnull function attribute marks pointer parameters that -+- must not be NULL. Do not define __nonnull if it is already defined, -+- for portability when this file is used in Gnulib. */ -++ must not be NULL. This has the name __nonnull in glibc, -++ and __attribute_nonnull__ in files shared with Gnulib to avoid -++ collision with a different __nonnull in DragonFlyBSD 5.9. */ -++#ifndef __attribute_nonnull__ -++# if __GNUC_PREREQ (3,3) || __glibc_has_attribute (__nonnull__) -++# define __attribute_nonnull__(params) __attribute__ ((__nonnull__ params)) -++# else -++# define __attribute_nonnull__(params) -++# endif -++#endif -+ #ifndef __nonnull -+-# if __GNUC_PREREQ (3,3) -+-# define __nonnull(params) __attribute__ ((__nonnull__ params)) -++# define __nonnull(params) __attribute_nonnull__ (params) -++#endif -++ -++/* The returns_nonnull function attribute marks the return type of the function -++ as always being non-null. */ -++#ifndef __returns_nonnull -++# if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__returns_nonnull__) -++# define __returns_nonnull __attribute__ ((__returns_nonnull__)) -+ # else -+-# define __nonnull(params) -++# define __returns_nonnull -+ # endif -+ #endif -+ -+ /* If fortification mode, we warn about unused results of certain -+ function calls which can lead to problems. */ -+-#if __GNUC_PREREQ (3,4) -++#if __GNUC_PREREQ (3,4) || __glibc_has_attribute (__warn_unused_result__) -+ # define __attribute_warn_unused_result__ \ -+ __attribute__ ((__warn_unused_result__)) -+ # if defined __USE_FORTIFY_LEVEL && __USE_FORTIFY_LEVEL > 0 -+@@ -314,7 +418,7 @@ -+ #endif -+ -+ /* Forces a function to be always inlined. */ -+-#if __GNUC_PREREQ (3,2) -++#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__always_inline__) -+ /* The Linux kernel defines __always_inline in stddef.h (283d7573), and -+ it conflicts with this definition. Therefore undefine it first to -+ allow either header to be included first. */ -+@@ -327,7 +431,7 @@ -+ -+ /* Associate error messages with the source location of the call site rather -+ than with the source location inside the function. */ -+-#if __GNUC_PREREQ (4,3) -++#if __GNUC_PREREQ (4,3) || __glibc_has_attribute (__artificial__) -+ # define __attribute_artificial__ __attribute__ ((__artificial__)) -+ #else -+ # define __attribute_artificial__ /* Ignore */ -+@@ -370,12 +474,14 @@ -+ run in pedantic mode if the uses are carefully marked using the -+ `__extension__' keyword. But this is not generally available before -+ version 2.8. */ -+-#if !__GNUC_PREREQ (2,8) -++#if !(__GNUC_PREREQ (2,8) || defined __clang__) -+ # define __extension__ /* Ignore */ -+ #endif -+ -+-/* __restrict is known in EGCS 1.2 and above. */ -+-#if !__GNUC_PREREQ (2,92) -++/* __restrict is known in EGCS 1.2 and above, and in clang. -++ It works also in C++ mode (outside of arrays), but only when spelled -++ as '__restrict', not 'restrict'. */ -++#if !(__GNUC_PREREQ (2,92) || __clang_major__ >= 3) -+ # if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L -+ # define __restrict restrict -+ # else -+@@ -385,8 +491,9 @@ -+ -+ /* ISO C99 also allows to declare arrays as non-overlapping. The syntax is -+ array_name[restrict] -+- GCC 3.1 supports this. */ -+-#if __GNUC_PREREQ (3,1) && !defined __GNUG__ -++ GCC 3.1 and clang support this. -++ This syntax is not usable in C++ mode. */ -++#if (__GNUC_PREREQ (3,1) || __clang_major__ >= 3) && !defined __cplusplus -+ # define __restrict_arr __restrict -+ #else -+ # ifdef __GNUC__ -+@@ -401,7 +508,7 @@ -+ # endif -+ #endif -+ -+-#if __GNUC__ >= 3 -++#if (__GNUC__ >= 3) || __glibc_has_builtin (__builtin_expect) -+ # define __glibc_unlikely(cond) __builtin_expect ((cond), 0) -+ # define __glibc_likely(cond) __builtin_expect ((cond), 1) -+ #else -+@@ -409,15 +516,10 @@ -+ # define __glibc_likely(cond) (cond) -+ #endif -+ -+-#ifdef __has_attribute -+-# define __glibc_has_attribute(attr) __has_attribute (attr) -+-#else -+-# define __glibc_has_attribute(attr) 0 -+-#endif -+- -+ #if (!defined _Noreturn \ -+ && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \ -+- && !__GNUC_PREREQ (4,7)) -++ && !(__GNUC_PREREQ (4,7) \ -++ || (3 < __clang_major__ + (5 <= __clang_minor__)))) -+ # if __GNUC_PREREQ (2,8) -+ # define _Noreturn __attribute__ ((__noreturn__)) -+ # else -+@@ -434,22 +536,63 @@ -+ # define __attribute_nonstring__ -+ #endif -+ -++/* Undefine (also defined in libc-symbols.h). */ -++#undef __attribute_copy__ -++#if __GNUC_PREREQ (9, 0) -++/* Copies attributes from the declaration or type referenced by -++ the argument. */ -++# define __attribute_copy__(arg) __attribute__ ((__copy__ (arg))) -++#else -++# define __attribute_copy__(arg) -++#endif -++ -+ #if (!defined _Static_assert && !defined __cplusplus \ -+ && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \ -+- && (!__GNUC_PREREQ (4, 6) || defined __STRICT_ANSI__)) -++ && (!(__GNUC_PREREQ (4, 6) || __clang_major__ >= 4) \ -++ || defined __STRICT_ANSI__)) -+ # define _Static_assert(expr, diagnostic) \ -+ extern int (*__Static_assert_function (void)) \ -+ [!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })] -+ #endif -+ -+-/* The #ifndef lets Gnulib avoid including these on non-glibc -+- platforms, where the includes typically do not exist. */ -+-#ifndef __WORDSIZE -++/* Gnulib avoids including these, as they don't work on non-glibc or -++ older glibc platforms. */ -++#ifndef __GNULIB_CDEFS -+ # include -+ # include -+ #endif -+ -+-#if defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH -++#if __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1 -++# ifdef __REDIRECT -++ -++/* Alias name defined automatically. */ -++# define __LDBL_REDIR(name, proto) ... unused__ldbl_redir -++# define __LDBL_REDIR_DECL(name) \ -++ extern __typeof (name) name __asm (__ASMNAME ("__" #name "ieee128")); -++ -++/* Alias name defined automatically, with leading underscores. */ -++# define __LDBL_REDIR2_DECL(name) \ -++ extern __typeof (__##name) __##name \ -++ __asm (__ASMNAME ("__" #name "ieee128")); -++ -++/* Alias name defined manually. */ -++# define __LDBL_REDIR1(name, proto, alias) ... unused__ldbl_redir1 -++# define __LDBL_REDIR1_DECL(name, alias) \ -++ extern __typeof (name) name __asm (__ASMNAME (#alias)); -++ -++# define __LDBL_REDIR1_NTH(name, proto, alias) \ -++ __REDIRECT_NTH (name, proto, alias) -++# define __REDIRECT_NTH_LDBL(name, proto, alias) \ -++ __LDBL_REDIR1_NTH (name, proto, __##alias##ieee128) -++ -++/* Unused. */ -++# define __REDIRECT_LDBL(name, proto, alias) ... unused__redirect_ldbl -++# define __LDBL_REDIR_NTH(name, proto) ... unused__ldbl_redir_nth -++ -++# else -++_Static_assert (0, "IEEE 128-bits long double requires redirection on this platform"); -++# endif -++#elif defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH -+ # define __LDBL_COMPAT 1 -+ # ifdef __REDIRECT -+ # define __LDBL_REDIR1(name, proto, alias) __REDIRECT (name, proto, alias) -+@@ -458,6 +601,8 @@ -+ # define __LDBL_REDIR1_NTH(name, proto, alias) __REDIRECT_NTH (name, proto, alias) -+ # define __LDBL_REDIR_NTH(name, proto) \ -+ __LDBL_REDIR1_NTH (name, proto, __nldbl_##name) -++# define __LDBL_REDIR2_DECL(name) \ -++ extern __typeof (__##name) __##name __asm (__ASMNAME ("__nldbl___" #name)); -+ # define __LDBL_REDIR1_DECL(name, alias) \ -+ extern __typeof (name) name __asm (__ASMNAME (#alias)); -+ # define __LDBL_REDIR_DECL(name) \ -+@@ -468,11 +613,13 @@ -+ __LDBL_REDIR1_NTH (name, proto, __nldbl_##alias) -+ # endif -+ #endif -+-#if !defined __LDBL_COMPAT || !defined __REDIRECT -++#if (!defined __LDBL_COMPAT && __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 0) \ -++ || !defined __REDIRECT -+ # define __LDBL_REDIR1(name, proto, alias) name proto -+ # define __LDBL_REDIR(name, proto) name proto -+ # define __LDBL_REDIR1_NTH(name, proto, alias) name proto __THROW -+ # define __LDBL_REDIR_NTH(name, proto) name proto __THROW -++# define __LDBL_REDIR2_DECL(name) -+ # define __LDBL_REDIR_DECL(name) -+ # ifdef __REDIRECT -+ # define __REDIRECT_LDBL(name, proto, alias) __REDIRECT (name, proto, alias) -+@@ -503,7 +650,7 @@ -+ check is required to enable the use of generic selection. */ -+ #if !defined __cplusplus \ -+ && (__GNUC_PREREQ (4, 9) \ -+- || __glibc_clang_has_extension (c_generic_selections) \ -++ || __glibc_has_extension (c_generic_selections) \ -+ || (!defined __GNUC__ && defined __STDC_VERSION__ \ -+ && __STDC_VERSION__ >= 201112L)) -+ # define __HAVE_GENERIC_SELECTION 1 -+@@ -511,4 +658,50 @@ -+ # define __HAVE_GENERIC_SELECTION 0 -+ #endif -+ -++#if __GNUC_PREREQ (10, 0) -++/* Designates a 1-based positional argument ref-index of pointer type -++ that can be used to access size-index elements of the pointed-to -++ array according to access mode, or at least one element when -++ size-index is not provided: -++ access (access-mode, [, ]) */ -++# define __attr_access(x) __attribute__ ((__access__ x)) -++/* For _FORTIFY_SOURCE == 3 we use __builtin_dynamic_object_size, which may -++ use the access attribute to get object sizes from function definition -++ arguments, so we can't use them on functions we fortify. Drop the object -++ size hints for such functions. */ -++# if __USE_FORTIFY_LEVEL == 3 -++# define __fortified_attr_access(a, o, s) __attribute__ ((__access__ (a, o))) -++# else -++# define __fortified_attr_access(a, o, s) __attr_access ((a, o, s)) -++# endif -++# if __GNUC_PREREQ (11, 0) -++# define __attr_access_none(argno) __attribute__ ((__access__ (__none__, argno))) -++# else -++# define __attr_access_none(argno) -++# endif -++#else -++# define __fortified_attr_access(a, o, s) -++# define __attr_access(x) -++# define __attr_access_none(argno) -++#endif -++ -++#if __GNUC_PREREQ (11, 0) -++/* Designates dealloc as a function to call to deallocate objects -++ allocated by the declared function. */ -++# define __attr_dealloc(dealloc, argno) \ -++ __attribute__ ((__malloc__ (dealloc, argno))) -++# define __attr_dealloc_free __attr_dealloc (__builtin_free, 1) -++#else -++# define __attr_dealloc(dealloc, argno) -++# define __attr_dealloc_free -++#endif -++ -++/* Specify that a function such as setjmp or vfork may return -++ twice. */ -++#if __GNUC_PREREQ (4, 1) -++# define __attribute_returns_twice__ __attribute__ ((__returns_twice__)) -++#else -++# define __attribute_returns_twice__ /* Ignore. */ -++#endif -++ -+ #endif /* sys/cdefs.h */ -+--- gdb-10.2/gnulib/import/libc-config.h.orig -++++ gdb-10.2/gnulib/import/libc-config.h -+@@ -79,13 +79,9 @@ -+ #ifndef _FEATURES_H -+ # define _FEATURES_H 1 -+ #endif -+-/* Define __WORDSIZE so that does not attempt to include -+- nonexistent files. Make it a syntax error, since Gnulib does not -+- use __WORDSIZE now, and if Gnulib uses it later the syntax error -+- will let us know that __WORDSIZE needs configuring. */ -+-#ifndef __WORDSIZE -+-# define __WORDSIZE %%% -+-#endif -++/* Define __GNULIB_CDEFS so that does not attempt to include -++ nonexistent files. */ -++# define __GNULIB_CDEFS -+ /* Undef the macros unconditionally defined by our copy of glibc -+ , so that they do not clash with any system-defined -+ versions. */ -+--- gdb-10.2/libiberty/aclocal.m4.orig -++++ gdb-10.2/libiberty/aclocal.m4 -+@@ -16,6 +16,8 @@ AC_CACHE_CHECK([for working strncmp], ac -+ [AC_TRY_RUN([ -+ /* Test by Jim Wilson and Kaveh Ghazi. -+ Check whether strncmp reads past the end of its string parameters. */ -++#include -++#include -+ #include -+ -+ #ifdef HAVE_FCNTL_H -+@@ -43,7 +45,8 @@ AC_CACHE_CHECK([for working strncmp], ac -+ -+ #define MAP_LEN 0x10000 -+ -+-main () -++int -++main (void) -+ { -+ #if defined(HAVE_MMAP) || defined(HAVE_MMAP_ANYWHERE) -+ char *p; -+@@ -149,7 +152,10 @@ if test $ac_cv_os_cray = yes; then -+ fi -+ -+ AC_CACHE_CHECK(stack direction for C alloca, ac_cv_c_stack_direction, -+-[AC_TRY_RUN([find_stack_direction () -++[AC_TRY_RUN([#include -++ -++int -++find_stack_direction (void) -+ { -+ static char *addr = 0; -+ auto char dummy; -+@@ -161,7 +167,9 @@ AC_CACHE_CHECK(stack direction for C all -+ else -+ return (&dummy > addr) ? 1 : -1; -+ } -+-main () -++ -++int -++main (void) -+ { -+ exit (find_stack_direction() < 0); -+ }], -+--- gdb-10.2/libiberty/configure.orig -++++ gdb-10.2/libiberty/configure -+@@ -6724,7 +6724,10 @@ else -+ else -+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+ /* end confdefs.h. */ -+-find_stack_direction () -++#include -++ -++int -++find_stack_direction (void) -+ { -+ static char *addr = 0; -+ auto char dummy; -+@@ -6736,7 +6739,9 @@ find_stack_direction () -+ else -+ return (&dummy > addr) ? 1 : -1; -+ } -+-main () -++ -++int -++main (void) -+ { -+ exit (find_stack_direction() < 0); -+ } -+@@ -7557,6 +7562,8 @@ else -+ -+ /* Test by Jim Wilson and Kaveh Ghazi. -+ Check whether strncmp reads past the end of its string parameters. */ -++#include -++#include -+ #include -+ -+ #ifdef HAVE_FCNTL_H -+@@ -7584,7 +7591,8 @@ else -+ -+ #define MAP_LEN 0x10000 -+ -+-main () -++int -++main (void) -+ { -+ #if defined(HAVE_MMAP) || defined(HAVE_MMAP_ANYWHERE) -+ char *p; -+--- gdb-10.2/readline/readline/aclocal.m4.orig -++++ gdb-10.2/readline/readline/aclocal.m4 -+@@ -10,6 +10,7 @@ AC_DEFUN(BASH_C_LONG_LONG, -+ ac_cv_c_long_long=yes -+ else -+ AC_TRY_RUN([ -++#include -+ int -+ main() -+ { -+@@ -33,6 +34,7 @@ AC_DEFUN(BASH_C_LONG_DOUBLE, -+ ac_cv_c_long_double=yes -+ else -+ AC_TRY_RUN([ -++#include -+ int -+ main() -+ { -+@@ -134,6 +136,8 @@ typedef int (*_bashfunc)(const char *, . -+ #else -+ typedef int (*_bashfunc)(); -+ #endif -++#include -++int -+ main() -+ { -+ _bashfunc pf; -+@@ -191,9 +195,11 @@ AC_CACHE_VAL(bash_cv_under_sys_siglist, -+ #ifdef HAVE_UNISTD_H -+ #include -+ #endif -++#include -+ #ifndef UNDER_SYS_SIGLIST_DECLARED -+ extern char *_sys_siglist[]; -+ #endif -++int -+ main() -+ { -+ char *msg = (char *)_sys_siglist[2]; -+@@ -218,9 +224,11 @@ AC_CACHE_VAL(bash_cv_sys_siglist, -+ #ifdef HAVE_UNISTD_H -+ #include -+ #endif -++#include -+ #if !HAVE_DECL_SYS_SIGLIST -+ extern char *sys_siglist[]; -+ #endif -++int -+ main() -+ { -+ char *msg = sys_siglist[2]; -+@@ -273,6 +281,8 @@ AC_CACHE_VAL(bash_cv_dup2_broken, -+ [AC_TRY_RUN([ -+ #include -+ #include -++#include -++int -+ main() -+ { -+ int fd1, fd2, fl; -+@@ -335,6 +345,8 @@ AC_CACHE_VAL(bash_cv_opendir_not_robust, -+ # include -+ # endif -+ #endif /* HAVE_DIRENT_H */ -++#include -++int -+ main() -+ { -+ DIR *dir; -+@@ -514,6 +526,8 @@ AC_TRY_RUN([ -+ #include -+ #include -+ #include -++#include -++int -+ main() -+ { -+ #ifdef HAVE_QUAD_T -+@@ -583,6 +597,7 @@ AC_CACHE_VAL(bash_cv_getenv_redef, -+ #ifdef HAVE_UNISTD_H -+ # include -+ #endif -++#include -+ #ifndef __STDC__ -+ # ifndef const -+ # define const -+@@ -598,6 +613,7 @@ getenv (name) -+ { -+ return "42"; -+ } -++int -+ main() -+ { -+ char *s; -+@@ -786,7 +802,9 @@ AC_CACHE_VAL(bash_cv_func_sigsetjmp, -+ #include -+ #include -+ #include -++#include -+ -++int -+ main() -+ { -+ #if !defined (_POSIX_VERSION) || !defined (HAVE_POSIX_SIGNALS) -+@@ -835,7 +853,10 @@ AC_CACHE_VAL(bash_cv_func_strcoll_broken -+ #if defined (HAVE_LOCALE_H) -+ #include -+ #endif -++#include -++#include -+ -++int -+ main(c, v) -+ int c; -+ char *v[]; -+@@ -881,6 +902,7 @@ AC_CACHE_VAL(bash_cv_printf_a_format, -+ [AC_TRY_RUN([ -+ #include -+ #include -++#include -+ -+ int -+ main() -+@@ -1241,6 +1263,8 @@ AC_CACHE_VAL(bash_cv_pgrp_pipe, -+ #ifdef HAVE_UNISTD_H -+ # include -+ #endif -++#include -++int -+ main() -+ { -+ # ifdef GETPGRP_VOID -+@@ -1305,6 +1329,7 @@ AC_CACHE_VAL(bash_cv_must_reinstall_sigh -+ #ifdef HAVE_UNISTD_H -+ #include -+ #endif -++#include -+ -+ typedef RETSIGTYPE sigfunc(); -+ -+@@ -1335,6 +1360,7 @@ int s; -+ nsigint++; -+ } -+ -++int -+ main() -+ { -+ nsigint = 0; -+@@ -1418,8 +1444,11 @@ AC_CACHE_VAL(bash_cv_sys_named_pipes, -+ #ifdef HAVE_UNISTD_H -+ #include -+ #endif -++#include -++#include -+ -+ /* Add more tests in here as appropriate. */ -++int -+ main() -+ { -+ int fd, err; -+@@ -1651,11 +1680,13 @@ AC_CACHE_VAL(bash_cv_unusable_rtsigs, -+ [AC_TRY_RUN([ -+ #include -+ #include -++#include -+ -+ #ifndef NSIG -+ # define NSIG 64 -+ #endif -+ -++int -+ main () -+ { -+ int n_sigs = 2 * NSIG; -+@@ -1770,6 +1801,7 @@ bash_cv_wcwidth_broken, -+ #include -+ #include -+ -++int -+ main(c, v) -+ int c; -+ char **v; -+@@ -1834,9 +1866,11 @@ AC_CACHE_VAL(ac_cv_rl_version, -+ [AC_TRY_RUN([ -+ #include -+ #include -++#include -+ -+ extern int rl_gnu_readline_p; -+ -++int -+ main() -+ { -+ FILE *fp; -+@@ -1926,7 +1960,9 @@ AC_CACHE_VAL(bash_cv_func_ctype_nonascii -+ #endif -+ #include -+ #include -++#include -+ -++int -+ main(c, v) -+ int c; -+ char *v[]; -+@@ -4068,7 +4104,9 @@ AC_DEFUN([BASH_FUNC_SNPRINTF], -+ AC_CACHE_CHECK([for standard-conformant snprintf], [bash_cv_func_snprintf], -+ [AC_TRY_RUN([ -+ #include -++#include -+ -++int -+ main() -+ { -+ int n; -+@@ -4154,6 +4192,7 @@ AC_CACHE_VAL(bash_cv_wexitstatus_offset, -+ -+ #include -+ -++int -+ main(c, v) -+ int c; -+ char **v; -+--- gdb-10.2/readline/readline/configure.orig -++++ gdb-10.2/readline/readline/configure -+@@ -1,5 +1,5 @@ -+ #! /bin/sh -+-# From configure.ac for Readline 8.0, version 2.85. -++# From configure.ac for Readline 8.0, version 2.86. -+ # Guess values for system-dependent variables and create Makefiles. -+ # Generated by GNU Autoconf 2.69 for readline 8.0. -+ # -+@@ -5316,6 +5316,7 @@ else -+ #ifdef HAVE_UNISTD_H -+ #include -+ #endif -++#include -+ -+ typedef RETSIGTYPE sigfunc(); -+ -+@@ -5346,7 +5347,8 @@ int s; -+ nsigint++; -+ } -+ -+-main() -++int -++main(void) -+ { -+ nsigint = 0; -+ set_signal_handler(SIGINT, sigint); -+@@ -5396,8 +5398,10 @@ else -+ #include -+ #include -+ #include -++#include -+ -+-main() -++int -++main(void) -+ { -+ #if !defined (_POSIX_VERSION) || !defined (HAVE_POSIX_SIGNALS) -+ exit (1); -+@@ -5499,7 +5503,10 @@ else -+ #if defined (HAVE_LOCALE_H) -+ #include -+ #endif -++#include -++#include -+ -++int -+ main(c, v) -+ int c; -+ char *v[]; -+@@ -5569,7 +5576,9 @@ else -+ #endif -+ #include -+ #include -++#include -+ -++int -+ main(c, v) -+ int c; -+ char *v[]; -+@@ -6713,6 +6722,7 @@ else -+ #include -+ #include -+ -++int -+ main(c, v) -+ int c; -+ char **v; -+--- gdb-10.2/readline/readline/configure.ac.orig -++++ gdb-10.2/readline/readline/configure.ac -+@@ -5,7 +5,7 @@ dnl report bugs to chet@po.cwru.edu -+ dnl -+ dnl Process this file with autoconf to produce a configure script. -+ -+-# Copyright (C) 1987-2018 Free Software Foundation, Inc. -++# Copyright (C) 1987-2019 Free Software Foundation, Inc. -+ -+ # This program is free software: you can redistribute it and/or modify -+ # it under the terms of the GNU General Public License as published by -+@@ -20,7 +20,7 @@ dnl Process this file with autoconf to p -+ # You should have received a copy of the GNU General Public License -+ # along with this program. If not, see . -+ -+-AC_REVISION([for Readline 8.0, version 2.85]) -++AC_REVISION([for Readline 8.0, version 2.86]) -+ -+ m4_include([../../config/override.m4]) -+ --- -2.37.1 - diff --git a/0039-Fix-for-net-n-option-to-properly-deal-with-an-invali.patch b/0039-Fix-for-net-n-option-to-properly-deal-with-an-invali.patch deleted file mode 100644 index dec47aa..0000000 --- a/0039-Fix-for-net-n-option-to-properly-deal-with-an-invali.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 5a652ed0c8db8d4c5891091b747470431054c717 Mon Sep 17 00:00:00 2001 -From: Lianbo Jiang -Date: Wed, 8 Mar 2023 20:22:02 +0800 -Subject: [PATCH 11/12] Fix for "net -n" option to properly deal with an - invalid argument - -The help/man page of the "net" command suggests that "-n" option can -accept two kinds of argument: PID or task_struct pointer. However, -the "net -n" command accepts an invalid argument and shows the -namespace of the current context silently. For example: - - crash> net -n 1000000000 - NET_DEVICE NAME IP ADDRESS(ES) - ffff949dc11d7000 lo 127.0.0.1 - ffff949dcc01c000 eno49 192.168.122.17 - -With the patch, emit an error expectedly. - - crash> net -n 1000000000 - net: invalid task or pid value: 1000000000 - -Reported-by: Buland Kumar Singh -Signed-off-by: Lianbo Jiang ---- - net.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/net.c b/net.c -index 987dc8934942..18c238be346d 100644 ---- a/net.c -+++ b/net.c -@@ -420,6 +420,9 @@ cmd_net(void) - case STR_PID: - case STR_TASK: - task = tc->task; -+ break; -+ case STR_INVALID: -+ error(FATAL, "invalid task or pid value: %s\n", args[optind]); - } - } - break; --- -2.37.1 - diff --git a/0040-gdb-Fix-an-assertion-failure-in-dw2_find_pc_sect_com.patch b/0040-gdb-Fix-an-assertion-failure-in-dw2_find_pc_sect_com.patch deleted file mode 100644 index dad68e2..0000000 --- a/0040-gdb-Fix-an-assertion-failure-in-dw2_find_pc_sect_com.patch +++ /dev/null @@ -1,71 +0,0 @@ -From ade71c3ec1d28751c3d6ba1eec71781bdff093d3 Mon Sep 17 00:00:00 2001 -From: Lianbo Jiang -Date: Tue, 7 Mar 2023 19:04:08 +0800 -Subject: [PATCH 12/12] gdb: Fix an assertion failure in - dw2_find_pc_sect_compunit_symtab() - -This is a partial backport patch from gdb commit 834eaf9201c1 ("Fix -crash in new DWARF indexer"). - -Without the patch, the "dis -rl" option may abort due to an assertion -failure in gdb's dw2_find_pc_sect_compunit_symtab(): - - crash> dis -rl ffffffff96ad716c - dwarf2/read.c:4928: internal-error: compunit_symtab* dw2_find_pc_sect_compunit_symtab(objfile*, bound_minimal_symbol, CORE_ADDR, obj_section*, int): Assertion `result != NULL' failed. - A problem internal to GDB has been detected, - further debugging may prove unreliable. - Quit this debugging session? (y or n) dwarf2/read.c:4928: internal-error: compunit_symtab* dw2_find_pc_sect_compunit_symtab(objfile*, bound_minimal_symbol, CORE_ADDR, obj_section*, int): Assertion `result != NULL' failed. - A problem internal to GDB has been detected, - further debugging may prove unreliable. - Aborted (core dumped) - -Reported-by: Buland Kumar Singh -Signed-off-by: Lianbo Jiang ---- - gdb-10.2.patch | 19 +++++++++++++++++-- - 1 file changed, 17 insertions(+), 2 deletions(-) - -diff --git a/gdb-10.2.patch b/gdb-10.2.patch -index 5089df9e72e1..835aae9859be 100644 ---- a/gdb-10.2.patch -+++ b/gdb-10.2.patch -@@ -4,7 +4,7 @@ - # that have already been applied. However, if a gdb file has been modified - # multiple times, the subsequent patching may fail to recognize that a - # given patch has been previously applied, and will attempt to re-apply it. --# To prevent any uninintended consequences, this file also acts as a -+# To prevent any unintended consequences, this file also acts as a - # shell script that can restore any gdb file to its original state prior - # to all subsequent patch applications. - -@@ -12,7 +12,8 @@ tar xvzmf gdb-10.2.tar.gz \ - gdb-10.2/gdb/symtab.c \ - gdb-10.2/gdb/printcmd.c \ - gdb-10.2/gdb/symfile.c \ -- gdb-10.2/gdb/Makefile.in -+ gdb-10.2/gdb/Makefile.in \ -+ gdb-10.2/gdb/dwarf2/read.c - - exit 0 - -@@ -3105,3 +3106,17 @@ exit 0 - - m4_include([../../config/override.m4]) - -+--- gdb-10.2/gdb/dwarf2/read.c.orig -++++ gdb-10.2/gdb/dwarf2/read.c -+@@ -4925,7 +4925,10 @@ dw2_find_pc_sect_compunit_symtab (struct objfile *objfile, -+ result = recursively_find_pc_sect_compunit_symtab -+ (dw2_instantiate_symtab (data, per_objfile, false), pc); -+ -+- gdb_assert (result != NULL); -++ if (warn_if_readin && result == nullptr) -++ warning (_("(Error: pc %s in address map, but not in symtab.)"), -++ paddress (objfile->arch (), pc)); -++ -+ return result; -+ } -+ --- -2.37.1 - diff --git a/0041-Fix-kmem-n-option-to-display-memory-blocks-on-Linux-.patch b/0041-Fix-kmem-n-option-to-display-memory-blocks-on-Linux-.patch deleted file mode 100644 index f231256..0000000 --- a/0041-Fix-kmem-n-option-to-display-memory-blocks-on-Linux-.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 489093c2183f4f0365d8957e7275cd88225942ce Mon Sep 17 00:00:00 2001 -From: Kazuhito Hagio -Date: Fri, 10 Mar 2023 02:38:26 +0000 -Subject: [PATCH] Fix "kmem -n" option to display memory blocks on Linux - 6.3-rc1 and later - -Kernel commit d2bf38c088e0 ("driver core: remove private pointer from -struct bus_type") removed the bus_type.p member, and the "kmem -n" -option fails with the following error before displaying memory block -information on Linux 6.3-rc1 and later kernels. - - kmem: invalid structure member offset: bus_type_p - FILE: memory.c LINE: 17852 FUNCTION: init_memory_block() - -Search bus_kset.list instead for subsys_private of memory subsys. - -Signed-off-by: Kazuhito Hagio ---- - defs.h | 2 ++ - memory.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++------ - symbols.c | 2 ++ - 3 files changed, 61 insertions(+), 6 deletions(-) - -diff --git a/defs.h b/defs.h -index 1f2cf6e0ce01..12ad6aaa0998 100644 ---- a/defs.h -+++ b/defs.h -@@ -2214,6 +2214,8 @@ struct offset_table { /* stash of commonly-used offsets */ - long inet6_ifaddr_if_list; - long inet6_ifaddr_if_next; - long in6_addr_in6_u; -+ long kset_kobj; -+ long subsys_private_subsys; - }; - - struct size_table { /* stash of commonly-used sizes */ -diff --git a/memory.c b/memory.c -index c4a6ecd18004..592a5ef49d50 100644 ---- a/memory.c -+++ b/memory.c -@@ -17822,6 +17822,13 @@ static void - init_memory_block_offset(void) - { - MEMBER_OFFSET_INIT(bus_type_p, "bus_type", "p"); -+ if (INVALID_MEMBER(bus_type_p)) { -+ MEMBER_OFFSET_INIT(kset_list, "kset", "list"); -+ MEMBER_OFFSET_INIT(kset_kobj, "kset", "kobj"); -+ MEMBER_OFFSET_INIT(kobject_name, "kobject", "name"); -+ MEMBER_OFFSET_INIT(kobject_entry, "kobject", "entry"); -+ MEMBER_OFFSET_INIT(subsys_private_subsys, "subsys_private", "subsys"); -+ } - MEMBER_OFFSET_INIT(subsys_private_klist_devices, - "subsys_private", "klist_devices"); - MEMBER_OFFSET_INIT(klist_k_list, "klist", "k_list"); -@@ -17842,15 +17849,60 @@ init_memory_block_offset(void) - } - - static void --init_memory_block(struct list_data *ld, int *klistcnt, ulong **klistbuf) -+init_memory_block(int *klistcnt, ulong **klistbuf) - { -- ulong memory_subsys = symbol_value("memory_subsys"); - ulong private, klist, start; -+ struct list_data list_data, *ld; -+ -+ ld = &list_data; -+ private = 0; - - init_memory_block_offset(); - -- readmem(memory_subsys + OFFSET(bus_type_p), KVADDR, &private, -- sizeof(void *), "memory_subsys.private", FAULT_ON_ERROR); -+ /* -+ * v6.3-rc1 -+ * d2bf38c088e0 driver core: remove private pointer from struct bus_type -+ */ -+ if (INVALID_MEMBER(bus_type_p)) { -+ int i, cnt; -+ char buf[32]; -+ ulong bus_kset, list, name; -+ -+ BZERO(ld, sizeof(struct list_data)); -+ -+ get_symbol_data("bus_kset", sizeof(ulong), &bus_kset); -+ readmem(bus_kset + OFFSET(kset_list), KVADDR, &list, -+ sizeof(ulong), "bus_kset.list", FAULT_ON_ERROR); -+ -+ ld->flags |= LIST_ALLOCATE; -+ ld->start = list; -+ ld->end = bus_kset + OFFSET(kset_list); -+ ld->list_head_offset = OFFSET(kobject_entry); -+ -+ cnt = do_list(ld); -+ for (i = 0; i < cnt; i++) { -+ readmem(ld->list_ptr[i] + OFFSET(kobject_name), KVADDR, &name, -+ sizeof(ulong), "kobject.name", FAULT_ON_ERROR); -+ read_string(name, buf, sizeof(buf)-1); -+ if (CRASHDEBUG(1)) -+ fprintf(fp, "kobject: %lx name: %s\n", ld->list_ptr[i], buf); -+ if (STREQ(buf, "memory")) { -+ /* entry is subsys_private.subsys.kobj. See bus_to_subsys(). */ -+ private = ld->list_ptr[i] - OFFSET(kset_kobj) -+ - OFFSET(subsys_private_subsys); -+ break; -+ } -+ } -+ FREEBUF(ld->list_ptr); -+ } else { -+ ulong memory_subsys = symbol_value("memory_subsys"); -+ readmem(memory_subsys + OFFSET(bus_type_p), KVADDR, &private, -+ sizeof(void *), "memory_subsys.private", FAULT_ON_ERROR); -+ } -+ -+ if (!private) -+ error(FATAL, "cannot determine subsys_private for memory.\n"); -+ - klist = private + OFFSET(subsys_private_klist_devices) + - OFFSET(klist_k_list); - BZERO(ld, sizeof(struct list_data)); -@@ -17875,7 +17927,6 @@ dump_memory_blocks(int initialize) - ulong memory_block, device; - ulong *klistbuf; - int klistcnt, i; -- struct list_data list_data; - char mb_hdr[BUFSIZE]; - char paddr_hdr[BUFSIZE]; - char buf1[BUFSIZE]; -@@ -17892,7 +17943,7 @@ dump_memory_blocks(int initialize) - if (initialize) - return; - -- init_memory_block(&list_data, &klistcnt, &klistbuf); -+ init_memory_block(&klistcnt, &klistbuf); - - if ((symbol_exists("memory_block_size_probed")) || - (MEMBER_EXISTS("memory_block", "end_section_nr"))) -diff --git a/symbols.c b/symbols.c -index 28846d06273c..f0721023816d 100644 ---- a/symbols.c -+++ b/symbols.c -@@ -10404,6 +10404,7 @@ dump_offset_table(char *spec, ulong makestruct) - OFFSET(kobject_entry)); - fprintf(fp, " kset_list: %ld\n", - OFFSET(kset_list)); -+ fprintf(fp, " kset_kobj: %ld\n", OFFSET(kset_kobj)); - fprintf(fp, " request_list_count: %ld\n", - OFFSET(request_list_count)); - fprintf(fp, " request_cmd_flags: %ld\n", -@@ -10441,6 +10442,7 @@ dump_offset_table(char *spec, ulong makestruct) - fprintf(fp, " blk_mq_tags_rqs: %ld\n", - OFFSET(blk_mq_tags_rqs)); - -+ fprintf(fp, " subsys_private_subsys: %ld\n", OFFSET(subsys_private_subsys)); - fprintf(fp, " subsys_private_klist_devices: %ld\n", - OFFSET(subsys_private_klist_devices)); - fprintf(fp, " subsystem_kset: %ld\n", --- -2.37.1 - diff --git a/crash-8.0.2_build.patch b/crash-8.0.3_build.patch similarity index 91% rename from crash-8.0.2_build.patch rename to crash-8.0.3_build.patch index 898d09c..bb09e2b 100644 --- a/crash-8.0.2_build.patch +++ b/crash-8.0.3_build.patch @@ -1,5 +1,5 @@ ---- crash-8.0.2/Makefile.orig -+++ crash-8.0.2/Makefile +--- crash-8.0.3/Makefile.orig ++++ crash-8.0.3/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.2/configure.c.orig -+++ crash-8.0.2/configure.c +--- crash-8.0.3/configure.c.orig ++++ crash-8.0.3/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]); diff --git a/crash.spec b/crash.spec index 10d7d97..1e043f5 100644 --- a/crash.spec +++ b/crash.spec @@ -3,8 +3,8 @@ # Summary: Kernel analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles Name: crash -Version: 8.0.2 -Release: 4%{?dist} +Version: 8.0.3 +Release: 1%{?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 @@ -18,48 +18,7 @@ Requires: binutils Provides: bundled(libiberty) Provides: bundled(gdb) = 10.2 Patch0: lzo_snappy_zstd.patch -Patch1: 0001-ps-Provide-an-option-to-display-no-header-line.patch -Patch2: 0002-arm64-fix-backtraces-of-KASAN-kernel-dumpfile-trunca.patch -Patch3: 0003-arm64-handle-vabits_actual-symbol-missing-case.patch -Patch4: 0004-EPPIC-extension-support-for-crash-8.x-gdb-10.x.patch -Patch5: 0005-x86_64-Fix-for-move-of-per-cpu-variables-into-struct.patch -Patch6: 0006-Fix-for-mm_struct.rss_stat-conversion-into-percpu_co.patch -Patch7: 0007-Fix-mount-command-to-appropriately-display-the-mount.patch -Patch8: 0008-Add-RISCV64-framework-code-support.patch -Patch9: 0009-RISCV64-Make-crash-tool-enter-command-line-and-suppo.patch -Patch10: 0010-RISCV64-Add-dis-command-support.patch -Patch11: 0011-RISCV64-Add-irq-command-support.patch -Patch12: 0012-RISCV64-Add-bt-command-support.patch -Patch13: 0013-RISCV64-Add-help-r-command-support.patch -Patch14: 0014-RISCV64-Add-help-m-M-command-support.patch -Patch15: 0015-RISCV64-Add-mach-command-support.patch -Patch16: 0016-RISCV64-Add-the-implementation-of-symbol-verify.patch -Patch17: 0017-SLUB-Fix-for-offset-change-of-struct-slab-members-on.patch -Patch18: 0018-Fix-for-kmem-i-to-display-correct-SLAB-statistics-on.patch -Patch19: 0019-Fix-build-failure-due-to-no-EM_RISCV-with-glibc-2.23.patch -Patch20: 0020-gdb-Fix-an-assertion-failure-in-the-gdb-s-copy_type.patch -Patch21: 0021-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.1-and-later.patch -Patch22: 0022-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.2-rc1-and-l.patch -Patch23: 0023-Port-the-maple-tree-data-structures-and-functions.patch -Patch24: 0024-Add-maple-tree-support-to-tree-command.patch -Patch25: 0025-Add-do_maple_tree-for-maple-tree-operations.patch -Patch26: 0026-Introduce-maple-tree-vma-iteration-to-vm_area_dump.patch -Patch27: 0027-Update-the-help-text-of-tree-command-for-maple-tree.patch -Patch28: 0028-Dump-maple-tree-offset-variables-by-help-o.patch -Patch29: 0029-Fix-for-bt-command-printing-bogus-exception-frame-wa.patch -Patch30: 0030-Fix-kmem-s-S-not-working-properly-on-RHEL8.6-and-lat.patch -Patch31: 0031-Fix-for-net-s-option-to-show-IPv6-addresses-on-Linux.patch -Patch32: 0032-Fix-for-kmem-i-option-to-not-print-invalid-values-fo.patch -Patch33: 0033-Fix-for-bt-command-unnecessarily-printing-an-excepti.patch -Patch34: 0034-Fix-for-dis-command-to-correctly-display-the-offset-.patch -Patch35: 0035-x86_64-Fix-bt-command-on-kernels-with-random_kstack_.patch -Patch36: 0036-Fix-for-search-u-option-failing-in-maple-tree-kernel.patch -Patch37: 0037-Enhance-net-command-to-display-IPv6-address-of-netwo.patch -Patch38: 0038-Fix-C99-compatibility-issues-in-embedded-copy-of-GDB.patch -Patch39: 0039-Fix-for-net-n-option-to-properly-deal-with-an-invali.patch -Patch40: 0040-gdb-Fix-an-assertion-failure-in-dw2_find_pc_sect_com.patch -Patch41: 0041-Fix-kmem-n-option-to-display-memory-blocks-on-Linux-.patch -Patch42: crash-8.0.2_build.patch +Patch1: crash-8.0.3_build.patch %description The core analysis suite is a self-contained tool that can be used to @@ -81,47 +40,6 @@ offered by Mission Critical Linux, or the LKCD kernel patch. %setup -n %{name}-%{version} -q %patch0 -p1 -b lzo_snappy_zstd.patch %patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 -%patch7 -p1 -%patch8 -p1 -%patch9 -p1 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -%patch13 -p1 -%patch14 -p1 -%patch15 -p1 -%patch16 -p1 -%patch17 -p1 -%patch18 -p1 -%patch19 -p1 -%patch20 -p1 -%patch21 -p1 -%patch22 -p1 -%patch23 -p1 -%patch24 -p1 -%patch25 -p1 -%patch26 -p1 -%patch27 -p1 -%patch28 -p1 -%patch29 -p1 -%patch30 -p1 -%patch31 -p1 -%patch32 -p1 -%patch33 -p1 -%patch34 -p1 -%patch35 -p1 -%patch36 -p1 -%patch37 -p1 -%patch38 -p1 -%patch39 -p1 -%patch40 -p1 -%patch41 -p1 -%patch42 -p1 %build @@ -147,6 +65,9 @@ cp -p defs.h %{buildroot}%{_includedir}/crash %{_includedir}/* %changelog +* Fri Apr 28 2023 Lianbo Jiang - 8.0.3-1 +- Rebase to upstream crash 8.0.3 + * Fri Mar 10 2023 Lianbo Jiang - 8.0.2-4 - Fix "kmem -n" option to display memory blocks on Linux 6.3-rc1 and later - gdb: Fix an assertion failure in dw2_find_pc_sect_compunit_symtab() diff --git a/sources b/sources index ef38a0b..29d88c0 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (crash-8.0.2.tar.gz) = 9ff24d1206e9376e83690f76c817a48a68ff6adce677fad70335a73550a59c9af6e4753c1199f22eafa60c137156313244bbf98ed01bc2b066f41d324738ef6b +SHA512 (crash-8.0.3.tar.gz) = 1ce7fda89274051cea02a049a674f2ca43fc02e00121f951af0d4c23c7b74cc79949ec376bb6737f82b95fec0cbe495b53a09df7e5f1f31ee5a829c1d53d0ba0 SHA512 (gdb-10.2.tar.gz) = aa89caf47c1c84366020377d47e7c51ddbc48e5b7686f244e38797c8eb88411cf57fcdc37eb669961efb41ceeac4181747f429625fd1acce7712cb9a1fea9c41