Commit | Line | Data |
---|---|---|
a1dada70 | 1 | #ifndef lint |
ecc0ec9e | 2 | static char sccsid[] = "@(#)access.c 4.8 %G%"; |
a1dada70 | 3 | #endif |
f974a810 | 4 | /* |
6d4468aa | 5 | * Adb: access data in file/process address space. |
f974a810 | 6 | * |
6d4468aa BJ |
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. | |
f974a810 | 11 | */ |
6eadceb1 | 12 | |
f974a810 | 13 | #include "defs.h" |
6d4468aa | 14 | |
f974a810 | 15 | |
f974a810 BJ |
16 | MAP txtmap; |
17 | MAP datmap; | |
18 | INT wtflag; | |
19 | STRING errflg; | |
20 | INT errno; | |
21 | ||
22 | INT pid; | |
23 | ||
6d4468aa BJ |
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 | */ | |
28 | put(addr, space, value) | |
29 | off_t addr; { (void) access(WT, addr, space, value); } | |
f974a810 | 30 | |
6d4468aa BJ |
31 | u_int |
32 | get(addr, space) | |
33 | off_t addr; { return (access(RD, addr, space, 0)); }; | |
f974a810 | 34 | |
6d4468aa BJ |
35 | u_int |
36 | chkget(addr, space) | |
37 | off_t addr; { u_int w = get(addr, space); chkerr(); return(w); } | |
f974a810 | 38 | |
6d4468aa BJ |
39 | u_int |
40 | bchkget(addr, space) | |
41 | off_t addr; { return(chkget(addr, space) & LOBYTE); } | |
f974a810 | 42 | |
6d4468aa BJ |
43 | /* |
44 | * Read/write according to mode at address addr in i/d space. | |
45 | * Value is quantity to be written, if write. | |
46 | * | |
47 | * This routine decides whether to get the data from the subprocess | |
48 | * address space with ptrace, or to get it from the files being | |
49 | * debugged. | |
50 | * | |
51 | * When the kernel is being debugged with the -k flag we interpret | |
52 | * the system page tables for data space, mapping p0 and p1 addresses | |
53 | * relative to the ``current'' process (as specified by its p_addr in | |
54 | * <p) and mapping system space addresses through the system page tables. | |
55 | */ | |
56 | access(mode, addr, space, value) | |
57 | int mode, space, value; | |
58 | off_t addr; | |
f974a810 | 59 | { |
6d4468aa BJ |
60 | int rd = mode == RD; |
61 | int file, w; | |
62 | ||
6d4468aa BJ |
63 | if (space == NSP) |
64 | return(0); | |
65 | if (pid) { | |
ecc0ec9e SL |
66 | int pmode = (space&DSP ? |
67 | (rd ? PT_READ_D : PT_WRITE_D) : | |
68 | (rd ? PT_READ_I : PT_WRITE_I)); | |
6d4468aa BJ |
69 | |
70 | w = ptrace(pmode, pid, addr, value); | |
71 | if (errno) | |
72 | rwerr(space); | |
73 | return (w); | |
74 | } | |
75 | w = 0; | |
76 | if (mode==WT && wtflag==0) | |
77 | error("not in write mode"); | |
a0daaed3 | 78 | if (!chkmap(&addr, space)) |
6d4468aa | 79 | return (0); |
6d4468aa BJ |
80 | file = (space&DSP) ? datmap.ufd : txtmap.ufd; |
81 | if (kernel && space == DSP) { | |
6d4468aa BJ |
82 | addr = vtophys(addr); |
83 | if (addr < 0) | |
84 | return (0); | |
6d4468aa | 85 | } |
47cbe1cb | 86 | if (physrw(file, addr, rd ? &w : &value, rd) < 0) |
6d4468aa BJ |
87 | rwerr(space); |
88 | return (w); | |
f974a810 BJ |
89 | } |
90 | ||
6d4468aa BJ |
91 | /* |
92 | * When looking at kernel data space through /dev/mem or | |
93 | * with a core file, do virtual memory mapping. | |
94 | */ | |
95 | vtophys(addr) | |
96 | off_t addr; | |
f974a810 | 97 | { |
6d4468aa BJ |
98 | int oldaddr = addr; |
99 | int v; | |
100 | struct pte pte; | |
101 | ||
102 | addr &= ~0xc0000000; | |
103 | v = btop(addr); | |
6d4468aa BJ |
104 | switch (oldaddr&0xc0000000) { |
105 | ||
106 | case 0xc0000000: | |
107 | case 0x80000000: | |
108 | /* | |
109 | * In system space get system pte. If | |
110 | * valid or reclaimable then physical address | |
111 | * is combination of its page number and the page | |
112 | * offset of the original address. | |
113 | */ | |
114 | if (v >= slr) | |
115 | goto oor; | |
116 | addr = ((long)(sbr+v)) &~ 0x80000000; | |
117 | goto simple; | |
118 | ||
119 | case 0x40000000: | |
120 | /* | |
121 | * In p1 space must not be in shadow region. | |
122 | */ | |
123 | if (v < pcb.pcb_p1lr) | |
124 | goto oor; | |
125 | addr = pcb.pcb_p1br+v; | |
126 | break; | |
127 | ||
128 | case 0x00000000: | |
129 | /* | |
130 | * In p0 space must not be off end of region. | |
131 | */ | |
132 | if (v >= pcb.pcb_p0lr) | |
133 | goto oor; | |
134 | addr = pcb.pcb_p0br+v; | |
135 | break; | |
136 | oor: | |
6d4468aa BJ |
137 | errflg = "address out of segment"; |
138 | return (-1); | |
139 | } | |
140 | /* | |
141 | * For p0/p1 address, user-level page table should | |
142 | * be in kernel vm. Do second-level indirect by recursing. | |
143 | */ | |
144 | if ((addr & 0x80000000) == 0) { | |
145 | errflg = "bad p0br or p1br in pcb"; | |
6d4468aa BJ |
146 | return (-1); |
147 | } | |
6d4468aa | 148 | addr = vtophys(addr); |
6d4468aa BJ |
149 | simple: |
150 | /* | |
151 | * Addr is now address of the pte of the page we | |
152 | * are interested in; get the pte and paste up the | |
153 | * physical address. | |
154 | */ | |
155 | if (physrw(fcor, addr, (int *)&pte, 1) < 0) { | |
156 | errflg = "page table botch"; | |
157 | return (-1); | |
158 | } | |
159 | /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */ | |
160 | if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) { | |
161 | errflg = "page not valid/reclaimable"; | |
162 | return (-1); | |
163 | } | |
164 | return (ptob(pte.pg_pfnum) + (oldaddr & PGOFSET)); | |
f974a810 | 165 | } |
f974a810 | 166 | |
6d4468aa BJ |
167 | rwerr(space) |
168 | int space; | |
6eadceb1 BJ |
169 | { |
170 | ||
6d4468aa BJ |
171 | if (space & DSP) |
172 | errflg = "data address not found"; | |
173 | else | |
174 | errflg = "text address not found"; | |
6eadceb1 BJ |
175 | } |
176 | ||
6d4468aa BJ |
177 | physrw(file, addr, aw, rd) |
178 | off_t addr; | |
179 | int *aw, rd; | |
6eadceb1 | 180 | { |
6eadceb1 | 181 | |
6d4468aa BJ |
182 | if (longseek(file,addr)==0 || |
183 | (rd ? read(file,aw,sizeof(int)) : write(file,aw,sizeof(int))) < 1) | |
184 | return (-1); | |
6d4468aa | 185 | return (0); |
6eadceb1 | 186 | } |
6d4468aa BJ |
187 | |
188 | chkmap(addr,space) | |
189 | REG L_INT *addr; | |
f974a810 BJ |
190 | REG INT space; |
191 | { | |
192 | REG MAPPTR amap; | |
193 | amap=((space&DSP?&datmap:&txtmap)); | |
6d4468aa BJ |
194 | IF space&STAR ORF !within(*addr,amap->b1,amap->e1) |
195 | THEN IF within(*addr,amap->b2,amap->e2) | |
196 | THEN *addr += (amap->f2)-(amap->b2); | |
197 | ELSE rwerr(space); return(0); | |
f974a810 | 198 | FI |
6d4468aa | 199 | ELSE *addr += (amap->f1)-(amap->b1); |
f974a810 BJ |
200 | FI |
201 | return(1); | |
202 | } | |
203 | ||
6d4468aa BJ |
204 | within(addr,lbd,ubd) |
205 | u_int addr, lbd, ubd; { return(addr>=lbd && addr<ubd); } | |
f974a810 BJ |
206 | |
207 | longseek(f, a) | |
6d4468aa | 208 | off_t a; { return(lseek(f, a, 0) != -1); } |