//***   dbutil.cpp -- debug helpers
// DESCRIPTION
//  this file has the shared-source 'master' implementation.  it is
// #included in each DLL that uses it.
//  clients do something like:
//      #include "priv.h"   // for types, ASSERT, DM_*, DF_*, etc.
//      #include "../lib/dbutil.cpp"

#ifdef DEBUG // {

#if ( _X86_)

// warning: these macros assume we have an ebp-linked chain.  for debug we do.
#define BP_GETOLDBP(pbp)    (*((int *)(pbp) + 0))
#define BP_GETRET(pbp)      (*((int *)(pbp) + 1))

//***   DBGetStackBack -- walk stack frame
// #if 0 w/ sanity checks #endif
// ENTRY/EXIT
//  pfp         INOUT ptr to frame ptr (IN:starting, OUT:ending)
//  pstkback    OUT:fp/ret pairs, IN:optional size/addr pairs for sanity check
//  nstkback    ARRAYSIZE(pstckback)
//  #if 0
//  ncheck      # of IN pstkback size/addr sanity-check pairs
//  #endif
//  n           (return) # of frames successfully walked
// DESCRIPTION
//  fills in OUT pstckback w/ backtrace info for nstckback frames.
//  #if 0
//  if ncheck > 0, makes sure that initial backtrace entries are in the
//  range of the function specified by the IN size/addr pairs in pstkback.
//  #endif
// NOTES
//  not sure if we return the right pfp' value (untested)
int DBGetStackBack(int *pfp, struct DBstkback *pstkback, int nstkback /*,int nchk*/)
{
    int fp = *pfp;
    int ret;
    int i = 0;

    __try {
        for (; i < nstkback; i++, pstkback++) {
            ret = BP_GETRET(fp);
#if 0
            if (i < ncheck && pstkback->ret != 0) {
                ASSERT(pstkback->fp == 0 || pstkback->fp == -1 || pstkback->fp <= 512);
                if (!(pstkback->ret <= ret && ret <= pstkback->ret + pstkback->fp)) {
                    // constraint violated
                    break;
                }
            }
#endif
            fp = BP_GETOLDBP(fp);
            pstkback->ret = ret;
            pstkback->fp = fp;
        }
    }
    __except(EXCEPTION_EXECUTE_HANDLER) {
        TraceMsg(TF_ALWAYS, "atm: GPF");
        // just use last 'ret' we had
    }

    *pfp = fp;
    return i;
}

#endif
#endif // }
