[PATCH v2 1/2] diskdump/netdump: fix segmentation fault caused by failure of stopping CPUs
by HATAYAMA Daisuke
There's no NMI on ARM. Hence, stopping the non-panicking CPUs from the
panicking CPU via IPI can fail easily if interrupts are being masked
in those moment. Moreover, crash_notes are not initialized for such
unstopped CPUs and the corresponding NT_PRSTATUS notes are not
attached to vmcore. However, crash utility never takes it
consideration such uninitialized crash_notes and then ends with
mapping different NT_PRSTATUS to actually unstopped CPUs. This corrupt
mapping can result crash utility into segmentation fault in the
operations where register values in NT_PRSTATUS notes are used.
For example:
crash> bt 1408
PID: 1408 TASK: ffff000003e22200 CPU: 2 COMMAND: "repro"
Segmentation fault (core dumped)
crash> help -D
diskdump_data:
filename: 127.0.0.1-2023-05-26-02:21:27/vmcore-ld1
flags: 46 (KDUMP_CMPRS_LOCAL|ERROR_EXCLUDED|LZO_SUPPORTED)
...snip...
notes_buf: 1815df0
num_vmcoredd_notes: 0
num_prstatus_notes: 5
notes[0]: 1815df0 (NT_PRSTATUS)
si.signo: 0 si.code: 0 si.errno: 0
...snip...
PSTATE: 80400005 FPVALID: 00000000
notes[4]: 1808f10 (NT_PRSTATUS)
Segmentation fault (core dumped)
To fix this issue, let's map NT_PRSTATUS to some CPU only if the
corresponding crash_notes is checked to be initialized.
Signed-off-by: HATAYAMA Daisuke <d.hatayama(a)fujitsu.com>
---
defs.h | 1 +
diskdump.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
netdump.c | 5 ++++-
3 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/defs.h b/defs.h
index bfa07c3..655de55 100644
--- a/defs.h
+++ b/defs.h
@@ -7113,6 +7113,7 @@ int dumpfile_is_split(void);
void show_split_dumpfiles(void);
void x86_process_elf_notes(void *, unsigned long);
void *diskdump_get_prstatus_percpu(int);
+int have_crash_notes(int cpu);
void map_cpus_to_prstatus_kdump_cmprs(void);
void diskdump_display_regs(int, FILE *);
void process_elf32_notes(void *, ulong);
diff --git a/diskdump.c b/diskdump.c
index 94bca4d..af65816 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -101,6 +101,55 @@ int dumpfile_is_split(void)
return KDUMP_SPLIT();
}
+int have_crash_notes(int cpu)
+{
+ ulong crash_notes, notes_ptr;
+ char *buf, *p;
+ Elf64_Nhdr *note = NULL;
+
+ if (!readmem(symbol_value("crash_notes"),
+ KVADDR,
+ &crash_notes,
+ sizeof(crash_notes),
+ "crash_notes",
+ RETURN_ON_ERROR)) {
+ error(WARNING, "cannot read \"crash_notes\"\n");
+ return FALSE;
+ }
+
+ if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF))
+ notes_ptr = crash_notes + kt->__per_cpu_offset[cpu];
+ else
+ notes_ptr = crash_notes;
+
+ buf = GETBUF(SIZE(note_buf));
+
+ if (!readmem(notes_ptr,
+ KVADDR,
+ buf,
+ SIZE(note_buf),
+ "note_buf_t",
+ RETURN_ON_ERROR)) {
+ error(WARNING, "cpu %d: cannot read NT_PRSTATUS note\n", cpu);
+ return FALSE;
+ }
+
+ note = (Elf64_Nhdr *)buf;
+ p = buf + sizeof(Elf64_Nhdr);
+
+ if (note->n_type != NT_PRSTATUS) {
+ error(WARNING, "cpu %d: invalid NT_PRSTATUS note (n_type != NT_PRSTATUS)\n", cpu);
+ return FALSE;
+ }
+
+ if (!STRNEQ(p, "CORE")) {
+ error(WARNING, "cpu %d: invalid NT_PRSTATUS note (name != \"CORE\")\n", cpu);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
void
map_cpus_to_prstatus_kdump_cmprs(void)
{
@@ -131,7 +180,7 @@ map_cpus_to_prstatus_kdump_cmprs(void)
nrcpus = (kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS);
for (i = 0, j = 0; i < nrcpus; i++) {
- if (in_cpu_map(ONLINE_MAP, i)) {
+ if (in_cpu_map(ONLINE_MAP, i) && (!symbol_exists("crash_notes") || have_crash_notes(i))) {
dd->nt_prstatus_percpu[i] = nt_ptr[j++];
dd->num_prstatus_notes =
MAX(dd->num_prstatus_notes, i+1);
diff --git a/netdump.c b/netdump.c
index 4eba66c..9500cf4 100644
--- a/netdump.c
+++ b/netdump.c
@@ -99,8 +99,11 @@ map_cpus_to_prstatus(void)
nrcpus = (kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS);
for (i = 0, j = 0; i < nrcpus; i++) {
- if (in_cpu_map(ONLINE_MAP, i))
+ if (in_cpu_map(ONLINE_MAP, i) && (!symbol_exists("crash_notes") || have_crash_notes(i))) {
nd->nt_prstatus_percpu[i] = nt_ptr[j++];
+ nd->num_prstatus_notes =
+ MAX(nd->num_prstatus_notes, i+1);
+ }
}
FREEBUF(nt_ptr);
--
2.25.1
1 year, 3 months
[PATCH v2] x86_64: Fix "bt" command printing stale entries on Linux 6.4 and later
by HAGIO KAZUHITO(萩尾 一仁)
From: Kazuhito Hagio <k-hagio-ab(a)nec.com>
Kernel commit fb799447ae29 ("x86,objtool: Split UNWIND_HINT_EMPTY in
two"), which is contained in Linux 6.4 and later kernels, changed
ORC_TYPE_CALL macro from 0 to 2. As a result, the "bt" command cannot
use ORC entries, and can display stale entries in a call trace.
crash> bt 1
PID: 1 TASK: ffff93cd06294180 CPU: 51 COMMAND: "systemd"
#0 [ffffb72bc00cbc98] __schedule at ffffffff86e52aae
#1 [ffffb72bc00cbd00] schedule at ffffffff86e52f6a
#2 [ffffb72bc00cbd18] schedule_hrtimeout_range_clock at ffffffff86e58ef5
#3 [ffffb72bc00cbd88] ep_poll at ffffffff8669624d
#4 [ffffb72bc00cbe28] do_epoll_wait at ffffffff86696371
#5 [ffffb72bc00cbe30] do_timerfd_settime at ffffffff8669902b <<
#6 [ffffb72bc00cbe60] __x64_sys_epoll_wait at ffffffff86696bf0
#7 [ffffb72bc00cbeb0] do_syscall_64 at ffffffff86e3feb9
#8 [ffffb72bc00cbee0] __task_pid_nr_ns at ffffffff863330d7 <<
#9 [ffffb72bc00cbf08] syscall_exit_to_user_mode at ffffffff86e466b2 << stale entries
#10 [ffffb72bc00cbf18] do_syscall_64 at ffffffff86e3fec9 <<
#11 [ffffb72bc00cbf50] entry_SYSCALL_64_after_hwframe at ffffffff870000aa
Also, kernel commit ffb1b4a41016 added a member to struct orc_entry.
Although this does not affect the crash's unwinder, its debugging
information can be displayed incorrectly.
To fix these,
(1) introduce "kernel_orc_entry_6_4" structure corresponding to 6.4 and
abstruction layer "orc_entry" structure in crash,
(2) switch ORC_TYPE_CALL to 2 or 0 with kernel's orc_entry structure.
Related orc_entry history:
v4.14 39358a033b2e introduced struct orc_entry
v4.19 d31a580266ee added orc_entry.end member
v6.3 ffb1b4a41016 added orc_entry.signal member
v6.4 fb799447ae29 removed end member and changed type member to 3 bits
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
v2:
- better debugging information for orc_entry.{signal,end}.
defs.h | 27 ++++++++++++-
x86_64.c | 119 +++++++++++++++++++++++++++++++++++++++++++------------
2 files changed, 118 insertions(+), 28 deletions(-)
diff --git a/defs.h b/defs.h
index 21cc760444d1..c1ac347c8e26 100644
--- a/defs.h
+++ b/defs.h
@@ -6354,9 +6354,29 @@ typedef struct __attribute__((__packed__)) {
unsigned int sp_reg:4;
unsigned int bp_reg:4;
unsigned int type:2;
+ unsigned int signal:1;
unsigned int end:1;
} kernel_orc_entry;
+typedef struct __attribute__((__packed__)) {
+ signed short sp_offset;
+ signed short bp_offset;
+ unsigned int sp_reg:4;
+ unsigned int bp_reg:4;
+ unsigned int type:3;
+ unsigned int signal:1;
+} kernel_orc_entry_6_4;
+
+typedef struct orc_entry {
+ signed short sp_offset;
+ signed short bp_offset;
+ unsigned int sp_reg;
+ unsigned int bp_reg;
+ unsigned int type;
+ unsigned int signal;
+ unsigned int end;
+} orc_entry;
+
struct ORC_data {
int module_ORC;
uint lookup_num_blocks;
@@ -6367,10 +6387,12 @@ struct ORC_data {
ulong orc_lookup;
ulong ip_entry;
ulong orc_entry;
- kernel_orc_entry kernel_orc_entry;
+ orc_entry orc_entry_data;
+ int has_signal;
+ int has_end;
};
-#define ORC_TYPE_CALL 0
+#define ORC_TYPE_CALL ((machdep->flags & ORC_6_4) ? 2 : 0)
#define ORC_TYPE_REGS 1
#define ORC_TYPE_REGS_IRET 2
#define UNWIND_HINT_TYPE_SAVE 3
@@ -6447,6 +6469,7 @@ struct machine_specific {
#define ORC (0x4000)
#define KPTI (0x8000)
#define L1TF (0x10000)
+#define ORC_6_4 (0x20000)
#define VM_FLAGS (VM_ORIG|VM_2_6_11|VM_XEN|VM_XEN_RHEL4|VM_5LEVEL)
diff --git a/x86_64.c b/x86_64.c
index 5019c69e452e..74d38106bb3c 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -132,9 +132,9 @@ static void GART_init(void);
static void x86_64_exception_stacks_init(void);
static int in_START_KERNEL_map(ulong);
static ulong orc_ip(ulong);
-static kernel_orc_entry *__orc_find(ulong, ulong, uint, ulong);
-static kernel_orc_entry *orc_find(ulong);
-static kernel_orc_entry *orc_module_find(ulong);
+static orc_entry *__orc_find(ulong, ulong, uint, ulong);
+static orc_entry *orc_find(ulong);
+static orc_entry *orc_module_find(ulong);
static ulong ip_table_to_vaddr(ulong);
static void orc_dump(ulong);
@@ -806,6 +806,8 @@ x86_64_dump_machdep_table(ulong arg)
fprintf(fp, "%sFRAMESIZE_DEBUG", others++ ? "|" : "");
if (machdep->flags & ORC)
fprintf(fp, "%sORC", others++ ? "|" : "");
+ if (machdep->flags & ORC_6_4)
+ fprintf(fp, "%sORC_6_4", others++ ? "|" : "");
if (machdep->flags & FRAMEPOINTER)
fprintf(fp, "%sFRAMEPOINTER", others++ ? "|" : "");
if (machdep->flags & GART_REGION)
@@ -980,6 +982,8 @@ x86_64_dump_machdep_table(ulong arg)
fprintf(fp, " ORC_data: %s", machdep->flags & ORC ? "\n" : "(unused)\n");
if (machdep->flags & ORC) {
fprintf(fp, " module_ORC: %s\n", ms->orc.module_ORC ? "TRUE" : "FALSE");
+ fprintf(fp, " has_signal: %s\n", ms->orc.has_signal ? "TRUE" : "FALSE");
+ fprintf(fp, " has_end: %s\n", ms->orc.has_end ? "TRUE" : "FALSE");
fprintf(fp, " lookup_num_blocks: %d\n", ms->orc.lookup_num_blocks);
fprintf(fp, " __start_orc_unwind_ip: %lx\n", ms->orc.__start_orc_unwind_ip);
fprintf(fp, " __stop_orc_unwind_ip: %lx\n", ms->orc.__stop_orc_unwind_ip);
@@ -988,14 +992,18 @@ x86_64_dump_machdep_table(ulong arg)
fprintf(fp, " orc_lookup: %lx\n", ms->orc.orc_lookup);
fprintf(fp, " ip_entry: %lx\n", ms->orc.ip_entry);
fprintf(fp, " orc_entry: %lx\n", ms->orc.orc_entry);
- fprintf(fp, " kernel_orc_entry:\n");
- fprintf(fp, " sp_offset: %d\n", ms->orc.kernel_orc_entry.sp_offset);
- fprintf(fp, " bp_offset: %d\n", ms->orc.kernel_orc_entry.bp_offset);
- fprintf(fp, " sp_reg: %d\n", ms->orc.kernel_orc_entry.sp_reg);
- fprintf(fp, " bp_reg: %d\n", ms->orc.kernel_orc_entry.bp_reg);
- fprintf(fp, " type: %d\n", ms->orc.kernel_orc_entry.type);
- if (MEMBER_EXISTS("orc_entry", "end"))
- fprintf(fp, " end: %d\n", ms->orc.kernel_orc_entry.end);
+ fprintf(fp, " orc_entry_data:\n");
+ fprintf(fp, " sp_offset: %d\n", ms->orc.orc_entry_data.sp_offset);
+ fprintf(fp, " bp_offset: %d\n", ms->orc.orc_entry_data.bp_offset);
+ fprintf(fp, " sp_reg: %d\n", ms->orc.orc_entry_data.sp_reg);
+ fprintf(fp, " bp_reg: %d\n", ms->orc.orc_entry_data.bp_reg);
+ fprintf(fp, " type: %d\n", ms->orc.orc_entry_data.type);
+ if (ms->orc.has_signal)
+ fprintf(fp, " signal: %d\n", ms->orc.orc_entry_data.signal);
+ else
+ fprintf(fp, " signal: (n/a)\n");
+ if (ms->orc.has_end)
+ fprintf(fp, " end: %d\n", ms->orc.orc_entry_data.end);
else
fprintf(fp, " end: (n/a)\n");
}
@@ -6439,6 +6447,12 @@ x86_64_ORC_init(void)
MEMBER_OFFSET_INIT(inactive_task_frame_bp, "inactive_task_frame", "bp");
MEMBER_OFFSET_INIT(inactive_task_frame_ret_addr, "inactive_task_frame", "ret_addr");
+ orc->has_signal = MEMBER_EXISTS("orc_entry", "signal"); /* added at 6.3 */
+ orc->has_end = MEMBER_EXISTS("orc_entry", "end"); /* removed at 6.4 */
+
+ if (orc->has_signal && !orc->has_end)
+ machdep->flags |= ORC_6_4;
+
machdep->flags |= ORC;
}
@@ -8521,7 +8535,7 @@ x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp, char *stack_
int reterror;
int arg_exists;
int exception;
- kernel_orc_entry *korc;
+ orc_entry *korc;
if (!(bt->flags & BT_FRAMESIZE_DEBUG)) {
if ((bt->flags & BT_FRAMESIZE_IGNORE_MASK) ||
@@ -8607,11 +8621,14 @@ x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp, char *stack_
if ((machdep->flags & ORC) && (korc = orc_find(textaddr))) {
if (CRASHDEBUG(1)) {
+ struct ORC_data *orc = &machdep->machspec->orc;
fprintf(fp,
"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"))
+ if (orc->has_signal)
+ fprintf(fp, " signal: %d", korc->signal);
+ if (orc->has_end)
fprintf(fp, " end: %d", korc->end);
fprintf(fp, "\n");
}
@@ -9117,7 +9134,53 @@ orc_ip(ulong ip)
return (ip + ip_entry);
}
-static kernel_orc_entry *
+static orc_entry *
+orc_get_entry(struct ORC_data *orc)
+{
+ struct orc_entry *entry = &orc->orc_entry_data;
+
+ if (machdep->flags & ORC_6_4) {
+ kernel_orc_entry_6_4 korc;
+
+ if (!readmem(orc->orc_entry, KVADDR, &korc, sizeof(kernel_orc_entry_6_4),
+ "kernel orc_entry", RETURN_ON_ERROR|QUIET))
+ return NULL;
+
+ entry->sp_offset = korc.sp_offset;
+ entry->bp_offset = korc.bp_offset;
+ entry->sp_reg = korc.sp_reg;
+ entry->bp_reg = korc.bp_reg;
+ entry->type = korc.type;
+ entry->signal = korc.signal;
+ } else {
+ kernel_orc_entry korc;
+
+ if (!readmem(orc->orc_entry, KVADDR, &korc, sizeof(kernel_orc_entry),
+ "kernel orc_entry", RETURN_ON_ERROR|QUIET))
+ return NULL;
+
+ entry->sp_offset = korc.sp_offset;
+ entry->bp_offset = korc.bp_offset;
+ entry->sp_reg = korc.sp_reg;
+ entry->bp_reg = korc.bp_reg;
+ entry->type = korc.type;
+ if (orc->has_end) {
+ /*
+ * orc_entry.signal was inserted before orc_entry.end.
+ * see ffb1b4a41016.
+ */
+ if (orc->has_signal) {
+ entry->signal = korc.signal;
+ entry->end = korc.end;
+ } else
+ entry->end = korc.signal; /* on purpose */
+ }
+ }
+
+ return entry;
+}
+
+static orc_entry *
__orc_find(ulong ip_table_ptr, ulong u_table_ptr, uint num_entries, ulong ip)
{
int index;
@@ -9127,7 +9190,7 @@ __orc_find(ulong ip_table_ptr, ulong u_table_ptr, uint num_entries, ulong ip)
int *ip_table = (int *)ip_table_ptr;
struct ORC_data *orc = &machdep->machspec->orc;
ulong vaddr;
- kernel_orc_entry *korc;
+ orc_entry *korc;
if (CRASHDEBUG(2)) {
int i, ip_entry;
@@ -9171,18 +9234,20 @@ __orc_find(ulong ip_table_ptr, ulong u_table_ptr, uint num_entries, ulong ip)
orc->ip_entry = (ulong)found;
orc->orc_entry = u_table_ptr + (index * SIZE(orc_entry));
- if (!readmem(orc->orc_entry, KVADDR, &orc->kernel_orc_entry,
- sizeof(kernel_orc_entry), "kernel orc_entry", RETURN_ON_ERROR|QUIET))
+
+ if (!orc_get_entry(orc))
return NULL;
- korc = &orc->kernel_orc_entry;
+ korc = &orc->orc_entry_data;
if (CRASHDEBUG(2)) {
fprintf(fp, " found: %lx index: %d\n", (ulong)found, index);
fprintf(fp,
" orc_entry: %lx sp_offset: %d bp_offset: %d sp_reg: %d bp_reg: %d type: %d",
orc->orc_entry, korc->sp_offset, korc->bp_offset, korc->sp_reg, korc->bp_reg, korc->type);
- if (MEMBER_EXISTS("orc_entry", "end"))
+ if (orc->has_signal)
+ fprintf(fp, " signal: %d", korc->signal);
+ if (orc->has_end)
fprintf(fp, " end: %d", korc->end);
fprintf(fp, "\n");
}
@@ -9195,7 +9260,7 @@ __orc_find(ulong ip_table_ptr, ulong u_table_ptr, uint num_entries, ulong ip)
#define LOOKUP_START_IP (unsigned long)kt->stext
#define LOOKUP_STOP_IP (unsigned long)kt->etext
-static kernel_orc_entry *
+static orc_entry *
orc_find(ulong ip)
{
unsigned int idx, start, stop;
@@ -9265,7 +9330,7 @@ orc_find(ulong ip)
orc->__start_orc_unwind + (start * SIZE(orc_entry)), stop - start, ip);
}
-static kernel_orc_entry *
+static orc_entry *
orc_module_find(ulong ip)
{
struct load_module *lm;
@@ -9312,7 +9377,7 @@ static void
orc_dump(ulong ip)
{
struct ORC_data *orc = &machdep->machspec->orc;
- kernel_orc_entry *korc;
+ orc_entry *korc;
ulong vaddr, offset;
struct syment *sp, *orig;
@@ -9335,13 +9400,15 @@ next_in_func:
fprintf(fp, "%s+%ld -> ", sp->name, offset);
else
fprintf(fp, "(unresolved) -> ");
- if (!readmem(orc->orc_entry, KVADDR, &orc->kernel_orc_entry, sizeof(kernel_orc_entry),
- "kernel orc_entry", RETURN_ON_ERROR))
+
+ if (!orc_get_entry(orc))
error(FATAL, "cannot read orc_entry\n");
- korc = &orc->kernel_orc_entry;
+ korc = &orc->orc_entry_data;
fprintf(fp, "orc: %lx spo: %d bpo: %d spr: %d bpr: %d type: %d",
orc->orc_entry, korc->sp_offset, korc->bp_offset, korc->sp_reg, korc->bp_reg, korc->type);
- if (MEMBER_EXISTS("orc_entry", "end"))
+ if (orc->has_signal)
+ fprintf(fp, " signal: %d", korc->signal);
+ if (orc->has_end)
fprintf(fp, " end: %d", korc->end);
fprintf(fp, "\n");
--
2.31.1
1 year, 3 months
Re: [Crash-utility] [PATCH v2] Output prompt when stdin is not a TTY
by lijiang
On Wed, May 31, 2023 at 2:07 PM <crash-utility-request(a)redhat.com> wrote:
> Date: Wed, 31 May 2023 14:01:36 +0800
> From: Hsin-Yi Wang <hsinyi(a)chromium.org>
> To: crash-utility(a)redhat.com, k-hagio-ab(a)nec.com
> Subject: [Crash-utility] [PATCH v2] Output prompt when stdin is not a
> TTY.
> Message-ID: <20230531060349.711886-1-hsinyi(a)chromium.org>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> When stdin is not a TTY, prompt ("crash> ") won't be displayed. If
> another process interact with crash with piped stdin/stdout, it will not
> get the prompt as a delimiter.
>
> Compared to other debugger like gdb, crash seems intended to give a
> prompt in this case in the beginning of process_command_line(). It
> checks if pc->flags does NOT have any of
> READLINE|SILENT|CMDLINE_IFILE|RCHOME_IFILE|RCLOCAL_IFILE, a
> prompt should be printed. The check will never be true since READLINE is
> set in setup_environment() unconditionally.
>
> It makes more sense to change the READLINE flag in the check to TTY
> instead. Besides this change, the prompt in process_command_line() should
> only be print when it's not in the middle of processing the input file
> recovering from a previous FATAL command, because the prompt will be
> displayed by the exec_input_file().
>
> Additionally, when stdin is not TTY, repeat the command line from user
> after prompt, which can give more context.
>
> The prompt and command line can be opt out by using the silent (-s) flag.
>
>
Thank you for the fix, Hsin-Yi.
For v2, I have no other issues, so: Ack.
Thanks.
Lianbo
> Signed-off-by: Hsin-Yi Wang <hsinyi(a)chromium.org>
> ---
> v1: https://listman.redhat.com/archives/crash-utility/2023-May/010740.html
> v1->v2:
> 1. remove additional prompt when recovering from FATAL command from
> file.
> 2. fix a few space/tab indent.
> ---
> cmdline.c | 14 +++++++++-----
> 1 file changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/cmdline.c b/cmdline.c
> index ded6551..b7f919a 100644
> --- a/cmdline.c
> +++ b/cmdline.c
> @@ -64,8 +64,8 @@ process_command_line(void)
> fp = stdout;
> BZERO(pc->command_line, BUFSIZE);
>
> - if (!(pc->flags &
> - (READLINE|SILENT|CMDLINE_IFILE|RCHOME_IFILE|RCLOCAL_IFILE)))
> + if (!pc->ifile_in_progress && !(pc->flags &
> + (TTY|SILENT|CMDLINE_IFILE|RCHOME_IFILE|RCLOCAL_IFILE)))
> fprintf(fp, "%s", pc->prompt);
> fflush(fp);
>
> @@ -136,12 +136,16 @@ process_command_line(void)
> add_history(pc->command_line);
>
> check_special_handling(pc->command_line);
> - } else {
> - if (fgets(pc->command_line, BUFSIZE-1, stdin) == NULL)
> + } else {
> + if (fgets(pc->command_line, BUFSIZE-1, stdin) == NULL)
> clean_exit(1);
> + if (!(pc->flags & SILENT)) {
> + fprintf(fp, "%s", pc->command_line);
> + fflush(fp);
> + }
> clean_line(pc->command_line);
> strcpy(pc->orig_line, pc->command_line);
> - }
> + }
>
> /*
> * First clean out all linefeeds and leading/trailing spaces.
> --
> 2.41.0.rc0.172.g3f132b7071-goog
>
1 year, 3 months
[RFC PATCH 00/15] Support module memory layout change on Linux 6.4
by HAGIO KAZUHITO(萩尾 一仁)
This patchset supports module memory layout change on Linux 6.4 by
kernel commit [1]. Without the patchset, crash cannot even start a
session with an error message like this:
crash: invalid structure member offset: module_core_size
FILE: kernel.c LINE: 3787 FUNCTION: module_init()
(For the current crash, you can use "crash --no_modules" option without
module functionalities to avoid the failure of startup.)
This patchset is also located at GitHub [2].
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit...
[2] https://github.com/k-hagio/crash/tree/6.4-module.wip2
Probably most of module and symbol functions will work, though maybe
there might be lack of fixes for some functions and there might be my
misunderstanding of crash code. (There are also some functions not
fixed because crash does not use them for the recent kernels.)
Please let me know if there are any bugs and comments on the design,
coding style and etc.
* The current patchset is a draft and kind of POC, fixes are piled up
and no code and performance optimization. I will rearrange them later.
* Currently enum mod_mem_type is backported from the kernel as it is,
because I'm not sure whether it's likely to change soon.
* The new module memory areas are scattered, and managed by the
following struct load_module members.
struct load_module {
...
/* For 6.4 module_memory */
struct module_memory mem[MOD_MEM_NUM_TYPES];
struct syment **symtable;
struct syment **symend;
struct syment *ext_symtable[MOD_MEM_NUM_TYPES];
struct syment *ext_symend[MOD_MEM_NUM_TYPES];
struct syment *load_symtable[MOD_MEM_NUM_TYPES];
struct syment *load_symend[MOD_MEM_NUM_TYPES];
int address_order[MOD_MEM_NUM_TYPES];
int nr_mems;
};
* "sym -M" output is ordered by module text start address on a
per-module basis for now. (how can I say...) So if you get all of
module symbols in address order, need to sort them. But modules will be
mixed.
crash> sym -M | grep MODULE # displayed per module
...
ffffffffc046f000 MODULE TEXT START: dm_mirror
ffffffffc0472000 MODULE TEXT END: dm_mirror
ffffffffc0473000 MODULE DATA START: dm_mirror
ffffffffc0475000 MODULE DATA END: dm_mirror
ffffffffc0476000 MODULE RODATA START: dm_mirror
ffffffffc0478000 MODULE RODATA END: dm_mirror
ffffffffc044b000 MODULE RO_AFTER_INIT START: libata # lower than the
previous
ffffffffc044c000 MODULE RO_AFTER_INIT END: libata
ffffffffc0479000 MODULE TEXT START: libata
ffffffffc049d000 MODULE TEXT END: libata
ffffffffc049e000 MODULE DATA START: libata
ffffffffc04c8000 MODULE DATA END: libata
...
crash> sym -M | grep MODULE | sort # displayed in address order
...
ffffffffc0468000 MODULE RODATA START: dm_region_hash
ffffffffc046a000 MODULE RODATA END: dm_region_hash
ffffffffc046b000 MODULE RODATA START: t10_pi
ffffffffc046c000 MODULE RODATA END: t10_pi
ffffffffc046d000 MODULE TEXT START: ghash_clmulni_intel
ffffffffc046e000 MODULE TEXT END: ghash_clmulni_intel
ffffffffc046f000 MODULE TEXT START: dm_mirror
ffffffffc0472000 MODULE TEXT END: dm_mirror
...
Kazuhito Hagio (15):
Add support for struct module_memory on Linux 6.4 and later
Support "sym -l|-M|-m" options
Make "sym -m" option print symbols in address order
Fix verify_module() and next_module_vaddr()
Fix {lowest,highest}_modules_address() and is_kernel_text()
Support "mod -s|-S" options
Support percpu symbols for "sym" options
Support "mod -d|-D" options
Support "sym -n" option
Support "sym -p" option
Fix module_symbol() and is_kernel_text()
Remove unused find_mod_etext() in store_module_symbols_v3()
Fix get_section, check_for_dups, symbol_query, symbol_name_count
Fix symbol_search_next, symbol_complete_match and get_syment_array
mod: Change "BASE" on header to "TEXT_BASE" to clarify
defs.h | 45 ++
gdb-10.2.patch | 16 +
kernel.c | 47 +-
memory.c | 36 +-
symbols.c | 1571 +++++++++++++++++++++++++++++++++++++++++++++---
5 files changed, 1616 insertions(+), 99 deletions(-)
--
2.31.1
1 year, 3 months
[Question] crash-arm64 cannot determine VA_BITS_ACTUAL for qemu dump-guest-memory
by Qiwu.Chen
Dear Mantainers,
I meet a problem that the latest crash tool built for ARM64 cannot load the vmcore genarated by Qemu ARM64 guest OS.
1) The vmcore captured by "dump-guest-memory" cmd in qemu monitor mode:
(qemu) dump-guest-memory vmcore
$ file vmcore
vmcore: ELF 64-bit LSB core file, ARM aarch64, version 1 (SYSV), SVR4-style
My host OS installed qemu-system-aarch64 version is 6.2.0
$ qemu-system-aarch64 --version
QEMU emulator version 6.2.0
2) The test for linux version both 5.0 and 5.15 which disable kaslr is NG, but test linux version 4.0 loading vmcore is OK.
Here's the error log while crash tool loading linux-5.15 vmcore:
$ crash64 vmlinux vmcore
crash64 8.0.3++
Copyright (C) 2002-2022 Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation
Copyright (C) 1999-2006 Hewlett-Packard Co
Copyright (C) 2005, 2006, 2011, 2012 Fujitsu Limited
Copyright (C) 2006, 2007 VA Linux Systems Japan K.K.
Copyright (C) 2005, 2011, 2020-2022 NEC Corporation
Copyright (C) 1999, 2002, 2007 Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
Copyright (C) 2015, 2021 VMware, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions. Enter "help copying" to see the conditions.
This program has absolutely no warranty. Enter "help warranty" for details.
crash64: cannot determine VA_BITS_ACTUAL
3) It seems crash tool cannot get vabits_actual from vmcore, so I append "vabits_actual=48" to crash cmd:
$ crash-arm64 vmlinux vmcore -m vabits_actual=48
The result shows some symbols seek error:
crash-arm64: seek error: kernel virtual address: ffff800011769918 type: "possible"WARNING: cannot read cpu_possible_map
crash-arm64: seek error: kernel virtual address: ffff800011769958 type: "present"
WARNING: cannot read cpu_present_map
crash-arm64: seek error: kernel virtual address: ffff800011769938 type: "online"
WARNING: cannot read cpu_online_map
crash-arm64: seek error: kernel virtual address: ffff800011769978 type: "active"
WARNING: cannot read cpu_active_map
crash-arm64: seek error: kernel virtual address: ffff800011936390 type: "shadow_timekeeper xtime_sec"
xtime timespec.tv_sec: 55fcd060743a: Thu Feb 11 04:14:50 CST 2997960
crash-arm64: seek error: kernel virtual address: ffff800011771268 type: "init_uts_ns"
The attachment is the detailed log which append "-d 1" to crash cmd.
Could you please help this?
Thanks
1 year, 3 months