1 #ifndef lint 2 static char sccsid[] = "@(#)access.c 5.2 (Berkeley) 02/04/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 } 229