qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Kyle Zeng <jkjh1jkjh1@gmail.com>
To: qemu-devel@nongnu.org
Cc: richard.henderson@linaro.org
Subject: [PATCH] Dump NT_FILE note when generate coredump
Date: Mon, 11 Jan 2021 22:09:03 -0700	[thread overview]
Message-ID: <CADCLYBRh81DuwLd3WB2QyLRFwwL6WaML2pKV6Tw6zS1wbCf+pA@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 5601 bytes --]

This patch adds support for adding NT_FILE note in the ELF coredump.
It follows what's defined in readelf.
Let me know if there is any issue with the patch.
The patch is attached in plaintext below

Thanks,
Kyle
---------

From 3c42074f9e99e6b5ca840b9ee9e965fb69122ef1 Mon Sep 17 00:00:00 2001
From: Kyle ZENG <jkjh1jkjh1@gmail.com>
Date: Mon, 11 Jan 2021 21:54:09 -0700
Subject: [PATCH] add NT_FILE note for ELF core dump

Signed-off-by: Kyle ZENG <jkjh1jkjh1@gmail.com>
---
 include/elf.h        |  1 +
 linux-user/elfload.c | 92 ++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 90 insertions(+), 3 deletions(-)

diff --git a/include/elf.h b/include/elf.h
index 7a418ee..f701fd9 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -1645,6 +1645,7 @@ typedef struct elf64_shdr {
 #define NT_TASKSTRUCT 4
 #define NT_AUXV 6
 #define NT_PRXFPREG     0x46e62b7f      /* copied from
gdb5.1/include/elf/common.h */
+#define NT_FILE     0x46494c45          /* copied from
gdb/include/elf/common.h */
 #define NT_S390_GS_CB   0x30b           /* s390 guarded storage registers
*/
 #define NT_S390_VXRS_HIGH 0x30a         /* s390 vector registers 16-31 */
 #define NT_S390_VXRS_LOW  0x309         /* s390 vector registers 0-15
(lower half) */
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index a640507..c095c0c 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -3317,6 +3317,13 @@ struct target_elf_prpsinfo {
     char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
 };

+struct target_ntfile_entry {
+    abi_ulong   vm_start;
+    abi_ulong   vm_end;
+    abi_ulong   page_offset;
+    char        *path;
+};
+
 /* Here is the structure in which status of each thread is captured. */
 struct elf_thread_status {
     QTAILQ_ENTRY(elf_thread_status)  ets_link;
@@ -3677,6 +3684,84 @@ static void fill_auxv_note(struct memelfnote *note,
const TaskState *ts)
     }
 }

+static void fill_ntfile_note(struct memelfnote *note, TaskState *ts)
+{
+    GSList *map_info = read_self_maps();
+    GSList *s;
+    int count = 0;
+    int data_size = sizeof(abi_long)*2; // reserve space for num_map_entry
and page_size
+    struct target_ntfile_entry *entries = NULL;
+
+    // grab memory mapping first
+    for (s = map_info; s; s = g_slist_next(s)) {
+        MapInfo *e = (MapInfo *) s->data;
+
+        if (h2g_valid(e->start)) {
+            unsigned long min = e->start;
+            unsigned long max = e->end;
+            int flags = page_get_flags(h2g(min));
+            const char *path;
+
+            max = h2g_valid(max - 1) ?
+                max : (uintptr_t) g2h(GUEST_ADDR_MAX) + 1;
+
+            if (page_check_range(h2g(min), max - min, flags) == -1) {
+                continue;
+            }
+
+            if (h2g(min) == ts->info->stack_limit) {
+                path = "[stack]";
+            } else {
+                path = e->path;
+            }
+
+            count++;
+            entries = realloc(entries, sizeof(struct
target_ntfile_entry)*count);
+            struct target_ntfile_entry *entry = &entries[count-1];
+            memset(entry, 0, sizeof(*entry));
+
+            data_size += sizeof(abi_long)*3 + strlen(path) + 1;
+            entry->vm_start = h2g(min);
+            entry->vm_end = h2g(max - 1) + 1;
+            entry->page_offset = e->offset;
+            entry->path = strdup(path);
+        }
+    }
+
+    // prepare the memory mapping in NT_FILE format
+    char *ptr;
+    int idx = 0;
+    ptr = (char *)g_malloc0(data_size);
+    abi_long *long_ptr = (abi_long *)ptr;
+
+    // memory mappings
+    long_ptr[idx++] = count;    // number of map entries
+    long_ptr[idx++] = TARGET_PAGE_SIZE;   // target page size
+    for(int i=0; i<count; i++) {
+        struct target_ntfile_entry *entry = &entries[i];
+        long_ptr[idx++] = entry->vm_start;
+        long_ptr[idx++] = entry->vm_end;
+        long_ptr[idx++] = entry->page_offset;
+    }
+
+    // path names
+    idx *= sizeof(abi_long);
+    for(int i=0; i<count; i++) {
+        struct target_ntfile_entry *entry = &entries[i];
+        int path_size = strlen(entry->path);
+        strcpy(&ptr[idx], entry->path);
+        idx += path_size + 1;
+        free(entry->path);
+    }
+
+    // write it out
+    fill_note(note, "CORE", NT_FILE, data_size, ptr);
+
+    // cleanup
+    free(entries);
+    free_self_maps(map_info);
+}
+
 /*
  * Constructs name of coredump file.  We have following convention
  * for the name:
@@ -3807,7 +3892,7 @@ static void init_note_info(struct elf_note_info *info)
 static int fill_note_info(struct elf_note_info *info,
                           long signr, const CPUArchState *env)
 {
-#define NUMNOTES 3
+#define NUMNOTES 4
     CPUState *cpu = env_cpu((CPUArchState *)env);
     TaskState *ts = (TaskState *)cpu->opaque;
     int i;
@@ -3824,7 +3909,7 @@ static int fill_note_info(struct elf_note_info *info,

     /*
      * First fill in status (and registers) of current thread
-     * including process info & aux vector.
+     * including process info, aux vector & memory mapping.
      */
     fill_prstatus(info->prstatus, ts, signr);
     elf_core_copy_regs(&info->prstatus->pr_reg, env);
@@ -3834,7 +3919,8 @@ static int fill_note_info(struct elf_note_info *info,
     fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
               sizeof (*info->psinfo), info->psinfo);
     fill_auxv_note(&info->notes[2], ts);
-    info->numnote = 3;
+    fill_ntfile_note(&info->notes[3], ts);
+    info->numnote = NUMNOTES;

     info->notes_size = 0;
     for (i = 0; i < info->numnote; i++)
-- 
2.17.1

[-- Attachment #2: Type: text/html, Size: 6872 bytes --]

                 reply	other threads:[~2021-01-12  6:05 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=CADCLYBRh81DuwLd3WB2QyLRFwwL6WaML2pKV6Tw6zS1wbCf+pA@mail.gmail.com \
    --to=jkjh1jkjh1@gmail.com \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.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).