|
|
1.1 ! root 1: /* ! 2: * db/db8.c ! 3: * A debugger. ! 4: * Child process. ! 5: * All the machine-independent ptrace() code is here. ! 6: */ ! 7: ! 8: #include <errno.h> ! 9: #include <signal.h> ! 10: #include <sys/param.h> ! 11: #include <sys/ptrace.h> ! 12: #include "db.h" ! 13: ! 14: /* ! 15: * Read 'n' characters starting at address 'a' into the buffer 'bp' ! 16: * from segment 'f' in the child process. ! 17: * Return 1 on success, 0 on failure. ! 18: */ ! 19: int ! 20: getp(f, a, bp, n) int f; ADDR_T a; register char *bp; register int n; ! 21: { ! 22: int d, n1, pcmd; ! 23: ! 24: /* Set pcmd to the appropriate ptrace() read command. */ ! 25: switch(f) { ! 26: case ISEG: pcmd = PTRACE_RD_TXT; break; ! 27: case DSEG: pcmd = PTRACE_RD_DAT; break; ! 28: case USEG: pcmd = PTRACE_RD_USR; break; ! 29: } ! 30: ! 31: /* Read in PTSIZE-sized chunks. */ ! 32: for (errno = 0; n != 0; n -= n1, a += n1, bp += n1) { ! 33: n1 = (n > PTSIZE) ? PTSIZE : n; ! 34: d = ptrace(pcmd, pid, (int)a, 0); ! 35: if (errno) ! 36: return 0; ! 37: memcpy(bp, &d, n1); ! 38: } ! 39: return 1; ! 40: } ! 41: ! 42: /* ! 43: * Infanticide. ! 44: */ ! 45: void ! 46: killc() ! 47: { ! 48: reg_flag = R_INVALID; ! 49: if (execflag) { ! 50: ptrace(PTRACE_TERM, pid, 0, 0); ! 51: waitc(); ! 52: execflag = 0; ! 53: } ! 54: #if 0 ! 55: trapstr = NULL; ! 56: #endif ! 57: } ! 58: ! 59: /* ! 60: * Write 'n' characters from the buffer 'bp' ! 61: * to segment 'f' in the child process starting at address 'a'. ! 62: * Return 1 on success, 0 on failure. ! 63: */ ! 64: int ! 65: putp(f, a, bp, n) int f; ADDR_T a; register char *bp; register int n; ! 66: { ! 67: int d, n1, pcmd, prcmd; ! 68: ! 69: /* Set pcmd to the appropriate ptrace() write command. */ ! 70: switch(f) { ! 71: case ISEG: pcmd = PTRACE_WR_TXT; break; ! 72: case DSEG: pcmd = PTRACE_WR_DAT; break; ! 73: case USEG: pcmd = PTRACE_WR_USR; break; ! 74: } ! 75: for (errno = 0; n != 0; n -= n1, a += n1, bp += n1) { ! 76: if (n < PTSIZE) { ! 77: /* Read first so write can leave extra bytes unchanged. */ ! 78: n1 = n; ! 79: switch(f) { ! 80: case ISEG: prcmd = PTRACE_RD_TXT; break; ! 81: case DSEG: prcmd = PTRACE_RD_DAT; break; ! 82: case USEG: prcmd = PTRACE_RD_USR; break; ! 83: } ! 84: d = ptrace(prcmd, pid, (int)a, 0); ! 85: } else ! 86: n1 = PTSIZE; ! 87: memcpy(&d, bp, n1); ! 88: ptrace(pcmd, pid, (int)a, d); ! 89: if (errno) { ! 90: perror("putp()"); ! 91: return 0; ! 92: } ! 93: } ! 94: return 1; ! 95: } ! 96: ! 97: /* ! 98: * Run the child and wait for it to stop. ! 99: * Return 0 on error. ! 100: */ ! 101: int ! 102: runc() ! 103: { ! 104: register int pcmd; ! 105: ! 106: switch (step_mode) { ! 107: case SNULL: ! 108: case SWAIT: ! 109: pcmd = PTRACE_RESUME; ! 110: break; ! 111: case SCALL: ! 112: case SCONT: ! 113: case SSTEP: ! 114: pcmd = PTRACE_SSTEP; ! 115: break; ! 116: default: ! 117: panic("invalid step_mode=%d", step_mode); ! 118: } ! 119: errno = 0; ! 120: reg_flag = R_INVALID; ! 121: ptrace(pcmd, pid, 1, 0); ! 122: if (errno) { ! 123: perror("ptrace"); ! 124: return 0; ! 125: } ! 126: if (waitc() == 0) ! 127: return 0; ! 128: get_regs(R_SOME); ! 129: return 1; ! 130: } ! 131: ! 132: /* ! 133: * Start execution of the child. ! 134: * 'argv' is the argument list, ! 135: * 'ifn' is the name of the input file, ! 136: * 'ofn' is the name of the output file, and ! 137: * 'aflag' tells us whether the output file is opened for append or write. ! 138: */ ! 139: int ! 140: startc(argv, ifn, ofn, aflag) char **argv; char *ifn; char *ofn; int aflag; ! 141: { ! 142: register int n; ! 143: ! 144: reg_flag = R_INVALID; ! 145: if ((pid = fork()) < 0) ! 146: return printr("Cannot fork"); ! 147: if (pid == 0) { ! 148: /* Child process. */ ! 149: if (ifn != NULL) { ! 150: if ((n=open(ifn, 0)) < 0) ! 151: panic("Cannot open \"%s\"", ifn); ! 152: dup2(n, 0); ! 153: close(n); ! 154: } ! 155: if (ofn != NULL) { ! 156: n = -1; ! 157: if (aflag) { ! 158: if ((n = open(ofn, 1)) >= 0) ! 159: lseek(n, 0L, SEEK_END); ! 160: } ! 161: if (n < 0) { ! 162: if ((n=creat(ofn, 0644)) < 0) ! 163: panic("%s: cannot create", ofn); ! 164: } ! 165: dup2(n, 1); ! 166: close(n); ! 167: } ! 168: ptrace(PTRACE_SETUP, 0, 0, 0); /* I hear you, Dad... */ ! 169: execv(lfn, argv); ! 170: exit(1); ! 171: } ! 172: /* Parent process. */ ! 173: if (waitc() == 0) ! 174: return 0; ! 175: ! 176: /* ! 177: * Now the child is running, so map the child process rather ! 178: * than the disk file. ! 179: * FIX_ME The map addresses for DSEG and ISEG here are bogus. ! 180: */ ! 181: map_init(); ! 182: map_set(DSEG, MIN_ADDR, MAX_ADDR, (off_t)0, MAP_CHILD); ! 183: map_set(ISEG, MIN_ADDR, MAX_ADDR, (off_t)0, MAP_CHILD); ! 184: map_set(USEG, MIN_ADDR, (ADDR_T)UPASIZE, (off_t)0, MAP_CHILD); ! 185: execflag = 1; ! 186: get_regs(R_SOME); ! 187: return 1; ! 188: } ! 189: ! 190: /* ! 191: * Wait for the child to stop. ! 192: */ ! 193: int ! 194: waitc() ! 195: { ! 196: register int p; ! 197: int s; ! 198: ! 199: while ((p = wait(&s)) != pid) { ! 200: if (p >= 0) { ! 201: printr("Adopted a child %d", p); ! 202: continue; ! 203: } ! 204: if (intflag == 0) { ! 205: execflag = 0; ! 206: return printr("Nonexistent child"); ! 207: } ! 208: intflag = 0; ! 209: } ! 210: if ((s & 0xff) != 0x7f) { ! 211: execflag = 0; ! 212: return printr("Child process terminated (0x%X)", (s >> 8) & 0xFF ); ! 213: } ! 214: return 1; ! 215: } ! 216: ! 217: #if DBPTRACE ! 218: #undef ptrace ! 219: int ! 220: dbptrace(cmd, pid, loc, val) int cmd, pid, loc, val; ! 221: { ! 222: register int n; ! 223: ! 224: printf("ptrace(%d, %d, 0x%X, 0x%X) = ", cmd, pid, loc, val); ! 225: n = ptrace(cmd, pid, loc, val); ! 226: printf("0x%X\n", n); ! 227: return n; ! 228: } ! 229: #endif ! 230: ! 231: /* end of db/db8.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.