Blame SOURCES/use_QEMU_registers_for_active_task_backtraces.patch

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