Print this page
5554 kmdb can't trace stacks that begin within itself
Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>


 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;