src/cpu/sparc/vm/frame_sparc.cpp

changeset 542
93b6525e3b82
parent 435
a61af66fc99e
child 631
d1605aabd0a1
     1.1 --- a/src/cpu/sparc/vm/frame_sparc.cpp	Mon Apr 07 15:15:16 2008 -0700
     1.2 +++ b/src/cpu/sparc/vm/frame_sparc.cpp	Tue Apr 08 12:23:15 2008 -0400
     1.3 @@ -157,22 +157,158 @@
     1.4    check_location_valid();
     1.5  }
     1.6  
     1.7 +bool frame::safe_for_sender(JavaThread *thread) {
     1.8  
     1.9 -bool frame::safe_for_sender(JavaThread *thread) {
    1.10 -  address   sp = (address)_sp;
    1.11 -  if (sp != NULL &&
    1.12 -      (sp <= thread->stack_base() && sp >= thread->stack_base() - thread->stack_size())) {
    1.13 -      // Unfortunately we can only check frame complete for runtime stubs and nmethod
    1.14 -      // other generic buffer blobs are more problematic so we just assume they are
    1.15 -      // ok. adapter blobs never have a frame complete and are never ok.
    1.16 -      if (_cb != NULL && !_cb->is_frame_complete_at(_pc)) {
    1.17 -        if (_cb->is_nmethod() || _cb->is_adapter_blob() || _cb->is_runtime_stub()) {
    1.18 -          return false;
    1.19 -        }
    1.20 +  address _SP = (address) sp();
    1.21 +  address _FP = (address) fp();
    1.22 +  address _UNEXTENDED_SP = (address) unextended_sp();
    1.23 +  // sp must be within the stack
    1.24 +  bool sp_safe = (_SP <= thread->stack_base()) &&
    1.25 +                 (_SP >= thread->stack_base() - thread->stack_size());
    1.26 +
    1.27 +  if (!sp_safe) {
    1.28 +    return false;
    1.29 +  }
    1.30 +
    1.31 +  // unextended sp must be within the stack and above or equal sp
    1.32 +  bool unextended_sp_safe = (_UNEXTENDED_SP <= thread->stack_base()) &&
    1.33 +                            (_UNEXTENDED_SP >= _SP);
    1.34 +
    1.35 +  if (!unextended_sp_safe) return false;
    1.36 +
    1.37 +  // an fp must be within the stack and above (but not equal) sp
    1.38 +  bool fp_safe = (_FP <= thread->stack_base()) &&
    1.39 +                 (_FP > _SP);
    1.40 +
    1.41 +  // We know sp/unextended_sp are safe only fp is questionable here
    1.42 +
    1.43 +  // If the current frame is known to the code cache then we can attempt to
    1.44 +  // to construct the sender and do some validation of it. This goes a long way
    1.45 +  // toward eliminating issues when we get in frame construction code
    1.46 +
    1.47 +  if (_cb != NULL ) {
    1.48 +
    1.49 +    // First check if frame is complete and tester is reliable
    1.50 +    // Unfortunately we can only check frame complete for runtime stubs and nmethod
    1.51 +    // other generic buffer blobs are more problematic so we just assume they are
    1.52 +    // ok. adapter blobs never have a frame complete and are never ok.
    1.53 +
    1.54 +    if (!_cb->is_frame_complete_at(_pc)) {
    1.55 +      if (_cb->is_nmethod() || _cb->is_adapter_blob() || _cb->is_runtime_stub()) {
    1.56 +        return false;
    1.57        }
    1.58 -      return true;
    1.59 +    }
    1.60 +
    1.61 +    // Entry frame checks
    1.62 +    if (is_entry_frame()) {
    1.63 +      // an entry frame must have a valid fp.
    1.64 +
    1.65 +      if (!fp_safe) {
    1.66 +        return false;
    1.67 +      }
    1.68 +
    1.69 +      // Validate the JavaCallWrapper an entry frame must have
    1.70 +
    1.71 +      address jcw = (address)entry_frame_call_wrapper();
    1.72 +
    1.73 +      bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > _FP);
    1.74 +
    1.75 +      return jcw_safe;
    1.76 +
    1.77 +    }
    1.78 +
    1.79 +    intptr_t* younger_sp = sp();
    1.80 +    intptr_t* _SENDER_SP = sender_sp(); // sender is actually just _FP
    1.81 +    bool adjusted_stack = is_interpreted_frame();
    1.82 +
    1.83 +    address   sender_pc = (address)younger_sp[I7->sp_offset_in_saved_window()] + pc_return_offset;
    1.84 +
    1.85 +
    1.86 +    // We must always be able to find a recognizable pc
    1.87 +    CodeBlob* sender_blob = CodeCache::find_blob_unsafe(sender_pc);
    1.88 +    if (sender_pc == NULL ||  sender_blob == NULL) {
    1.89 +      return false;
    1.90 +    }
    1.91 +
    1.92 +    // It should be safe to construct the sender though it might not be valid
    1.93 +
    1.94 +    frame sender(_SENDER_SP, younger_sp, adjusted_stack);
    1.95 +
    1.96 +    // Do we have a valid fp?
    1.97 +    address sender_fp = (address) sender.fp();
    1.98 +
    1.99 +    // an fp must be within the stack and above (but not equal) current frame's _FP
   1.100 +
   1.101 +    bool sender_fp_safe = (sender_fp <= thread->stack_base()) &&
   1.102 +                   (sender_fp > _FP);
   1.103 +
   1.104 +    if (!sender_fp_safe) {
   1.105 +      return false;
   1.106 +    }
   1.107 +
   1.108 +
   1.109 +    // If the potential sender is the interpreter then we can do some more checking
   1.110 +    if (Interpreter::contains(sender_pc)) {
   1.111 +      return sender.is_interpreted_frame_valid(thread);
   1.112 +    }
   1.113 +
   1.114 +    // Could just be some random pointer within the codeBlob
   1.115 +    if (!sender.cb()->instructions_contains(sender_pc)) return false;
   1.116 +
   1.117 +    // We should never be able to see an adapter if the current frame is something from code cache
   1.118 +
   1.119 +    if ( sender_blob->is_adapter_blob()) {
   1.120 +      return false;
   1.121 +    }
   1.122 +
   1.123 +    if( sender.is_entry_frame()) {
   1.124 +      // Validate the JavaCallWrapper an entry frame must have
   1.125 +
   1.126 +      address jcw = (address)sender.entry_frame_call_wrapper();
   1.127 +
   1.128 +      bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > sender_fp);
   1.129 +
   1.130 +      return jcw_safe;
   1.131 +    }
   1.132 +
   1.133 +    // If the frame size is 0 something is bad because every nmethod has a non-zero frame size
   1.134 +    // because you must allocate window space
   1.135 +
   1.136 +    if (sender_blob->frame_size() == 0) {
   1.137 +      assert(!sender_blob->is_nmethod(), "should count return address at least");
   1.138 +      return false;
   1.139 +    }
   1.140 +
   1.141 +    // The sender should positively be an nmethod or call_stub. On sparc we might in fact see something else.
   1.142 +    // The cause of this is because at a save instruction the O7 we get is a leftover from an earlier
   1.143 +    // window use. So if a runtime stub creates two frames (common in fastdebug/jvmg) then we see the
   1.144 +    // stale pc. So if the sender blob is not something we'd expect we have little choice but to declare
   1.145 +    // the stack unwalkable. pd_get_top_frame_for_signal_handler tries to recover from this by unwinding
   1.146 +    // that initial frame and retrying.
   1.147 +
   1.148 +    if (!sender_blob->is_nmethod()) {
   1.149 +      return false;
   1.150 +    }
   1.151 +
   1.152 +    // Could put some more validation for the potential non-interpreted sender
   1.153 +    // frame we'd create by calling sender if I could think of any. Wait for next crash in forte...
   1.154 +
   1.155 +    // One idea is seeing if the sender_pc we have is one that we'd expect to call to current cb
   1.156 +
   1.157 +    // We've validated the potential sender that would be created
   1.158 +
   1.159 +    return true;
   1.160 +
   1.161    }
   1.162 -  return false;
   1.163 +
   1.164 +  // Must be native-compiled frame. Since sender will try and use fp to find
   1.165 +  // linkages it must be safe
   1.166 +
   1.167 +  if (!fp_safe) return false;
   1.168 +
   1.169 +  // could try and do some more potential verification of native frame if we could think of some...
   1.170 +
   1.171 +  return true;
   1.172  }
   1.173  
   1.174  // constructors
   1.175 @@ -450,7 +586,7 @@
   1.176  }
   1.177  
   1.178  
   1.179 -bool frame::is_interpreted_frame_valid() const {
   1.180 +bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
   1.181  #ifdef CC_INTERP
   1.182    // Is there anything to do?
   1.183  #else
   1.184 @@ -462,6 +598,7 @@
   1.185    if (sp() == 0 || (intptr_t(sp()) & (2*wordSize-1)) != 0) {
   1.186      return false;
   1.187    }
   1.188 +
   1.189    const intptr_t interpreter_frame_initial_sp_offset = interpreter_frame_vm_local_words;
   1.190    if (fp() + interpreter_frame_initial_sp_offset < sp()) {
   1.191      return false;
   1.192 @@ -471,9 +608,43 @@
   1.193    if (fp() <= sp()) {        // this attempts to deal with unsigned comparison above
   1.194      return false;
   1.195    }
   1.196 -  if (fp() - sp() > 4096) {  // stack frames shouldn't be large.
   1.197 +  // do some validation of frame elements
   1.198 +
   1.199 +  // first the method
   1.200 +
   1.201 +  methodOop m = *interpreter_frame_method_addr();
   1.202 +
   1.203 +  // validate the method we'd find in this potential sender
   1.204 +  if (!Universe::heap()->is_valid_method(m)) return false;
   1.205 +
   1.206 +  // stack frames shouldn't be much larger than max_stack elements
   1.207 +
   1.208 +  if (fp() - sp() > 1024 + m->max_stack()*Interpreter::stackElementSize()) {
   1.209      return false;
   1.210    }
   1.211 +
   1.212 +  // validate bci/bcx
   1.213 +
   1.214 +  intptr_t  bcx    = interpreter_frame_bcx();
   1.215 +  if (m->validate_bci_from_bcx(bcx) < 0) {
   1.216 +    return false;
   1.217 +  }
   1.218 +
   1.219 +  // validate constantPoolCacheOop
   1.220 +
   1.221 +  constantPoolCacheOop cp = *interpreter_frame_cache_addr();
   1.222 +
   1.223 +  if (cp == NULL ||
   1.224 +      !Space::is_aligned(cp) ||
   1.225 +      !Universe::heap()->is_permanent((void*)cp)) return false;
   1.226 +
   1.227 +  // validate locals
   1.228 +
   1.229 +  address locals =  (address) *interpreter_frame_locals_addr();
   1.230 +
   1.231 +  if (locals > thread->stack_base() || locals < (address) fp()) return false;
   1.232 +
   1.233 +  // We'd have to be pretty unlucky to be mislead at this point
   1.234  #endif /* CC_INTERP */
   1.235    return true;
   1.236  }

mercurial