All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.