home *** CD-ROM | disk | FTP | other *** search
- /*
- * @(#)util.c 1.5 91/09/05
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/ptrace.h>
- #include <machine/reg.h>
-
- #include "defs.h"
-
- int max_str_len = DFLT_STR_LEN;
-
- char *
- xlookup(xlat, val)
- Xlat *xlat;
- {
- int i;
-
- for (; xlat->str != NULL; xlat++)
- if (xlat->val == val)
- return xlat->str;
-
- return NULL;
- }
-
- /*
- * Print entry in Xlat table, if there.
- */
- int
- printxval(xlat, val, dflt)
- Xlat *xlat;
- char *dflt;
- {
- char *str = xlookup(xlat, val);
-
- if (str)
- fprintf(outf, "%s", str);
- else
- fprintf(outf, "%s(%#x)", dflt, val);
-
- return 0;
- }
-
- /*
- * interpret `xlat' as an array of flags
- * print the entries whose bits are on in `flags'
- * return # of flags printed
- */
- int
- addflags(xlat, flags)
- Xlat *xlat;
- int flags;
- {
- int n;
-
- for (n = 0; xlat->str; xlat++) {
- if (flags & xlat->val) {
- fprintf(outf, "|%s", xlat->str);
- n++;
- }
- }
- return n;
- }
-
- int
- printflags(xlat, flags)
- Xlat *xlat;
- int flags;
- {
- int n;
- char *format;
-
- format = "%s";
- for (n = 0; xlat->str; xlat++) {
- if (flags & xlat->val) {
- fprintf(outf, format, xlat->str);
- n++;
- format = "|%s";
- }
- }
- return n;
- }
-
- int
- printstr(pid, addr, len)
- {
- static unsigned char *str, *malloc();
- int i, n, c;
-
- if (str == (unsigned char *)0) {
- if ((str = malloc(max_str_len)) == NULL) {
- fprintf(stderr, "printstr: no memory\n");
- return -1;
- }
- }
-
- if (len < 0) {
- if (umovestr(pid, addr, n = max_str_len, str) < 0)
- return -1;
- } else {
- if (umove(pid, addr, n = MIN(len, max_str_len), str) < 0)
- return -1;
- }
-
- putc('"', outf);
- for (i = 0; i < n; i++) {
- if (len < 0)
- if (str[i] == '\0')
- break;
- switch (c = str[i]) {
- case '\n':
- putc('\\', outf); putc('n', outf);
- break;
- case '\t':
- putc('\\', outf); putc('t', outf);
- break;
- case '\r':
- putc('\\', outf); putc('r', outf);
- break;
- default:
- if (isprint(c)) {
- putc(c, outf);
- } else {
- fprintf(outf, "\\%x", c);
- }
- break;
- }
-
- }
- putc('"', outf);
- if (n < len || (len < 0 && i >= n)) {
- putc('.', outf); putc('.', outf);
- }
- return 0;
- }
-
- /*
- * move `len' bytes of data from process `pid'
- * at address `addr' to out space at `laddr'
- */
- int
- umove(pid, addr, len, laddr)
- int pid;
- int addr, len;
- char *laddr;
- {
- #if 1
- if (ptrace(PTRACE_READDATA, pid, (char *)addr, len, laddr) < 0) {
- perror("ptrace(PTRACE_READDATA,..");
- return -1;
- }
- #else
- int n, m;
- union {
- int val;
- char x[4];
- } u;
-
- if (addr & 3) /* addr not a multiple of 4 */ {
- n = addr - (addr &= 0xfffffffc); /* residue */
- u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
- bcopy(&u.x[n], laddr, m = MIN(4-n,len));
- addr += 4, laddr += m, len -= m;
- }
- while (len) {
- u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
- bcopy(u.x, laddr, m = MIN(4,len));
- addr += 4, laddr += m, len -= m;
- }
- #endif
- return 0;
- }
-
- /*
- * like `umove' but make the additional effort of looking
- * for a terminating zero byte.
- */
- int
- umovestr(pid, addr, len, laddr)
- int pid;
- u_int addr, len;
- char *laddr;
- {
- int i, n, m;
- union {
- int val;
- char x[4];
- } u;
-
- if (addr & 3) /* addr not a multiple of 4 */ {
- n = addr - (addr & 0xfffffffc); /* residue */
- addr &= 0xfffffffc; /* residue */
- errno = 0;
- u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
- if (errno) {
- perror("umovestr");
- return -1;
- }
- bcopy(&u.x[n], laddr, m = MIN(4-n,len));
- while (n & 3)
- if (u.x[n++] == '\0')
- return 0;
- len -= m, laddr += m, addr += 4;
- }
- while (len) {
- errno = 0;
- u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
- if (errno) {
- perror("umovestr");
- return -1;
- }
- bcopy(u.x, laddr, m = MIN(4,len));
- for (i = 0; i < 4; i++)
- if (u.x[i] == '\0')
- return 0;
-
- addr += 4, laddr += m, len -= m;
- }
- return 0;
- }
-
- int
- setbpt(tcp)
- struct tcb *tcp;
- {
- #ifdef sparc /* This code is slightly sparc specific */
-
- struct regs regs;
- #define BPT 0x91d02001
- #define LOOP 0x10800000
- #define NOP 0x01000000
- static int loopdeloop[2] = {LOOP, NOP};
-
- if (tcp->flags & TCB_BPTSET) {
- fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
- return -1;
- }
- if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
- perror("setbpt: ptrace(PTRACE_GETREGS, ...");
- return -1;
- }
- tcp->baddr = regs.r_o7 + 8;
- if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
- sizeof tcp->inst, (char *)tcp->inst) < 0) {
- perror("PTRACE_READTEXT,...");
- return -1;
- }
-
- /*
- * XXX - BRUTAL MODE ON
- * We cannot set a real BPT in the child, since it will not be
- * traced at the moment it will reach the trap and would probably
- * die with a core dump.
- * Thus, we are force our way in by taking out two instructions
- * and insert an eternal loop in stead, in expectance of the SIGSTOP
- * generated by out PTRACE_ATTACH.
- * Of cause, if we evaporate ourselves in the middle of all this...
- */
- if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *)tcp->baddr,
- sizeof loopdeloop, (char *)loopdeloop) < 0) {
- perror("PTRACE_WRITETEXT,...");
- return -1;
- }
- tcp->flags |= TCB_BPTSET;
-
- #endif /* sparc */
-
- return 0;
- }
-
- int
- clearbpt(tcp)
- struct tcb *tcp;
- {
- #ifdef sparc
-
- struct regs regs;
-
- if (!(tcp->flags & TCB_BPTSET)) {
- fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
- return -1;
- }
- if (ptrace(PTRACE_WRITETEXT, tcp->pid, tcp->baddr,
- sizeof tcp->inst, (char *)tcp->inst) < 0) {
- perror("clearbtp: PTRACE_WRITETEXT,...");
- return -1;
- }
- tcp->flags &= ~TCB_BPTSET;
-
- /*
- * Since we don't have a single instruction breakpoint, we may have
- * to adjust the program counter after removing the our `breakpoint'.
- */
- if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
- perror("clearbpt: ptrace(PTRACE_GETREGS, ...");
- return -1;
- }
- if ((regs.r_pc < tcp->baddr) ||
- (regs.r_pc > tcp->baddr + 4)) {
- /* The breakpoint has not been reached yet */
- if (debug)
- fprintf(stderr,
- "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
- regs.r_pc, tcp->parent->baddr);
- return 0;
- }
- if (regs.r_pc != tcp->baddr)
- if (debug)
- fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
- regs.r_pc, tcp->baddr);
-
- regs.r_pc = tcp->baddr;
- if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
- perror("clearbpt: ptrace(PTRACE_SETREGS, ...");
- return -1;
- }
-
- #endif /* sparc */
-
- return 0;
- }
-
- int
- pokearg(pid, argno, data)
- {
- struct regs regs;
-
- if (debug)
- fprintf(stderr, "Poking: %u -> u_arg[%u]\n", data, argno);
-
- #if 0
- /* DOESN'T WORK */
- if (ptrace(PTRACE_POKEUSER, pid,
- uoff(u_arg[0]) + argno*sizeof(((struct user *)0)->u_arg[0]), data) < 0) {
- perror(" [ptrace(PTRACE_POKEUSER,..)]");
- return -1;
- }
- #endif
- return 0;
- }
-
-