180 case M_ADD_IMM8:
181 n = ins[2];
182 break;
183
184 default:
185 n = 0;
186 }
187
188 return (MIN((ssize_t)n, size) / sizeof (long));
189 }
190
191 int
192 mdb_ia32_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp,
193 mdb_tgt_stack_f *func, void *arg)
194 {
195 mdb_tgt_gregset_t gregs;
196 kreg_t *kregs = &gregs.kregs[0];
197 int got_pc = (gsp->kregs[KREG_EIP] != 0);
198 int err;
199
200 struct {
201 uintptr_t fr_savfp;
202 uintptr_t fr_savpc;
203 long fr_argv[32];
204 } fr;
205
206 uintptr_t fp = gsp->kregs[KREG_EBP];
207 uintptr_t pc = gsp->kregs[KREG_EIP];
208 uintptr_t lastfp = 0;
209
210 ssize_t size;
211 uint_t argc;
212 int detect_exception_frames = 0;
213 #ifndef _KMDB
214 int xp;
215
216 if ((mdb_readsym(&xp, sizeof (xp), "xpv_panicking") != -1) && (xp > 0))
217 detect_exception_frames = 1;
218 #endif
219
220 bcopy(gsp, &gregs, sizeof (gregs));
221
222 while (fp != 0) {
223
224 /*
225 * Ensure progress (increasing fp), and prevent
226 * endless loop with the same FP.
227 */
228 if (fp <= lastfp) {
229 err = EMDB_STKFRAME;
230 goto badfp;
231 }
232 if (fp & (STACK_ALIGN - 1)) {
233 err = EMDB_STKALIGN;
234 goto badfp;
235 }
236 if ((size = mdb_tgt_vread(t, &fr, sizeof (fr), fp)) >=
237 (ssize_t)(2 * sizeof (uintptr_t))) {
238 size -= (ssize_t)(2 * sizeof (uintptr_t));
239 argc = kvm_argcount(t, fr.fr_savpc, size);
240 } else {
241 err = EMDB_NOMAP;
242 goto badfp;
243 }
244
245 if (got_pc && func(arg, pc, argc, fr.fr_argv, &gregs) != 0)
246 break;
247
248 kregs[KREG_ESP] = kregs[KREG_EBP];
249
250 lastfp = fp;
251 fp = fr.fr_savfp;
252 /*
253 * The Xen hypervisor marks a stack frame as belonging to
254 * an exception by inverting the bits of the pointer to
255 * that frame. We attempt to identify these frames by
256 * inverting the pointer and seeing if it is within 0xfff
257 * bytes of the last frame.
258 */
259 if (detect_exception_frames)
260 if ((fp != 0) && (fp < lastfp) &&
261 ((lastfp ^ ~fp) < 0xfff))
262 fp = ~fp;
263
264 kregs[KREG_EBP] = fp;
|
180 case M_ADD_IMM8:
181 n = ins[2];
182 break;
183
184 default:
185 n = 0;
186 }
187
188 return (MIN((ssize_t)n, size) / sizeof (long));
189 }
190
191 int
192 mdb_ia32_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp,
193 mdb_tgt_stack_f *func, void *arg)
194 {
195 mdb_tgt_gregset_t gregs;
196 kreg_t *kregs = &gregs.kregs[0];
197 int got_pc = (gsp->kregs[KREG_EIP] != 0);
198 int err;
199
200 struct fr {
201 uintptr_t fr_savfp;
202 uintptr_t fr_savpc;
203 long fr_argv[32];
204 } fr;
205
206 uintptr_t fp = gsp->kregs[KREG_EBP];
207 uintptr_t pc = gsp->kregs[KREG_EIP];
208 uintptr_t lastfp = 0;
209
210 ssize_t size;
211 uint_t argc;
212 int detect_exception_frames = 0;
213 int advance_tortoise = 1;
214 uintptr_t tortoise_fp = 0;
215 #ifndef _KMDB
216 int xp;
217
218 if ((mdb_readsym(&xp, sizeof (xp), "xpv_panicking") != -1) && (xp > 0))
219 detect_exception_frames = 1;
220 #endif
221
222 bcopy(gsp, &gregs, sizeof (gregs));
223
224 while (fp != 0) {
225 if (fp & (STACK_ALIGN - 1)) {
226 err = EMDB_STKALIGN;
227 goto badfp;
228 }
229 if ((size = mdb_tgt_vread(t, &fr, sizeof (fr), fp)) >=
230 (ssize_t)(2 * sizeof (uintptr_t))) {
231 size -= (ssize_t)(2 * sizeof (uintptr_t));
232 argc = kvm_argcount(t, fr.fr_savpc, size);
233 } else {
234 err = EMDB_NOMAP;
235 goto badfp;
236 }
237
238 if (tortoise_fp == 0) {
239 tortoise_fp = fp;
240 } else {
241 if (advance_tortoise != 0) {
242 struct fr tfr;
243
244 if (mdb_tgt_vread(t, &tfr, sizeof (tfr),
245 tortoise_fp) != sizeof (tfr)) {
246 err = EMDB_NOMAP;
247 goto badfp;
248 }
249
250 tortoise_fp = tfr.fr_savfp;
251 }
252
253 if (fp == tortoise_fp) {
254 err = EMDB_STKFRAME;
255 goto badfp;
256 }
257 }
258
259 advance_tortoise = !advance_tortoise;
260
261 if (got_pc && func(arg, pc, argc, fr.fr_argv, &gregs) != 0)
262 break;
263
264 kregs[KREG_ESP] = kregs[KREG_EBP];
265
266 lastfp = fp;
267 fp = fr.fr_savfp;
268 /*
269 * The Xen hypervisor marks a stack frame as belonging to
270 * an exception by inverting the bits of the pointer to
271 * that frame. We attempt to identify these frames by
272 * inverting the pointer and seeing if it is within 0xfff
273 * bytes of the last frame.
274 */
275 if (detect_exception_frames)
276 if ((fp != 0) && (fp < lastfp) &&
277 ((lastfp ^ ~fp) < 0xfff))
278 fp = ~fp;
279
280 kregs[KREG_EBP] = fp;
|