[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 18/21] dump: use qga VMDUMP_INFO for ELF dump
From: |
Marc-André Lureau |
Subject: |
[Qemu-devel] [PATCH 18/21] dump: use qga VMDUMP_INFO for ELF dump |
Date: |
Sat, 11 Mar 2017 17:22:53 +0400 |
Add vmcoreinfo ELF note.
NUMBRE(phys_base) in vmcoreinfo has only been recently introduced in
Linux 4.10 ("kexec: export the value of phys_base instead of symbol
address"). To accomadate for older kernels, modify the vmcoreinfo to add
the new fields and help newer crash that will use it.
Signed-off-by: Marc-André Lureau <address@hidden>
---
include/sysemu/dump.h | 2 +
dump.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 135 insertions(+)
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index ef931be469..ff0e9894b7 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -191,6 +191,8 @@ typedef struct DumpState {
* this could be used to calculate
* how much work we have
* finished. */
+ uint8_t *vmcoreinfo;
+ size_t vmcoreinfo_size;
} DumpState;
uint16_t cpu_to_dump16(DumpState *s, uint16_t val);
diff --git a/dump.c b/dump.c
index 68b406459e..0ebfb5471a 100644
--- a/dump.c
+++ b/dump.c
@@ -27,6 +27,7 @@
#include "qapi/qmp/qerror.h"
#include "qmp-commands.h"
#include "qapi-event.h"
+#include "qemu/error-report.h"
#include <zlib.h>
#ifdef CONFIG_LZO
@@ -82,6 +83,8 @@ static int dump_cleanup(DumpState *s)
if (s->resume) {
vm_start();
}
+ g_free(s->vmcoreinfo);
+ s->vmcoreinfo = NULL;
return 0;
}
@@ -232,6 +235,19 @@ static inline int cpu_index(CPUState *cpu)
return cpu->cpu_index + 1;
}
+static void write_vmcoreinfo_note(WriteCoreDumpFunction f, DumpState *s,
+ Error **errp)
+{
+ int ret;
+
+ if (s->vmcoreinfo) {
+ ret = f(s->vmcoreinfo, s->vmcoreinfo_size, s);
+ if (ret < 0) {
+ error_setg(errp, "dump: failed to write vmcoreinfo");
+ }
+ }
+}
+
static void write_elf64_notes(WriteCoreDumpFunction f, DumpState *s,
Error **errp)
{
@@ -255,6 +271,8 @@ static void write_elf64_notes(WriteCoreDumpFunction f,
DumpState *s,
return;
}
}
+
+ write_vmcoreinfo_note(f, s, errp);
}
static void write_elf32_note(DumpState *s, Error **errp)
@@ -300,6 +318,8 @@ static void write_elf32_notes(WriteCoreDumpFunction f,
DumpState *s,
return;
}
}
+
+ write_vmcoreinfo_note(f, s, errp);
}
static void write_elf_section(DumpState *s, int type, Error **errp)
@@ -711,6 +731,50 @@ static int buf_write_note(const void *buf, size_t size,
void *opaque)
return 0;
}
+static void get_note_sizes(DumpState *s, const void *note,
+ uint64_t *note_head_size,
+ uint64_t *name_size,
+ uint64_t *desc_size)
+{
+ uint64_t note_head_sz;
+ uint64_t name_sz;
+ uint64_t desc_sz;
+
+ if (s->dump_info.d_class == ELFCLASS64) {
+ const Elf64_Nhdr *hdr = note;
+ note_head_sz = sizeof(Elf64_Nhdr);
+ name_sz = hdr->n_namesz;
+ desc_sz = hdr->n_descsz;
+ } else {
+ const Elf32_Nhdr *hdr = note;
+ note_head_sz = sizeof(Elf32_Nhdr);
+ name_sz = hdr->n_namesz;
+ desc_sz = hdr->n_descsz;
+ }
+
+ if (note_head_size) {
+ *note_head_size = note_head_sz;
+ }
+ if (name_size) {
+ *name_size = name_sz;
+ }
+ if (desc_size) {
+ *desc_size = desc_sz;
+ }
+}
+
+static void set_note_desc_size(DumpState *s, void *note,
+ uint64_t desc_size)
+{
+ if (s->dump_info.d_class == ELFCLASS64) {
+ Elf64_Nhdr *hdr = note;
+ hdr->n_descsz = desc_size;
+ } else {
+ Elf32_Nhdr *hdr = note;
+ hdr->n_descsz = desc_size;
+ }
+}
+
/* write common header, sub header and elf note to vmcore */
static void create_header32(DumpState *s, Error **errp)
{
@@ -1485,6 +1549,42 @@ static int64_t dump_calculate_size(DumpState *s)
return total;
}
+static void vmcoreinfo_add_phys_base(DumpState *s)
+{
+ uint64_t size, note_head_size, name_size;
+ char **lines, *physbase = NULL;
+ uint8_t *newvmci, *vmci;
+ size_t i;
+
+ get_note_sizes(s, s->vmcoreinfo, ¬e_head_size, &name_size, &size);
+ note_head_size = ((note_head_size + 3) / 4) * 4;
+ name_size = ((name_size + 3) / 4) * 4;
+ vmci = s->vmcoreinfo + note_head_size + name_size;
+ *(vmci + size) = '\0';
+ lines = g_strsplit((char *)vmci, "\n", -1);
+ for (i = 0; lines[i]; i++) {
+ if (g_str_has_prefix(lines[i], "NUMBER(phys_base)=")) {
+ goto end;
+ }
+ }
+
+ physbase = g_strdup_printf("\nNUMBER(phys_base)=%ld",
+ s->dump_info.phys_base);
+ s->vmcoreinfo_size =
+ ((note_head_size + name_size + size + strlen(physbase) + 3) / 4) * 4;
+
+ newvmci = g_malloc(s->vmcoreinfo_size);
+ memcpy(newvmci, s->vmcoreinfo, note_head_size + name_size + size - 1);
+ memcpy(newvmci + note_head_size + name_size + size - 1, physbase,
+ strlen(physbase) + 1);
+ g_free(s->vmcoreinfo);
+ s->vmcoreinfo = newvmci;
+ set_note_desc_size(s, s->vmcoreinfo, size + strlen(physbase));
+
+end:
+ g_strfreev(lines);
+}
+
static void dump_init(DumpState *s, int fd, bool has_format,
DumpGuestMemoryFormat format, bool paging, bool
has_filter,
int64_t begin, int64_t length, Error **errp)
@@ -1560,6 +1660,39 @@ static void dump_init(DumpState *s, int fd, bool
has_format,
goto cleanup;
}
+ if (dump_info.has_phys_base) {
+ s->dump_info.phys_base = dump_info.phys_base;
+ }
+ if (dump_info.vmcoreinfo) {
+ uint64_t addr, size, note_head_size, name_size, desc_size;
+ int count = sscanf(dump_info.vmcoreinfo, "%" PRIx64 " %" PRIx64,
+ &addr, &size);
+ if (count != 2) {
+ /* non fatal error */
+ error_report("Failed to parse vmcoreinfo");
+ } else {
+ assert(!s->vmcoreinfo);
+ s->vmcoreinfo = g_malloc(size);
+ cpu_physical_memory_read(addr, s->vmcoreinfo, size);
+
+ get_note_sizes(s, s->vmcoreinfo,
+ ¬e_head_size, &name_size, &desc_size);
+ s->vmcoreinfo_size = ((note_head_size + 3) / 4 +
+ (name_size + 3) / 4 +
+ (desc_size + 3) / 4) * 4;
+ if (s->vmcoreinfo_size > size) {
+ error_report("Invalid vmcoreinfo header, size mismatch");
+ g_free(s->vmcoreinfo);
+ s->vmcoreinfo = NULL;
+ } else {
+ if (dump_info.has_phys_base) {
+ vmcoreinfo_add_phys_base(s);
+ }
+ s->note_size += s->vmcoreinfo_size;
+ }
+ }
+ }
+
/* get memory mapping */
if (paging) {
qemu_get_guest_memory_mapping(&s->list, &s->guest_phys_blocks, &err);
--
2.12.0.191.gc5d8de91d
- [Qemu-devel] [PATCH 08/21] qdev: use int and uint properties, (continued)
- [Qemu-devel] [PATCH 08/21] qdev: use int and uint properties, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 10/21] Use uint property getter/setter where appropriate, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 11/21] qdict: learn to lookup quint, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 12/21] test-qga: drop everything until guest-sync, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 13/21] qga: report error on keyfile dump error, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 14/21] qga: add and populate VMDumpInfo, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 15/21] qga: register event emit function, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 16/21] qga: emit VMDUMP_INFO event, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 17/21] virtio-channel: parse qga stream for VMDUMP_INFO event, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 18/21] dump: use qga VMDUMP_INFO for ELF dump,
Marc-André Lureau <=
- [Qemu-devel] [PATCH 19/21] kdump: write vmcoreinfo in header, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 20/21] scripts/dump-guest-memory.py: fix int128_get64 on recent gcc, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 21/21] scripts/dump-guest-memory.py: add VMCOREINFO, Marc-André Lureau, 2017/03/11
- Re: [Qemu-devel] [PATCH 00/21] WIP: dump: add kaslr support (for after 2.9), no-reply, 2017/03/11
- Re: [Qemu-devel] [PATCH 00/21] WIP: dump: add kaslr support (for after 2.9), Dave Anderson, 2017/03/11