1*14467Ssam #ifndef lint 2*14467Ssam static char sccsid[] = "@(#)access.c 4.7 08/11/83"; 3*14467Ssam #endif 43753Sroot /* 53778Sroot * Adb: access data in file/process address space. 63753Sroot * 73778Sroot * The routines in this file access referenced data using 83778Sroot * the maps to access files, ptrace to access subprocesses, 93778Sroot * or the system page tables when debugging the kernel, 103778Sroot * to translate virtual to physical addresses. 113753Sroot */ 123753Sroot 133753Sroot #include "defs.h" 143753Sroot 153778Sroot 163753Sroot MAP txtmap; 173753Sroot MAP datmap; 183753Sroot INT wtflag; 193753Sroot STRING errflg; 203753Sroot INT errno; 213753Sroot 223753Sroot INT pid; 233753Sroot 243778Sroot /* 253778Sroot * Primitives: put a value in a space, get a value from a space 263778Sroot * and get a word or byte not returning if an error occurred. 273778Sroot */ 283778Sroot put(addr, space, value) 293778Sroot off_t addr; { (void) access(WT, addr, space, value); } 303753Sroot 313778Sroot u_int 323778Sroot get(addr, space) 333778Sroot off_t addr; { return (access(RD, addr, space, 0)); }; 343753Sroot 353778Sroot u_int 363778Sroot chkget(addr, space) 373778Sroot off_t addr; { u_int w = get(addr, space); chkerr(); return(w); } 383753Sroot 393778Sroot u_int 403778Sroot bchkget(addr, space) 413778Sroot off_t addr; { return(chkget(addr, space) & LOBYTE); } 423778Sroot 433778Sroot /* 443778Sroot * Read/write according to mode at address addr in i/d space. 453778Sroot * Value is quantity to be written, if write. 463778Sroot * 473778Sroot * This routine decides whether to get the data from the subprocess 483778Sroot * address space with ptrace, or to get it from the files being 493778Sroot * debugged. 503778Sroot * 513778Sroot * When the kernel is being debugged with the -k flag we interpret 523778Sroot * the system page tables for data space, mapping p0 and p1 addresses 533778Sroot * relative to the ``current'' process (as specified by its p_addr in 543778Sroot * <p) and mapping system space addresses through the system page tables. 553778Sroot */ 563778Sroot access(mode, addr, space, value) 573778Sroot int mode, space, value; 583778Sroot off_t addr; 593753Sroot { 603778Sroot int rd = mode == RD; 613778Sroot int file, w; 623753Sroot 633778Sroot if (space == NSP) 643778Sroot return(0); 653778Sroot if (pid) { 663778Sroot int pmode = (space&DSP?(rd?RDUSER:WDUSER):(rd?RIUSER:WIUSER)); 673753Sroot 683778Sroot w = ptrace(pmode, pid, addr, value); 693778Sroot if (errno) 703778Sroot rwerr(space); 713778Sroot return (w); 723778Sroot } 733778Sroot w = 0; 743778Sroot if (mode==WT && wtflag==0) 753778Sroot error("not in write mode"); 763780Sroot if (!chkmap(&addr, space)) 773778Sroot return (0); 783778Sroot file = (space&DSP) ? datmap.ufd : txtmap.ufd; 793778Sroot if (kernel && space == DSP) { 803778Sroot addr = vtophys(addr); 813778Sroot if (addr < 0) 823778Sroot return (0); 833778Sroot } 847322Swnj if (physrw(file, addr, rd ? &w : &value, rd) < 0) 853778Sroot rwerr(space); 863778Sroot return (w); 873753Sroot } 883753Sroot 893778Sroot /* 903778Sroot * When looking at kernel data space through /dev/mem or 913778Sroot * with a core file, do virtual memory mapping. 923778Sroot */ 933778Sroot vtophys(addr) 943778Sroot off_t addr; 953753Sroot { 963778Sroot int oldaddr = addr; 973778Sroot int v; 983778Sroot struct pte pte; 993753Sroot 1003778Sroot addr &= ~0xc0000000; 1013778Sroot v = btop(addr); 1023778Sroot switch (oldaddr&0xc0000000) { 1033753Sroot 1043778Sroot case 0xc0000000: 1053778Sroot case 0x80000000: 1063778Sroot /* 1073778Sroot * In system space get system pte. If 1083778Sroot * valid or reclaimable then physical address 1093778Sroot * is combination of its page number and the page 1103778Sroot * offset of the original address. 1113778Sroot */ 1123778Sroot if (v >= slr) 1133778Sroot goto oor; 1143778Sroot addr = ((long)(sbr+v)) &~ 0x80000000; 1153778Sroot goto simple; 1163778Sroot 1173778Sroot case 0x40000000: 1183778Sroot /* 1193778Sroot * In p1 space must not be in shadow region. 1203778Sroot */ 1213778Sroot if (v < pcb.pcb_p1lr) 1223778Sroot goto oor; 1233778Sroot addr = pcb.pcb_p1br+v; 1243778Sroot break; 1253778Sroot 1263778Sroot case 0x00000000: 1273778Sroot /* 1283778Sroot * In p0 space must not be off end of region. 1293778Sroot */ 1303778Sroot if (v >= pcb.pcb_p0lr) 1313778Sroot goto oor; 1323778Sroot addr = pcb.pcb_p0br+v; 1333778Sroot break; 1343778Sroot oor: 1353778Sroot errflg = "address out of segment"; 1363778Sroot return (-1); 1373778Sroot } 1383778Sroot /* 1393778Sroot * For p0/p1 address, user-level page table should 1403778Sroot * be in kernel vm. Do second-level indirect by recursing. 1413778Sroot */ 1423778Sroot if ((addr & 0x80000000) == 0) { 1433778Sroot errflg = "bad p0br or p1br in pcb"; 1443778Sroot return (-1); 1453778Sroot } 1463778Sroot addr = vtophys(addr); 1473778Sroot simple: 1483778Sroot /* 1493778Sroot * Addr is now address of the pte of the page we 1503778Sroot * are interested in; get the pte and paste up the 1513778Sroot * physical address. 1523778Sroot */ 1533778Sroot if (physrw(fcor, addr, (int *)&pte, 1) < 0) { 1543778Sroot errflg = "page table botch"; 1553778Sroot return (-1); 1563778Sroot } 1573778Sroot /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */ 1583778Sroot if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) { 1593778Sroot errflg = "page not valid/reclaimable"; 1603778Sroot return (-1); 1613778Sroot } 1623778Sroot return (ptob(pte.pg_pfnum) + (oldaddr & PGOFSET)); 1633753Sroot } 1643753Sroot 1653778Sroot rwerr(space) 1663778Sroot int space; 1673777Sroot { 1683777Sroot 1693778Sroot if (space & DSP) 1703778Sroot errflg = "data address not found"; 1713778Sroot else 1723778Sroot errflg = "text address not found"; 1733777Sroot } 1743777Sroot 1753778Sroot physrw(file, addr, aw, rd) 1763778Sroot off_t addr; 1773778Sroot int *aw, rd; 1783777Sroot { 1793777Sroot 1803778Sroot if (longseek(file,addr)==0 || 1813778Sroot (rd ? read(file,aw,sizeof(int)) : write(file,aw,sizeof(int))) < 1) 1823778Sroot return (-1); 1833778Sroot return (0); 1843777Sroot } 1853778Sroot 1863778Sroot chkmap(addr,space) 1873778Sroot REG L_INT *addr; 1883753Sroot REG INT space; 1893753Sroot { 1903753Sroot REG MAPPTR amap; 1913753Sroot amap=((space&DSP?&datmap:&txtmap)); 1923778Sroot IF space&STAR ORF !within(*addr,amap->b1,amap->e1) 1933778Sroot THEN IF within(*addr,amap->b2,amap->e2) 1943778Sroot THEN *addr += (amap->f2)-(amap->b2); 1953778Sroot ELSE rwerr(space); return(0); 1963753Sroot FI 1973778Sroot ELSE *addr += (amap->f1)-(amap->b1); 1983753Sroot FI 1993753Sroot return(1); 2003753Sroot } 2013753Sroot 2023778Sroot within(addr,lbd,ubd) 2033778Sroot u_int addr, lbd, ubd; { return(addr>=lbd && addr<ubd); } 2043753Sroot 2053753Sroot longseek(f, a) 2063778Sroot off_t a; { return(lseek(f, a, 0) != -1); } 207