Annotation of 43BSDReno/bin/adb/common_source/access.c, revision 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.