Patchwork [05/23] bsd-user: add bsd_binprm to TaskState for core dumping emulation

login
register
mail settings
Submitter Stacey Son
Date June 24, 2013, 2:03 a.m.
Message ID <1372039435-41921-6-git-send-email-sson@FreeBSD.org>
Download mbox | patch
Permalink /patch/253942/
State New
Headers show

Comments

Stacey Son - June 24, 2013, 2:03 a.m.
Add the bsd_binprm (formerly linux_binprm) structure to TaskState so it can be
used to support core dumping emulation support in the future. Also, make freebsd
the default bsd_type, if compiled on a FreeBSD system.

Signed-off-by: Stacey Son <sson@FreeBSD.org>
---
 bsd-user/bsdload.c |   36 ++++++++++++++++++------------------
 bsd-user/elfload.c |    6 +++---
 bsd-user/main.c    |   19 ++++++++++++++++++-
 bsd-user/qemu.h    |   22 +++++++++++++---------
 bsd-user/signal.c  |    6 ------
 5 files changed, 52 insertions(+), 37 deletions(-)

Patch

diff --git a/bsd-user/bsdload.c b/bsd-user/bsdload.c
index 637a217..cc4f534 100644
--- a/bsd-user/bsdload.c
+++ b/bsd-user/bsdload.c
@@ -68,7 +68,7 @@  static int count(char ** vec)
     return(i);
 }
 
-static int prepare_binprm(struct linux_binprm *bprm)
+static int prepare_binprm(struct bsd_binprm *bprm)
 {
     struct stat         st;
     int mode;
@@ -170,33 +170,33 @@  abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
 }
 
 int loader_exec(const char * filename, char ** argv, char ** envp,
-             struct target_pt_regs * regs, struct image_info *infop)
+             struct target_pt_regs *regs, struct image_info *infop,
+             struct bsd_binprm *bprm)
 {
-    struct linux_binprm bprm;
     int retval;
     int i;
 
-    bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
+    bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
     for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */
-            bprm.page[i] = NULL;
+            bprm->page[i] = NULL;
     retval = open(filename, O_RDONLY);
     if (retval < 0)
         return retval;
-    bprm.fd = retval;
-    bprm.filename = (char *)filename;
-    bprm.argc = count(argv);
-    bprm.argv = argv;
-    bprm.envc = count(envp);
-    bprm.envp = envp;
+    bprm->fd = retval;
+    bprm->filename = (char *)filename;
+    bprm->argc = count(argv);
+    bprm->argv = argv;
+    bprm->envc = count(envp);
+    bprm->envp = envp;
 
-    retval = prepare_binprm(&bprm);
+    retval = prepare_binprm(bprm);
 
     if(retval>=0) {
-        if (bprm.buf[0] == 0x7f
-                && bprm.buf[1] == 'E'
-                && bprm.buf[2] == 'L'
-                && bprm.buf[3] == 'F') {
-            retval = load_elf_binary(&bprm,regs,infop);
+        if (bprm->buf[0] == 0x7f
+                && bprm->buf[1] == 'E'
+                && bprm->buf[2] == 'L'
+                && bprm->buf[3] == 'F') {
+            retval = load_elf_binary(bprm, regs, infop);
         } else {
             fprintf(stderr, "Unknown binary format\n");
             return -1;
@@ -211,7 +211,7 @@  int loader_exec(const char * filename, char ** argv, char ** envp,
 
     /* Something went wrong, return the inode and free the argument pages*/
     for (i=0 ; i<MAX_ARG_PAGES ; i++) {
-        g_free(bprm.page[i]);
+        g_free(bprm->page[i]);
     }
     return(retval);
 }
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 035bcea..0f6c3db 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -679,7 +679,7 @@  static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
     return p;
 }
 
-static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
+static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
                                  struct image_info *info)
 {
     abi_ulong stack_base, size, error;
@@ -1164,8 +1164,8 @@  static void load_symbols(struct elfhdr *hdr, int fd)
     syminfos = s;
 }
 
-int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
-                    struct image_info * info)
+int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
+                    struct image_info *info)
 {
     struct elfhdr elf_ex;
     struct elfhdr interp_elf_ex;
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 2eb4a1b..0442dbe 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -884,6 +884,15 @@  static void usage(void)
 
 THREAD CPUArchState *thread_env;
 
+void stop_all_tasks(void)
+{
+    /*
+     * We trust when using NPTL (pthreads) start_exclusive() handles thread
+     * stopping correctly.
+     */
+    start_exclusive();
+}
+
 /* Assumes contents are already zeroed.  */
 void init_task_state(TaskState *ts)
 {
@@ -905,6 +914,7 @@  int main(int argc, char **argv)
     const char *log_mask = NULL;
     struct target_pt_regs regs1, *regs = &regs1;
     struct image_info info1, *info = &info1;
+    struct bsd_binprm bprm;
     TaskState ts1, *ts = &ts1;
     CPUArchState *env;
     int optind;
@@ -912,7 +922,11 @@  int main(int argc, char **argv)
     int gdbstub_port = 0;
     char **target_environ, **wrk;
     envlist_t *envlist = NULL;
+#ifdef __FreeBSD__
+    bsd_type = target_freebsd;
+#else
     bsd_type = target_openbsd;
+#endif
 
     if (argc <= 1)
         usage();
@@ -1054,6 +1068,8 @@  int main(int argc, char **argv)
     /* Zero out regs */
     memset(regs, 0, sizeof(struct target_pt_regs));
 
+    memset(&bprm, 0, sizeof(bprm));
+
     /* Zero out image_info */
     memset(info, 0, sizeof(struct image_info));
 
@@ -1133,7 +1149,7 @@  int main(int argc, char **argv)
     }
 #endif /* CONFIG_USE_GUEST_BASE */
 
-    if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) {
+    if (loader_exec(filename, argv+optind, target_environ, regs, info, &bprm)) {
         printf("Error loading %s\n", filename);
         _exit(1);
     }
@@ -1178,6 +1194,7 @@  int main(int argc, char **argv)
     memset(ts, 0, sizeof(TaskState));
     init_task_state(ts);
     ts->info = info;
+    ts->bprm = &bprm;
     env->opaque = ts;
 
 #if defined(TARGET_I386)
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index c0cdfcd..a36e9d2 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -90,6 +90,7 @@  typedef struct TaskState {
     struct TaskState *next;
     int used; /* non zero if used */
     struct image_info *info;
+    struct bsd_binprm *bprm;
 
     struct emulated_sigtable sigtab[TARGET_NSIG];
     struct qemu_sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
@@ -100,6 +101,7 @@  typedef struct TaskState {
 } __attribute__((aligned(16))) TaskState;
 
 void init_task_state(TaskState *ts);
+void stop_all_tasks(void);
 extern const char *qemu_uname_release;
 #if defined(CONFIG_USE_GUEST_BASE)
 extern unsigned long mmap_min_addr;
@@ -117,7 +119,7 @@  extern unsigned long mmap_min_addr;
  * This structure is used to hold the arguments that are
  * used when loading binaries.
  */
-struct linux_binprm {
+struct bsd_binprm {
         char buf[128];
         void *page[MAX_ARG_PAGES];
         abi_ulong p;
@@ -126,19 +128,21 @@  struct linux_binprm {
         int argc, envc;
         char **argv;
         char **envp;
-        char * filename;        /* Name of binary */
+        char *filename;        /* Name of binary */
+        int (*core_dump)(int, const CPUArchState *);
 };
 
 void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
 abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
                               abi_ulong stringp, int push_ptr);
-int loader_exec(const char * filename, char ** argv, char ** envp,
-             struct target_pt_regs * regs, struct image_info *infop);
-
-int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
-                    struct image_info * info);
-int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
-                    struct image_info * info);
+int loader_exec(const char *filename, char **argv, char **envp,
+             struct target_pt_regs *regs, struct image_info *infop,
+             struct bsd_binprm *bprm);
+
+int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
+                    struct image_info *info);
+int load_flt_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
+                    struct image_info *info);
 
 abi_long memcpy_to_target(abi_ulong dest, const void *src,
                           unsigned long len);
