|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)access.c 5.3 (Berkeley) 9/15/89"; ! 3: #endif ! 4: ! 5: /* ! 6: * Adb: access data in file/process address space. ! 7: */ ! 8: ! 9: #include "defs.h" ! 10: #include <sys/file.h> ! 11: #include <sys/ptrace.h> ! 12: ! 13: off_t lseek(); ! 14: ! 15: /* ! 16: * Read or write from or to the given address, accessing or altering ! 17: * only the given byte(s). Return the number of bytes transferred. ! 18: * Remote (debuggee) addresses are specified as a <space,address> pair. ! 19: * Neither the remote nor the local address need be aligned. ! 20: * ! 21: * If there is a current process, ask the system to do this (via ptrace ! 22: * [ick]). If debugging the kernel, use vtophys() to map virtual to ! 23: * physical locations (in a system-dependent manner). Otherwise we ! 24: * can just read or write the files being debugged directly. ! 25: */ ! 26: int ! 27: adbio(rw, space, rmtaddr, localaddr, cnt) ! 28: enum rwmode rw; ! 29: int space; ! 30: addr_t rmtaddr; ! 31: caddr_t localaddr; ! 32: int cnt; ! 33: { ! 34: register int ret; ! 35: register struct map *mp; ! 36: struct m1 *mm; ! 37: ! 38: static char *derr = "data address not found"; ! 39: static char *terr = "text address not found"; ! 40: #define rwerr() errflag = space & SP_DATA ? derr : terr ! 41: #define within(which) (rmtaddr >= which.b && rmtaddr < which.e) ! 42: ! 43: if (space == SP_NONE) { ! 44: /* The no-space is all zero. */ ! 45: bzero(localaddr, cnt); ! 46: return (cnt); ! 47: } ! 48: if (pid) { ! 49: ret = io_ptrace(rw, space, rmtaddr, localaddr, cnt); ! 50: if (ret != cnt) ! 51: rwerr(); ! 52: return (ret); ! 53: } ! 54: if (rw == RWMODE_WRITE && !wtflag) ! 55: error("not in write mode"); ! 56: mp = space & SP_DATA ? &datmap : &txtmap; ! 57: if ((space & SP_STAR) == 0 && within(mp->m1)) ! 58: mm = &mp->m1; ! 59: else if (within(mp->m2)) ! 60: mm = &mp->m2; ! 61: else { ! 62: rwerr(); ! 63: return (0); ! 64: } ! 65: rmtaddr += mm->f - mm->b; ! 66: if (kernel && space == SP_DATA) { ! 67: char *err = NULL; ! 68: ! 69: rmtaddr = vtophys(rmtaddr, &err); ! 70: if (err) { ! 71: errflag = err; ! 72: return (0); ! 73: } ! 74: } ! 75: if (lseek(mp->ufd, (off_t)rmtaddr, 0) == -1) { ! 76: rwerr(); ! 77: return (0); ! 78: } ! 79: if (rw == RWMODE_READ) { ! 80: ret = read(mp->ufd, localaddr, cnt); ! 81: /* gratuitously supply extra zeroes at end of file */ ! 82: if (ret > 0 && ret < cnt) { ! 83: bzero(localaddr + ret, cnt - ret); ! 84: ret = cnt; ! 85: } ! 86: } else ! 87: ret = write(mp->ufd, localaddr, cnt); ! 88: if (ret != cnt) ! 89: rwerr(); ! 90: return (ret); ! 91: #undef rwerr ! 92: #undef within ! 93: } ! 94: ! 95: /* ! 96: * Read a single object of length `len' from the core file at the ! 97: * given offset. Return the length read. (This routine allows vtophys ! 98: * and kernel crash startup code to read ptes, etc.) ! 99: */ ! 100: int ! 101: readcore(off, addr, len) ! 102: off_t off; ! 103: caddr_t addr; ! 104: int len; ! 105: { ! 106: ! 107: if (lseek(corefile.fd, off, L_SET) == -1) ! 108: return (-1); ! 109: return (read(corefile.fd, addr, len)); ! 110: } ! 111: ! 112: /* ! 113: * THE FOLLOWING IS GROSS. WE SHOULD REPLACE PTRACE WITH SPECIAL ! 114: * FILES A LA /proc. ! 115: * ! 116: * Read or write using ptrace. io_ptrace arranges that the ! 117: * addresses passed to ptrace are an even multiple of sizeof(int), ! 118: * and is able to read or write single bytes. ! 119: * ! 120: * Since ptrace is so horribly slow, and some commands do repeated ! 121: * reading of units smaller than an `int', io_ptrace calls cptrace ! 122: * (cached ptrace) to allow some cacheing. cptrace also converts a ! 123: * read/write op and a space into a ptrace op, and returns 0 on success ! 124: * and hence takes a pointer to the value cell rather than the value. ! 125: */ ! 126: struct cache { ! 127: short rop, wop; /* ptrace ops for read and write */ ! 128: int valid; /* true iff cache entry valid */ ! 129: int *addr; /* address of cached value */ ! 130: int val; /* and the value */ ! 131: }; ! 132: static struct cache icache = { PT_READ_I, PT_WRITE_I }; ! 133: static struct cache dcache = { PT_READ_D, PT_WRITE_D }; ! 134: ! 135: /* ! 136: * Invalidate one or both caches. ! 137: * This is the only function that accepts two spaces simultaneously. ! 138: */ ! 139: cacheinval(space) ! 140: int space; ! 141: { ! 142: ! 143: if (space & SP_INSTR) ! 144: icache.valid = 0; ! 145: if (space & SP_DATA) ! 146: dcache.valid = 0; ! 147: } ! 148: ! 149: int cachehit, cachemiss; /* statistics */ ! 150: ! 151: static int ! 152: cptrace(rw, space, p, addr, val) ! 153: enum rwmode rw; ! 154: int space, p, *addr, *val; ! 155: { ! 156: register struct cache *c = space & SP_DATA ? &dcache : &icache; ! 157: int v; ! 158: ! 159: if (rw == RWMODE_READ) { ! 160: if (c->valid && c->addr == addr) { ! 161: cachehit++; ! 162: *val = c->val; ! 163: return (0); ! 164: } ! 165: cachemiss++; ! 166: errno = 0; ! 167: if ((v = ptrace(c->rop, p, addr, 0)) == -1 && errno) ! 168: return (-1); ! 169: *val = v; ! 170: } else { ! 171: c->valid = 0; /* paranoia */ ! 172: errno = 0; ! 173: if (ptrace(c->wop, p, addr, v = *val) == -1 && errno) ! 174: return (-1); ! 175: } ! 176: c->valid = 1; ! 177: c->addr = addr; ! 178: c->val = v; ! 179: return (0); ! 180: } ! 181: ! 182: int ! 183: io_ptrace(rw, space, rmtaddr, localaddr, cnt) ! 184: register enum rwmode rw; ! 185: register int space; ! 186: addr_t rmtaddr; ! 187: register caddr_t localaddr; ! 188: register int cnt; ! 189: { ! 190: register addr_t addr; ! 191: register int nbytes, ret = 0, off; ! 192: int tmp; ! 193: ! 194: /* ! 195: * Start by aligning rmtaddr; set nbytes to the number of bytes of ! 196: * useful data we shall obtain. ! 197: */ ! 198: off = rmtaddr % sizeof(int); /* addr_t is unsigned */ ! 199: addr = rmtaddr - off; ! 200: nbytes = sizeof(int) - off; ! 201: while (cnt != 0) { ! 202: if (cnt < nbytes) ! 203: nbytes = cnt; ! 204: if (rw == RWMODE_READ) { ! 205: if (cptrace(rw, space, pid, (int *)addr, &tmp)) ! 206: return (ret); ! 207: bcopy((caddr_t)&tmp + off, localaddr, nbytes); ! 208: } else { ! 209: if (nbytes < sizeof(int) && ! 210: cptrace(RWMODE_READ, space, pid, (int *)addr, &tmp)) ! 211: return (ret); ! 212: bcopy(localaddr, (caddr_t)&tmp + off, nbytes); ! 213: if (cptrace(rw, space, pid, (int *)addr, &tmp)) ! 214: return (ret); ! 215: } ! 216: addr += sizeof(int); ! 217: localaddr += nbytes; ! 218: ret += nbytes; ! 219: cnt -= nbytes; ! 220: /* ! 221: * For the rest of the loop, the offset is 0 and we can ! 222: * use all the bytes obtained. ! 223: */ ! 224: off = 0; ! 225: nbytes = sizeof(int); ! 226: } ! 227: return (ret); ! 228: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.