mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
8254158: Consolidate per-platform stack overflow handling code
Reviewed-by: fparain, hseigel
This commit is contained in:
parent
715e24afb2
commit
ba5dc67a74
10 changed files with 168 additions and 513 deletions
|
@ -162,40 +162,11 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
|
|||
return frame(sp, epc);
|
||||
}
|
||||
|
||||
bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
|
||||
address pc = (address) os::Linux::ucontext_get_pc(uc);
|
||||
if (Interpreter::contains(pc)) {
|
||||
// Interpreter performs stack banging after the fixed frame header has
|
||||
// been generated while the compilers perform it before. To maintain
|
||||
// semantic consistency between interpreted and compiled frames, the
|
||||
// method returns the Java sender of the current frame.
|
||||
*fr = os::fetch_frame_from_context(uc);
|
||||
if (!fr->is_first_java_frame()) {
|
||||
assert(fr->safe_for_sender(thread), "Safety check");
|
||||
*fr = fr->java_sender();
|
||||
}
|
||||
} else {
|
||||
// More complex code with compiled code.
|
||||
assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
|
||||
CodeBlob* cb = CodeCache::find_blob(pc);
|
||||
if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
|
||||
// Not sure where the pc points to, fallback to default
|
||||
// stack overflow handling. In compiled code, we bang before
|
||||
// the frame is complete.
|
||||
return false;
|
||||
} else {
|
||||
intptr_t* sp = os::Linux::ucontext_get_sp(uc);
|
||||
address lr = ucontext_get_lr(uc);
|
||||
*fr = frame(sp, lr);
|
||||
if (!fr->is_java_frame()) {
|
||||
assert(fr->safe_for_sender(thread), "Safety check");
|
||||
assert(!fr->is_first_frame(), "Safety check");
|
||||
*fr = fr->java_sender();
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(fr->is_java_frame(), "Safety check");
|
||||
return true;
|
||||
frame os::fetch_compiled_frame_from_context(const void* ucVoid) {
|
||||
const ucontext_t* uc = (const ucontext_t*)ucVoid;
|
||||
intptr_t* sp = os::Linux::ucontext_get_sp(uc);
|
||||
address lr = ucontext_get_lr(uc);
|
||||
return frame(sp, lr);
|
||||
}
|
||||
|
||||
frame os::get_sender_for_C_frame(frame* fr) {
|
||||
|
@ -327,60 +298,8 @@ JVM_handle_linux_signal(int sig,
|
|||
// Check if fault address is within thread stack.
|
||||
if (thread->is_in_full_stack(addr)) {
|
||||
// stack overflow
|
||||
StackOverflow* overflow_state = thread->stack_overflow_state();
|
||||
if (overflow_state->in_stack_yellow_reserved_zone(addr)) {
|
||||
if (thread->thread_state() == _thread_in_Java) {
|
||||
if (overflow_state->in_stack_reserved_zone(addr)) {
|
||||
frame fr;
|
||||
if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) {
|
||||
assert(fr.is_java_frame(), "Must be a Javac frame");
|
||||
frame activation =
|
||||
SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
|
||||
if (activation.sp() != NULL) {
|
||||
overflow_state->disable_stack_reserved_zone();
|
||||
if (activation.is_interpreted_frame()) {
|
||||
overflow_state->set_reserved_stack_activation((address)activation.fp());
|
||||
} else {
|
||||
overflow_state->set_reserved_stack_activation((address)activation.unextended_sp());
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Throw a stack overflow exception.
|
||||
// Guard pages will be reenabled while unwinding the stack.
|
||||
overflow_state->disable_stack_yellow_reserved_zone();
|
||||
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
|
||||
} else {
|
||||
// Thread was in the vm or native code. Return and try to finish.
|
||||
overflow_state->disable_stack_yellow_reserved_zone();
|
||||
return 1;
|
||||
}
|
||||
} else if (overflow_state->in_stack_red_zone(addr)) {
|
||||
// Fatal red zone violation. Disable the guard pages and fall through
|
||||
// to handle_unexpected_exception way down below.
|
||||
overflow_state->disable_stack_red_zone();
|
||||
tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
|
||||
|
||||
// This is a likely cause, but hard to verify. Let's just print
|
||||
// it as a hint.
|
||||
tty->print_raw_cr("Please check if any of your loaded .so files has "
|
||||
"enabled executable stack (see man page execstack(8))");
|
||||
} else {
|
||||
// Accessing stack address below sp may cause SEGV if current
|
||||
// thread has MAP_GROWSDOWN stack. This should only happen when
|
||||
// current thread was created by user code with MAP_GROWSDOWN flag
|
||||
// and then attached to VM. See notes in os_linux.cpp.
|
||||
if (thread->osthread()->expanding_stack() == 0) {
|
||||
thread->osthread()->set_expanding_stack();
|
||||
if (os::Linux::manually_expand_stack(thread, addr)) {
|
||||
thread->osthread()->clear_expanding_stack();
|
||||
return 1;
|
||||
}
|
||||
thread->osthread()->clear_expanding_stack();
|
||||
} else {
|
||||
fatal("recursive segv. expanding stack.");
|
||||
}
|
||||
if (os::Posix::handle_stack_overflow(thread, addr, pc, uc, &stub)) {
|
||||
return 1; // continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue