1 #ifndef lint 2 static char sccsid[] = "@(#)access.c 5.1 (Berkeley) 01/16/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 * N.B.: The cache retains the pid, so that killing and restarting 127 * a process invalidates the cache entry. If pid's were reused fast 128 * enough this could fail, and we would need a cache-invalidate 129 * routine, to be called whenever a process is started. Fortunately 130 * that is not now the case. 131 */ 132 int cachehit, cachemiss; /* statistics */ 133 134 static int 135 cptrace(rw, space, p, addr, val) 136 enum rwmode rw; 137 int space, p, *addr, *val; 138 { 139 static struct cache { 140 short rop, wop; /* ptrace ops for read and write */ 141 int pid; /* pid, iff cache entry valid */ 142 int *addr; /* address of cached value */ 143 int val; /* and the value */ 144 } cache[2] = { {PT_READ_D, PT_WRITE_D}, {PT_READ_I, PT_WRITE_I} }; 145 register struct cache *c; 146 int v; 147 148 /* set c to point to cache[0] for dspace, cache[1] for ispace */ 149 c = space & SP_DATA ? &cache[0] : &cache[1]; 150 if (rw == RWMODE_READ) { 151 if (c->pid == p && c->addr == addr) { 152 cachehit++; 153 *val = c->val; 154 return (0); 155 } 156 cachemiss++; 157 errno = 0; 158 if ((v = ptrace(c->rop, p, addr, 0)) == -1 && errno) 159 return (-1); 160 *val = v; 161 } else { 162 c->pid = 0; /* paranoia */ 163 errno = 0; 164 if (ptrace(c->wop, p, addr, v = *val) == -1 && errno) 165 return (-1); 166 } 167 c->pid = p; 168 c->addr = addr; 169 c->val = v; 170 return (0); 171 } 172 173 int 174 io_ptrace(rw, space, rmtaddr, localaddr, cnt) 175 register enum rwmode rw; 176 register int space; 177 addr_t rmtaddr; 178 register caddr_t localaddr; 179 register int cnt; 180 { 181 register addr_t addr; 182 register int nbytes, ret = 0, off; 183 int tmp; 184 185 /* 186 * Start by aligning rmtaddr; set nbytes to the number of bytes of 187 * useful data we shall obtain. 188 */ 189 off = rmtaddr % sizeof(int); /* addr_t is unsigned */ 190 addr = rmtaddr - off; 191 nbytes = sizeof(int) - off; 192 while (cnt != 0) { 193 if (cnt < nbytes) 194 nbytes = cnt; 195 if (rw == RWMODE_READ) { 196 if (cptrace(rw, space, pid, (int *)addr, &tmp)) 197 return (ret); 198 bcopy((caddr_t)&tmp + off, localaddr, nbytes); 199 } else { 200 if (nbytes < sizeof(int) && 201 cptrace(RWMODE_READ, space, pid, (int *)addr, &tmp)) 202 return (ret); 203 bcopy(localaddr, (caddr_t)&tmp + off, nbytes); 204 if (cptrace(rw, space, pid, (int *)addr, &tmp)) 205 return (ret); 206 } 207 addr += sizeof(int); 208 localaddr += nbytes; 209 ret += nbytes; 210 cnt -= nbytes; 211 /* 212 * For the rest of the loop, the offset is 0 and we can 213 * use all the bytes obtained. 214 */ 215 off = 0; 216 nbytes = sizeof(int); 217 } 218 return (ret); 219 } 220