qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] sysroot


From: Edgar E. Iglesias
Subject: [Qemu-devel] sysroot
Date: Mon, 3 Mar 2008 14:57:56 +0100
User-agent: Mutt/1.5.16 (2007-06-09)

Hello,

>From my experience, many times when one cross compiles software for linux at 
>some point one ends up creating a directory which contains a root filesystem 
>for the target. A nice thing with qemu is the ability to cross run programs 
>within that target dir with the linux-user -L option.

Due to the way the -L option (linux-user/path.c) works, when a file does not 
exist in the target directory qemu may open files from the hosts root. This may 
be undesirable when trying to simulate the behavior from the targets point of 
view. An example is with at least some versions of glibc's dynamic linker and a 
missing target/etc/ld.so.cache. 
Also, if the target/ tree contains many files, the startup time for a 
simulation can increase allot (up to minutes if qemu even manages to run before 
being killed by the OOM). This is because it takes a long time & memory for 
qemu to scan the entire tree and generate it's internal representation.

IIUC, chroot can be used to avoid these issues but that would require that qemu 
itself be linked -static:ally and placed in target/.

I think it would be nice to have a -sysroot option that does a more simple and 
strict path remapping by always prepending the sysroot. Something similar to 
what the --sysroot option in the sim/GDB simulators does.

This patch shows how it could work. Only absolute paths get remapped.

I would appreciate any comments on this.

Thanks and best regards
-- 
Edgar E. Iglesias
Axis Communications AB

diff --git a/darwin-user/qemu.h b/darwin-user/qemu.h
index 41b57f8..2147da3 100644
--- a/darwin-user/qemu.h
+++ b/darwin-user/qemu.h
@@ -106,7 +106,7 @@ void write_dt(void *ptr, unsigned long addr, unsigned long 
limit, int flags);
 
 extern CPUState *global_env;
 void cpu_loop(CPUState *env);
-void init_paths(const char *prefix);
+void init_paths(const char *prefix, int sysroot);
 const char *path(const char *pathname);
 
 extern int loglevel;
diff --git a/linux-user/main.c b/linux-user/main.c
index 0079c7a..1c63610 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1912,6 +1912,7 @@ void usage(void)
            "-d options   activate log (logfile=%s)\n"
            "-p pagesize  set the host page size to 'pagesize'\n"
            "-strace      log system calls\n"
+           "-sysroot     Root for system calls with absolute file-names\n"
            "\n"
            "Environment variables:\n"
            "QEMU_STRACE       Print system calls and arguments similar to 
the\n"
@@ -1943,6 +1944,7 @@ int main(int argc, char **argv)
     int gdbstub_port = 0;
     int drop_ld_preload = 0, environ_count = 0;
     char **target_environ, **wrk, **dst;
+    char *sysroot = NULL;
 
     if (argc <= 1)
         usage();
@@ -2014,6 +2016,8 @@ int main(int argc, char **argv)
             drop_ld_preload = 1;
         } else if (!strcmp(r, "strace")) {
             do_strace = 1;
+        } else if (!strcmp(r, "sysroot")) {
+            sysroot = argv[optind++];
         } else
         {
             usage();
@@ -2030,7 +2034,10 @@ int main(int argc, char **argv)
     memset(info, 0, sizeof(struct image_info));
 
     /* Scan interp_prefix dir for replacement files. */
-    init_paths(interp_prefix);
+    if (sysroot)
+        init_paths(sysroot, 1);
+    else
+        init_paths(interp_prefix, 0);
 
     if (cpu_model == NULL) {
 #if defined(TARGET_I386)
diff --git a/linux-user/path.c b/linux-user/path.c
index 7da0a8b..ece8d89 100644
--- a/linux-user/path.c
+++ b/linux-user/path.c
@@ -25,6 +25,8 @@ struct pathelem
 };
 
 static struct pathelem *base;
+static int use_sysroot;
+static size_t sysroot_pathlen;
 
 /* First N chars of S1 match S2, and S2 is N chars long. */
 static int strneq(const char *s1, unsigned int n, const char *s2)
@@ -118,7 +120,7 @@ follow_path(const struct pathelem *cursor, const char *name)
     return NULL;
 }
 
-void init_paths(const char *prefix)
+void init_paths(const char *prefix, int sysroot)
 {
     char pref_buf[PATH_MAX];
 
@@ -137,13 +139,21 @@ void init_paths(const char *prefix)
     } else
         strcpy(pref_buf,prefix + 1);
 
-    base = new_entry("", NULL, pref_buf);
-    base = add_dir_maybe(base);
-    if (base->num_entries == 0) {
-        free (base);
-        base = NULL;
+    use_sysroot = sysroot;
+    if (sysroot) {
+        base = malloc(sizeof (*base));
+        sysroot_pathlen = strlen(pref_buf);
+        base->pathname = malloc(sysroot_pathlen + PATH_MAX + 1);
+        memcpy(base->pathname, pref_buf, sysroot_pathlen);
     } else {
-        set_parents(base, base);
+        base = new_entry("", NULL, pref_buf);
+        base = add_dir_maybe(base);
+        if (base->num_entries == 0) {
+            free (base);
+            base = NULL;
+        } else {
+            set_parents(base, base);
+        }
     }
 }
 
@@ -155,5 +165,11 @@ const char *path(const char *name)
     if (!base || name[0] != '/')
        return name;
 
-    return follow_path(base, name) ?: name;
+    if (use_sysroot) {
+        size_t name_len;
+        /* Prepend base->pathname to name.  */
+        name_len = strlen(name);
+        return memcpy (base->pathname + sysroot_pathlen, name, name_len + 1);
+    } else
+        return follow_path(base, name) ?: name;
 }
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index b33ad89..9e1b4f4 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -166,7 +166,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
 extern CPUState *global_env;
 void cpu_loop(CPUState *env);
-void init_paths(const char *prefix);
+void init_paths(const char *prefix, int sysroot);
 const char *path(const char *pathname);
 char *target_strerror(int err);
 
diff --git a/tests/test_path.c b/tests/test_path.c
index 7d6e831..e146736 100644
--- a/tests/test_path.c
+++ b/tests/test_path.c
@@ -69,7 +69,7 @@ static unsigned int do_test(void)
     if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE5", 0600)) != 0)
        return __LINE__;
 
-    init_paths("/tmp/qemu-test_path");
+    init_paths("/tmp/qemu-test_path", 0);
 
     NO_CHANGE("/tmp");
     NO_CHANGE("/tmp/");




reply via email to

[Prev in Thread] Current Thread [Next in Thread]