home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sd386v50.zip / sd386src.zip / XSRVUNWD.C < prev    next >
Text File  |  1996-02-05  |  66KB  |  958 lines

  1. /*****************************************************************************/
  2. /* File:                                             IBM INTERNAL USE ONLY   */
  3. /*   xsrvunwd.c                                                              */
  4. /*                                                                           */
  5. /* Description:                                                              */
  6. /*                                                                           */
  7. /*   Start the debuggee.                                                     */
  8. /*                                                                           */
  9. /* History:                                                                  */
  10. /*                                                                           */
  11. /*   07/01/93 Created.                                                       */
  12. /*                                                                           */
  13. /*...                                                                        */
  14. /*... 06/04/93  827   Joe       Add remote debug support.                    */
  15. /*...                                                                        */
  16. /*****************************************************************************/
  17. #include "all.h"
  18.  
  19. #define ROLLBACK        300
  20. #define NEARRET         1
  21. #define FARRET          0
  22. #define ATR32           0xD0            /* stack frame is 32-bit          107*/
  23. #define ATR16           0x00            /* stack frame 1s 16-bit          107*/
  24. #define NUM_FRAME_BYTES 12              /* bumped to 12.                  706*/
  25. /*****************************************************************************/
  26. /* SetActFrames()                                                            */
  27. /*                                                                           */
  28. /* Description:                                                              */
  29. /*  1. Establishes the following arrays for the current state of the user's  */
  30. /*     stack:                                                                */
  31. /*                                                                           */
  32. /*      ActFaddrs[]   the CS:IP or EIP values for the stack frames        107*/
  33. /*      ActCSAtrs[]   0 => 16-bit stack frame  1 => 32-bit stack frame    107*/
  34. /*      ActFlines[][] the mid/lno values for the CS:IP/EIP return values  107*/
  35. /*      ActScopes[]   pointers to SSProc records for the frame CS:IP/EIP vals*/
  36. /*      ActFrames[]   offsets in the stack of the stack frames ( EBP values )*/
  37. /*                                                                           */
  38. /* Parameters:                                                               */
  39. /*   none                                                                    */
  40. /*                                                                           */
  41. /* Return:                                                                   */
  42. /*   none                                                                    */
  43. /*                                                                           */
  44. /* Assumptions:                                                              */
  45. /*                                                                           */
  46. /*    This routine has to guarantee the above arrays are valid. "Valid"      */
  47. /*    implies, for example, that ActFaddrs contains valid addresses          */
  48. /*    in the application code.                                               */
  49. /*                                                                           */
  50. /*****************************************************************************/
  51. ULONG XSrvGetCallStack(STACK_PARMS *pparms,
  52.                        UCHAR       **ppActCSAtrs,
  53.                        UINT        **ppActFrames,
  54.                        UINT        **ppActFaddrs )
  55.  
  56. {                                       /*                                   */
  57.  int      n;                            /* stack frame index                 */
  58.  uint     limit;                        /* top of stack not including Exec...*/
  59.  uint     frame;                        /* stack frame offset                */
  60.  ushort   SS;                           /* SS selector value                 */
  61.  ushort   CS;                           /* CS part of CS:IP on stack      107*/
  62.  ushort   IP;                           /* IP part of CS:IP on stack      107*/
  63.  uint     EIP;                          /* EIP on stack                   107*/
  64.  uint    *fptr;                         /* pointer to stack frame            */
  65.  uint     lframe[NUM_FRAME_BYTES/2];    /* local copy of stack frame      107*/
  66.  uint     bytesread;                    /* bytes read from user addr space521*/
  67.  int      ret;                          /* Far or Near return flag.          */
  68.  ushort   ReturnCS;                     /* stack frame return CS          107*/
  69.  ULONG    FlatCSIP;                     /* frame CS:IP as a flat addr     107*/
  70.  uchar    SSAtr;                        /* current frame's 16/32-bit stat 107*/
  71.  ushort   BP;                           /* BP part of stack frame         107*/
  72.  uint     PrevFrame;                    /* previous frame location.       706*/
  73.  
  74.  USHORT   AppPTB_CS;
  75.  USHORT   AppPTB_SS;
  76.  ULONG    AppPTB_EBP;
  77.  ULONG    AppPTB_ESP;
  78.  UCHAR    AppPTB_SSAtr;
  79.  int      ShowAllFlag;
  80.  int      ShowNamedFlag = FALSE;
  81.  UINT     NActFrames;
  82.  UCHAR    ActCSAtrs[MAXAFRAMES];        /* 0=>16-bit frame 1=>32-bit         */
  83.  UINT     ActFrames[MAXAFRAMES];        /* value of frame pointer (bp)       */
  84.  UINT     ActFaddrs[MAXAFRAMES];        /* value of return "EIP" on stack    */
  85.  UCHAR   *pActCSAtrs = NULL;
  86.  UINT    *pActFrames = NULL;
  87.  UINT    *pActFaddrs = NULL;
  88.  BOOL     Initial_EBP_Ok;
  89.  
  90.  /****************************************************************************/
  91.  /* - pull off the unwind values.                                            */
  92.  /****************************************************************************/
  93.  AppPTB_CS    = pparms->CS;
  94.  AppPTB_SS    = pparms->SS;
  95.  AppPTB_EBP   = pparms->EBP;
  96.  AppPTB_ESP   = pparms->ESP;
  97.  AppPTB_SSAtr = pparms->SSAtr;
  98.  ShowAllFlag  = pparms->ShowAllFlag;
  99.  
  100.  /****************************************************************************/
  101.  /* - Sometimes we might stop within optimized code or assembler code        */
  102.  /*   where the EBP may have been used for a general purpose register.       */
  103.  /*   When this happens, the call stack unwinding can't get started.  So,    */
  104.  /*   we run a verification check on the initial EBP and if it fails, we     */
  105.  /*   try to scan the stack looking for a valid link in the EBP chain.       */
  106.  /****************************************************************************/
  107.  Initial_EBP_Ok = FALSE;
  108.  if( IsValid_EBP(AppPTB_EBP) == TRUE )
  109.   Initial_EBP_Ok = TRUE;
  110.  
  111.  if( (AppPTB_SSAtr == ATR32) && (Initial_EBP_Ok == FALSE) )
  112.  /****************************************************************************/
  113.  /*                                                                          */
  114.  /* - If the initial EBP is invalid, then start scanning the stack looking   */
  115.  /*   for a valid link in the EBP chain defined like so:                     */
  116.  /*                                                                          */
  117.  /*                ----------------         ----------------                 */
  118.  /*  Initial EBP->| Next EBP       |------>| xxxxxxxxxxxxxxx|-->             */
  119.  /*                ----------------         ----------------                 */
  120.  /*               | 32 bit eip ret |       | 32 bit eip ret |                */
  121.  /*                ----------------         ----------------                 */
  122.  /*               | 32 bit eip ret |       | 32 bit eip ret |                */
  123.  /*                ----------------         ----------------                 */
  124.  /*                                                                          */
  125.  /* - Note that a 32 bit eip return in either of the stack addresses above   */
  126.  /*   EBP is considered valid.                                               */
  127.  /*                                                                          */
  128.  /****************************************************************************/
  129.  {
  130.   #define BIT32_STACK_WIDTH    4
  131.   #define MAX_STACK_ITERATIONS 100
  132.  
  133.   BOOL   Next_EBP_Ok;
  134.  
  135.   ULONG  StackAddress;
  136.   ULONG  NextStackAddress;
  137.   int    i;
  138.   UCHAR *pNext_EBP_Buffer;
  139.  
  140.   Initial_EBP_Ok = FALSE;
  141.   Next_EBP_Ok    = FALSE;
  142.   StackAddress   = AppPTB_ESP;
  143.  
  144.   for( i = 1; i <= MAX_STACK_ITERATIONS ; i++ )
  145.   {
  146.    /**************************************************************************/
  147.    /* - verify the first stack frame.                                        */
  148.    /**************************************************************************/
  149.    if( IsValid_EBP( StackAddress ) == TRUE )
  150.     Initial_EBP_Ok = TRUE;
  151.  
  152.    /**************************************************************************/
  153.    /* - verify the next stack frame.                                         */
  154.    /**************************************************************************/
  155.    Next_EBP_Ok = FALSE;
  156.    if( Initial_EBP_Ok == TRUE )
  157.    {
  158.     pNext_EBP_Buffer = Getnbytes( StackAddress, BIT32_STACK_WIDTH, &bytesread);
  159.     NextStackAddress = *(ULONG *)pNext_EBP_Buffer;
  160.  
  161.     Next_EBP_Ok      = FALSE;
  162.  
  163.     if( IsValid_EBP( NextStackAddress ) == TRUE )
  164.     {
  165.      Next_EBP_Ok = TRUE;
  166.      break;
  167.     }
  168.    }
  169.  
  170.    StackAddress += BIT32_STACK_WIDTH;
  171.   }
  172.   /***************************************************************************/
  173.   /* - if we were successful, then update the EBP with its starting value.   */
  174.   /***************************************************************************/
  175.   if( Next_EBP_Ok == TRUE )
  176.    AppPTB_EBP = StackAddress;
  177.  }
  178.  
  179.  /****************************************************************************/
  180.  /* - Now, we're ready to start the unwind algorithm.                        */
  181.  /* - AppPTB_EBP will be the value from the DosDebug registers, or           */
  182.  /*   it will be the seed value determined from the above seeding algorithm  */
  183.  /*   for a 32 bit stack.                                                    */
  184.  /****************************************************************************/
  185.  ReturnCS=AppPTB_CS;                    /* initialize stack return CS     107*/
  186.  BP=(ushort)AppPTB_EBP;                 /* saves a union!                 107*/
  187.  if( (AppPTB_EBP && AppPTB_SSAtr) ||    /* if there is a stack frame ...  107*/
  188.      (BP         && !AppPTB_SSAtr))
  189.   {
  190.    limit = frame = AppPTB_EBP;          /* assume 32-bit current stack    107*/
  191.    if ( !AppPTB_SSAtr )                 /* 16-bit current stack ?         107*/
  192.     limit = frame = (uint)Sys_SelOff2Flat(AppPTB_SS,BP);
  193.  
  194.    SSAtr = AppPTB_SSAtr;                /* init stack frame 16/32-bit stat107*/
  195.                                         /* begin stack frame scan            */
  196.    for( n=0 ;                           /* initialeze the frame index        */
  197.         n < MAXAFRAMES ;                /* proceed to oldest frame or max    */
  198.         ++n                             /* bump frame index                  */
  199.       )                                 /*                                   */
  200.     {                                   /* current ss:bp+2->0th cs:ip        */
  201.                                         /*         (SS:EBP+4->0th EIP)    107*/
  202.      /************************************************************************/
  203.      /*                                                                      */
  204.      /*  1. Get the return address from the stack. It may be a near          */
  205.      /*     return( IP ) or a far return( CS:IP ) on the 16-bit stack frame. */
  206.      /*     It may be a flat address return (EIP) on the 32-bit stack frame. */
  207.      /*     It may be a thunk return!                                        */
  208.      /*                                                                      */
  209.      /************************************************************************/
  210.      fptr = (uint *)Getnbytes(frame,    /* get BP/IP/CS, BP/IP, | EBP/EIP 827*/
  211.                               NUM_FRAME_BYTES,
  212.                               &bytesread);
  213.      if ( bytesread != NUM_FRAME_BYTES )/* did we get something back ?    521*/
  214.       break;                            /* if not then forget it          107*/
  215.      memcpy( lframe, fptr, NUM_FRAME_BYTES ); /* make local copy of frame 107*/
  216.      ActCSAtrs[n]=SSAtr;                /* assume new frame same as old   107*/
  217.      if ( SSAtr )                       /* curr frame 32-bit ?            107*/
  218.      {                                                                  /*706*/
  219.       #define MAXITER 2                                                 /*706*/
  220.       int iter;                                                         /*706*/
  221.       int foundit = FALSE;                                              /*706*/
  222.                                                                         /*706*/
  223.       /*******************************************************************706*/
  224.       /* - When C-set2 makes a 32-16 call, then the 32 bit function       706*/
  225.       /*   containing the call has a call in the prolog to check if       706*/
  226.       /*   there is enough stack space to execute the 16 bit function.    706*/
  227.       /*   If there isn't, then the stack gets moved.                     706*/
  228.       /*******************************************************************706*/
  229.       for( iter=1;!foundit && iter <= MAXITER; iter++)                  /*706*/
  230.       {                                                                 /*706*/
  231.                                                                         /*706*/
  232.        EIP = *(lframe+iter);             /* define EIP                  /*706*/
  233.        if ( !IsNearReturn( EIP, (ushort)1 ) )                           /*827*/
  234.         continue;                                                       /*706*/
  235.        foundit = TRUE;                                                  /*706*/
  236.       }                                                                 /*706*/
  237.                                                                         /*706*/
  238.       if( foundit == FALSE )                                            /*706*/
  239.       {                                                                 /*706*/
  240.        int StackSwitch = TRUE;                                          /*706*/
  241. /*------------------------------------------------------------------------706*/
  242.        if( (ShowAllFlag == TRUE) || (ShowNamedFlag == TRUE) )           /*706*/
  243.        {                                                                /*706*/
  244.         /*********************************************************************/
  245.         /*                                                                706*/
  246.         /* - Before we switch to a 16 bit stack let's first check to      706*/
  247.         /*   see if the chain continues but the eip is just bad. This can 706*/
  248.         /*   happen in the case of an exception handler. A typical example706*/
  249.         /*   might look like so:                                          706*/
  250.         /*                                                                706*/
  251.         /* 0x22AC4->0X22AF4->0X22B4C->0X22C64->0X22DDC->0X22E1C->0X22E38->0  */
  252.         /*          1A02C5EA 1A02C28C 1A02C0FA 0000000  010062   104B2    706*/
  253.         /*                                     |                          706*/
  254.         /*                                      - bad eip                 706*/
  255.         /*                                                                706*/
  256.         /*****************************************************************706*/
  257.         {                                                               /*706*/
  258.          uint  nframe[2];                                               /*706*/
  259.          uint *p;                                                       /*706*/
  260.                                                                         /*706*/
  261.          p = (uint *)Getnbytes(*lframe,8,&bytesread );                  /*827*/
  262.          if( bytesread < 8 )                                            /*706*/
  263.           goto skipit;                                                  /*706*/
  264.          memcpy(nframe,p,8);                                            /*706*/
  265.          EIP = *(nframe + 1);                                           /*706*/
  266.          if ( IsNearReturn( EIP, (ushort)1 ) )                          /*827*/
  267.          {                                                              /*706*/
  268.           foundit = TRUE;                                               /*706*/
  269.           StackSwitch = FALSE;                                          /*706*/
  270.           memcpy(lframe,nframe,8);                                      /*706*/
  271.          }                                                              /*706*/
  272.         }                                                               /*706*/
  273.                                                                         /*706*/
  274. skipit:                                                                 /*706*/
  275.         if( foundit == FALSE )                                          /*706*/
  276.         {                                                               /*706*/
  277.          /********************************************************************/
  278.          /* Well, let's try one final brute force technique.              706*/
  279.          /*                                                               706*/
  280.          /********************************************************************/
  281.          {                                                              /*706*/
  282.           #define STACK_WORDS 50                                        /*706*/
  283.           ushort *ptr;                                                  /*706*/
  284.           ushort  lclstack[STACK_WORDS];                                /*706*/
  285.           int     nbytes;                                               /*706*/
  286.           ushort *lclframe;                                             /*706*/
  287.                                                                         /*706*/
  288.           /*******************************************************************/
  289.           /* now get a chunk of the stack and make it local.              706*/
  290.           /*******************************************************************/
  291. /*827*/   ptr =(ushort *)Getnbytes(frame,STACK_WORDS*sizeof(short),&bytesread);
  292.           if ( bytesread < 6 )                                          /*706*/
  293.            break;    /* break out of the big for{} */                   /*706*/
  294.           memcpy( lclstack, ptr , bytesread );                          /*706*/
  295.           lclframe = lclstack;                                          /*706*/
  296.                                                                         /*706*/
  297.           /*******************************************************************/
  298.           /* Scoot down through the stack until we find a CS:IP that      706*/
  299.           /* was generated by a far call. This will be our "prospective"  706*/
  300.           /* frame.                                                       706*/
  301.           /*******************************************************************/
  302.           SS = Flat2Sel(frame);                                         /*706*/
  303.           for(nbytes = 6; (nbytes <= bytesread); lclframe++,nbytes += 2)/*706*/
  304.           {                                                             /*706*/
  305.            IP = *(lclframe+1);                                          /*706*/
  306.            CS = *(lclframe+2);                                          /*706*/
  307.            FlatCSIP=Sys_SelOff2Flat( CS ,IP );                         /*706*/
  308.                                                                         /*706*/
  309.            if ( IsFarReturn(FlatCSIP ) )                                /*827*/
  310.            {                                                            /*706*/
  311.             ushort  NextIP;                                             /*706*/
  312.             ushort  NextCS;                                             /*706*/
  313.             uint    NextFlatCSIP;                                       /*706*/
  314.             uint    numbytes;                                           /*706*/
  315.             ushort nextlclframe[3];                                     /*706*/
  316.                                                                         /*706*/
  317.             /*****************************************************************/
  318.             /* Now, let's take our "prospective" frame and see if it      706*/
  319.             /* is linked to another frame. If it is, then we continue     706*/
  320.             /* unwinding from our "prospective" frame.                    706*/
  321.             /*****************************************************************/
  322.             BP = *lclframe;                                             /*706*/
  323. /*827*/     ptr = (ushort *)Getnbytes((uint)Sys_SelOff2Flat(SS,BP),6,&numbytes);
  324.             if( numbytes != 6 )                                         /*706*/
  325.              continue;                                                  /*706*/
  326.             memcpy(nextlclframe,ptr,6);                                 /*706*/
  327.                                                                         /*706*/
  328.             NextIP = *(nextlclframe+1);                                 /*706*/
  329.             NextCS = *(nextlclframe+2);                                 /*706*/
  330.             NextFlatCSIP=Sys_SelOff2Flat( NextCS ,NextIP );            /*706*/
  331.                                                                         /*706*/
  332.             if (  IsFarReturn(NextFlatCSIP ) )                          /*827*/
  333.             {                                                           /*706*/
  334.              frame = frame + (uint)( (lclframe-lclstack)*sizeof(short));/*706*/
  335.              memcpy( lframe, lclframe, 6 );                             /*706*/
  336.              break;                                                     /*706*/
  337.             }                                                           /*706*/
  338.            }  /* end of test for look ahead frame.                */    /*706*/
  339.           }   /* end of loop to scan stack looking for next frame.*/    /*706*/
  340.          }    /* end of code block for generic 16-32 thunk.       */    /*706*/
  341.         }     /* end of test for generic 16-32 thunk.             */    /*706*/
  342.        }      /* end of ShowAllFlag tests.                        */    /*706*/
  343. /*------------------------------------------------------------------------706*/
  344.        /**********************************************************************/
  345.        /* - When we get here, we will just switch the stack to 16 bit if  706*/
  346.        /*   the ShowAllFlag was not set.                                  706*/
  347.        /* - If the ShowAllFlag was set then the two additional tests will 706*/
  348.        /*   have set up the stack frame for continuing the unwind.        706*/
  349.        /* - If the ShowAllFlag was set and neither test found a frame,    706*/
  350.        /*   then we fall into default processing as if the tests had      706*/
  351.        /*   not been run.                                                 706*/
  352.        /******************************************************************706*/
  353.        if( StackSwitch == TRUE )                                        /*706*/
  354.        {                                                                /*706*/
  355.         ActCSAtrs[n]=ATR16;                                             /*706*/
  356.         SSAtr=ATR16;                                                    /*706*/
  357.         goto stack16;                                                   /*706*/
  358.        }                                                                /*706*/
  359.       }                                                                 /*706*/
  360.  
  361.       ActFaddrs[n] = EIP;               /* stuff EIP value into ActFaddrs 107*/
  362.       frame = *lframe;                  /* define new frame               107*/
  363.      }                                  /* end curr frame 32-bit          107*/
  364.      else                               /* curr frame is 16-bit           107*/
  365.      {
  366. stack16:
  367.       SS = Flat2Sel(frame);             /* stack selector for 16-bit      107*/
  368.       BP = (ushort)*lframe;             /* define BP from stack           107*/
  369.       IP = *((ushort*)lframe+1);        /* define IP from stack           107*/
  370.       CS = *((ushort*)lframe+2);        /* define CS from stack           107*/
  371.       PrevFrame = frame;                /* hold on to previos frame loc.  706*/
  372.       frame = (uint)Sys_SelOff2Flat( SS , BP ); /* define new frame          107*/
  373.  
  374.       ret = NEARRET;                    /* assume near return on stack.      */
  375.       FlatCSIP=Sys_SelOff2Flat( CS ,IP ); /* trial return flat addr607*/
  376.       if (                              /* addr valid and                 827*/
  377.            IsFarReturn( FlatCSIP ) )    /* this a 16-bit far return ?     827*/
  378.        ret = FARRET;
  379.  
  380.       /***********************************************************************/
  381.       /* At this point, we have determined the return type of the stack      */
  382.       /* frame address.  Now, if the return is near, then this frame was     */
  383.       /* run in the CS of a previous frame with a far return.  By            */
  384.       /* previous, I mean a frame that we have already unwound.  If it's a   */
  385.       /* far return, then we update the CS that subsequent nodes were run in.*/
  386.       /*                                                                     */
  387.       /***********************************************************************/
  388.       if( ret == NEARRET )
  389.       {
  390.        /**********************************************************************/
  391.        /* Test the return address to see if it was generated by a 16 bit     */
  392.        /* near call.                                                         */
  393.        /**********************************************************************/
  394.        CS=ReturnCS;                                                     /*706*/
  395.        FlatCSIP=Sys_SelOff2Flat(CS,IP);                              /*706*/
  396.        if( IsNearReturn(FlatCSIP,(ushort)0) )                           /*827*/
  397.         goto NEAR_16_BIT;                                               /*706*/
  398.                                                                         /*706*/
  399.        /**********************************************************************/
  400.        /* Let's look for a CL386 thunk.                                      */
  401.        /**********************************************************************/
  402.        FlatCSIP=*(lframe+1);                                            /*706*/
  403.        if ( IsNearReturn(FlatCSIP,(ushort)1) )                          /*827*/
  404.         goto THUNK;                                                     /*706*/
  405.                                                                         /*706*/
  406.        /**********************************************************************/
  407.        /* Okay... so we'll look for a Cset thunk.                         706*/
  408.        /**********************************************************************/
  409.        FlatCSIP = CsetThunk(&frame,lframe);                             /*706*/
  410.        if ( IsNearReturn(FlatCSIP,(ushort)1) )                          /*827*/
  411.         goto THUNK;                                                     /*706*/
  412.                                                                         /*706*/
  413.        /**********************************************************************/
  414.        /* Hmmm...  well, this could be a PL/X86 thunk.                       */
  415.        /* The frame will be EIP/IP/CS.  Let's try!                           */
  416.        /**********************************************************************/
  417.        IP = *((ushort*)lframe+2);                                       /*706*/
  418.        CS = *((ushort*)lframe+3);                                       /*706*/
  419.  
  420.        /**********************************************************************/
  421.        /* - test bits 2 and 3 of the CS to verify that it's a valid          */
  422.        /*   LDT ring 2/3 selector.                                           */
  423.        /**********************************************************************/
  424.        if( ( (CS & 6) == 6 )  &&
  425.            ( FlatCSIP=Sys_SelOff2Flat(CS,IP) ) &&                    /*706*/
  426.            IsFarReturn(FlatCSIP)                                        /*827*/
  427.          )                                                              /*827*/
  428.         goto THUNK;                                                     /*706*/
  429.                                                                         /*706*/
  430. /*------------------------------------------------------------------------706*/
  431.        if( ShowAllFlag == TRUE )                                        /*706*/
  432.        {                                                                /*706*/
  433.        /**********************************************************************/
  434.        /* Well, let's try one final brute force technique.                706*/
  435.        /*                                                                 706*/
  436.        /**********************************************************************/
  437.         #define STACK_DWORDS 50                                         /*706*/
  438.         uint *ptr;                                                      /*706*/
  439.         uint  lclstack[STACK_DWORDS];                                   /*706*/
  440.         int   nbytes;                                                   /*706*/
  441.         uint *lclframe;                                                 /*706*/
  442.                                                                         /*706*/
  443.         /*********************************************************************/
  444.         /* go back to the previous frame and align on a dword boundary.   706*/
  445.         /*********************************************************************/
  446.         frame = PrevFrame;                                              /*706*/
  447.         frame += 3;                                                     /*706*/
  448.         frame &= 0xfffffffc;                                            /*706*/
  449.                                                                         /*706*/
  450.         /*********************************************************************/
  451.         /* now get a chunk of the stack and make it local.                706*/
  452.         /*********************************************************************/
  453. /*827*/ ptr = (uint *)Getnbytes(frame, STACK_DWORDS*sizeof(int),&bytesread);
  454.         if ( bytesread < 8 )                                            /*706*/
  455.          break;                                                         /*706*/
  456.         memcpy( lclstack, ptr , bytesread );                            /*706*/
  457.         lclframe = lclstack;                                            /*706*/
  458.                                                                         /*706*/
  459.         /*********************************************************************/
  460.         /* Scoot down through the stack until we get to an EIP that was   706*/
  461.         /* generated by a near call. This will be our "prospective" frame.706*/
  462.         /*********************************************************************/
  463.         for(nbytes = 8; (nbytes <= bytesread); lclframe++, nbytes += 4) /*706*/
  464.         {                                                               /*706*/
  465.          FlatCSIP = *(lclframe+1);                                      /*706*/
  466.          if ( IsNearReturn(FlatCSIP,(ushort)1) )                        /*827*/
  467.          {                                                              /*706*/
  468.           uint  nextcsip;                                               /*706*/
  469.           uint  nextlclframe[2];                                        /*706*/
  470.           uint  numbytes;                                               /*706*/
  471.                                                                         /*706*/
  472.           /*******************************************************************/
  473.           /* Now, let's take our "prospective" frame and see if it really 706*/
  474.           /* is linked to another frame. If it is, then we continue       706*/
  475.           /* unwinding from our "prospective" frame.                      706*/
  476.           /*******************************************************************/
  477.           ptr = (uint *)Getnbytes( *lclframe, 8, &numbytes);            /*827*/
  478.           if( numbytes != 8 )                                           /*706*/
  479.            continue;                                                    /*706*/
  480.           memcpy(nextlclframe,ptr,8);                                   /*706*/
  481.                                                                         /*706*/
  482.           nextcsip  = *(nextlclframe + 1 );                             /*706*/
  483.           if ( IsNearReturn(nextcsip,(ushort)1) )                       /*827*/
  484.           {                                                             /*706*/
  485.            frame = frame + (lclframe - lclstack)*sizeof(int);           /*706*/
  486.            memcpy( lframe, lclframe, 8 );                               /*706*/
  487.            goto THUNK;                                                  /*706*/
  488.           }                                                             /*706*/
  489.          }                                                              /*706*/
  490.         }                                                               /*706*/
  491.        } /* end of ShowAllFlag test    */                               /*706*/
  492. /*------------------------------------------------------------------------706*/
  493.        /**********************************************************************/
  494.        /* you have run out of luck at this point so we just quit.         706*/
  495.        /**********************************************************************/
  496.        break;                                                           /*706*/
  497.  
  498. THUNK:
  499.        ActCSAtrs[n]=ATR32;            /* next frame is 32-bit           107*/
  500.        SSAtr=ATR32;                   /* set for next loop iteration    107*/
  501.        frame=*lframe;                 /* define new 32-bit frame        107*/
  502.  
  503.       }
  504.       else /* if(ret == FARRET) */      /* stack return is far               */
  505.        ReturnCS=CS;                     /* update the return CS              */
  506.  
  507. NEAR_16_BIT:                                                            /*706*/
  508.       ActFaddrs[n] = FlatCSIP;          /* stuff flat CS:IP into ActFaddrs107*/
  509.      }                                  /* end curr frame is 16-bit       107*/
  510.  
  511.      if( frame < limit )                /* if frame is outside frame space   */
  512.       break;                            /*                                   */
  513.      /************************************************************************/
  514.      /* In the following statements FindScope() returns a pointer to the     */
  515.      /* SSProc record in the symbols area for an EIP return value in the     */
  516.      /* ActFaddrs array.  As a side effect, the mid and lno associated with  */
  517.      /* this EIP are put into the ActFlines array.  The offset ( EBP ) into  */
  518.      /* the stack of the stack frame is stored in ActFrames.                 */
  519.      /************************************************************************/
  520.  
  521. #if 0
  522.      ActScopes[n] = FindScope( ActFaddrs[n] , /* ->EIP value to scope     107*/
  523.                          &ActFlines[n][0] );  /* where to stuff mid/lno   224*/
  524. #endif
  525.      ActFrames[n] = frame;              /* stack offset of this frame        */
  526.  
  527.      /************************************************************************/
  528.      /* At this point, if we're only interested in seeing stack frames    706*/
  529.      /* for which we have named functions, then if the stack frame has    706*/
  530.      /* no scope, then we simply respin the loop on this value of n.      706*/
  531.      /* This can be time consuming especially for large PM apps.          706*/
  532.      /************************************************************************/
  533. #if 0
  534.      if( (ShowNamedFlag == TRUE) && (ActScopes[n] == 0) )               /*706*/
  535.       n--;                                                              /*706*/
  536. #endif
  537.     }                                   /* end of stack frame scan           */
  538.   }                                     /*                                   */
  539.  else                                   /* if AppPTB_EBP was null         107*/
  540.   n = 0 ;                               /* then there are no active frames   */
  541.                                         /*                                   */
  542.  /****************************************************************************/
  543.  /* Save the number of active frames and define  a pointer to the SSProc     */
  544.  /* record for the currently executing function.                             */
  545.  /****************************************************************************/
  546.  NActFrames = n;                        /* save the number of active frames  */
  547.  
  548.  if( NActFrames )
  549.  {
  550.   pActCSAtrs = Talloc(NActFrames*sizeof(ActCSAtrs[0]));
  551.   pActFrames = Talloc(NActFrames*sizeof(ActFrames[0]));
  552.   pActFaddrs = Talloc(NActFrames*sizeof(ActFaddrs[0]));
  553.   memcpy(pActCSAtrs,ActCSAtrs,NActFrames*sizeof(ActCSAtrs[0]));
  554.   memcpy(pActFrames,ActFrames,NActFrames*sizeof(ActFrames[0]));
  555.   memcpy(pActFaddrs,ActFaddrs,NActFrames*sizeof(ActFaddrs[0]));
  556.  
  557.   *ppActCSAtrs = pActCSAtrs;
  558.   *ppActFrames = pActFrames;
  559.   *ppActFaddrs = pActFaddrs;
  560.  }
  561.  return(NActFrames);
  562.  
  563. }
  564.  
  565. /*****************************************************************************/
  566. /* IsFarReturn()                                                             */
  567. /*                                                                           */
  568. /* Description:                                                              */
  569. /*   Verifies that a stack return address was generated by a far call.       */
  570. /*                                                                           */
  571. /* Parameters:                                                               */
  572. /*   addr        input - flat address of instruction.                     107*/
  573. /*   pdf         input - EXE/DLL containing the instruction.                 */
  574. /*                                                                           */
  575. /* Return:                                                                   */
  576. /*   TRUE or FALSE.                                                          */
  577. /*                                                                           */
  578. /* Assumptions:                                                              */
  579. /*                                                                           */
  580. /*   pdf is valid.                                                           */
  581. /*                                                                           */
  582. /*****************************************************************************/
  583. int IsFarReturn(UINT addr)              /* ->current instruction             */
  584.                                         /* EXE/DLL containing addr.          */
  585. {                                       /*                                   */
  586.  DTIF    packet;                        /* disassembly info packet.          */
  587.  uint    BaseLoadAddrOfObject;
  588. /*****************************************************************************/
  589. /*                                                                        706*/
  590. /* 1. Find out the base load address of the object containing this        706*/
  591. /*    address.                                                            706*/
  592. /* 2. Roll back the address one instruction.                              706*/
  593. /* 3. Disassemble the instruction and test for far return.                706*/
  594. /*                                                                        706*/
  595. /*****************************************************************************/
  596.  if( ( BaseLoadAddrOfObject = GetBaseAddr(addr) ) == 0 )                /*706*/
  597.   return(FALSE);                                                        /*706*/
  598.  addr = _rollback ( addr, -1, BaseLoadAddrOfObject );                   /*706*/
  599.  memset(&packet,0,sizeof(DTIF));        /* bzero->memset.               /*706*/
  600.  packet.Flags.Use32bit=0;               /* we are in USE16 segment      /*706*/
  601.  _GetInstrPacket( addr, (DTIF*)&packet );                                /*706*/
  602.  if(packet.retType == CALLFARIND ||     /* far call indirect.           /*706*/
  603.     packet.retType == CALLFARDIR ||     /* far call direct.             /*706*/
  604.     packet.retType == RETFAR            /* far return. ( PM dispatch).  /*706*/
  605.    )                                                                    /*706*/
  606.   return( TRUE );                                                       /*706*/
  607.  return( FALSE );                                                       /*706*/
  608. }                                       /* end IsFarReturn().           /*706*/
  609.  
  610. /*****************************************************************************/
  611. /* IsNearReturn()                                                            */
  612. /*                                                                           */
  613. /* Description:                                                              */
  614. /*   Verifies that a stack return address was generated by a near 16-/32-bit */
  615. /*   caller!                                                              107*/
  616. /*                                                                           */
  617. /* Parameters:                                                               */
  618. /*   addr        input - flat address of instruction.                        */
  619. /*   pdf         input - EXE/DLL containing the instruction.                 */
  620. /*   Im32Bit     input - tells us this is a USE32 segment or not.            */
  621. /*                                                                           */
  622. /* Return:                                                                   */
  623. /*   TRUE or FALSE.                                                          */
  624. /*                                                                           */
  625. /* Assumptions:                                                              */
  626. /*                                                                           */
  627. /*   pdf is valid.                                                           */
  628. /*                                                                           */
  629. /*****************************************************************************/
  630. int IsNearReturn(UINT addr,USHORT Im32Bit)
  631.                                         /* ->current instruction             */
  632.                                         /* EXE/DLL containing addr.          */
  633.                                         /* 1=>USE32  0=>USE16                */
  634. {                                       /*                                   */
  635.  DTIF    packet;                        /* disassembly info packet.          */
  636.  ULONG   BaseAddr;
  637. /*****************************************************************************/
  638. /*                                                                           */
  639. /* 1. Find out the base address and length of the module that contains       */
  640. /*    the address.                                                           */
  641. /* 2. Roll back the address one instruction.                                 */
  642. /* 3. Disassemble the instruction and test for far return.                   */
  643. /*                                                                           */
  644. /*****************************************************************************/
  645.  
  646.  if( (BaseAddr = GetBaseAddr(addr)) == 0)
  647.   return(FALSE);
  648.  addr = _rollback ( addr, -1, BaseAddr);
  649.  memset(&packet,0,sizeof(DTIF));        /* bzero->memset.                    */
  650.  packet.Flags.Use32bit=0;               /* assume USE16 segment              */
  651.  if ( Im32Bit )
  652.    packet.Flags.Use32bit=1;             /* USE32 segment                     */
  653.  _GetInstrPacket( addr, (DTIF*)&packet );
  654.  if(packet.retType == CALLIPDISP  ||    /* near call IP+DISP.                */
  655.     packet.retType == CALLNEARIND ||    /* near call indirect.               */
  656.     packet.retType == CALLREGNEAR       /* near call direct.                 */
  657.    )
  658.   return( TRUE );
  659.  return( FALSE );
  660. }                                       /* end IsNearReturn().               */
  661.  
  662. /*****************************************************************************/
  663. /* _rollback                                                                  */
  664. /*                                                                           */
  665. /* Description:                                                              */
  666. /*   adjusts an address backwards in the instruction stream.                 */
  667. /*                                                                           */
  668. /* Parameters:                                                               */
  669. /*   iap        ->current instruction (where we are sitting in showA window).*/
  670. /*   deltai     number of instructions to adjust iap by.                     */
  671. /*   fbyte      offset of first byte in current module.                      */
  672. /*   lbyte      offset of last byte in current module.                       */
  673. /*                                                                           */
  674. /* Return:                                                                   */
  675. /*   p          iap modified by deltai worth of instructions (when possible).*/
  676. /*                                                                           */
  677. /* Assumptions:                                                              */
  678. /*                                                                           */
  679. /*   deltai is negative.                                                     */
  680. /*                                                                           */
  681. /*****************************************************************************/
  682. UINT _rollback(UINT iap,int deltai,UINT fbyte )
  683.                                         /* ->current instruction             */
  684.                                         /* # of instsrs to adj for disasm    */
  685.                                         /* offset of first byte in curr mid  */
  686. {                                       /* begin instdelta                   */
  687.   int   lentab[ROLLBACK];               /* retained instruction lengths      */
  688.   int   i;                              /* index into lentab                 */
  689.   uint  trialiap;                       /* experimental ptr to scroll     107*/
  690.   UCHAR *streamptr;                     /* ->read in instruction stream   107*/
  691.   UCHAR type;                           /* indicates 16- or 32-bit code   107*/
  692.   uint  read;                           /* number of bytes read in by DBGetCS*/
  693.   UCHAR bitness;
  694.  
  695. /*****************************************************************************/
  696. /*                                                                           */
  697. /* Scrolling assembly instructions backward is tricky.    The idea is to     */
  698. /* start disassembling (for instruction length only) at a point well behind  */
  699. /* where you currently are and keep track of these lengths.  At some point,  */
  700. /* this stream of disassembly will (about 99.999% of the time!) meet back at */
  701. /* the current instruction.  You can then back track thru an array of lengths*/
  702. /* to figure out the proper address to scroll back to.                       */
  703. /*                                                                           */
  704. /*****************************************************************************/
  705.   if ( deltai < 0 &&                    /* want to delta backward and        */
  706.        iap != fbyte )                   /*   we can ?                     107*/
  707.   {                                     /* begin delta backward              */
  708.     bitness = _GetBitness( iap );          /* set type for InstLengthGlob    107*/
  709.     type = (bitness==BIT16)?USE16:USE32;
  710.     trialiap = fbyte;                   /* assume scroll back to mid start107*/
  711.     if ( fbyte + ROLLBACK <  iap )      /* just need rollback amount ?    107*/
  712.       trialiap = iap - ROLLBACK;        /* scroll back shorter amt        107*/
  713.  
  714.     streamptr=Getnbytes(trialiap,       /* read in all bytes up thru addr 107*/
  715.                         iap-trialiap,
  716.                         &read);
  717.  
  718.     i = 0;                              /* initialize index into lentab      */
  719.     while( trialiap < iap )             /* still need disasm lengths ?    107*/
  720.     {                                   /* disasm forward till we converge   */
  721.       lentab[i] = _InstLengthGlob( streamptr, type ); /* gimme inst len !  107*/
  722.       trialiap += lentab[i];            /* bump to next instr address     107*/
  723.       streamptr += lentab[i++];         /* bump to next instr & next entry107*/
  724.  
  725.     }                                   /* end disasm frwd till we converge  */
  726.  
  727.     if ( trialiap == iap )              /* did we converge ?              107*/
  728.       for(
  729.            i--;                         /* back up to last instr entry       */
  730.            i >= 0;                      /* make sure we still have entries   */
  731.            i--                          /* back up another entry             */
  732.          )
  733.       {                                 /* add up all instr lengths for delta*/
  734.         iap -= lentab[i];               /* back up by this entry's length 107*/
  735.         if ( !( ++deltai ) )            /* done scrolling back ?             */
  736.           break;                        /* finished adjusting iap            */
  737.       }                                 /* end add up all instr lens for delt*/
  738.   }                                     /* end delta backward                */
  739.  
  740.   return( iap );                        /* give back new deltad address      */
  741. }                                       /* end instdelta                     */
  742.  
  743.  
  744. /*************************************************************************107*/
  745. /* InstLengthGlob()                                                       107*/
  746. /*                                                                        107*/
  747. /* Description:                                                           107*/
  748. /*   Gets the length of an assembler instruction where the instruction    107*/
  749. /*   stream is already in our memory (no more DBGets!).                   107*/
  750. /*                                                                        107*/
  751. /* Parameters:                                                            107*/
  752. /*   inststreamptr  input - points to instruction stream.                 107*/
  753. /*   type           input - 0=>USE16, 1=>USE32.                           107*/
  754. /*                                                                        107*/
  755. /* Return:                                                                107*/
  756. /*                  length of instruction.                                107*/
  757. /*                                                                        107*/
  758. /* Assumptions:                                                           107*/
  759. /*                                                                        107*/
  760. /*    instruction stream already read in via DBGet!                       107*/
  761. /*************************************************************************107*/
  762. UCHAR _InstLengthGlob( UCHAR* inststreamptr, UCHAR type )
  763. {
  764.  DTIF     InstrPacket;
  765.  int      PacketSize;
  766.  UCHAR    InstrLen;                     /* instruction length             534*/
  767.  UCHAR    hexbuffer[HEXBUFFSIZE];       /* where disassembler puts hex.   108*/
  768.  char     mnebuffer[MNEMBUFFSIZE];      /* where disassembler puts mne.   108*/
  769.  UCHAR    textbuffer[TEXTBUFFSIZE];     /* where disassembler puts text.  108*/
  770.  
  771.  memset(&InstrPacket,0, sizeof(InstrPacket));
  772.  memset(hexbuffer   ,0, sizeof(hexbuffer));
  773.  memset(mnebuffer   ,0, sizeof(mnebuffer));
  774.  memset(textbuffer  ,0, sizeof(textbuffer));
  775.  
  776.  InstrPacket.InstPtr=inststreamptr;     /* ->read in hex from user app       */
  777.  InstrPacket.InstEIP=0xffffffff;        /* EIP value for this instr->        */
  778.  InstrPacket.Flags.Use32bit=type;       /* based upon address type           */
  779.  InstrPacket.Flags.MASMbit=1;           /* 1 for masm disassembly.           */
  780.  InstrPacket.Flags.N387bit=1;           /* not a 80x87 processor instr       */
  781.  InstrPacket.Flags.Unused1=0;           /* make zero due to possible futur   */
  782.  /****************************************************************************/
  783.  /* We don't really care about these buffers at this time. We put them       */
  784.  /* in to satisfy the disassembler.                                          */
  785.  /****************************************************************************/
  786.  InstrPacket.HexBuffer=hexbuffer;       /* hexbuffer will have instr strea   */
  787.  InstrPacket.MneBuffer=mnebuffer;       /* -> disassembled mnemonic.         */
  788.  InstrPacket.TextBuffer=textbuffer;     /* for disasembly text               */
  789.  DisAsm( &InstrPacket );                /* disassemble current instruction   */
  790.  InstrLen = InstrPacket.retInstLen;     /*                                534*/
  791.  if(InstrPacket.retType == REPETC )     /* instr is of repeat form ?      534*/
  792.  {                                      /*                                534*/
  793.    InstrPacket.HexBuffer=hexbuffer;     /* hexbuffer will have instr strea534*/
  794.    InstrPacket.MneBuffer=mnebuffer;     /* -> disassembled mnemonic.      534*/
  795.    InstrPacket.TextBuffer=textbuffer;   /* for disasembly text            534*/
  796.    DisAsm( &InstrPacket );              /* disassemble current instruction534*/
  797.    InstrLen += InstrPacket.retInstLen;  /*                                534*/
  798.  }                                      /*                                534*/
  799.  return(InstrLen);                      /* caller gets instruction length 534*/
  800. }                                       /* end GetInstrPacket.               */
  801.  
  802. /*****************************************************************************/
  803. /* CsetThunk()                                                            706*/
  804. /*                                                                        706*/
  805. /* Description:                                                           706*/
  806. /*   Find the EIP and the EBP of the caller in a 32-16 thunk.             706*/
  807. /*                                                                        706*/
  808. /*            ------------                                                706*/
  809. /*    BP---->|    BP      |---  16 bit pointer to top of thunk save area  706*/
  810. /*            ------------    |                                           706*/
  811. /*           |            |   |                                           706*/
  812. /*            ------------    |                                           706*/
  813. /*           |            |                                              706*/
  814. /*            -------------------------  <----32 bit save area. 38H bytes 706*/
  815. /*      ---0 |REGSAVE_2_ESP            |                                  706*/
  816. /*     |      -------------------------                                   706*/
  817. /*     |   4 |REGSAVE_SS               |                                  706*/
  818. /*     |      -------------------------                                   706*/
  819. /*     |   8 |                         |                                  706*/
  820. /*     |      -------------------------                                   706*/
  821. /*     |   C |                         |                                  706*/
  822. /*     |      -------------------------                                   706*/
  823. /*     |   10|                         |                                  706*/
  824. /*     |      -------------------------                                   706*/
  825. /*     |   14|                         |                                  706*/
  826. /*     |      -------------------------                                   706*/
  827. /*     |   18|REGSAVE_2_GS|REGSAVE_2_FS|                                  706*/
  828. /*     |      -------------------------                                   706*/
  829. /*     |   1C|REGSAVE_2_DS|REGSAVE_2_ES|                                  706*/
  830. /*     |      -------------------------                                   706*/
  831. /*     |   20|REGSAVE_2_ESI            |                                  706*/
  832. /*     |      -------------------------                                   706*/
  833. /*     |   24|REGSAVE_2_EDI            |                                  706*/
  834. /*     |      -------------------------                                   706*/
  835. /*     |   28|REGSAVE_2_EBX            |                                  706*/
  836. /*     |      -------------------------                                   706*/
  837. /*     |   2C|REGSAVE_2_EBP            | <---this is the EBP of the       706*/
  838. /*     |      -------------------------      caller's frame.              706*/
  839. /*      -->30|REGSAVE_2_EIP            | <---this is the return address   706*/
  840. /*            -------------------------      into the caller.             706*/
  841. /*         34|REGSAVE_1_ESP            |                                  706*/
  842. /*            -------------------------                                   706*/
  843. /*           |                         |                                  706*/
  844. /*           |                         |                                  706*/
  845. /*           | caller's auto           |                                  706*/
  846. /*           |                         |                                  706*/
  847. /*  caller's |                         |                                  706*/
  848. /*   EBP----> -------------------------                                   706*/
  849. /*           |      EBP                |                                  706*/
  850. /*            -------------------------                                   706*/
  851. /*           |      ESP                | <-- this is for a stack adjustmnt706*/
  852. /*            -------------------------      within the prolog of a 32 bit706*/
  853. /*           |      EIP                |     function that contains a     706*/
  854. /*            -------------------------       thunk to a 16 bit function. 706*/
  855. /*           |                         |                                  706*/
  856. /*                                                                        706*/
  857. /*                                                                        706*/
  858. /* Parameters:                                                            706*/
  859. /*   *pframe          input - ->to the variable( called "frame" actually) 706*/
  860. /*                              that holds the current frame location.    706*/
  861. /*                                                                        706*/
  862. /* Return:                                                                706*/
  863. /*   CallerRetAddr      - the flat return eip into the caller.            706*/
  864. /*                                                                        706*/
  865. /* Assumptions:                                                           706*/
  866. /*                                                                        706*/
  867. /*************************************************************************706*/
  868. #define BYTESTOREAD 8                                                   /*706*/
  869. #define OFFSET_OF_REGSAVE_2_GS   0x18                                   /*706*/
  870. #define OFFSET_OF_REGSAVE_2_EBP  0x2C                                   /*706*/
  871. uint CsetThunk(uint *pframe , uint *lframe )                            /*706*/
  872. {                                                                       /*706*/
  873.  uint  BytesObtained;                                                   /*706*/
  874.  uint *PtrToFrame;                                                      /*706*/
  875.  uint  frame;                                                           /*706*/
  876.  uint  CallerRetAddr;                                                   /*706*/
  877.                                                                         /*706*/
  878.  /************************************************************************706*/
  879.  /* add +30 to get to the offset of the "real" frame.                     706*/
  880.  /************************************************************************706*/
  881.  frame = *pframe + OFFSET_OF_REGSAVE_2_EBP - OFFSET_OF_REGSAVE_2_GS;    /*706*/
  882.                                                                         /*706*/
  883.  /************************************************************************706*/
  884.  /* Get 8 bytes of from the users stack. EBP/EIP.                         706*/
  885.  /************************************************************************706*/
  886.                                                                         /*706*/
  887.  PtrToFrame = (uint *)Getnbytes(frame, BYTESTOREAD, &BytesObtained);    /*827*/
  888.                                                                         /*706*/
  889.  /************************************************************************706*/
  890.  /* Return the EIP unless we couldn't read from the stack.                706*/
  891.  /************************************************************************706*/
  892.  if ( BytesObtained != BYTESTOREAD )                                    /*706*/
  893.   return(0);                                                            /*706*/
  894.                                                                         /*706*/
  895.  /************************************************************************706*/
  896.  /* - update the lframe for the caller.                                   706*/
  897.  /* - update the frame location in the caller.                            706*/
  898.  /* - return the caller's EIP.                                            706*/
  899.  /************************************************************************706*/
  900.  memcpy( lframe, PtrToFrame, BYTESTOREAD );                             /*706*/
  901.  *pframe = *PtrToFrame;                                                 /*706*/
  902.  CallerRetAddr = *(PtrToFrame+1);                                       /*706*/
  903.                                                                         /*706*/
  904.  return( CallerRetAddr);                                                /*706*/
  905. }                                       /* end CsetThunk().             /*706*/
  906.  
  907. /*****************************************************************************/
  908. /* IsValid_EBP()                                                             */
  909. /*                                                                           */
  910. /* Description:                                                              */
  911. /*                                                                           */
  912. /*   Checks an EBP to see if it meets the requirements of being a valid      */
  913. /*   link in the chain of EBPs.                                              */
  914. /*                                                                           */
  915. /* Parameters:                                                               */
  916. /*                                                                           */
  917. /*   ebp            EBP that we're testing.                                  */
  918. /*                                                                           */
  919. /* Return:                                                                   */
  920. /*                                                                           */
  921. /*   EBP_Ok    TRUE ==>valid.                                                */
  922. /*             FALSE==>invalid.                                              */
  923. /*                                                                           */
  924. /* Assumptions:                                                              */
  925. /*                                                                           */
  926. /*****************************************************************************/
  927.  
  928. #define BIT32_STACK_WIDTH   4
  929. #define EIP_ITERATION_CHECK 2
  930. #define USE32_SEGMENT       1
  931.  
  932. BOOL IsValid_EBP( ULONG ebp )
  933. {
  934.  ULONG  StackAddress;
  935.  BOOL   EBP_Ok;
  936.  int    iterations;
  937.  UCHAR *pEIP_Buffer;
  938.  ULONG  ulEIP;
  939.  UINT   BytesRead;
  940.  
  941.  StackAddress = ebp + BIT32_STACK_WIDTH;
  942.  EBP_Ok       = FALSE;
  943.  
  944.  for( iterations = 1; iterations <= EIP_ITERATION_CHECK; iterations++ )
  945.  {
  946.   pEIP_Buffer = Getnbytes( StackAddress, BIT32_STACK_WIDTH, &BytesRead);
  947.   ulEIP       = *(ULONG *)pEIP_Buffer;
  948.  
  949.   if ( IsNearReturn( ulEIP, USE32_SEGMENT ) == TRUE )
  950.   {
  951.    EBP_Ok = TRUE;
  952.    break;
  953.   }
  954.   StackAddress += BIT32_STACK_WIDTH;
  955.  }
  956.  return( EBP_Ok );
  957. }
  958.