qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Richard Henderson <richard.henderson@linaro.org>
To: qemu-devel@nongnu.org
Subject: [PATCH 13/60] linux-user/elfload: Rely on walk_memory_regions for vmas
Date: Fri,  1 Mar 2024 13:05:32 -1000	[thread overview]
Message-ID: <20240301230619.661008-14-richard.henderson@linaro.org> (raw)
In-Reply-To: <20240301230619.661008-1-richard.henderson@linaro.org>

Rather than creating new data structures for vma,
rely on the IntervalTree used by walk_memory_regions.

Use PAGE_* constants, per the page table api, rather
than PROT_* constants, per the mmap api.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/elfload.c | 213 ++++++++++++++++---------------------------
 1 file changed, 78 insertions(+), 135 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 47b5ce3005..ae0abc4931 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -4041,29 +4041,6 @@ struct target_elf_prpsinfo {
     char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
 };
 
-struct vm_area_struct {
-    target_ulong   vma_start;  /* start vaddr of memory region */
-    target_ulong   vma_end;    /* end vaddr of memory region */
-    abi_ulong      vma_flags;  /* protection etc. flags for the region */
-    QTAILQ_ENTRY(vm_area_struct) vma_link;
-};
-
-struct mm_struct {
-    QTAILQ_HEAD(, vm_area_struct) mm_mmap;
-    int mm_count;           /* number of mappings */
-};
-
-static void vma_init(struct mm_struct *);
-static void vma_delete(struct mm_struct *);
-static int vma_add_mapping(struct mm_struct *, target_ulong,
-                           target_ulong, abi_ulong);
-static int vma_get_mapping_count(const struct mm_struct *);
-static struct vm_area_struct *vma_first(const struct mm_struct *);
-static struct vm_area_struct *vma_next(struct vm_area_struct *);
-static abi_ulong vma_dump_size(const struct vm_area_struct *);
-static int vma_walker(void *priv, target_ulong start, target_ulong end,
-                      unsigned long flags);
-
 #ifdef BSWAP_NEEDED
 static void bswap_prstatus(struct target_elf_prstatus *prstatus)
 {
@@ -4105,69 +4082,14 @@ static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {}
 static inline void bswap_note(struct elf_note *en) { }
 #endif /* BSWAP_NEEDED */
 
-/*
- * Minimal support for linux memory regions.  These are needed
- * when we are finding out what memory exactly belongs to
- * emulated process.  No locks needed here, as long as
- * thread that received the signal is stopped.
- */
-
-static void vma_init(struct mm_struct *mm)
-{
-    mm->mm_count = 0;
-    QTAILQ_INIT(&mm->mm_mmap);
-}
-
-static void vma_delete(struct mm_struct *mm)
-{
-    struct vm_area_struct *vma;
-
-    while ((vma = vma_first(mm)) != NULL) {
-        QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link);
-        g_free(vma);
-    }
-}
-
-static int vma_add_mapping(struct mm_struct *mm, target_ulong start,
-                           target_ulong end, abi_ulong flags)
-{
-    struct vm_area_struct *vma;
-
-    if ((vma = g_malloc0(sizeof (*vma))) == NULL)
-        return (-1);
-
-    vma->vma_start = start;
-    vma->vma_end = end;
-    vma->vma_flags = flags;
-
-    QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link);
-    mm->mm_count++;
-
-    return (0);
-}
-
-static struct vm_area_struct *vma_first(const struct mm_struct *mm)
-{
-    return (QTAILQ_FIRST(&mm->mm_mmap));
-}
-
-static struct vm_area_struct *vma_next(struct vm_area_struct *vma)
-{
-    return (QTAILQ_NEXT(vma, vma_link));
-}
-
-static int vma_get_mapping_count(const struct mm_struct *mm)
-{
-    return (mm->mm_count);
-}
-
 /*
  * Calculate file (dump) size of given memory region.
  */
