home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / prgramer / unix / emx / test / debug.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  6.6 KB  |  339 lines

  1. /* debug.c (emx+gcc) */
  2.  
  3. /* Test ptrace() */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <process.h>
  9. #include <errno.h>
  10. #include <sys/ptrace.h>
  11. #include <sys/user.h>
  12. #include <sys/reg.h>
  13.  
  14. typedef unsigned char byte;
  15.  
  16. struct reg
  17. {
  18.   char *name;
  19.   int regno;
  20.   unsigned value;
  21. };
  22.  
  23. struct breakpoint
  24. {
  25.   struct breakpoint *next;
  26.   unsigned addr;
  27.   byte save;
  28. };
  29.  
  30. #define N_EIP 8
  31.  
  32. static struct reg regs[] =
  33. {
  34.   {"eax", EAX},
  35.   {"ebx", EBX},
  36.   {"ecx", ECX},
  37.   {"edx", EDX},
  38.   {"esi", ESI},
  39.   {"edi", EDI},
  40.   {"esp", UESP},
  41.   {"ebp", EBP},
  42.   {"eip", EIP},
  43.   {NULL, 0}
  44. };
  45.  
  46.  
  47. static int pid;
  48. static int silent;
  49. static int auto_switch;
  50. static int uaddr;
  51. static long dump_addr;
  52. static struct breakpoint *breakpoints = NULL;
  53.  
  54. static void show_regs (void)
  55. {
  56.   int i, j, r;
  57.  
  58.   j = 4;
  59.   for (i = 0; regs[i].name != NULL; ++i)
  60.     {
  61.       errno = 0;
  62.       r = ptrace (PTRACE_PEEKUSER, pid, uaddr + regs[i].regno * 4, 0);
  63.       if (errno != 0) perror ("ptrace");
  64.       regs[i].value = r;
  65.       if (j == 4)
  66.         {
  67.           j = 0; putchar ('\n');
  68.         }
  69.       ++j;
  70.       printf ("%s=%.8x ", regs[i].name, r);
  71.     }
  72.   errno = 0;
  73.   r = ptrace (PTRACE_PEEKTEXT, pid, regs[N_EIP].value, 0);
  74.   if (errno == 0)
  75.     for (i = 0; i < 4; ++i)
  76.       {
  77.         printf ("%.2x ", r & 0xff);
  78.         r >>= 8;
  79.       }
  80.   putchar ('\n');
  81. }
  82.  
  83.  
  84. static void insert_bp (struct breakpoint *bp, int eip)
  85. {
  86.   int r;
  87.  
  88.   if (bp->addr != eip)
  89.     {
  90.       errno = 0;
  91.       r = ptrace (PTRACE_PEEKTEXT, pid, bp->addr, 0);
  92.       if (errno != 0)
  93.         return;
  94.       bp->save = (byte)r;
  95.       r = (r & ~0xff) | 0xcc;
  96.       ptrace (PTRACE_POKETEXT, pid, bp->addr, r);
  97.     }
  98. }
  99.  
  100.  
  101. static void remove_bp (struct breakpoint *bp)
  102. {
  103.   int r;
  104.  
  105.   errno = 0;
  106.   r = ptrace (PTRACE_PEEKTEXT, pid, bp->addr, 0);
  107.   if (errno != 0)
  108.     return;
  109.   r = (r & ~0xff) | bp->save;
  110.   ptrace (PTRACE_POKETEXT, pid, bp->addr, r);
  111. }
  112.  
  113.  
  114. static void insert_breakpoints (struct breakpoint *bp)
  115. {
  116.   int r;
  117.  
  118.   errno = 0;
  119.   r = ptrace (PTRACE_PEEKUSER, pid, uaddr + EIP * 4, 0);
  120.   if (errno != 0) perror ("ptrace");
  121.   while (bp != NULL)
  122.     {
  123.       insert_bp (bp, r);
  124.       bp = bp->next;
  125.     }
  126. }
  127.  
  128.  
  129. static void remove_breakpoints (struct breakpoint *bp)
  130. {
  131.   if (bp != NULL)
  132.     {
  133.       remove_breakpoints (bp->next);
  134.       remove_bp (bp);
  135.     }
  136. }
  137.  
  138.  
  139. static void run (int cmd)
  140. {
  141.   int s, t, p, r, e;
  142.   struct breakpoint *bp;
  143.  
  144.   insert_breakpoints (breakpoints);
  145.   if (auto_switch)
  146.     ptrace (PTRACE_SESSION, pid, 0, 2);
  147.   s = ptrace (cmd, pid, 0, 0);
  148.   e = errno;
  149.   if (auto_switch)
  150.       ptrace (PTRACE_SESSION, pid, 0, 0);
  151.   remove_breakpoints (breakpoints);
  152.   errno = e;
  153.   if (s < 0)
  154.     perror ("ptrace");
  155.   else
  156.     {
  157.       p = wait (&t);
  158.       if (p == -1)
  159.         perror ("wait");
  160.       if (!silent)
  161.         printf ("wait: %.4x\n", t);
  162.       if ((t & 0377) != 0177)
  163.         {
  164.           printf ("Program terminated (%d)\n", (t >> 8) & 0xff);
  165.           exit (0);
  166.         }
  167.       errno = 0;
  168.       r = ptrace (PTRACE_PEEKUSER, pid, uaddr + EIP * 4, 0);
  169.       if (errno != 0) perror ("ptrace");
  170.       --r;
  171.       for (bp = breakpoints; bp != NULL; bp = bp->next)
  172.         if (bp->addr == r)
  173.           break;
  174.       if (bp != NULL)
  175.         ptrace (PTRACE_POKEUSER, pid, uaddr + EIP * 4, r);
  176.     }
  177. }
  178.  
  179.  
  180. static void dump (char *buf)
  181. {
  182.   int i, j, r;
  183.   long n;
  184.   char *p;
  185.  
  186.   if (*buf != 0)
  187.     {
  188.       errno = 0;
  189.       n = strtol (buf, &p, 16);
  190.       if (errno != 0 || *p != 0)
  191.         {
  192.           printf ("Error!\n");
  193.           return;
  194.         }
  195.       dump_addr = n;
  196.     }
  197.   for (i = 0; i < 8; ++i)
  198.     {
  199.       printf ("%.8lx: ", dump_addr);
  200.       for (j = 0; j < 8; ++j)
  201.         {
  202.           errno = 0;
  203.           r = ptrace (PTRACE_PEEKTEXT, pid, dump_addr, 0);
  204.           if (errno != 0)
  205.             fputs ("?? ?? ", stdout);
  206.           else
  207.             printf ("%.2x %.2x ", r & 0xff, (r >> 8) & 0xff);
  208.           dump_addr += 2;
  209.         }
  210.       putchar ('\n');
  211.     }
  212. }
  213.  
  214.  
  215. static void set_bp (char *buf)
  216. {
  217.   int i;
  218.   long addr;
  219.   struct breakpoint *bp, **abp;
  220.   char *p;
  221.  
  222.   if (*buf == 0)
  223.     {
  224.       for (i = 1, bp = breakpoints; bp != NULL; bp = bp->next)
  225.         printf ("Breakpoint %d at %.8lx\n", i, bp->addr);
  226.     }
  227.   else
  228.     {
  229.       errno = 0;
  230.       addr = strtol (buf, &p, 16);
  231.       if (errno != 0 || *p != 0)
  232.         {
  233.           printf ("Error!\n");
  234.           return;
  235.         }
  236.       bp = malloc (sizeof (struct breakpoint));
  237.       if (bp == NULL)
  238.         {
  239.           printf ("Out of memory\n");
  240.           return;
  241.         }
  242.       bp->next = NULL;
  243.       bp->addr = addr;
  244.       for (abp = &breakpoints; *abp != NULL; abp = &(*abp)->next)
  245.         ;
  246.       *abp = bp;
  247.     }
  248. }
  249.  
  250.  
  251. static void start (const char *prog, const char * const *args,
  252.                    const char * const *envp)
  253. {
  254.   struct user u;
  255.  
  256.   pid = spawnve (P_DEBUG | P_WINDOWED, prog, args, envp);
  257.   if (pid < 0)
  258.     {
  259.       perror ("spawnve");
  260.       exit (2);
  261.     }
  262.   printf ("pid=%d\n", pid);
  263.   errno = 0;
  264.   uaddr = ptrace (PTRACE_PEEKUSER, pid, (char *)&u.u_ar0 - (char *)&u, 0);
  265.   if (errno != 0) perror ("ptrace");
  266.   uaddr -= 0xe0000000;
  267. }
  268.  
  269.  
  270. static void command_loop (void)
  271. {
  272.   char buf[10], *p;
  273.  
  274.   for (;;)
  275.     {
  276.       if (fgets (buf, sizeof (buf), stdin) == NULL)
  277.         break;
  278.       p = strchr (buf, '\n');
  279.       if (p != NULL) *p = 0;
  280.       if (buf[0] == 'q')
  281.         break;
  282.       else if (buf[0] == 'd')
  283.         dump (buf+1);
  284.       else if (buf[0] == 'b')
  285.         set_bp (buf+1);
  286.       else if (buf[0] == 'g')
  287.         {
  288.           run (PTRACE_RESUME);
  289.           show_regs ();
  290.         }
  291.       else if (buf[0] == 0)
  292.         {
  293.           run (PTRACE_STEP);
  294.           show_regs ();
  295.         }
  296.       else
  297.         {
  298.           puts ("q        quit");
  299.           puts ("d ADDR   dump");
  300.           puts ("g        resume");
  301.           puts ("b ADDR   set breakpoint");
  302.           puts ("(empty)  step");
  303.         }
  304.     }
  305. }
  306.  
  307.  
  308. int main (int argc, char **argv, char **envp)
  309. {
  310.   int i;
  311.  
  312.   i = 1; silent = 0; auto_switch = 0;
  313.   while (i < argc)
  314.     {
  315.       if (strcmp (argv[i], "-s") == 0)
  316.         {
  317.           silent = 1; ++i;
  318.         }
  319.       else if (strcmp (argv[i], "-a") == 0)
  320.         {
  321.           auto_switch = 1; ++i;
  322.         }
  323.       else
  324.         break;
  325.     }
  326.   if (i+1 > argc)
  327.     {
  328.       fputs ("usage: emx debug [-a] [-s] prog [args]\n", stderr);
  329.       exit (1);
  330.     }
  331.   start (argv[i], (const char * const *)(argv+i), (const char * const *)envp);
  332.   if (silent)
  333.     for (;;)
  334.       run (PTRACE_STEP);
  335.   else
  336.     command_loop ();
  337.   return (0);
  338. }
  339.