summary refs log tree commit diff stats
path: root/linux-user/main.c
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2009-07-17 12:48:08 +0100
committerPaul Brook <paul@codesourcery.com>2009-07-17 13:12:41 +0100
commit379f6698d73f476de38682b3ff96ecb226728c43 (patch)
tree35ec0c77416322f16fa27d646af50c60363168e3 /linux-user/main.c
parenta9ff9df188615d653a5a904bafbe724d40143e35 (diff)
downloadfocaccia-qemu-379f6698d73f476de38682b3ff96ecb226728c43.tar.gz
focaccia-qemu-379f6698d73f476de38682b3ff96ecb226728c43.zip
Userspace guest address offsetting
Re-implement GUEST_BASE support.
Offset guest ddress space by default if the guest binary contains
regions below the host mmap_min_addr.
Implement support for i386, x86-64 and arm hosts.

Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
Signed-off-by: Paul Brook <paul@codesourcery.com>
Diffstat (limited to 'linux-user/main.c')
-rw-r--r--linux-user/main.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index 9038b58e7e..4388c04c9a 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -39,6 +39,11 @@
 char *exec_path;
 
 int singlestep;
+#if defined(CONFIG_USE_GUEST_BASE)
+unsigned long mmap_min_addr;
+unsigned long guest_base;
+int have_guest_base;
+#endif
 
 static const char *interp_prefix = CONFIG_QEMU_PREFIX;
 const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
@@ -2320,6 +2325,9 @@ static void usage(void)
            "-E var=value      sets/modifies targets environment variable(s)\n"
            "-U var            unsets targets environment variable(s)\n"
            "-0 argv0          forces target process argv[0] to be argv0\n"
+#if defined(CONFIG_USE_GUEST_BASE)
+           "-B address        set guest_base address to address\n"
+#endif
            "\n"
            "Debug options:\n"
            "-d options   activate log (logfile=%s)\n"
@@ -2495,6 +2503,11 @@ int main(int argc, char **argv, char **envp)
 #endif
                 exit(1);
             }
+#if defined(CONFIG_USE_GUEST_BASE)
+        } else if (!strcmp(r, "B")) {
+           guest_base = strtol(argv[optind++], NULL, 0);
+           have_guest_base = 1;
+#endif
         } else if (!strcmp(r, "drop-ld-preload")) {
             (void) envlist_unsetenv(envlist, "LD_PRELOAD");
         } else if (!strcmp(r, "singlestep")) {
@@ -2572,6 +2585,35 @@ int main(int argc, char **argv, char **envp)
     target_environ = envlist_to_environ(envlist, NULL);
     envlist_free(envlist);
 
+#if defined(CONFIG_USE_GUEST_BASE)
+    /*
+     * Now that page sizes are configured in cpu_init() we can do
+     * proper page alignment for guest_base.
+     */
+    guest_base = HOST_PAGE_ALIGN(guest_base);
+
+    /*
+     * Read in mmap_min_addr kernel parameter.  This value is used
+     * When loading the ELF image to determine whether guest_base
+     * is needed.
+     *
+     * When user has explicitly set the quest base, we skip this
+     * test.
+     */
+    if (!have_guest_base) {
+        FILE *fp;
+
+        if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
+            unsigned long tmp;
+            if (fscanf(fp, "%lu", &tmp) == 1) {
+                mmap_min_addr = tmp;
+                qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr);
+            }
+            fclose(fp);
+        }
+    }
+#endif /* CONFIG_USE_GUEST_BASE */
+
     /*
      * Prepare copy of argv vector for target.
      */
@@ -2622,6 +2664,9 @@ int main(int argc, char **argv, char **envp)
     free(target_environ);
 
     if (qemu_log_enabled()) {
+#if defined(CONFIG_USE_GUEST_BASE)
+        qemu_log("guest_base  0x%lx\n", guest_base);
+#endif
         log_page_dump();
 
         qemu_log("start_brk   0x" TARGET_ABI_FMT_lx "\n", info->start_brk);