< prev index next >
src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp
Print this page
rev 7905 : 8074552: SafeFetch32 and SafeFetchN do not work in error handling
Summary: handle SafeFetch faults in secondary signal handlers
Contributed-by: Thomas Stuefe
*** 111,120 ****
--- 111,128 ----
// Hopefully it was zero'd out beforehand.
guarantee(uc->uc_mcontext.regs != NULL, "only use ucontext_get_pc in sigaction context");
return (address)uc->uc_mcontext.regs->nip;
}
+ // modify PC in ucontext.
+ // Note: Only use this for an ucontext handed down to a signal handler. See comment
+ // in ucontext_get_pc.
+ void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) {
+ guarantee(uc->uc_mcontext.regs != NULL, "only use ucontext_set_pc in sigaction context");
+ uc->uc_mcontext.regs->nip = (unsigned long)pc;
+ }
+
intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) {
return (intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/];
}
intptr_t* os::Linux::ucontext_get_fp(ucontext_t * uc) {
*** 211,221 ****
// Moved SafeFetch32 handling outside thread!=NULL conditional block to make
// it work if no associated JavaThread object exists.
if (uc) {
address const pc = os::Linux::ucontext_get_pc(uc);
if (pc && StubRoutines::is_safefetch_fault(pc)) {
! uc->uc_mcontext.regs->nip = (unsigned long)StubRoutines::continuation_for_safefetch_fault(pc);
return true;
}
}
// decide if this trap can be handled by a stub
--- 219,229 ----
// Moved SafeFetch32 handling outside thread!=NULL conditional block to make
// it work if no associated JavaThread object exists.
if (uc) {
address const pc = os::Linux::ucontext_get_pc(uc);
if (pc && StubRoutines::is_safefetch_fault(pc)) {
! os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return true;
}
}
// decide if this trap can be handled by a stub
*** 358,368 ****
if (nm != NULL && nm->has_unsafe_access()) {
// We don't really need a stub here! Just set the pending exeption and
// continue at the next instruction after the faulting read. Returning
// garbage from this read is ok.
thread->set_pending_unsafe_access_error();
! uc->uc_mcontext.regs->nip = ((unsigned long)pc) + 4;
return true;
}
}
}
--- 366,376 ----
if (nm != NULL && nm->has_unsafe_access()) {
// We don't really need a stub here! Just set the pending exeption and
// continue at the next instruction after the faulting read. Returning
// garbage from this read is ok.
thread->set_pending_unsafe_access_error();
! os::Linux::ucontext_set_pc(uc, pc + 4);
return true;
}
}
}
*** 377,387 ****
sig == SIGBUS && thread->doing_unsafe_access()) {
// We don't really need a stub here! Just set the pending exeption and
// continue at the next instruction after the faulting read. Returning
// garbage from this read is ok.
thread->set_pending_unsafe_access_error();
! uc->uc_mcontext.regs->nip = ((unsigned long)pc) + 4;
return true;
}
}
// Check to see if we caught the safepoint code in the
--- 385,395 ----
sig == SIGBUS && thread->doing_unsafe_access()) {
// We don't really need a stub here! Just set the pending exeption and
// continue at the next instruction after the faulting read. Returning
// garbage from this read is ok.
thread->set_pending_unsafe_access_error();
! os::Linux::ucontext_set_pc(uc, pc + 4);
return true;
}
}
// Check to see if we caught the safepoint code in the
*** 400,410 ****
}
if (stub != NULL) {
// Save all thread context in case we need to restore it.
if (thread != NULL) thread->set_saved_exception_pc(pc);
! uc->uc_mcontext.regs->nip = (unsigned long)stub;
return true;
}
// signal-chaining
if (os::Linux::chained_handler(sig, info, ucVoid)) {
--- 408,418 ----
}
if (stub != NULL) {
// Save all thread context in case we need to restore it.
if (thread != NULL) thread->set_saved_exception_pc(pc);
! os::Linux::ucontext_set_pc(uc, stub);
return true;
}
// signal-chaining
if (os::Linux::chained_handler(sig, info, ucVoid)) {
< prev index next >