-static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
+static size_t vma_dump_size(target_ulong start, target_ulong end,
+                            unsigned long flags)
 {
     /* The area must be readable. */
-    if (!(vma->vma_flags & PROT_READ)) {
+    if (!(flags & PAGE_READ)) {
         return 0;
     }
 
@@ -4176,22 +4098,13 @@ static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
      * non-writable code that debugger can read directly from
      * target library etc. If there is no elf header, we dump it.
      */
-    if (!(vma->vma_flags & PROT_WRITE) &&
-        (vma->vma_flags & PROT_EXEC) &&
-        memcmp(g2h_untagged(vma->vma_start), ELFMAG, SELFMAG) == 0) {
+    if (!(flags & PAGE_WRITE_ORG) &&
+        (flags & PAGE_EXEC) &&
+        memcmp(g2h_untagged(start), ELFMAG, SELFMAG) == 0) {
         return 0;
     }
 
-    return vma->vma_end - vma->vma_start;
-}
-
-static int vma_walker(void *priv, target_ulong start, target_ulong end,
-                      unsigned long flags)
-{
-    struct mm_struct *mm = (struct mm_struct *)priv;
-
-    vma_add_mapping(mm, start, end, flags);
-    return (0);
+    return end - start;
 }
 
 static size_t size_note(const char *name, size_t datasz)
@@ -4367,6 +4280,61 @@ static int dump_write(int fd, const void *ptr, size_t size)
     return (0);
 }
 
+typedef struct {
+    unsigned count;
+    size_t size;
+} CountAndSizeRegions;
+
+static int wmr_count_and_size_regions(void *opaque, target_ulong start,
+                                      target_ulong end, unsigned long flags)
+{
+    CountAndSizeRegions *css = opaque;
+
+    css->count++;
+    css->size += vma_dump_size(start, end, flags);
+    return 0;
+}
+
+typedef struct {
+    struct elf_phdr *phdr;
+    off_t offset;
+} FillRegionPhdr;
+
+static int wmr_fill_region_phdr(void *opaque, target_ulong start,
+                                target_ulong end, unsigned long flags)
+{
+    FillRegionPhdr *d = opaque;
+    struct elf_phdr *phdr = d->phdr;
+
+    phdr->p_type = PT_LOAD;
+    phdr->p_vaddr = start;
+    phdr->p_paddr = 0;
+    phdr->p_filesz = vma_dump_size(start, end, flags);
+    phdr->p_offset = d->offset;
+    d->offset += phdr->p_filesz;
+    phdr->p_memsz = end - start;
+    phdr->p_flags = (flags & PAGE_READ ? PF_R : 0)
+                  | (flags & PAGE_WRITE_ORG ? PF_W : 0)
+                  | (flags & PAGE_EXEC ? PF_X : 0);
+    phdr->p_align = ELF_EXEC_PAGESIZE;
+
+    bswap_phdr(phdr, 1);
+    d->phdr = phdr + 1;
+    return 0;
+}
+
+static int wmr_write_region(void *opaque, target_ulong start,
+                            target_ulong end, unsigned long flags)
+{
+    int fd = *(int *)opaque;
+    size_t size = vma_dump_size(start, end, flags);
+
+    if (!size) {
+        return 0;
+    }
+    return dump_write(fd, g2h_untagged(start), size);
+}
+
 /*
  * Write out ELF coredump.
  *
@@ -4414,12 +4382,11 @@ static int elf_core_dump(int signr, const CPUArchState *env)
 {
     const CPUState *cpu = env_cpu((CPUArchState *)env);
     const TaskState *ts = (const TaskState *)cpu->opaque;
-    struct vm_area_struct *vma;
     struct rlimit dumpsize;
-    struct mm_struct mm;
+    CountAndSizeRegions css;
     off_t offset, note_offset, data_offset;
     size_t note_size;
-    int segs, cpus, ret;
+    int cpus, ret;
     int fd = -1;
     CPUState *cpu_iter;
 
@@ -4438,9 +4405,8 @@ static int elf_core_dump(int signr, const CPUArchState *env)
      * Walk through target process memory mappings and
      * set up structure containing this information.
      */
-    vma_init(&mm);
-    walk_memory_regions(&mm, vma_walker);
-    segs = vma_get_mapping_count(&mm);
+    memset(&css, 0, sizeof(css));
+    walk_memory_regions(&css, wmr_count_and_size_regions);
 
     cpus = 0;
     CPU_FOREACH(cpu_iter) {
@@ -4448,22 +4414,18 @@ static int elf_core_dump(int signr, const CPUArchState *env)
     }
 
     offset = sizeof(struct elfhdr);
-    offset += (segs + 1) * sizeof(struct elf_phdr);
+    offset += (css.count + 1) * sizeof(struct elf_phdr);
     note_offset = offset;
 
     offset += size_note("CORE", ts->info->auxv_len);
     offset += size_note("CORE", sizeof(struct target_elf_prpsinfo));
     offset += size_note("CORE", sizeof(struct target_elf_prstatus)) * cpus;
     note_size = offset - note_offset;
-    offset = ROUND_UP(offset, ELF_EXEC_PAGESIZE);
-    data_offset = offset;
-
-    for (vma = vma_first(&mm); vma != NULL; vma = vma_next(vma)) {
-        offset += vma_dump_size(vma);
-    }
+    data_offset = ROUND_UP(offset, ELF_EXEC_PAGESIZE);
 
     /* Do not dump if the corefile size exceeds the limit. */
-    if (dumpsize.rlim_cur != RLIM_INFINITY && dumpsize.rlim_cur < offset) {
+    if (dumpsize.rlim_cur != RLIM_INFINITY
+        && dumpsize.rlim_cur < data_offset + css.size) {
         errno = 0;
         goto out;
     }
@@ -4485,36 +4447,22 @@ static int elf_core_dump(int signr, const CPUArchState *env)
      */
     {
         g_autofree void *header = g_malloc0(data_offset);
+        FillRegionPhdr frp;
         void *hptr, *dptr;
 
         /* Create elf file header. */
         hptr = header;
-        fill_elf_header(hptr, segs + 1, ELF_MACHINE, 0);
+        fill_elf_header(hptr, css.count + 1, ELF_MACHINE, 0);
         hptr += sizeof(struct elfhdr);
 
         /* Create elf program headers. */
         fill_elf_note_phdr(hptr, note_size, note_offset);
         hptr += sizeof(struct elf_phdr);
 
-        offset = data_offset;
-        for (vma = vma_first(&mm); vma != NULL; vma = vma_next(vma)) {
-            struct elf_phdr *phdr = hptr;
-
-            phdr->p_type = PT_LOAD;
-            phdr->p_offset = offset;
-            phdr->p_vaddr = vma->vma_start;
-            phdr->p_paddr = 0;
-            phdr->p_filesz = vma_dump_size(vma);
-            offset += phdr->p_filesz;
-            phdr->p_memsz = vma->vma_end - vma->vma_start;
-            phdr->p_flags = (vma->vma_flags & PROT_READ ? PF_R : 0)
-                          | (vma->vma_flags & PROT_WRITE ? PF_W : 0)
-                          | (vma->vma_flags & PROT_EXEC ? PF_X : 0);
-            phdr->p_align = ELF_EXEC_PAGESIZE;
-
-            bswap_phdr(phdr, 1);
-            hptr += sizeof(struct elf_phdr);
-        }
+        frp.phdr = hptr;
+        frp.offset = data_offset;
+        walk_memory_regions(&frp, wmr_fill_region_phdr);
+        hptr = frp.phdr;
 
         /* Create the notes. */
         dptr = fill_note(&hptr, NT_AUXV, "CORE", ts->info->auxv_len);
@@ -4539,12 +4487,8 @@ static int elf_core_dump(int signr, const CPUArchState *env)
     /*
      * Finally write process memory into the corefile as well.
      */
-    for (vma = vma_first(&mm); vma != NULL; vma = vma_next(vma)) {
-        size_t size = vma_dump_size(vma);
-
-        if (size && dump_write(fd, g2h_untagged(vma->vma_start), size) < 0) {
-            goto out;
-        }
+    if (walk_memory_regions(&fd, wmr_write_region) < 0) {
+        goto out;
     }
     errno = 0;
 
@@ -4552,7 +4496,6 @@ static int elf_core_dump(int signr, const CPUArchState *env)
     ret = -errno;
     mmap_unlock();
     cpu_list_unlock();
-    vma_delete(&mm);
     close(fd);
     return ret;
 }
-- 
2.34.1



  parent reply	other threads:[~2024-03-01 23:11 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-01 23:05 [PATCH 00/60] linux-user and tcg patch queue Richard Henderson
2024-03-01 23:05 ` [PATCH 01/60] linux-user/elfload: Disable core dump if getrlimit fails Richard Henderson
2024-03-01 23:05 ` [PATCH 02/60] linux-user/elfload: Merge init_note_info and fill_note_info Richard Henderson
2024-03-01 23:05 ` [PATCH 03/60] linux-user/elfload: Tidy fill_note_info and struct elf_note_info Richard Henderson
2024-03-01 23:05 ` [PATCH 04/60] linux-user/elfload: Stack allocate struct mm_struct Richard Henderson
2024-03-01 23:05 ` [PATCH 05/60] linux-user/elfload: Latch errno before cleanup in elf_core_dump Richard Henderson
2024-03-01 23:05 ` [PATCH 06/60] linux-user/elfload: Open core file after vma_init Richard Henderson
2024-03-01 23:05 ` [PATCH 07/60] linux-user/elfload: Truncate core file on open Richard Henderson
2024-03-01 23:05 ` [PATCH 08/60] linux-user/elfload: Lock cpu list and mmap during elf_core_dump Richard Henderson
2024-03-01 23:05 ` [PATCH 09/60] linux-user/elfload: Size corefile before opening Richard Henderson
2024-03-01 23:05 ` [PATCH 10/60] linux-user/elfload: Write corefile elf header in one block Richard Henderson
2024-03-01 23:05 ` [PATCH 11/60] linux-user/elfload: Write process memory to core file in larger chunks Richard Henderson
2024-03-01 23:05 ` [PATCH 12/60] linux-user/elfload: Simplify vma_dump_size Richard Henderson
2024-03-01 23:05 ` Richard Henderson [this message]
2024-03-01 23:05 ` [PATCH 14/60] linux-user/elfload: Unprotect regions before core dump Richard Henderson
2024-03-01 23:05 ` [PATCH 15/60] tcg/aarch64: Apple does not align __int128_t in even registers Richard Henderson
2024-03-01 23:05 ` [PATCH 16/60] accel/tcg: Set can_do_io at at start of lookup_tb_ptr helper Richard Henderson
2024-03-01 23:05 ` [PATCH 17/60] tcg: Avoid double lock if page tables happen to be in mmio memory Richard Henderson
2024-03-01 23:05 ` [PATCH 18/60] accel/tcg: Remove qemu_host_page_size from page_protect/page_unprotect Richard Henderson
2024-03-01 23:05 ` [PATCH 19/60] linux-user: Adjust SVr4 NULL page mapping Richard Henderson
2024-03-01 23:05 ` [PATCH 20/60] linux-user: Remove qemu_host_page_{size, mask} in probe_guest_base Richard Henderson
2024-03-01 23:05 ` [PATCH 21/60] linux-user: Remove qemu_host_page_size from create_elf_tables Richard Henderson
2024-03-01 23:05 ` [PATCH 22/60] linux-user/hppa: Simplify init_guest_commpage Richard Henderson
2024-03-01 23:05 ` [PATCH 23/60] linux-user/nios2: Remove qemu_host_page_size from init_guest_commpage Richard Henderson
2024-03-01 23:05 ` [PATCH 24/60] linux-user/arm: " Richard Henderson
2024-03-01 23:05 ` [PATCH 25/60] linux-user: Remove qemu_host_page_size from elf_core_dump Richard Henderson
2024-03-01 23:05 ` [PATCH 26/60] linux-user: Remove qemu_host_page_{size, mask} from mmap.c Richard Henderson
2024-03-01 23:05 ` [PATCH 27/60] linux-user: Remove REAL_HOST_PAGE_ALIGN " Richard Henderson
2024-03-01 23:05 ` [PATCH 28/60] linux-user: Remove HOST_PAGE_ALIGN " Richard Henderson
2024-03-01 23:05 ` [PATCH 29/60] migration: Remove qemu_host_page_size Richard Henderson
2024-03-01 23:05 ` [PATCH 30/60] hw/tpm: Remove HOST_PAGE_ALIGN from tpm_ppi_init Richard Henderson
2024-03-01 23:05 ` [PATCH 31/60] softmmu/physmem: Remove qemu_host_page_size Richard Henderson
2024-03-01 23:05 ` [PATCH 32/60] softmmu/physmem: Remove HOST_PAGE_ALIGN Richard Henderson
2024-03-01 23:05 ` [PATCH 33/60] linux-user: Remove qemu_host_page_size from main Richard Henderson
2024-03-01 23:05 ` [PATCH 34/60] linux-user: Split out target_mmap__locked Richard Henderson
2024-03-01 23:05 ` [PATCH 35/60] linux-user: Move some mmap checks outside the lock Richard Henderson
2024-03-01 23:05 ` [PATCH 36/60] linux-user: Fix sub-host-page mmap Richard Henderson
2024-03-01 23:05 ` [PATCH 37/60] linux-user: Split out mmap_end Richard Henderson
2024-03-01 23:05 ` [PATCH 38/60] linux-user: Do early mmap placement only for reserved_va Richard Henderson
2024-03-01 23:05 ` [PATCH 39/60] linux-user: Split out do_munmap Richard Henderson
2024-03-01 23:05 ` [PATCH 40/60] linux-user: Use do_munmap for target_mmap failure Richard Henderson
2024-03-01 23:06 ` [PATCH 41/60] linux-user: Split out mmap_h_eq_g Richard Henderson
2024-03-01 23:06 ` [PATCH 42/60] linux-user: Split out mmap_h_lt_g Richard Henderson
2024-03-01 23:06 ` [PATCH 43/60] linux-user: Split out mmap_h_gt_g Richard Henderson
2024-03-01 23:06 ` [PATCH 44/60] tests/tcg: Remove run-test-mmap-* Richard Henderson
2024-03-01 23:06 ` [PATCH 45/60] tests/tcg: Extend file in linux-madvise.c Richard Henderson
2024-03-01 23:06 ` [PATCH 46/60] *-user: Deprecate and disable -p pagesize Richard Henderson
2024-03-01 23:06 ` [PATCH 47/60] cpu: Remove page_size_init Richard Henderson
2024-03-01 23:06 ` [PATCH 48/60] accel/tcg: Disconnect TargetPageDataNode from page size Richard Henderson
2024-03-01 23:06 ` [PATCH 49/60] linux-user: Allow TARGET_PAGE_BITS_VARY Richard Henderson
2024-03-01 23:06 ` [PATCH 50/60] target/arm: Enable TARGET_PAGE_BITS_VARY for AArch64 user-only Richard Henderson
2024-03-01 23:06 ` [PATCH 51/60] linux-user: Bound mmap_min_addr by host page size Richard Henderson
2024-03-01 23:06 ` [PATCH 52/60] target/ppc: Enable TARGET_PAGE_BITS_VARY for user-only Richard Henderson
2024-03-01 23:06 ` [PATCH 53/60] target/alpha: " Richard Henderson
2024-03-01 23:06 ` [PATCH 54/60] linux-user: Remove pgb_dynamic alignment assertion Richard Henderson
2024-03-01 23:06 ` [PATCH 55/60] tcg/optimize: fix uninitialized variable Richard Henderson
2024-03-01 23:06 ` [PATCH 56/60] linux-user/x86_64: Handle the vsyscall page in open_self_maps_{2, 4} Richard Henderson
2024-04-11 22:09   ` Michael Tokarev
2024-03-01 23:06 ` [PATCH 57/60] linux-user/loongarch64: Remove TARGET_FORCE_SHMLBA Richard Henderson
2024-03-01 23:06 ` [PATCH 58/60] linux-user: Add strace for shmat Richard Henderson
2024-03-01 23:06 ` [PATCH 59/60] linux-user: Rewrite target_shmat Richard Henderson
2024-03-01 23:06 ` [PATCH 60/60] tests/tcg: Check that shmat() does not break /proc/self/maps Richard Henderson
2024-03-01 23:13 ` [PULL 00/60] linux-user and tcg patch queue Richard Henderson
2024-03-05 11:17 ` [PATCH " 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=20240301230619.661008-14-richard.henderson@linaro.org \
    --to=richard.henderson@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).