Annotation of coherent/b/bin/db/i386/i386db1.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * db/i386/i386db1.c
        !             3:  * A debugger.
        !             4:  * i386-specific code.
        !             5:  * This file contains all the routines called by the machine-independent code
        !             6:  * except disassemble(), which is in i386db2.c.
        !             7:  */
        !             8: 
        !             9: #include <sys/ptrace.h>
        !            10: #include <sys/sysi86.h>
        !            11: #include <errno.h>
        !            12: #include "i386db.h"
        !            13: 
        !            14: /*
        !            15:  * Get the return pc and frame pointer to set a return breakpoint.
        !            16:  * Like traceback(), this knows some gory details about the calling sequence;
        !            17:  * see the comment there for elucidation.
        !            18:  * At a function entry point,
        !            19:  * %ebp is the caller's stack frame and *%esp contains the ra.
        !            20:  * Inside a function (after the frame save),
        !            21:  * *%ebp is the caller's stack frame and the ra is at a fixed offset from %ebp.
        !            22:  */
        !            23: int
        !            24: bpt_setr(cmd) char *cmd;
        !            25: {
        !            26:        register ADDR_T sp, myfp;
        !            27:        ADDR_T ra, fp;
        !            28:        unsigned char b;
        !            29: 
        !            30:        add = get_pc();
        !            31:        fp = get_fp();
        !            32:        sp = get_sp();
        !            33:        dbprintf(("bpt_setr(%s) ip=%X bp=%X sp=%X\n", cmd, add, fp, sp));
        !            34: 
        !            35:        /* Fetch the next opcode. */
        !            36:        if (getb(ISEG, &b, sizeof(b)) == 0)
        !            37:                return 0;                       /* opcode fetch failed */
        !            38: 
        !            39:        /* Find the return address and the caller's stack frame. */
        !            40:        if ((IS_LOUT && b == PUSHESI)
        !            41:         || (!IS_LOUT && (b==ENTER || b==PUSHEBP)))
        !            42:                add = sp;                       /* sp points at ra, fp ok */
        !            43:        else {
        !            44:                add = myfp = fp;                /* fetch caller's fp */
        !            45:                if (get_sized(DSEG, &fp) == 0)
        !            46:                        return 0;
        !            47:                add = myfp + (IS_LOUT) ? 6 : 4; /* ra at known offset off fp */
        !            48:        }
        !            49: 
        !            50:        /* Fetch the return address. */
        !            51:        if (get_sized(DSEG, &ra) == 0)
        !            52:                return 0;                       /* ra fetch failed */
        !            53:        dbprintf(("placing BRET breakpoint: ra=%X fp=%X cmd=%s\n", ra, fp, cmd));
        !            54:        return bpt_set(BRET, ra, fp, cmd);      /* set the return bpt */
        !            55: }
        !            56: 
        !            57: /*
        !            58:  * See if the given instruction is a breakpoint.
        !            59:  */
        !            60: int
        !            61: bpt_test(pc) ADDR_T pc;
        !            62: {
        !            63:        unsigned char w;
        !            64: 
        !            65:        dbprintf(("bpt_test(%x)\n", pc));
        !            66:        add = pc;
        !            67:        return getb(ISEG, &w, sizeof(w))!=0 && w==TRAP;
        !            68: }
        !            69: 
        !            70: /*
        !            71:  * Display registers.
        !            72:  * The 'flag' arg is R_GEN to get the general registers
        !            73:  * or R_ALL to get all the registers (including NDP).
        !            74:  */
        !            75: void
        !            76: display_reg(flag) int flag;
        !            77: {
        !            78:        register REGNAME *rp;
        !            79:        register ADDR_T val;
        !            80:        register char *name;
        !            81:        register int n;
        !            82: 
        !            83:        if (testint())
        !            84:                return;
        !            85: 
        !            86:        if (get_regs(flag) == 0)
        !            87:                return;
        !            88: 
        !            89:        for (n = 0, rp = reg_name; rp < &reg_name[NGREGS]; rp++) {
        !            90: 
        !            91:                if (testint())
        !            92:                        return;
        !            93: 
        !            94:                /* Print register name. */
        !            95:                name = rp->r_name;
        !            96:                if (IS_LOUT) {
        !            97:                        if (*name == 'e' && strlen(name) == 3)
        !            98:                                ++name;
        !            99:                        printx("%%%-2s=", name);
        !           100:                } else
        !           101:                        printx("%%%-3s=", name);
        !           102: 
        !           103:                /* Print contents. */
        !           104:                val = *(ADDR_T *)(((char *)&ureg) + rp->r_offset);
        !           105:                switch(rp->r_flag) {
        !           106:                case RF_1632:
        !           107:                        if (!IS_LOUT) {
        !           108:                                printx(ADDR_FMT, val);
        !           109:                                break;
        !           110:                        }
        !           111:                        /* else fall through... */
        !           112:                case RF_16:
        !           113:                        printx(ADDR16_FMT, val&0xFFFF);
        !           114:                        break;
        !           115:                default:
        !           116:                        printr("<flag=%x>", rp->r_flag);
        !           117:                }
        !           118:                putchar(((++n % 4) == 0 || n == NGREGS) ? '\n' : '\t');
        !           119:        }
        !           120: 
        !           121: #ifndef        NOFP
        !           122:        /*
        !           123:         * Dump the NDP state for :rN.
        !           124:         * Thanks to hal for this code,
        !           125:         * more detail than the average user needs...
        !           126:         */
        !           127:        if (flag == R_ALL) {
        !           128:                register struct _fpstate *fstp;
        !           129:                register int i;
        !           130: #if    0
        !           131:                register int j;
        !           132: #endif
        !           133:                int tagbits, tos;
        !           134:                unsigned char opfirst, opsecond;
        !           135:                unsigned int fcs, exp, sigzero;
        !           136:                double d;
        !           137: 
        !           138:                fstp = &ureg.ur_fpstate;
        !           139:                fcs = fstp->cssel;
        !           140:                tos = (fstp->sw >> 11) & 7;
        !           141: #if    0
        !           142:                printx("\nfstp=%08X\ttos=%d  ", fstp, tos);
        !           143: #endif
        !           144:                opfirst = 0xD8 | ((fcs >> 24) & 7);
        !           145:                opsecond = fcs >> 16;
        !           146: #if    0
        !           147:                printx("cw=%04X\tsw=%04X\ttag=%04X\n",
        !           148:                  fstp->cw&0xFFFF, fstp->sw&0xFFFF, fstp->tag&0xFFFF);
        !           149:                printx("op=%02X\t%02X\tfcs=%04X\tfip=%08X\tfos=%04X\tfoo=%08X\n",
        !           150:                  opfirst, opsecond,
        !           151:                  fcs&0xFFFF, fstp->ipoff, fstp->datasel&0xFFFF, fstp->dataoff);
        !           152: #endif
        !           153:                if (testint())
        !           154:                        return;
        !           155:                for (i = 0; i < 8; i++) {
        !           156:                        tagbits = (fstp->tag >> (((tos + i) & 7) * 2)) & 3;
        !           157:                        printx("%%st%d=", i);
        !           158: #if    0
        !           159:                        printx("(%d) at %08X ", tagbits, fstp->_st + i);
        !           160: #endif
        !           161:                        switch(tagbits) {
        !           162:                        case 0:                 /* Normal */
        !           163:                                if (get_fp_reg(&fstp->_st[i], &d) == 0)
        !           164:                                        printx("(none)");       /* no NDP */
        !           165:                                else
        !           166:                                        printx("%g", d);
        !           167: #if    0
        !           168:                                for (j = 0; j < 4; j++)
        !           169:                                        printx("%04X ", fstp->_st[i].significand[j]);
        !           170:                                printx(":%04X\n", fstp->_st[i].exponent);
        !           171: #endif
        !           172:                                break;
        !           173:                        case 1:                 /* Zero */
        !           174:                                printx("0.0");
        !           175:                                break;
        !           176:                        case 2:                 /* NaN, Infinity, Denormal */
        !           177:                                exp = fstp->_st[i].exponent;
        !           178:                                sigzero = (fstp->_st[i].significand[0] == 0
        !           179:                                        && fstp->_st[i].significand[1] == 0
        !           180:                                        && fstp->_st[i].significand[2] == 0
        !           181:                                        && fstp->_st[i].significand[3] == 0x8000);
        !           182:                                putx((exp & 0x8000) ? '-' : '+');
        !           183:                                exp &= 0x7FFF;
        !           184:                                if (exp == 0x7FFF)
        !           185:                                        printx(sigzero ? "Infinity" : "NaN");
        !           186:                                else if (exp == 0 && !sigzero)
        !           187:                                        printx("Denormal");
        !           188:                                else                    /* shouldn't happen */
        !           189:                                        printx("Special: %08X %08X %08X %08X : %08X\n",
        !           190:                                          fstp->_st[i].significand[0],
        !           191:                                          fstp->_st[i].significand[1],
        !           192:                                          fstp->_st[i].significand[2],
        !           193:                                          fstp->_st[i].significand[3],
        !           194:                                          fstp->_st[i].exponent);
        !           195:                                break;
        !           196:                        case 3:                         /* Empty */
        !           197:                                printx("<Empty>");
        !           198:                                break;
        !           199:                        }
        !           200:                        if (i==3 || i==7)
        !           201:                                putx('\n');
        !           202:                        else
        !           203:                                putx('\t');
        !           204:                }
        !           205:        }
        !           206: #endif
        !           207: }
        !           208: 
        !           209: /*
        !           210:  * Find the segment in which an address resides.
        !           211:  * For COFF, the address implies a unique segment (or SEG_NONE).
        !           212:  * For l.out, the same address can represent an item in either DSEG or ISEG
        !           213:  * (i.e. the address->segment mapping is one->many), so this is does not
        !           214:  * necessarily give the right answer; it is even less right since the
        !           215:  * segmentation maps for the child process are at present set up incorrectly.
        !           216:  * Return SEG_NONE if not found.
        !           217:  */
        !           218: int
        !           219: find_seg(addr) register ADDR_T addr;
        !           220: {
        !           221:        register int s;
        !           222: 
        !           223:        if (IS_COFF)
        !           224:                return (addr < (ADDR_T)0x00400000) ? ISEG
        !           225:                     : (addr < (ADDR_T)0x80000000) ? DSEG
        !           226:                     : SEG_NONE;
        !           227:        for (s = 0; s < NSEGS; s++)
        !           228:                if (map_addr(s, addr) != (MAP *)NULL)
        !           229:                        return s;
        !           230:        return SEG_NONE;
        !           231: }
        !           232: 
        !           233: /*
        !           234:  * Given a size character 't1' and a type 't2',
        !           235:  * return the appropriate format string.
        !           236:  */
        !           237: char *
        !           238: get_format(t1, t2) register int t1, t2;
        !           239: {
        !           240:        register char *cp, *sp;
        !           241: 
        !           242:        if (t1 == 'f' || t1 == 'F')
        !           243:                return "%g";
        !           244:        if (t1 == 'h')
        !           245:                t1 = 'w';
        !           246:        if ((cp = strchr(sp = "bwlv", t1)) == NULL)
        !           247:                return "?";
        !           248:        t1 = cp - sp;
        !           249:        if ((cp = strchr(sp = "duox", t2)) == NULL)
        !           250:                return "?";
        !           251:        t2 = cp - sp;
        !           252:        return formtab[t1][t2];
        !           253: }
        !           254: 
        !           255: /*
        !           256:  * Return the frame pointer.
        !           257:  * Mask to 16-bit value for l.out.
        !           258:  */
        !           259: ADDR_T
        !           260: get_fp()
        !           261: {
        !           262:        return (IS_LOUT) ? ureg.ur_bp & 0xFFFF : ureg.ur_bp;
        !           263: }
        !           264: 
        !           265: /*
        !           266:  * Store the value from an NDP register into a double.
        !           267:  * If the machine has no NDP, fail and return 0.
        !           268:  * If the machine has an NDP (or NDP emulation),
        !           269:  * use the coprocessor instructions in _get_fp_reg()
        !           270:  * to convert the 80-bit arg to the 64-bit result
        !           271:  * and return 1.
        !           272:  */
        !           273: int
        !           274: get_fp_reg(fpregp, dp) struct _fpreg *fpregp; double *dp;
        !           275: {
        !           276:        if (!NDP_flag)
        !           277:                return 0;                       /* sorry */
        !           278:        *dp = _get_fp_reg(fpregp);              /* store converted result */
        !           279:        return 1;
        !           280: }
        !           281: 
        !           282: /*
        !           283:  * Return the program counter.
        !           284:  * Mask to 16-bit value for l.out.
        !           285:  */
        !           286: ADDR_T
        !           287: get_pc()
        !           288: {
        !           289:        return (IS_LOUT) ? ureg.ur_ip & 0xFFFF : ureg.ur_ip;
        !           290: }
        !           291: 
        !           292: /*
        !           293:  * Read registers from the child process.
        !           294:  * The flag is:
        !           295:  *     R_SOME  read %eip, %ebp, %esp and signal number only
        !           296:  *     R_GEN   read the general registers
        !           297:  *     R_ALL   read all the registers, general and NDP
        !           298:  * This is for efficiency; the values of the registers other than ip/bp/sp
        !           299:  * are needed only for :r and ?, and because ptrace() only reads an int
        !           300:  * at a time it requires many system calls to read the complete register set.
        !           301:  * Return 1 on success, 0 on failure.
        !           302:  */
        !           303: int
        !           304: get_regs(flag) int flag;
        !           305: {
        !           306:        static char *nope = "Cannot read registers";
        !           307: 
        !           308:        dbprintf(("get_regs(%d) reg_flag=%d\n", flag, reg_flag));
        !           309: 
        !           310:        if (reg_flag != R_INVALID && reg_flag >= flag)
        !           311:                return 1;                       /* already read */
        !           312:        reg_flag = R_INVALID;                   /* in case read fails */
        !           313:        if (flag == R_SOME) {
        !           314:                add = PTRACE_EIP;
        !           315:                if (getb(USEG, (char *)&ureg.ur_ip, PTSIZE) == 0)
        !           316:                        return printr(nope);
        !           317:                add = PTRACE_EBP;
        !           318:                if (getb(USEG, (char *)&ureg.ur_bp, PTSIZE) == 0)
        !           319:                        return printr(nope);
        !           320:                add = PTRACE_UESP;
        !           321:                if (getb(USEG, (char *)&ureg.ur_sp, PTSIZE) == 0)
        !           322:                        return printr(nope);
        !           323:                add = PTRACE_SIG;
        !           324:                if (getb(USEG, (char *)&ureg.ur_sig, PTSIZE) == 0)
        !           325:                        return printr("Cannot read signal in traced process");
        !           326:                dbprintf(("get_regs(R_SOME): ip=%x bp=%x sp=%x sig=%d\n", ureg.ur_ip, ureg.ur_bp, ureg.ur_sp, ureg.ur_sig));
        !           327:        } else {                                /* R_GEN or R_ALL */
        !           328:                add = UREG_BASE;                /* pseudo-offset of ureg */
        !           329:                if (getb(USEG, (char *)&ureg, 
        !           330:                      (flag==R_GEN) ? UREG_GEN_SIZE : UREG_ALL_SIZE) == 0)
        !           331:                        return printr(nope);
        !           332:        }
        !           333:        reg_flag = flag;
        !           334:        return 1;
        !           335: }
        !           336: 
        !           337: /*
        !           338:  * Return the child program signal number.
        !           339:  */
        !           340: int
        !           341: get_sig()
        !           342: {
        !           343:        return ureg.ur_sig;
        !           344: }
        !           345: 
        !           346: /*
        !           347:  * Get a word or dword from segment s and store it in *lp.
        !           348:  */
        !           349: int
        !           350: get_sized(s, lp) int s; ADDR_T *lp;
        !           351: {
        !           352:        unsigned short i;
        !           353: 
        !           354:        if (IS_LOUT) {
        !           355:                if (getb(s, (char *)&i, sizeof(i)) == 0) /* get 2 bytes for l.out */
        !           356:                        return 0;
        !           357:                *lp = (ADDR_T)i;
        !           358:                return 1;
        !           359:        }
        !           360:        return getb(s, (char *)lp, sizeof(*lp));        /* get 4 bytes for COFF */
        !           361: 
        !           362: }
        !           363: 
        !           364: /*
        !           365:  * Return the stack pointer.
        !           366:  * Mask to 16-bit value for l.out.
        !           367:  */
        !           368: ADDR_T
        !           369: get_sp()
        !           370: {
        !           371:        return (IS_LOUT) ? ureg.ur_sp & 0xFFFF : ureg.ur_sp;
        !           372: }
        !           373: 
        !           374: /*
        !           375:  * Perform i386-specific initialization.
        !           376:  * This checks whether NDP (or emulation) is present;
        !           377:  * get_fp_reg requires either NDP or emulation
        !           378:  * to convert an 80-bit NDP double to 64-bit format.
        !           379:  */
        !           380: void
        !           381: init_mch()
        !           382: {
        !           383:        int NDPstate;
        !           384: 
        !           385:        if (sysi86(SI86FPHW, &NDPstate) == -1)
        !           386:                panic("sysi86() call failed");
        !           387:        NDP_flag = (NDPstate != FP_NO);
        !           388: }
        !           389: 
        !           390: /*
        !           391:  * Return true if instruction at %eip is a call.
        !           392:  */
        !           393: int
        !           394: is_call()
        !           395: {
        !           396:        unsigned char   w[4];
        !           397:        int i;
        !           398: 
        !           399:        add = get_pc();
        !           400:        dbprintf(("is_call(): eip=%x\n", add));
        !           401:        if (getb(ISEG, (char *)&i, sizeof(i)) == 0)
        !           402:                return;
        !           403:        w[0] = i & 0xff;
        !           404:        w[1] = (i>>8) & 0xff;
        !           405:        return (w[0] == CALL)                           /* Direct call */
        !           406:            || (w[0]==ICALL1 && (w[1]&IC2MSK)==ICALL2); /* Indirect call */
        !           407: }
        !           408: 
        !           409: /*
        !           410:  * If the given name matches a register,
        !           411:  * set up 'sp' with the address of a register in the user area.
        !           412:  */
        !           413: int
        !           414: is_reg(sp) SYM *sp;
        !           415: {
        !           416:        register char *cp, *np;
        !           417:        register REGNAME *rp;
        !           418: 
        !           419:        for (cp = sp->s_id, rp = reg_name; rp < &reg_name[NREGS]; rp++) {
        !           420:                np = rp->r_name;
        !           421:                if (strcmp(cp, np) == 0) {
        !           422:                        sp->s_addr = rp->r_offset;
        !           423:                        sp->s_segn = USEG;
        !           424:                        return 1;
        !           425:                } else if (*np == 'e' && strcmp(cp, np+1) == 0) {
        !           426:                        /* Recognize e.g. "si" as word equivalent of "esi". */
        !           427:                        sp->s_addr = rp->r_offset;
        !           428:                        sp->s_segn = USEG;
        !           429:                        return 1;
        !           430:                }
        !           431:        }
        !           432:        return 0;
        !           433: }
        !           434: 
        !           435: /*
        !           436:  * Watch out for system calls if single stepping.
        !           437:  * If at system call, save the address (sys_add) and the contents (sys_in)
        !           438:  * of the replaced instruction and set *flagp to 2.
        !           439:  * Return 0 on error.
        !           440:  */
        !           441: int
        !           442: is_syscall(flagp) int *flagp;
        !           443: {
        !           444:        unsigned char w;
        !           445: 
        !           446:        if (*flagp == 0)
        !           447:                return 1;                       /* not single stepping */
        !           448:        add = get_pc();
        !           449:        dbprintf(("is_syscall(): pc=%X ", add));
        !           450:        if (getb(ISEG, (char *)&w, sizeof(w)) == 0)
        !           451:                return 1;                       /* should this be 0? */
        !           452: 
        !           453:        if (IS_LOUT) {                  /* l.out */
        !           454:                if (w != INT)           /* Interrupt (system call) */
        !           455:                        return 1;       /* not at a system call */
        !           456:                add = get_pc() + 2;
        !           457:        } else {                        /* COFF */
        !           458:                if (w != LCALL)         /* lcall (possibly system call) */
        !           459:                        return 1;       /* not at a system call */
        !           460:                add = get_pc() + 7;
        !           461:        }
        !           462:        sys_add = add;
        !           463:        if (getb(ISEG, (char *)sys_in, sizeof(sys_in)) == 0)
        !           464:                return printr("Cannot get breakpoint");
        !           465:        add = sys_add;
        !           466:        dbprintf(("is_syscall: set system call bpt at %X replacing %X\n", add, sys_in[0]));
        !           467:        if (putb(ISEG, (char *)bin, sizeof(bin)) == 0)
        !           468:                return printr("Cannot set breakpoint");
        !           469:        *flagp = 2;                     /* indicate system call seen */
        !           470:        return 1;
        !           471: }
        !           472: 
        !           473: /*
        !           474:  * Print an address as a constant.
        !           475:  */
        !           476: void
        !           477: print_const(buf, addr) register char *buf; ADDR_T addr;
        !           478: {
        !           479:        sprintf(buf, (addr < (ADDR_T)0x10) ? "%ld" : "0x%lX", (long)addr);
        !           480: }
        !           481: 
        !           482: /*
        !           483:  * Restore after stepping past a system call.
        !           484:  * This basically undoes what is_syscall() does.
        !           485:  * Note that the system call may not return where you would expect,
        !           486:  * e.g. for sigreturn!
        !           487:  */
        !           488: int
        !           489: rest_syscall(flagp) int *flagp;
        !           490: {
        !           491:        ADDR_T pc;
        !           492: 
        !           493:        pc = get_pc() - sizeof(BIN);
        !           494:        if (pc == sys_add)
        !           495:                set_pc(pc);             /* back up %eip */
        !           496:        dbprintf(("rest_syscall(): step_flag=%d sys_add=%X pc=%X\n", *flagp, sys_add, pc));
        !           497:        add = sys_add;                  /* restore instruction */
        !           498:        if (putb(ISEG, (char *)sys_in, sizeof(sys_in)) == 0)
        !           499:                return printr("Cannot restore sys_in");
        !           500:        *flagp = 1;                     /* restore step_mode==1 */
        !           501:        return 1;
        !           502: }
        !           503: 
        !           504: /*
        !           505:  * Set up segmentation for COFF.
        !           506:  */
        !           507: void
        !           508: setcoffseg()
        !           509: {
        !           510:        register SCNHDR *shp, *oshp;
        !           511:        ADDR_T fbase, tbase, tsize, dbase, dsize, bbase, bsize;
        !           512:        off_t tsp, dsp, bsp;
        !           513:        int i;
        !           514: 
        !           515:        fbase = sizeof(FILEHDR) + coff_hdr.f_opthdr;
        !           516:        tbase = tsize = dbase = dsize = bbase = bsize = MIN_ADDR;
        !           517:        tsp = dsp = bsp = (off_t)0;
        !           518:        oshp = shp = (SCNHDR *)nalloc(coff_hdr.f_nscns*sizeof(SCNHDR), "COFF section headers");
        !           519:        if (fseek(lfp, (long)fbase, SEEK_SET) == -1)
        !           520:                panic("COFF header seek failed");
        !           521:        for (i = 0; i < coff_hdr.f_nscns; shp++, i++) {
        !           522:                /* Read a COFF section header. */
        !           523:                if (fread(shp, sizeof(SCNHDR), 1, lfp) != 1)
        !           524:                        panic("Cannot read COFF section header");
        !           525: 
        !           526:                /* Set base and size info according to flags. */
        !           527:                switch((int)shp->s_flags) {
        !           528:                case STYP_TEXT:
        !           529:                        tbase = shp->s_vaddr;
        !           530:                        tsize = shp->s_size;
        !           531:                        tsp = shp->s_scnptr; 
        !           532:                        break;
        !           533:                case STYP_DATA:
        !           534:                        dbase = shp->s_vaddr;
        !           535:                        dsize = shp->s_size;
        !           536:                        dsp = shp->s_scnptr; 
        !           537:                        break;
        !           538:                case STYP_BSS:
        !           539:                        bbase = shp->s_vaddr;
        !           540:                        bsize = shp->s_size;
        !           541:                        bsp = shp->s_scnptr; 
        !           542:                        break;
        !           543:                default:
        !           544:                        continue;               /* ignore other section types */
        !           545:                }
        !           546:        }
        !           547: 
        !           548:        endpure = (MAP *)NULL;                  /* no pure data */
        !           549: #if    0
        !           550:        dbase = rup(dbase);                     /* round up? */
        !           551: #endif
        !           552: #if    1
        !           553:        /* Assume separate. */
        !           554:        map_set(ISEG, tbase, tsize, tsp, MAP_PROG);
        !           555:        map_set(DSEG, dbase, dsize, dsp, MAP_PROG);
        !           556:        map_set(DSEG, bbase, bsize+4L, bsp, MAP_PROG);
        !           557: #else
        !           558:        /* Assume NOT separate. */
        !           559:        map_set(DSEG, tbase, tsize, tsp, MAP_PROG);
        !           560:        map_set(DSEG, dbase, dsize, dsp, MAP_PROG);
        !           561:        map_set(DSEG, bbase, bsize+4L, bsp, MAP_PROG);
        !           562:        ISPACE = DSPACE;
        !           563: #endif
        !           564:        nfree(oshp);
        !           565: }
        !           566: 
        !           567: /*
        !           568:  * Set up segmentation for a system dump.
        !           569:  */
        !           570: void
        !           571: setdump(name) char *name;
        !           572: {
        !           573:        setkmem(name);
        !           574: }
        !           575: 
        !           576: /*
        !           577:  * Set up segmentation for kernel memory.
        !           578:  * FIX_ME This is much bogosity.  "etext" is no more, for one thing...
        !           579:  */
        !           580: void
        !           581: setkmem(name) char *name;
        !           582: {
        !           583:        register off_t l;
        !           584:        unsigned int n;
        !           585:        static SYM *etextp;
        !           586: 
        !           587:        cfn = name;
        !           588:        cfp = openfile(name, rflag);
        !           589:        map_set(USEG, MIN_ADDR, MAX_ADDR, (off_t)0, MAP_CORE);
        !           590:        add = 2;
        !           591:        if (getb(USEG, (char *)&n, sizeof(n)) == 0)
        !           592:                panic("Bad memory file");
        !           593:        l = (off_t)n << 4;
        !           594:        map_set(ISEG, MIN_ADDR, MAX_ADDR, (off_t)l, MAP_CORE);
        !           595:        if (etextp == (SYM *)NULL) {
        !           596:                /* Find the address of "etext". */
        !           597:                etextp = (SYM *)nalloc(sizeof(SYM) + 6, "symbol \"etext\"");
        !           598:                strcpy(etextp->s_id, "etext");
        !           599:                if (!is_symbol(etextp))
        !           600:                        etextp->s_addr = (off_t)1;
        !           601:                dbprintf(("main=%lX\n", etextp->s_addr));
        !           602:        }
        !           603:        if (!is_symbol(etextp))
        !           604:                DSPACE = ISPACE;
        !           605:        else {
        !           606:                n = rup(etextp->s_addr);
        !           607:                map_set(DSEG, MIN_ADDR, MAX_ADDR, (off_t)l+n, MAP_CORE);
        !           608:        }
        !           609: }
        !           610: 
        !           611: /*
        !           612:  * Set up segmentation for an l.out.
        !           613:  */
        !           614: void
        !           615: setloutseg()
        !           616: {
        !           617:        register off_t fbase;
        !           618:        register ADDR_T si, pi, bi, sd, pd, rs;
        !           619: 
        !           620:        fbase = (off_t)sizeof(ldh);
        !           621:        si = ldh.l_ssize[L_SHRI];
        !           622:        pi = ldh.l_ssize[L_PRVI];
        !           623:        bi = ldh.l_ssize[L_BSSI];
        !           624:        sd = ldh.l_ssize[L_SHRD];
        !           625:        pd = ldh.l_ssize[L_PRVD];
        !           626:        dbprintf(("l.out sizes: si=%lX pi=%lX bi=%lX sd=%lX pd=%lX\n", si, pi, bi, sd, pd));
        !           627:        endpure = (MAP *)NULL;                  /* no pure data */
        !           628:        switch (ldh.l_flag & (LF_SEP|LF_SHR)) {
        !           629: 
        !           630:        case 0:                                 /* not separate, not shared */
        !           631:                map_set(DSEG, MIN_ADDR, si+pi, fbase, MAP_PROG);
        !           632:                map_set(DSEG, si+pi+bi, sd+pd, fbase+(off_t)(si+pi), MAP_PROG);
        !           633:                ISPACE = DSPACE;
        !           634:                break;
        !           635: 
        !           636:        case LF_SHR:                            /* not separate, shared */
        !           637:                rs = rup(si+sd);
        !           638:                map_set(DSEG, MIN_ADDR, si, fbase, MAP_PROG);
        !           639:                map_set(DSEG, si, sd, fbase+(off_t)(si+pi), MAP_PROG);
        !           640:                map_set(DSEG, rs, pi, fbase+(off_t)si, MAP_PROG);
        !           641:                map_set(DSEG, rs+pi, pd, fbase+(off_t)(si+pi+sd), MAP_PROG);
        !           642:                ISPACE = DSPACE;
        !           643:                break;
        !           644: 
        !           645:        case LF_SEP:                            /* separate, not shared */
        !           646:                map_set(ISEG, MIN_ADDR, si+pi, fbase, MAP_PROG);
        !           647:                map_set(DSEG, MIN_ADDR, sd+pd, fbase+(off_t)(si+pi), MAP_PROG);
        !           648:                break;
        !           649: 
        !           650:        case LF_SEP|LF_SHR:                     /* separate, shared */
        !           651:                rs  = rup(sd);
        !           652:                map_set(ISEG, MIN_ADDR, si+pi, fbase, MAP_PROG);
        !           653:                map_set(DSEG, MIN_ADDR, sd, fbase+(off_t)(si+pi), MAP_PROG);
        !           654:                map_set(DSEG, rs, pd, fbase+(off_t)(si+pi+sd), MAP_PROG);
        !           655:                break;
        !           656:        }
        !           657: }
        !           658: 
        !           659: /*
        !           660:  * Set the program counter.
        !           661:  */
        !           662: void
        !           663: set_pc(ip) ADDR_T ip;
        !           664: {
        !           665:        dbprintf(("set_pc(%lX)\n", ip));
        !           666:        ureg.ur_ip = ip;
        !           667:        add = PTRACE_EIP;
        !           668:        putb(USEG, (char *)&ureg.ur_ip, sizeof(ureg.ur_ip));
        !           669: }
        !           670: 
        !           671: /*
        !           672:  * Set a BSIN breakpoint at the return address given by %esp.
        !           673:  */
        !           674: void
        !           675: set_ra_bpt()
        !           676: {
        !           677:        ADDR_T ra;
        !           678: 
        !           679:        add = get_sp();
        !           680:        dbprintf(("set_ra_bpt(): sp=%lX ", add));
        !           681:        if (get_sized(DSEG, &ra) == 0)
        !           682:                return;
        !           683:        bpt_set(BSIN, ra, get_fp(), NULL);
        !           684:        dbprintf(("ra=%lX bp=%lX\n", ra, get_fp()));
        !           685: }
        !           686: 
        !           687: /*
        !           688:  * Set the signal number.
        !           689:  * This gets executed when a core file is read;
        !           690:  * dunno why the signal number in the register save is different.
        !           691:  */
        !           692: void
        !           693: set_sig(sig) int sig;
        !           694: {
        !           695:        dbprintf(("set_sig(%X)\n", sig));
        !           696:        ureg.ur_sig = sig;
        !           697:        add = PTRACE_SIG;
        !           698:        putb(USEG, (char *)&ureg.ur_sig, sizeof(ureg.ur_sig));
        !           699: }
        !           700: 
        !           701: /*
        !           702:  * Stack traceback.
        !           703:  * This code knows some gory details about the C calling sequence
        !           704:  * for code compiled by either the i8086 compiler or the i386 compiler.
        !           705:  * It must be changed if the calling sequence changes!
        !           706:  *
        !           707:  * i8086 stack frame:
        !           708:  *     bp+6+(2*n)->    [argn]
        !           709:  *                     [...]
        !           710:  *     bp+8->          [arg1]
        !           711:  *     bp+6->          ra
        !           712:  *     bp+4->          saved si
        !           713:  *     bp+2->          saved di
        !           714:  *     bp->            saved bp
        !           715:  *     bp-n            [locals]
        !           716:  * Here [] indicates optional; note that the registers are always saved.
        !           717:  * Arguments are popped after the call with "add %sp, $n".
        !           718:  *
        !           719:  * i386 stack frame:
        !           720:  *     bp+4+(4*n)->    [argn]
        !           721:  *                     [...]
        !           722:  *     bp+8->          [arg1]
        !           723:  *     bp+4->          ra
        !           724:  *     bp->            saved bp
        !           725:  *     bp-x->          [locals]
        !           726:  *     bp-x-4->        [saved esi]
        !           727:  *     bp-x-8->        [saved edi]
        !           728:  *     bp-x-12->       [saved ebx]
        !           729:  * Here the registers are saved only if required.
        !           730:  * The function entry sequence may begin with either "enter $n, $0" (if locals)
        !           731:  * or with "push %ebp; movl %ebp, %esp" (if no locals).
        !           732:  * Arguments are popped after the call with "pop %ecx" or "add %esp, $n".
        !           733:  */
        !           734: void
        !           735: traceback(levels) int levels;
        !           736: {
        !           737:        ADDR_T bp, pc, rpc;             /* ebp, eip, return pc  */
        !           738:        register int argc;              /* arg count            */
        !           739:        int at_start;                   /* at start, before ebp save */
        !           740:        int qflag;                      /* quit flag            */
        !           741:        static SYM *mainp;              /* "main"               */
        !           742:        int size;                       /* bytes per stack item */
        !           743:        SYM *sp;
        !           744:        int i, n;
        !           745:        char *fmt;
        !           746:        unsigned char b[3], e[1];       /* opcode buffers */
        !           747: 
        !           748:        fmt = (IS_LOUT) ? ADDR16_FMT : ADDR_FMT;
        !           749:        if (mainp == (SYM *)NULL) {
        !           750:                /* Find the address of "main". */
        !           751:                mainp = (SYM *)nalloc(sizeof(SYM) + 5, "symbol \"main\"");
        !           752:                strcpy(mainp->s_id, "main");
        !           753:                if (!is_symbol(mainp))
        !           754:                        mainp->s_addr = (off_t)1;
        !           755:                dbprintf(("main=%lX\n", mainp->s_addr));
        !           756:        }
        !           757: 
        !           758:        /* Set operand size, get registers ip and bp. */
        !           759:        size = (IS_LOUT) ? 2 : 4;       /* word for l.out, dword for COFF */
        !           760:        add = pc = get_pc();
        !           761:        dbprintf(("ip=%lX\n", pc));
        !           762:        if (getb(ISEG, b, 1) == 0) {    /* fetch opcode at ip to b[] */
        !           763:                printe("Illegal ip");
        !           764:                return;
        !           765:        }
        !           766:        bp = get_fp();
        !           767:        dbprintf(("bp=%lX\n", bp));
        !           768: 
        !           769:        /* Fetch the first byte of the current routine. */
        !           770:        if ((sp = findsym(1, pc)) != (SYM *)NULL) {
        !           771:                dbprintf(("findsym found %s, addr=%lX\n", sp->s_id, sp->s_addr));
        !           772:                add = sp->s_addr;
        !           773:                getb(ISEG, (char *)e, 1);
        !           774:                dbprintf(("opcode fetched from %s: %x\n", sp->s_id, e[0]));
        !           775:        } else
        !           776:                e[0] = (IS_LOUT) ? PUSHESI : ENTER;     /* take a guess... */
        !           777: 
        !           778:        /*
        !           779:         * If we are right at the start of the routine,
        !           780:         * set at_start and kludge bp so that we can see this
        !           781:         * call in the traceback.
        !           782:         * sp currently must point to ra,
        !           783:         * so bp will be at sp-6 for l.out or sp-4 for COFF.
        !           784:         * Otherwise, use the current bp as is.
        !           785:         */
        !           786:        if ((IS_LOUT && (b[0]==PUSHESI || e[0]!=PUSHESI))
        !           787:         || (!IS_LOUT && (b[0]==ENTER || b[0]==PUSHEBP || (e[0]!=ENTER && e[0]!=PUSHEBP)))) {
        !           788:                at_start = 1;
        !           789:                bp = ureg.ur_sp - (8 - size);
        !           790:                if (IS_LOUT)
        !           791:                        bp &= 0xFFFF;
        !           792:        } else
        !           793:                at_start = 0;
        !           794: 
        !           795:        for (qflag = 0; ; ) {
        !           796: 
        !           797:                /* Fetch the return PC. */
        !           798:                add = (IS_LOUT) ? bp + 6 : bp + 4;
        !           799:                if (get_sized(DSEG, &rpc) == 0)
        !           800:                        break;
        !           801:                dbprintf(("return pc=%lX\n", rpc));
        !           802: 
        !           803:                /*
        !           804:                 * Fetch code from return location and look for stack adjust.
        !           805:                 * If present, calculate the argc from it.
        !           806:                 * The i386 compiler deletes stack adjust before "leave";
        !           807:                 * these are currently printed with "(???)" args (argc==-1).
        !           808:                 */
        !           809:                argc = 0;
        !           810:                add = rpc;
        !           811:                if (getb(ISEG, b, 3) != 0) {
        !           812:                        if (b[0]==ADDSP1 && b[1]==ADDSP2)       /* add sp,$? */
        !           813:                                argc = b[2] / size;
        !           814:                        else if (!IS_LOUT && b[0]==POPECX)      /* pop %ecx */
        !           815:                                argc = 1;
        !           816:                        else if (!IS_LOUT && b[0]==LEAVE)       /* leave */
        !           817:                                argc = -1;
        !           818:                }
        !           819:                dbprintf(("argc=%d\n", argc));
        !           820: 
        !           821:                /*
        !           822:                 * Fetch the opcode preceding the return PC, presumably "call".
        !           823:                 * Print a line like "bp pc name(arg1, ..., argn)\n".
        !           824:                 */
        !           825:                add = rpc - 1 - size;
        !           826:                if (getb(ISEG, b, 1) == 0)
        !           827:                        break;
        !           828:                if (get_sized(ISEG, &n) == 0)
        !           829:                        break;
        !           830:                printx(fmt, bp);
        !           831:                printx("  ");
        !           832:                printx(fmt, pc);
        !           833:                printx("  ");
        !           834:                if (b[0] == CALL) {
        !           835:                        n += rpc;
        !           836:                        putaddr(ISEG, (ADDR_T)n);
        !           837:                        if (n == mainp->s_addr) {
        !           838:                                qflag = 1;
        !           839:                                argc = 3;
        !           840:                        }
        !           841:                } else {
        !           842:                        /* Not a call, e.g. icall. */
        !           843:                        if ((sp = findsym(1, pc)) == (SYM *)NULL)
        !           844:                                printx("*");
        !           845:                        else {
        !           846:                                putaddr(ISEG, pc);
        !           847:                                if (strcmp(sp->s_id, "main") == 0) {
        !           848:                                        qflag = 1;
        !           849:                                        argc = 3;
        !           850:                                }
        !           851:                        }
        !           852:                }
        !           853: 
        !           854:                /*
        !           855:                 * Splat the arg list.
        !           856:                 * Offset 8 coincidently works for both file formats.
        !           857:                 */
        !           858:                putx('(');
        !           859:                add = bp + 8;
        !           860:                if (argc == -1)
        !           861:                        printx("???");
        !           862:                else for (i = 0; i < argc; i++) {
        !           863:                        if (get_sized(DSEG, &n) == 0)
        !           864:                                break;
        !           865:                        if (i != 0)
        !           866:                                printx(", ");
        !           867:                        print_const(miscbuf, (ADDR_T)n);
        !           868:                        printx("%s", miscbuf);
        !           869:                }
        !           870:                printx(")\n");
        !           871: 
        !           872:                /* Move to the next frame and repeat ad nauseum. */
        !           873:                if (testint())
        !           874:                        return;
        !           875:                if (qflag)
        !           876:                        break;
        !           877:                if (at_start) {
        !           878:                        at_start = 0;
        !           879:                        bp = get_fp();
        !           880:                } else {
        !           881:                        add = bp;
        !           882:                        if (get_sized(DSEG, &bp) == 0)
        !           883:                                break;
        !           884:                }
        !           885:                if (--levels == 0)
        !           886:                        return;
        !           887:                pc = rpc;
        !           888:        }
        !           889: }
        !           890: 
        !           891: /* end of db/i386/i386db1.c */

unix.superglobalmegacorp.com

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