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 2007/02/27 13:36:49 UTC
svn commit: r512236 - in
/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win:
em64t/exception_handlers.asm ia32_em64t/
ia32_em64t/nt_exception_filter_common.cpp
Author: gshimansky
Date: Tue Feb 27 04:36:48 2007
New Revision: 512236
URL: http://svn.apache.org/viewvc?view=rev&rev=512236
Log:
Additional files needed for HARMONY-3233
Added:
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/em64t/exception_handlers.asm (with props)
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32_em64t/
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32_em64t/nt_exception_filter_common.cpp (with props)
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/em64t/exception_handlers.asm
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/em64t/exception_handlers.asm?view=auto&rev=512236
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/em64t/exception_handlers.asm (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/em64t/exception_handlers.asm Tue Feb 27 04:36:48 2007
@@ -0,0 +1,97 @@
+PUBLIC vectored_exception_handler
+EXTRN vectored_exception_handler_internal:PROC
+
+PUBLIC asm_c_exception_handler
+EXTRN c_exception_handler:PROC
+
+PUBLIC asm_exception_catch_callback
+EXTRN exception_catch_callback_wrapper:PROC
+
+PUBLIC asm_jvmti_exception_catch_callback
+EXTRN jvmti_exception_catch_callback_wrapper:PROC
+
+_TEXT SEGMENT
+
+vectored_exception_handler PROC
+
+; LONG NTAPI vectored_exception_handler(LPEXCEPTION_POINTERS nt_exception)
+; Args:
+; rcx - nt_exception
+; rdx - none
+; r8 - none
+; r9 - none
+
+ pushfq
+ cld
+ sub rsp, 32 ; allocate stack for 4 registers
+ call vectored_exception_handler_internal
+ add esp, 32
+ popfq
+ ret
+
+vectored_exception_handler ENDP
+
+
+asm_c_exception_handler PROC
+
+; void __cdecl asm_c_exception_handler(Class *exn_class, bool in_java)
+; void __cdecl c_exception_handler(Class* exn_class, bool in_java)
+; Args:
+; rcx - nt_exception
+; rdx - in_java (actually in dl)
+; r8 - none
+; r9 - none
+
+ pushfq
+ cld
+ sub rsp, 32 ; allocate stack for 4 registers
+ call c_exception_handler
+ add esp, 32
+ popfq
+ ret
+
+asm_c_exception_handler ENDP
+
+
+asm_exception_catch_callback PROC
+
+; void __cdecl exception_catch_callback_wrapper()
+; Args:
+; rcx - none
+; rdx - none
+; r8 - none
+; r9 - none
+
+ pushfq
+ cld
+ sub rsp, 32 ; allocate stack for 4 registers
+ call exception_catch_callback_wrapper
+ add esp, 32
+ popfq
+ ret
+
+asm_exception_catch_callback ENDP
+
+
+asm_jvmti_exception_catch_callback PROC
+
+; void __cdecl jvmti_exception_catch_callback_wrapper()
+; Args:
+; rcx - none
+; rdx - none
+; r8 - none
+; r9 - none
+
+ pushfq
+ cld
+ sub rsp, 32 ; allocate stack for 4 registers
+ call jvmti_exception_catch_callback_wrapper
+ add esp, 32
+ popfq
+ ret
+
+asm_jvmti_exception_catch_callback ENDP
+
+_TEXT ENDS
+
+END
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/em64t/exception_handlers.asm
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32_em64t/nt_exception_filter_common.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32_em64t/nt_exception_filter_common.cpp?view=auto&rev=512236
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32_em64t/nt_exception_filter_common.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32_em64t/nt_exception_filter_common.cpp Tue Feb 27 04:36:48 2007
@@ -0,0 +1,378 @@
+/*
+ * 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.
+ */
+
+
+#include "clog.h"
+#include "method_lookup.h"
+#include "Environment.h"
+#include "exceptions.h"
+#include "exceptions_jit.h"
+#include "interpreter_exports.h"
+#include "stack_iterator.h"
+#include "stack_dump.h"
+#include "jvmti_break_intf.h"
+#include "m2n.h"
+
+// Windows specific
+#include <string>
+#include <excpt.h>
+
+#include "exception_filter.h"
+
+
+#if INSTRUMENTATION_BYTE == INSTRUMENTATION_BYTE_INT3
+#define JVMTI_EXCEPTION_STATUS STATUS_BREAKPOINT
+#elif INSTRUMENTATION_BYTE == INSTRUMENTATION_BYTE_HLT || INSTRUMENTATION_BYTE == INSTRUMENTATION_BYTE_CLI
+#define JVMTI_EXCEPTION_STATUS STATUS_PRIVILEGED_INSTRUCTION
+#else
+#error Unknown value of INSTRUMENTATION_BYTE
+#endif
+
+static void print_callstack(LPEXCEPTION_POINTERS nt_exception) {
+ PCONTEXT context = nt_exception->ContextRecord;
+ Registers regs;
+ nt_to_vm_context(context, ®s);
+ st_print_stack(®s);
+ fflush(stderr);
+}
+
+/*
+ * Information about stack
+ */
+inline void* find_stack_addr() {
+ void* stack_addr;
+ size_t reg_size;
+ MEMORY_BASIC_INFORMATION memory_information;
+
+ VirtualQuery(&memory_information, &memory_information, sizeof(memory_information));
+ reg_size = memory_information.RegionSize;
+ stack_addr =((char*) memory_information.BaseAddress) + reg_size;
+
+ return stack_addr;
+}
+
+inline size_t find_stack_size() {
+ void* stack_addr;
+ size_t stack_size;
+ size_t reg_size;
+ MEMORY_BASIC_INFORMATION memory_information;
+
+ VirtualQuery(&memory_information, &memory_information, sizeof(memory_information));
+ reg_size = memory_information.RegionSize;
+ stack_addr = ((char*) memory_information.BaseAddress) + reg_size;
+ stack_size = ((char*) stack_addr) - ((char*) memory_information.AllocationBase);
+
+ return stack_size;
+}
+
+inline size_t find_guard_page_size() {
+ size_t guard_size;
+ SYSTEM_INFO system_info;
+
+ GetSystemInfo(&system_info);
+ guard_size = system_info.dwPageSize;
+
+ return guard_size;
+}
+
+inline size_t find_guard_stack_size() {
+ // guaerded stack size on windows can be equals one page size only :(
+ return find_guard_page_size();
+}
+
+static size_t common_stack_size;
+static size_t common_guard_stack_size;
+static size_t common_guard_page_size;
+
+inline void* get_stack_addr() {
+ return p_TLS_vmthread->stack_addr;
+}
+
+inline size_t get_stack_size() {
+ return common_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() {
+ p_TLS_vmthread->stack_addr = find_stack_addr();
+ common_stack_size = find_stack_size();
+ common_guard_stack_size = find_guard_stack_size();
+ common_guard_page_size =find_guard_page_size();
+}
+
+void set_guard_stack() {
+ void* stack_addr = get_stack_addr();
+ size_t stack_size = get_stack_size();
+ size_t page_size = get_guard_page_size();
+
+ if (!VirtualFree((char*)stack_addr - stack_size + page_size,
+ page_size, MEM_DECOMMIT)) {
+ // should be successful always
+ assert(0);
+ }
+
+ DWORD oldProtect;
+
+ if (!VirtualProtect((char*)stack_addr - stack_size + page_size + page_size,
+ page_size, PAGE_GUARD | PAGE_READWRITE, &oldProtect)) {
+ // should be successful always
+ assert(0);
+ }
+
+ p_TLS_vmthread->restore_guard_page = false;
+}
+
+size_t get_available_stack_size() {
+ char* stack_adrr = (char*) get_stack_addr();
+ size_t used_stack_size = ((size_t)stack_adrr) - ((size_t)(&stack_adrr));
+ size_t available_stack_size =
+ get_stack_size() - used_stack_size
+ - get_guard_page_size() - get_guard_stack_size();
+ return available_stack_size;
+}
+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) {
+ if (get_available_stack_size() < required_size) {
+ Global_Env *env = VM_Global_State::loader_env;
+ exn_raise_by_class(env->java_lang_StackOverflowError_Class);
+ return false;
+ } else {
+ return true;
+ }
+}
+
+// exception catch callback to restore stack after Stack Overflow Error
+void __cdecl exception_catch_callback_wrapper(){
+ exception_catch_callback();
+}
+
+// exception catch support for JVMTI
+void __cdecl jvmti_exception_catch_callback_wrapper(){
+ Registers regs = p_TLS_vmthread->regs;
+ jvmti_exception_catch_callback(®s);
+}
+
+LONG NTAPI vectored_exception_handler_internal(LPEXCEPTION_POINTERS nt_exception)
+{
+ DWORD code = nt_exception->ExceptionRecord->ExceptionCode;
+ PCONTEXT context = nt_exception->ContextRecord;
+ Registers regs;
+ bool flag_replaced = false;
+
+ // Convert NT context to Registers
+ nt_to_vm_context(context, ®s);
+ POINTER_SIZE_INT saved_eip = (POINTER_SIZE_INT)regs.get_ip();
+
+ // 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_jit_breakpoints_handling_buffer;
+ if (saved_eip >= break_buf &&
+ saved_eip < break_buf + 50)
+ {
+ flag_replaced = true;
+ regs.set_ip(p_TLS_vmthread->jvmti_saved_exception_registers.get_ip());
+ vm_to_nt_context(®s, context);
+ }
+
+ TRACE2("signals", ("VEH received an exception: code = %x, ip = %p, sp = %p",
+ nt_exception->ExceptionRecord->ExceptionCode, regs.get_ip(), regs_get_sp(®s)));
+
+ // the possible reasons for hardware exception are
+ // - segfault or division by zero in java code
+ // => NullPointerException or ArithmeticException
+ //
+ // - breakpoint or privileged instruction in java code
+ // => send jvmti breakpoint event
+ //
+ // - stack overflow, either in java or in native
+ // => StackOverflowError
+ //
+ // - other (internal VM error or debugger breakpoint)
+ // => delegate to default handler
+
+ bool in_java = (vm_identify_eip(regs.get_ip()) == VM_TYPE_JAVA);
+
+ // delegate "other" cases to default handler
+ if (!in_java && code != STATUS_STACK_OVERFLOW)
+ {
+ regs.set_ip((void*)saved_eip);
+ vm_to_nt_context(®s, context);
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ // if HWE occured in java code, suspension should also have been disabled
+ assert(!in_java || !hythread_is_suspend_enabled());
+
+ Global_Env *env = VM_Global_State::loader_env;
+ // the actual exception object will be created lazily,
+ // we determine only exception class here
+ Class *exn_class = 0;
+
+ switch(nt_exception->ExceptionRecord->ExceptionCode)
+ {
+ case STATUS_STACK_OVERFLOW:
+ {
+ TRACE2("signals",
+ ("StackOverflowError detected at ip = %p, esp = %p",
+ regs.get_ip(), regs_get_sp(®s)));
+
+ p_TLS_vmthread->restore_guard_page = true;
+ exn_class = env->java_lang_StackOverflowError_Class;
+ if (in_java) {
+ // stack overflow occured in java code:
+ // nothing special to do
+ } else if (is_unwindable()) {
+ // stack overflow occured in native code that can be unwound
+ // safely.
+ // Throwing exception requires suspend disabled status
+ if (hythread_is_suspend_enabled())
+ hythread_suspend_disable();
+ } else {
+ // stack overflow occured in native code that
+ // cannot be unwound.
+ // Mark raised exception in TLS and resume execution
+ exn_raise_by_class(env->java_lang_StackOverflowError_Class);
+ regs.set_ip((void*)saved_eip);
+ vm_to_nt_context(®s, context);
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ }
+ break;
+ case STATUS_ACCESS_VIOLATION:
+ {
+ TRACE2("signals",
+ ("NullPointerException detected at ip = %p", regs.get_ip()));
+ exn_class = env->java_lang_NullPointerException_Class;
+ }
+ break;
+
+ case STATUS_INTEGER_DIVIDE_BY_ZERO:
+ {
+ TRACE2("signals",
+ ("ArithmeticException detected at ip = %p", regs.get_ip()));
+ exn_class = env->java_lang_ArithmeticException_Class;
+ }
+ break;
+ case JVMTI_EXCEPTION_STATUS:
+ // JVMTI breakpoint in JITted code
+ {
+ // Breakpoints should not occur in breakpoint buffer
+ assert(!flag_replaced);
+
+ TRACE2("signals",
+ ("JVMTI breakpoint detected at ip = %p", regs.get_ip()));
+ bool handled = jvmti_jit_breakpoint_handler(®s);
+ if (handled)
+ {
+ vm_to_nt_context(®s, context);
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ else
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ default:
+ // unexpected hardware exception occured in java code
+ print_callstack(nt_exception);
+ regs.set_ip((void*)saved_eip);
+ vm_to_nt_context(®s, context);
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ // we must not call potentially blocking or suspendable code
+ // (i.e. java code of exception constructor) from exception
+ // handler, because this handler may hold a system-wide lock,
+ // and this may result in a deadlock.
+
+ // it was reported that exception handler grabs a system
+ // lock on Windows XPsp2 and 2003sp0, but not on a 2003sp1
+
+ // save register context of hardware exception site
+ // into thread-local registers snapshot
+ assert(p_TLS_vmthread);
+ p_TLS_vmthread->regs = regs;
+
+ // __cdecl <=> push parameters in the reversed order
+ // push in_java argument onto stack
+ regs_push_param_onto_stack(®s, in_java);
+ // push the exn_class argument onto stack
+ assert(exn_class);
+ regs_push_param_onto_stack(®s, (POINTER_SIZE_INT)exn_class);
+ // imitate return IP on stack
+ regs_push_param_onto_stack(®s, 0);
+
+ // set up the real exception handler address
+ regs.set_ip(asm_c_exception_handler);
+ // Store changes into NT context
+ vm_to_nt_context(®s, context);
+
+ // exit NT exception handler and transfer
+ // control to VM exception handler
+ return EXCEPTION_CONTINUE_EXECUTION;
+}
+
+void __cdecl c_exception_handler(Class* exn_class, bool in_java)
+{
+ // 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 = p_TLS_vmthread->regs;
+
+ M2nFrame* prev_m2n = m2n_get_last_frame();
+ M2nFrame* m2n = NULL;
+ if (in_java)
+ m2n = m2n_push_suspended_frame(®s);
+
+ TRACE2("signals", ("should throw exception %p at IP=%p, SP=%p",
+ exn_class, regs.get_ip(), regs_get_sp(®s)));
+ exn_athrow_regs(®s, exn_class, false);
+
+ if (ti->get_global_capability(DebugUtilsTI::TI_GC_ENABLE_EXCEPTION_EVENT)) {
+ // Set return address to current IP
+ regs_push_param_onto_stack(®s, (POINTER_SIZE_INT)regs.get_ip());
+ // Set IP to callback address
+ regs.set_ip(asm_jvmti_exception_catch_callback);
+ } else if (p_TLS_vmthread->restore_guard_page) {
+ // Set return address to current IP
+ regs_push_param_onto_stack(®s, (POINTER_SIZE_INT)regs.get_ip());
+ // Set IP to callback address
+ regs.set_ip(asm_exception_catch_callback);
+ }
+
+ StackIterator *si =
+ si_create_from_registers(®s, false, prev_m2n);
+
+ if (m2n)
+ STD_FREE(m2n);
+
+ p_TLS_vmthread->regs = regs;
+ si_transfer_control(si);
+ assert(!"si_transfer_control should not return");
+}
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32_em64t/nt_exception_filter_common.cpp
------------------------------------------------------------------------------
svn:eol-style = native