Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 4fe6a413a9
Fetching contributors…

Cannot retrieve contributors at this time

file 205 lines (162 sloc) 5.181 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
/*
* Copyright (C) 2009 Pekka Enberg
*
* This file is released under the GPL version 2 with the following
* clarification and special exception:
*
* Linking this library statically or dynamically with other modules is
* making a combined work based on this library. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* As a special exception, the copyright holders of this library give you
* permission to link this library with independent modules to produce an
* executable, regardless of the license terms of these independent
* modules, and to copy and distribute the resulting executable under terms
* of your choice, provided that you also meet, for each linked independent
* module, the terms and conditions of the license of that module. An
* independent module is a module which is not derived from or based on
* this library. If you modify this library, you may extend this exception
* to your version of the library, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
* Please refer to the file LICENSE for details.
*/

#include "jit/exception.h"

#include "vm/backtrace.h"
#include "vm/call.h"
#include "vm/class.h"
#include "vm/gc.h"
#include "vm/jni.h"
#include "vm/object.h"
#include "vm/preload.h"
#include "vm/signal.h"
#include "vm/stack-trace.h"
#include "vm/thread.h"

#include "sys/signal.h"

#include <ucontext.h>
#include <stddef.h>
#include <unistd.h>
#include <stdio.h>

static unsigned long throw_arithmetic_exception(unsigned long src_addr)
{
signal_new_exception(vm_java_lang_ArithmeticException,
"division by zero");
return throw_from_signal_bh(src_addr);
}

static unsigned long throw_null_pointer_exception(unsigned long src_addr)
{
signal_new_exception(vm_java_lang_NullPointerException, NULL);
return throw_from_signal_bh(src_addr);
}

static unsigned long throw_stack_overflow_error(unsigned long src_addr)
{
struct vm_object *obj;

obj = vm_alloc_stack_overflow_error();
if (!obj)
error("failed to allocate instance of StackOverflowError.");

signal_exception(obj);

return throw_from_signal_bh(src_addr);
}

static unsigned long rethrow_bh(unsigned long src_addr)
{
return throw_from_signal_bh(src_addr);
}

static void sigfpe_handler(int sig, siginfo_t *si, void *ctx)
{
if (signal_from_native(ctx))
goto exit;

if (si->si_code == FPE_INTDIV) {
if (install_signal_bh(ctx, throw_arithmetic_exception) == 0)
return;

fprintf(stderr, "%s: install_signal_bh() failed.\n", __func__);
}

 exit:
print_backtrace_and_die(sig, si, ctx);
}

static void sigill_handler(int sig, siginfo_t *si, void *ctx)
{
print_backtrace_and_die(sig, si, ctx);
}

static void sigsegv_handler(int sig, siginfo_t *si, void *ctx)
{
if (signal_from_native(ctx))
goto exit;

/* Assume that zero-page access is caused by dereferencing a
null pointer */
if (!si->si_addr) {
/* We must be extra caucious here because IP might be
invalid */
if (get_signal_source_cu(ctx) == NULL)
goto exit;

if (install_signal_bh(ctx, throw_null_pointer_exception) == 0)
return;

fprintf(stderr, "%s: install_signal_bh() failed.\n", __func__);
goto exit;
}

/* Garbage collection safepoint */
if (si->si_addr == gc_safepoint_page) {
ucontext_t *uc = ctx;

save_signal_registers(&(vm_get_exec_env()->thread_register_state), &uc->uc_mcontext);
gc_safepoint(&(vm_get_exec_env()->thread_register_state));
return;
}

/* Check if exception was triggered by exception guard */
if (si->si_addr == exceptions_guard_page ||
si->si_addr == trampoline_exceptions_guard_page) {
struct vm_object *exception;

exception = exception_occurred();
if (exception == NULL) {
fprintf(stderr, "%s: spurious exception-test failure\n",
__func__);
goto exit;
}

if (si->si_addr == trampoline_exceptions_guard_page)
throw_from_trampoline(ctx, exception);
else
install_signal_bh(ctx, &rethrow_bh);

return;
}

/* Static field access */
if (si->si_addr == static_guard_page) {
install_signal_bh(ctx, &static_field_signal_bh);
return;
}

if (si->si_addr == jni_stack_badoffset ||
si->si_addr == vm_native_stack_badoffset) {
install_signal_bh(ctx, throw_stack_overflow_error);
return;
}

 exit:
print_backtrace_and_die(sig, si, ctx);
}

static int main_called;

static void sigquit_handler(int sig, siginfo_t *si, void *ctx)
{
struct vm_thread *this;

print_trace();

if (main_called)
return;

main_called = true;

list_for_each_entry(this, &thread_list, list_node) {
if (this == vm_thread_self())
continue;

pthread_kill(this->posix_id, SIGQUIT);
}
}

void setup_signal_handlers(void)
{
struct sigaction sa;

sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_SIGINFO;

sa.sa_sigaction = sigsegv_handler;
sigaction(SIGSEGV, &sa, NULL);

sa.sa_sigaction = sigill_handler;
sigaction(SIGILL, &sa, NULL);

sa.sa_sigaction = sigfpe_handler;
sigaction(SIGFPE, &sa, NULL);

sa.sa_sigaction = sigquit_handler;
sigaction(SIGQUIT, &sa, NULL);

gc_setup_signals();
}
Something went wrong with that request. Please try again.