diff --git a/bsd-user/signal.c b/bsd-user/signal.c
index eb452fc..4ee97af 100644
--- a/bsd-user/signal.c
+++ b/bsd-user/signal.c
@@ -263,7 +263,6 @@  void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
     tswap_siginfo(tinfo, tinfo);
 }
 
-#if 0 /* not yet */
 /* Returns 1 if given signal should dump core if not handled. */
 static int core_dump_signal(int sig)
 {
@@ -280,7 +279,6 @@  static int core_dump_signal(int sig)
         return 0;
     }
 }
-#endif /* not yet */
 
 /* Signal queue handling. */
 static inline struct qemu_sigqueue *alloc_sigqueue(CPUArchState *env)
@@ -306,10 +304,8 @@  static inline void free_sigqueue(CPUArchState *env, struct qemu_sigqueue *q)
 /* Abort execution with signal. */
 void QEMU_NORETURN force_sig(int target_sig)
 {
-#if 0 /* not yet */
     TaskState *ts = (TaskState *)thread_env->opaque;
     int core_dumped = 0;
-#endif
     int host_sig;
     struct sigaction act;
 
@@ -317,7 +313,6 @@  void QEMU_NORETURN force_sig(int target_sig)
     gdb_signalled(thread_env, target_sig);
 
     /* Dump core if supported by target binary format */
-#if 0 /* net yet */
     if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
         stop_all_tasks();
         core_dumped =
@@ -335,7 +330,6 @@  void QEMU_NORETURN force_sig(int target_sig)
          (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) "
              "- %s\n", target_sig, strsignal(host_sig), "core dumped");
     }
-#endif /* not yet */
 
     /*
      * The proper exit code for dying from an uncaught signal is