From: "Michael S. Tsirkin" <mst@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
"Marc-André Lureau" <marcandre.lureau@redhat.com>
Subject: [Qemu-devel] [PULL 05/26] dump: add guest ELF note
Date: Sun, 15 Oct 2017 06:22:55 +0300 [thread overview]
Message-ID: <1508036858-13479-6-git-send-email-mst@redhat.com> (raw)
In-Reply-To: <1508036858-13479-1-git-send-email-mst@redhat.com>
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Read the guest ELF PT_NOTE from guest memory when fw_cfg
etc/vmcoreinfo entry provides the location, and write it as an
additional note in the dump.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/sysemu/dump.h | 2 +
dump.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 109 insertions(+)
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index 2672a15..df43bd0 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -192,6 +192,8 @@ typedef struct DumpState {
* this could be used to calculate
* how much work we have
* finished. */
+ uint8_t *guest_note; /* ELF note content */
+ size_t guest_note_size;
} DumpState;
uint16_t cpu_to_dump16(DumpState *s, uint16_t val);
diff --git a/dump.c b/dump.c
index 7ebcf55..1479f1f 100644
--- a/dump.c
+++ b/dump.c
@@ -25,6 +25,8 @@
#include "qapi/qmp/qerror.h"
#include "qmp-commands.h"
#include "qapi-event.h"
+#include "qemu/error-report.h"
+#include "hw/misc/vmcoreinfo.h"
#include <zlib.h>
#ifdef CONFIG_LZO
@@ -37,6 +39,13 @@
#define ELF_MACHINE_UNAME "Unknown"
#endif
+#define MAX_GUEST_NOTE_SIZE (1 << 20) /* 1MB should be enough */
+
+#define ELF_NOTE_SIZE(hdr_size, name_size, desc_size) \
+ ((DIV_ROUND_UP((hdr_size), 4) + \
+ DIV_ROUND_UP((name_size), 4) + \
+ DIV_ROUND_UP((desc_size), 4)) * 4)
+
uint16_t cpu_to_dump16(DumpState *s, uint16_t val)
{
if (s->dump_info.d_endian == ELFDATA2LSB) {
@@ -75,6 +84,8 @@ static int dump_cleanup(DumpState *s)
guest_phys_blocks_free(&s->guest_phys_blocks);
memory_mapping_list_free(&s->list);
close(s->fd);
+ g_free(s->guest_note);
+ s->guest_note = NULL;
if (s->resume) {
if (s->detached) {
qemu_mutex_lock_iothread();
@@ -234,6 +245,19 @@ static inline int cpu_index(CPUState *cpu)
return cpu->cpu_index + 1;
}
+static void write_guest_note(WriteCoreDumpFunction f, DumpState *s,
+ Error **errp)
+{
+ int ret;
+
+ if (s->guest_note) {
+ ret = f(s->guest_note, s->guest_note_size, s);
+ if (ret < 0) {
+ error_setg(errp, "dump: failed to write guest note");
+ }
+ }
+}
+
static void write_elf64_notes(WriteCoreDumpFunction f, DumpState *s,
Error **errp)
{
@@ -257,6 +281,8 @@ static void write_elf64_notes(WriteCoreDumpFunction f, DumpState *s,
return;
}
}
+
+ write_guest_note(f, s, errp);
}
static void write_elf32_note(DumpState *s, Error **errp)
@@ -302,6 +328,8 @@ static void write_elf32_notes(WriteCoreDumpFunction f, DumpState *s,
return;
}
}
+
+ write_guest_note(f, s, errp);
}
static void write_elf_section(DumpState *s, int type, Error **errp)
@@ -713,6 +741,44 @@ static int buf_write_note(const void *buf, size_t size, void *opaque)
return 0;
}
+/*
+ * This function retrieves various sizes from an elf header.
+ *
+ * @note has to be a valid ELF note. The return sizes are unmodified
+ * (not padded or rounded up to be multiple of 4).
+ */
+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 = tswap64(hdr->n_namesz);
+ desc_sz = tswap64(hdr->n_descsz);
+ } else {
+ const Elf32_Nhdr *hdr = note;
+ note_head_sz = sizeof(Elf32_Nhdr);
+ name_sz = tswap32(hdr->n_namesz);
+ desc_sz = tswap32(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;
+ }
+}
+
/* write common header, sub header and elf note to vmcore */
static void create_header32(DumpState *s, Error **errp)
{
@@ -1491,6 +1557,7 @@ 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)
{
+ VMCoreInfoState *vmci = vmcoreinfo_find();
CPUState *cpu;
int nr_cpus;
Error *err = NULL;
@@ -1568,6 +1635,46 @@ static void dump_init(DumpState *s, int fd, bool has_format,
goto cleanup;
}
+ /*
+ * The goal of this block is to copy the guest note out of
+ * the guest. Failure to do so is not fatal for dumping.
+ */
+ if (vmci) {
+ uint64_t addr, note_head_size, name_size, desc_size;
+ uint32_t size;
+ uint16_t format;
+
+ note_head_size = s->dump_info.d_class == ELFCLASS32 ?
+ sizeof(Elf32_Nhdr) : sizeof(Elf64_Nhdr);
+
+ format = le16_to_cpu(vmci->vmcoreinfo.guest_format);
+ size = le32_to_cpu(vmci->vmcoreinfo.size);
+ addr = le64_to_cpu(vmci->vmcoreinfo.paddr);
+ if (!vmci->has_vmcoreinfo) {
+ warn_report("guest note is not present");
+ } else if (size < note_head_size || size > MAX_GUEST_NOTE_SIZE) {
+ warn_report("guest note size is invalid: %" PRIu32, size);
+ } else if (format != VMCOREINFO_FORMAT_ELF) {
+ warn_report("guest note format is unsupported: %" PRIu16, format);
+ } else {
+ s->guest_note = g_malloc(size + 1); /* +1 for adding \0 */
+ cpu_physical_memory_read(addr, s->guest_note, size);
+
+ get_note_sizes(s, s->guest_note, NULL, &name_size, &desc_size);
+ s->guest_note_size = ELF_NOTE_SIZE(note_head_size, name_size,
+ desc_size);
+ if (name_size > MAX_GUEST_NOTE_SIZE ||
+ desc_size > MAX_GUEST_NOTE_SIZE ||
+ s->guest_note_size > size) {
+ warn_report("Invalid guest note header");
+ g_free(s->guest_note);
+ s->guest_note = NULL;
+ } else {
+ s->note_size += s->guest_note_size;
+ }
+ }
+ }
+
/* get memory mapping */
if (paging) {
qemu_get_guest_memory_mapping(&s->list, &s->guest_phys_blocks, &err);
--
MST
next prev parent reply other threads:[~2017-10-15 3:23 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-15 3:22 [Qemu-devel] [PULL 00/26] pc, pci, virtio: fixes, features Michael S. Tsirkin
2017-10-15 3:22 ` [Qemu-devel] [PULL 01/26] xio3130_downstream: Report error if pcie_chassis_add_slot() failed Michael S. Tsirkin
2017-10-15 3:22 ` [Qemu-devel] [PULL 02/26] pci: Set err to errp directly rather than through error_propagate() Michael S. Tsirkin
2017-10-15 3:22 ` [Qemu-devel] [PULL 03/26] fw_cfg: add write callback Michael S. Tsirkin
2017-10-15 3:22 ` [Qemu-devel] [PULL 04/26] hw/misc: add vmcoreinfo device Michael S. Tsirkin
2017-10-15 3:22 ` Michael S. Tsirkin [this message]
2017-10-15 3:22 ` [Qemu-devel] [PULL 06/26] dump: update phys_base header field based on VMCOREINFO content Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 07/26] kdump: set vmcoreinfo location Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 08/26] scripts/dump-guest-memory.py: add vmcoreinfo Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 09/26] MAINTAINERS: add Dump maintainers Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 10/26] virtio/vhost: reset dev->log after syncing Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 11/26] pci: allow 32-bit PCI IO accesses to pass through the PCI bridge Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 12/26] hw/pci-bridge/pcie_pci_bridge: properly handle MSI unavailability case Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 13/26] virtio/pci/migration: Convert to VMState Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 14/26] PCI: PCIe access should always be little endian Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 15/26] pci: conventional-pci-device and pci-express-device interfaces Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 16/26] pci: Add interface names to hybrid PCI devices Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 17/26] pci: Add INTERFACE_PCIE_DEVICE to all PCIe devices Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 18/26] pci: Add INTERFACE_CONVENTIONAL_PCI_DEVICE to Conventional PCI devices Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 19/26] xen/pt: Mark TYPE_XEN_PT_DEVICE as hybrid Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 20/26] pci: Validate interfaces on base_class_init Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 21/26] hw/gen_pcie_root_port: make IO RO 0 on IO disabled Michael S. Tsirkin
2017-10-15 3:23 ` [Qemu-devel] [PULL 22/26] virtio: fix descriptor counting in virtqueue_pop Michael S. Tsirkin
2017-10-15 3:24 ` [Qemu-devel] [PULL 23/26] virtio-pci: Replace modern_as with direct access to modern_bar Michael S. Tsirkin
2017-10-15 3:24 ` [Qemu-devel] [PULL 24/26] isapc: Remove unnecessary migration compatibility code Michael S. Tsirkin
2017-10-15 3:24 ` [Qemu-devel] [PULL 25/26] pc: remove useless hot_add_cpu initialisation Michael S. Tsirkin
2017-10-15 3:24 ` [Qemu-devel] [PULL 26/26] tests/pxe: Test more NICs when running in SPEED=slow mode Michael S. Tsirkin
2017-10-16 17:29 ` [Qemu-devel] [PULL 00/26] pc, pci, virtio: fixes, features Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1508036858-13479-6-git-send-email-mst@redhat.com \
--to=mst@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).