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

@@ -206,11 +206,11 @@
         long fr_argv[32];
         int start_index; /* index to save_instr where to start comparison */
         int err;
         int i;
 
-        struct {
+        struct fr {
                 uintptr_t fr_savfp;
                 uintptr_t fr_savpc;
         } fr;
 
         uintptr_t fp = gsp->kregs[KREG_RBP];

@@ -223,10 +223,12 @@
 
         GElf_Sym s;
         mdb_syminfo_t sip;
         mdb_ctf_funcinfo_t mfp;
         int xpv_panic = 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))
                 xpv_panic = 1;

@@ -235,23 +237,38 @@
         bcopy(gsp, &gregs, sizeof (gregs));
 
         while (fp != 0) {
                 int args_style = 0;
 
-                /*
-                 * Ensure progress (increasing fp), and prevent
-                 * endless loop with the same FP.
-                 */
-                if (fp <= lastfp) {
-                        err = EMDB_STKFRAME;
+                if (mdb_tgt_vread(t, &fr, sizeof (fr), fp) != sizeof (fr)) {
+                        err = EMDB_NOMAP;
                         goto badfp;
                 }
-                if (mdb_tgt_vread(t, &fr, sizeof (fr), fp) != sizeof (fr)) {
+
+                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 ((mdb_tgt_lookup_by_addr(t, pc, MDB_TGT_SYM_FUZZY,
                     NULL, 0, &s, &sip) == 0) &&
                     (mdb_ctf_func_info(&s, &sip, &mfp) == 0)) {
                         int return_type = mdb_ctf_type_kind(mfp.mtf_return);
                         mdb_ctf_id_t args_types[5];