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 */ 28 put(addr, space, value) 29 off_t addr; { (void) access(WT, addr, space, value); } 30 31 u_int 32 get(addr, space) 33 off_t addr; { return (access(RD, addr, space, 0)); }; 34 35 u_int 36 chkget(addr, space) 37 off_t addr; { u_int w = get(addr, space); chkerr(); return(w); } 38 39 u_int 40 bchkget(addr, space) 41 off_t addr; { return(chkget(addr, space) & LOBYTE); } 42 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; 59 { 60 int rd = mode == RD; 61 int file, w; 62 63 if (space == NSP) 64 return(0); 65 if (pid) { 66 int pmode = (space&DSP ? 67 (rd ? PT_READ_D : PT_WRITE_D) : 68 (rd ? PT_READ_I : PT_WRITE_I)); 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"); 78 if (!chkmap(&addr, space)) 79 return (0); 80 file = (space&DSP) ? datmap.ufd : txtmap.ufd; 81 if (kernel && space == DSP) { 82 addr = vtophys(addr); 83 if (addr < 0) 84 return (0); 85 } 86 if (physrw(file, addr, rd ? &w : &value, rd) < 0) 87 rwerr(space); 88 return (w); 89 } 90 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; 97 { 98 int oldaddr = addr; 99 int v; 100 struct pte pte; 101 102 addr &= ~0xc0000000; 103 v = btop(addr); 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: 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"; 146 return (-1); 147 } 148 addr = vtophys(addr); 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)); 165 } 166 167 rwerr(space) 168 int space; 169 { 170 171 if (space & DSP) 172 errflg = "data address not found"; 173 else 174 errflg = "text address not found"; 175 } 176 177 physrw(file, addr, aw, rd) 178 off_t addr; 179 int *aw, rd; 180 { 181 182 if (longseek(file,addr)==0 || 183 (rd ? read(file,aw,sizeof(int)) : write(file,aw,sizeof(int))) < 1) 184 return (-1); 185 return (0); 186 } 187 188 chkmap(addr,space) 189 REG L_INT *addr; 190 REG INT space; 191 { 192 REG MAPPTR amap; 193 amap=((space&DSP?&datmap:&txtmap)); 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); 198 FI 199 ELSE *addr += (amap->f1)-(amap->b1); 200 FI 201 return(1); 202 } 203 204 within(addr,lbd,ubd) 205 u_int addr, lbd, ubd; { return(addr>=lbd && addr<ubd); } 206 207 longseek(f, a) 208 off_t a; { return(lseek(f, a, 0) != -1); } 209