summary refs log tree commit diff stats
path: root/linux-user
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2024-02-27 08:25:22 -1000
committerRichard Henderson <richard.henderson@linaro.org>2024-02-29 11:03:52 -1000
commit41689bb30cb55f411a4d9f7a31f3e601292d3be2 (patch)
tree9272a16e68c8693b3fac4655cadc25ff152e4af6 /linux-user
parent50e33f52fbc476f71eb006e0c8d3fa355539c3e1 (diff)
downloadfocaccia-qemu-41689bb30cb55f411a4d9f7a31f3e601292d3be2.tar.gz
focaccia-qemu-41689bb30cb55f411a4d9f7a31f3e601292d3be2.zip
linux-user/elfload: Unprotect regions before core dump
By unprotecting regions, we re-instate writability and
unify regions that have been split, which may reduce
the total number of regions.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/elfload.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ae0abc4931..38bfc9ac67 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -3963,6 +3963,8 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
 }
 
 #ifdef USE_ELF_CORE_DUMP
+#include "exec/translate-all.h"
+
 /*
  * Definitions to generate Intel SVR4-like core files.
  * These mostly have the same names as the SVR4 types with "target_elf_"
@@ -4280,6 +4282,23 @@ static int dump_write(int fd, const void *ptr, size_t size)
     return (0);
 }
 
+static int wmr_page_unprotect_regions(void *opaque, target_ulong start,
+                                      target_ulong end, unsigned long flags)
+{
+    if ((flags & (PAGE_WRITE | PAGE_WRITE_ORG)) == PAGE_WRITE_ORG) {
+        size_t step = MAX(TARGET_PAGE_SIZE, qemu_host_page_size);
+
+        while (1) {
+            page_unprotect(start, 0);
+            if (end - start <= step) {
+                break;
+            }
+            start += step;
+        }
+    }
+    return 0;
+}
+
 typedef struct {
     unsigned count;
     size_t size;
@@ -4401,6 +4420,9 @@ static int elf_core_dump(int signr, const CPUArchState *env)
     cpu_list_lock();
     mmap_lock();
 
+    /* By unprotecting, we merge vmas that might be split. */
+    walk_memory_regions(NULL, wmr_page_unprotect_regions);
+
     /*
      * Walk through target process memory mappings and
      * set up structure containing this information.