Annotation of 43BSDReno/bin/adb/common_source/access.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)access.c   5.3 (Berkeley) 9/15/89";
                      3: #endif
                      4: 
                      5: /*
                      6:  * Adb: access data in file/process address space.
                      7:  */
                      8: 
                      9: #include "defs.h"
                     10: #include <sys/file.h>
                     11: #include <sys/ptrace.h>
                     12: 
                     13: off_t  lseek();
                     14: 
                     15: /*
                     16:  * Read or write from or to the given address, accessing or altering
                     17:  * only the given byte(s).  Return the number of bytes transferred.
                     18:  * Remote (debuggee) addresses are specified as a <space,address> pair.
                     19:  * Neither the remote nor the local address need be aligned.
                     20:  *
                     21:  * If there is a current process, ask the system to do this (via ptrace
                     22:  * [ick]).  If debugging the kernel, use vtophys() to map virtual to
                     23:  * physical locations (in a system-dependent manner).  Otherwise we
                     24:  * can just read or write the files being debugged directly.
                     25:  */
                     26: int
                     27: adbio(rw, space, rmtaddr, localaddr, cnt)
                     28:        enum rwmode rw;
                     29:        int space;
                     30:        addr_t rmtaddr;
                     31:        caddr_t localaddr;
                     32:        int cnt;
                     33: {
                     34:        register int ret;
                     35:        register struct map *mp;
                     36:        struct m1 *mm;
                     37: 
                     38:        static char *derr = "data address not found";
                     39:        static char *terr = "text address not found";
                     40: #define rwerr() errflag = space & SP_DATA ? derr : terr
                     41: #define        within(which) (rmtaddr >= which.b && rmtaddr < which.e)
                     42: 
                     43:        if (space == SP_NONE) {
                     44:                /* The no-space is all zero. */
                     45:                bzero(localaddr, cnt);
                     46:                return (cnt);
                     47:        }
                     48:        if (pid) {
                     49:                ret = io_ptrace(rw, space, rmtaddr, localaddr, cnt);
                     50:                if (ret != cnt)
                     51:                        rwerr();
                     52:                return (ret);
                     53:        }
                     54:        if (rw == RWMODE_WRITE && !wtflag)
                     55:                error("not in write mode");
                     56:        mp = space & SP_DATA ? &datmap : &txtmap;
                     57:        if ((space & SP_STAR) == 0 && within(mp->m1))
                     58:                mm = &mp->m1;
                     59:        else if (within(mp->m2))
                     60:                mm = &mp->m2;
                     61:        else {
                     62:                rwerr();
                     63:                return (0);
                     64:        }
                     65:        rmtaddr += mm->f - mm->b;
                     66:        if (kernel && space == SP_DATA) {
                     67:                char *err = NULL;
                     68: 
                     69:                rmtaddr = vtophys(rmtaddr, &err);
                     70:                if (err) {
                     71:                        errflag = err;
                     72:                        return (0);
                     73:                }
                     74:        }
                     75:        if (lseek(mp->ufd, (off_t)rmtaddr, 0) == -1) {
                     76:                rwerr();
                     77:                return (0);
                     78:        }
                     79:        if (rw == RWMODE_READ) {
                     80:                ret = read(mp->ufd, localaddr, cnt);
                     81:                /* gratuitously supply extra zeroes at end of file */
                     82:                if (ret > 0 && ret < cnt) {
                     83:                        bzero(localaddr + ret, cnt - ret);
                     84:                        ret = cnt;
                     85:                }
                     86:        } else
                     87:                ret = write(mp->ufd, localaddr, cnt);
                     88:        if (ret != cnt)
                     89:                rwerr();
                     90:        return (ret);
                     91: #undef rwerr
                     92: #undef within
                     93: }
                     94: 
                     95: /*
                     96:  * Read a single object of length `len' from the core file at the
                     97:  * given offset.  Return the length read.  (This routine allows vtophys
                     98:  * and kernel crash startup code to read ptes, etc.)
                     99:  */
                    100: int
                    101: readcore(off, addr, len)
                    102:        off_t off;
                    103:        caddr_t addr;
                    104:        int len;
                    105: {
                    106: 
                    107:        if (lseek(corefile.fd, off, L_SET) == -1)
                    108:                return (-1);
                    109:        return (read(corefile.fd, addr, len));
                    110: }
                    111: 
                    112: /*
                    113:  * THE FOLLOWING IS GROSS.  WE SHOULD REPLACE PTRACE WITH SPECIAL
                    114:  * FILES A LA /proc.
                    115:  *
                    116:  * Read or write using ptrace.  io_ptrace arranges that the
                    117:  * addresses passed to ptrace are an even multiple of sizeof(int),
                    118:  * and is able to read or write single bytes.
                    119:  *
                    120:  * Since ptrace is so horribly slow, and some commands do repeated
                    121:  * reading of units smaller than an `int', io_ptrace calls cptrace
                    122:  * (cached ptrace) to allow some cacheing.  cptrace also converts a
                    123:  * read/write op and a space into a ptrace op, and returns 0 on success
                    124:  * and hence takes a pointer to the value cell rather than the value.
                    125:  */
                    126: struct cache {
                    127:        short   rop, wop;               /* ptrace ops for read and write */
                    128:        int     valid;                  /* true iff cache entry valid */
                    129:        int     *addr;                  /* address of cached value */
                    130:        int     val;                    /* and the value */
                    131: };
                    132: static struct cache icache = { PT_READ_I, PT_WRITE_I };
                    133: static struct cache dcache = { PT_READ_D, PT_WRITE_D };
                    134: 
                    135: /*
                    136:  * Invalidate one or both caches.
                    137:  * This is the only function that accepts two spaces simultaneously.
                    138:  */
                    139: cacheinval(space)
                    140:        int space;
                    141: {
                    142: 
                    143:        if (space & SP_INSTR)
                    144:                icache.valid = 0;
                    145:        if (space & SP_DATA)
                    146:                dcache.valid = 0;
                    147: }
                    148: 
                    149: int    cachehit, cachemiss;            /* statistics */
                    150: 
                    151: static int
                    152: cptrace(rw, space, p, addr, val)
                    153:        enum rwmode rw;
                    154:        int space, p, *addr, *val;
                    155: {
                    156:        register struct cache *c = space & SP_DATA ? &dcache : &icache;
                    157:        int v;
                    158: 
                    159:        if (rw == RWMODE_READ) {
                    160:                if (c->valid && c->addr == addr) {
                    161:                        cachehit++;
                    162:                        *val = c->val;
                    163:                        return (0);
                    164:                }
                    165:                cachemiss++;
                    166:                errno = 0;
                    167:                if ((v = ptrace(c->rop, p, addr, 0)) == -1 && errno)
                    168:                        return (-1);
                    169:                *val = v;
                    170:        } else {
                    171:                c->valid = 0;           /* paranoia */
                    172:                errno = 0;
                    173:                if (ptrace(c->wop, p, addr, v = *val) == -1 && errno)
                    174:                        return (-1);
                    175:        }
                    176:        c->valid = 1;
                    177:        c->addr = addr;
                    178:        c->val = v;
                    179:        return (0);
                    180: }
                    181: 
                    182: int
                    183: io_ptrace(rw, space, rmtaddr, localaddr, cnt)
                    184:        register enum rwmode rw;
                    185:        register int space;
                    186:        addr_t rmtaddr;
                    187:        register caddr_t localaddr;
                    188:        register int cnt;
                    189: {
                    190:        register addr_t addr;
                    191:        register int nbytes, ret = 0, off;
                    192:        int tmp;
                    193: 
                    194:        /*
                    195:         * Start by aligning rmtaddr; set nbytes to the number of bytes of
                    196:         * useful data we shall obtain.
                    197:         */
                    198:        off = rmtaddr % sizeof(int);    /* addr_t is unsigned */
                    199:        addr = rmtaddr - off;
                    200:        nbytes = sizeof(int) - off;
                    201:        while (cnt != 0) {
                    202:                if (cnt < nbytes)
                    203:                        nbytes = cnt;
                    204:                if (rw == RWMODE_READ) {
                    205:                        if (cptrace(rw, space, pid, (int *)addr, &tmp))
                    206:                                return (ret);
                    207:                        bcopy((caddr_t)&tmp + off, localaddr, nbytes);
                    208:                } else {
                    209:                        if (nbytes < sizeof(int) &&
                    210:                            cptrace(RWMODE_READ, space, pid, (int *)addr, &tmp))
                    211:                                return (ret);
                    212:                        bcopy(localaddr, (caddr_t)&tmp + off, nbytes);
                    213:                        if (cptrace(rw, space, pid, (int *)addr, &tmp))
                    214:                                return (ret);
                    215:                }
                    216:                addr += sizeof(int);
                    217:                localaddr += nbytes;
                    218:                ret += nbytes;
                    219:                cnt -= nbytes;
                    220:                /*
                    221:                 * For the rest of the loop, the offset is 0 and we can
                    222:                 * use all the bytes obtained.
                    223:                 */
                    224:                off = 0;
                    225:                nbytes = sizeof(int);
                    226:        }
                    227:        return (ret);
                    228: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.