< prev index next >

src/os_cpu/linux_x86/vm/os_linux_x86.cpp

Print this page
rev 7970 : 8074552:  SafeFetch32 and SafeFetchN do not work in error handling
Summary: handle SafeFetch faults in secondary signal handlers
Reviewed-by: dholmes
Contributed-by: Thomas Stuefe


 105   return (address) esp;
 106 #endif
 107 }
 108 
 109 char* os::non_memory_address_word() {
 110   // Must never look like an address returned by reserve_memory,
 111   // even in its subfields (as defined by the CPU immediate fields,
 112   // if the CPU splits constants across multiple instructions).
 113 
 114   return (char*) -1;
 115 }
 116 
 117 void os::initialize_thread(Thread* thr) {
 118 // Nothing to do.
 119 }
 120 
 121 address os::Linux::ucontext_get_pc(ucontext_t * uc) {
 122   return (address)uc->uc_mcontext.gregs[REG_PC];
 123 }
 124 




 125 intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) {
 126   return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
 127 }
 128 
 129 intptr_t* os::Linux::ucontext_get_fp(ucontext_t * uc) {
 130   return (intptr_t*)uc->uc_mcontext.gregs[REG_FP];
 131 }
 132 
 133 // For Forte Analyzer AsyncGetCallTrace profiling support - thread
 134 // is currently interrupted by SIGPROF.
 135 // os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal
 136 // frames. Currently we don't do that on Linux, so it's the same as
 137 // os::fetch_frame_from_context().
 138 ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread,
 139   ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
 140 
 141   assert(thread != NULL, "just checking");
 142   assert(ret_sp != NULL, "just checking");
 143   assert(ret_fp != NULL, "just checking");
 144 


 262   }
 263 /*
 264   NOTE: does not seem to work on linux.
 265   if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
 266     // can't decode this kind of signal
 267     info = NULL;
 268   } else {
 269     assert(sig == info->si_signo, "bad siginfo");
 270   }
 271 */
 272   // decide if this trap can be handled by a stub
 273   address stub = NULL;
 274 
 275   address pc          = NULL;
 276 
 277   //%note os_trap_1
 278   if (info != NULL && uc != NULL && thread != NULL) {
 279     pc = (address) os::Linux::ucontext_get_pc(uc);
 280 
 281     if (StubRoutines::is_safefetch_fault(pc)) {
 282       uc->uc_mcontext.gregs[REG_PC] = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc));
 283       return 1;
 284     }
 285 
 286 #ifndef AMD64
 287     // Halt if SI_KERNEL before more crashes get misdiagnosed as Java bugs
 288     // This can happen in any running code (currently more frequently in
 289     // interpreter code but has been seen in compiled code)
 290     if (sig == SIGSEGV && info->si_addr == 0 && info->si_code == SI_KERNEL) {
 291       fatal("An irrecoverable SI_KERNEL SIGSEGV has occurred due "
 292             "to unstable signal handling in this distribution.");
 293     }
 294 #endif // AMD64
 295 
 296     // Handle ALL stack overflow variations here
 297     if (sig == SIGSEGV) {
 298       address addr = (address) info->si_addr;
 299 
 300       // check if fault address is within thread stack
 301       if (addr < thread->stack_base() &&
 302           addr >= thread->stack_base() - thread->stack_size()) {


 497         // different addresses and failing to unguard the page, resulting in
 498         // an endless loop.  This condition is probably even more unlikely than
 499         // the first.
 500         //
 501         // Although both cases could be avoided by using locks or thread local
 502         // last_addr, these solutions are unnecessary complication: this
 503         // handler is a best-effort safety net, not a complete solution.  It is
 504         // disabled by default and should only be used as a workaround in case
 505         // we missed any no-execute-unsafe VM code.
 506 
 507         last_addr = addr;
 508       }
 509     }
 510   }
 511 #endif // !AMD64
 512 
 513   if (stub != NULL) {
 514     // save all thread context in case we need to restore it
 515     if (thread != NULL) thread->set_saved_exception_pc(pc);
 516 
 517     uc->uc_mcontext.gregs[REG_PC] = (greg_t)stub;
 518     return true;
 519   }
 520 
 521   // signal-chaining
 522   if (os::Linux::chained_handler(sig, info, ucVoid)) {
 523      return true;
 524   }
 525 
 526   if (!abort_if_unrecognized) {
 527     // caller wants another chance, so give it to him
 528     return false;
 529   }
 530 
 531   if (pc == NULL && uc != NULL) {
 532     pc = os::Linux::ucontext_get_pc(uc);
 533   }
 534 
 535   // unmask current signal
 536   sigset_t newset;
 537   sigemptyset(&newset);




 105   return (address) esp;
 106 #endif
 107 }
 108 
 109 char* os::non_memory_address_word() {
 110   // Must never look like an address returned by reserve_memory,
 111   // even in its subfields (as defined by the CPU immediate fields,
 112   // if the CPU splits constants across multiple instructions).
 113 
 114   return (char*) -1;
 115 }
 116 
 117 void os::initialize_thread(Thread* thr) {
 118 // Nothing to do.
 119 }
 120 
 121 address os::Linux::ucontext_get_pc(ucontext_t * uc) {
 122   return (address)uc->uc_mcontext.gregs[REG_PC];
 123 }
 124 
 125 void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) {
 126   uc->uc_mcontext.gregs[REG_PC] = (intptr_t)pc;
 127 }
 128 
 129 intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) {
 130   return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
 131 }
 132 
 133 intptr_t* os::Linux::ucontext_get_fp(ucontext_t * uc) {
 134   return (intptr_t*)uc->uc_mcontext.gregs[REG_FP];
 135 }
 136 
 137 // For Forte Analyzer AsyncGetCallTrace profiling support - thread
 138 // is currently interrupted by SIGPROF.
 139 // os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal
 140 // frames. Currently we don't do that on Linux, so it's the same as
 141 // os::fetch_frame_from_context().
 142 ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread,
 143   ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
 144 
 145   assert(thread != NULL, "just checking");
 146   assert(ret_sp != NULL, "just checking");
 147   assert(ret_fp != NULL, "just checking");
 148 


 266   }
 267 /*
 268   NOTE: does not seem to work on linux.
 269   if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
 270     // can't decode this kind of signal
 271     info = NULL;
 272   } else {
 273     assert(sig == info->si_signo, "bad siginfo");
 274   }
 275 */
 276   // decide if this trap can be handled by a stub
 277   address stub = NULL;
 278 
 279   address pc          = NULL;
 280 
 281   //%note os_trap_1
 282   if (info != NULL && uc != NULL && thread != NULL) {
 283     pc = (address) os::Linux::ucontext_get_pc(uc);
 284 
 285     if (StubRoutines::is_safefetch_fault(pc)) {
 286       os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
 287       return 1;
 288     }
 289 
 290 #ifndef AMD64
 291     // Halt if SI_KERNEL before more crashes get misdiagnosed as Java bugs
 292     // This can happen in any running code (currently more frequently in
 293     // interpreter code but has been seen in compiled code)
 294     if (sig == SIGSEGV && info->si_addr == 0 && info->si_code == SI_KERNEL) {
 295       fatal("An irrecoverable SI_KERNEL SIGSEGV has occurred due "
 296             "to unstable signal handling in this distribution.");
 297     }
 298 #endif // AMD64
 299 
 300     // Handle ALL stack overflow variations here
 301     if (sig == SIGSEGV) {
 302       address addr = (address) info->si_addr;
 303 
 304       // check if fault address is within thread stack
 305       if (addr < thread->stack_base() &&
 306           addr >= thread->stack_base() - thread->stack_size()) {


 501         // different addresses and failing to unguard the page, resulting in
 502         // an endless loop.  This condition is probably even more unlikely than
 503         // the first.
 504         //
 505         // Although both cases could be avoided by using locks or thread local
 506         // last_addr, these solutions are unnecessary complication: this
 507         // handler is a best-effort safety net, not a complete solution.  It is
 508         // disabled by default and should only be used as a workaround in case
 509         // we missed any no-execute-unsafe VM code.
 510 
 511         last_addr = addr;
 512       }
 513     }
 514   }
 515 #endif // !AMD64
 516 
 517   if (stub != NULL) {
 518     // save all thread context in case we need to restore it
 519     if (thread != NULL) thread->set_saved_exception_pc(pc);
 520 
 521     os::Linux::ucontext_set_pc(uc, stub);
 522     return true;
 523   }
 524 
 525   // signal-chaining
 526   if (os::Linux::chained_handler(sig, info, ucVoid)) {
 527      return true;
 528   }
 529 
 530   if (!abort_if_unrecognized) {
 531     // caller wants another chance, so give it to him
 532     return false;
 533   }
 534 
 535   if (pc == NULL && uc != NULL) {
 536     pc = os::Linux::ucontext_get_pc(uc);
 537   }
 538 
 539   // unmask current signal
 540   sigset_t newset;
 541   sigemptyset(&newset);


< prev index next >