You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by gs...@apache.org on 2008/01/09 18:07:30 UTC
svn commit: r610460 - in /harmony/enhanced/drlvm/trunk:
build/make/components/vm/ vm/vmcore/src/ncai/utils/
vm/vmcore/src/util/linux/ vm/vmcore/src/util/linux/ia32_em64t/
vm/vmcore/src/util/linux/include/
Author: gshimansky
Date: Wed Jan 9 09:07:05 2008
New Revision: 610460
URL: http://svn.apache.org/viewvc?rev=610460&view=rev
Log:
Applied patch from HARMONY-5366
[drlvm][signals] Linux signal handling unification
Added:
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/ia32_em64t/
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp (with props)
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/crash_handler.h
- copied unchanged from r610387, harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/crash_handler.h
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/signals_common.h (with props)
Removed:
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/crash_handler.h
Modified:
harmony/enhanced/drlvm/trunk/build/make/components/vm/vmcore.xml
harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_utils_linux.cpp
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_em64t.cpp
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ipf.cpp
Modified: harmony/enhanced/drlvm/trunk/build/make/components/vm/vmcore.xml
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/build/make/components/vm/vmcore.xml?rev=610460&r1=610459&r2=610460&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/build/make/components/vm/vmcore.xml (original)
+++ harmony/enhanced/drlvm/trunk/build/make/components/vm/vmcore.xml Wed Jan 9 09:07:05 2008
@@ -149,6 +149,7 @@
<exclude name="util/linux/signals_ia32.cpp" unless="is.unix.x86"/>
<exclude name="util/linux/signals_em64t.cpp" unless="is.unix.x86_64"/>
<exclude name="util/linux/signals_ipf.cpp" unless="is.unix.ia64"/>
+ <include name="util/linux/ia32_em64t/*.cpp" if="is.unix" unless="is.ia64"/>
</fileset>
<includepath path="${extra.zlib.includes}" if="is.windows"/>
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_utils_linux.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_utils_linux.cpp?rev=610460&r1=610459&r2=610460&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_utils_linux.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_utils_linux.cpp Wed Jan 9 09:07:05 2008
@@ -6,8 +6,8 @@
#include "open/ncai_thread.h"
#include "ncai_internal.h"
-void linux_ucontext_to_regs(Registers* regs, ucontext_t *uc);
-void linux_regs_to_ucontext(ucontext_t *uc, Registers* regs);
+void ucontext_to_regs(Registers* regs, ucontext_t *uc);
+void regs_to_ucontext(ucontext_t *uc, Registers* regs);
bool ncai_get_generic_registers(hythread_t thread, Registers* regs)
{
@@ -20,6 +20,6 @@
if (status != TM_ERROR_NONE)
return false;
- linux_ucontext_to_regs(regs, &uc);
+ ucontext_to_regs(regs, &uc);
return true;
}
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp?rev=610460&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp Wed Jan 9 09:07:05 2008
@@ -0,0 +1,623 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_DOMAIN "signals"
+#include "cxxlog.h"
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <stdio.h>
+#include <iostream>
+#include <fstream>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <sys/ucontext.h>
+#include <sys/wait.h>
+
+
+#undef __USE_XOPEN
+#include <signal.h>
+
+#include <pthread.h>
+#if defined(FREEBSD)
+#include <pthread_np.h>
+#endif
+#include <sys/time.h>
+#include "method_lookup.h"
+
+#include "Class.h"
+#include "environment.h"
+
+#include "open/gc.h"
+
+#include "init.h"
+#include "exceptions.h"
+#include "exceptions_jit.h"
+#include "vm_threads.h"
+#include "open/vm_util.h"
+#include "compile.h"
+#include "vm_stats.h"
+#include "sync_bits.h"
+
+#include "object_generic.h"
+#include "thread_manager.h"
+
+#include "exception_filter.h"
+#include "interpreter.h"
+#include "crash_handler.h"
+#include "stack_dump.h"
+#include "jvmti_break_intf.h"
+
+#include "signals_common.h"
+
+
+static void general_crash_handler(int signum, Registers* regs, const char* message);
+
+
+extern "C" {
+static void __attribute__ ((used, cdecl)) c_exception_handler(Class* exn_class, bool java_code) {
+ // this exception handler is executed *after* NT exception handler returned
+ DebugUtilsTI* ti = VM_Global_State::loader_env->TI;
+ // Create local copy for registers because registers in TLS can be changed
+ Registers regs = {0};
+ VM_thread *thread = p_TLS_vmthread;
+ assert(thread);
+ assert(exn_class);
+
+ if (thread->regs) {
+ regs = *thread->regs;
+ }
+
+ exn_athrow_regs(®s, exn_class, java_code, true);
+}
+}
+
+static void throw_from_sigcontext(ucontext_t *uc, Class* exc_clss)
+{
+ Registers regs;
+ ucontext_to_regs(®s, uc);
+
+ DebugUtilsTI* ti = VM_Global_State::loader_env->TI;
+ bool java_code = (vm_identify_eip((void *)regs.get_ip()) == VM_TYPE_JAVA);
+ VM_thread* vmthread = p_TLS_vmthread;
+ NativeCodePtr callback = (NativeCodePtr) c_exception_handler;
+
+ vm_set_exception_registers(vmthread, regs);
+ add_red_zone(®s);
+ regs_push_param(®s, java_code, 1/*2nd arg */);
+ assert(exc_clss);
+ regs_push_param(®s, (POINTER_SIZE_INT)exc_clss, 0/* 1st arg */);
+ // To get proper stack alignment on x86_64
+ regs_align_stack(®s);
+ // imitate return IP on stack
+ regs_push_return_address(®s, NULL);
+
+ // set up the real exception handler address
+ regs.set_ip(callback);
+ regs_to_ucontext(uc, ®s);
+}
+
+static bool java_throw_from_sigcontext(ucontext_t *uc, Class* exc_clss)
+{
+ ASSERT_NO_INTERPRETER;
+ void* ip = (void*)UC_IP(uc);
+ VM_Code_Type vmct = vm_identify_eip(ip);
+ if(vmct != VM_TYPE_JAVA) {
+ return false;
+ }
+
+ throw_from_sigcontext(uc, exc_clss);
+ return true;
+}
+
+/*
+ * Information about stack
+ */
+inline void* find_stack_addr() {
+ int err;
+ void* stack_addr;
+ pthread_attr_t pthread_attr;
+ size_t stack_size;
+
+ pthread_t thread = pthread_self();
+ err = pthread_attr_init(&pthread_attr);
+ assert(!err);
+#if defined(FREEBSD)
+ err = pthread_attr_get_np(thread, &pthread_attr);
+#else
+ err = pthread_getattr_np(thread, &pthread_attr);
+#endif
+ assert(!err);
+ err = pthread_attr_getstack(&pthread_attr, &stack_addr, &stack_size);
+ assert(!err);
+ pthread_attr_destroy(&pthread_attr);
+
+ return (void *)((unsigned char *)stack_addr + stack_size);
+}
+
+#if 0
+inline size_t find_stack_size() {
+ int err;
+ size_t stack_size;
+ pthread_attr_t pthread_attr;
+
+ pthread_attr_init(&pthread_attr);
+ err = pthread_attr_getstacksize(&pthread_attr, &stack_size);
+ pthread_attr_destroy(&pthread_attr);
+ return stack_size;
+}
+#endif
+
+inline size_t find_guard_stack_size() {
+ return 64*1024;
+}
+
+inline size_t find_guard_page_size() {
+ int err;
+ size_t guard_size;
+ pthread_attr_t pthread_attr;
+
+ pthread_attr_init(&pthread_attr);
+ err = pthread_attr_getguardsize(&pthread_attr, &guard_size);
+ pthread_attr_destroy(&pthread_attr);
+
+ return guard_size;
+}
+
+static size_t common_guard_stack_size;
+static size_t common_guard_page_size;
+
+inline void* get_stack_addr() {
+ return jthread_self_vm_thread_unsafe()->stack_addr;
+}
+
+inline size_t get_stack_size() {
+ return jthread_self_vm_thread_unsafe()->stack_size;
+}
+
+inline size_t get_guard_stack_size() {
+ return common_guard_stack_size;
+}
+
+inline size_t get_guard_page_size() {
+ return common_guard_page_size;
+}
+
+#ifdef _IA32_
+static void __attribute__ ((cdecl)) stack_holder(char* addr) {
+ char buf[1024];
+
+ if (addr > (buf + ((size_t)1024))) {
+ return;
+ }
+ stack_holder(addr);
+}
+#endif
+
+void init_stack_info() {
+ vm_thread_t vm_thread = jthread_self_vm_thread_unsafe();
+
+ // find stack parametrs
+ char* stack_addr = (char *)find_stack_addr();
+ vm_thread->stack_addr = stack_addr;
+ size_t stack_size = hythread_get_thread_stacksize(hythread_self());
+ assert(stack_size > 0);
+
+ vm_thread->stack_size = stack_size;
+
+ common_guard_stack_size = find_guard_stack_size();
+ common_guard_page_size = find_guard_page_size();
+
+ // stack should be mapped so it's result of future mapping
+ char* res;
+ // begin of the stack can be protected by OS, but this part already mapped
+ // found address of current stack page
+ char* current_page_addr =
+ (char*)(((size_t)&res) & (~(common_guard_page_size-1)));
+
+ // leave place for mmap work
+ char* mapping_page_addr = current_page_addr - common_guard_page_size;
+
+#ifdef _IA32_
+ // makes sure that stack allocated till mapping_page_addr
+ stack_holder(mapping_page_addr);
+#endif
+
+ // found size of the stack area which should be maped
+ size_t stack_mapping_size = (size_t)mapping_page_addr
+ - (size_t)stack_addr + stack_size;
+
+ // maps unmapped part of the stack
+ res = (char*) mmap(stack_addr - stack_size, stack_mapping_size,
+ PROT_READ | PROT_WRITE, STACK_MMAP_ATTRS, -1, 0);
+
+ // stack should be mapped, checks result
+ assert(res == (stack_addr - stack_size));
+
+ // set guard page
+ set_guard_stack();
+}
+
+bool set_guard_stack() {
+ int err;
+ char* stack_addr = (char*) get_stack_addr();
+ size_t stack_size = get_stack_size();
+ size_t guard_stack_size = get_guard_stack_size();
+ size_t guard_page_size = get_guard_page_size();
+
+ if (((size_t)(&stack_addr) - get_mem_protect_stack_size())
+ < ((size_t)((char*)stack_addr - stack_size
+ + guard_stack_size + 2 * guard_page_size))) {
+ return false;
+ }
+
+ err = mprotect(stack_addr - stack_size + guard_page_size +
+ guard_stack_size, guard_page_size, PROT_NONE );
+
+ assert(!err);
+
+ // sets alternative, guard stack
+ stack_t sigalt;
+ sigalt.ss_sp = stack_addr - stack_size + guard_page_size;
+#if defined(FREEBSD)
+ sigalt.ss_flags = 0;
+#else
+ sigalt.ss_flags = SS_ONSTACK;
+#endif
+ sigalt.ss_size = guard_stack_size;
+ err = sigaltstack (&sigalt, NULL);
+
+ assert(!err);
+
+ // notify that stack is OK and there are no needs to restore it
+ jthread_self_vm_thread_unsafe()->restore_guard_page = false;
+
+ return true;
+}
+
+size_t get_available_stack_size() {
+ char* stack_addr = (char*) get_stack_addr();
+ size_t used_stack_size = stack_addr - ((char*)&stack_addr);
+ size_t available_stack_size;
+
+ if (!(p_TLS_vmthread->restore_guard_page)) {
+ available_stack_size = get_stack_size() - used_stack_size
+ - 2 * get_guard_page_size() - get_guard_stack_size();
+ } else {
+ available_stack_size = get_stack_size() - used_stack_size - get_guard_page_size();
+ }
+
+ if (available_stack_size > 0) {
+ return (size_t) available_stack_size;
+ }
+
+ return 0;
+}
+
+bool check_available_stack_size(size_t required_size) {
+ size_t available_stack_size = get_available_stack_size();
+
+ if (available_stack_size < required_size) {
+ if (available_stack_size < get_guard_stack_size()) {
+ remove_guard_stack(p_TLS_vmthread);
+ }
+ Global_Env *env = VM_Global_State::loader_env;
+ exn_raise_by_class(env->java_lang_StackOverflowError_Class);
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool check_stack_size_enough_for_exception_catch(void* sp) {
+ char* stack_adrr = (char*) get_stack_addr();
+ size_t used_stack_size = ((size_t)stack_adrr) - ((size_t)sp);
+ size_t available_stack_size =
+ get_stack_size() - used_stack_size
+ - 2 * get_guard_page_size() - get_guard_stack_size();
+ return get_restore_stack_size() < available_stack_size;
+}
+
+void remove_guard_stack(vm_thread_t vm_thread) {
+ int err;
+ char* stack_addr = (char*) get_stack_addr();
+ size_t stack_size = get_stack_size();
+ size_t guard_stack_size = get_guard_stack_size();
+ size_t guard_page_size = get_guard_page_size();
+
+
+ err = mprotect(stack_addr - stack_size + guard_page_size +
+ guard_stack_size, guard_page_size, PROT_READ | PROT_WRITE);
+
+
+ stack_t sigalt;
+ sigalt.ss_sp = stack_addr - stack_size + guard_page_size;
+ sigalt.ss_flags = SS_DISABLE;
+ sigalt.ss_size = guard_stack_size;
+
+ err = sigaltstack (&sigalt, NULL);
+
+ vm_thread->restore_guard_page = true;
+}
+
+static bool check_stack_overflow(siginfo_t *info, ucontext_t *uc) {
+ char* stack_addr = (char*) get_stack_addr();
+ size_t stack_size = get_stack_size();
+ size_t guard_stack_size = get_guard_stack_size();
+ size_t guard_page_size = get_guard_page_size();
+
+ char* guard_page_begin = stack_addr - stack_size + guard_page_size + guard_stack_size;
+ char* guard_page_end = guard_page_begin + guard_page_size;
+
+ // FIXME: Workaround for main thread
+ guard_page_end += guard_page_size;
+
+ char* fault_addr = (char*)(info->si_addr);
+ //char* esp_value = (char*)(uc->uc_mcontext.gregs[REG_ESP]);
+
+ return((guard_page_begin <= fault_addr) && (fault_addr < guard_page_end));
+}
+
+
+
+static void stack_overflow_handler(int signum, siginfo_t* UNREF info, void* context)
+{
+ ucontext_t *uc = (ucontext_t *)context;
+ Global_Env *env = VM_Global_State::loader_env;
+
+ vm_thread_t vm_thread = p_TLS_vmthread;
+ remove_guard_stack(vm_thread);
+ vm_thread->restore_guard_page = true;
+
+ if (java_throw_from_sigcontext(
+ uc, env->java_lang_StackOverflowError_Class)) {
+ return;
+ } else {
+ if (is_unwindable()) {
+ if (hythread_is_suspend_enabled()) {
+ tmn_suspend_disable();
+ }
+ throw_from_sigcontext(
+ uc, env->java_lang_StackOverflowError_Class);
+ } else {
+ exn_raise_by_class(env->java_lang_StackOverflowError_Class);
+ }
+ }
+}
+
+
+static void null_java_reference_handler(int signum, siginfo_t* UNREF info, void* context)
+{
+ ucontext_t *uc = (ucontext_t *)context;
+ VM_thread *vm_thread = p_TLS_vmthread;
+ Registers regs;
+ ucontext_to_regs(®s, uc);
+
+ if (vm_thread && vm_thread->jvmti_thread.violation_flag)
+ {
+ vm_thread->jvmti_thread.violation_flag = 0;
+ regs.set_ip(vm_thread->jvmti_thread.violation_restart_address);
+ regs_to_ucontext(uc, ®s);
+ return;
+ }
+
+ Global_Env *env = VM_Global_State::loader_env;
+
+ TRACE2("signals", "NPE or SOE detected at " << (void*)UC_IP(uc));
+
+ if (check_stack_overflow(info, uc)) {
+ stack_overflow_handler(signum, info, context);
+ return;
+ }
+
+ if (!interpreter_enabled()) {
+ if (java_throw_from_sigcontext(
+ uc, env->java_lang_NullPointerException_Class)) {
+ return;
+ }
+ }
+
+ general_crash_handler(signum, ®s, "SIGSEGV");
+}
+
+
+static void null_java_divide_by_zero_handler(int signum, siginfo_t* UNREF info, void* context)
+{
+ ucontext_t *uc = (ucontext_t *)context;
+ Global_Env *env = VM_Global_State::loader_env;
+
+ TRACE2("signals",
+ "ArithmeticException detected at " << (void*)UC_IP(uc));
+
+ if (!interpreter_enabled()) {
+ if (java_throw_from_sigcontext(
+ uc, env->java_lang_ArithmeticException_Class)) {
+ return;
+ }
+ }
+
+ Registers regs;
+ ucontext_to_regs(®s, uc);
+ general_crash_handler(signum, ®s, "SIGFPE");
+}
+
+static void jvmti_jit_breakpoint_handler(int signum, siginfo_t* UNREF info, void* context)
+{
+ ucontext_t *uc = (ucontext_t*)context;
+ Registers regs;
+
+ ucontext_to_regs(®s, uc);
+ TRACE2("signals", "JVMTI breakpoint detected at " << (void*)regs.get_ip());
+
+ if (!interpreter_enabled())
+ {
+ bool handled = jvmti_jit_breakpoint_handler(®s);
+ if (handled)
+ {
+ regs_to_ucontext(uc, ®s);
+ return;
+ }
+ }
+
+ general_crash_handler(signum, ®s, "SIGTRAP");
+}
+
+/**
+ * Print out the call stack of the aborted thread.
+ * @note call stacks may be used for debugging
+ */
+static void abort_handler (int signum, siginfo_t* UNREF info, void* context)
+{
+ Registers regs;
+ ucontext_to_regs(®s, (ucontext_t *)context);
+ general_crash_handler(signum, ®s, "SIGABRT");
+}
+
+static void general_crash_handler(int signum, Registers* regs, const char* message)
+{
+ // setup default handler
+ signal(signum, SIG_DFL);
+ // Print message
+ fprintf(stderr, "Signal is reported: %s\n", message);
+
+ if (!is_gdb_crash_handler_enabled() ||
+ !gdb_crash_handler())
+ {
+ // print stack trace
+ st_print_stack(regs);
+ }
+}
+
+static void general_signal_handler(int signum, siginfo_t* info, void* context)
+{
+ bool replaced = false;
+ ucontext_t* uc = (ucontext_t *)context;
+ POINTER_SIZE_INT saved_eip = (POINTER_SIZE_INT)UC_IP(uc);
+ POINTER_SIZE_INT new_eip = saved_eip;
+ VM_thread* vm_thread = p_TLS_vmthread;
+ bool violation =
+ (signum == SIGSEGV) && vm_thread && vm_thread->jvmti_thread.violation_flag;
+
+ // If exception is occured in processor instruction previously
+ // instrumented by breakpoint, the actual exception address will reside
+ // in jvmti_jit_breakpoints_handling_buffer
+ // We should replace exception address with saved address of instruction
+ POINTER_SIZE_INT break_buf =
+ (POINTER_SIZE_INT)vm_thread->jvmti_thread.jvmti_jit_breakpoints_handling_buffer;
+ if (saved_eip >= break_buf &&
+ saved_eip < break_buf + TM_JVMTI_MAX_BUFFER_SIZE)
+ {
+ // Breakpoints should not occur in breakpoint buffer
+ assert(signum != SIGTRAP);
+
+ replaced = true;
+ new_eip = (POINTER_SIZE_INT)vm_get_ip_from_regs(vm_thread);
+ UC_IP(uc) = new_eip;
+ }
+
+ // Pass exception to NCAI exception handler
+ bool is_handled = 0;
+ bool is_internal = (signum == SIGTRAP) || violation;
+ ncai_process_signal_event((NativeCodePtr)UC_IP(uc),
+ (jint)signum, is_internal, &is_handled);
+ if (is_handled)
+ return;
+
+ switch (signum)
+ {
+ case SIGTRAP:
+ jvmti_jit_breakpoint_handler(signum, info, context);
+ break;
+ case SIGSEGV:
+ null_java_reference_handler(signum, info, context);
+ break;
+ case SIGFPE:
+ null_java_divide_by_zero_handler(signum, info, context);
+ break;
+ case SIGABRT:
+ abort_handler(signum, info, context);
+ break;
+ case SIGINT:
+ vm_interrupt_handler(signum);
+ break;
+ case SIGQUIT:
+ vm_dump_handler(signum);
+ break;
+ default:
+ // Unknown signal
+ assert(0);
+ break;
+ }
+
+ // If EIP was not changed in specific handler to start another handler,
+ // we should restore original EIP, if it's nesessary
+ if (replaced &&
+ UC_IP(uc) == new_eip)
+ {
+ UC_IP(uc) = saved_eip;
+ }
+}
+
+void initialize_signals()
+{
+ struct sigaction sa;
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = &general_signal_handler;
+ sigaction(SIGTRAP, &sa, NULL);
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO | SA_ONSTACK;;
+ sa.sa_sigaction = &general_signal_handler;
+ sigaction(SIGSEGV, &sa, NULL);
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = &general_signal_handler;
+ sigaction(SIGFPE, &sa, NULL);
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = &general_signal_handler;
+ sigaction(SIGINT, &sa, NULL);
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = &general_signal_handler;
+ sigaction(SIGQUIT, &sa, NULL);
+
+ /* install abort_handler to print out call stack on assertion failures */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = &general_signal_handler;
+ sigaction( SIGABRT, &sa, NULL);
+ /* abort_handler installed */
+
+ // Prepare gdb crash handler
+ init_gdb_crash_handler();
+
+} //initialize_signals
+
+void shutdown_signals() {
+ //FIXME: should be defined in future
+} //shutdown_signals
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/signals_common.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/signals_common.h?rev=610460&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/signals_common.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/signals_common.h Wed Jan 9 09:07:05 2008
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _SIGNALS_COMMON_H_
+#define _SIGNALS_COMMON_H_
+
+#include <sys/ucontext.h>
+#include "vm_core_types.h"
+
+
+#ifdef _IPF_
+#error IPF architecture is not adopted for unified signal handling
+#endif
+
+#ifdef _EM64T_
+// vvvvvvvv EM64T vvvvvvvv
+
+// Prototype: POINTER_SIZE_INT& UC_IP(ucontext_t* uc)
+#define UC_IP(uc) (uc->uc_mcontext.gregs[REG_RIP])
+
+inline void add_red_zone(Registers* pregs) {pregs->rsp -= 0x80;}
+
+void regs_push_param(Registers* pregs, POINTER_SIZE_INT param, int UNREF num);
+
+inline void regs_push_return_address(Registers* pregs, void* ret_addr) {
+ pregs->rsp = pregs->rsp - 8;
+ *((void**)pregs->rsp) = ret_addr;
+}
+
+inline void regs_align_stack(Registers* pregs) {
+ pregs->rsp = pregs->rsp - 8;
+ *((void**)pregs->rsp) = 0;
+}
+
+inline size_t get_mem_protect_stack_size() { return 0x0400; }
+
+inline size_t get_restore_stack_size() {
+ return get_mem_protect_stack_size() + 0x0400;
+}
+
+// ^^^^^^^^ EM64T ^^^^^^^^
+#else // #ifdef _EM64T_
+// vvvvvvvv IA-32 vvvvvvvv
+
+#if defined(LINUX)
+// Prototype: POINTER_SIZE_INT& UC_IP(ucontext_t* uc)
+#define UC_IP(uc) (uc->uc_mcontext.gregs[REG_EIP])
+#elif defined(FREEBSD)
+#define UC_IP(uc) (uc->uc_mcontext.mc_eip)
+#endif
+
+inline void add_red_zone(Registers* pregs) {}
+
+inline void regs_push_param(Registers* pregs, POINTER_SIZE_INT param, int UNREF num) {
+ pregs->esp = pregs->esp - 4;
+ *((uint32*)pregs->esp) = param;
+}
+
+inline void regs_push_return_address(Registers* pregs, void* ret_addr) {
+ pregs->esp = pregs->esp - 4;
+ *((void**)pregs->esp) = ret_addr;
+}
+
+inline void regs_align_stack(Registers* pregs) {}
+
+inline size_t get_mem_protect_stack_size() { return 0x0100; }
+
+inline size_t get_restore_stack_size() {
+ return get_mem_protect_stack_size() + 0x0100;
+}
+
+// ^^^^^^^^ IA-32 ^^^^^^^^
+#endif // #ifdef _EM64T_
+
+
+// Linux/FreeBSD defines
+#if defined(FREEBSD)
+#define STACK_MMAP_ATTRS \
+ (MAP_FIXED | MAP_PRIVATE | MAP_ANON | MAP_STACK)
+#else
+#define STACK_MMAP_ATTRS \
+ (MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN)
+#endif
+
+
+
+void ucontext_to_regs(Registers* regs, ucontext_t *uc);
+void regs_to_ucontext(ucontext_t *uc, Registers* regs);
+
+
+#endif // _SIGNALS_COMMON_H_
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/signals_common.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_em64t.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_em64t.cpp?rev=610460&r1=610459&r2=610460&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_em64t.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_em64t.cpp Wed Jan 9 09:07:05 2008
@@ -14,63 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/**
- * @author Intel, Evgueni Brevnov
- * @version $Revision: 1.1.2.1.4.4 $
- */
-// We use signal handlers to detect null pointer and divide by zero
-// exceptions.
-// There must be an easier way of locating the context in the signal
-// handler than what we do here.
-#define LOG_DOMAIN "port.old"
-#include "cxxlog.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <stdio.h>
-#include <iostream>
-#include <fstream>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
#include <sys/ucontext.h>
-#include <sys/wait.h>
-#include <sys/mman.h>
-
-#undef __USE_XOPEN
-#include <signal.h>
-
-#include <pthread.h>
-#include <sys/time.h>
-#include "method_lookup.h"
+#include "vm_core_types.h"
+#include "signals_common.h"
-#include "Class.h"
-#include "environment.h"
-
-#include "open/gc.h"
-
-#include "init.h"
-#include "exceptions.h"
-#include "exceptions_jit.h"
-#include "vm_threads.h"
-#include "open/vm_util.h"
-#include "compile.h"
-#include "vm_stats.h"
-#include "sync_bits.h"
-#include "object_generic.h"
-#include "thread_manager.h"
-
-#include "exception_filter.h"
-#include "interpreter.h"
-#include "crash_handler.h"
-#include "stack_dump.h"
-
-void linux_ucontext_to_regs(Registers* regs, ucontext_t *uc)
+void ucontext_to_regs(Registers* regs, ucontext_t *uc)
{
regs->rax = uc->uc_mcontext.gregs[REG_RAX];
regs->rcx = uc->uc_mcontext.gregs[REG_RCX];
@@ -81,8 +32,8 @@
regs->rbp = uc->uc_mcontext.gregs[REG_RBP];
regs->rip = uc->uc_mcontext.gregs[REG_RIP];
regs->rsp = uc->uc_mcontext.gregs[REG_RSP];
- regs->r8 = uc->uc_mcontext.gregs[REG_R8];
- regs->r9 = uc->uc_mcontext.gregs[REG_R9];
+ regs->r8 = uc->uc_mcontext.gregs[REG_R8];
+ regs->r9 = uc->uc_mcontext.gregs[REG_R9];
regs->r10 = uc->uc_mcontext.gregs[REG_R10];
regs->r11 = uc->uc_mcontext.gregs[REG_R11];
regs->r12 = uc->uc_mcontext.gregs[REG_R12];
@@ -92,7 +43,7 @@
regs->eflags = uc->uc_mcontext.gregs[REG_EFL];
}
-void linux_regs_to_ucontext(ucontext_t *uc, Registers* regs)
+void regs_to_ucontext(ucontext_t *uc, Registers* regs)
{
uc->uc_mcontext.gregs[REG_RAX] = regs->rax;
uc->uc_mcontext.gregs[REG_RCX] = regs->rcx;
@@ -103,8 +54,8 @@
uc->uc_mcontext.gregs[REG_RBP] = regs->rbp;
uc->uc_mcontext.gregs[REG_RIP] = regs->rip;
uc->uc_mcontext.gregs[REG_RSP] = regs->rsp;
- uc->uc_mcontext.gregs[REG_R8] = regs->r8;
- uc->uc_mcontext.gregs[REG_R9] = regs->r9;
+ uc->uc_mcontext.gregs[REG_R8] = regs->r8;
+ uc->uc_mcontext.gregs[REG_R9] = regs->r9;
uc->uc_mcontext.gregs[REG_R10] = regs->r10;
uc->uc_mcontext.gregs[REG_R11] = regs->r11;
uc->uc_mcontext.gregs[REG_R12] = regs->r12;
@@ -139,567 +90,3 @@
return;
}
}
-
-void regs_push_return_address(Registers* pregs, void* ret_addr)
-{
- pregs->rsp = pregs->rsp - 8;
- *((void**)pregs->rsp) = ret_addr;
-}
-
-extern "C" {
-// Gregory -
-// Attribute cdecl is not used here because it has no meaning in x86_64 calling conventions
-void __attribute__ ((used)) c_exception_handler(Class* exn_class, bool java_code) {
- // this exception handler is executed *after* NT exception handler returned
- DebugUtilsTI* ti = VM_Global_State::loader_env->TI;
- // Create local copy for registers because registers in TLS can be changed
- Registers regs = {0};
- VM_thread *thread = p_TLS_vmthread;
- assert(thread);
- assert(exn_class);
-
- if (thread->regs) {
- regs = *(Registers*)thread->regs;
- }
-
- exn_athrow_regs(®s, exn_class, java_code, true);
-}
-}
-
-static void throw_from_sigcontext(ucontext_t *uc, Class* exc_clss)
-{
- Registers regs;
- linux_ucontext_to_regs(®s, uc);
-
- DebugUtilsTI* ti = VM_Global_State::loader_env->TI;
- bool java_code = (vm_identify_eip((void *)regs.rip) == VM_TYPE_JAVA);
- VM_thread* vmthread = p_TLS_vmthread;
- NativeCodePtr callback = (NativeCodePtr) c_exception_handler;
- const static uint64 red_zone_size = 0x80;
-
- vm_set_exception_registers(vmthread, regs);
- regs.rsp -= red_zone_size;
- regs_push_param(®s, java_code, 1);
- assert(exc_clss);
- regs_push_param(®s, (POINTER_SIZE_INT)exc_clss, 0);
- // imitate return IP on stack
- regs_push_return_address(®s, NULL);
- regs_push_return_address(®s, NULL);
-
- // set up the real exception handler address
- regs.set_ip(callback);
- linux_regs_to_ucontext(uc, ®s);
-}
-
-static bool java_throw_from_sigcontext(ucontext_t *uc, Class* exc_clss)
-{
- ASSERT_NO_INTERPRETER;
- unsigned *rip = (unsigned *) uc->uc_mcontext.gregs[REG_RIP];
- VM_Code_Type vmct = vm_identify_eip((void *)rip);
- if(vmct != VM_TYPE_JAVA) {
- return false;
- }
-
- throw_from_sigcontext(uc, exc_clss);
- return true;
-}
-
-/**
- * the saved copy of the executable name.
- */
-static char executable[1024];
-
-/**
- * invokes addr2line to decode stack.
- */
-void addr2line (char *buf) {
-
- if ('\0' == executable[0]) {
- // no executable name is available, degrade gracefully
- LWARN(41, "Execution stack follows, consider using addr2line\n{0}" << buf);
- return;
- }
-
- //
- // NOTE: this function is called from signal handler,
- // so it should use only limited list
- // of async signal-safe system calls
- //
- // Currently used list:
- // pipe, fork, close, dup2, execle, write, wait
- //
- int pipes[2];
- pipe(pipes); // create pipe
- if (0 == fork()) { // child
-
- close(pipes[1]); // close unneeded write pipe
- close(0); // close stdin
- dup2(pipes[0],0); // replicate read pipe as stdin
-
- close(1); // close stdout
- dup2(2,1); // replicate stderr as stdout
-
- char *env[] = {NULL};
-
- execle("/usr/bin/addr2line", "addr2line", "-e", executable, "-C", "-s", "-f", NULL, env);
-
- } else { // parent
- close(pipes[0]); // close unneeded read pipe
-
- write(pipes[1],buf,strlen(buf));
- close(pipes[1]); // close write pipe
-
- int status;
- wait(&status); // wait for the child to complete
- }
-}
-
-/*
- * Information about stack
- */
-inline void* find_stack_addr() {
- int err;
- void* stack_addr;
- size_t stack_size;
- pthread_attr_t pthread_attr;
-
- pthread_t thread = pthread_self();
- err = pthread_getattr_np(thread, &pthread_attr);
- assert(!err);
- err = pthread_attr_getstack(&pthread_attr, &stack_addr, &stack_size);
- assert(!err);
- pthread_attr_destroy(&pthread_attr);
-
- return (void *)((unsigned char *)stack_addr + stack_size);
-}
-
-#if 0
-inline size_t find_stack_size() {
- int err;
- size_t stack_size;
- pthread_attr_t pthread_attr;
-
- pthread_attr_init(&pthread_attr);
- err = pthread_attr_getstacksize(&pthread_attr, &stack_size);
- pthread_attr_destroy(&pthread_attr);
- return stack_size;
-}
-#endif
-
-inline size_t find_guard_stack_size() {
- return 64*1024;
-}
-
-inline size_t find_guard_page_size() {
- int err;
- size_t guard_size;
- pthread_attr_t pthread_attr;
-
- pthread_attr_init(&pthread_attr);
- err = pthread_attr_getguardsize(&pthread_attr, &guard_size);
- pthread_attr_destroy(&pthread_attr);
- return guard_size;
-}
-
-static size_t common_guard_stack_size;
-static size_t common_guard_page_size;
-
-inline void* get_stack_addr() {
- return jthread_self_vm_thread_unsafe()->stack_addr;
-}
-
-inline size_t get_stack_size() {
- return jthread_self_vm_thread_unsafe()->stack_size;
-}
-
-inline size_t get_guard_stack_size() {
- return common_guard_stack_size;
-}
-
-inline size_t get_guard_page_size() {
- return common_guard_page_size;
-}
-
-void init_stack_info() {
- vm_thread_t vm_thread = jthread_self_vm_thread_unsafe();
- char* stack_addr = (char *)find_stack_addr();
- unsigned int stack_size = hythread_get_thread_stacksize(hythread_self());
- vm_thread->stack_addr = stack_addr;
- vm_thread->stack_size = stack_size;
- common_guard_stack_size = find_guard_stack_size();
- common_guard_page_size =find_guard_page_size();
-
- // stack should be mapped so it's result of future mapping
- char* res;
-
- // begin of the stack can be protected by OS, but this part already mapped
- // found address of current stack page
- char* current_page_addr =
- (char*)(((size_t)&res) & (~(common_guard_page_size-1)));
-
- // leave place for mmap work
- char* mapping_page_addr = current_page_addr - common_guard_page_size;
-
- // makes sure that stack allocated till mapping_page_addr
- //stack_holder(mapping_page_addr);
-
- // found size of the stack area which should be maped
- size_t stack_mapping_size = (size_t)mapping_page_addr
- - (size_t)stack_addr + stack_size;
-
- // maps unmapped part of the stack
- res = (char*) mmap(stack_addr - stack_size,
- stack_mapping_size,
- PROT_READ | PROT_WRITE,
- MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN,
- -1,
- 0);
- // stack should be mapped, checks result
- assert(res == (stack_addr - stack_size));
-
- // set guard page
- set_guard_stack();
-}
-
-size_t get_mem_protect_stack_size() {
- return 0x0400;
-}
-
-size_t get_restore_stack_size() {
- return get_mem_protect_stack_size() + 0x0400;
-}
-
-bool set_guard_stack() {
- int err;
- char* stack_addr = (char*) get_stack_addr();
- size_t stack_size = get_stack_size();
- size_t guard_stack_size = get_guard_stack_size();
- size_t guard_page_size = get_guard_page_size();
-
- if (((size_t)(&stack_addr) - get_mem_protect_stack_size())
- < ((size_t)((char*)stack_addr - stack_size
- + guard_stack_size + 2 * guard_page_size))) {
- return false;
- }
-
- err = mprotect(stack_addr - stack_size + guard_page_size + guard_stack_size,
- guard_page_size, PROT_NONE);
-
- stack_t sigalt;
- sigalt.ss_sp = stack_addr - stack_size + guard_page_size;
- sigalt.ss_flags = SS_ONSTACK;
- sigalt.ss_size = guard_stack_size;
-
- err = sigaltstack (&sigalt, NULL);
-
- jthread_self_vm_thread_unsafe()->restore_guard_page = false;
-
- return true;
-}
-
-size_t get_available_stack_size() {
- char* stack_addr = (char*) get_stack_addr();
- size_t used_stack_size = stack_addr - ((char*)&stack_addr);
- int available_stack_size;
-
- if (!(p_TLS_vmthread->restore_guard_page)) {
- available_stack_size = get_stack_size() - used_stack_size
- - 2 * get_guard_page_size() - get_guard_stack_size();
- } else {
- available_stack_size = get_stack_size() - used_stack_size - get_guard_page_size();
- }
-
- if (available_stack_size > 0) {
- return (size_t) available_stack_size;
- } else {
- return 0;
- }
-}
-
-bool check_available_stack_size(size_t required_size) {
- size_t available_stack_size = get_available_stack_size();
-
- if (available_stack_size < required_size) {
- if (available_stack_size < get_guard_stack_size()) {
- remove_guard_stack(p_TLS_vmthread);
- }
- Global_Env *env = VM_Global_State::loader_env;
- exn_raise_by_class(env->java_lang_StackOverflowError_Class);
- return false;
- } else {
- return true;
- }
-}
-
-bool check_stack_size_enough_for_exception_catch(void* sp) {
- char* stack_adrr = (char*) get_stack_addr();
- size_t used_stack_size = ((size_t)stack_adrr) - ((size_t)sp);
- size_t available_stack_size =
- get_stack_size() - used_stack_size
- - 2 * get_guard_page_size() - get_guard_stack_size();
- return get_restore_stack_size() < available_stack_size;
-}
-
-void remove_guard_stack() {
- vm_thread_t vm_thread = jthread_self_vm_thread_unsafe();
- assert(vm_thread);
- remove_guard_stack(vm_thread);
-}
-
-void remove_guard_stack(vm_thread_t vm_thread) {
- int err;
- char* stack_addr = (char*) get_stack_addr();
- size_t stack_size = get_stack_size();
- size_t guard_stack_size = get_guard_stack_size();
- size_t guard_page_size = get_guard_page_size();
-
- err = mprotect(stack_addr - stack_size + guard_page_size + guard_stack_size,
- guard_page_size, PROT_READ | PROT_WRITE);
-
- stack_t sigalt;
- sigalt.ss_sp = stack_addr - stack_size + guard_page_size;
- sigalt.ss_flags = SS_DISABLE;
- sigalt.ss_size = guard_stack_size;
-
- err = sigaltstack (&sigalt, NULL);
-
- vm_thread->restore_guard_page = true;
-}
-
-bool check_stack_overflow(siginfo_t *info, ucontext_t *uc) {
- char* stack_addr = (char*) get_stack_addr();
- size_t stack_size = get_stack_size();
- size_t guard_stack_size = get_guard_stack_size();
- size_t guard_page_size = get_guard_page_size();
-
- char* guard_page_begin = stack_addr - stack_size + guard_page_size + guard_stack_size;
- char* guard_page_end = guard_page_begin + guard_page_size;
-
- // FIXME: Workaround for main thread
- guard_page_end += guard_page_size;
-
- char* fault_addr = (char*)(info->si_addr);
- //char* esp_value = (char*)(uc->uc_mcontext.gregs[REG_ESP]);
-
- return((guard_page_begin <= fault_addr) && (fault_addr < guard_page_end));
-}
-
-
-/*
- * We find the true signal stack frame set-up by kernel,which is located
- * by locate_sigcontext() below; then change its content according to
- * exception handling semantics, so that when the signal handler is
- * returned, application can continue its execution in Java exception handler.
- */
-void stack_overflow_handler(int signum, siginfo_t* UNREF info, void* context)
-{
- ucontext_t *uc = (ucontext_t *)context;
- Global_Env *env = VM_Global_State::loader_env;
-
- vm_thread_t vm_thread = p_TLS_vmthread;
- remove_guard_stack(vm_thread);
- vm_thread->restore_guard_page = true;
-
- if (java_throw_from_sigcontext(
- uc, env->java_lang_StackOverflowError_Class)) {
- return;
- } else {
- if (is_unwindable()) {
- if (hythread_is_suspend_enabled()) {
- tmn_suspend_disable();
- }
- throw_from_sigcontext(
- uc, env->java_lang_StackOverflowError_Class);
- } else {
- exn_raise_by_class(env->java_lang_StackOverflowError_Class);
- }
- }
-}
-
-
-void null_java_reference_handler(int signum, siginfo_t* info, void* context)
-{
- ucontext_t *uc = (ucontext_t *)context;
- Global_Env *env = VM_Global_State::loader_env;
-
- if (check_stack_overflow(info, uc)) {
- stack_overflow_handler(signum, info, context);
- return;
- }
-
- if (!interpreter_enabled()) {
- if (java_throw_from_sigcontext(
- uc, env->java_lang_NullPointerException_Class)) {
- return;
- }
- }
-
- fprintf(stderr, "SIGSEGV in VM code.\n");
- Registers regs;
- linux_ucontext_to_regs(®s, uc);
-
- // setup default handler
- signal(signum, SIG_DFL);
-
- if (!is_gdb_crash_handler_enabled() ||
- !gdb_crash_handler())
- {
- // print stack trace
- st_print_stack(®s);
- }
-}
-
-
-void null_java_divide_by_zero_handler(int signum, siginfo_t* info, void* context)
-{
- ucontext_t *uc = (ucontext_t *)context;
- Global_Env *env = VM_Global_State::loader_env;
-
- if (!interpreter_enabled()) {
- if (java_throw_from_sigcontext(
- uc, env->java_lang_ArithmeticException_Class)) {
- return;
- }
- }
-
- fprintf(stderr, "SIGFPE in VM code.\n");
- Registers regs;
- linux_ucontext_to_regs(®s, uc);
-
- // setup default handler
- signal(signum, SIG_DFL);
-
- if (!is_gdb_crash_handler_enabled() ||
- !gdb_crash_handler())
- {
- // print stack trace
- st_print_stack(®s);
- }
-}
-
-void jvmti_jit_breakpoint_handler(int signum, siginfo_t* UNREF info, void* context)
-{
- ucontext_t *uc = (ucontext_t *)context;
- Registers regs;
-
- linux_ucontext_to_regs(®s, uc);
- TRACE2("signals", "JVMTI breakpoint detected at " <<
- (void *)regs.rip);
- assert(!interpreter_enabled());
-
- bool handled = jvmti_jit_breakpoint_handler(®s);
- if (handled)
- {
- linux_regs_to_ucontext(uc, ®s);
- return;
- }
-
- fprintf(stderr, "SIGTRAP in VM code.\n");
- linux_ucontext_to_regs(®s, uc);
-
- // setup default handler
- signal(signum, SIG_DFL);
-
- if (!is_gdb_crash_handler_enabled() ||
- !gdb_crash_handler())
- {
- // print stack trace
- st_print_stack(®s);
- }
-}
-
-/**
- * Print out the call stack of the aborted thread.
- * @note call stacks may be used for debugging
- */
-void abort_handler (int signum, siginfo_t* UNREF info, void* context) {
- fprintf(stderr, "SIGABRT in VM code.\n");
- Registers regs;
- ucontext_t *uc = (ucontext_t *)context;
- linux_ucontext_to_regs(®s, uc);
-
- // setup default handler
- signal(signum, SIG_DFL);
-
- if (!is_gdb_crash_handler_enabled() ||
- !gdb_crash_handler())
- {
- // print stack trace
- st_print_stack(®s);
- }
-}
-
-void general_signal_handler(int signum, siginfo_t* info, void* context)
-{
- bool replaced = false;
- ucontext_t* uc = (ucontext_t *)context;
- POINTER_SIZE_INT saved_ip = (POINTER_SIZE_INT)uc->uc_mcontext.gregs[REG_RIP];
- POINTER_SIZE_INT new_ip = 0;
-
- // If exception is occured in processor instruction previously
- // instrumented by breakpoint, the actual exception address will reside
- // in jvmti_jit_breakpoints_handling_buffer
- // We should replace exception address with saved address of instruction
- POINTER_SIZE_INT break_buf =
- (POINTER_SIZE_INT)p_TLS_vmthread->jvmti_thread.jvmti_jit_breakpoints_handling_buffer;
- if (saved_ip >= break_buf &&
- saved_ip < break_buf + TM_JVMTI_MAX_BUFFER_SIZE)
- {
- // Breakpoints should not occur in breakpoint buffer
- assert(signum != SIGTRAP);
-
- replaced = true;
- new_ip = (POINTER_SIZE_INT)vm_get_ip_from_regs(p_TLS_vmthread);
- uc->uc_mcontext.gregs[REG_RIP] = (greg_t)new_ip;
- }
-
- // FIXME: Should unify all signals here as it is done on ia32
- jvmti_jit_breakpoint_handler(signum, info, context);
-
- // If EIP was not changed in specific handler to start another handler,
- // we should restore original EIP, if it's nesessary
- if (replaced &&
- (POINTER_SIZE_INT)uc->uc_mcontext.gregs[REG_RIP] == new_ip)
- {
- uc->uc_mcontext.gregs[REG_RIP] = (greg_t)saved_ip;
- }
-}
-
-void initialize_signals()
-{
- struct sigaction sa;
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &general_signal_handler;
- sigaction(SIGTRAP, &sa, NULL);
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO | SA_ONSTACK;;
- sa.sa_sigaction = &null_java_reference_handler;
- sigaction(SIGSEGV, &sa, NULL);
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &null_java_divide_by_zero_handler;
- sigaction(SIGFPE, &sa, NULL);
-
- signal(SIGINT, (void (*)(int)) vm_interrupt_handler);
- signal(SIGQUIT, (void (*)(int)) vm_dump_handler);
-
- /* install abort_handler to print out call stack on assertion failures */
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &abort_handler;
- sigaction( SIGABRT, &sa, NULL);
- /* abort_handler installed */
-
- // Prepare gdb crash handler
- init_gdb_crash_handler();
-
-} //initialize_signals
-
-void shutdown_signals() {
- //FIXME: should be defined in future
-} //shutdown_signals
-
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp?rev=610460&r1=610459&r2=610460&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp Wed Jan 9 09:07:05 2008
@@ -14,69 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/**
- * @author Intel, Evgueni Brevnov
- * @version $Revision: 1.1.2.1.4.4 $
- */
-// We use signal handlers to detect null pointer and divide by zero
-// exceptions.
-// There must be an easier way of locating the context in the signal
-// handler than what we do here.
-#define LOG_DOMAIN "port.old"
-#include "cxxlog.h"
-
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <stdio.h>
-#include <iostream>
-#include <fstream>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
#include <sys/ucontext.h>
-#include <sys/wait.h>
-
-
-#undef __USE_XOPEN
-#include <signal.h>
-
-#include <pthread.h>
-#if defined(FREEBSD)
-#include <pthread_np.h>
-#endif
-#include <sys/time.h>
-#include "method_lookup.h"
-
-#include "Class.h"
-#include "environment.h"
-
-#include "open/gc.h"
+#include "vm_core_types.h"
+#include "signals_common.h"
-#include "init.h"
-#include "exceptions.h"
-#include "exceptions_jit.h"
-#include "vm_threads.h"
-#include "open/vm_util.h"
-#include "compile.h"
-#include "vm_stats.h"
-#include "sync_bits.h"
-
-#include "object_generic.h"
-#include "thread_manager.h"
-
-#include "exception_filter.h"
-#include "interpreter.h"
-#include "crash_handler.h"
-#include "stack_dump.h"
-#include "jvmti_break_intf.h"
#if defined(LINUX)
-void linux_ucontext_to_regs(Registers* regs, ucontext_t *uc)
+void ucontext_to_regs(Registers* regs, ucontext_t *uc)
{
regs->eax = uc->uc_mcontext.gregs[REG_EAX];
regs->ecx = uc->uc_mcontext.gregs[REG_ECX];
@@ -90,7 +36,7 @@
regs->eflags = uc->uc_mcontext.gregs[REG_EFL];
}
-void linux_regs_to_ucontext(ucontext_t *uc, Registers* regs)
+void regs_to_ucontext(ucontext_t *uc, Registers* regs)
{
uc->uc_mcontext.gregs[REG_EAX] = regs->eax;
uc->uc_mcontext.gregs[REG_ECX] = regs->ecx;
@@ -104,13 +50,8 @@
uc->uc_mcontext.gregs[REG_EFL] = regs->eflags;
}
-#define UCONTEXT_TO_REGS linux_ucontext_to_regs
-#define REGS_TO_UCONTEXT linux_regs_to_ucontext
-#define REGISTER_EIP uc->uc_mcontext.gregs[REG_EIP]
-
-#else
-#if defined(FREEBSD)
-void freebsd_ucontext_to_regs(Registers* regs, ucontext_t *uc)
+#elif defined(FREEBSD)
+void ucontext_to_regs(Registers* regs, ucontext_t *uc)
{
regs->eax = uc->uc_mcontext.mc_eax;
regs->ecx = uc->uc_mcontext.mc_ecx;
@@ -124,7 +65,7 @@
regs->eflags = uc->uc_mcontext.mc_eflags;
}
-void freebsd_regs_to_ucontext(ucontext_t *uc, Registers* regs)
+void regs_to_ucontext(ucontext_t *uc, Registers* regs)
{
uc->uc_mcontext.mc_eax = regs->eax;
uc->uc_mcontext.mc_ecx = regs->ecx;
@@ -138,687 +79,6 @@
uc->uc_mcontext.mc_eflags = regs->eflags;
}
-#define UCONTEXT_TO_REGS freebsd_ucontext_to_regs
-#define REGS_TO_UCONTEXT freebsd_regs_to_ucontext
-#define REGISTER_EIP uc->uc_mcontext.mc_eip
#else
#error need to add correct mcontext_t lookup for registers
#endif
-#endif
-
-
-void regs_push_param(Registers* pregs, POINTER_SIZE_INT param, int UNREF num)
-{
- pregs->esp = pregs->esp - 4;
- *((uint32*)pregs->esp) = param;
-}
-
-void regs_push_return_address(Registers* pregs, void* ret_addr)
-{
- pregs->esp = pregs->esp - 4;
- *((void**)pregs->esp) = ret_addr;
-}
-
-extern "C" {
-void __attribute__ ((used, cdecl)) c_exception_handler(Class* exn_class, bool java_code) {
- // this exception handler is executed *after* NT exception handler returned
- DebugUtilsTI* ti = VM_Global_State::loader_env->TI;
- // Create local copy for registers because registers in TLS can be changed
- Registers regs = {0};
- VM_thread *thread = p_TLS_vmthread;
- assert(thread);
- assert(exn_class);
-
- if (thread->regs) {
- regs = *(Registers*)thread->regs;
- }
-
- exn_athrow_regs(®s, exn_class, java_code, true);
-}
-}
-
-static void throw_from_sigcontext(ucontext_t *uc, Class* exc_clss)
-{
- Registers regs;
- UCONTEXT_TO_REGS(®s, uc);
-
- DebugUtilsTI* ti = VM_Global_State::loader_env->TI;
- bool java_code = (vm_identify_eip((void *)regs.eip) == VM_TYPE_JAVA);
- VM_thread* vmthread = p_TLS_vmthread;
- NativeCodePtr callback = (NativeCodePtr) c_exception_handler;
-
- vm_set_exception_registers(vmthread, regs);
- regs_push_param(®s, java_code, 1/*2nd arg */);
- assert(exc_clss);
- regs_push_param(®s, (POINTER_SIZE_INT)exc_clss, 0/* 1st arg */);
- // imitate return IP on stack
- regs_push_return_address(®s, NULL);
-
- // set up the real exception handler address
- regs.set_ip(callback);
- REGS_TO_UCONTEXT(uc, ®s);
-}
-
-static bool java_throw_from_sigcontext(ucontext_t *uc, Class* exc_clss)
-{
- ASSERT_NO_INTERPRETER;
- unsigned *eip = (unsigned *) REGISTER_EIP;
- VM_Code_Type vmct = vm_identify_eip((void *)eip);
- if(vmct != VM_TYPE_JAVA) {
- return false;
- }
-
- throw_from_sigcontext(uc, exc_clss);
- return true;
-}
-
-/**
- * the saved copy of the executable name.
- */
-static char executable[1024];
-
-/**
- * invokes addr2line to decode stack.
- */
-void addr2line (char *buf) {
-
- if ('\0' == executable[0]) {
- // no executable name is available, degrade gracefully
- LWARN(41, "Execution stack follows, consider using addr2line\n{0}" << buf);
- return;
- }
-
- //
- // NOTE: this function is called from signal handler,
- // so it should use only limited list
- // of async signal-safe system calls
- //
- // Currently used list:
- // pipe, fork, close, dup2, execle, write, wait
- //
- int pipes[2];
- pipe(pipes); // create pipe
- if (0 == fork()) { // child
-
- close(pipes[1]); // close unneeded write pipe
- close(0); // close stdin
- dup2(pipes[0],0); // replicate read pipe as stdin
-
- close(1); // close stdout
- dup2(2,1); // replicate stderr as stdout
-
- char *env[] = {NULL};
-
- execle("/usr/bin/addr2line", "addr2line", "-e", executable, "-C", "-s", NULL, env);
-
- } else { // parent
- close(pipes[0]); // close unneeded read pipe
-
- write(pipes[1],buf,strlen(buf));
- close(pipes[1]); // close write pipe
-
- int status;
- wait(&status); // wait for the child to complete
- }
-}
-
-/**
- * Print out the call stack.
- */
-void print_native_stack (unsigned *ebp) {
- int depth = 17;
- LWARN(42, "Fatal error");
- char buf[1024];
- unsigned int n = 0;
- while (ebp && ebp[1] && --depth >= 0 && (n<sizeof(buf)-20)) {
- n += sprintf(buf+n,"%08x\n",ebp[1]);
- ebp = (unsigned *)ebp[0];
- }
- addr2line(buf);
-}
-
-/*
- * Information about stack
- */
-inline void* find_stack_addr() {
- int err;
- void* stack_addr;
- pthread_attr_t pthread_attr;
- size_t stack_size;
-
- pthread_t thread = pthread_self();
- err = pthread_attr_init(&pthread_attr);
- assert(!err);
-#if defined(FREEBSD)
- err = pthread_attr_get_np(thread, &pthread_attr);
-#else
- err = pthread_getattr_np(thread, &pthread_attr);
-#endif
- assert(!err);
- err = pthread_attr_getstack(&pthread_attr, &stack_addr, &stack_size);
- assert(!err);
- pthread_attr_destroy(&pthread_attr);
-
- return (void *)((unsigned char *)stack_addr + stack_size);
-}
-
-#if 0
-inline size_t find_stack_size() {
- int err;
- size_t stack_size;
- pthread_attr_t pthread_attr;
-
- pthread_attr_init(&pthread_attr);
- err = pthread_attr_getstacksize(&pthread_attr, &stack_size);
- pthread_attr_destroy(&pthread_attr);
- return stack_size;
-}
-#endif
-
-inline size_t find_guard_stack_size() {
- return 64*1024;
-
-}
-
-inline size_t find_guard_page_size() {
- int err;
- size_t guard_size;
- pthread_attr_t pthread_attr;
-
- pthread_attr_init(&pthread_attr);
- err = pthread_attr_getguardsize(&pthread_attr, &guard_size);
- pthread_attr_destroy(&pthread_attr);
-
- return guard_size;
-}
-
-static size_t common_guard_stack_size;
-static size_t common_guard_page_size;
-
-inline void* get_stack_addr() {
- return jthread_self_vm_thread_unsafe()->stack_addr;
-}
-
-inline size_t get_stack_size() {
- return jthread_self_vm_thread_unsafe()->stack_size;
-}
-
-inline size_t get_guard_stack_size() {
- return common_guard_stack_size;
-}
-
-inline size_t get_guard_page_size() {
- return common_guard_page_size;
-}
-
-static void __attribute__ ((cdecl)) stack_holder(char* addr) {
- char buf[1024];
-
- if (addr > (buf + ((size_t)1024))) {
- return;
- }
- stack_holder(addr);
-}
-
-void init_stack_info() {
- vm_thread_t vm_thread = jthread_self_vm_thread_unsafe();
-
- // find stack parametrs
- char* stack_addr = (char *)find_stack_addr();
- vm_thread->stack_addr = stack_addr;
- unsigned int stack_size = hythread_get_thread_stacksize(hythread_self());
-
- assert(stack_size > 0);
-
- vm_thread->stack_size = stack_size;
-
-
- common_guard_stack_size = find_guard_stack_size();
- common_guard_page_size = find_guard_page_size();
-
- // stack should be mapped so it's result of future mapping
- char* res;
-
-
- // begin of the stack can be protected by OS, but this part already mapped
- // found address of current stack page
- char* current_page_addr =
- (char*)(((size_t)&res) & (~(common_guard_page_size-1)));
-
- // leave place for mmap work
- char* mapping_page_addr = current_page_addr - common_guard_page_size;
-
- // makes sure that stack allocated till mapping_page_addr
- stack_holder(mapping_page_addr);
-
- // found size of the stack area which should be maped
- size_t stack_mapping_size = (size_t)mapping_page_addr
- - (size_t)stack_addr + stack_size;
-
- // maps unmapped part of the stack
- res = (char*) mmap(stack_addr - stack_size,
- stack_mapping_size,
- PROT_READ | PROT_WRITE,
- MAP_FIXED | MAP_PRIVATE |
-#if defined(FREEBSD)
- MAP_ANON | MAP_STACK,
-#else
- MAP_ANONYMOUS | MAP_GROWSDOWN,
-#endif
- -1,
- 0);
- // stack should be mapped, checks result
- assert(res == (stack_addr - stack_size));
-
- // set guard page
- set_guard_stack();
-}
-
-size_t get_mem_protect_stack_size() {
- return 0x0100;
-}
-
-size_t get_restore_stack_size() {
- return get_mem_protect_stack_size() + 0x0100;
-}
-
-bool set_guard_stack() {
- int err;
- char* stack_addr = (char*) get_stack_addr();
- size_t stack_size = get_stack_size();
- size_t guard_stack_size = get_guard_stack_size();
- size_t guard_page_size = get_guard_page_size();
-
- if (((size_t)(&stack_addr) - get_mem_protect_stack_size())
- < ((size_t)((char*)stack_addr - stack_size
- + guard_stack_size + 2 * guard_page_size))) {
- return false;
- }
-
- err = mprotect(stack_addr - stack_size + guard_page_size +
- guard_stack_size, guard_page_size, PROT_NONE );
-
- assert(!err);
-
- // sets alternative, guard stack
- stack_t sigalt;
- sigalt.ss_sp = stack_addr - stack_size + guard_page_size;
-#if defined(FREEBSD)
- sigalt.ss_flags = 0;
-#else
- sigalt.ss_flags = SS_ONSTACK;
-#endif
- sigalt.ss_size = guard_stack_size;
- err = sigaltstack (&sigalt, NULL);
-
- assert(!err);
-
- // notify that stack is OK and there are no needs to restore it
- jthread_self_vm_thread_unsafe()->restore_guard_page = false;
-
- return true;
-}
-
-size_t get_available_stack_size() {
- char* stack_addr = (char*) get_stack_addr();
- size_t used_stack_size = stack_addr - ((char*)&stack_addr);
- int available_stack_size;
-
- if (!(p_TLS_vmthread->restore_guard_page)) {
- available_stack_size = get_stack_size() - used_stack_size
- - 2 * get_guard_page_size() - get_guard_stack_size();
- } else {
- available_stack_size = get_stack_size() - used_stack_size - get_guard_page_size();
- }
-
- if (available_stack_size > 0) {
- return (size_t) available_stack_size;
- } else {
- return 0;
- }
-}
-size_t get_default_stack_size() {
- size_t default_stack_size = get_stack_size();
- return default_stack_size;
-}
-bool check_available_stack_size(size_t required_size) {
- size_t available_stack_size = get_available_stack_size();
-
- if (available_stack_size < required_size) {
- if (available_stack_size < get_guard_stack_size()) {
- remove_guard_stack(p_TLS_vmthread);
- }
- Global_Env *env = VM_Global_State::loader_env;
- exn_raise_by_class(env->java_lang_StackOverflowError_Class);
- return false;
- } else {
- return true;
- }
-}
-
-bool check_stack_size_enough_for_exception_catch(void* sp) {
- char* stack_adrr = (char*) get_stack_addr();
- size_t used_stack_size = ((size_t)stack_adrr) - ((size_t)sp);
- size_t available_stack_size =
- get_stack_size() - used_stack_size
- - 2 * get_guard_page_size() - get_guard_stack_size();
- return get_restore_stack_size() < available_stack_size;
-}
-
-void remove_guard_stack() {
- vm_thread_t vm_thread = jthread_self_vm_thread_unsafe();
- assert(vm_thread);
- remove_guard_stack(vm_thread);
-}
-
-void remove_guard_stack(vm_thread_t vm_thread) {
- int err;
- char* stack_addr = (char*) get_stack_addr();
- size_t stack_size = get_stack_size();
- size_t guard_stack_size = get_guard_stack_size();
- size_t guard_page_size = get_guard_page_size();
-
-
- err = mprotect(stack_addr - stack_size + guard_page_size +
- guard_stack_size, guard_page_size, PROT_READ | PROT_WRITE);
-
-
- stack_t sigalt;
- sigalt.ss_sp = stack_addr - stack_size + guard_page_size;
- sigalt.ss_flags = SS_DISABLE;
- sigalt.ss_size = guard_stack_size;
-
- err = sigaltstack (&sigalt, NULL);
-
- vm_thread->restore_guard_page = true;
-}
-
-bool check_stack_overflow(siginfo_t *info, ucontext_t *uc) {
- char* stack_addr = (char*) get_stack_addr();
- size_t stack_size = get_stack_size();
- size_t guard_stack_size = get_guard_stack_size();
- size_t guard_page_size = get_guard_page_size();
-
- char* guard_page_begin = stack_addr - stack_size + guard_page_size + guard_stack_size;
- char* guard_page_end = guard_page_begin + guard_page_size;
-
- // FIXME: Workaround for main thread
- guard_page_end += guard_page_size;
-
- char* fault_addr = (char*)(info->si_addr);
- //char* esp_value = (char*)(uc->uc_mcontext.gregs[REG_ESP]);
-
- return((guard_page_begin <= fault_addr) && (fault_addr < guard_page_end));
-}
-
-/*
- * We find the true signal stack frame set-up by kernel,which is located
- * by locate_sigcontext() below; then change its content according to
- * exception handling semantics, so that when the signal handler is
- * returned, application can continue its execution in Java exception handler.
- */
-
-void stack_overflow_handler(int signum, siginfo_t* UNREF info, void* context)
-{
- ucontext_t *uc = (ucontext_t *)context;
- Global_Env *env = VM_Global_State::loader_env;
-
- vm_thread_t vm_thread = p_TLS_vmthread;
- remove_guard_stack(vm_thread);
- vm_thread->restore_guard_page = true;
-
- if (java_throw_from_sigcontext(
- uc, env->java_lang_StackOverflowError_Class)) {
- return;
- } else {
- if (is_unwindable()) {
- if (hythread_is_suspend_enabled()) {
- tmn_suspend_disable();
- }
- throw_from_sigcontext(
- uc, env->java_lang_StackOverflowError_Class);
- } else {
- exn_raise_by_class(env->java_lang_StackOverflowError_Class);
- }
- }
-}
-
-void null_java_reference_handler(int signum, siginfo_t* UNREF info, void* context)
-{
- ucontext_t *uc = (ucontext_t *)context;
- VM_thread *vm_thread = p_TLS_vmthread;
- Registers regs;
- UCONTEXT_TO_REGS(®s, uc);
-
- if (vm_thread && vm_thread->jvmti_thread.violation_flag)
- {
- vm_thread->jvmti_thread.violation_flag = 0;
- regs.set_ip(vm_thread->jvmti_thread.violation_restart_address);
- linux_regs_to_ucontext(uc, ®s);
- return;
- }
-
- Global_Env *env = VM_Global_State::loader_env;
-
- TRACE2("signals", "NPE or SOE detected at " << (void*)REGISTER_EIP);
-
- if (check_stack_overflow(info, uc)) {
- stack_overflow_handler(signum, info, context);
- return;
- }
-
- if (!interpreter_enabled()) {
- if (java_throw_from_sigcontext(
- uc, env->java_lang_NullPointerException_Class)) {
- return;
- }
- }
- fprintf(stderr, "SIGSEGV in VM code.\n");
-
- // setup default handler
- signal(signum, SIG_DFL);
-
- if (!is_gdb_crash_handler_enabled() ||
- !gdb_crash_handler())
- {
- // print stack trace
- st_print_stack(®s);
- }
-}
-
-
-void null_java_divide_by_zero_handler(int signum, siginfo_t* UNREF info, void* context)
-{
- ucontext_t *uc = (ucontext_t *)context;
- Global_Env *env = VM_Global_State::loader_env;
-
- TRACE2("signals",
- "ArithmeticException detected at " << (void*)REGISTER_EIP);
-
- if (!interpreter_enabled()) {
- if (java_throw_from_sigcontext(
- uc, env->java_lang_ArithmeticException_Class)) {
- return;
- }
- }
-
- fprintf(stderr, "SIGFPE in VM code.\n");
- Registers regs;
- UCONTEXT_TO_REGS(®s, uc);
-
- // setup default handler
- signal(signum, SIG_DFL);
-
- if (!is_gdb_crash_handler_enabled() ||
- !gdb_crash_handler())
- {
- // print stack trace
- st_print_stack(®s);
- }
-}
-
-void jvmti_jit_breakpoint_handler(int signum, siginfo_t* UNREF info, void* context)
-{
- ucontext_t *uc = (ucontext_t *)context;
- Registers regs;
-
- UCONTEXT_TO_REGS(®s, uc);
- TRACE2("signals", "JVMTI breakpoint detected at " <<
- (void *)regs.eip);
-
- bool handled = jvmti_jit_breakpoint_handler(®s);
- if (handled)
- {
- REGS_TO_UCONTEXT(uc, ®s);
- return;
- }
-
- fprintf(stderr, "SIGTRAP in VM code.\n");
- UCONTEXT_TO_REGS(®s, uc);
-
- // setup default handler
- signal(signum, SIG_DFL);
-
- if (!is_gdb_crash_handler_enabled() ||
- !gdb_crash_handler())
- {
- // print stack trace
- st_print_stack(®s);
- }
-}
-
-/**
- * Print out the call stack of the aborted thread.
- * @note call stacks may be used for debugging
- */
-void abort_handler (int signum, siginfo_t* UNREF info, void* context) {
- fprintf(stderr, "SIGABRT in VM code.\n");
- Registers regs;
- ucontext_t *uc = (ucontext_t *)context;
- UCONTEXT_TO_REGS(®s, uc);
-
- // setup default handler
- signal(signum, SIG_DFL);
-
- if (!is_gdb_crash_handler_enabled() ||
- !gdb_crash_handler())
- {
- // print stack trace
- st_print_stack(®s);
- }
-}
-
-void general_signal_handler(int signum, siginfo_t* info, void* context)
-{
- bool replaced = false;
- ucontext_t* uc = (ucontext_t *)context;
- uint32 saved_eip = (uint32)REGISTER_EIP;
- uint32 new_eip = saved_eip;
- VM_thread* vm_thread = p_TLS_vmthread;
- bool violation =
- (signum == SIGSEGV) && vm_thread && vm_thread->jvmti_thread.violation_flag;
-
- // If exception is occured in processor instruction previously
- // instrumented by breakpoint, the actual exception address will reside
- // in jvmti_jit_breakpoints_handling_buffer
- // We should replace exception address with saved address of instruction
- uint32 break_buf =
- (uint32)vm_thread->jvmti_thread.jvmti_jit_breakpoints_handling_buffer;
- if (saved_eip >= break_buf &&
- saved_eip < break_buf + TM_JVMTI_MAX_BUFFER_SIZE)
- {
- // Breakpoints should not occur in breakpoint buffer
- assert(signum != SIGTRAP);
-
- replaced = true;
- new_eip = (uint32)vm_get_ip_from_regs(vm_thread);
- REGISTER_EIP = new_eip;
- }
-
- // Pass exception to NCAI exception handler
- bool is_handled = 0;
- bool is_internal = (signum == SIGTRAP) || violation;
- ncai_process_signal_event((NativeCodePtr)uc->uc_mcontext.gregs[REG_EIP],
- (jint)signum, is_internal, &is_handled);
- if (is_handled)
- return;
-
- switch (signum)
- {
- case SIGTRAP:
- jvmti_jit_breakpoint_handler(signum, info, context);
- break;
- case SIGSEGV:
- null_java_reference_handler(signum, info, context);
- break;
- case SIGFPE:
- null_java_divide_by_zero_handler(signum, info, context);
- break;
- case SIGABRT:
- abort_handler(signum, info, context);
- break;
- case SIGINT:
- vm_interrupt_handler(signum);
- break;
- case SIGQUIT:
- vm_dump_handler(signum);
- break;
- default:
- // Unknown signal
- assert(0);
- break;
- }
-
- // If EIP was not changed in specific handler to start another handler,
- // we should restore original EIP, if it's nesessary
- if (replaced &&
- (uint32)REGISTER_EIP == new_eip)
- {
- REGISTER_EIP = saved_eip;
- }
-}
-
-void initialize_signals()
-{
- struct sigaction sa;
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &general_signal_handler;
- sigaction(SIGTRAP, &sa, NULL);
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO | SA_ONSTACK;;
- sa.sa_sigaction = &general_signal_handler;
- sigaction(SIGSEGV, &sa, NULL);
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &general_signal_handler;
- sigaction(SIGFPE, &sa, NULL);
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &general_signal_handler;
- sigaction(SIGINT, &sa, NULL);
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &general_signal_handler;
- sigaction(SIGQUIT, &sa, NULL);
-
- /* install abort_handler to print out call stack on assertion failures */
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &general_signal_handler;
- sigaction( SIGABRT, &sa, NULL);
- /* abort_handler installed */
-
- // Prepare gdb crash handler
- init_gdb_crash_handler();
-
-} //initialize_signals
-
-void shutdown_signals() {
- //FIXME: should be defined in future
-} //shutdown_signals
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ipf.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ipf.cpp?rev=610460&r1=610459&r2=610460&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ipf.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ipf.cpp Wed Jan 9 09:07:05 2008
@@ -75,7 +75,7 @@
#include <semaphore.h>
-void linux_ucontext_to_regs(Registers* regs, ucontext_t* uc)
+void ucontext_to_regs(Registers* regs, ucontext_t* uc)
{
memcpy(regs->gr, uc->uc_mcontext.sc_gr, sizeof(regs->gr));
memcpy(regs->fp, uc->uc_mcontext.sc_fr, sizeof(regs->fp));
@@ -88,7 +88,7 @@
regs->ip = uc->uc_mcontext.sc_ip;
}
-void linux_regs_to_ucontext(ucontext_t* uc, Registers* regs)
+void regs_to_ucontext(ucontext_t* uc, Registers* regs)
{
memcpy(uc->uc_mcontext.sc_gr, regs->gr, sizeof(regs->gr));
memcpy(uc->uc_mcontext.sc_fr, regs->fp, sizeof(regs->fp));
@@ -129,7 +129,7 @@
fprintf(stderr, "SIGABRT in VM code.\n");
Registers regs;
ucontext_t *uc = (ucontext_t *)context;
- linux_ucontext_to_regs(®s, uc);
+ ucontext_to_regs(®s, uc);
// setup default handler
signal(signum, SIG_DFL);
@@ -169,7 +169,7 @@
fprintf(stderr, "SIGFPE in VM code.\n");
Registers regs;
- linux_ucontext_to_regs(®s, uc);
+ ucontext_to_regs(®s, uc);
// setup default handler
signal(signum, SIG_DFL);
@@ -453,7 +453,7 @@
}
fprintf(stderr, "SIGSEGV in VM code.\n");
Registers regs;
- linux_ucontext_to_regs(®s, uc);
+ ucontext_to_regs(®s, uc);
// setup default handler
signal(signum, SIG_DFL);