home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / c / djgpp / go32 / debug.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-30  |  18.5 KB  |  726 lines

  1. /* This is file DEBUG.C */
  2. /*
  3. ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* History:175,26 */
  16. #include <stdio.h>
  17. #include <setjmp.h>
  18. #include <math.h>
  19. #include <dos.h>
  20.  
  21. #include "build.h"
  22. #include "types.h"
  23. #include "gdt.h"
  24. #include "tss.h"
  25. #include "utils.h"
  26. #include "unassmbl.h"
  27. #include "syms.h"
  28. #include "paging.h"
  29. #include "npx.h"
  30. #include "mono.h"
  31.  
  32. extern int was_exception, have_80387;
  33. jmp_buf back_to_debugger;
  34. int can_longjmp=0;
  35.  
  36. #if DEBUGGER
  37.  
  38. extern word32 dr[8];
  39. extern word32 dr0, dr1, dr2, dr3, dr6, dr7;
  40.  
  41. typedef struct {
  42.     char *cp;
  43.     int t;
  44.     } item;
  45.  
  46. my_getline(char *buf, char *lasttoken)
  47. {
  48.   int idx, i, ch;
  49.   if (use_ansi)
  50.     printf("\033[0;32m");
  51.   mono_attr = MONO_NORMAL;
  52.   printf(">> %s", lasttoken);
  53.   for (i=0; lasttoken[i]; i++)
  54.     mputchar(8);
  55.   while (!kbhit());
  56.   for (i=0; lasttoken[i]; i++)
  57.     mputchar(' ');
  58.   for (i=0; lasttoken[i]; i++)
  59.     mputchar(8);
  60.   idx = 0;
  61.   if (use_ansi)
  62.     printf("\033[1;33m");
  63.   mono_attr = MONO_BOLD;
  64.   while (1)
  65.   {
  66.     ch = getch();
  67.     switch (ch)
  68.     {
  69.       case 10:
  70.       case 13:
  71.         buf[idx] = 0;
  72.         if (!idx && lasttoken[0])
  73.           printf("\r  \r");
  74.         else
  75.           mputchar('\n');
  76.         if (use_ansi)
  77.           printf("\033[0m");
  78.         mono_attr = MONO_NORMAL;
  79.         return;
  80.       case 27:
  81.         while (idx)
  82.         {
  83.           printf("\b \b");
  84.           idx--;
  85.         }
  86.         break;
  87.       case 8:
  88.         if (idx)
  89.         {
  90.           printf("\b \b");
  91.           idx--;
  92.         }
  93.         break;
  94.       default:
  95.         mputchar(ch);
  96.         buf[idx++] = ch;
  97.         break;
  98.     }
  99.   }
  100. }
  101.  
  102. typedef enum { Zero, Unknown, CONT, STEP, NEXT, REGS, SET, HELP, LIST,
  103. DUMP, QUIT, BREAK, STATUS, WHERE, DUMP_A, DUMP_B, DUMP_W, WHEREIS, XNPX,
  104. CLS };
  105.  
  106. extern struct {
  107.   char *name;
  108.   int size;
  109.   int ofs;
  110.   } regs[];
  111.  
  112. item cmds[] = {
  113.     "g", CONT,
  114.     "go", CONT,
  115.     "cont", CONT,
  116.     "c", CONT,
  117.     "step", STEP,
  118.     "s", STEP,
  119.     "next", NEXT,
  120.     "n", NEXT,
  121.     "regs", REGS,
  122.     "r", REGS,
  123.     "set", SET,
  124.     "help", HELP,
  125.     "h", HELP,
  126.     "?", HELP,
  127.     "list", LIST,
  128.     "l", LIST,
  129.     "u", LIST,
  130.     "dump", DUMP,
  131.     "d", DUMP,
  132.     "da", DUMP_A,
  133.     "db", DUMP_B,
  134.     "dw", DUMP_W,
  135.     "dd", DUMP,
  136.     "quit", QUIT,
  137.     "q", QUIT,
  138.     "break", BREAK,
  139.     "b", BREAK,
  140.     "status", STATUS,
  141.     "where", WHERE,
  142.     "whereis", WHEREIS,
  143.     "npx", XNPX,
  144.     "cls", CLS,
  145.     0, 0
  146.     };
  147.  
  148. extern int debug_mode;
  149.  
  150. debugger()
  151. {
  152.   char buf[140], token[10];
  153.   char buf2[140], *name, lasttoken[140];
  154.   int i, n, s, len, rem_cmd, cmd, vstep, found;
  155.   word32 vaddr, v, rem_v, olddr7;
  156.   int32 delta;
  157.  
  158.   dr0 = dr1 = dr2 = ARENA;
  159.   dr3 = syms_name2val("_main") + ARENA;
  160.   if (undefined_symbol)
  161.     dr3 = tss_ptr->tss_eip + ARENA;
  162.   rem_cmd = Zero;
  163.   lasttoken[0] = 0;
  164.   setjmp(back_to_debugger);
  165.   can_longjmp = 1;
  166.   while (1)
  167.   {
  168.     if (debug_mode)
  169.     {
  170.       int found;
  171.       my_getline(buf, lasttoken);
  172.       token[0] = 0;
  173.       if (sscanf(buf, "%s %[^\n]", token, buf) < 2)
  174.         buf[0] = 0;
  175.       if (token[0])
  176.         strcpy(lasttoken, token);
  177.       cmd = rem_cmd;
  178.       found = 0;
  179.       for (i=0; cmds[i].cp; i++)
  180.         if (strcmp(cmds[i].cp, token) == 0)
  181.         {
  182.           cmd = cmds[i].t;
  183.           found = 1;
  184.         }
  185.       if (!found && token[0])
  186.         cmd = Unknown;
  187.       if (rem_cmd != cmd)
  188.         vaddr = tss_ptr->tss_eip;
  189.     }
  190.     else
  191.     {
  192.       cmd = CONT;
  193.       debug_mode = 1;
  194.     }
  195.     switch (cmd)
  196.     {
  197.       case HELP:
  198.         printf("Commands:\n"
  199.                "go <v>\tg\tgo, stop at <v>\n"
  200.                "cont\tc\tcontinue execution\n"
  201.                "step\ts\tstep through current instruction\n"
  202.                "next\tn\tstep to next instruction\n"
  203.                "list\tl u\tlist instructions (takes addr, count)\n"
  204.                "dump\td\tdump memory (takes addr, count)\n"
  205.                "break\tb\tset breakpoint (takes which, addr)\n"
  206.                "status\t\tbreakpoint status\n"
  207.                "regs\tr\tprint registers\n"
  208.                "set\t\tset register/memory\n"
  209.                "npx\t\tdisplay 80387 contents\n"
  210.                "cls\t\tclear screen\n"
  211.                "help\th,?\tprint help\n"
  212.                "quit\tq\tquit\n"
  213.                );
  214.         break;
  215.       case CONT:
  216.         sscanf(buf, "%s", buf);
  217.         if (buf[0])
  218.         {
  219.           v = syms_name2val(buf);
  220.           if (undefined_symbol)
  221.             break;
  222.           dr3 = v+ARENA;
  223.           dr7 |= 0xc0;
  224.         }
  225.         else
  226.           dr7 &= ~0xc0;
  227.         olddr7 = dr7;
  228.         dr7 = 0;
  229.         tss_ptr->tss_eflags |= 0x0100;
  230.         go_til_stop();
  231.         dr7 = olddr7;
  232.         if (tss_ptr->tss_irqn == 1)
  233.         {
  234.           tss_ptr->tss_eflags &= ~0x0100;
  235.           tss_ptr->tss_eflags |= 0x10000;
  236.           go_til_stop();
  237.           if (tss_ptr->tss_irqn == 1)
  238.             tssprint(tss_ptr);
  239.         }
  240.         print_reason();
  241.         dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
  242.         break;
  243.       case STEP:
  244.         if (rem_cmd != cmd)
  245.           n = 1;
  246.         sscanf(buf, "%d", &n);
  247.         tss_ptr->tss_eflags |= 0x0100;
  248.         for (i=0; i<n; i++)
  249.         {
  250.           olddr7 = dr7;
  251.           dr7 = 0;
  252.           go_til_stop();
  253.           dr7 = olddr7;
  254.           print_reason();
  255.           dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
  256.           if (tss_ptr->tss_irqn != 1)
  257.             break;
  258.         }
  259.         tss_ptr->tss_eflags &= ~0x0100;
  260.         break;
  261.       case NEXT:
  262.         if (rem_cmd != cmd)
  263.           n = 1;
  264.         sscanf(buf, "%d", &n);
  265.         for (i=0; i<n; i++)
  266.         {
  267.           olddr7 = dr7;
  268.           dr7 &= ~0xc0;
  269.           dr7 |= 0xc0;
  270.           if (last_unassemble_unconditional ||
  271.               last_unassemble_jump)
  272.             tss_ptr->tss_eflags |= 0x0100; /* step */
  273.           else
  274.             tss_ptr->tss_eflags &= ~0x0100;
  275.           go_til_stop();
  276.           dr7 = olddr7;
  277.           print_reason();
  278.           dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
  279.           if (tss_ptr->tss_irqn != 1)
  280.             break;
  281.         }
  282.         tss_ptr->tss_eflags &= ~0x0100;
  283.         break;
  284.       case WHERE:
  285.         v = tss_ptr->tss_ebp;
  286.         vaddr = tss_ptr->tss_eip;
  287.         printf("0x%08lx %s", vaddr, syms_val2name(vaddr, &delta));
  288.         name = syms_val2line(vaddr, &i, 0);
  289.         if (name)
  290.           printf(", line %d in file %s", i, name);
  291.         else if (delta)
  292.           printf("%+ld", delta);
  293.         mputchar('\n');
  294.         do {
  295.           if (v == 0)
  296.             break;
  297.           rem_v = peek32(v+ARENA);
  298.           if (rem_v == 0)
  299.             break;
  300.           vaddr = peek32(v+ARENA+4);
  301.           printf("0x%08lx %s", vaddr, syms_val2name(vaddr, &delta));
  302.           name = syms_val2line(vaddr, &i, 0);
  303.           if (name)
  304.             printf(", line %d in file %s", i, name);
  305.           else if (delta)
  306.             printf("%+ld", delta);
  307.           mputchar('\n');
  308.           v = rem_v;
  309.         } while ((v>=tss_ptr->tss_esp) && (v<0x90000000L));
  310.         break;
  311.       case WHEREIS:
  312.         sscanf(buf, "%s", buf2);
  313.         if (strpbrk(buf2, "*?"))
  314.         {
  315.           syms_listwild(buf2);
  316.           break;
  317.         }
  318.         if (buf2[0])
  319.           vaddr = syms_name2val(buf2);
  320.         if (undefined_symbol)
  321.           break;
  322.         name = syms_val2name(vaddr, &delta);
  323.         printf("0x%08lx %s", vaddr, name);
  324.         if (delta)
  325.           printf("+%lx", delta);
  326.         name = syms_val2line(vaddr, &i, 0);
  327.         if (name)
  328.           printf(", line %d in file %s", i, name);
  329.         mputchar('\n');
  330.         break;
  331.       case LIST:
  332.         if (rem_cmd != cmd)
  333.           n = 10;
  334.         buf2[0] = 0;
  335.         sscanf(buf, "%s %d", buf2, &n);
  336.         if (buf2[0] && strcmp(buf2, "."))
  337.           vaddr = syms_name2val(buf2);
  338.         if (undefined_symbol)
  339.           break;
  340.         for (i=0; i<n; i++)
  341.         {
  342.           vaddr = unassemble(vaddr, 0);
  343.           i += last_unassemble_extra_lines;
  344. /*          if (last_unassemble_unconditional)
  345.             break; */
  346.         }
  347.         break;
  348.       case DUMP_A:
  349.         buf2[0] = 0;
  350.         sscanf(buf, "%s %d", buf2, &n);
  351.         if (buf2[0])
  352.           vaddr = syms_name2val(buf2);
  353.         if (undefined_symbol)
  354.           break;
  355.         while (1)
  356.         {
  357.           word8 ch;
  358.           if (!page_is_valid(vaddr+ARENA))
  359.           {
  360.             printf("<bad address>\n");
  361.             break;
  362.           }
  363.           ch = peek8(vaddr+ARENA);
  364.           if (ch == 0)
  365.           {
  366.             mputchar('\n');
  367.             break;
  368.           }
  369.           if (ch < ' ')
  370.             printf("^%c", ch+'@');
  371.           else if ((ch >= ' ') && (ch < 0x7f))
  372.             mputchar(ch);
  373.           else if (ch == 0x7f)
  374.             printf("^?");
  375.           else if ((ch >= 0x80) && (ch < 0xa0))
  376.             printf("M-^%c", ch-0x80+'@');
  377.           else if (ch >= 0xa0)
  378.             printf("M-%c", ch-0x80);
  379.           vaddr++;
  380.         }
  381.         break;
  382.       case DUMP:
  383.       case DUMP_B:
  384.       case DUMP_W:
  385.         if (rem_cmd != cmd)
  386.           n = 4;
  387.         buf2[0] = 0;
  388.         sscanf(buf, "%s %d", buf2, &n);
  389.         if (buf2[0])
  390.           vaddr = syms_name2val(buf2);
  391.         if (undefined_symbol)
  392.           break;
  393.         s = 0;
  394.         len = n + (~((vaddr&15)/4-1) & 3);
  395.         for (i=-(vaddr&15)/4; i<len; i++)
  396.         {
  397.           if ((s&3) == 0)
  398.             printf("0x%08lx:", vaddr+i*4);
  399.           if ((i>=0) && (i<n))
  400.             printf(" 0x%08lx", peek32(vaddr+i*4+ARENA));
  401.           else
  402.             printf("           ");
  403.           if ((s & 3) == 3)
  404.           {
  405.             int j, c;
  406.             printf("  ");
  407.             for (j=0; j<16; j++)
  408.               if ((j+i*4-12>=0) && (j+i*4-12 < n*4))
  409.               {
  410.                 c = peek8(vaddr+j+i*4-12+ARENA);
  411.                 if (c<' ')
  412.                   mputchar('.');
  413.                 else
  414.                   mputchar(c);
  415.               }
  416.               else
  417.                 mputchar(' ');
  418.             printf("\n");
  419.           }
  420.           s++;
  421.         }
  422.         if (s & 3)
  423.           printf("\n");
  424.         vaddr += n*4;
  425.         break;
  426.       case BREAK:
  427.         vaddr = n = 0;
  428.         buf2[0] = 0;
  429.         sscanf(buf, "%d %s", &n, buf2);
  430.         if (buf2[0])
  431.           vaddr = syms_name2val(buf2);
  432.         if (undefined_symbol)
  433.           break;
  434.         dr[n] = vaddr + ARENA;
  435.         if (vaddr == 0)
  436.           dr7 &= ~(2 << (n*2));
  437.         else
  438.           dr7 |= 2 << (n*2);
  439.       case STATUS:
  440.         s = 0;
  441.         for (n=0; n<4; n++)
  442.         {
  443.           s = 1;
  444.           name = syms_val2name(dr[n]-ARENA, &delta);
  445.           printf("  dr%d  %s", n, name);
  446.           if (delta)
  447.             printf("+%#lx", delta);
  448.           if (name[0] != '0')
  449.             printf(" (0x%lx)", dr[n] - ARENA);
  450.           if (~dr7 & (3 << (n*2)))
  451.             printf(" (disabled)");
  452.           mputchar('\n');
  453.         }
  454.         if (s == 0)
  455.           printf("  No breakpoints set\n");
  456.         break;
  457.       case REGS:
  458.         tssprint(tss_ptr);
  459.         unassemble(tss_ptr->tss_eip, 0);
  460.         break;
  461.       case SET:
  462.         cmd = Zero;
  463.         lasttoken[0] = 0;
  464.         buf2[0] = 0;
  465.         len = sscanf(buf, "%s %s", buf2, buf);
  466.         if (buf2[0] == 0)
  467.         {
  468.           break;
  469.         }
  470.         if (len > 1)
  471.         {
  472.           v = syms_name2val(buf);
  473.           if (undefined_symbol)
  474.             break;
  475.         }
  476.         found = 0;
  477.         for (i=0; regs[i].name; i++)
  478.           if (strcmp(regs[i].name, buf2) == 0)
  479.           {
  480.             found = 1;
  481.             if (len > 1)
  482.             {
  483.               switch (regs[i].size)
  484.               {
  485.                 case 1:
  486.                   *(word8 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  487.                   break;
  488.                 case 2:
  489.                   *(word16 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  490.                   break;
  491.                 case 4:
  492.                   *(word32 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  493.                   break;
  494.               }
  495.             }
  496.             else
  497.             {
  498.               switch (regs[i].size)
  499.               {
  500.                 case 1:
  501.                   printf("%02x ", *(word8 *)((word8 *)tss_ptr + regs[i].ofs));
  502.                   my_getline(buf, "");
  503.                   if (buf[0])
  504.                   {
  505.                     v = syms_name2val(buf);
  506.                     if (undefined_symbol)
  507.                       break;
  508.                     *(word8 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  509.                   }
  510.                   break;
  511.                 case 2:
  512.                   printf("%04x ", *(word16 *)((word16 *)tss_ptr + regs[i].ofs));
  513.                   my_getline(buf, "");
  514.                   if (buf[0])
  515.                   {
  516.                     v = syms_name2val(buf);
  517.                     if (undefined_symbol)
  518.                       break;
  519.                     *(word16 *)((word16 *)tss_ptr + regs[i].ofs) = v;
  520.                   }
  521.                   break;
  522.                 case 4:
  523.                   printf("%08lx ", *(word32 *)((word32 *)tss_ptr + regs[i].ofs));
  524.                   my_getline(buf, "");
  525.                   if (buf[0])
  526.                   {
  527.                     v = syms_name2val(buf);
  528.                     if (undefined_symbol)
  529.                       break;
  530.                     *(word32 *)((word32 *)tss_ptr + regs[i].ofs) = v;
  531.                   }
  532.                   break;
  533.               }
  534.             }
  535.             break;
  536.           }
  537.         if (found)
  538.           break;
  539.         vaddr = syms_name2val(buf2);
  540.         if (undefined_symbol)
  541.           break;
  542.         if (len < 2)
  543.         {
  544.           v = syms_name2val(buf);
  545.           if (undefined_symbol)
  546.             break;
  547.           poke32(vaddr, v);
  548.         }
  549.         while (1)
  550.         {
  551.           printf("0x%08lx 0x%08lx", vaddr, peek32(vaddr+ARENA));
  552.           my_getline(buf, "");
  553.           if (buf[0])
  554.           {
  555.             if (strcmp(buf, ".") == 0)
  556.               break;
  557.             poke32(vaddr+ARENA, syms_name2val(buf));
  558.           }
  559.           vaddr += 4;
  560.         }
  561.         break;
  562.       case XNPX:
  563.         if (!have_80387)
  564.         {
  565.           printf("No 80387 present\n");
  566.           break;
  567.         }
  568.         save_npx();
  569.         printf("Control: 0x%04lx  Status: 0x%04lx  Tag: 0x%04lx\n",
  570.                npx.control, npx.status, npx.tag);
  571.         for (i=0; i<8; i++)
  572.         {
  573.           double d;
  574.           int tag;
  575.           int tos = (npx.status >> 11) & 7;
  576.           printf("st(%d)  ", i);
  577.           if (npx.reg[i].sign)
  578.             mputchar('-');
  579.           else
  580.             mputchar('+');
  581.           printf(" %04x %04x %04x %04x e %04x    ",
  582.                  npx.reg[i].sig3,
  583.                  npx.reg[i].sig2,
  584.                  npx.reg[i].sig1,
  585.                  npx.reg[i].sig0,
  586.                  npx.reg[i].exponent);
  587.           tag = (npx.tag >> (((i+tos)%8)*2)) & 3;
  588.           switch (tag)
  589.           {
  590.             case 0:
  591.               printf("Valid");
  592.               if (((int)npx.reg[i].exponent-16382 < 1000) &&
  593.                   ((int)npx.reg[i].exponent-16382 > -1000))
  594.               {
  595.                 d = npx.reg[i].sig3/65536.0 + npx.reg[i].sig2/65536.0/65536.0
  596.                   + npx.reg[i].sig1/65536.0/65536.0/65536.0;
  597.                 d = ldexp(d,(int)npx.reg[i].exponent-16382);
  598.                 if (npx.reg[i].sign)
  599.                   d = -d;
  600.                 printf("  %.16lg", d);
  601.               }
  602.               else
  603.                 printf("  (too big to display)");
  604.               mputchar('\n');
  605.               break;
  606.             case 1:
  607.               printf("Zero\n");
  608.               break;
  609.             case 2:
  610.               printf("Special\n");
  611.               break;
  612.             case 3:
  613.               printf("Empty\n");
  614.               break;
  615.           }
  616.         }
  617.         break;
  618.       case CLS:
  619.         if (use_mono)
  620.           mputchar(12);
  621.         else
  622.         {
  623.           _AH=15;
  624.           geninterrupt(0x10);
  625.           _AH = 0;
  626.           geninterrupt(0x10);
  627.           mputchar('\n');
  628.         }
  629.         break;
  630.       case QUIT:
  631.         return;
  632.       case Zero:
  633.         break;
  634.       default:
  635.         printf("Unknown command\n");
  636.         lasttoken[0] = 0;
  637.         cmd = Zero;
  638.         break;
  639.     }
  640.     if (undefined_symbol)
  641.     {
  642.       lasttoken[0] = 0;
  643.       cmd = Zero;
  644.       undefined_symbol = 0;
  645.     }
  646.     rem_cmd = cmd;
  647.     debug_mode = 1;
  648.   }
  649. }
  650. #endif /* DEBUGGER */
  651.  
  652. go_til_stop()
  653. {
  654.   while (1)
  655.   {
  656.     go32();
  657.     if (!was_exception)
  658.       return;
  659.     if (exception_handler())
  660.       return;
  661.   }
  662. }
  663.  
  664. #if DEBUGGER
  665. print_reason()
  666. {
  667.   int n, i;
  668.   i = tss_ptr->tss_irqn;
  669.   if ((i == 0x21) && ((tss_ptr->tss_eax & 0xff00) == 0x4c00))
  670.   {
  671.     tss_ptr->tss_eip -= 2; /* point to int 21h */
  672.     return;
  673.   }
  674.   if (use_ansi)
  675.     printf("\033[1;34m");
  676.   mono_attr = MONO_BOLD;
  677.   if (i != 1)
  678.   {
  679.     tssprint(tss_ptr);
  680.     if (tss_ptr != &a_tss)
  681.     {
  682.       printf("NOT a_tss\n");
  683.     }
  684.     if (i == 0x79)
  685.       printf("Keyboard interrupt\n");
  686.     else if (i == 0x75)
  687.     {
  688.       save_npx();
  689.       printf("Numeric Exception (");
  690.       if ((npx.status & 0x0241) == 0x0241)
  691.         printf("stack overflow");
  692.       else if ((npx.status & 0x0241) == 0x0041)
  693.         printf("stack underflow");
  694.       else if (npx.status & 1)
  695.         printf("invalid operation");
  696.       else if (npx.status & 2)
  697.         printf("denormal operand");
  698.       else if (npx.status & 4)
  699.         printf("divide by zero");
  700.       else if (npx.status & 8)
  701.         printf("overflow");
  702.       else if (npx.status & 16)
  703.         printf("underflow");
  704.       else if (npx.status & 32)
  705.         printf("loss of precision");
  706.       printf(") at eip=0x%08lx\n", npx.eip);
  707.       unassemble(npx.eip, 0);
  708.     }
  709.     else
  710.     {
  711.       printf("exception %d (%#02x) occurred", i, i);
  712.       if ((i == 8) || ((i>=10) && (i<=14)))
  713.         printf(", error code=%#lx", tss_ptr->tss_error);
  714.       mputchar('\n');
  715.     }
  716.   }
  717.   for (n=0; n<3; n++)
  718.     if ((dr6 & (1<<n)) && (dr7 & (3<<(n*2))))
  719.       printf("breakpoint %d hit\n", n);
  720.   if (use_ansi)
  721.     printf("\033[0m");
  722.   mono_attr = MONO_NORMAL;
  723. }
  724.  
  725. #endif /* DEBUGGER */
  726.