[Crash-utility] [PATCH v3 2/2] arm/arm64: read elf notes for qemu generated cores

Andrew Jones drjones at redhat.com
Fri Nov 20 14:16:50 UTC 2015


QEMU can generate both non-makedumpfile (just elf) and makedumpfile
formatted kdumps. In neither case will crash_notes have prstatus, as
crash_kexec doesn't run in the kernel, however the elf notes will
contain the prstatus, and we can dig them out of there.
---
 arm.c     | 22 ++++++++++++++++++++++
 arm64.c   | 22 ++++++++++++++++++++++
 defs.h    |  1 +
 netdump.c | 21 +++++++++++++++++++++
 4 files changed, 66 insertions(+)

diff --git a/arm.c b/arm.c
index ffc7c06d0f42c..8fc3d48a8ac89 100644
--- a/arm.c
+++ b/arm.c
@@ -597,6 +597,28 @@ arm_get_crash_notes(void)
 		note = (Elf32_Nhdr *)buf;
 		p = buf + sizeof(Elf32_Nhdr);
 
+		/*
+		 * dumpfiles created with qemu won't have crash_notes, but there will
+		 * be elf notes.
+		 */
+		if (note->n_namesz == 0 && (DISKDUMP_DUMPFILE() || KDUMP_DUMPFILE())) {
+			if (DISKDUMP_DUMPFILE())
+				note = diskdump_get_prstatus_percpu(i);
+			else if (KDUMP_DUMPFILE())
+				note = netdump_get_prstatus_percpu(i);
+			if (note) {
+				/*
+				 * SIZE(note_buf) accounts for a "final note", which is a
+				 * trailing empty elf note header.
+				 */
+				long notesz = SIZE(note_buf) - sizeof(Elf32_Nhdr);
+
+				if (sizeof(Elf32_Nhdr) + roundup(note->n_namesz, 4) +
+				    note->n_descsz == notesz)
+					BCOPY((char *)note, buf, notesz);
+			}
+		}
+
 		if (note->n_type != NT_PRSTATUS) {
 			error(WARNING, "invalid note (n_type != NT_PRSTATUS)\n");
 			goto fail;
diff --git a/arm64.c b/arm64.c
index 9d03d1d54b574..b399d7a5c37fe 100644
--- a/arm64.c
+++ b/arm64.c
@@ -1827,6 +1827,28 @@ arm64_get_crash_notes(void)
 		note = (Elf64_Nhdr *)buf;
 		p = buf + sizeof(Elf64_Nhdr);
 
+		/*
+		 * dumpfiles created with qemu won't have crash_notes, but there will
+		 * be elf notes.
+		 */
+		if (note->n_namesz == 0 && (DISKDUMP_DUMPFILE() || KDUMP_DUMPFILE())) {
+			if (DISKDUMP_DUMPFILE())
+				note = diskdump_get_prstatus_percpu(i);
+			else if (KDUMP_DUMPFILE())
+				note = netdump_get_prstatus_percpu(i);
+			if (note) {
+				/*
+				 * SIZE(note_buf) accounts for a "final note", which is a
+				 * trailing empty elf note header.
+				 */
+				long notesz = SIZE(note_buf) - sizeof(Elf64_Nhdr);
+
+				if (sizeof(Elf64_Nhdr) + roundup(note->n_namesz, 4) +
+				    note->n_descsz == notesz)
+					BCOPY((char *)note, buf, notesz);
+			}
+		}
+
 		if (note->n_type != NT_PRSTATUS) {
 			error(WARNING, "invalid note (n_type != NT_PRSTATUS)\n");
 			goto fail;
diff --git a/defs.h b/defs.h
index 3e5dbd99942b2..8a4045ec78c37 100644
--- a/defs.h
+++ b/defs.h
@@ -5720,6 +5720,7 @@ void dump_registers_for_qemu_mem_dump(void);
 void kdump_backup_region_init(void);
 void display_regs_from_elf_notes(int, FILE *);
 void display_ELF_note(int, int, void *, FILE *);
+void *netdump_get_prstatus_percpu(int);
 #define PRSTATUS_NOTE (1)
 #define QEMU_NOTE     (2)
 
diff --git a/netdump.c b/netdump.c
index bfa818fdef8e1..3ff49f0577c23 100644
--- a/netdump.c
+++ b/netdump.c
@@ -2345,6 +2345,27 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
 	return len;
 }
 
+void *
+netdump_get_prstatus_percpu(int cpu)
+{
+	int online;
+
+	if ((cpu < 0) || (cpu >= nd->num_prstatus_notes))
+		return NULL;
+
+	/*
+	 * If no cpu mapping was done, then there must be
+	 * a one-to-one relationship between the number
+	 * of online cpus and the number of notes.
+	 */
+	if ((online = get_cpus_online()) &&
+	    (online == kt->cpus) &&
+	    (online != nd->num_prstatus_notes))
+		return NULL;
+
+	return nd->nt_prstatus_percpu[cpu];
+}
+
 /*
  *  Send the request to the proper architecture hander.
  */
-- 
2.4.3




More information about the Crash-utility mailing list