From patchwork Wed Dec 30 17:59:44 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Jacobowitz X-Patchwork-Id: 41918 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id A7EE61007D2 for ; Thu, 31 Dec 2009 05:00:27 +1100 (EST) Received: from localhost ([127.0.0.1]:39283 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NQ2qO-00053a-It for incoming@patchwork.ozlabs.org; Wed, 30 Dec 2009 13:00:24 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NQ2pr-00051h-PL for qemu-devel@nongnu.org; Wed, 30 Dec 2009 12:59:51 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NQ2pn-0004zA-AU for qemu-devel@nongnu.org; Wed, 30 Dec 2009 12:59:51 -0500 Received: from [199.232.76.173] (port=57770 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NQ2pm-0004z2-W6 for qemu-devel@nongnu.org; Wed, 30 Dec 2009 12:59:47 -0500 Received: from nan.false.org ([208.75.86.248]:40894) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NQ2pm-00049X-Dm for qemu-devel@nongnu.org; Wed, 30 Dec 2009 12:59:46 -0500 Received: from nan.false.org (localhost [127.0.0.1]) by nan.false.org (Postfix) with ESMTP id C9B2210DAA; Wed, 30 Dec 2009 17:59:45 +0000 (GMT) Received: from caradoc.them.org (209.195.188.212.nauticom.net [209.195.188.212]) by nan.false.org (Postfix) with ESMTP id 86C1E10D9E; Wed, 30 Dec 2009 17:59:45 +0000 (GMT) Received: from drow by caradoc.them.org with local (Exim 4.69) (envelope-from ) id 1NQ2pk-0002PD-OW; Wed, 30 Dec 2009 12:59:44 -0500 Date: Wed, 30 Dec 2009 12:59:44 -0500 From: Daniel Jacobowitz To: Laurent Desnogues Subject: Re: [Qemu-devel] [PATCH] ARM semihosting improvements Message-ID: <20091230175944.GA9162@caradoc.them.org> References: <20091230172351.GA2326@caradoc.them.org> <761ea48b0912300932i559251cfif0fc252e219edd31@mail.gmail.com> <20091230173713.GA3957@caradoc.them.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20091230173713.GA3957@caradoc.them.org> User-Agent: Mutt/1.5.20 (2009-06-14) X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: qemu-devel@nongnu.org X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Daniel Jacobowitz This patch improves ARM semihosting to the point where qemu-system-arm can simulate cc1 from GCC. It can't simulate GCC itself, which requires POSIXy bits like execve, but the backend works, including the preprocessor. * Use -kernel and -append for SYS_GET_CMDLINE. This lets semihosted programs receive command line options. * Correctly return errno values without gdb attached. Previously most system calls discarded errno. * Set errno == ENOENT after SYS_FLEN of a directory. This is a workaround for the absence of stat in the ARM semihosting protocol. Now stat on directories will report that they do not exist, which causes most applications to skip the missing directory. Also fixes a use-after-free when using semihosting with linux-user, as pointed out by Laurent Desnogues. Signed-off-by: Daniel Jacobowitz diff --git a/arm-semi.c b/arm-semi.c index 5239ffc..e4d1ae5 100644 --- a/arm-semi.c +++ b/arm-semi.c @@ -35,6 +35,7 @@ #include "qemu-common.h" #include "sysemu.h" #include "gdbstub.h" +#include "hw/arm-misc.h" #endif #define SYS_OPEN 0x01 @@ -108,8 +109,12 @@ static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code) return code; } #else +static target_ulong syscall_err; + static inline uint32_t set_swi_errno(CPUState *env, uint32_t code) { + if (code == (uint32_t)-1) + syscall_err = errno; return code; } @@ -118,10 +123,6 @@ static inline uint32_t set_swi_errno(CPUState *env, uint32_t code) static target_ulong arm_semi_syscall_len; -#if !defined(CONFIG_USER_ONLY) -static target_ulong syscall_err; -#endif - static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err) { #ifdef CONFIG_USER_ONLY @@ -156,8 +157,17 @@ static void arm_semi_flen_cb(CPUState *env, target_ulong ret, target_ulong err) { /* The size is always stored in big-endian order, extract the value. We assume the size always fit in 32 bits. */ - uint32_t size; + uint32_t size, mode; cpu_memory_rw_debug(env, env->regs[13]-64+32, (uint8_t *)&size, 4, 0); + + /* Report that all directories do not exist. */ + cpu_memory_rw_debug(env, env->regs[13]-64+8, (uint8_t *)&mode, 4, 0); + mode = be32_to_cpu(mode); + if (mode & 040000) { + err = 2; + size = -1; + } + env->regs[0] = be32_to_cpu(size); #ifdef CONFIG_USER_ONLY ((TaskState *)env->opaque)->swi_errno = err; @@ -310,6 +320,11 @@ uint32_t do_arm_semihosting(CPUState *env) ret = set_swi_errno(ts, fstat(ARG(0), &buf)); if (ret == (uint32_t)-1) return -1; + if (S_ISDIR (buf.st_mode)) { + errno = ENOENT; + set_swi_errno(ts, -1); + return -1; + } return buf.st_size; } case SYS_TMPNAM: @@ -370,13 +385,21 @@ uint32_t do_arm_semihosting(CPUState *env) return syscall_err; #endif case SYS_GET_CMDLINE: -#ifdef CONFIG_USER_ONLY - /* Build a commandline from the original argv. */ { - char **arg = ts->info->host_argv; int len = ARG(1); /* lock the buffer on the ARM side */ char *cmdline_buffer = (char*)lock_user(VERIFY_WRITE, ARG(0), len, 0); +#ifdef CONFIG_USER_ONLY + /* Build a commandline from the original argv. */ + char **arg = ts->info->host_argv; +#else + /* Build a commandline from -kernel and -append. */ + /* This is simple but only because we do no escaping. */ + const char *arglist[3] = { 0 }, **arg = arglist; + + arglist[0] = env->boot_info->kernel_filename; + arglist[1] = env->boot_info->kernel_cmdline; +#endif if (!cmdline_buffer) /* FIXME - should this error code be -TARGET_EFAULT ? */ @@ -410,9 +433,6 @@ uint32_t do_arm_semihosting(CPUState *env) /* Return success if commandline fit into buffer. */ return *arg ? -1 : 0; } -#else - return -1; -#endif case SYS_HEAPINFO: { uint32_t *ptr; diff --git a/linux-user/main.c b/linux-user/main.c index a0d8ce7..fbff44a 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2782,11 +2782,6 @@ int main(int argc, char **argv, char **envp) _exit(1); } - for (i = 0; i < target_argc; i++) { - free(target_argv[i]); - } - free(target_argv); - for (wrk = target_environ; *wrk; wrk++) { free(*wrk); }