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); }