13753Sroot /* 23778Sroot * Adb: access data in file/process address space. 33753Sroot * 43778Sroot * The routines in this file access referenced data using 53778Sroot * the maps to access files, ptrace to access subprocesses, 63778Sroot * or the system page tables when debugging the kernel, 73778Sroot * to translate virtual to physical addresses. 83753Sroot */ 93753Sroot 103753Sroot #include "defs.h" 11*3780Sroot static char sccsid[] = "@(#)access.c 4.4 05/15/81"; 123753Sroot 133778Sroot 143753Sroot MAP txtmap; 153753Sroot MAP datmap; 163753Sroot INT wtflag; 173753Sroot STRING errflg; 183753Sroot INT errno; 193753Sroot 203753Sroot INT pid; 213753Sroot 223778Sroot /* 233778Sroot * Primitives: put a value in a space, get a value from a space 243778Sroot * and get a word or byte not returning if an error occurred. 253778Sroot */ 263778Sroot put(addr, space, value) 273778Sroot off_t addr; { (void) access(WT, addr, space, value); } 283753Sroot 293778Sroot u_int 303778Sroot get(addr, space) 313778Sroot off_t addr; { return (access(RD, addr, space, 0)); }; 323753Sroot 333778Sroot u_int 343778Sroot chkget(addr, space) 353778Sroot off_t addr; { u_int w = get(addr, space); chkerr(); return(w); } 363753Sroot 373778Sroot u_int 383778Sroot bchkget(addr, space) 393778Sroot off_t addr; { return(chkget(addr, space) & LOBYTE); } 403778Sroot 413778Sroot /* 423778Sroot * Read/write according to mode at address addr in i/d space. 433778Sroot * Value is quantity to be written, if write. 443778Sroot * 453778Sroot * This routine decides whether to get the data from the subprocess 463778Sroot * address space with ptrace, or to get it from the files being 473778Sroot * debugged. 483778Sroot * 493778Sroot * When the kernel is being debugged with the -k flag we interpret 503778Sroot * the system page tables for data space, mapping p0 and p1 addresses 513778Sroot * relative to the ``current'' process (as specified by its p_addr in 523778Sroot * <p) and mapping system space addresses through the system page tables. 533778Sroot */ 543778Sroot access(mode, addr, space, value) 553778Sroot int mode, space, value; 563778Sroot off_t addr; 573753Sroot { 583778Sroot int rd = mode == RD; 593778Sroot int file, w; 603753Sroot 613778Sroot if (space == NSP) 623778Sroot return(0); 633778Sroot if (pid) { 643778Sroot int pmode = (space&DSP?(rd?RDUSER:WDUSER):(rd?RIUSER:WIUSER)); 653753Sroot 663778Sroot w = ptrace(pmode, pid, addr, value); 673778Sroot if (errno) 683778Sroot rwerr(space); 693778Sroot return (w); 703778Sroot } 713778Sroot w = 0; 723778Sroot if (mode==WT && wtflag==0) 733778Sroot error("not in write mode"); 74*3780Sroot if (!chkmap(&addr, space)) 753778Sroot return (0); 763778Sroot file = (space&DSP) ? datmap.ufd : txtmap.ufd; 773778Sroot if (kernel && space == DSP) { 783778Sroot addr = vtophys(addr); 793778Sroot if (addr < 0) 803778Sroot return (0); 813778Sroot } 823778Sroot if (physrw(file, addr, &w, rd) < 0) 833778Sroot rwerr(space); 843778Sroot return (w); 853753Sroot } 863753Sroot 873778Sroot /* 883778Sroot * When looking at kernel data space through /dev/mem or 893778Sroot * with a core file, do virtual memory mapping. 903778Sroot */ 913778Sroot vtophys(addr) 923778Sroot off_t addr; 933753Sroot { 943778Sroot int oldaddr = addr; 953778Sroot int v; 963778Sroot struct pte pte; 973753Sroot 983778Sroot addr &= ~0xc0000000; 993778Sroot v = btop(addr); 1003778Sroot switch (oldaddr&0xc0000000) { 1013753Sroot 1023778Sroot case 0xc0000000: 1033778Sroot case 0x80000000: 1043778Sroot /* 1053778Sroot * In system space get system pte. If 1063778Sroot * valid or reclaimable then physical address 1073778Sroot * is combination of its page number and the page 1083778Sroot * offset of the original address. 1093778Sroot */ 1103778Sroot if (v >= slr) 1113778Sroot goto oor; 1123778Sroot addr = ((long)(sbr+v)) &~ 0x80000000; 1133778Sroot goto simple; 1143778Sroot 1153778Sroot case 0x40000000: 1163778Sroot /* 1173778Sroot * In p1 space must not be in shadow region. 1183778Sroot */ 1193778Sroot if (v < pcb.pcb_p1lr) 1203778Sroot goto oor; 1213778Sroot addr = pcb.pcb_p1br+v; 1223778Sroot break; 1233778Sroot 1243778Sroot case 0x00000000: 1253778Sroot /* 1263778Sroot * In p0 space must not be off end of region. 1273778Sroot */ 1283778Sroot if (v >= pcb.pcb_p0lr) 1293778Sroot goto oor; 1303778Sroot addr = pcb.pcb_p0br+v; 1313778Sroot break; 1323778Sroot oor: 1333778Sroot errflg = "address out of segment"; 1343778Sroot return (-1); 1353778Sroot } 1363778Sroot /* 1373778Sroot * For p0/p1 address, user-level page table should 1383778Sroot * be in kernel vm. Do second-level indirect by recursing. 1393778Sroot */ 1403778Sroot if ((addr & 0x80000000) == 0) { 1413778Sroot errflg = "bad p0br or p1br in pcb"; 1423778Sroot return (-1); 1433778Sroot } 1443778Sroot addr = vtophys(addr); 1453778Sroot simple: 1463778Sroot /* 1473778Sroot * Addr is now address of the pte of the page we 1483778Sroot * are interested in; get the pte and paste up the 1493778Sroot * physical address. 1503778Sroot */ 1513778Sroot if (physrw(fcor, addr, (int *)&pte, 1) < 0) { 1523778Sroot errflg = "page table botch"; 1533778Sroot return (-1); 1543778Sroot } 1553778Sroot /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */ 1563778Sroot if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) { 1573778Sroot errflg = "page not valid/reclaimable"; 1583778Sroot return (-1); 1593778Sroot } 1603778Sroot return (ptob(pte.pg_pfnum) + (oldaddr & PGOFSET)); 1613753Sroot } 1623753Sroot 1633778Sroot rwerr(space) 1643778Sroot int space; 1653777Sroot { 1663777Sroot 1673778Sroot if (space & DSP) 1683778Sroot errflg = "data address not found"; 1693778Sroot else 1703778Sroot errflg = "text address not found"; 1713777Sroot } 1723777Sroot 1733778Sroot physrw(file, addr, aw, rd) 1743778Sroot off_t addr; 1753778Sroot int *aw, rd; 1763777Sroot { 1773777Sroot 1783778Sroot if (longseek(file,addr)==0 || 1793778Sroot (rd ? read(file,aw,sizeof(int)) : write(file,aw,sizeof(int))) < 1) 1803778Sroot return (-1); 1813778Sroot return (0); 1823777Sroot } 1833778Sroot 1843778Sroot chkmap(addr,space) 1853778Sroot REG L_INT *addr; 1863753Sroot REG INT space; 1873753Sroot { 1883753Sroot REG MAPPTR amap; 1893753Sroot amap=((space&DSP?&datmap:&txtmap)); 1903778Sroot IF space&STAR ORF !within(*addr,amap->b1,amap->e1) 1913778Sroot THEN IF within(*addr,amap->b2,amap->e2) 1923778Sroot THEN *addr += (amap->f2)-(amap->b2); 1933778Sroot ELSE rwerr(space); return(0); 1943753Sroot FI 1953778Sroot ELSE *addr += (amap->f1)-(amap->b1); 1963753Sroot FI 1973753Sroot return(1); 1983753Sroot } 1993753Sroot 2003778Sroot within(addr,lbd,ubd) 2013778Sroot u_int addr, lbd, ubd; { return(addr>=lbd && addr<ubd); } 2023753Sroot 2033753Sroot longseek(f, a) 2043778Sroot off_t a; { return(lseek(f, a, 0) != -1); } 205