52 #include "runtime/vm_version.hpp" |
52 #include "runtime/vm_version.hpp" |
53 #include "services/heapDumper.hpp" |
53 #include "services/heapDumper.hpp" |
54 #include "utilities/defaultStream.hpp" |
54 #include "utilities/defaultStream.hpp" |
55 #include "utilities/events.hpp" |
55 #include "utilities/events.hpp" |
56 #include "utilities/formatBuffer.hpp" |
56 #include "utilities/formatBuffer.hpp" |
|
57 #include "utilities/globalDefinitions.hpp" |
57 #include "utilities/macros.hpp" |
58 #include "utilities/macros.hpp" |
58 #include "utilities/vmError.hpp" |
59 #include "utilities/vmError.hpp" |
59 |
60 |
60 #include <stdio.h> |
61 #include <stdio.h> |
|
62 |
|
63 // Support for showing register content on asserts/guarantees. |
|
64 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT |
|
65 static char g_dummy; |
|
66 char* g_assert_poison = &g_dummy; |
|
67 static intx g_asserting_thread = 0; |
|
68 static void* g_assertion_context = NULL; |
|
69 #endif // CAN_SHOW_REGISTERS_ON_ASSERT |
61 |
70 |
62 #ifndef ASSERT |
71 #ifndef ASSERT |
63 # ifdef _DEBUG |
72 # ifdef _DEBUG |
64 // NOTE: don't turn the lines below into a comment -- if you're getting |
73 // NOTE: don't turn the lines below into a comment -- if you're getting |
65 // a compile error here, change the settings to define ASSERT |
74 // a compile error here, change the settings to define ASSERT |
210 void report_vm_error(const char* file, int line, const char* error_msg, const char* detail_fmt, ...) |
219 void report_vm_error(const char* file, int line, const char* error_msg, const char* detail_fmt, ...) |
211 { |
220 { |
212 if (Debugging || error_is_suppressed(file, line)) return; |
221 if (Debugging || error_is_suppressed(file, line)) return; |
213 va_list detail_args; |
222 va_list detail_args; |
214 va_start(detail_args, detail_fmt); |
223 va_start(detail_args, detail_fmt); |
215 VMError::report_and_die(Thread::current_or_null(), file, line, error_msg, detail_fmt, detail_args); |
224 void* context = NULL; |
|
225 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT |
|
226 if (g_assertion_context != NULL && os::current_thread_id() == g_asserting_thread) { |
|
227 context = g_assertion_context; |
|
228 } |
|
229 #endif // CAN_SHOW_REGISTERS_ON_ASSERT |
|
230 VMError::report_and_die(Thread::current_or_null(), context, file, line, error_msg, detail_fmt, detail_args); |
216 va_end(detail_args); |
231 va_end(detail_args); |
217 } |
232 } |
218 |
233 |
219 void report_vm_status_error(const char* file, int line, const char* error_msg, |
234 void report_vm_status_error(const char* file, int line, const char* error_msg, |
220 int status, const char* detail) { |
235 int status, const char* detail) { |
224 void report_fatal(const char* file, int line, const char* detail_fmt, ...) |
239 void report_fatal(const char* file, int line, const char* detail_fmt, ...) |
225 { |
240 { |
226 if (Debugging || error_is_suppressed(file, line)) return; |
241 if (Debugging || error_is_suppressed(file, line)) return; |
227 va_list detail_args; |
242 va_list detail_args; |
228 va_start(detail_args, detail_fmt); |
243 va_start(detail_args, detail_fmt); |
229 VMError::report_and_die(Thread::current_or_null(), file, line, "fatal error", detail_fmt, detail_args); |
244 void* context = NULL; |
|
245 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT |
|
246 if (g_assertion_context != NULL && os::current_thread_id() == g_asserting_thread) { |
|
247 context = g_assertion_context; |
|
248 } |
|
249 #endif // CAN_SHOW_REGISTERS_ON_ASSERT |
|
250 VMError::report_and_die(Thread::current_or_null(), context, file, line, "fatal error", detail_fmt, detail_args); |
230 va_end(detail_args); |
251 va_end(detail_args); |
231 } |
252 } |
232 |
253 |
233 void report_vm_out_of_memory(const char* file, int line, size_t size, |
254 void report_vm_out_of_memory(const char* file, int line, size_t size, |
234 VMErrorType vm_err_type, const char* detail_fmt, ...) { |
255 VMErrorType vm_err_type, const char* detail_fmt, ...) { |
674 STATIC_ASSERT(0 == 0); |
695 STATIC_ASSERT(0 == 0); |
675 STATIC_ASSERT(1 == 1); |
696 STATIC_ASSERT(1 == 1); |
676 }; |
697 }; |
677 |
698 |
678 #endif // !PRODUCT |
699 #endif // !PRODUCT |
|
700 |
|
701 // Support for showing register content on asserts/guarantees. |
|
702 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT |
|
703 |
|
704 static ucontext_t g_stored_assertion_context; |
|
705 |
|
706 void initialize_assert_poison() { |
|
707 char* page = os::reserve_memory(os::vm_page_size()); |
|
708 if (page) { |
|
709 if (os::commit_memory(page, os::vm_page_size(), false) && |
|
710 os::protect_memory(page, os::vm_page_size(), os::MEM_PROT_NONE)) { |
|
711 g_assert_poison = page; |
|
712 } |
|
713 } |
|
714 } |
|
715 |
|
716 static bool store_context(const void* context) { |
|
717 if (memcpy(&g_stored_assertion_context, context, sizeof(ucontext_t)) == false) { |
|
718 return false; |
|
719 } |
|
720 #if defined(__linux) && defined(PPC64) |
|
721 // on Linux ppc64, ucontext_t contains pointers into itself which have to be patched up |
|
722 // after copying the context (see comment in sys/ucontext.h): |
|
723 *((void**) &g_stored_assertion_context.uc_mcontext.regs) = &(g_stored_assertion_context.uc_mcontext.gp_regs); |
|
724 #endif |
|
725 return true; |
|
726 } |
|
727 |
|
728 bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address) { |
|
729 if (faulting_address == g_assert_poison) { |
|
730 // Disarm poison page. |
|
731 os::protect_memory((char*)g_assert_poison, os::vm_page_size(), os::MEM_PROT_RWX); |
|
732 // Store Context away. |
|
733 if (ucVoid) { |
|
734 const jlong my_tid = os::current_thread_id(); |
|
735 if (Atomic::cmpxchg(my_tid, &g_asserting_thread, (intx)0) == 0) { |
|
736 if (store_context(ucVoid)) { |
|
737 g_assertion_context = &g_stored_assertion_context; |
|
738 } |
|
739 } |
|
740 } |
|
741 return true; |
|
742 } |
|
743 return false; |
|
744 } |
|
745 #endif // CAN_SHOW_REGISTERS_ON_ASSERT |
|
746 |