Annotation of coherent/b/bin/db/i386/i386db1.c, revision 1.1.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.