< prev index next >

src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp

Print this page
rev 54204 : 8220794: PPC64: Fix signal handler for SIGSEGV on branch to illegal address
Reviewed-by:


 115 // modify PC in ucontext.
 116 // Note: Only use this for an ucontext handed down to a signal handler. See comment
 117 // in ucontext_get_pc.
 118 void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) {
 119   guarantee(uc->uc_mcontext.regs != NULL, "only use ucontext_set_pc in sigaction context");
 120   uc->uc_mcontext.regs->nip = (unsigned long)pc;
 121 }
 122 
 123 static address ucontext_get_lr(const ucontext_t * uc) {
 124   return (address)uc->uc_mcontext.regs->link;
 125 }
 126 
 127 intptr_t* os::Linux::ucontext_get_sp(const ucontext_t * uc) {
 128   return (intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/];
 129 }
 130 
 131 intptr_t* os::Linux::ucontext_get_fp(const ucontext_t * uc) {
 132   return NULL;
 133 }
 134 




 135 ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
 136                     intptr_t** ret_sp, intptr_t** ret_fp) {
 137 
 138   ExtendedPC  epc;
 139   const ucontext_t* uc = (const ucontext_t*)ucVoid;
 140 
 141   if (uc != NULL) {
 142     epc = ExtendedPC(os::Linux::ucontext_get_pc(uc));
 143     if (ret_sp) *ret_sp = os::Linux::ucontext_get_sp(uc);
 144     if (ret_fp) *ret_fp = os::Linux::ucontext_get_fp(uc);
 145   } else {
 146     // construct empty ExtendedPC for return value checking
 147     epc = ExtendedPC(NULL);
 148     if (ret_sp) *ret_sp = (intptr_t *)NULL;
 149     if (ret_fp) *ret_fp = (intptr_t *)NULL;
 150   }
 151 
 152   return epc;
 153 }
 154 


 287   // Moved SafeFetch32 handling outside thread!=NULL conditional block to make
 288   // it work if no associated JavaThread object exists.
 289   if (uc) {
 290     address const pc = os::Linux::ucontext_get_pc(uc);
 291     if (pc && StubRoutines::is_safefetch_fault(pc)) {
 292       os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
 293       return true;
 294     }
 295   }
 296 
 297   // decide if this trap can be handled by a stub
 298   address stub = NULL;
 299   address pc   = NULL;
 300 
 301   //%note os_trap_1
 302   if (info != NULL && uc != NULL && thread != NULL) {
 303     pc = (address) os::Linux::ucontext_get_pc(uc);
 304 
 305     // Handle ALL stack overflow variations here
 306     if (sig == SIGSEGV) {
 307       // Si_addr may not be valid due to a bug in the linux-ppc64 kernel (see
 308       // comment below). Use get_stack_bang_address instead of si_addr.
 309       address addr = ((NativeInstruction*)pc)->get_stack_bang_address(uc);













 310 
 311       // Check if fault address is within thread stack.
 312       if (thread->on_local_stack(addr)) {
 313         // stack overflow
 314         if (thread->in_stack_yellow_reserved_zone(addr)) {
 315           if (thread->thread_state() == _thread_in_Java) {
 316             if (thread->in_stack_reserved_zone(addr)) {
 317               frame fr;
 318               if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) {
 319                 assert(fr.is_java_frame(), "Must be a Javac frame");
 320                 frame activation =
 321                   SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
 322                 if (activation.sp() != NULL) {
 323                   thread->disable_stack_reserved_zone();
 324                   if (activation.is_interpreted_frame()) {
 325                     thread->set_reserved_stack_activation((address)activation.fp());
 326                   } else {
 327                     thread->set_reserved_stack_activation((address)activation.unextended_sp());
 328                   }
 329                   return 1;




 115 // modify PC in ucontext.
 116 // Note: Only use this for an ucontext handed down to a signal handler. See comment
 117 // in ucontext_get_pc.
 118 void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) {
 119   guarantee(uc->uc_mcontext.regs != NULL, "only use ucontext_set_pc in sigaction context");
 120   uc->uc_mcontext.regs->nip = (unsigned long)pc;
 121 }
 122 
 123 static address ucontext_get_lr(const ucontext_t * uc) {
 124   return (address)uc->uc_mcontext.regs->link;
 125 }
 126 
 127 intptr_t* os::Linux::ucontext_get_sp(const ucontext_t * uc) {
 128   return (intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/];
 129 }
 130 
 131 intptr_t* os::Linux::ucontext_get_fp(const ucontext_t * uc) {
 132   return NULL;
 133 }
 134 
 135 static unsigned long ucontext_get_trap(const ucontext_t * uc) {
 136   return uc->uc_mcontext.regs->trap;
 137 }
 138 
 139 ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
 140                     intptr_t** ret_sp, intptr_t** ret_fp) {
 141 
 142   ExtendedPC  epc;
 143   const ucontext_t* uc = (const ucontext_t*)ucVoid;
 144 
 145   if (uc != NULL) {
 146     epc = ExtendedPC(os::Linux::ucontext_get_pc(uc));
 147     if (ret_sp) *ret_sp = os::Linux::ucontext_get_sp(uc);
 148     if (ret_fp) *ret_fp = os::Linux::ucontext_get_fp(uc);
 149   } else {
 150     // construct empty ExtendedPC for return value checking
 151     epc = ExtendedPC(NULL);
 152     if (ret_sp) *ret_sp = (intptr_t *)NULL;
 153     if (ret_fp) *ret_fp = (intptr_t *)NULL;
 154   }
 155 
 156   return epc;
 157 }
 158 


 291   // Moved SafeFetch32 handling outside thread!=NULL conditional block to make
 292   // it work if no associated JavaThread object exists.
 293   if (uc) {
 294     address const pc = os::Linux::ucontext_get_pc(uc);
 295     if (pc && StubRoutines::is_safefetch_fault(pc)) {
 296       os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
 297       return true;
 298     }
 299   }
 300 
 301   // decide if this trap can be handled by a stub
 302   address stub = NULL;
 303   address pc   = NULL;
 304 
 305   //%note os_trap_1
 306   if (info != NULL && uc != NULL && thread != NULL) {
 307     pc = (address) os::Linux::ucontext_get_pc(uc);
 308 
 309     // Handle ALL stack overflow variations here
 310     if (sig == SIGSEGV) {
 311       // si_addr may not be valid due to a bug in the linux-ppc64 kernel (see
 312       // comment below). Use get_stack_bang_address instead of si_addr.
 313       // If SIGSEGV is caused due to a branch to an invalid address an
 314       // "Instruction Storage" interruption is generated and 'pc' (NIP) already
 315       // contains the invalid address. Otherwise, the SIGSEGV is caused due to
 316       // load/store instruction trying to load/store from/to an invalid address
 317       // and causing a "Data Storage" interruption, so we inspect the intruction
 318       // in order to extract the faulty data addresss.
 319       address addr;
 320       if ((ucontext_get_trap(uc) & 0x0F00 /* no IRQ reply bits */) == 0x0400) {
 321         // Instruction interruption
 322         addr = pc;
 323       } else {
 324         // Data interruption (0x0300): extract faulty data address
 325         addr = ((NativeInstruction*)pc)->get_stack_bang_address(uc);
 326       }
 327 
 328       // Check if fault address is within thread stack.
 329       if (thread->on_local_stack(addr)) {
 330         // stack overflow
 331         if (thread->in_stack_yellow_reserved_zone(addr)) {
 332           if (thread->thread_state() == _thread_in_Java) {
 333             if (thread->in_stack_reserved_zone(addr)) {
 334               frame fr;
 335               if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) {
 336                 assert(fr.is_java_frame(), "Must be a Javac frame");
 337                 frame activation =
 338                   SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
 339                 if (activation.sp() != NULL) {
 340                   thread->disable_stack_reserved_zone();
 341                   if (activation.is_interpreted_frame()) {
 342                     thread->set_reserved_stack_activation((address)activation.fp());
 343                   } else {
 344                     thread->set_reserved_stack_activation((address)activation.unextended_sp());
 345                   }
 346                   return 1;


< prev index next >