From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=47967 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PqSWQ-0006pH-HU for qemu-devel@nongnu.org; Fri, 18 Feb 2011 10:45:31 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PqSWP-0005wg-0a for qemu-devel@nongnu.org; Fri, 18 Feb 2011 10:45:30 -0500 Received: from eu1sys200aog105.obsmtp.com ([207.126.144.119]:46908) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PqSWO-0005wV-MY for qemu-devel@nongnu.org; Fri, 18 Feb 2011 10:45:28 -0500 Received: from zeta.dmz-eu.st.com (ns2.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id EBD6149C for ; Fri, 18 Feb 2011 15:45:26 +0000 (GMT) Received: from Webmail-eu.st.com (safex1hubcas6.st.com [10.75.90.73]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id C82D5472D for ; Fri, 18 Feb 2011 15:45:26 +0000 (GMT) From: Christophe Lyon Date: Fri, 18 Feb 2011 16:45:23 +0100 Message-ID: <1298043923-13787-1-git-send-email-christophe.lyon@st.com> MIME-Version: 1.0 Content-Type: text/plain Subject: [Qemu-devel] [PATCH] target-arm: return the right exit code when using semi-hosting. List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org On ARM, the SYS_EXIT semi-hosting call has no room for application exit code, hence exiting a program from qemu always returns 0. This patch catches to argument passed to exit() and uses it as the return code when processing SYS_EXIT. Signed-off-by: Christophe Lyon --- arm-semi.c | 6 ++++-- cpu-exec.c | 23 +++++++++++++++++++++++ hw/elf_ops.h | 13 +++++++++++++ hw/loader.c | 2 ++ linux-user/elfload.c | 20 ++++++++++++++++++++ 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/arm-semi.c b/arm-semi.c index 1d5179b..4ef3769 100644 --- a/arm-semi.c +++ b/arm-semi.c @@ -166,6 +166,8 @@ static void arm_semi_flen_cb(CPUState *env, target_ulong ret, target_ulong err) #endif } +extern target_ulong arm_exit_code; + #define ARG(n) \ ({ \ target_ulong __arg; \ @@ -478,8 +480,8 @@ uint32_t do_arm_semihosting(CPUState *env) return 0; } case SYS_EXIT: - gdb_exit(env, 0); - exit(0); + gdb_exit(env, arm_exit_code); + exit(arm_exit_code); default: fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr); cpu_dump_state(env, stderr, fprintf, 0); diff --git a/cpu-exec.c b/cpu-exec.c index b03b3a7..e1eac64 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -198,6 +198,14 @@ static inline TranslationBlock *tb_find_fast(void) /* main execution loop */ +/* On ARM, semi-hosting has no room for application exit code. To work + around this, when we start executing exit(), we take note of its + parameter, which will be used as return code. */ +target_ulong addr_of_exit = 0; +#if defined(TARGET_ARM) +target_ulong arm_exit_code = 0; +#endif + volatile sig_atomic_t exit_request; int cpu_exec(CPUState *env1) @@ -208,6 +216,10 @@ int cpu_exec(CPUState *env1) uint8_t *tc_ptr; unsigned long next_tb; +#if defined(TARGET_ARM) + static int arm_exit_reached = 0; +#endif + if (cpu_halted(env1) == EXCP_HALTED) return EXCP_HALTED; @@ -544,6 +556,17 @@ int cpu_exec(CPUState *env1) #endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */ spin_lock(&tb_lock); tb = tb_find_fast(); + +#if defined(TARGET_ARM) + /* When we reach exit(), make a copy of the + application exit code. */ + if ((tb->pc == addr_of_exit) + && (arm_exit_reached == 0)) { + arm_exit_code = env->regs[0]; + arm_exit_reached = 1; + } +#endif + /* Note: we do it here to avoid a gcc bug on Mac OS X when doing it in tb_find_slow */ if (tb_invalidated_flag) { diff --git a/hw/elf_ops.h b/hw/elf_ops.h index 0bd7235..373c8cd 100644 --- a/hw/elf_ops.h +++ b/hw/elf_ops.h @@ -181,6 +181,19 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, s->next = syminfos; syminfos = s; qemu_free(shdr_table); + + /* Take note of the address of the exit() function, to speed up + exit() calls tracking. This is currently used only for ARM, but + target-dependent code is not allowed in this module. */ + i = 0; + while (i < nsyms) { + if (strcmp("exit", s->disas_strtab + syms[i].st_name) == 0) { + addr_of_exit = syms[i].st_value; + break; + } + i++; + } + return 0; fail: qemu_free(syms); diff --git a/hw/loader.c b/hw/loader.c index 35d792e..3ee9986 100644 --- a/hw/loader.c +++ b/hw/loader.c @@ -249,6 +249,8 @@ static void *load_at(int fd, int offset, int size) #define ELF_CLASS ELFCLASS32 #include "elf.h" +extern int addr_of_exit; + #define SZ 32 #define elf_word uint32_t #define elf_sword int32_t diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 2de83e4..fa460c8 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1455,9 +1455,14 @@ static void load_elf_image(const char *image_name, int image_fd, info->brk = info->end_code; } +#if !defined(TARGET_ARM) + /* On ARM, we want symbols in order to catch exit() calls. */ if (qemu_log_enabled()) { +#endif load_symbols(ehdr, image_fd, load_bias); +#if !defined(TARGET_ARM) } +#endif close(image_fd); return; @@ -1545,6 +1550,8 @@ static int symcmp(const void *s0, const void *s1) : ((sym0->st_value > sym1->st_value) ? 1 : 0); } +extern target_ulong addr_of_exit; + /* Best attempt to load symbols from this ELF object. */ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias) { @@ -1641,6 +1648,19 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias) s->lookup_symbol = lookup_symbolxx; s->next = syminfos; syminfos = s; + + /* Take note of the address of the exit() function, to speed up + exit() calls tracking. This is currently used only for ARM, but + this code fragment must remain target-independent so that it is + in sync with hw/elf_ops.h. */ + i = 0; + while (i < nsyms) { + if (strcmp("exit", s->disas_strtab + syms[i].st_name) == 0) { + addr_of_exit = syms[i].st_value; + break; + } + i++; + } } int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, -- 1.7.2.3