src/cpu/x86/vm/frame_x86.cpp

Print this page
rev 4773 : 8005849: JEP 167: Event-Based JVM Tracing
Reviewed-by: acorn, coleenp, sla
Contributed-by: Karen Kinnear <karen.kinnear@oracle.com>, Bengt Rutisson <bengt.rutisson@oracle.com>, Calvin Cheung <calvin.cheung@oracle.com>, Erik Gahlin <erik.gahlin@oracle.com>, Erik Helin <erik.helin@oracle.com>, Jesper Wilhelmsson <jesper.wilhelmsson@oracle.com>, Keith McGuigan <keith.mcguigan@oracle.com>, Mattias Tobiasson <mattias.tobiasson@oracle.com>, Markus Gronlund <markus.gronlund@oracle.com>, Mikael Auno <mikael.auno@oracle.com>, Nils Eliasson <nils.eliasson@oracle.com>, Nils Loodin <nils.loodin@oracle.com>, Rickard Backman <rickard.backman@oracle.com>, Staffan Larsen <staffan.larsen@oracle.com>, Stefan Karlsson <stefan.karlsson@oracle.com>, Yekaterina Kantserova <yekaterina.kantserova@oracle.com>

*** 1,7 **** /* ! * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 31,40 **** --- 31,41 ---- #include "prims/methodHandles.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/monitorChunk.hpp" + #include "runtime/os.hpp" #include "runtime/signature.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "vmreg_x86.inline.hpp" #ifdef COMPILER1
*** 52,79 **** bool frame::safe_for_sender(JavaThread *thread) { address sp = (address)_sp; address fp = (address)_fp; address unextended_sp = (address)_unextended_sp; ! // sp must be within the stack ! bool sp_safe = (sp <= thread->stack_base()) && ! (sp >= thread->stack_base() - thread->stack_size()); if (!sp_safe) { return false; } // unextended sp must be within the stack and above or equal sp ! bool unextended_sp_safe = (unextended_sp <= thread->stack_base()) && (unextended_sp >= sp); if (!unextended_sp_safe) { return false; } // an fp must be within the stack and above (but not equal) sp ! bool fp_safe = (fp <= thread->stack_base()) && (fp > sp); // We know sp/unextended_sp are safe only fp is questionable here // If the current frame is known to the code cache then we can attempt to // to construct the sender and do some validation of it. This goes a long way --- 53,87 ---- bool frame::safe_for_sender(JavaThread *thread) { address sp = (address)_sp; address fp = (address)_fp; address unextended_sp = (address)_unextended_sp; ! ! // consider stack guards when trying to determine "safe" stack pointers ! static size_t stack_guard_size = os::uses_stack_guard_pages() ? (StackYellowPages + StackRedPages) * os::vm_page_size() : 0; ! size_t usable_stack_size = thread->stack_size() - stack_guard_size; ! ! // sp must be within the usable part of the stack (not in guards) ! bool sp_safe = (sp < thread->stack_base()) && ! (sp >= thread->stack_base() - usable_stack_size); ! if (!sp_safe) { return false; } // unextended sp must be within the stack and above or equal sp ! bool unextended_sp_safe = (unextended_sp < thread->stack_base()) && (unextended_sp >= sp); if (!unextended_sp_safe) { return false; } // an fp must be within the stack and above (but not equal) sp ! // second evaluation on fp+ is added to handle situation where fp is -1 ! bool fp_safe = (fp < thread->stack_base() && (fp > sp) && (((fp + (return_addr_offset * sizeof(void*))) < thread->stack_base()))); // We know sp/unextended_sp are safe only fp is questionable here // If the current frame is known to the code cache then we can attempt to // to construct the sender and do some validation of it. This goes a long way
*** 84,93 **** --- 92,108 ---- // First check if frame is complete and tester is reliable // Unfortunately we can only check frame complete for runtime stubs and nmethod // other generic buffer blobs are more problematic so we just assume they are // ok. adapter blobs never have a frame complete and are never ok. + // check for a valid frame_size, otherwise we are unlikely to get a valid sender_pc + + if (!Interpreter::contains(_pc) && _cb->frame_size() <= 0) { + //assert(0, "Invalid frame_size"); + return false; + } + if (!_cb->is_frame_complete_at(_pc)) { if (_cb->is_nmethod() || _cb->is_adapter_blob() || _cb->is_runtime_stub()) { return false; } }
*** 105,115 **** // Validate the JavaCallWrapper an entry frame must have address jcw = (address)entry_frame_call_wrapper(); ! bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > fp); return jcw_safe; } --- 120,130 ---- // Validate the JavaCallWrapper an entry frame must have address jcw = (address)entry_frame_call_wrapper(); ! bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > fp); return jcw_safe; }
*** 132,157 **** sender_sp = _unextended_sp + _cb->frame_size(); // On Intel the return_address is always the word on the stack sender_pc = (address) *(sender_sp-1); } - // We must always be able to find a recognizable pc - CodeBlob* sender_blob = CodeCache::find_blob_unsafe(sender_pc); - if (sender_pc == NULL || sender_blob == NULL) { - return false; - } - // If the potential sender is the interpreter then we can do some more checking if (Interpreter::contains(sender_pc)) { // ebp is always saved in a recognizable place in any code we generate. However // only if the sender is interpreted/call_stub (c1 too?) are we certain that the saved ebp // is really a frame pointer. intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); ! bool saved_fp_safe = ((address)saved_fp <= thread->stack_base()) && (saved_fp > sender_sp); if (!saved_fp_safe) { return false; } --- 147,166 ---- sender_sp = _unextended_sp + _cb->frame_size(); // On Intel the return_address is always the word on the stack sender_pc = (address) *(sender_sp-1); } // If the potential sender is the interpreter then we can do some more checking if (Interpreter::contains(sender_pc)) { // ebp is always saved in a recognizable place in any code we generate. However // only if the sender is interpreted/call_stub (c1 too?) are we certain that the saved ebp // is really a frame pointer. intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); ! bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); if (!saved_fp_safe) { return false; }
*** 161,170 **** --- 170,190 ---- return sender.is_interpreted_frame_valid(thread); } + // We must always be able to find a recognizable pc + CodeBlob* sender_blob = CodeCache::find_blob_unsafe(sender_pc); + if (sender_pc == NULL || sender_blob == NULL) { + return false; + } + + // Could be a zombie method + if (sender_blob->is_zombie() || sender_blob->is_unloaded()) { + return false; + } + // Could just be some random pointer within the codeBlob if (!sender_blob->code_contains(sender_pc)) { return false; }
*** 172,185 **** if (sender_blob->is_adapter_blob()) { return false; } // Could be the call_stub - if (StubRoutines::returns_to_call_stub(sender_pc)) { intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); ! bool saved_fp_safe = ((address)saved_fp <= thread->stack_base()) && (saved_fp > sender_sp); if (!saved_fp_safe) { return false; } --- 192,204 ---- if (sender_blob->is_adapter_blob()) { return false; } // Could be the call_stub if (StubRoutines::returns_to_call_stub(sender_pc)) { intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); ! bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); if (!saved_fp_safe) { return false; }
*** 188,216 **** frame sender(sender_sp, saved_fp, sender_pc); // Validate the JavaCallWrapper an entry frame must have address jcw = (address)sender.entry_frame_call_wrapper(); ! bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > (address)sender.fp()); return jcw_safe; } ! // If the frame size is 0 something is bad because every nmethod has a non-zero frame size // because the return address counts against the callee's frame. ! if (sender_blob->frame_size() == 0) { assert(!sender_blob->is_nmethod(), "should count return address at least"); return false; } // We should never be able to see anything here except an nmethod. If something in the // code cache (current frame) is called by an entity within the code cache that entity // should not be anything but the call stub (already covered), the interpreter (already covered) // or an nmethod. ! assert(sender_blob->is_nmethod(), "Impossible call chain"); // Could put some more validation for the potential non-interpreted sender // frame we'd create by calling sender if I could think of any. Wait for next crash in forte... // One idea is seeing if the sender_pc we have is one that we'd expect to call to current cb --- 207,246 ---- frame sender(sender_sp, saved_fp, sender_pc); // Validate the JavaCallWrapper an entry frame must have address jcw = (address)sender.entry_frame_call_wrapper(); ! bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > (address)sender.fp()); return jcw_safe; } ! if (sender_blob->is_nmethod()) { ! nmethod* nm = sender_blob->as_nmethod_or_null(); ! if (nm != NULL) { ! if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc)) { ! return false; ! } ! } ! } ! ! // If the frame size is 0 something (or less) is bad because every nmethod has a non-zero frame size // because the return address counts against the callee's frame. ! if (sender_blob->frame_size() <= 0) { assert(!sender_blob->is_nmethod(), "should count return address at least"); return false; } // We should never be able to see anything here except an nmethod. If something in the // code cache (current frame) is called by an entity within the code cache that entity // should not be anything but the call stub (already covered), the interpreter (already covered) // or an nmethod. ! if (!sender_blob->is_nmethod()) { ! return false; ! } // Could put some more validation for the potential non-interpreted sender // frame we'd create by calling sender if I could think of any. Wait for next crash in forte... // One idea is seeing if the sender_pc we have is one that we'd expect to call to current cb