|
30 | 30 | #include "utilities/globalDefinitions.hpp" |
31 | 31 | #include "runtime/frame.inline.hpp" |
32 | 32 | #include "runtime/interfaceSupport.inline.hpp" |
| 33 | +#include "runtime/sharedRuntime.hpp" |
33 | 34 | #include "services/memTracker.hpp" |
34 | 35 | #include "runtime/atomic.hpp" |
35 | 36 | #include "runtime/java.hpp" |
@@ -907,6 +908,119 @@ size_t os::Posix::get_initial_stack_size(ThreadType thr_type, size_t req_stack_s |
907 | 908 | return stack_size; |
908 | 909 | } |
909 | 910 |
|
| 911 | +#ifndef ZERO |
| 912 | +#ifndef ARM |
| 913 | +static bool get_frame_at_stack_banging_point(JavaThread* thread, address pc, const void* ucVoid, frame* fr) { |
| 914 | + if (Interpreter::contains(pc)) { |
| 915 | + // interpreter performs stack banging after the fixed frame header has |
| 916 | + // been generated while the compilers perform it before. To maintain |
| 917 | + // semantic consistency between interpreted and compiled frames, the |
| 918 | + // method returns the Java sender of the current frame. |
| 919 | + *fr = os::fetch_frame_from_context(ucVoid); |
| 920 | + if (!fr->is_first_java_frame()) { |
| 921 | + // get_frame_at_stack_banging_point() is only called when we |
| 922 | + // have well defined stacks so java_sender() calls do not need |
| 923 | + // to assert safe_for_sender() first. |
| 924 | + *fr = fr->java_sender(); |
| 925 | + } |
| 926 | + } else { |
| 927 | + // more complex code with compiled code |
| 928 | + assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above"); |
| 929 | + CodeBlob* cb = CodeCache::find_blob(pc); |
| 930 | + if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) { |
| 931 | + // Not sure where the pc points to, fallback to default |
| 932 | + // stack overflow handling |
| 933 | + return false; |
| 934 | + } else { |
| 935 | + // in compiled code, the stack banging is performed just after the return pc |
| 936 | + // has been pushed on the stack |
| 937 | + *fr = os::fetch_compiled_frame_from_context(ucVoid); |
| 938 | + if (!fr->is_java_frame()) { |
| 939 | + assert(!fr->is_first_frame(), "Safety check"); |
| 940 | + // See java_sender() comment above. |
| 941 | + *fr = fr->java_sender(); |
| 942 | + } |
| 943 | + } |
| 944 | + } |
| 945 | + assert(fr->is_java_frame(), "Safety check"); |
| 946 | + return true; |
| 947 | +} |
| 948 | +#endif // ARM |
| 949 | + |
| 950 | +// This return true if the signal handler should just continue, ie. return after calling this |
| 951 | +bool os::Posix::handle_stack_overflow(JavaThread* thread, address addr, address pc, |
| 952 | + const void* ucVoid, address* stub) { |
| 953 | + // stack overflow |
| 954 | + StackOverflow* overflow_state = thread->stack_overflow_state(); |
| 955 | + if (overflow_state->in_stack_yellow_reserved_zone(addr)) { |
| 956 | + if (thread->thread_state() == _thread_in_Java) { |
| 957 | +#ifndef ARM |
| 958 | + // arm32 doesn't have this |
| 959 | + if (overflow_state->in_stack_reserved_zone(addr)) { |
| 960 | + frame fr; |
| 961 | + if (get_frame_at_stack_banging_point(thread, pc, ucVoid, &fr)) { |
| 962 | + assert(fr.is_java_frame(), "Must be a Java frame"); |
| 963 | + frame activation = |
| 964 | + SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr); |
| 965 | + if (activation.sp() != NULL) { |
| 966 | + overflow_state->disable_stack_reserved_zone(); |
| 967 | + if (activation.is_interpreted_frame()) { |
| 968 | + overflow_state->set_reserved_stack_activation((address)( |
| 969 | + activation.fp() + frame::interpreter_frame_initial_sp_offset)); |
| 970 | + } else { |
| 971 | + overflow_state->set_reserved_stack_activation((address)activation.unextended_sp()); |
| 972 | + } |
| 973 | + return true; // just continue |
| 974 | + } |
| 975 | + } |
| 976 | + } |
| 977 | +#endif // ARM |
| 978 | + // Throw a stack overflow exception. Guard pages will be reenabled |
| 979 | + // while unwinding the stack. |
| 980 | + overflow_state->disable_stack_yellow_reserved_zone(); |
| 981 | + *stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW); |
| 982 | + } else { |
| 983 | + // Thread was in the vm or native code. Return and try to finish. |
| 984 | + overflow_state->disable_stack_yellow_reserved_zone(); |
| 985 | + return true; // just continue |
| 986 | + } |
| 987 | + } else if (overflow_state->in_stack_red_zone(addr)) { |
| 988 | + // Fatal red zone violation. Disable the guard pages and fall through |
| 989 | + // to handle_unexpected_exception way down below. |
| 990 | + overflow_state->disable_stack_red_zone(); |
| 991 | + tty->print_raw_cr("An irrecoverable stack overflow has occurred."); |
| 992 | + |
| 993 | + // This is a likely cause, but hard to verify. Let's just print |
| 994 | + // it as a hint. |
| 995 | + tty->print_raw_cr("Please check if any of your loaded .so files has " |
| 996 | + "enabled executable stack (see man page execstack(8))"); |
| 997 | + |
| 998 | + } else { |
| 999 | +#if !defined(AIX) && !defined(__APPLE__) |
| 1000 | + // bsd and aix don't have this |
| 1001 | + |
| 1002 | + // Accessing stack address below sp may cause SEGV if current |
| 1003 | + // thread has MAP_GROWSDOWN stack. This should only happen when |
| 1004 | + // current thread was created by user code with MAP_GROWSDOWN flag |
| 1005 | + // and then attached to VM. See notes in os_linux.cpp. |
| 1006 | + if (thread->osthread()->expanding_stack() == 0) { |
| 1007 | + thread->osthread()->set_expanding_stack(); |
| 1008 | + if (os::Linux::manually_expand_stack(thread, addr)) { |
| 1009 | + thread->osthread()->clear_expanding_stack(); |
| 1010 | + return true; // just continue |
| 1011 | + } |
| 1012 | + thread->osthread()->clear_expanding_stack(); |
| 1013 | + } else { |
| 1014 | + fatal("recursive segv. expanding stack."); |
| 1015 | + } |
| 1016 | +#else |
| 1017 | + tty->print_raw_cr("SIGSEGV happened inside stack but outside yellow and red zone."); |
| 1018 | +#endif // AIX or BSD |
| 1019 | + } |
| 1020 | + return false; |
| 1021 | +} |
| 1022 | +#endif // ZERO |
| 1023 | + |
910 | 1024 | bool os::Posix::is_root(uid_t uid){ |
911 | 1025 | return ROOT_UID == uid; |
912 | 1026 | } |
|
0 commit comments