[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] target-arm: return the right exit code when using s
From: |
Christophe Lyon |
Subject: |
[Qemu-devel] [PATCH] target-arm: return the right exit code when using semi-hosting. |
Date: |
Fri, 18 Feb 2011 16:45:23 +0100 |
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 <address@hidden>
---
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
- [Qemu-devel] [PATCH] target-arm: return the right exit code when using semi-hosting.,
Christophe Lyon <=