home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3999 / util.c < prev   
Encoding:
C/C++ Source or Header  |  1991-09-09  |  6.5 KB  |  345 lines

  1. /*
  2.  * @(#)util.c    1.5 91/09/05
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include <errno.h>
  8. #include <sys/types.h>
  9. #include <sys/ptrace.h>
  10. #include <machine/reg.h>
  11.  
  12. #include "defs.h"
  13.  
  14. int max_str_len = DFLT_STR_LEN;
  15.  
  16. char *
  17. xlookup(xlat, val)
  18. Xlat *xlat;
  19. {
  20.     int i;
  21.  
  22.     for (; xlat->str != NULL; xlat++)
  23.         if (xlat->val == val)
  24.             return xlat->str;
  25.  
  26.     return NULL;
  27. }
  28.  
  29. /*
  30.  * Print entry in Xlat table, if there.
  31.  */
  32. int
  33. printxval(xlat, val, dflt)
  34. Xlat *xlat;
  35. char *dflt;
  36. {
  37.     char *str = xlookup(xlat, val);
  38.  
  39.     if (str)
  40.         fprintf(outf, "%s", str);
  41.     else
  42.         fprintf(outf, "%s(%#x)", dflt, val);
  43.  
  44.     return 0;
  45. }
  46.  
  47. /*
  48.  * interpret `xlat' as an array of flags
  49.  * print the entries whose bits are on in `flags'
  50.  * return # of flags printed
  51.  */
  52. int
  53. addflags(xlat, flags)
  54. Xlat *xlat;
  55. int flags;
  56. {
  57.     int n;
  58.  
  59.     for (n = 0; xlat->str; xlat++) {
  60.         if (flags & xlat->val) {
  61.             fprintf(outf, "|%s", xlat->str);
  62.             n++;
  63.         }
  64.     }
  65.     return n;
  66. }
  67.  
  68. int
  69. printflags(xlat, flags)
  70. Xlat *xlat;
  71. int flags;
  72. {
  73.     int n;
  74.     char *format;
  75.  
  76.     format = "%s";
  77.     for (n = 0; xlat->str; xlat++) {
  78.         if (flags & xlat->val) {
  79.             fprintf(outf, format, xlat->str);
  80.             n++;
  81.             format = "|%s";
  82.         }
  83.     }
  84.     return n;
  85. }
  86.  
  87. int
  88. printstr(pid, addr, len)
  89. {
  90.     static unsigned char *str, *malloc();
  91.     int i, n, c;
  92.  
  93.     if (str == (unsigned char *)0) {
  94.         if ((str = malloc(max_str_len)) == NULL) {
  95.             fprintf(stderr, "printstr: no memory\n");
  96.             return -1;
  97.         }
  98.     }
  99.  
  100.     if (len < 0) {
  101.         if (umovestr(pid, addr, n = max_str_len, str) < 0)
  102.             return -1;
  103.     } else {
  104.         if (umove(pid, addr, n = MIN(len, max_str_len), str) < 0)
  105.             return -1;
  106.     }
  107.  
  108.     putc('"', outf);
  109.     for (i = 0; i < n; i++) {
  110.         if (len < 0)
  111.             if (str[i] == '\0')
  112.                 break;
  113.         switch (c = str[i]) {
  114.         case '\n':
  115.             putc('\\', outf); putc('n', outf);
  116.             break;
  117.         case '\t':
  118.             putc('\\', outf); putc('t', outf);
  119.             break;
  120.         case '\r':
  121.             putc('\\', outf); putc('r', outf);
  122.             break;
  123.         default:
  124.             if (isprint(c)) {
  125.                 putc(c, outf);
  126.             } else {
  127.                 fprintf(outf, "\\%x", c);
  128.             }
  129.             break;
  130.         }
  131.  
  132.     }
  133.     putc('"', outf);
  134.     if (n < len || (len < 0 && i >= n)) {
  135.         putc('.', outf); putc('.', outf);
  136.     }
  137.     return 0;
  138. }
  139.  
  140. /*
  141.  * move `len' bytes of data from process `pid'
  142.  * at address `addr' to out space at `laddr'
  143.  */
  144. int
  145. umove(pid, addr, len, laddr)
  146. int pid;
  147. int addr, len;
  148. char *laddr;
  149. {
  150. #if 1
  151.     if (ptrace(PTRACE_READDATA, pid, (char *)addr, len, laddr) < 0) {
  152.         perror("ptrace(PTRACE_READDATA,..");
  153.         return -1;
  154.     }
  155. #else
  156.     int n, m;
  157.     union {
  158.         int val;
  159.         char x[4];
  160.     } u;
  161.  
  162.     if (addr & 3) /* addr not a multiple of 4 */ {
  163.         n = addr - (addr &= 0xfffffffc); /* residue */
  164.         u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
  165.         bcopy(&u.x[n], laddr, m = MIN(4-n,len));
  166.         addr += 4, laddr += m, len -= m;
  167.     }
  168.     while (len) {
  169.         u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
  170.         bcopy(u.x, laddr, m = MIN(4,len));
  171.         addr += 4, laddr += m, len -= m;
  172.     }
  173. #endif
  174.     return 0;
  175. }
  176.  
  177. /*
  178.  * like `umove' but make the additional effort of looking
  179.  * for a terminating zero byte.
  180.  */
  181. int
  182. umovestr(pid, addr, len, laddr)
  183. int pid;
  184. u_int addr, len;
  185. char *laddr;
  186. {
  187.     int i, n, m;
  188.     union {
  189.         int val;
  190.         char x[4];
  191.     } u;
  192.  
  193.     if (addr & 3) /* addr not a multiple of 4 */ {
  194.         n = addr - (addr & 0xfffffffc); /* residue */
  195.         addr &= 0xfffffffc; /* residue */
  196.         errno = 0;
  197.         u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
  198.         if (errno) {
  199.             perror("umovestr");
  200.             return -1;
  201.         }
  202.         bcopy(&u.x[n], laddr, m = MIN(4-n,len));
  203.         while (n & 3)
  204.             if (u.x[n++] == '\0')
  205.                 return 0;
  206.         len -= m, laddr += m, addr += 4;
  207.     }
  208.     while (len) {
  209.         errno = 0;
  210.         u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
  211.         if (errno) {
  212.             perror("umovestr");
  213.             return -1;
  214.         }
  215.         bcopy(u.x, laddr, m = MIN(4,len));
  216.         for (i = 0; i < 4; i++)
  217.             if (u.x[i] == '\0')
  218.                 return 0;
  219.  
  220.         addr += 4, laddr += m, len -= m;
  221.     }
  222.     return 0;
  223. }
  224.  
  225. int
  226. setbpt(tcp)
  227. struct tcb *tcp;
  228. {
  229. #ifdef sparc    /* This code is slightly sparc specific */
  230.  
  231.     struct regs regs;
  232. #define BPT    0x91d02001
  233. #define LOOP    0x10800000
  234. #define NOP    0x01000000
  235.     static int loopdeloop[2] = {LOOP, NOP};
  236.  
  237.     if (tcp->flags & TCB_BPTSET) {
  238.         fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
  239.         return -1;
  240.     }
  241.     if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
  242.         perror("setbpt: ptrace(PTRACE_GETREGS, ...");
  243.         return -1;
  244.     }
  245.     tcp->baddr = regs.r_o7 + 8;
  246.     if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
  247.                 sizeof tcp->inst, (char *)tcp->inst) < 0) {
  248.         perror("PTRACE_READTEXT,...");
  249.         return -1;
  250.     }
  251.  
  252.     /*
  253.      * XXX - BRUTAL MODE ON
  254.      * We cannot set a real BPT in the child, since it will not be
  255.      * traced at the moment it will reach the trap and would probably
  256.      * die with a core dump.
  257.      * Thus, we are force our way in by taking out two instructions
  258.      * and insert an eternal loop in stead, in expectance of the SIGSTOP
  259.      * generated by out PTRACE_ATTACH.
  260.      * Of cause, if we evaporate ourselves in the middle of all this...
  261.      */
  262.     if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *)tcp->baddr,
  263.                 sizeof loopdeloop, (char *)loopdeloop) < 0) {
  264.         perror("PTRACE_WRITETEXT,...");
  265.         return -1;
  266.     }
  267.     tcp->flags |= TCB_BPTSET;
  268.  
  269. #endif /* sparc */
  270.  
  271.     return 0;
  272. }
  273.  
  274. int
  275. clearbpt(tcp)
  276. struct tcb *tcp;
  277. {
  278. #ifdef sparc
  279.  
  280.     struct regs regs;
  281.  
  282.     if (!(tcp->flags & TCB_BPTSET)) {
  283.         fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
  284.         return -1;
  285.     }
  286.     if (ptrace(PTRACE_WRITETEXT, tcp->pid, tcp->baddr,
  287.                 sizeof tcp->inst, (char *)tcp->inst) < 0) {
  288.         perror("clearbtp: PTRACE_WRITETEXT,...");
  289.         return -1;
  290.     }
  291.     tcp->flags &= ~TCB_BPTSET;
  292.  
  293.     /*
  294.      * Since we don't have a single instruction breakpoint, we may have
  295.      * to adjust the program counter after removing the our `breakpoint'.
  296.      */
  297.     if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
  298.         perror("clearbpt: ptrace(PTRACE_GETREGS, ...");
  299.         return -1;
  300.     }
  301.     if ((regs.r_pc < tcp->baddr) ||
  302.                 (regs.r_pc > tcp->baddr + 4)) {
  303.         /* The breakpoint has not been reached yet */
  304.         if (debug)
  305.             fprintf(stderr,
  306.                 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
  307.                     regs.r_pc, tcp->parent->baddr);
  308.         return 0;
  309.     }
  310.     if (regs.r_pc != tcp->baddr)
  311.         if (debug)
  312.             fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
  313.                 regs.r_pc, tcp->baddr);
  314.  
  315.     regs.r_pc = tcp->baddr;
  316.     if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
  317.         perror("clearbpt: ptrace(PTRACE_SETREGS, ...");
  318.         return -1;
  319.     }
  320.  
  321. #endif /* sparc */
  322.  
  323.     return 0;
  324. }
  325.  
  326. int
  327. pokearg(pid, argno, data)
  328. {
  329.     struct regs regs;
  330.  
  331.     if (debug)
  332.         fprintf(stderr, "Poking: %u -> u_arg[%u]\n", data, argno);
  333.  
  334. #if    0
  335.     /* DOESN'T WORK */
  336.     if (ptrace(PTRACE_POKEUSER, pid,
  337.         uoff(u_arg[0]) + argno*sizeof(((struct user *)0)->u_arg[0]), data) < 0) {
  338.         perror(" [ptrace(PTRACE_POKEUSER,..)]");
  339.         return -1;
  340.     }
  341. #endif
  342.     return 0;
  343. }
  344.  
  345.