Annotation of Net2/ddb/db_run.c, revision 1.1.1.2

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     23:  * any improvements or extensions that they make and grant Carnegie the
                     24:  * rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  * HISTORY
                     28:  * $Log: db_run.c,v $
1.1.1.2 ! root       29:  * Revision 1.1.1.1  1993/03/21 09:46:27  cgd
        !            30:  * initial import of 386bsd-0.1 sources
        !            31:  *
1.1       root       32:  * Revision 1.1  1992/03/25  21:45:24  pace
                     33:  * Initial revision
                     34:  *
                     35:  * Revision 2.5  91/02/05  17:06:58  mrt
                     36:  *     Changed to new Mach copyright
                     37:  *     [91/01/31  16:19:05  mrt]
                     38:  * 
                     39:  * Revision 2.4  91/01/08  15:09:10  rpd
                     40:  *     Fixed bug in db_restart_at_pc.
                     41:  *     [90/12/07            rpd]
                     42:  *     Added STEP_COUNT and count option to db_continue_cmd.
                     43:  *     Changed db_stop_at_pc to return (modified) is_breakpoint.
                     44:  *     Fixed db_stop_at_pc to print newlines in the right places.
                     45:  *     [90/11/27            rpd]
                     46:  * 
                     47:  * Revision 2.3  90/10/25  14:43:59  rwd
                     48:  *     Changed db_find_breakpoint to db_find_breakpoint_here.
                     49:  *     [90/10/18            rpd]
                     50:  * 
                     51:  *     Fixed db_set_single_step to pass regs to branch_taken.
                     52:  *     Added watchpoint argument to db_restart_at_pc.
                     53:  *     [90/10/17            rpd]
                     54:  *     Generalized the watchpoint support.
                     55:  *     [90/10/16            rwd]
                     56:  *     Added watchpoint support.
                     57:  *     [90/10/16            rpd]
                     58:  * 
                     59:  * Revision 2.2  90/08/27  21:51:59  dbg
                     60:  *     Fixed names for single-step functions.
                     61:  *     [90/08/20            af]
                     62:  *     Reduce lint.
                     63:  *     [90/08/07            dbg]
                     64:  *     Created.
                     65:  *     [90/07/25            dbg]
                     66:  * 
                     67:  */
                     68: /*
                     69:  *     Author: David B. Golub, Carnegie Mellon University
                     70:  *     Date:   7/90
                     71:  */
                     72: 
                     73: /*
                     74:  * Commands to run process.
                     75:  */
                     76: #include "param.h"
                     77: #include "proc.h"
                     78: #include <machine/db_machdep.h>
                     79: 
                     80: #include <ddb/db_lex.h>
                     81: #include <ddb/db_break.h>
                     82: #include <ddb/db_access.h>
                     83: 
                     84: int    db_run_mode;
                     85: #define        STEP_NONE       0
                     86: #define        STEP_ONCE       1
                     87: #define        STEP_RETURN     2
                     88: #define        STEP_CALLT      3
                     89: #define        STEP_CONTINUE   4
                     90: #define STEP_INVISIBLE 5
                     91: #define        STEP_COUNT      6
                     92: 
                     93: boolean_t      db_sstep_print;
                     94: int            db_loop_count;
                     95: int            db_call_depth;
                     96: 
                     97: int            db_inst_count;
                     98: int            db_load_count;
                     99: int            db_store_count;
                    100: 
                    101: #ifndef db_set_single_step
                    102: void           db_set_single_step(/* db_regs_t *regs */);      /* forward */
                    103: #endif
                    104: #ifndef db_clear_single_step
                    105: void           db_clear_single_step(/* db_regs_t *regs */);
                    106: #endif
                    107: 
                    108: boolean_t
                    109: db_stop_at_pc(is_breakpoint)
                    110:        boolean_t       *is_breakpoint;
                    111: {
                    112:        register db_addr_t      pc;
                    113:        register db_breakpoint_t bkpt;
                    114: 
                    115:        db_clear_single_step(DDB_REGS);
                    116:        db_clear_breakpoints();
                    117:        db_clear_watchpoints();
                    118:        pc = PC_REGS(DDB_REGS);
                    119: 
                    120: #ifdef FIXUP_PC_AFTER_BREAK
                    121:        if (*is_breakpoint) {
                    122:            /*
                    123:             * Breakpoint trap.  Fix up the PC if the
                    124:             * machine requires it.
                    125:             */
                    126:            FIXUP_PC_AFTER_BREAK
                    127:            pc = PC_REGS(DDB_REGS);
                    128:        }
                    129: #endif
                    130: 
                    131:        /*
                    132:         * Now check for a breakpoint at this address.
                    133:         */
                    134:        bkpt = db_find_breakpoint_here(pc);
                    135:        if (bkpt) {
                    136:            if (--bkpt->count == 0) {
                    137:                bkpt->count = bkpt->init_count;
                    138:                *is_breakpoint = TRUE;
                    139:                return (TRUE);  /* stop here */
                    140:            }
                    141:        } else if (*is_breakpoint) {
                    142:                ddb_regs.tf_eip += 1;
                    143:        }
                    144:                
                    145:        *is_breakpoint = FALSE;
                    146: 
                    147:        if (db_run_mode == STEP_INVISIBLE) {
                    148:            db_run_mode = STEP_CONTINUE;
                    149:            return (FALSE);     /* continue */
                    150:        }
                    151:        if (db_run_mode == STEP_COUNT) {
                    152:            return (FALSE); /* continue */
                    153:        }
                    154:        if (db_run_mode == STEP_ONCE) {
                    155:            if (--db_loop_count > 0) {
                    156:                if (db_sstep_print) {
                    157:                    db_printf("\t\t");
                    158:                    db_print_loc_and_inst(pc);
                    159:                    db_printf("\n");
                    160:                }
                    161:                return (FALSE); /* continue */
                    162:            }
                    163:        }
                    164:        if (db_run_mode == STEP_RETURN) {
                    165:            db_expr_t ins = db_get_value(pc, sizeof(int), FALSE);
                    166: 
                    167:            /* continue until matching return */
                    168: 
                    169:            if (!inst_trap_return(ins) &&
                    170:                (!inst_return(ins) || --db_call_depth != 0)) {
                    171:                if (db_sstep_print) {
                    172:                    if (inst_call(ins) || inst_return(ins)) {
                    173:                        register int i;
                    174: 
                    175:                        db_printf("[after %6d]     ", db_inst_count);
                    176:                        for (i = db_call_depth; --i > 0; )
                    177:                            db_printf("  ");
                    178:                        db_print_loc_and_inst(pc);
                    179:                        db_printf("\n");
                    180:                    }
                    181:                }
                    182:                if (inst_call(ins))
                    183:                    db_call_depth++;
                    184:                return (FALSE); /* continue */
                    185:            }
                    186:        }
                    187:        if (db_run_mode == STEP_CALLT) {
                    188:            db_expr_t ins = db_get_value(pc, sizeof(int), FALSE);
                    189: 
                    190:            /* continue until call or return */
                    191: 
                    192:            if (!inst_call(ins) &&
                    193:                !inst_return(ins) &&
                    194:                !inst_trap_return(ins)) {
                    195:                return (FALSE); /* continue */
                    196:            }
                    197:        }
                    198:        db_run_mode = STEP_NONE;
                    199:        return (TRUE);
                    200: }
                    201: 
                    202: void
                    203: db_restart_at_pc(watchpt)
                    204:        boolean_t watchpt;
                    205: {
                    206:        register db_addr_t      pc = PC_REGS(DDB_REGS);
                    207: 
                    208:        if ((db_run_mode == STEP_COUNT) ||
                    209:            (db_run_mode == STEP_RETURN) ||
                    210:            (db_run_mode == STEP_CALLT)) {
                    211:            db_expr_t           ins;
                    212: 
                    213:            /*
                    214:             * We are about to execute this instruction,
                    215:             * so count it now.
                    216:             */
                    217: 
                    218:            ins = db_get_value(pc, sizeof(int), FALSE);
                    219:            db_inst_count++;
                    220:            db_load_count += inst_load(ins);
                    221:            db_store_count += inst_store(ins);
                    222: #ifdef SOFTWARE_SSTEP
                    223:            /* XXX works on mips, but... */
                    224:            if (inst_branch(ins) || inst_call(ins)) {
                    225:                ins = db_get_value(next_instr_address(pc,1),
                    226:                                   sizeof(int), FALSE);
                    227:                db_inst_count++;
                    228:                db_load_count += inst_load(ins);
                    229:                db_store_count += inst_store(ins);
                    230:            }
                    231: #endif SOFTWARE_SSTEP
                    232:        }
                    233: 
                    234:        if (db_run_mode == STEP_CONTINUE) {
                    235:            if (watchpt || db_find_breakpoint_here(pc)) {
                    236:                /*
                    237:                 * Step over breakpoint/watchpoint.
                    238:                 */
                    239:                db_run_mode = STEP_INVISIBLE;
                    240:                db_set_single_step(DDB_REGS);
                    241:            } else {
                    242:                db_set_breakpoints();
                    243:                db_set_watchpoints();
                    244:            }
                    245:        } else {
                    246:            db_set_single_step(DDB_REGS);
                    247:        }
                    248: }
                    249: 
                    250: void
                    251: db_single_step(regs)
                    252:        db_regs_t *regs;
                    253: {
                    254:        if (db_run_mode == STEP_CONTINUE) {
                    255:            db_run_mode = STEP_INVISIBLE;
                    256:            db_set_single_step(regs);
                    257:        }
                    258: }
                    259: 
                    260: #ifdef SOFTWARE_SSTEP
                    261: /*
                    262:  *     Software implementation of single-stepping.
                    263:  *     If your machine does not have a trace mode
                    264:  *     similar to the vax or sun ones you can use
                    265:  *     this implementation, done for the mips.
                    266:  *     Just define the above conditional and provide
                    267:  *     the functions/macros defined below.
                    268:  *
                    269:  * extern boolean_t
                    270:  *     inst_branch(),          returns true if the instruction might branch
                    271:  * extern unsigned
                    272:  *     branch_taken(),         return the address the instruction might
                    273:  *                             branch to
                    274:  *     db_getreg_val();        return the value of a user register,
                    275:  *                             as indicated in the hardware instruction
                    276:  *                             encoding, e.g. 8 for r8
                    277:  *                     
                    278:  * next_instr_address(pc,bd)   returns the address of the first
                    279:  *                             instruction following the one at "pc",
                    280:  *                             which is either in the taken path of
                    281:  *                             the branch (bd==1) or not.  This is
                    282:  *                             for machines (mips) with branch delays.
                    283:  *
                    284:  *     A single-step may involve at most 2 breakpoints -
                    285:  *     one for branch-not-taken and one for branch taken.
                    286:  *     If one of these addresses does not already have a breakpoint,
                    287:  *     we allocate a breakpoint and save it here.
                    288:  *     These breakpoints are deleted on return.
                    289:  */                    
                    290: db_breakpoint_t        db_not_taken_bkpt = 0;
                    291: db_breakpoint_t        db_taken_bkpt = 0;
                    292: 
                    293: void
                    294: db_set_single_step(regs)
                    295:        register db_regs_t *regs;
                    296: {
                    297:        db_addr_t pc = PC_REGS(regs);
                    298:        register unsigned        inst, brpc;
                    299: 
                    300:        /*
                    301:         *      User was stopped at pc, e.g. the instruction
                    302:         *      at pc was not executed.
                    303:         */
                    304:        inst = db_get_value(pc, sizeof(int), FALSE);
                    305:        if (inst_branch(inst) || inst_call(inst)) {
                    306:            extern unsigned getreg_val();
                    307: 
                    308:            brpc = branch_taken(inst, pc, getreg_val, regs);
                    309:            if (brpc != pc) {   /* self-branches are hopeless */
                    310:                db_taken_bkpt = db_set_temp_breakpoint(brpc);
                    311:            }
                    312:            pc = next_instr_address(pc,1);
                    313:        }
                    314:        pc = next_instr_address(pc,0);
                    315:        db_not_taken_bkpt = db_set_temp_breakpoint(pc);
                    316: }
                    317: 
                    318: void
                    319: db_clear_single_step(regs)
                    320:        db_regs_t *regs;
                    321: {
                    322:        register db_breakpoint_t        bkpt;
                    323: 
                    324:        if (db_taken_bkpt != 0) {
                    325:            db_delete_temp_breakpoint(db_taken_bkpt);
                    326:            db_taken_bkpt = 0;
                    327:        }
                    328:        if (db_not_taken_bkpt != 0) {
                    329:            db_delete_temp_breakpoint(db_not_taken_bkpt);
                    330:            db_not_taken_bkpt = 0;
                    331:        }
                    332: }
                    333: 
                    334: #endif SOFTWARE_SSTEP
                    335: 
                    336: extern int     db_cmd_loop_done;
                    337: 
                    338: /* single-step */
                    339: /*ARGSUSED*/
                    340: void
                    341: db_single_step_cmd(addr, have_addr, count, modif)
                    342:        db_expr_t       addr;
                    343:        int             have_addr;
                    344:        db_expr_t       count;
                    345:        char *          modif;
                    346: {
                    347:        boolean_t       print = FALSE;
                    348: 
                    349:        if (count == -1)
                    350:            count = 1;
                    351: 
                    352:        if (modif[0] == 'p')
                    353:            print = TRUE;
                    354: 
                    355:        db_run_mode = STEP_ONCE;
                    356:        db_loop_count = count;
                    357:        db_sstep_print = print;
                    358:        db_inst_count = 0;
                    359:        db_load_count = 0;
                    360:        db_store_count = 0;
                    361: 
                    362:        db_cmd_loop_done = 1;
                    363: }
                    364: 
                    365: /* trace and print until call/return */
                    366: /*ARGSUSED*/
                    367: void
                    368: db_trace_until_call_cmd(addr, have_addr, count, modif)
                    369:        db_expr_t       addr;
                    370:        int             have_addr;
                    371:        db_expr_t       count;
                    372:        char *          modif;
                    373: {
                    374:        boolean_t       print = FALSE;
                    375: 
                    376:        if (modif[0] == 'p')
                    377:            print = TRUE;
                    378: 
                    379:        db_run_mode = STEP_CALLT;
                    380:        db_sstep_print = print;
                    381:        db_inst_count = 0;
                    382:        db_load_count = 0;
                    383:        db_store_count = 0;
                    384: 
                    385:        db_cmd_loop_done = 1;
                    386: }
                    387: 
                    388: /*ARGSUSED*/
                    389: void
                    390: db_trace_until_matching_cmd(addr, have_addr, count, modif)
                    391:        db_expr_t       addr;
                    392:        int             have_addr;
                    393:        db_expr_t       count;
                    394:        char *          modif;
                    395: {
                    396:        boolean_t       print = FALSE;
                    397: 
                    398:        if (modif[0] == 'p')
                    399:            print = TRUE;
                    400: 
                    401:        db_run_mode = STEP_RETURN;
                    402:        db_call_depth = 1;
                    403:        db_sstep_print = print;
                    404:        db_inst_count = 0;
                    405:        db_load_count = 0;
                    406:        db_store_count = 0;
                    407: 
                    408:        db_cmd_loop_done = 1;
                    409: }
                    410: 
                    411: /* continue */
                    412: /*ARGSUSED*/
                    413: void
                    414: db_continue_cmd(addr, have_addr, count, modif)
                    415:        db_expr_t       addr;
                    416:        int             have_addr;
                    417:        db_expr_t       count;
                    418:        char *          modif;
                    419: {
                    420:        if (modif[0] == 'c')
                    421:            db_run_mode = STEP_COUNT;
                    422:        else
                    423:            db_run_mode = STEP_CONTINUE;
                    424:        db_inst_count = 0;
                    425:        db_load_count = 0;
                    426:        db_store_count = 0;
                    427: 
                    428:        db_cmd_loop_done = 1;
                    429: }

unix.superglobalmegacorp.com

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