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;
|