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];