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");) |
144 } |
144 } |
145 |
145 |
146 // We will only follow one level of uc_link since there are libthread |
146 // We will only follow one level of uc_link since there are libthread |
147 // issues with ucontext linking and it is better to be safe and just |
147 // issues with ucontext linking and it is better to be safe and just |
148 // let caller retry later. |
148 // let caller retry later. |
149 ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread, |
149 const ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread, |
150 ucontext_t *uc) { |
150 const ucontext_t *uc) { |
151 |
151 |
152 ucontext_t *retuc = NULL; |
152 const ucontext_t *retuc = NULL; |
153 |
153 |
154 if (uc != NULL) { |
154 if (uc != NULL) { |
155 if (uc->uc_link == NULL) { |
155 if (uc->uc_link == NULL) { |
156 // cannot validate without uc_link so accept current ucontext |
156 // cannot validate without uc_link so accept current ucontext |
157 retuc = uc; |
157 retuc = uc; |
169 } |
169 } |
170 return retuc; |
170 return retuc; |
171 } |
171 } |
172 |
172 |
173 // Assumes ucontext is valid |
173 // Assumes ucontext is valid |
174 ExtendedPC os::Solaris::ucontext_get_ExtendedPC(ucontext_t *uc) { |
174 ExtendedPC os::Solaris::ucontext_get_ExtendedPC(const ucontext_t *uc) { |
175 return ExtendedPC((address)uc->uc_mcontext.gregs[REG_PC]); |
175 return ExtendedPC((address)uc->uc_mcontext.gregs[REG_PC]); |
176 } |
176 } |
177 |
177 |
178 void os::Solaris::ucontext_set_pc(ucontext_t* uc, address pc) { |
178 void os::Solaris::ucontext_set_pc(ucontext_t* uc, address pc) { |
179 uc->uc_mcontext.gregs [REG_PC] = (greg_t) pc; |
179 uc->uc_mcontext.gregs [REG_PC] = (greg_t) pc; |
180 } |
180 } |
181 |
181 |
182 // Assumes ucontext is valid |
182 // Assumes ucontext is valid |
183 intptr_t* os::Solaris::ucontext_get_sp(ucontext_t *uc) { |
183 intptr_t* os::Solaris::ucontext_get_sp(const ucontext_t *uc) { |
184 return (intptr_t*)uc->uc_mcontext.gregs[REG_SP]; |
184 return (intptr_t*)uc->uc_mcontext.gregs[REG_SP]; |
185 } |
185 } |
186 |
186 |
187 // Assumes ucontext is valid |
187 // Assumes ucontext is valid |
188 intptr_t* os::Solaris::ucontext_get_fp(ucontext_t *uc) { |
188 intptr_t* os::Solaris::ucontext_get_fp(const ucontext_t *uc) { |
189 return (intptr_t*)uc->uc_mcontext.gregs[REG_FP]; |
189 return (intptr_t*)uc->uc_mcontext.gregs[REG_FP]; |
190 } |
190 } |
191 |
191 |
192 address os::Solaris::ucontext_get_pc(ucontext_t *uc) { |
192 address os::Solaris::ucontext_get_pc(const ucontext_t *uc) { |
193 return (address) uc->uc_mcontext.gregs[REG_PC]; |
193 return (address) uc->uc_mcontext.gregs[REG_PC]; |
194 } |
194 } |
195 |
195 |
196 // For Forte Analyzer AsyncGetCallTrace profiling support - thread |
196 // For Forte Analyzer AsyncGetCallTrace profiling support - thread |
197 // is currently interrupted by SIGPROF. |
197 // is currently interrupted by SIGPROF. |
198 // |
198 // |
199 // The difference between this and os::fetch_frame_from_context() is that |
199 // The difference between this and os::fetch_frame_from_context() is that |
200 // here we try to skip nested signal frames. |
200 // here we try to skip nested signal frames. |
201 // This method is also used for stack overflow signal handling. |
201 // This method is also used for stack overflow signal handling. |
202 ExtendedPC os::Solaris::fetch_frame_from_ucontext(Thread* thread, |
202 ExtendedPC os::Solaris::fetch_frame_from_ucontext(Thread* thread, |
203 ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { |
203 const ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { |
204 |
204 |
205 assert(thread != NULL, "just checking"); |
205 assert(thread != NULL, "just checking"); |
206 assert(ret_sp != NULL, "just checking"); |
206 assert(ret_sp != NULL, "just checking"); |
207 assert(ret_fp != NULL, "just checking"); |
207 assert(ret_fp != NULL, "just checking"); |
208 |
208 |
209 ucontext_t *luc = os::Solaris::get_valid_uc_in_signal_handler(thread, uc); |
209 const ucontext_t *luc = os::Solaris::get_valid_uc_in_signal_handler(thread, uc); |
210 return os::fetch_frame_from_context(luc, ret_sp, ret_fp); |
210 return os::fetch_frame_from_context(luc, ret_sp, ret_fp); |
211 } |
211 } |
212 |
212 |
213 ExtendedPC os::fetch_frame_from_context(void* ucVoid, |
213 ExtendedPC os::fetch_frame_from_context(const void* ucVoid, |
214 intptr_t** ret_sp, intptr_t** ret_fp) { |
214 intptr_t** ret_sp, intptr_t** ret_fp) { |
215 |
215 |
216 ExtendedPC epc; |
216 ExtendedPC epc; |
217 ucontext_t *uc = (ucontext_t*)ucVoid; |
217 const ucontext_t *uc = (const ucontext_t*)ucVoid; |
218 |
218 |
219 if (uc != NULL) { |
219 if (uc != NULL) { |
220 epc = os::Solaris::ucontext_get_ExtendedPC(uc); |
220 epc = os::Solaris::ucontext_get_ExtendedPC(uc); |
221 if (ret_sp) *ret_sp = os::Solaris::ucontext_get_sp(uc); |
221 if (ret_sp) *ret_sp = os::Solaris::ucontext_get_sp(uc); |
222 if (ret_fp) *ret_fp = os::Solaris::ucontext_get_fp(uc); |
222 if (ret_fp) *ret_fp = os::Solaris::ucontext_get_fp(uc); |
772 |
772 |
773 ShouldNotReachHere(); |
773 ShouldNotReachHere(); |
774 return false; |
774 return false; |
775 } |
775 } |
776 |
776 |
777 void os::print_context(outputStream *st, void *context) { |
777 void os::print_context(outputStream *st, const void *context) { |
778 if (context == NULL) return; |
778 if (context == NULL) return; |
779 |
779 |
780 ucontext_t *uc = (ucontext_t*)context; |
780 const ucontext_t *uc = (const ucontext_t*)context; |
781 st->print_cr("Registers:"); |
781 st->print_cr("Registers:"); |
782 #ifdef AMD64 |
782 #ifdef AMD64 |
783 st->print( "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]); |
783 st->print( "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]); |
784 st->print(", RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]); |
784 st->print(", RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]); |
785 st->print(", RCX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RCX]); |
785 st->print(", RCX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RCX]); |
831 address pc = epc.pc(); |
831 address pc = epc.pc(); |
832 st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); |
832 st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); |
833 print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); |
833 print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); |
834 } |
834 } |
835 |
835 |
836 void os::print_register_info(outputStream *st, void *context) { |
836 void os::print_register_info(outputStream *st, const void *context) { |
837 if (context == NULL) return; |
837 if (context == NULL) return; |
838 |
838 |
839 ucontext_t *uc = (ucontext_t*)context; |
839 const ucontext_t *uc = (const ucontext_t*)context; |
840 |
840 |
841 st->print_cr("Register to memory mapping:"); |
841 st->print_cr("Register to memory mapping:"); |
842 st->cr(); |
842 st->cr(); |
843 |
843 |
844 // this is horrendously verbose but the layout of the registers in the |
844 // this is horrendously verbose but the layout of the registers in the |