|
|
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.