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

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

unix.superglobalmegacorp.com

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