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