|
|
d39c82 |
commit b4af1d9b48998186aef8cd9abc47c6d59e36114e
|
|
|
d39c82 |
Author: Dave Anderson <anderson@redhat.com>
|
|
|
d39c82 |
Date: Tue Dec 2 17:26:40 2014 -0500
|
|
|
d39c82 |
|
|
|
d39c82 |
Fix for finding the starting stack and instruction pointer hooks for
|
|
|
d39c82 |
the active tasks in x86_64 ELF or compressed dumpfiles created by the
|
|
|
d39c82 |
KVM "virsh dump --memory-only" facility. Without the patch, the
|
|
|
d39c82 |
backtraces of active tasks may show an invalid starting frame that
|
|
|
d39c82 |
indicates "__schedule". The fix displays the exception RIP and dumps
|
|
|
d39c82 |
the register contents that are stored in the dumpfile header. If the
|
|
|
d39c82 |
active task was operating in the kernel, the backtrace continues from
|
|
|
d39c82 |
there; if the task was operating in user-space, the backtrace is
|
|
|
d39c82 |
complete at that point.
|
|
|
d39c82 |
(anderson@redhat.com)
|
|
|
d39c82 |
|
|
|
d39c82 |
diff --git a/defs.h b/defs.h
|
|
|
d39c82 |
index 2e52bc4..dc2d65a 100644
|
|
|
d39c82 |
--- a/defs.h
|
|
|
d39c82 |
+++ b/defs.h
|
|
|
d39c82 |
@@ -5547,6 +5547,7 @@ int write_proc_kcore(int, void *, int, ulong, physaddr_t);
|
|
|
d39c82 |
int kcore_memory_dump(FILE *);
|
|
|
d39c82 |
void dump_registers_for_qemu_mem_dump(void);
|
|
|
d39c82 |
void kdump_backup_region_init(void);
|
|
|
d39c82 |
+void display_regs_from_elf_notes(int, FILE *);
|
|
|
d39c82 |
|
|
|
d39c82 |
/*
|
|
|
d39c82 |
* ramdump.c
|
|
|
d39c82 |
diff --git a/diskdump.c b/diskdump.c
|
|
|
d39c82 |
index 3d33fdc..6b2aab5 100644
|
|
|
d39c82 |
--- a/diskdump.c
|
|
|
d39c82 |
+++ b/diskdump.c
|
|
|
d39c82 |
@@ -102,6 +102,9 @@ map_cpus_to_prstatus_kdump_cmprs(void)
|
|
|
d39c82 |
int online, i, j, nrcpus;
|
|
|
d39c82 |
size_t size;
|
|
|
d39c82 |
|
|
|
d39c82 |
+ if (pc->flags2 & QEMU_MEM_DUMP_COMPRESSED) /* notes exist for all cpus */
|
|
|
d39c82 |
+ return;
|
|
|
d39c82 |
+
|
|
|
d39c82 |
if (!(online = get_cpus_online()) || (online == kt->cpus))
|
|
|
d39c82 |
return;
|
|
|
d39c82 |
|
|
|
d39c82 |
diff --git a/netdump.c b/netdump.c
|
|
|
d39c82 |
index 903faa0..6029a54 100644
|
|
|
d39c82 |
--- a/netdump.c
|
|
|
d39c82 |
+++ b/netdump.c
|
|
|
d39c82 |
@@ -72,6 +72,9 @@ map_cpus_to_prstatus(void)
|
|
|
d39c82 |
int online, i, j, nrcpus;
|
|
|
d39c82 |
size_t size;
|
|
|
d39c82 |
|
|
|
d39c82 |
+ if (pc->flags2 & QEMU_MEM_DUMP_ELF) /* notes exist for all cpus */
|
|
|
d39c82 |
+ return;
|
|
|
d39c82 |
+
|
|
|
d39c82 |
if (!(online = get_cpus_online()) || (online == kt->cpus))
|
|
|
d39c82 |
return;
|
|
|
d39c82 |
|
|
|
d39c82 |
@@ -2398,8 +2401,8 @@ get_regs_from_note(char *note, ulong *ip, ulong *sp)
|
|
|
d39c82 |
return user_regs;
|
|
|
d39c82 |
}
|
|
|
d39c82 |
|
|
|
d39c82 |
-static void
|
|
|
d39c82 |
-display_regs_from_elf_notes(int cpu)
|
|
|
d39c82 |
+void
|
|
|
d39c82 |
+display_regs_from_elf_notes(int cpu, FILE *ofp)
|
|
|
d39c82 |
{
|
|
|
d39c82 |
Elf32_Nhdr *note32;
|
|
|
d39c82 |
Elf64_Nhdr *note64;
|
|
|
d39c82 |
@@ -2408,13 +2411,16 @@ display_regs_from_elf_notes(int cpu)
|
|
|
d39c82 |
int c, skipped_count;
|
|
|
d39c82 |
|
|
|
d39c82 |
/*
|
|
|
d39c82 |
- * NT_PRSTATUS notes are only related to online cpus, offline cpus
|
|
|
d39c82 |
- * should be skipped.
|
|
|
d39c82 |
+ * Kdump NT_PRSTATUS notes are only related to online cpus,
|
|
|
d39c82 |
+ * so offline cpus should be skipped.
|
|
|
d39c82 |
*/
|
|
|
d39c82 |
- skipped_count = 0;
|
|
|
d39c82 |
- for (c = 0; c < cpu; c++) {
|
|
|
d39c82 |
- if (check_offline_cpu(c))
|
|
|
d39c82 |
- skipped_count++;
|
|
|
d39c82 |
+ if (pc->flags2 & QEMU_MEM_DUMP_ELF)
|
|
|
d39c82 |
+ skipped_count = 0;
|
|
|
d39c82 |
+ else {
|
|
|
d39c82 |
+ for (c = skipped_count = 0; c < cpu; c++) {
|
|
|
d39c82 |
+ if (check_offline_cpu(c))
|
|
|
d39c82 |
+ skipped_count++;
|
|
|
d39c82 |
+ }
|
|
|
d39c82 |
}
|
|
|
d39c82 |
|
|
|
d39c82 |
if ((cpu - skipped_count) >= nd->num_prstatus_notes) {
|
|
|
d39c82 |
@@ -2433,7 +2439,7 @@ display_regs_from_elf_notes(int cpu)
|
|
|
d39c82 |
len = roundup(len + note64->n_descsz, 4);
|
|
|
d39c82 |
user_regs = ((char *)note64) + len - SIZE(user_regs_struct) - sizeof(long);
|
|
|
d39c82 |
|
|
|
d39c82 |
- fprintf(fp,
|
|
|
d39c82 |
+ fprintf(ofp,
|
|
|
d39c82 |
" RIP: %016llx RSP: %016llx RFLAGS: %08llx\n"
|
|
|
d39c82 |
" RAX: %016llx RBX: %016llx RCX: %016llx\n"
|
|
|
d39c82 |
" RDX: %016llx RSI: %016llx RDI: %016llx\n"
|
|
|
d39c82 |
@@ -2473,7 +2479,7 @@ display_regs_from_elf_notes(int cpu)
|
|
|
d39c82 |
len = roundup(len + note32->n_descsz, 4);
|
|
|
d39c82 |
user_regs = ((char *)note32) + len - SIZE(user_regs_struct) - sizeof(long);
|
|
|
d39c82 |
|
|
|
d39c82 |
- fprintf(fp,
|
|
|
d39c82 |
+ fprintf(ofp,
|
|
|
d39c82 |
" EAX: %08x EBX: %08x ECX: %08x EDX: %08x\n"
|
|
|
d39c82 |
" ESP: %08x EIP: %08x ESI: %08x EDI: %08x\n"
|
|
|
d39c82 |
" CS: %04x DS: %04x ES: %04x FS: %04x\n"
|
|
|
d39c82 |
@@ -2506,7 +2512,7 @@ display_regs_from_elf_notes(int cpu)
|
|
|
d39c82 |
len = roundup(len + note64->n_namesz, 4);
|
|
|
d39c82 |
len = roundup(len + note64->n_descsz, 4);
|
|
|
d39c82 |
// user_regs = ((char *)note64) + len - SIZE(user_regs_struct) - sizeof(long);
|
|
|
d39c82 |
- fprintf(fp, "display_regs_from_elf_notes: ARM64 register dump TBD\n");
|
|
|
d39c82 |
+ fprintf(ofp, "display_regs_from_elf_notes: ARM64 register dump TBD\n");
|
|
|
d39c82 |
}
|
|
|
d39c82 |
}
|
|
|
d39c82 |
|
|
|
d39c82 |
@@ -2519,7 +2525,7 @@ dump_registers_for_elf_dumpfiles(void)
|
|
|
d39c82 |
error(FATAL, "-r option not supported for this dumpfile\n");
|
|
|
d39c82 |
|
|
|
d39c82 |
if (NETDUMP_DUMPFILE()) {
|
|
|
d39c82 |
- display_regs_from_elf_notes(0);
|
|
|
d39c82 |
+ display_regs_from_elf_notes(0, fp);
|
|
|
d39c82 |
return;
|
|
|
d39c82 |
}
|
|
|
d39c82 |
|
|
|
d39c82 |
@@ -2530,7 +2536,7 @@ dump_registers_for_elf_dumpfiles(void)
|
|
|
d39c82 |
}
|
|
|
d39c82 |
|
|
|
d39c82 |
fprintf(fp, "%sCPU %d:\n", c ? "\n" : "", c);
|
|
|
d39c82 |
- display_regs_from_elf_notes(c);
|
|
|
d39c82 |
+ display_regs_from_elf_notes(c, fp);
|
|
|
d39c82 |
}
|
|
|
d39c82 |
}
|
|
|
d39c82 |
|
|
|
d39c82 |
@@ -2556,7 +2562,8 @@ get_netdump_regs_x86_64(struct bt_info *bt, ulong *ripp, ulong *rspp)
|
|
|
d39c82 |
bt->flags |= BT_DUMPFILE_SEARCH;
|
|
|
d39c82 |
|
|
|
d39c82 |
if (((NETDUMP_DUMPFILE() || KDUMP_DUMPFILE()) &&
|
|
|
d39c82 |
- VALID_STRUCT(user_regs_struct) && (bt->task == tt->panic_task)) ||
|
|
|
d39c82 |
+ VALID_STRUCT(user_regs_struct) &&
|
|
|
d39c82 |
+ ((bt->task == tt->panic_task) || (pc->flags2 & QEMU_MEM_DUMP_ELF))) ||
|
|
|
d39c82 |
(KDUMP_DUMPFILE() && (kt->flags & DWARF_UNWIND) &&
|
|
|
d39c82 |
(bt->flags & BT_DUMPFILE_SEARCH))) {
|
|
|
d39c82 |
if (nd->num_prstatus_notes > 1)
|
|
|
d39c82 |
diff --git a/task.c b/task.c
|
|
|
d39c82 |
index f5bbe64..147ff5c 100644
|
|
|
d39c82 |
--- a/task.c
|
|
|
d39c82 |
+++ b/task.c
|
|
|
d39c82 |
@@ -483,7 +483,7 @@ task_init(void)
|
|
|
d39c82 |
tt->this_task = pid_to_task(active_pid);
|
|
|
d39c82 |
}
|
|
|
d39c82 |
else {
|
|
|
d39c82 |
- if (KDUMP_DUMPFILE() && !(pc->flags2 & QEMU_MEM_DUMP_ELF))
|
|
|
d39c82 |
+ if (KDUMP_DUMPFILE())
|
|
|
d39c82 |
map_cpus_to_prstatus();
|
|
|
d39c82 |
else if (ELF_NOTES_VALID() && DISKDUMP_DUMPFILE())
|
|
|
d39c82 |
map_cpus_to_prstatus_kdump_cmprs();
|
|
|
d39c82 |
diff --git a/x86_64.c b/x86_64.c
|
|
|
d39c82 |
index bbf1326..df6c561 100644
|
|
|
d39c82 |
--- a/x86_64.c
|
|
|
d39c82 |
+++ b/x86_64.c
|
|
|
d39c82 |
@@ -2963,11 +2963,13 @@ x86_64_low_budget_back_trace_cmd(struct bt_info *bt_in)
|
|
|
d39c82 |
diskdump_display_regs(bt->tc->processor, ofp);
|
|
|
d39c82 |
else if (SADUMP_DUMPFILE())
|
|
|
d39c82 |
sadump_display_regs(bt->tc->processor, ofp);
|
|
|
d39c82 |
+ else if (pc->flags2 & QEMU_MEM_DUMP_ELF)
|
|
|
d39c82 |
+ display_regs_from_elf_notes(bt->tc->processor, ofp);
|
|
|
d39c82 |
return;
|
|
|
d39c82 |
} else if ((bt->flags & BT_KERNEL_SPACE) &&
|
|
|
d39c82 |
(KVMDUMP_DUMPFILE() ||
|
|
|
d39c82 |
(ELF_NOTES_VALID() && DISKDUMP_DUMPFILE()) ||
|
|
|
d39c82 |
- SADUMP_DUMPFILE())) {
|
|
|
d39c82 |
+ SADUMP_DUMPFILE() || (pc->flags2 & QEMU_MEM_DUMP_ELF))) {
|
|
|
d39c82 |
fprintf(ofp, " [exception RIP: ");
|
|
|
d39c82 |
if ((sp = value_search(bt->instptr, &offset))) {
|
|
|
d39c82 |
fprintf(ofp, "%s", sp->name);
|
|
|
d39c82 |
@@ -2983,6 +2985,9 @@ x86_64_low_budget_back_trace_cmd(struct bt_info *bt_in)
|
|
|
d39c82 |
diskdump_display_regs(bt->tc->processor, ofp);
|
|
|
d39c82 |
else if (SADUMP_DUMPFILE())
|
|
|
d39c82 |
sadump_display_regs(bt->tc->processor, ofp);
|
|
|
d39c82 |
+ else if (pc->flags2 & QEMU_MEM_DUMP_ELF)
|
|
|
d39c82 |
+ display_regs_from_elf_notes(bt->tc->processor, ofp);
|
|
|
d39c82 |
+
|
|
|
d39c82 |
} else if (bt->flags & BT_START) {
|
|
|
d39c82 |
x86_64_print_stack_entry(bt, ofp, level,
|
|
|
d39c82 |
0, bt->instptr);
|
|
|
d39c82 |
@@ -4565,7 +4570,7 @@ skip_stage:
|
|
|
d39c82 |
*rip = ur_rip;
|
|
|
d39c82 |
*rsp = ur_rsp;
|
|
|
d39c82 |
if (is_kernel_text(ur_rip) &&
|
|
|
d39c82 |
- (INSTACK(ur_rsp, bt) ||
|
|
|
d39c82 |
+ (INSTACK(ur_rsp, bt_in) ||
|
|
|
d39c82 |
in_alternate_stack(bt->tc->processor, ur_rsp)))
|
|
|
d39c82 |
bt_in->flags |= BT_KERNEL_SPACE;
|
|
|
d39c82 |
if (!is_kernel_text(ur_rip) && in_user_stack(bt->tc->task, ur_rsp))
|
|
|
d39c82 |
@@ -4596,14 +4601,14 @@ skip_stage:
|
|
|
d39c82 |
ur_rip = ULONG(user_regs + OFFSET(user_regs_struct_rip));
|
|
|
d39c82 |
ur_rsp = ULONG(user_regs + OFFSET(user_regs_struct_rsp));
|
|
|
d39c82 |
if (!in_alternate_stack(bt->tc->processor, ur_rsp) &&
|
|
|
d39c82 |
- !stkptr_to_task(bt->task)) {
|
|
|
d39c82 |
+ !stkptr_to_task(ur_rsp)) {
|
|
|
d39c82 |
if (CRASHDEBUG(1))
|
|
|
d39c82 |
error(INFO,
|
|
|
d39c82 |
"x86_64_get_dumpfile_stack_frame: "
|
|
|
d39c82 |
"ELF mismatch: RSP: %lx task: %lx\n",
|
|
|
d39c82 |
ur_rsp, bt->task);
|
|
|
d39c82 |
} else {
|
|
|
d39c82 |
- if (is_kernel_text(ur_rip) && (INSTACK(ur_rsp, bt) ||
|
|
|
d39c82 |
+ if (is_kernel_text(ur_rip) && (INSTACK(ur_rsp, bt_in) ||
|
|
|
d39c82 |
in_alternate_stack(bt->tc->processor, ur_rsp)))
|
|
|
d39c82 |
bt_in->flags |= BT_KERNEL_SPACE;
|
|
|
d39c82 |
if (!is_kernel_text(ur_rip) && in_user_stack(bt->tc->task, ur_rsp))
|
|
|
d39c82 |
|