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

@@ -195,11 +195,11 @@
         mdb_tgt_gregset_t gregs;
         kreg_t *kregs = &gregs.kregs[0];
         int got_pc = (gsp->kregs[KREG_EIP] != 0);
         int err;
 
-        struct {
+        struct fr {
                 uintptr_t fr_savfp;
                 uintptr_t fr_savpc;
                 long fr_argv[32];
         } fr;
 

@@ -208,29 +208,22 @@
         uintptr_t lastfp = 0;
 
         ssize_t size;
         uint_t argc;
         int detect_exception_frames = 0;
+        int advance_tortoise = 1;
+        uintptr_t tortoise_fp = 0;
 #ifndef _KMDB
         int xp;
 
         if ((mdb_readsym(&xp, sizeof (xp), "xpv_panicking") != -1) && (xp > 0))
                 detect_exception_frames = 1;
 #endif
 
         bcopy(gsp, &gregs, sizeof (gregs));
 
         while (fp != 0) {
-
-                /*
-                 * Ensure progress (increasing fp), and prevent
-                 * endless loop with the same FP.
-                 */
-                if (fp <= lastfp) {
-                        err = EMDB_STKFRAME;
-                        goto badfp;
-                }
                 if (fp & (STACK_ALIGN - 1)) {
                         err = EMDB_STKALIGN;
                         goto badfp;
                 }
                 if ((size = mdb_tgt_vread(t, &fr, sizeof (fr), fp)) >=

@@ -240,10 +233,33 @@
                 } else {
                         err = EMDB_NOMAP;
                         goto badfp;
                 }
 
+                if (tortoise_fp == 0) {
+                        tortoise_fp = fp;
+                } else {
+                        if (advance_tortoise != 0) {
+                                struct fr tfr;
+
+                                if (mdb_tgt_vread(t, &tfr, sizeof (tfr),
+                                    tortoise_fp) != sizeof (tfr)) {
+                                        err = EMDB_NOMAP;
+                                        goto badfp;
+                                }
+
+                                tortoise_fp = tfr.fr_savfp;
+                        }
+
+                        if (fp == tortoise_fp) {
+                                err = EMDB_STKFRAME;
+                                goto badfp;
+                        }
+                }
+
+                advance_tortoise = !advance_tortoise;
+
                 if (got_pc && func(arg, pc, argc, fr.fr_argv, &gregs) != 0)
                         break;
 
                 kregs[KREG_ESP] = kregs[KREG_EBP];