crash/0022-x86_64_irq_eframe_link_init-Fix-wrong-instruction-se.patch
Lianbo Jiang f1cd67284d Update to gdb-10.2
Release: crash-7.3.0-4

Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
2021-10-12 18:59:25 +08:00

91 lines
3.3 KiB
Diff

From 51f21b0d1c91a4ae02ebf0d8c81460ec8b6c1283 Mon Sep 17 00:00:00 2001
From: Tao Liu <ltao@redhat.com>
Date: Thu, 15 Jul 2021 17:34:29 +0800
Subject: [PATCH 22/27] x86_64_irq_eframe_link_init: Fix wrong instruction
searching range calculation
In function x86_64_irq_eframe_link_init, instruction "push xxx" is searched in
addresses range from "common_interrupt" to the next nearby symbol, in order to
calculate the value of irq_eframe_link. The searching distance is given by
max_instructions, which is calculated by end ranging address minus start ranging
address. Then crash asks gdb to disassemble max_instructions quantity of instructions.
Taking max_instructions as the quantity of disassemble instructions is inappropriate,
because most x86_64 instructions have a length longer than 1, as a consequence, much
more than the actual needed instructions get disassembled.
In gdb-7.6 crash, the extra instructions are skipped by "if (!strstr(buf, sp->name))",
which breaks if one instruction doesn't belongs to a symbol:
0xffffffff8005d5b4 <common_interrupt+0>: cld
0xffffffff8005d5b5 <common_interrupt+1>: sub $0x48,%rsp
...
0xffffffff8005d61e <common_interrupt+106>: leaveq
0xffffffff8005d61f <exit_intr>: mov %gs:0x10,%rcx <--- searching stops here
...
In gdb-10.2 crash, "exit_intr" doesn't show, however it really exist. As a result,
searching for "push xxx" will go to a wrong place.
0xffffffff8005d5b4 <common_interrupt+0>: cld
0xffffffff8005d5b5 <common_interrupt+1>: sub $0x48,%rsp
...
0xffffffff8005d61e <common_interrupt+106>: leave
0xffffffff8005d61f <common_interrupt+107>: mov %gs:0x10,%rcx <--- searching continues
...
(gdb) p exit_intr
$1 = {<text variable, no debug info>} 0xffffffff8005d61f <common_interrupt+107>
(gdb) info symbol exit_intr
common_interrupt + 107 in section .text
The previous way to determine start and end searching range is not stable, otherwise we may
encounter regression that cmd "bt" prints wrong IRQ stack. This patch fix the bug by removing
max_instructions calculation, and directly ask gdb to disassemble addresses range from
"common_interrupt" to the next nearby symbol.
Signed-off-by: Tao Liu <ltao@redhat.com>
---
x86_64.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/x86_64.c b/x86_64.c
index d0565ba26a0c..552d6194930b 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -6472,7 +6472,6 @@ x86_64_irq_eframe_link_init(void)
char buf[BUFSIZE];
char link_register[BUFSIZE];
char *arglist[MAXARGS];
- ulong max_instructions;
if (machdep->machspec->irq_eframe_link == UNINITIALIZED)
machdep->machspec->irq_eframe_link = 0;
@@ -6487,12 +6486,10 @@ x86_64_irq_eframe_link_init(void)
return;
}
- max_instructions = spn->value - sp->value;
-
open_tmpfile();
- sprintf(buf, "x/%ldi 0x%lx",
- max_instructions, sp->value);
+ sprintf(buf, "disassemble 0x%lx, 0x%lx",
+ sp->value, spn->value);
if (!gdb_pass_through(buf, pc->tmpfile, GNU_RETURN_ON_ERROR))
return;
@@ -6501,6 +6498,8 @@ x86_64_irq_eframe_link_init(void)
rewind(pc->tmpfile);
while (fgets(buf, BUFSIZE, pc->tmpfile)) {
+ if (STRNEQ(buf, "Dump of assembler code"))
+ continue;
if (!strstr(buf, sp->name))
break;
if ((c = parse_line(buf, arglist)) < 4)
--
2.30.2