Blame SOURCES/kvm-dump-Use-a-buffer-for-ELF-section-data-and-headers.patch

bf143f
From a918c7305ec7c68e8bc37b449f71e75d84124cd0 Mon Sep 17 00:00:00 2001
bf143f
From: Janosch Frank <frankja@linux.ibm.com>
bf143f
Date: Mon, 17 Oct 2022 08:38:13 +0000
bf143f
Subject: [PATCH 32/42] dump: Use a buffer for ELF section data and headers
bf143f
MIME-Version: 1.0
bf143f
Content-Type: text/plain; charset=UTF-8
bf143f
Content-Transfer-Encoding: 8bit
bf143f
bf143f
RH-Author: Cédric Le Goater <clg@redhat.com>
bf143f
RH-MergeRequest: 226: s390: Enhanced Interpretation for PCI Functions and Secure Execution guest dump
bf143f
RH-Bugzilla: 1664378 2043909
bf143f
RH-Acked-by: Thomas Huth <thuth@redhat.com>
bf143f
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
bf143f
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
bf143f
RH-Commit: [32/41] e1a03e202e67764581e486f37e13e479200e5846
bf143f
bf143f
Currently we're writing the NULL section header if we overflow the
bf143f
physical header number in the ELF header. But in the future we'll add
bf143f
custom section headers AND section data.
bf143f
bf143f
To facilitate this we need to rearange section handling a bit. As with
bf143f
the other ELF headers we split the code into a prepare and a write
bf143f
step.
bf143f
bf143f
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
bf143f
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
bf143f
Message-Id: <20221017083822.43118-2-frankja@linux.ibm.com>
bf143f
(cherry picked from commit e41ed29bcee5cb16715317bcf290f6b5c196eb0a)
bf143f
Signed-off-by: Cédric Le Goater <clg@redhat.com>
bf143f
---
bf143f
 dump/dump.c           | 75 +++++++++++++++++++++++++++++--------------
bf143f
 include/sysemu/dump.h |  2 ++
bf143f
 2 files changed, 53 insertions(+), 24 deletions(-)
bf143f
bf143f
diff --git a/dump/dump.c b/dump/dump.c
bf143f
index 88177fa886..4142b4cc0c 100644
bf143f
--- a/dump/dump.c
bf143f
+++ b/dump/dump.c
bf143f
@@ -381,31 +381,60 @@ static void write_elf_phdr_note(DumpState *s, Error **errp)
bf143f
     }
bf143f
 }
bf143f
 
bf143f
-static void write_elf_section(DumpState *s, int type, Error **errp)
bf143f
+static void prepare_elf_section_hdr_zero(DumpState *s)
bf143f
 {
bf143f
-    Elf32_Shdr shdr32;
bf143f
-    Elf64_Shdr shdr64;
bf143f
-    int shdr_size;
bf143f
-    void *shdr;
bf143f
-    int ret;
bf143f
+    if (dump_is_64bit(s)) {
bf143f
+        Elf64_Shdr *shdr64 = s->elf_section_hdrs;
bf143f
 
bf143f
-    if (type == 0) {
bf143f
-        shdr_size = sizeof(Elf32_Shdr);
bf143f
-        memset(&shdr32, 0, shdr_size);
bf143f
-        shdr32.sh_info = cpu_to_dump32(s, s->phdr_num);
bf143f
-        shdr = &shdr32;
bf143f
+        shdr64->sh_info = cpu_to_dump32(s, s->phdr_num);
bf143f
     } else {
bf143f
-        shdr_size = sizeof(Elf64_Shdr);
bf143f
-        memset(&shdr64, 0, shdr_size);
bf143f
-        shdr64.sh_info = cpu_to_dump32(s, s->phdr_num);
bf143f
-        shdr = &shdr64;
bf143f
+        Elf32_Shdr *shdr32 = s->elf_section_hdrs;
bf143f
+
bf143f
+        shdr32->sh_info = cpu_to_dump32(s, s->phdr_num);
bf143f
+    }
bf143f
+}
bf143f
+
bf143f
+static void prepare_elf_section_hdrs(DumpState *s)
bf143f
+{
bf143f
+    size_t len, sizeof_shdr;
bf143f
+
bf143f
+    /*
bf143f
+     * Section ordering:
bf143f
+     * - HDR zero
bf143f
+     */
bf143f
+    sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
bf143f
+    len = sizeof_shdr * s->shdr_num;
bf143f
+    s->elf_section_hdrs = g_malloc0(len);
bf143f
+
bf143f
+    /*
bf143f
+     * The first section header is ALWAYS a special initial section
bf143f
+     * header.
bf143f
+     *
bf143f
+     * The header should be 0 with one exception being that if
bf143f
+     * phdr_num is PN_XNUM then the sh_info field contains the real
bf143f
+     * number of segment entries.
bf143f
+     *
bf143f
+     * As we zero allocate the buffer we will only need to modify
bf143f
+     * sh_info for the PN_XNUM case.
bf143f
+     */
bf143f
+    if (s->phdr_num >= PN_XNUM) {
bf143f
+        prepare_elf_section_hdr_zero(s);
bf143f
     }
bf143f
+}
bf143f
 
bf143f
-    ret = fd_write_vmcore(shdr, shdr_size, s);
bf143f
+static void write_elf_section_headers(DumpState *s, Error **errp)
bf143f
+{
bf143f
+    size_t sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
bf143f
+    int ret;
bf143f
+
bf143f
+    prepare_elf_section_hdrs(s);
bf143f
+
bf143f
+    ret = fd_write_vmcore(s->elf_section_hdrs, s->shdr_num * sizeof_shdr, s);
bf143f
     if (ret < 0) {
bf143f
-        error_setg_errno(errp, -ret,
bf143f
-                         "dump: failed to write section header table");
bf143f
+        error_setg_errno(errp, -ret, "dump: failed to write section headers");
bf143f
     }
bf143f
+
bf143f
+    g_free(s->elf_section_hdrs);
bf143f
 }
bf143f
 
bf143f
 static void write_data(DumpState *s, void *buf, int length, Error **errp)
bf143f
@@ -592,12 +621,10 @@ static void dump_begin(DumpState *s, Error **errp)
bf143f
         return;
bf143f
     }
bf143f
 
bf143f
-    /* write section to vmcore */
bf143f
-    if (s->shdr_num) {
bf143f
-        write_elf_section(s, 1, errp);
bf143f
-        if (*errp) {
bf143f
-            return;
bf143f
-        }
bf143f
+    /* write section headers to vmcore */
bf143f
+    write_elf_section_headers(s, errp);
bf143f
+    if (*errp) {
bf143f
+        return;
bf143f
     }
bf143f
 
bf143f
     /* write notes to vmcore */
bf143f
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
bf143f
index b62513d87d..9995f65dc8 100644
bf143f
--- a/include/sysemu/dump.h
bf143f
+++ b/include/sysemu/dump.h
bf143f
@@ -177,6 +177,8 @@ typedef struct DumpState {
bf143f
     int64_t filter_area_begin;  /* Start address of partial guest memory area */
bf143f
     int64_t filter_area_length; /* Length of partial guest memory area */
bf143f
 
bf143f
+    void *elf_section_hdrs;     /* Pointer to section header buffer */
bf143f
+
bf143f
     uint8_t *note_buf;          /* buffer for notes */
bf143f
     size_t note_buf_offset;     /* the writing place in note_buf */
bf143f
     uint32_t nr_cpus;           /* number of guest's cpu */
bf143f
-- 
bf143f
2.37.3
bf143f