mirror of https://github.com/crash-utility/crash
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>
This commit is contained in:
parent
fce91bec5b
commit
51f21b0d1c
9
x86_64.c
9
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)
|
||||
|
|
Loading…
Reference in New Issue