119 |
119 |
120 // Validate a ucontext retrieved from walking a uc_link of a ucontext. |
120 // Validate a ucontext retrieved from walking a uc_link of a ucontext. |
121 // There are issues with libthread giving out uc_links for different threads |
121 // There are issues with libthread giving out uc_links for different threads |
122 // on the same uc_link chain and bad or circular links. |
122 // on the same uc_link chain and bad or circular links. |
123 // |
123 // |
124 bool os::Solaris::valid_ucontext(Thread* thread, ucontext_t* valid, ucontext_t* suspect) { |
124 bool os::Solaris::valid_ucontext(Thread* thread, const ucontext_t* valid, const ucontext_t* suspect) { |
125 if (valid >= suspect || |
125 if (valid >= suspect || |
126 valid->uc_stack.ss_flags != suspect->uc_stack.ss_flags || |
126 valid->uc_stack.ss_flags != suspect->uc_stack.ss_flags || |
127 valid->uc_stack.ss_sp != suspect->uc_stack.ss_sp || |
127 valid->uc_stack.ss_sp != suspect->uc_stack.ss_sp || |
128 valid->uc_stack.ss_size != suspect->uc_stack.ss_size) { |
128 valid->uc_stack.ss_size != suspect->uc_stack.ss_size) { |
129 DEBUG_ONLY(tty->print_cr("valid_ucontext: failed test 1");) |
129 DEBUG_ONLY(tty->print_cr("valid_ucontext: failed test 1");) |
146 } |
146 } |
147 |
147 |
148 // We will only follow one level of uc_link since there are libthread |
148 // We will only follow one level of uc_link since there are libthread |
149 // issues with ucontext linking and it is better to be safe and just |
149 // issues with ucontext linking and it is better to be safe and just |
150 // let caller retry later. |
150 // let caller retry later. |
151 ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread, |
151 const ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread, |
152 ucontext_t *uc) { |
152 const ucontext_t *uc) { |
153 |
153 |
154 ucontext_t *retuc = NULL; |
154 const ucontext_t *retuc = NULL; |
155 |
155 |
156 // Sometimes the topmost register windows are not properly flushed. |
156 // Sometimes the topmost register windows are not properly flushed. |
157 // i.e., if the kernel would have needed to take a page fault |
157 // i.e., if the kernel would have needed to take a page fault |
158 if (uc != NULL && uc->uc_mcontext.gwins != NULL) { |
158 if (uc != NULL && uc->uc_mcontext.gwins != NULL) { |
159 ::handle_unflushed_register_windows(uc->uc_mcontext.gwins); |
159 ::handle_unflushed_register_windows(uc->uc_mcontext.gwins); |
177 } |
177 } |
178 return retuc; |
178 return retuc; |
179 } |
179 } |
180 |
180 |
181 // Assumes ucontext is valid |
181 // Assumes ucontext is valid |
182 ExtendedPC os::Solaris::ucontext_get_ExtendedPC(ucontext_t *uc) { |
182 ExtendedPC os::Solaris::ucontext_get_ExtendedPC(const ucontext_t *uc) { |
183 address pc = (address)uc->uc_mcontext.gregs[REG_PC]; |
183 address pc = (address)uc->uc_mcontext.gregs[REG_PC]; |
184 // set npc to zero to avoid using it for safepoint, good for profiling only |
184 // set npc to zero to avoid using it for safepoint, good for profiling only |
185 return ExtendedPC(pc); |
185 return ExtendedPC(pc); |
186 } |
186 } |
187 |
187 |
189 uc->uc_mcontext.gregs [REG_PC] = (greg_t) pc; |
189 uc->uc_mcontext.gregs [REG_PC] = (greg_t) pc; |
190 uc->uc_mcontext.gregs [REG_nPC] = (greg_t) (pc + 4); |
190 uc->uc_mcontext.gregs [REG_nPC] = (greg_t) (pc + 4); |
191 } |
191 } |
192 |
192 |
193 // Assumes ucontext is valid |
193 // Assumes ucontext is valid |
194 intptr_t* os::Solaris::ucontext_get_sp(ucontext_t *uc) { |
194 intptr_t* os::Solaris::ucontext_get_sp(const ucontext_t *uc) { |
195 return (intptr_t*)((intptr_t)uc->uc_mcontext.gregs[REG_SP] + STACK_BIAS); |
195 return (intptr_t*)((intptr_t)uc->uc_mcontext.gregs[REG_SP] + STACK_BIAS); |
196 } |
196 } |
197 |
197 |
198 // Solaris X86 only |
198 // Solaris X86 only |
199 intptr_t* os::Solaris::ucontext_get_fp(ucontext_t *uc) { |
199 intptr_t* os::Solaris::ucontext_get_fp(const ucontext_t *uc) { |
200 ShouldNotReachHere(); |
200 ShouldNotReachHere(); |
201 return NULL; |
201 return NULL; |
202 } |
202 } |
203 |
203 |
204 address os::Solaris::ucontext_get_pc(ucontext_t *uc) { |
204 address os::Solaris::ucontext_get_pc(const ucontext_t *uc) { |
205 return (address) uc->uc_mcontext.gregs[REG_PC]; |
205 return (address) uc->uc_mcontext.gregs[REG_PC]; |
206 } |
206 } |
207 |
207 |
208 |
208 |
209 // For Forte Analyzer AsyncGetCallTrace profiling support - thread |
209 // For Forte Analyzer AsyncGetCallTrace profiling support - thread |
213 // |
213 // |
214 // The difference between this and os::fetch_frame_from_context() is that |
214 // The difference between this and os::fetch_frame_from_context() is that |
215 // here we try to skip nested signal frames. |
215 // here we try to skip nested signal frames. |
216 // This method is also used for stack overflow signal handling. |
216 // This method is also used for stack overflow signal handling. |
217 ExtendedPC os::Solaris::fetch_frame_from_ucontext(Thread* thread, |
217 ExtendedPC os::Solaris::fetch_frame_from_ucontext(Thread* thread, |
218 ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { |
218 const ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { |
219 |
219 |
220 assert(thread != NULL, "just checking"); |
220 assert(thread != NULL, "just checking"); |
221 assert(ret_sp != NULL, "just checking"); |
221 assert(ret_sp != NULL, "just checking"); |
222 assert(ret_fp == NULL, "just checking"); |
222 assert(ret_fp == NULL, "just checking"); |
223 |
223 |
224 ucontext_t *luc = os::Solaris::get_valid_uc_in_signal_handler(thread, uc); |
224 const ucontext_t *luc = os::Solaris::get_valid_uc_in_signal_handler(thread, uc); |
225 |
225 |
226 return os::fetch_frame_from_context(luc, ret_sp, ret_fp); |
226 return os::fetch_frame_from_context(luc, ret_sp, ret_fp); |
227 } |
227 } |
228 |
228 |
229 |
229 |
230 // ret_fp parameter is only used by Solaris X86. |
230 // ret_fp parameter is only used by Solaris X86. |
231 ExtendedPC os::fetch_frame_from_context(void* ucVoid, |
231 ExtendedPC os::fetch_frame_from_context(const void* ucVoid, |
232 intptr_t** ret_sp, intptr_t** ret_fp) { |
232 intptr_t** ret_sp, intptr_t** ret_fp) { |
233 |
233 |
234 ExtendedPC epc; |
234 ExtendedPC epc; |
235 ucontext_t *uc = (ucontext_t*)ucVoid; |
235 const ucontext_t *uc = (const ucontext_t*)ucVoid; |
236 |
236 |
237 if (uc != NULL) { |
237 if (uc != NULL) { |
238 epc = os::Solaris::ucontext_get_ExtendedPC(uc); |
238 epc = os::Solaris::ucontext_get_ExtendedPC(uc); |
239 if (ret_sp) *ret_sp = os::Solaris::ucontext_get_sp(uc); |
239 if (ret_sp) *ret_sp = os::Solaris::ucontext_get_sp(uc); |
240 } else { |
240 } else { |
244 } |
244 } |
245 |
245 |
246 return epc; |
246 return epc; |
247 } |
247 } |
248 |
248 |
249 frame os::fetch_frame_from_context(void* ucVoid) { |
249 frame os::fetch_frame_from_context(const void* ucVoid) { |
250 intptr_t* sp; |
250 intptr_t* sp; |
251 intptr_t* fp; |
251 intptr_t* fp; |
252 ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); |
252 ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); |
253 return frame(sp, frame::unpatchable, epc.pc()); |
253 return frame(sp, frame::unpatchable, epc.pc()); |
254 } |
254 } |
603 |
603 |
604 ShouldNotReachHere(); |
604 ShouldNotReachHere(); |
605 return false; |
605 return false; |
606 } |
606 } |
607 |
607 |
608 void os::print_context(outputStream *st, void *context) { |
608 void os::print_context(outputStream *st, const void *context) { |
609 if (context == NULL) return; |
609 if (context == NULL) return; |
610 |
610 |
611 ucontext_t *uc = (ucontext_t*)context; |
611 const ucontext_t *uc = (const ucontext_t*)context; |
612 st->print_cr("Registers:"); |
612 st->print_cr("Registers:"); |
613 |
613 |
614 st->print_cr(" G1=" INTPTR_FORMAT " G2=" INTPTR_FORMAT |
614 st->print_cr(" G1=" INTPTR_FORMAT " G2=" INTPTR_FORMAT |
615 " G3=" INTPTR_FORMAT " G4=" INTPTR_FORMAT, |
615 " G3=" INTPTR_FORMAT " G4=" INTPTR_FORMAT, |
616 uc->uc_mcontext.gregs[REG_G1], |
616 uc->uc_mcontext.gregs[REG_G1], |
680 address pc = epc.pc(); |
680 address pc = epc.pc(); |
681 st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); |
681 st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); |
682 print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); |
682 print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); |
683 } |
683 } |
684 |
684 |
685 void os::print_register_info(outputStream *st, void *context) { |
685 void os::print_register_info(outputStream *st, const void *context) { |
686 if (context == NULL) return; |
686 if (context == NULL) return; |
687 |
687 |
688 ucontext_t *uc = (ucontext_t*)context; |
688 const ucontext_t *uc = (const ucontext_t*)context; |
689 intptr_t *sp = (intptr_t *)os::Solaris::ucontext_get_sp(uc); |
689 intptr_t *sp = (intptr_t *)os::Solaris::ucontext_get_sp(uc); |
690 |
690 |
691 st->print_cr("Register to memory mapping:"); |
691 st->print_cr("Register to memory mapping:"); |
692 st->cr(); |
692 st->cr(); |
693 |
693 |