aboutsummaryrefslogtreecommitdiff
path: root/linux-user/signal.c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@iki.fi>2009-04-07 09:57:11 +0300
committerRiku Voipio <riku.voipio@nokia.com>2009-06-16 16:56:28 +0300
commitedf8e2af1453ce56c72b2f25a745e3734177a05d (patch)
tree367df4d32d3d75137076cd38738199d4d5b27901 /linux-user/signal.c
parent88a8c98455cc28ef27f92fd0c6845cedf86d21fc (diff)
linux-user: implemented ELF coredump support for ARM target
When target process is killed with signal (such signal that should dump core) a coredump file is created. This file is similar than coredump generated by Linux (there are few exceptions though). Riku Voipio: added support for rlimit Signed-off-by: Mika Westerberg <mika.westerberg@iki.fi> Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
Diffstat (limited to 'linux-user/signal.c')
-rw-r--r--linux-user/signal.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 371927e2a2..6a34171aa0 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -27,6 +27,7 @@
#include <errno.h>
#include <assert.h>
#include <sys/ucontext.h>
+#include <sys/resource.h>
#include "qemu.h"
#include "qemu-common.h"
@@ -287,6 +288,23 @@ static int fatal_signal (int sig)
}
}
+/* returns 1 if given signal should dump core if not handled */
+static int core_dump_signal(int sig)
+{
+ switch (sig) {
+ case TARGET_SIGABRT:
+ case TARGET_SIGFPE:
+ case TARGET_SIGILL:
+ case TARGET_SIGQUIT:
+ case TARGET_SIGSEGV:
+ case TARGET_SIGTRAP:
+ case TARGET_SIGBUS:
+ return (1);
+ default:
+ return (0);
+ }
+}
+
void signal_init(void)
{
struct sigaction act;
@@ -352,13 +370,29 @@ static inline void free_sigqueue(CPUState *env, struct sigqueue *q)
/* abort execution with signal */
static void QEMU_NORETURN force_sig(int sig)
{
- int host_sig;
+ TaskState *ts = (TaskState *)thread_env->opaque;
+ int host_sig, core_dumped = 0;
struct sigaction act;
host_sig = target_to_host_signal(sig);
- fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
- sig, strsignal(host_sig));
gdb_signalled(thread_env, sig);
+ /* dump core if supported by target binary format */
+ if (core_dump_signal(sig) && (ts->bprm->core_dump != NULL)) {
+ stop_all_tasks();
+ core_dumped =
+ ((*ts->bprm->core_dump)(sig, thread_env) == 0);
+ }
+ if (core_dumped) {
+ /* we already dumped the core of target process, we don't want
+ * a coredump of qemu itself */
+ struct rlimit nodump;
+ getrlimit(RLIMIT_CORE, &nodump);
+ nodump.rlim_cur=0;
+ setrlimit(RLIMIT_CORE, &nodump);
+ (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
+ sig, strsignal(host_sig), "core dumped" );
+ }
+
/* The proper exit code for dieing from an uncaught signal is
* -<signal>. The kernel doesn't allow exit() or _exit() to pass
* a negative value. To get the proper exit code we need to