home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sherlock.zip / BRKPOINT.C < prev    next >
C/C++ Source or Header  |  1994-06-29  |  11KB  |  470 lines

  1. /*
  2. **  Sherlock - Copyright 1992, 1993, 1994
  3. **    Harfmann Software
  4. **    Compuserve: 73147,213
  5. **    All rights reserved
  6. */
  7. /*
  8. ** Define how to set/clear/list breakpoints.
  9. */
  10. #include    <stdio.h>
  11. #include    <stdlib.h>
  12. #include    <ctype.h>
  13. #include    <string.h>
  14. #include    <sys\stat.h>
  15. #define     INCL_DOSSESMGR
  16. #define     INCL_DOSEXCEPTIONS
  17.  
  18. #define     INCL_DOSPROCESS
  19. #include    <os2.h>
  20. #include    "debug.h"
  21.  
  22. #include    "Debugger.h"
  23. #include    "SrcInter.h"
  24. #include    "Source.h"
  25. #include    "BrkPoint.h"
  26.  
  27. /*
  28. ** Typedefs & structures
  29. */
  30. typedef struct _Breakpoint {
  31.     struct _Breakpoint *next;
  32.     ULONG   id;                 /* Watchpoint ID from DosDebug      */
  33.     ULONG   addr;               /* Address of the breakpoint        */
  34.     char   *desc;               /* Description of the breakpoint    */
  35.     int     oneTimeFlag;        /* true if go, false if breakpoint  */
  36. } Breakpoint;
  37.  
  38. static Breakpoint *Breakpoints = NULL;
  39.  
  40. /*
  41. ** Take a string which is supposed to be an executable address,
  42. ** and find out what that address is.
  43. */
  44. ULONG FindExecAddr(char *label, char **brkDesc)
  45. {
  46. ULONG    addr = 0;
  47. char   *desc;
  48. char   *dummy;
  49. ULONG lineNum;
  50. DebugModule *module;
  51. char    funcName[MAX_FUNCNAME];
  52. char    sourceName[CCHMAXPATH];
  53.  
  54.     /*
  55.     ** If there is no label, give up the ghost!
  56.     */
  57.     if(label == NULL)
  58.     return 0;
  59.  
  60.     /*
  61.     ** Find the address of the line given a line number.
  62.     */
  63.     if(label[0] == '.') {
  64.         module = FindModule(debugBuffer.MTE, NULL);
  65.     FindSource(module, Linearize(debugBuffer.EIP, debugBuffer.CS),
  66.            funcName, sourceName, &lineNum);
  67.  
  68.     /* Cannot find source module. */
  69.     if(strcmp(sourceName, "UNKNOWN") == 0) {
  70.         return 0;
  71.     }
  72.     lineNum = strtol(&label[1], &dummy, 0);
  73.     addr = FindSourceLine(module, lineNum, sourceName);
  74.  
  75.     /*
  76.     ** Build a string which describes the breakpoint.
  77.     */
  78.     desc = malloc(strlen(label) + strlen(sourceName) + 1);
  79.     strcpy(desc, sourceName);
  80.     strcat(desc, ":");
  81.     strcat(desc, &label[1]);
  82.     *brkDesc = desc;
  83.     return addr;
  84.     }
  85.  
  86.     /*
  87.     ** If we have a '!' in the string, then it is a compound
  88.     ** filename/line number
  89.     */
  90.     if(strchr(label, '!') != NULL) {
  91.     char        *line;
  92.  
  93.         line = strchr(label, '!');
  94.         *line = '\0';
  95.         module = FindModule(debugBuffer.MTE, NULL);
  96.     FindSource(module, Linearize(debugBuffer.EIP, debugBuffer.CS),
  97.            funcName, sourceName, &lineNum);
  98.     /* Cannot find source module. */
  99.     if(strcmp(sourceName, "UNKNOWN") == 0) {
  100.         return 0;
  101.     }
  102.     lineNum = strtol(&label[1], &dummy, 0);
  103.     addr = FindSourceLine(module, lineNum, sourceName);
  104.  
  105.     /*
  106.     ** Build a string which describes the breakpoint.
  107.     */
  108.     desc = malloc(strlen(label) + strlen(sourceName) + 1);
  109.     strcpy(desc, sourceName);
  110.     strcat(desc, ":");
  111.     strcat(desc, &label[1]);
  112.     *brkDesc = desc;
  113.     return addr;
  114.     }
  115.  
  116.     /*
  117.     ** Try finding the name as a function
  118.     */
  119.     if((addr = FindFuncAddr(NULL, label)) != 0) {
  120.     desc = malloc(strlen(label) + 1);
  121.     strcpy(desc, label);
  122.     *brkDesc = desc;
  123.     return addr;
  124.     }
  125.  
  126.     /*
  127.     ** If we could not find a function, try using the label as
  128.     ** a hex offset to break at.
  129.     */
  130.     addr = StrToAddr(label, TOADDR_CODE);
  131.     desc = malloc(strlen(label) + 1);
  132.     strcpy(desc, label);
  133.     *brkDesc = desc;
  134.     return addr;
  135. }
  136.  
  137. /*
  138. ** Take the command pointers and set up the commands.
  139. */
  140. int CommandGo(char **ptrs)
  141. {
  142. int    i;
  143. ULONG    addr;
  144. char   *desc;
  145. Breakpoint *bp;
  146.  
  147.     /*
  148.     ** If no parameter, then just go.
  149.     */
  150.     if(ptrs[2] == NULL)
  151.     return DBG_C_Go;
  152.  
  153.     /*
  154.     ** Find the address of the breakpoint.
  155.     */
  156.     addr = FindExecAddr(ptrs[2], &desc);
  157.     if(addr == 0) {
  158.     fprintf(logFile, "FUNCTION NOT FOUND!\n");
  159.     return -1;
  160.     }
  161.  
  162.     /*
  163.     ** Set the breakpoint to the address specified.
  164.     */
  165.     debugBuffer.Addr  = addr;
  166.     debugBuffer.Len   = 1;
  167.     debugBuffer.Index = 0;
  168.     debugBuffer.Value = DBG_W_Local | DBG_W_Execute;
  169.     DispatchCommand(DBG_C_SetWatch);
  170.  
  171.     /*
  172.     ** Add the breakpoint to the list, and tag it as a 'go'
  173.     ** breakpoint which will unconditionally be cleared the
  174.     ** next time we get back from the debuggee.
  175.     */
  176.     if(Breakpoints) {
  177.     for(i=0, bp=Breakpoints; bp->next; i++, bp=bp->next) ;
  178.     bp->next = malloc(sizeof(Breakpoint));
  179.     bp = bp->next;
  180.     } else {
  181.     i = 0;
  182.     Breakpoints = bp = malloc(sizeof(Breakpoint));
  183.     }
  184.     bp->id = debugBuffer.Index;
  185.     bp->addr = addr;
  186.     bp->next = NULL;
  187.     bp->desc = desc;
  188.     bp->oneTimeFlag = 1;
  189.     return DBG_C_Go;
  190. }
  191.  
  192. /*
  193. ** Do a single step to the next source instruction.
  194. */
  195. int CommandStep(char **ptrs)
  196. {
  197. int        i;
  198. ULONG        addr;
  199. ULONG        lineNum;
  200. Breakpoint *bp;
  201. DebugModule *module;
  202. char        funcName[MAX_FUNCNAME];
  203. char        funcName2[MAX_FUNCNAME];
  204. char        sourceName[CCHMAXPATH];
  205.  
  206.     /*
  207.     ** Provide a reference to keep from getting a compile warning.
  208.     */
  209.     ptrs;
  210.  
  211.     /*
  212.     ** Find the address specified.
  213.     */
  214.     module = FindModule(debugBuffer.MTE, NULL);
  215.     FindSource(module, Linearize(debugBuffer.EIP, debugBuffer.CS),
  216.            funcName, sourceName, &lineNum);
  217.     for(i=0; i<100; i++) {
  218.     lineNum++;
  219.     addr = FindSourceLine(module, lineNum, sourceName);
  220.     if(addr != 0) {
  221.         FindSource(module, addr, funcName2, sourceName, &lineNum);
  222.         if(strcmp(funcName2, funcName) == 0)
  223.         break;
  224.         fprintf(logFile, "Unable to find next line.  Next function found!\n");
  225.         return -1;
  226.     }
  227.     }
  228.  
  229.     /*
  230.     ** Did we find a line
  231.     */
  232.     if(addr == 0) {
  233.     fprintf(logFile, "Unable to find next line.\n");
  234.     return -1;
  235.     }
  236.  
  237.     /*
  238.     ** Set the breakpoint at the address specified.
  239.     */
  240.     debugBuffer.Addr  = addr;
  241.     debugBuffer.Len   = 1;
  242.     debugBuffer.Index = 0;
  243.     debugBuffer.Value = DBG_W_Local | DBG_W_Execute;
  244.     DispatchCommand(DBG_C_SetWatch);
  245.  
  246.     /*
  247.     ** Add the breakpoint to the list, and tag it as a 'go'
  248.     ** breakpoint which will unconditionally be cleared the
  249.     ** next time we get back from the debuggee.
  250.     */
  251.     if(Breakpoints) {
  252.     for(i=0, bp=Breakpoints; bp->next; i++, bp=bp->next) ;
  253.     bp->next = malloc(sizeof(Breakpoint));
  254.     bp = bp->next;
  255.     } else {
  256.     i = 0;
  257.     Breakpoints = bp = malloc(sizeof(Breakpoint));
  258.     }
  259.     bp->id = debugBuffer.Index;
  260.     bp->addr = addr;
  261.     bp->next = NULL;
  262.     bp->desc = NULL;
  263.     bp->oneTimeFlag = 1;
  264.     return DBG_C_Go;
  265. }
  266.  
  267. /*
  268. ** Take the command pointers and set up the commands.
  269. */
  270. int CommandBreakpoint(char **ptrs)
  271. {
  272. int    i;
  273. ULONG    addr;
  274. char   *dummy;
  275. char   *desc;
  276. Breakpoint *bp;
  277.  
  278.     /*
  279.     ** Something to do with breakpoints.  Find out what and do it.
  280.     */
  281.     switch(tolower(ptrs[1][1])) {
  282.     /*
  283.     ** Set a breakpoint.
  284.     */
  285.     case 'p': {
  286.         int err;
  287.  
  288.         /*
  289.         ** Get the address of the breakpoint.
  290.         */
  291.         addr = FindExecAddr(ptrs[2], &desc);
  292.         if(addr == 0) {
  293.         fprintf(logFile, "FUNCTION NOT FOUND!\n");
  294.         free(desc);
  295.         return -1;
  296.         }
  297.  
  298.         /*
  299.         ** Set the breakpoint
  300.         */
  301.         debugBuffer.Addr  = addr;
  302.         debugBuffer.Len   = 1;
  303.         debugBuffer.Index = 0;
  304.         debugBuffer.Value = DBG_W_Local | DBG_W_Execute;
  305.         err = DispatchCommand(DBG_C_SetWatch);
  306.         if(debugBuffer.Cmd != DBG_N_Success) {
  307.         fprintf(logFile, "ERROR CREATING BREAKPOINT %d!\n", err);
  308.         free(desc);
  309.         return -1;
  310.         }
  311.  
  312.         /*
  313.         ** Connect it to the list.
  314.         */
  315.         if(Breakpoints) {
  316.         for(i=0, bp=Breakpoints; bp->next; i++, bp=bp->next) ;
  317.         bp->next = malloc(sizeof(Breakpoint));
  318.         bp = bp->next;
  319.         } else {
  320.         i = 0;
  321.         Breakpoints = bp = malloc(sizeof(Breakpoint));
  322.         }
  323.         bp->id = debugBuffer.Index;
  324.         bp->addr = addr;
  325.         bp->next = NULL;
  326.         bp->desc = desc;
  327.         bp->oneTimeFlag = 0;
  328.         break;
  329.     }
  330.  
  331.     /*
  332.     ** Clear a breakpoint.
  333.     */
  334.     case 'c': {
  335.         Breakpoint *prior;
  336.         int num;
  337.  
  338.         /*
  339.         ** Find the watch number, and then the watchpoint id.
  340.         */
  341.         if(ptrs[2][0] == '*') {
  342.         FreeAllBreakpoints();
  343.         break;
  344.         } else {
  345.         i = strtol(ptrs[2], &dummy, 0);
  346.         prior = bp = Breakpoints;
  347.         for(i=0; bp && i<num; i++) {
  348.             prior = bp;
  349.             bp = bp->next;
  350.         }
  351.         }
  352.  
  353.         /*
  354.         ** Make sure the breakpoint exists.
  355.         */
  356.         if(bp == NULL) {
  357.         fprintf(logFile, "ILLEGAL BREAKPOINT NUMBER!\n");
  358.         return -1;
  359.         }
  360.  
  361.         /*
  362.         ** Remove the breakpoint from the list and from the debuggee.
  363.         */
  364.         if(bp == Breakpoints) {
  365.         Breakpoints = bp->next;
  366.         }
  367.         debugBuffer.Index = bp->id;
  368.         if(bp->desc)
  369.         free(bp->desc);
  370.         free(bp);
  371.         DispatchCommand(DBG_C_ClearWatch);
  372.         break;
  373.     }
  374.  
  375.     /*
  376.     ** List all of the breakpoints.
  377.     */
  378.     case 'l': {
  379.         for(i=0, bp=Breakpoints; bp; i++, bp=bp->next) {
  380.         fprintf(logFile, "Breakpoint [%d]:%08x\n\t%s\n",
  381.             i, bp->addr, bp->desc);
  382.         }
  383.         break;
  384.     }
  385.     }
  386.     return -1;
  387. }
  388.  
  389. /*
  390. ** Free all breakpoints.
  391. */
  392. void FreeAllBreakpoints()
  393. {
  394. Breakpoint *bp, *next;
  395.  
  396.     for(bp=Breakpoints; bp; ) {
  397.         debugBuffer.Index = bp->id;
  398.     DispatchCommand(DBG_C_ClearWatch);
  399.     next = bp->next;
  400.     if(bp->desc)
  401.         free(bp->desc);
  402.         free(bp);
  403.         bp = next;
  404.     }
  405.     Breakpoints = NULL;
  406. }
  407.  
  408. /*
  409. ** Answer whether a breakpoint is actually set at the given address.
  410. */
  411. int isValidBreakpoint(ULONG addr)
  412. {
  413. Breakpoint *bp;
  414. Breakpoint *tmp;
  415. int        isValid = 0;
  416. int        firstDead = 1;
  417.  
  418.     /*
  419.     ** First, see if this is an expected breakpoint.
  420.     */
  421.     for(bp=Breakpoints; bp; bp=bp->next) {
  422.         if(bp->addr == addr) {
  423.         isValid = 1;
  424.             debugBuffer.Addr  = addr;
  425.             debugBuffer.Len   = 1;
  426.             debugBuffer.Index = 0;
  427.             debugBuffer.Value = DBG_W_Local | DBG_W_Execute;
  428.         DispatchCommand(DBG_C_SetWatch);
  429.         break;
  430.         }
  431.     }
  432.  
  433.     /*
  434.     ** Now, remove all breakpoints.
  435.     */
  436.     for(bp=Breakpoints; bp;bp=bp->next) {
  437.         debugBuffer.Index = bp->id;
  438.     DispatchCommand(DBG_C_ClearWatch);
  439.     }
  440.  
  441.     /*
  442.     ** Now, go through the list again, setting only the 'permanent' breakpoints.
  443.     */
  444.     tmp = NULL;
  445.     for(bp=Breakpoints; bp;) {
  446.         if(!bp->oneTimeFlag) {
  447.             debugBuffer.Addr  = bp->addr;
  448.             debugBuffer.Len   = 1;
  449.             debugBuffer.Index = 0;
  450.             debugBuffer.Value = DBG_W_Local | DBG_W_Execute;
  451.         DispatchCommand(DBG_C_SetWatch);
  452.             if(tmp)
  453.                 tmp->next = bp;
  454.             else
  455.                 tmp = bp;
  456.             bp = bp->next;
  457.         } else {
  458.             Breakpoint *tmp2;
  459.  
  460.             tmp2 = bp;
  461.         bp = bp->next;
  462.         if(tmp2->desc)
  463.         free(tmp2->desc);
  464.             free(tmp2);
  465.         }
  466.     }
  467.     Breakpoints = tmp;
  468.     return isValid;
  469. }
  470.