home *** CD-ROM | disk | FTP | other *** search
- /* debug.c (emx+gcc) */
-
- /* Test ptrace() */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <process.h>
- #include <errno.h>
- #include <sys/ptrace.h>
- #include <sys/user.h>
- #include <sys/reg.h>
-
- typedef unsigned char byte;
-
- struct reg
- {
- char *name;
- int regno;
- unsigned value;
- };
-
- struct breakpoint
- {
- struct breakpoint *next;
- unsigned addr;
- byte save;
- };
-
- #define N_EIP 8
-
- static struct reg regs[] =
- {
- {"eax", EAX},
- {"ebx", EBX},
- {"ecx", ECX},
- {"edx", EDX},
- {"esi", ESI},
- {"edi", EDI},
- {"esp", UESP},
- {"ebp", EBP},
- {"eip", EIP},
- {NULL, 0}
- };
-
-
- static int pid;
- static int silent;
- static int auto_switch;
- static int uaddr;
- static long dump_addr;
- static struct breakpoint *breakpoints = NULL;
-
- static void show_regs (void)
- {
- int i, j, r;
-
- j = 4;
- for (i = 0; regs[i].name != NULL; ++i)
- {
- errno = 0;
- r = ptrace (PTRACE_PEEKUSER, pid, uaddr + regs[i].regno * 4, 0);
- if (errno != 0) perror ("ptrace");
- regs[i].value = r;
- if (j == 4)
- {
- j = 0; putchar ('\n');
- }
- ++j;
- printf ("%s=%.8x ", regs[i].name, r);
- }
- errno = 0;
- r = ptrace (PTRACE_PEEKTEXT, pid, regs[N_EIP].value, 0);
- if (errno == 0)
- for (i = 0; i < 4; ++i)
- {
- printf ("%.2x ", r & 0xff);
- r >>= 8;
- }
- putchar ('\n');
- }
-
-
- static void insert_bp (struct breakpoint *bp, int eip)
- {
- int r;
-
- if (bp->addr != eip)
- {
- errno = 0;
- r = ptrace (PTRACE_PEEKTEXT, pid, bp->addr, 0);
- if (errno != 0)
- return;
- bp->save = (byte)r;
- r = (r & ~0xff) | 0xcc;
- ptrace (PTRACE_POKETEXT, pid, bp->addr, r);
- }
- }
-
-
- static void remove_bp (struct breakpoint *bp)
- {
- int r;
-
- errno = 0;
- r = ptrace (PTRACE_PEEKTEXT, pid, bp->addr, 0);
- if (errno != 0)
- return;
- r = (r & ~0xff) | bp->save;
- ptrace (PTRACE_POKETEXT, pid, bp->addr, r);
- }
-
-
- static void insert_breakpoints (struct breakpoint *bp)
- {
- int r;
-
- errno = 0;
- r = ptrace (PTRACE_PEEKUSER, pid, uaddr + EIP * 4, 0);
- if (errno != 0) perror ("ptrace");
- while (bp != NULL)
- {
- insert_bp (bp, r);
- bp = bp->next;
- }
- }
-
-
- static void remove_breakpoints (struct breakpoint *bp)
- {
- if (bp != NULL)
- {
- remove_breakpoints (bp->next);
- remove_bp (bp);
- }
- }
-
-
- static void run (int cmd)
- {
- int s, t, p, r, e;
- struct breakpoint *bp;
-
- insert_breakpoints (breakpoints);
- if (auto_switch)
- ptrace (PTRACE_SESSION, pid, 0, 2);
- s = ptrace (cmd, pid, 0, 0);
- e = errno;
- if (auto_switch)
- ptrace (PTRACE_SESSION, pid, 0, 0);
- remove_breakpoints (breakpoints);
- errno = e;
- if (s < 0)
- perror ("ptrace");
- else
- {
- p = wait (&t);
- if (p == -1)
- perror ("wait");
- if (!silent)
- printf ("wait: %.4x\n", t);
- if ((t & 0377) != 0177)
- {
- printf ("Program terminated (%d)\n", (t >> 8) & 0xff);
- exit (0);
- }
- errno = 0;
- r = ptrace (PTRACE_PEEKUSER, pid, uaddr + EIP * 4, 0);
- if (errno != 0) perror ("ptrace");
- --r;
- for (bp = breakpoints; bp != NULL; bp = bp->next)
- if (bp->addr == r)
- break;
- if (bp != NULL)
- ptrace (PTRACE_POKEUSER, pid, uaddr + EIP * 4, r);
- }
- }
-
-
- static void dump (char *buf)
- {
- int i, j, r;
- long n;
- char *p;
-
- if (*buf != 0)
- {
- errno = 0;
- n = strtol (buf, &p, 16);
- if (errno != 0 || *p != 0)
- {
- printf ("Error!\n");
- return;
- }
- dump_addr = n;
- }
- for (i = 0; i < 8; ++i)
- {
- printf ("%.8lx: ", dump_addr);
- for (j = 0; j < 8; ++j)
- {
- errno = 0;
- r = ptrace (PTRACE_PEEKTEXT, pid, dump_addr, 0);
- if (errno != 0)
- fputs ("?? ?? ", stdout);
- else
- printf ("%.2x %.2x ", r & 0xff, (r >> 8) & 0xff);
- dump_addr += 2;
- }
- putchar ('\n');
- }
- }
-
-
- static void set_bp (char *buf)
- {
- int i;
- long addr;
- struct breakpoint *bp, **abp;
- char *p;
-
- if (*buf == 0)
- {
- for (i = 1, bp = breakpoints; bp != NULL; bp = bp->next)
- printf ("Breakpoint %d at %.8lx\n", i, bp->addr);
- }
- else
- {
- errno = 0;
- addr = strtol (buf, &p, 16);
- if (errno != 0 || *p != 0)
- {
- printf ("Error!\n");
- return;
- }
- bp = malloc (sizeof (struct breakpoint));
- if (bp == NULL)
- {
- printf ("Out of memory\n");
- return;
- }
- bp->next = NULL;
- bp->addr = addr;
- for (abp = &breakpoints; *abp != NULL; abp = &(*abp)->next)
- ;
- *abp = bp;
- }
- }
-
-
- static void start (const char *prog, const char * const *args,
- const char * const *envp)
- {
- struct user u;
-
- pid = spawnve (P_DEBUG | P_WINDOWED, prog, args, envp);
- if (pid < 0)
- {
- perror ("spawnve");
- exit (2);
- }
- printf ("pid=%d\n", pid);
- errno = 0;
- uaddr = ptrace (PTRACE_PEEKUSER, pid, (char *)&u.u_ar0 - (char *)&u, 0);
- if (errno != 0) perror ("ptrace");
- uaddr -= 0xe0000000;
- }
-
-
- static void command_loop (void)
- {
- char buf[10], *p;
-
- for (;;)
- {
- if (fgets (buf, sizeof (buf), stdin) == NULL)
- break;
- p = strchr (buf, '\n');
- if (p != NULL) *p = 0;
- if (buf[0] == 'q')
- break;
- else if (buf[0] == 'd')
- dump (buf+1);
- else if (buf[0] == 'b')
- set_bp (buf+1);
- else if (buf[0] == 'g')
- {
- run (PTRACE_RESUME);
- show_regs ();
- }
- else if (buf[0] == 0)
- {
- run (PTRACE_STEP);
- show_regs ();
- }
- else
- {
- puts ("q quit");
- puts ("d ADDR dump");
- puts ("g resume");
- puts ("b ADDR set breakpoint");
- puts ("(empty) step");
- }
- }
- }
-
-
- int main (int argc, char **argv, char **envp)
- {
- int i;
-
- i = 1; silent = 0; auto_switch = 0;
- while (i < argc)
- {
- if (strcmp (argv[i], "-s") == 0)
- {
- silent = 1; ++i;
- }
- else if (strcmp (argv[i], "-a") == 0)
- {
- auto_switch = 1; ++i;
- }
- else
- break;
- }
- if (i+1 > argc)
- {
- fputs ("usage: emx debug [-a] [-s] prog [args]\n", stderr);
- exit (1);
- }
- start (argv[i], (const char * const *)(argv+i), (const char * const *)envp);
- if (silent)
- for (;;)
- run (PTRACE_STEP);
- else
- command_loop ();
- return (0);
- }
-