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

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

unix.superglobalmegacorp.com

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