home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sd386v50.zip / sd386src.zip / XSRVGO.C < prev    next >
Text File  |  1996-03-20  |  64KB  |  1,394 lines

  1. /*****************************************************************************/
  2. /* File:                                             IBM INTERNAL USE ONLY   */
  3. /*   srvrgo.c                                                             827*/
  4. /*                                                                           */
  5. /* Description:                                                              */
  6. /*                                                                           */
  7. /*  Server execution functions.                                              */
  8. /*                                                                           */
  9. /* History:                                                                  */
  10. /*                                                                           */
  11. /*   05/04/93 Created.                                                       */
  12. /*                                                                           */
  13. /*...Release 1.04 (04/30/93)                                                 */
  14. /*...                                                                        */
  15. /*... 05/04/93  822   Joe       Add mte table handling.                      */
  16. /*... 09/16/93  901   Joe       Add code to handle resource interlock error. */
  17. /*...                                                                        */
  18. /*****************************************************************************/
  19. #include "all.h"
  20.  
  21. /*****************************************************************************/
  22. /* limbo variables. do something with them.                                  */
  23. /*****************************************************************************/
  24.  
  25. UCHAR  AppRegsZapped = 0;
  26.  
  27. /*---------------------------------------------------------------------------*/
  28. static int xcpt_continue_flag;
  29. static int Error_Interrupt_Flag = FALSE;
  30.  
  31. static ULONG EspProcessID;
  32. static ULONG EspSessionID;
  33. static BOOL  ChildTerminatedFlag;
  34.  
  35. ULONG GetEspProcessID( void ) {return(EspProcessID);}
  36. ULONG GetEspSessionID( void ) {return(EspSessionID);}
  37. BOOL  IsChildTerminated( void ) {return(ChildTerminatedFlag);}
  38. /*****************************************************************************/
  39. /* XSrvGoInit()                                                              */
  40. /*                                                                           */
  41. /* Description:                                                              */
  42. /*                                                                           */
  43. /*   Initialize a process for debugging.                                     */
  44. /*                                                                           */
  45. /* Parameters:                                                               */
  46. /*                                                                           */
  47. /*   pptb               -> to the ptrace buffer.                             */
  48. /*   ppModuleLoadTable  where to put a ptr to the ModuleLoadTable.           */
  49. /*   pModuleTableLength where to put the length of the ModuleLoadtable.      */
  50. /*                                                                           */
  51. /* Return:                                                                   */
  52. /*                                                                           */
  53. /*   rc           DosDebug return code.                                      */
  54. /*                                                                           */
  55. /* Assumptions:                                                              */
  56. /*                                                                           */
  57. /*   The Pid is contained in the ptrace buffer.                              */
  58. /*                                                                           */
  59. /*****************************************************************************/
  60. APIRET XSrvGoInit( PtraceBuffer  *pptb,
  61.                    ULONG         *pExecAddr,
  62.                    UINT         **ppModuleLoadTable,
  63.                    int           *pModuleTableLength)
  64. {
  65.  APIRET  rc;
  66.  UINT   *pModuleList = NULL;
  67.  
  68.  /****************************************************************************/
  69.  /* - This flag is used for terminating a child probe                        */
  70.  /****************************************************************************/
  71.  ChildTerminatedFlag = FALSE;
  72.  
  73.  /****************************************************************************/
  74.  /* - Set the process id and the session id of the debuggee.                 */
  75.  /* - Make a call to get the session id when the probe is remote.            */
  76.  /* - pptb->Tid was used as a carrier for the sessionid...set it back to 0.  */
  77.  /****************************************************************************/
  78.  EspProcessID = pptb->Pid;
  79.  EspSessionID = pptb->Tid;
  80.  
  81.  pptb->Tid    = 0;
  82.  
  83. #ifdef __ESP__
  84. /*---------------------------------------------------------------------------*/
  85.  {
  86.   ALLPIDS *p;
  87.   TIB     *pTib;
  88.   PIB     *pPib;
  89.   USHORT   EspPid;
  90.   ULONG    sid;
  91.   USHORT   mte;
  92.  
  93.   /***************************************************************************/
  94.   /* - Update shared memory structure with pid and sid that this probe       */
  95.   /*   will be debugging.                                                    */
  96.   /***************************************************************************/
  97.   DosGetInfoBlocks(&pTib,&pPib);
  98.   EspPid = (USHORT)pPib->pib_ulpid;
  99.   p = GetEspPid( EspPid );
  100.   p->pid = EspProcessID;
  101.   if( GetSessionID(EspProcessID, &sid) != 0 )
  102.    return(1);
  103.   EspSessionID = p->sid = sid;
  104.  
  105.   /***************************************************************************/
  106.   /* - Get the mte for this process.                                         */
  107.   /***************************************************************************/
  108.   GetProcessMte( EspProcessID, &mte );
  109.   p->mte = mte;
  110.  }
  111. /*---------------------------------------------------------------------------*/
  112. #endif
  113.  
  114.  /****************************************************************************/
  115.  /* Connect to the debuggee. The Pid is contained in the ptrace buffer.      */
  116.  /****************************************************************************/
  117.  pptb->Cmd = DBG_C_Connect;
  118.  pptb->Value = DBG_L_386;
  119.  pptb->Addr  = 1;                                                       /*901*/
  120.  rc = DosDebug(pptb);
  121.  if(rc)
  122.   return(rc);
  123.  
  124.  if( pptb->Cmd == DBG_N_Error )
  125.   return(1);
  126.  
  127.  /****************************************************************************/
  128.  /* This code will build a module table for dll loads and frees. ll other    */
  129.  /* notifications are simply returned back to the caller.                    */
  130.  /****************************************************************************/
  131.  for(;;)
  132.  {
  133.   pptb->Cmd = DBG_C_Stop;
  134.   rc = DosDebug(pptb);
  135.   if(rc || (pptb->Cmd == DBG_N_Error) )
  136.    goto fini;
  137.   switch( pptb->Cmd )
  138.   {
  139.    case DBG_N_Success:
  140.     goto fini;
  141.  
  142.    case DBG_N_ModuleLoad:
  143.    AddToModuleLoadTable(&pModuleList, pptb->Pid, pptb->Value);
  144.    break;
  145.  
  146.    case DBG_N_ModuleFree:
  147.     AddFreeToModuleLoadTable(&pModuleList, pptb->Value);
  148.     break;
  149.  
  150.    case DBG_N_ThreadCreate:
  151.     break;
  152.  
  153.    default:
  154.     goto fini;
  155.   }
  156.  }
  157. fini:
  158.  
  159.  if( pptb->CSAtr )
  160.   *pExecAddr = pptb->EIP;
  161.  else
  162.   *pExecAddr =  Sys_SelOff2Flat(pptb->CS,LoFlat(pptb->EIP));
  163.  
  164.  /****************************************************************************/
  165.  /* Pack the module table and get out.                                       */
  166.  /****************************************************************************/
  167.  if( pModuleList )
  168.   *ppModuleLoadTable = PackModuleLoadTable(pModuleList , pModuleTableLength);
  169.  return(rc);
  170. }
  171.  
  172. /*****************************************************************************/
  173. /* XSrvRestartAppl()                                                         */
  174. /*                                                                           */
  175. /* Description:                                                              */
  176. /*                                                                           */
  177. /*   Application execution.                                                  */
  178. /*                                                                           */
  179. /* Parameters:                                                               */
  180. /*                                                                           */
  181. /*   pptb               -> to the ptrace buffer.                             */
  182. /*   pExecAddr          where to put the current exec address.               */
  183. /*   ppModuleLoadTable  where to put a ptr to the ModuleLoadTable.           */
  184. /*   pModuleTableLength where to put the length of the ModuleLoadtable.      */
  185. /*   ExecFlags          decision control flags.                              */
  186. /*                                                                           */
  187. /* Return:                                                                   */
  188. /*                                                                           */
  189. /*   rc         Trap code.                                                   */
  190. /*                                                                           */
  191. /* Assumptions:                                                              */
  192. /*                                                                           */
  193. /*   pptb->Pid is the correct process id.                                    */
  194. /*   pptb->Cmd = DBG_C_Go,DBG_C_Step, or DBG_C_Continue.                     */
  195. /*                                                                           */
  196. /*****************************************************************************/
  197. APIRET XSrvRestartAppl( PtraceBuffer  *pptb,
  198.                         ULONG         *pExecAddr,
  199.                         UINT         **ppModuleLoadTable,
  200.                         int           *pModuleTableLength,
  201.                         int           ExecFlags   )
  202. {
  203.  APIRET rc;
  204.  ULONG  exception;
  205.  int    n;
  206.  UINT   *pModuleList = NULL;
  207.  ULONG  DbgCmd = pptb->Cmd;
  208.  ULONG  Pid    = pptb->Pid;
  209.  
  210.  /****************************************************************************/
  211.  /* - reset this flag which is used at quit/restart time to determine        */
  212.  /*   how to terminate the app.                                              */
  213.  /****************************************************************************/
  214.  Error_Interrupt_Flag = FALSE;
  215.  
  216. RestartApplication:
  217.  /****************************************************************************/
  218.  /* - Continue execution after an exception, or                              */
  219.  /* - Call DosDebug with one of the following commands:                      */
  220.  /*     - DBG_C_Go.                                                          */
  221.  /*     - DBG_C_Step.                                                        */
  222.  /****************************************************************************/
  223.  if (xcpt_continue_flag == 1)
  224.  {
  225.   pptb->Cmd=DBG_C_Continue;
  226.   pptb->Value=XCPT_CONTINUE_SEARCH;
  227.   xcpt_continue_flag = 0;
  228.  }
  229.  else
  230.   pptb->Cmd = DbgCmd;
  231.  
  232.  pptb->Pid = Pid;
  233.  rc = DosDebug( pptb );
  234.  /****************************************************************************/
  235.  /* We will get this error when processing Signals.                          */
  236.  /****************************************************************************/
  237.  if( (rc == ERROR_INTERRUPT) || ( (rc==0) && (pptb->Cmd > 0) ) )
  238.  {
  239.   pptb->Pid = Pid;
  240.   pptb->Cmd = DBG_C_ReadReg;
  241.   DosDebug( pptb);
  242.   rc = 0;
  243.   pptb->Cmd = DBG_N_AsyncStop;
  244.   Error_Interrupt_Flag = TRUE;
  245.  }
  246.  
  247.  if ( rc != 0 )
  248.   return( TRAP_ABEND );
  249.  
  250.  switch(pptb->Cmd)
  251.  {
  252.   case DBG_N_ProcTerm:                  /* -6                                */
  253.   case DBG_N_Success:                   /*  0                                */
  254.    ChildTerminatedFlag = TRUE;
  255.    rc = TRAP_EXIT;
  256.    break;
  257.  
  258.   case DBG_N_Error:
  259.    if(pptb->Value == ERROR_EXCL_SEM_ALREADY_OWNED)                      /*901*/
  260.     goto RestartApplication;                                            /*901*/
  261.    /**************************************************************************/
  262.    /* - test for a resource interlock kickout by testing for a thread        */
  263.    /*   status on thread 1. If we get an error, then we've been kicked       */
  264.    /*   out of debugging. This happens on OS/2 2.1 GA and was fixed by       */
  265.    /*   APAR PJ09240.                                                        */
  266.    /**************************************************************************/
  267.    {                                                                    /*901*/
  268.     PtraceBuffer ptb;                                                   /*901*/
  269.     ULONG        buffer;                                                /*901*/
  270.                                                                         /*901*/
  271.     ptb.Pid = pptb->Pid;                                                /*901*/
  272.     ptb.Cmd = DBG_C_ThrdStat;                                           /*901*/
  273.     ptb.Tid = 1;                                                        /*901*/
  274.     ptb.Buffer = (ULONG)&buffer;                                        /*901*/
  275.     ptb.Len = sizeof( buffer);                                          /*901*/
  276.     rc = DosDebug( &ptb);                                               /*901*/
  277.     if( ptb.Cmd == DBG_N_Error )                                        /*901*/
  278.     {                                                                   /*901*/
  279.      *pExecAddr = pptb->EIP;                                            /*901*/
  280.      rc = TRAP_INTERLOCK;                                               /*901*/
  281.      return(rc);                                                        /*901*/
  282.     }                                                                   /*901*/
  283.     else
  284.      rc = TRAP_ABEND;
  285.    }
  286.    break;
  287.  
  288.   case DBG_N_AsyncStop:
  289.    rc = TRAP_ASYNC;
  290.    break;
  291.  
  292.   case DBG_N_AliasFree:
  293.   default:
  294.    rc = TRAP_ABEND;
  295.    break;
  296.  
  297. #ifdef __ESP__                                                          /*919*/
  298. /*---------------------------------------------------------------------------*/
  299.   case DBG_N_NewProc:                                                   /*919*/
  300.    SendNewProcessToQue( pptb->Value );                                  /*919*/
  301.    goto RestartApplication;                                             /*919*/
  302. /*---------------------------------------------------------------------------*/
  303. #endif                                                                  /*919*/
  304.  
  305.   case DBG_N_ThreadCreate:
  306.   case DBG_N_ThreadTerm:
  307.   case DBG_N_RangeStep:
  308.    goto RestartApplication;
  309.  
  310.   case DBG_N_CoError:
  311.    rc = TRAP_FP;
  312.    break;
  313.  
  314.   case DBG_N_Exception:
  315.    exception = pptb->Buffer;
  316.    switch( exception )
  317.    {
  318.     case XCPT_BREAKPOINT:
  319.     case XCPT_SINGLE_STEP:
  320.      pptb->Cmd=DBG_C_Continue;
  321.      pptb->Value=XCPT_CONTINUE_STOP;
  322.      rc = DosDebug(pptb);
  323.      if( rc != 0 || pptb->Cmd != 0 )
  324.      { rc = TRAP_ABEND; break; }
  325.      rc = TRAP_BPT;
  326.      if( exception == XCPT_SINGLE_STEP )
  327.       rc=TRAP_SS;
  328.      break;
  329.  
  330.     default:
  331.      /************************************************************************/
  332.      /* - handle exceptions.                                                 */
  333.      /************************************************************************/
  334.      if(pptb->Value == DBG_X_STACK_INVALID)
  335.      {;}
  336.      else
  337.      {
  338.       /***********************************************************************/
  339.       /* - Resolve the exception to the XCPT_??? exception number.           */
  340.       /***********************************************************************/
  341.       exception = ResolveException(pptb);
  342.      }
  343.  
  344.      xcpt_continue_flag = 1;
  345.  
  346.      n = GetExceptionIndex(exception);
  347.  
  348.      if( GetExceptionMap(n) == NO_NOTIFY)
  349.       goto RestartApplication;
  350.  
  351.      rc = GetExceptionNumber(n);
  352.    }
  353.    break;
  354.  
  355.   case DBG_N_ModuleLoad:                /* -8                                */
  356.    if( ExecFlags & LOAD_MODULES )
  357.    {
  358.     AddToModuleLoadTable(&pModuleList, pptb->Pid, pptb->Value);
  359.     if( ExecFlags & RUNNING_DEFERRED )
  360.     {
  361.      rc = (APIRET)DBG_N_ModuleLoad;
  362.      break;
  363.     }
  364.    }
  365.    goto RestartApplication;
  366.  
  367.   case DBG_N_ModuleFree:                /* -16                               */
  368.    if( ExecFlags & LOAD_MODULES )
  369.     AddFreeToModuleLoadTable(&pModuleList, pptb->Value);
  370.    goto RestartApplication;
  371.  
  372.   case DBG_N_Watchpoint:                /* -14                               */
  373.    MarkWpNotSet(pptb->Index);
  374.    rc = TRAP_WATCH;
  375.    break;
  376.  }
  377.  
  378.  if( pptb->CSAtr )
  379.   *pExecAddr = pptb->EIP;
  380.  else
  381.  {
  382.   *pExecAddr = Sys_SelOff2Flat(pptb->CS,LoFlat(pptb->EIP));
  383.  }
  384.  
  385.  /****************************************************************************/
  386.  /* Pack the module table and get out.                                       */
  387.  /****************************************************************************/
  388.  if( pModuleList )
  389.   *ppModuleLoadTable = PackModuleLoadTable(pModuleList , pModuleTableLength);
  390.  return(rc);
  391. }
  392.  
  393. /*****************************************************************************/
  394. /* XSrvGoStep()                                                              */
  395. /*                                                                           */
  396. /* Description:                                                              */
  397. /*                                                                           */
  398. /*   Step a source line stepping over any call instructions.                 */
  399. /*                                                                           */
  400. /* Parameters:                                                               */
  401. /*                                                                           */
  402. /*   target   address of instruction following the call.                     */
  403. /*                                                                           */
  404. /* Return:                                                                   */
  405. /*                                                                           */
  406. /*   rc       TRAP_SS if we land on the bp after the call.                   */
  407. /*            Whatever rc we get from restartappl() otherwise.               */
  408. /*                                                                           */
  409. /* Assumptions:                                                              */
  410. /*                                                                           */
  411. /*****************************************************************************/
  412. APIRET XSrvGoStep( PtraceBuffer  *pptb,
  413.                    ULONG         *pExecAddr,
  414.                    UINT         **ppModuleLoadTable,
  415.                    int           *pModuleTableLength,
  416.                    ULONG         ExecAddr,
  417.                    ULONG         ExecAddrlo,
  418.                    ULONG         ExecAddrhi,
  419.                    int           how,
  420.                    int           ExecFlags )
  421. {
  422.  APIRET rc;
  423.  ULONG  InstructionLen;
  424.  ULONG  CallInstructionAddr=0;
  425.  ULONG  eip = 0;
  426.  UINT   *pModuleLoadTable = NULL;
  427.  int     ModuleTableLength = 0;
  428.  UINT   *pModuleLoadTableAccum = NULL;
  429.  int     ModuleTableLengthAccum = 0;
  430.  
  431.  /****************************************************************************/
  432.  /* - If the user tries to single step when an exception is pending then     */
  433.  /*   it gets mapped to a GoFast.                                            */
  434.  /****************************************************************************/
  435.  if (xcpt_continue_flag == 1)
  436.  {
  437.   rc=XSrvGoFast(pptb,
  438.                 pExecAddr,
  439.                 ppModuleLoadTable,
  440.                 pModuleTableLength,
  441.                 ExecAddr,
  442.                 ExecFlags);
  443.   return(rc);
  444.  }
  445.  /***********************************************************************101*/
  446.  /* - execute instructions within a source line until beyond the source  101*/
  447.  /*   line.                                                              101*/
  448.  /* - step over call instructions if skipcalls parameter is set.         101*/
  449.  /*                                                                      101*/
  450.  /***********************************************************************101*/
  451.  rc = TRAP_SS_ERROR;                                                   /*101*/
  452.  eip = ExecAddr;
  453.  while( (eip >= ExecAddrlo) && (eip <= ExecAddrhi) )
  454.  {                                                                     /*101*/
  455.   if( (how==OVERCALL) && IsCallInst(eip) )
  456.   {                                                                    /*101*/
  457.    CallInstructionAddr = eip;
  458.    InstructionLen = _InstLength(eip);                                  /*101*/
  459.    rc = StepOverCall( pptb,
  460.                       ExecAddr,
  461.                       &pModuleLoadTable,
  462.                       &ModuleTableLength,
  463.                       eip + InstructionLen,
  464.                       &eip,
  465.                       ExecFlags );
  466.   }                                                                    /*101*/
  467.   else                                                                 /*101*/
  468.   {
  469.    pptb->Cmd = DBG_C_SStep;
  470.    rc = XSrvRestartAppl(pptb,
  471.                         &eip,
  472.                         &pModuleLoadTable,
  473.                         &ModuleTableLength,
  474.                         ExecFlags);
  475.   }
  476.  
  477.   if(pModuleLoadTable)
  478.   {
  479.    pModuleLoadTableAccum = CoalesceTables( pModuleLoadTableAccum,
  480.                                            ModuleTableLengthAccum,
  481.                                            pModuleLoadTable,
  482.                                            ModuleTableLength,
  483.                                            &ModuleTableLengthAccum );
  484.    pModuleLoadTable = NULL;
  485.    ModuleTableLength = 0;
  486.   }
  487.  
  488.   if( rc != TRAP_SS )
  489.    break;
  490.  }
  491.  
  492.  if( rc == DBG_N_ModuleLoad )
  493.   *pExecAddr = CallInstructionAddr;
  494.  else if( pptb->CSAtr )
  495.   *pExecAddr = pptb->EIP;
  496.  else
  497.   *pExecAddr =  Sys_SelOff2Flat(pptb->CS,LoFlat(pptb->EIP));
  498.  
  499.  *ppModuleLoadTable = pModuleLoadTableAccum;
  500.  *pModuleTableLength = ModuleTableLengthAccum;
  501.  return( rc );                                                         /*101*/
  502. }
  503.  
  504. /*****************************************************************************/
  505. /* XSrvGoFast()                                                              */
  506. /*                                                                           */
  507. /* Description:                                                              */
  508. /*                                                                           */
  509. /*   Run until we get a notification from DosDebug.                          */
  510. /*                                                                           */
  511. /* Parameters:                                                               */
  512. /*                                                                           */
  513. /*   pptb               -> to the ptrace buffer.                             */
  514. /*   pExecAddr          -> receiver of next execution address.(after GoFast) */
  515. /*   ppModuleLoadTable  where to put a ptr to the ModuleLoadTable.           */
  516. /*   pModuleTableLength where to put the length of the ModuleLoadtable.      */
  517. /*   ExecAddr           address of exec instruction.(before GoFast )         */
  518. /*   ExecFlags          execution flags.                                     */
  519. /*                                                                           */
  520. /* Return:                                                                   */
  521. /*                                                                           */
  522. /* Assumptions:                                                              */
  523. /*                                                                           */
  524. /*****************************************************************************/
  525. APIRET XSrvGoFast( PtraceBuffer  *pptb,
  526.                    ULONG         *pExecAddr,
  527.                    UINT         **ppModuleLoadTable,
  528.                    int           *pModuleTableLength,
  529.                    ULONG         ExecAddr,
  530.                    int           ExecFlags)
  531. {
  532.  APIRET  rc;
  533.  UINT   *pModuleLoadTable = NULL;
  534.  int     ModuleTableLength = 0;
  535.  UINT   *pModuleLoadTableAccum = NULL;
  536.  int     ModuleTableLengthAccum = 0;
  537.  
  538.  /****************************************************************************/
  539.  /* - If there's a break point defined for the current CS:EIP, then          */
  540.  /*   single step before inserting the breakpoints.                          */
  541.  /* - Insert all the breakpoints.                                            */
  542.  /* - Run the application.                                                   */
  543.  /* - Handle any dll loads/frees.                                            */
  544.  /****************************************************************************/
  545.  if( _IfBrkOnAddr(ExecAddr) != NULL )
  546.  {
  547.   /***************************************************************************/
  548.   /* - step if a break point is defined for ExecAddr.                        */
  549.   /***************************************************************************/
  550.   pptb->Cmd = DBG_C_SStep;
  551.   rc=XSrvRestartAppl(pptb,
  552.                      pExecAddr,
  553.                      &pModuleLoadTable,
  554.                      &ModuleTableLength,
  555.                      ExecFlags);
  556.   if(pModuleLoadTable)
  557.   {
  558.    pModuleLoadTableAccum = CoalesceTables( pModuleLoadTableAccum,
  559.                                            ModuleTableLengthAccum,
  560.                                            pModuleLoadTable,
  561.                                            ModuleTableLength,
  562.                                            &ModuleTableLengthAccum );
  563.    pModuleLoadTable = NULL;
  564.    ModuleTableLength = 0;
  565.   }
  566.   if( rc != TRAP_SS )
  567.    goto fini;
  568.  }
  569.  
  570.  /****************************************************************************/
  571.  /* - let 'er rip.                                                           */
  572.  /****************************************************************************/
  573.  pptb->Cmd = DBG_C_Go;
  574.  XSrvInsertAllBrk();
  575.  rc=XSrvRestartAppl(pptb,
  576.                     pExecAddr,
  577.                     &pModuleLoadTable,
  578.                     &ModuleTableLength,
  579.                     ExecFlags);
  580.  if(pModuleLoadTable)
  581.  {
  582.   pModuleLoadTableAccum = CoalesceTables( pModuleLoadTableAccum,
  583.                                           ModuleTableLengthAccum,
  584.                                           pModuleLoadTable,
  585.                                           ModuleTableLength,
  586.                                           &ModuleTableLengthAccum );
  587.   pModuleLoadTable = NULL;
  588.   ModuleTableLength = 0;
  589.  }
  590.  XSrvRemoveAllBrk();
  591.  
  592. fini:
  593.  *ppModuleLoadTable = pModuleLoadTableAccum;
  594.  *pModuleTableLength = ModuleTableLengthAccum;
  595.  
  596.  return(rc);
  597. }
  598.  
  599. /*****************************************************************************/
  600. /* StepOverCall()                                                            */
  601. /*                                                                           */
  602. /* Description:                                                              */
  603. /*                                                                           */
  604. /*   Steps over a call instruction by setting a breakpoint at the next       */
  605. /*   instruction and executing to that point.                                */
  606. /*                                                                           */
  607. /* Parameters:                                                               */
  608. /*                                                                           */
  609. /*   pptb               -> to the ptrace buffer.                             */
  610. /*   ExecAddr           current execution address.                           */
  611. /*   ppModuleLoadTable  where to put a ptr to the ModuleLoadTable.           */
  612. /*   pModuleTableLength where to put the length of the ModuleLoadtable.      */
  613. /*   target             address of instruction following the call.           */
  614. /*   pEip               where to put the exec address after the call.        */
  615. /*                                                                           */
  616. /* Return:                                                                   */
  617. /*                                                                           */
  618. /*   rc       TRAP_SS if we land on the bp after the call.                   */
  619. /*            Whatever rc we get from restartappl() otherwise.               */
  620. /*                                                                           */
  621. /* Assumptions:                                                              */
  622. /*                                                                           */
  623. /*****************************************************************************/
  624. APIRET StepOverCall( PtraceBuffer  *pptb,
  625.                      ULONG          ExecAddr,
  626.                      UINT         **ppModuleLoadTable,
  627.                      int           *pModuleTableLength,
  628.                      ULONG          target,
  629.                      ULONG         *pEip,
  630.                      int            ExecFlags )
  631. {
  632.  APIRET  rc;
  633.  ULONG   eip;
  634.  UINT    OldEip;
  635.  UINT   *pModuleLoadTable = NULL;
  636.  int     ModuleTableLength = 0;
  637.  UINT   *pModuleLoadTableAccum = NULL;
  638.  int     ModuleTableLengthAccum = 0;
  639.  
  640.  XSrvDefBrk(target);
  641.  XSrvInsertAllBrk();
  642.  if( _IfBrkOnAddr( ExecAddr ) )
  643.  {
  644.   OldEip = ExecAddr;
  645.   XSrvRemoveOneBrk( ExecAddr );
  646.   pptb->Cmd = DBG_C_SStep;
  647.   rc = XSrvRestartAppl(pptb,&eip,&pModuleLoadTable,&ModuleTableLength,ExecFlags);
  648.   if(pModuleLoadTable)
  649.   {
  650.    pModuleLoadTableAccum = CoalesceTables( pModuleLoadTableAccum,
  651.                                            ModuleTableLengthAccum,
  652.                                            pModuleLoadTable,
  653.                                            ModuleTableLength,
  654.                                            &ModuleTableLengthAccum );
  655.    pModuleLoadTable = NULL;
  656.    ModuleTableLength = 0;
  657.   }
  658.   if( rc != TRAP_SS)
  659.    goto fini;
  660.   XSrvInsertOneBrk( OldEip);
  661.  }
  662.  
  663.  pptb->Cmd = DBG_C_Go;
  664.  rc=XSrvRestartAppl(pptb,&eip,&pModuleLoadTable,&ModuleTableLength,ExecFlags);
  665.  if(pModuleLoadTable)
  666.  {
  667.   pModuleLoadTableAccum = CoalesceTables( pModuleLoadTableAccum,
  668.                                           ModuleTableLengthAccum,
  669.                                           pModuleLoadTable,
  670.                                           ModuleTableLength,
  671.                                           &ModuleTableLengthAccum );
  672.   pModuleLoadTable = NULL;
  673.   ModuleTableLength = 0;
  674.  }
  675.  
  676. fini:
  677.  
  678.  XSrvRemoveAllBrk();
  679.  XSrvUndBrk(target);
  680.  
  681.  *ppModuleLoadTable = pModuleLoadTableAccum;
  682.  *pModuleTableLength = ModuleTableLengthAccum;
  683.  
  684.  *pEip = eip;
  685.  if( (rc == TRAP_BPT) && (eip == target) )
  686.   return(TRAP_SS);
  687.  return(rc);
  688. }
  689.  
  690.   int
  691. IsCallInst(UINT address)
  692. {
  693.   UCHAR dataword[2];                    /* word returned from Getnbytes      */
  694.   short   *wordptr = NULL;              /* pointer to word in user addr sp102*/
  695.   UINT    bytesread = 0;                /* bytes read from user addr space521*/
  696.  
  697.     wordptr = (short *)Getnbytes(address,2,&bytesread);
  698.     while( wordptr )
  699.     {
  700.      *(short *)dataword = *wordptr;
  701.      switch( dataword[0] )
  702.      {
  703.        case 0x9A:  /* far call */
  704.        case 0xE8:  /* near call */
  705.          return( TRUE );
  706.        case 0xFF:  /* indirect */
  707.          return(
  708.            ((dataword[1] & 0x38) == 0x18) ||
  709.            ((dataword[1] & 0x38) == 0x10)
  710.          );
  711.        case 0x26:  /* seg es: */
  712.        case 0x2E:  /* seg ds: */
  713.        case 0x36:  /* seg ss: */
  714.        case 0x3E:  /* seg cs: */
  715.          address += 1;
  716.          break;
  717.        default:
  718.          return( FALSE );
  719.      }
  720.      wordptr = (short *)Getnbytes(address,2,&bytesread);
  721.     }
  722.     return( FALSE );
  723. }
  724.  
  725. /*****************************************************************************/
  726. /* XSrvNormalQuit()                                                              */
  727. /*                                                                           */
  728. /* Description:                                                              */
  729. /*                                                                           */
  730. /*   Quit the debugger.                                                      */
  731. /*                                                                           */
  732. /* Parameters:                                                               */
  733. /*                                                                           */
  734. /*   none                                                                    */
  735. /*                                                                           */
  736. /* Return:                                                                   */
  737. /*                                                                           */
  738. /*    0 or 1                                                                 */
  739. /*                                                                           */
  740. /* Assumptions:                                                              */
  741. /*                                                                           */
  742. /*   The application is either in the "DBG_N_ProcTerm" since the             */
  743. /*   app has executed a DosExit, or the state is unknown.                    */
  744. /*                                                                           */
  745. /*****************************************************************************/
  746. #define DOSEXITORDINAL32BIT 234
  747.  
  748. #pragma map(DosExitEntryPt16,"_DosExitEntryPt16")
  749. extern char * _Seg16 DosExitEntryPt16;
  750. extern ushort _Far16 Get16BitDosExitEntry( ulong );
  751.  
  752. APIRET XSrvNormalQuit( int AppTerminated, UINT MteOfExe, ULONG EntryPt )
  753. {
  754.  PtraceBuffer  ptb;
  755.  uchar         CallDosExit16[5];
  756.  ulong         mte;
  757.  char          buf[256];
  758.  ulong         ActionCode;
  759.  ulong         ResultCode;
  760.  ulong         DosExitEntryPt=0;
  761.  uchar        *p;
  762.  int           i;
  763.  int           rc;
  764.  ulong         flatsssp;
  765.  ulong         StackSize;
  766.  
  767.  /****************************************************************************/
  768.  /* clear any watch points currently set as well as any pending wp           */
  769.  /* notifications.                                                           */
  770.  /****************************************************************************/
  771.  XSrvPullOutWps( );
  772.  
  773.  if( (AppTerminated == FALSE) && (Error_Interrupt_Flag == FALSE) )
  774.  {
  775.   memset(&ptb,0,sizeof(ptb));
  776.   ActionCode = 1;
  777.   ResultCode = 0;
  778.   if( _GetBitness(EntryPt) == BIT32 )
  779.   {
  780.    ptb.Pid = GetEspProcessID();
  781.    ptb.Tid = 1;
  782.  
  783.    /**************************************************************************/
  784.    /* For 32 bit exes, we find the DosExit entry pt and set up a stack       */
  785.    /* frame for making the call on behalf of the debuggee. This is a bit     */
  786.    /* different from the 16 bit scenario where we write a "Call DosExit"     */
  787.    /* instruction in the user's address space and then execute it.           */
  788.    /*                                                                        */
  789.    /* - Set esp to point 1k off the top of the stack.                        */
  790.    /* - Align the address on a dword.                                        */
  791.    /* - Set up a stack frame as follows:                                     */
  792.    /*                                                                        */
  793.    /*    esp--->+0| xxxxx  | <----ret addr ( don't care since no return )    */
  794.    /*           +4|   1    | <----Action code                                */
  795.    /*           +8|   0    | <----Result code                                */
  796.    /*    ebp--->+C|        |                                                 */
  797.    /*                                                                        */
  798.    /**************************************************************************/
  799.    flatsssp = GetExeStackTop(MteOfExe,&ptb.SS,&StackSize);
  800.    flatsssp -= 1096;
  801.    flatsssp += 3;
  802.    flatsssp &= 0xfffffffc;
  803.  
  804.    ptb.EBP = flatsssp;
  805.    ptb.ESP = ptb.EBP - 0xC;
  806.  
  807.    /**************************************************************************/
  808.    /* Set up the flat address registers.                                     */
  809.    /**************************************************************************/
  810.    ptb.DS  = 0x53;
  811.    ptb.ES  = 0x53;
  812.    ptb.SS  = 0x53;
  813.    ptb.CS  = 0x5B;
  814.    ptb.FS  = 0x150B;
  815.    ptb.GS  = 0x00;
  816.  
  817.    /**************************************************************************/
  818.    /* Set up the stack for a DosExit call and find the DosExit entry pt.     */
  819.    /**************************************************************************/
  820.    if( Putnbytes(ptb.ESP+4,4,(uchar*)&ActionCode) ||
  821.        Putnbytes(ptb.ESP+8,4,(uchar*)&ResultCode) ||
  822.        DosLoadModule( buf, sizeof(buf), "DOSCALL1", &mte ) ||
  823.        DosQueryProcAddr(mte,DOSEXITORDINAL32BIT,NULL,(PFN*)&DosExitEntryPt)||
  824.        DosFreeModule(mte)
  825.      )
  826.     return( 1 );
  827.  
  828.    ptb.EIP = DosExitEntryPt;
  829.   }
  830.   else
  831.   {
  832.    /**************************************************************************/
  833.    /* handle 16 bit EXE.                                                     */
  834.    /**************************************************************************/
  835.    ptb.Pid = GetEspProcessID();
  836.    ptb.Tid = 1;
  837.  
  838.    /**************************************************************************/
  839.    /* - Set esp to point into the middle of the stack or 1k off the          */
  840.    /*   top of the stack.                                                    */
  841.    /* - Get the load SS at the same time.                                    */
  842.    /* - Align the address on a dword.                                        */
  843.    /**************************************************************************/
  844.    flatsssp = GetExeStackTop(MteOfExe,&ptb.SS,&StackSize);
  845.    if( StackSize == 0 )
  846.     flatsssp -= 1096;
  847.    else
  848.     flatsssp -= (StackSize>>1);
  849.  
  850.    flatsssp += 3;
  851.    flatsssp &= 0xfffffffc;
  852.  
  853.    ptb.ESP = *((ushort*)&flatsssp);
  854.  
  855.    /**************************************************************************/
  856.    /* Set up the stack for a DosExit call and find the DosExit entry pt.     */
  857.    /**************************************************************************/
  858.    if( !flatsssp  ||
  859.         Putnbytes(flatsssp  ,2,(uchar*)&ResultCode) ||
  860.         Putnbytes(flatsssp+2,2,(uchar*)&ActionCode) ||
  861.         DosLoadModule( buf, sizeof(buf), "DOSCALLS", &mte ) ||
  862.         Get16BitDosExitEntry( mte )
  863.      )
  864.     return( 1 );
  865.  
  866.    /**************************************************************************/
  867.    /* Build an instruction for the DosExit call.                             */
  868.    /**************************************************************************/
  869.    p = (uchar *)&DosExitEntryPt16;
  870.    CallDosExit16[0] = 0x9A;
  871.    for(i=1;i<=4;i++)
  872.     CallDosExit16[i] = *p++;
  873.  
  874.    /**************************************************************************/
  875.    /* - Write the instruction a the user's entry point.                      */
  876.    /* - Set up the CS:IP for the call.                                       */
  877.    /**************************************************************************/
  878.    if( Putnbytes(EntryPt,sizeof(CallDosExit16),CallDosExit16) )
  879.     return( 1 );
  880.    Sys_Flat2SelOff(EntryPt,&ptb.CS,(ushort*)&ptb.EIP);
  881.   }
  882.  
  883.   ptb.Cmd = DBG_C_WriteReg;
  884.   if( DosDebug(&ptb) || (ptb.Cmd != 0) )
  885.    return(1);
  886.  }                                      /* end of if !AppTerminated          */
  887.  
  888.  rc = 0;
  889.  /****************************************************************************/
  890.  /*  - If we're quitting/restarting after a c-break, then we proceed         */
  891.  /*    immediately to the DBG_C_TERM and forget the GoTerm()                 */
  892.  /*  - Else, if the app has terminated, then it should be in                 */
  893.  /*    the DBG_N_ProcTerm state. GoTerm() will finish the job.               */
  894.  /****************************************************************************/
  895.  if( Error_Interrupt_Flag || GoTerm() )
  896.  {
  897.   /***************************************************************************/
  898.   /* If our normal termination did not work, we'll try DosDebug which        */
  899.   /* should be all that we need anyway, but...                               */
  900.   /***************************************************************************/
  901.   memset( &ptb,0,sizeof(ptb) );
  902.   ptb.Cmd = DBG_C_Term;
  903.   ptb.Pid = GetEspProcessID();
  904.   rc=( DosDebug(&ptb) || ptb.Cmd )?1:0;
  905.  }
  906.  
  907.  /****************************************************************************/
  908.  /* - clean up the breakpoint structures.                                    */
  909.  /****************************************************************************/
  910.  ClearBrks();
  911.  FreeObjectList();
  912.  
  913.  /****************************************************************************/
  914.  /* - end the parent session.                                                */
  915.  /****************************************************************************/
  916.  DosStopSession( STOP_SESSION_ALL, GetTerminateSessionID() );           /*919*/
  917.  return(rc);
  918. }                                       /* end NormalQuit()                  */
  919.  
  920.  
  921. /*****************************************************************************/
  922. /* GoTerm()                                                                  */
  923. /*                                                                           */
  924. /* Description:                                                              */
  925. /*                                                                           */
  926. /*   Terminate the debuggee process.                                         */
  927. /*                                                                           */
  928. /* Parameters:                                                               */
  929. /*                                                                           */
  930. /*   none                                                                    */
  931. /*                                                                           */
  932. /* Return:                                                                   */
  933. /*                                                                           */
  934. /*   0 or 1                                                                  */
  935. /*                                                                           */
  936. /* Assumptions:                                                              */
  937. /*                                                                           */
  938. /*   The application is either in the "DBG_N_ProcTerm" since the             */
  939. /*   app has executed a DosExit, or the state is unknown.                    */
  940. /*                                                                           */
  941. /*****************************************************************************/
  942. int GoTerm(  )
  943. {
  944.  long         DosDebugCmd;
  945.  BOOL         success;
  946.  PtraceBuffer ptb;
  947.  APIRET       rc;
  948.  ULONG        exception;
  949.  
  950.  memset(&ptb,0,sizeof(ptb));
  951.  success = FALSE;
  952.  
  953.  
  954.  /****************************************************************************/
  955.  /* - read the current registers for thread 1.                               */
  956.  /****************************************************************************/
  957.  ptb.Pid = GetEspProcessID();
  958.  ptb.Cmd = DBG_C_ReadReg;
  959.  ptb.Tid = 1;
  960.  rc = DosDebug( &ptb);
  961.  if ( rc != 0 || ptb.Cmd != DBG_N_Success )
  962.   return(1);
  963.  
  964.  /****************************************************************************/
  965.  /*  - Execute a final go command to force the debuggee to run a DosExit.    */
  966.  /*  - ...unless we're sitting on an exception, we'll give the exception     */
  967.  /*    back to the operating system and take it from there.                  */
  968.  /*                                                                          */
  969.  /****************************************************************************/
  970.  DosDebugCmd = DBG_C_Go;
  971.  if (xcpt_continue_flag == 1)
  972.  {
  973.   DosDebugCmd=DBG_C_Continue;
  974.   ptb.Value=XCPT_CONTINUE_SEARCH;
  975.   xcpt_continue_flag = 0;
  976.  }
  977.  
  978.  while( success == FALSE )
  979.  {
  980.   ptb.Cmd = DosDebugCmd;
  981.   ptb.Pid = GetEspProcessID();
  982.  
  983.   if( DosDebug( &ptb ) ||
  984.       ptb.Cmd == DBG_N_Error )
  985.    return(  1  );
  986.  
  987.   /***************************************************************************/
  988.   /* Process notifications from DosDebug.                                    */
  989.   /*                                                                         */
  990.   /* Termination should proceed as follows:                                  */
  991.   /*  - DBG_N_Exception with XCPT_PROCESS_TERMINATE.                         */
  992.   /*  - DBG_N_ThreadTerm for thread 1.                                       */
  993.   /*  - DBG_N_ProcTerm.                                                      */
  994.   /*  - DBG_N_Success.                                                       */
  995.   /*                                                                         */
  996.   /* If the DBG_N_ProcTerm notification has already been received as a       */
  997.   /* result of the debuggee executing a DosExit, then the first 2            */
  998.   /* notifications will have already gone by in Go().                        */
  999.   /*                                                                         */
  1000.   /***************************************************************************/
  1001.   switch( ptb.Cmd )
  1002.   {
  1003.    case DBG_N_ThreadTerm:
  1004.     DosDebugCmd = DBG_C_Go;
  1005.     continue;
  1006.  
  1007.    case DBG_N_ProcTerm:
  1008.     DosDebugCmd = DBG_C_Go;
  1009.     continue;
  1010.  
  1011.    case DBG_N_Success:
  1012.     success = TRUE;
  1013.     break;
  1014.  
  1015.    case DBG_N_Exception:
  1016.     exception = ResolveException( &ptb);
  1017.     if( ( exception == XCPT_PROCESS_TERMINATE ) ||
  1018.         ( exception == XCPT_ASYNC_PROCESS_TERMINATE ) ||
  1019.         ( exception == XCPT_SIGNAL )
  1020.       )
  1021.     {
  1022.      DosDebugCmd  = DBG_C_Continue;
  1023.      ptb.Value = XCPT_CONTINUE_SEARCH;
  1024.      continue;
  1025.     }
  1026.     else
  1027.      return(  1  );
  1028.  
  1029.    default:
  1030.     DosDebugCmd = DBG_C_Go;
  1031.     continue;
  1032.   }
  1033.  }
  1034.  return( 0 );
  1035. }                                       /* end GoTerm()                      */
  1036.  
  1037. /*****************************************************************************/
  1038. /* XSrvSetExecAddr()                                                         */
  1039. /*                                                                           */
  1040. /* Description:                                                              */
  1041. /*                                                                           */
  1042. /*   Change the execution address of the current thread.                     */
  1043. /*                                                                           */
  1044. /* Parameters:                                                               */
  1045. /*                                                                           */
  1046. /*   ExecAddr   the new execution address.                                   */
  1047. /*                                                                           */
  1048. /* Return:                                                                   */
  1049. /*                                                                           */
  1050. /*   rc                                                                      */
  1051. /*                                                                           */
  1052. /* Assumptions:                                                              */
  1053. /*                                                                           */
  1054. /*****************************************************************************/
  1055. APIRET XSrvSetExecAddr( ULONG ExecAddr )
  1056. {
  1057.  PtraceBuffer ptb;
  1058.  APIRET       rc;
  1059.  
  1060.  /****************************************************************************/
  1061.  /* - read the current registers for the current thread.                     */
  1062.  /****************************************************************************/
  1063.  memset(&ptb,0,sizeof(ptb));
  1064.  ptb.Pid = GetEspProcessID();
  1065.  ptb.Cmd = DBG_C_ReadReg;
  1066.  ptb.Tid = 0;
  1067.  rc = DosDebug( &ptb);
  1068.  if ( rc != 0 || ptb.Cmd != DBG_N_Success )
  1069.   return(1);
  1070.  
  1071.  /****************************************************************************/
  1072.  /* - Write the new execution address.                                       */
  1073.  /****************************************************************************/
  1074.  if(ptb.CSAtr)
  1075.   ptb.EIP = ExecAddr;
  1076.  else
  1077.   Sys_Flat2SelOff(ExecAddr,&ptb.CS,(USHORT*)&ptb.EIP);
  1078.  
  1079.  ptb.Cmd = DBG_C_WriteReg;
  1080.  rc = DosDebug( &ptb);
  1081.  if ( rc != 0 || ptb.Cmd != DBG_N_Success )
  1082.   return(1);
  1083.  return(0);
  1084. }
  1085.  
  1086. /*****************************************************************************/
  1087. /* XSrvWriteRegs()                                                           */
  1088. /*                                                                           */
  1089. /* Description:                                                              */
  1090. /*                                                                           */
  1091. /*   Write the registers and return exec addr.                               */
  1092. /*                                                                           */
  1093. /* Parameters:                                                               */
  1094. /*                                                                           */
  1095. /*   pExecAddr -> to address that will receive the flat execution address.   */
  1096. /*   pptb      -> to the ptrace buffer with the new registers.               */
  1097. /*                                                                           */
  1098. /* Return:                                                                   */
  1099. /*                                                                           */
  1100. /*   rc        0=>success                                                    */
  1101. /*             1=>failure                                                    */
  1102. /*                                                                           */
  1103. /* Assumption:                                                               */
  1104. /*                                                                           */
  1105. /*  pptb->tid is the thread we're writing the registers for.                 */
  1106. /*                                                                           */
  1107. /*****************************************************************************/
  1108. APIRET XSrvWriteRegs(ULONG *pExecAddr,PtraceBuffer *pptb)
  1109. {
  1110.  APIRET rc;
  1111.  
  1112.  pptb->Pid = GetEspProcessID();
  1113.  pptb->Cmd = DBG_C_WriteReg;
  1114.  pptb->Tid = pptb->Tid; /* just to emphasize the point! */
  1115.  rc = DosDebug( pptb);
  1116.  if( (rc != 0) || (pptb->Cmd != 0) )
  1117.   return(1);
  1118.  
  1119.  if( pptb->CSAtr )
  1120.   *pExecAddr = pptb->EIP;
  1121.  else
  1122.   *pExecAddr =  Sys_SelOff2Flat(pptb->CS,LoFlat(pptb->EIP));
  1123.  return(0);
  1124. }
  1125.  
  1126. /*****************************************************************************/
  1127. /* XSrvGetCoregs()                                                           */
  1128. /*                                                                           */
  1129. /* Description:                                                              */
  1130. /*                                                                           */
  1131. /*   Get the co-processor registers.                                         */
  1132. /*                                                                           */
  1133. /* Parameters:                                                               */
  1134. /*                                                                           */
  1135. /*   pCoproc_regs -> to the buffer receiving the regs.                       */
  1136. /*                                                                           */
  1137. /* Return:                                                                   */
  1138. /*                                                                           */
  1139. /*   rc        0=>success                                                    */
  1140. /*             1=>failure                                                    */
  1141. /*                                                                           */
  1142. /* Assumption:                                                               */
  1143. /*                                                                           */
  1144. /*  pptb->tid is the thread we're writing the registers for.                 */
  1145. /*                                                                           */
  1146. /*****************************************************************************/
  1147. APIRET XSrvGetCoRegs(void *pCoproc_regs)
  1148. {
  1149.  APIRET           rc;
  1150.  PtraceBuffer     ptb;
  1151.  
  1152.  memset(&ptb,0,sizeof(ptb));
  1153.  ptb.Cmd    = DBG_C_ReadCoRegs;
  1154.  ptb.Value  = DBG_CO_387;
  1155.  ptb.Pid    = GetEspProcessID();
  1156.  ptb.Tid    = 0;
  1157.  ptb.Buffer = (ulong)pCoproc_regs;
  1158.  ptb.Len    = 108;
  1159.  ptb.Index  = 0; /* reserved must be 0.*/
  1160.  
  1161.  rc = DosDebug(&ptb);
  1162.  if( rc != 0 || ptb.Cmd != 0 )
  1163.   return(1);
  1164.  return(0);
  1165. }
  1166.  
  1167. /*---------------------------------------------------------------------------*/
  1168. #ifdef __ESP__
  1169. /*****************************************************************************/
  1170. /* SpinThread()                                                           919*/
  1171. /*                                                                           */
  1172. /* Description:                                                              */
  1173. /*                                                                           */
  1174. /*   This thread executes a non-debug process under control of DosDebug.     */
  1175. /*                                                                           */
  1176. /* Parameters:                                                               */
  1177. /*                                                                           */
  1178. /*   ppid               -> to the pid being debu. is for.                    */
  1179. /*                                                                           */
  1180. /* Return:                                                                   */
  1181. /*                                                                           */
  1182. /* Assumptions:                                                              */
  1183. /*                                                                           */
  1184. /*   This function is invoked via _beginthread(). It is not called.          */
  1185. /*                                                                           */
  1186. /*****************************************************************************/
  1187. void SpinThread( void *ulpid)
  1188. {
  1189.  APIRET       rc;
  1190.  PtraceBuffer ptb;
  1191.  USHORT       pid;
  1192.  ULONG        DbgCmd;
  1193.  BOOL         ErrorCondition = FALSE;
  1194.  BOOL         Success = FALSE;
  1195.  ULONG        Exception;
  1196.  
  1197.  pid = (USHORT)ulpid;
  1198.  
  1199.  /****************************************************************************/
  1200.  /* - connect to this pid.                                                   */
  1201.  /****************************************************************************/
  1202.  memset(&ptb,0,sizeof(ptb));
  1203.  
  1204.  ptb.Cmd   = DBG_C_Connect;
  1205.  ptb.Pid   = pid;
  1206.  ptb.Value = DBG_L_386;
  1207.  ptb.Addr  = 1;
  1208.  
  1209.  rc = DosDebug(&ptb);
  1210.  if( rc || (ptb.Cmd == DBG_N_Error) )
  1211.   ErrorCondition = TRUE;
  1212.  
  1213.  /****************************************************************************/
  1214.  /* - Read the registers and extract an mte. We might need to know this      */
  1215.  /*   so that we can get the module name if there is an error.               */
  1216.  /****************************************************************************/
  1217.  ptb.Cmd   = DBG_C_ReadReg;
  1218.  ptb.Pid   = pid;
  1219.  ptb.Tid   = 1;
  1220.  rc        = DosDebug(&ptb);
  1221.  if( rc || (ptb.Cmd == DBG_N_Error) )
  1222.   ErrorCondition = TRUE;
  1223.  
  1224.  /****************************************************************************/
  1225.  /* - run this pid.                                                          */
  1226.  /****************************************************************************/
  1227.  DbgCmd = DBG_C_Go;
  1228.  for( ; (ErrorCondition == FALSE) && (Success == FALSE) ; )
  1229.  {
  1230.   ptb.Cmd = DbgCmd;
  1231.   rc = DosDebug(&ptb);
  1232.   if( rc || (ptb.Cmd == DBG_N_Error) )
  1233.    { ErrorCondition = TRUE; break; }
  1234.  
  1235.   switch( ptb.Cmd )
  1236.   {
  1237.    case DBG_N_Success:
  1238.     Success = TRUE;
  1239.     break;
  1240.  
  1241.    case DBG_N_NewProc:
  1242.     SendNewProcessToQue( ptb.Value );
  1243.     DbgCmd = DBG_C_Go;
  1244.     break;
  1245.  
  1246.    case DBG_N_Exception:
  1247.     Exception = ResolveException(&ptb);
  1248.     switch( Exception )
  1249.     {
  1250.      case XCPT_SINGLE_STEP:
  1251.      case XCPT_BREAKPOINT:
  1252.       break;
  1253.  
  1254.      case XCPT_ACCESS_VIOLATION:
  1255.       break;
  1256.  
  1257.      default:
  1258.       break;
  1259.     }
  1260.     DbgCmd    = DBG_C_Continue;
  1261.     ptb.Value = XCPT_CONTINUE_SEARCH;
  1262.     break;
  1263.  
  1264.    case DBG_N_AsyncStop:
  1265.     DbgCmd = DBG_C_Term;
  1266.     break;
  1267.  
  1268.    default:
  1269.     DbgCmd = DBG_C_Go;
  1270.     break;
  1271.   }
  1272.  }
  1273.  
  1274.  _endthread();
  1275. }
  1276.  
  1277. /*****************************************************************************/
  1278. /* SendNewProcessToQue()                                                  919*/
  1279. /*                                                                           */
  1280. /* Description:                                                              */
  1281. /*                                                                           */
  1282. /*   Send a new process notification to the esp que.                         */
  1283. /*                                                                           */
  1284. /* Parameters:                                                               */
  1285. /*                                                                           */
  1286. /*   pid       process id of the new process.                                */
  1287. /*                                                                           */
  1288. /* Return:                                                                   */
  1289. /*                                                                           */
  1290. /* Assumptions:                                                              */
  1291. /*                                                                           */
  1292. /*****************************************************************************/
  1293. void SendNewProcessToQue( USHORT pid)
  1294. {
  1295.  ESP_QUE_ELEMENT     Qelement;
  1296.  
  1297.  Qelement.ChildSid  = 0;
  1298.  Qelement.ChildPid  = pid;
  1299.  Qelement.ParentSid = 0;
  1300.  Qelement.ParentPid = 0;
  1301.  
  1302.  SendMsgToEspQue( ESP_QMSG_NEW_PROCESS,&Qelement,sizeof(Qelement) );
  1303. }
  1304. #endif
  1305. /*---------------------------------------------------------------------------*/
  1306.  
  1307. /*****************************************************************************/
  1308. /* GetProcessMte()                                                           */
  1309. /*                                                                           */
  1310. /* Description:                                                              */
  1311. /*                                                                           */
  1312. /*   Get the mte associated with a given pid.                                */
  1313. /*                                                                           */
  1314. /* Parameters:                                                               */
  1315. /*                                                                           */
  1316. /*   pMte     -> to the receiver of the mte.                                 */
  1317. /*   pid      process id of the EXE that we want the mte for.                */
  1318. /*                                                                           */
  1319. /* Return:                                                                   */
  1320. /*                                                                           */
  1321. /*   rc                                                                      */
  1322. /*                                                                           */
  1323. /* Assumptions:                                                              */
  1324. /*                                                                           */
  1325. /*   This function uses the undocumented DosQProcStatus() call so be         */
  1326. /*   wary of different behavior for different versions of the operating      */
  1327. /*   system. The documentation that we have at this time is unofficial       */
  1328. /*   but should be pretty close to what eventually gets documented.          */
  1329. /*   (At this time, there are plans to document the call.)                   */
  1330. /*                                                                           */
  1331. /*   We use a stack buffer of 64K as suggested by the DosQProcStatus()       */
  1332. /*   doc.                                                                    */
  1333. /*                                                                           */
  1334. /*****************************************************************************/
  1335. #define BUFFER_SIZE 64*1024-1
  1336. APIRET GetProcessMte( USHORT pid, USHORT *pMte )
  1337. {
  1338.  void           *pProcStatBuf;
  1339.  ULONG           flags;
  1340.  qsPrec_t       *pProcRec;              /* ptr to process record section    */
  1341.  qsS16Headrec_t *p16SemRec;             /* ptr to 16 bit sem section        */
  1342.  
  1343.  /****************************************************************************/
  1344.  /* - Now get the type.                                                      */
  1345.  /****************************************************************************/
  1346.  pProcRec  = NULL;
  1347.  p16SemRec = NULL;
  1348.  
  1349.  /****************************************************************************/
  1350.  /* - Allocate a 64k buffer. This is the recommended size since a large      */
  1351.  /*   system may generate this much. It's allocated on a 64k boundary        */
  1352.  /*   because DosQprocStatus() is a 16 bit call and we don't want the        */
  1353.  /*   buffer to overlap a 64k boundary.                                      */
  1354.  /****************************************************************************/
  1355.  flags = PAG_COMMIT|PAG_READ|PAG_WRITE|OBJ_TILE;
  1356.  if( DosAllocMem( &pProcStatBuf,BUFFER_SIZE,flags) ||
  1357.      DosQProcStatus( (ULONG*)pProcStatBuf , BUFFER_SIZE )
  1358.    )
  1359.   return(1);
  1360.  
  1361.  /****************************************************************************/
  1362.  /* Define a pointer to the process subsection of information.               */
  1363.  /****************************************************************************/
  1364.  pProcRec   = (qsPrec_t       *)((qsPtrRec_t*)pProcStatBuf)->pProcRec;
  1365.  p16SemRec  = (qsS16Headrec_t *)((qsPtrRec_t*)pProcStatBuf)->p16SemRec;
  1366.  
  1367.  /****************************************************************************/
  1368.  /* - scan to the proc record for the pid.                                   */
  1369.  /****************************************************************************/
  1370.  for( ;pProcRec->pid != pid; )
  1371.  {
  1372.   /***************************************************************************/
  1373.   /* Get a pointer to the next process block and test for past end of block. */
  1374.   /***************************************************************************/
  1375.   pProcRec = (qsPrec_t *)( (char*)(pProcRec->pThrdRec) +
  1376.                                   (pProcRec->cTCB)*sizeof(qsTrec_t));
  1377.  
  1378.   if((void*)pProcRec >= (void*)p16SemRec )
  1379.   {
  1380.    pProcRec = NULL;
  1381.    break;
  1382.   }
  1383.  }
  1384.  
  1385.  if(pProcRec == NULL )
  1386.   return(1);
  1387.  
  1388.  /****************************************************************************/
  1389.  /* - give the mte back to the caller.                                       */
  1390.  /****************************************************************************/
  1391.  *pMte  = pProcRec->hMte;
  1392.  return(0);
  1393. }
  1394.