1 #ifndef lint
2 static char sccsid[] = "@(#)access.c 4.8 10/13/84";
3 #endif
4 /*
5 * Adb: access data in file/process address space.
6 *
7 * The routines in this file access referenced data using
8 * the maps to access files, ptrace to access subprocesses,
9 * or the system page tables when debugging the kernel,
10 * to translate virtual to physical addresses.
11 */
12
13 #include "defs.h"
14
15
16 MAP txtmap;
17 MAP datmap;
18 INT wtflag;
19 STRING errflg;
20 int errno;
21
22 INT pid;
23
24 /*
25 * Primitives: put a value in a space, get a value from a space
26 * and get a word or byte not returning if an error occurred.
27 */
put(addr,space,value)28 put(addr, space, value)
29 off_t addr; { (void) access(WT, addr, space, value); }
30
31 #if vax || pdp11
32 u_int
get(addr,space)33 get(addr, space)
34 off_t addr; { return (access(RD, addr, space, 0)); }
35
36 u_int
lchkget(addr,space)37 lchkget(addr, space)
38 off_t addr; { u_int w = get(addr, space); chkerr(); return(w); }
39 #endif
40
41 #ifdef mc68000
42 /*
43 * 68000 Unices don't like odd addresses.
44 */
45 u_int
get(addr,space)46 get(addr, space)
47 off_t addr;
48 {
49 u_int data;
50
51 if (addr & 1) {
52 data = access(RD, addr - 1, space, 0);
53 return ((data >> 8) & 0xffff);
54 }
55 data = access(RD, addr, space, 0);
56 return ((data >> 16) & 0xffff);
57 }
58
59 u_int
lget(addr,space)60 lget(addr, space)
61 off_t addr;
62 {
63 if (addr & 1) {
64 u_int data = get(addr, space);
65 return (get(addr + 2, space) | (data << 16));
66 }
67 return (access(RD, addr, space, 0));
68 }
69
70 u_int
lchkget(addr,space)71 lchkget(addr, space)
72 off_t addr; { u_int w = lget(addr, space); chkerr(); return(w); }
73 #endif
74
75 #if !pdp11 && !vax && !mc68000
76 help!
77 #endif
78
79 u_int
chkget(addr,space)80 chkget(addr, space)
81 off_t addr; { u_int w = get(addr, space); chkerr(); return(w); }
82
83 u_int
bchkget(addr,space)84 bchkget(addr, space)
85 off_t addr; { return(lobyte(chkget(addr, space))); }
86
87 /*
88 * Read/write according to mode at address addr in i/d space.
89 * Value is quantity to be written, if write.
90 *
91 * This routine decides whether to get the data from the subprocess
92 * address space with ptrace, or to get it from the files being
93 * debugged.
94 *
95 * When the kernel is being debugged with the -k flag we interpret
96 * the system page tables for data space, mapping p0 and p1 addresses
97 * relative to the ``current'' process (as specified by its p_addr in
98 * <p) and mapping system space addresses through the system page tables.
99 */
access(mode,addr,space,value)100 access(mode, addr, space, value)
101 int mode, space, value;
102 off_t addr;
103 {
104 int rd = mode == RD;
105 int file, w;
106
107 if (space == NSP)
108 return(0);
109 if (pid) {
110 int pmode = (space&DSP ?
111 (rd ? PT_READ_D : PT_WRITE_D) :
112 (rd ? PT_READ_I : PT_WRITE_I));
113
114 w = ptrace(pmode, pid, addr, value);
115 if (errno)
116 rwerr(space);
117 return (w);
118 }
119 w = 0;
120 if (mode==WT && wtflag==0)
121 error("not in write mode");
122 if (!chkmap(&addr, space))
123 return (0);
124 file = mapptr(space)->ufd;
125 if (kernel && space == DSP) {
126 addr = vtophys(addr);
127 if (addr == -1)
128 return (0);
129 }
130 if (physrw(file, addr, rd ? &w : &value, rd) < 0)
131 rwerr(space);
132 return (w);
133 }
134
135 #ifdef vax
136 /*
137 * When looking at kernel data space through /dev/mem or
138 * with a core file, do virtual memory mapping.
139 */
vtophys(addr)140 vtophys(addr)
141 off_t addr;
142 {
143 int oldaddr = addr;
144 int v;
145 struct pte pte;
146
147 addr &= ~0xc0000000;
148 v = btop(addr);
149 switch (oldaddr&0xc0000000) {
150
151 case 0xc0000000:
152 case 0x80000000:
153 /*
154 * In system space get system pte. If
155 * valid or reclaimable then physical address
156 * is combination of its page number and the page
157 * offset of the original address.
158 */
159 if (v >= slr)
160 goto oor;
161 addr = ((long)(sbr+v)) &~ 0x80000000;
162 goto simple;
163
164 case 0x40000000:
165 /*
166 * In p1 space must not be in shadow region.
167 */
168 if (v < pcb.pcb_p1lr)
169 goto oor;
170 addr = pcb.pcb_p1br+v;
171 break;
172
173 case 0x00000000:
174 /*
175 * In p0 space must not be off end of region.
176 */
177 if (v >= pcb.pcb_p0lr)
178 goto oor;
179 addr = pcb.pcb_p0br+v;
180 break;
181 oor:
182 errflg = "address out of segment";
183 return (-1);
184 }
185 /*
186 * For p0/p1 address, user-level page table should
187 * be in kernel vm. Do second-level indirect by recursing.
188 */
189 if ((addr & 0x80000000) == 0) {
190 errflg = "bad p0br or p1br in pcb";
191 return (-1);
192 }
193 addr = vtophys(addr);
194 simple:
195 /*
196 * Addr is now address of the pte of the page we
197 * are interested in; get the pte and paste up the
198 * physical address.
199 */
200 if (physrw(fcor, addr, (int *)&pte, 1) < 0) {
201 errflg = "page table botch";
202 return (-1);
203 }
204 /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */
205 if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) {
206 errflg = "page not valid/reclaimable";
207 return (-1);
208 }
209 return (ptob(pte.pg_pfnum) + (oldaddr & PGOFSET));
210 }
211 #endif
212
213 #ifdef hp300
214
215 #ifdef NEWVM
216 #ifndef btop
217 #define btop hp300_btop
218 #endif
219 #ifndef ptob
220 #define ptob hp300_ptob
221 #endif
222 #endif
223
224 int is68040 = 0;
225
226 /*
227 * When looking at kernel data space through /dev/mem or
228 * with a core file, do virtual memory mapping.
229 */
vtophys(addr)230 vtophys(addr)
231 off_t addr;
232 {
233 int v;
234 struct pte pte;
235 int oldaddr = addr;
236
237 if (INKERNEL(addr)) {
238 /*
239 * In system space get system pte. If
240 * valid or reclaimable then physical address
241 * is combination of its page number and the page
242 * offset of the original address.
243 */
244 #ifdef NEWVM
245 /* locate PTE page in segtab */
246 if (is68040) {
247 int steaddr;
248
249 steaddr = KVTOPH((int)(sbr+(addr>>SG4_SHIFT1)));
250 lseek(fcor, (off_t)steaddr, 0);
251 read(fcor, &pte, sizeof pte);
252 #if 0
253 printf("va %X: ste1 %X@%X",
254 addr, *(int *)&pte, steaddr);
255 #endif
256 if (*(int *)&pte == SG_NV)
257 goto bad;
258 steaddr = (int)(((int *)(*(int *)&pte & SG4_ADDR1)) +
259 ((addr & SG4_MASK2) >> SG4_SHIFT2));
260 physrw(fcor, steaddr, (int *)&pte, 1);
261 #if 0
262 printf(" ste2 %X@%X", *(int *)&pte, steaddr);
263 #endif
264 } else {
265 lseek(fcor,
266 (off_t)KVTOPH((int)(sbr+(addr>>SG_ISHIFT))), 0);
267 read(fcor, &pte, sizeof pte);
268 #if 0
269 printf("va %X: ste %X@%X",
270 addr, *(int *)&pte, sbr+(addr>>SG_ISHIFT));
271 #endif
272 }
273 /* see if STE is valid */
274 if (*(int *)&pte == SG_NV) {
275 bad:
276 errflg = "address out of segment";
277 return(-1);
278 }
279 /* desired PTE is within that page */
280 v = btop(addr & SG_PMASK);
281 addr = (pte.pg_pfnum << PGSHIFT) + (v * sizeof pte);
282 #else
283 v = btop(addr - KERNOFF);
284 addr = (long)(sbr+v) + lowram;
285 #endif
286 }
287 else if (INUDOT(addr)) {
288 addr -= kernudot;
289 addr += masterpcbb;
290 return(vtophys(addr));
291 }
292 else /* user space */ {
293 #ifdef NEWVM
294 errflg = "cannot translate user addresses";
295 return (-1);
296 #else
297 v = btop(addr);
298 /*
299 * Must be within bounds of p0 or p1 regions.
300 */
301 if (v < pcb.pcb_p0lr)
302 addr = pcb.pcb_p0br+v;
303 else if (v >= pcb.pcb_p1lr)
304 addr = pcb.pcb_p1br+v;
305 else {
306 errflg = "address out of segment";
307 return (-1);
308 }
309 /*
310 * For p0/p1 address, user-level page table should
311 * be in kernel vm. Do second-level indirect by recursing.
312 */
313 if (!INKERNEL(addr)) {
314 errflg = "bad p0br or p1br in pcb";
315 return (-1);
316 }
317 addr = vtophys(addr);
318 #endif
319 }
320 /*
321 * Addr is now address of the pte of the page we
322 * are interested in; get the pte and paste up the
323 * physical address.
324 */
325 if (physrw(fcor, addr, (int *)&pte, 1) < 0) {
326 errflg = "page table botch";
327 return (-1);
328 }
329 if (pte.pg_v == 0 &&
330 #ifdef NEWVM
331 pte.pg_pfnum == 0
332 #else
333 (pte.pg_fod || pte.pg_pfnum == 0)
334 #endif
335 ) {
336 errflg = "page not valid/reclaimable";
337 return (-1);
338 }
339 #if 0
340 printf(" -> pte %X@%X -> addr %X\n",
341 *(int *)&pte, addr, ptob(pte.pg_pfnum) + (oldaddr & PGOFSET));
342 #endif
343 return (ptob(pte.pg_pfnum) + (oldaddr & PGOFSET));
344 }
345 #endif
346
347 #if !vax && !hp300
348 help!
349 #endif
350
rwerr(space)351 rwerr(space)
352 int space;
353 {
354
355 if (space & DSP)
356 errflg = "data address not found";
357 else if (space & PSP)
358 errflg = "physical address not found";
359 else
360 errflg = "text address not found";
361 }
362
physrw(file,addr,aw,rd)363 physrw(file, addr, aw, rd)
364 off_t addr;
365 int *aw, rd;
366 {
367
368 #ifdef hp300
369 if (kcore && !kmem && file == fcor)
370 addr -= lowram;
371 #endif
372 if (longseek(file,addr)==0 ||
373 (rd ? read(file,aw,sizeof(int)) : write(file,aw,sizeof(int))) < 1)
374 return (-1);
375 return (0);
376 }
377
chkmap(addr,space)378 chkmap(addr,space)
379 REG L_INT *addr;
380 REG INT space;
381 {
382 REG MAPPTR amap;
383 amap = mapptr(space);
384 IF space&STAR ORF !within(*addr,amap->b1,amap->e1)
385 THEN IF within(*addr,amap->b2,amap->e2)
386 THEN *addr += (amap->f2)-(amap->b2);
387 ELSE rwerr(space); return(0);
388 FI
389 ELSE *addr += (amap->f1)-(amap->b1);
390 FI
391 return(1);
392 }
393
within(addr,lbd,ubd)394 within(addr,lbd,ubd)
395 u_int addr, lbd, ubd; { return(addr>=lbd && addr<ubd); }
396
longseek(f,a)397 longseek(f, a)
398 off_t a; { return(lseek(f, a, 0) != -1); }
399
400 #ifdef NEWVM
401 #undef lseek
402 #undef off_t
Lseek(f,o,w)403 Lseek(f, o, w)
404 int f, w; Ooff_t o; { return(lseek(f, (off_t)o, w)); }
405 #endif
406