Annotation of Net2/ddb/db_run.c, revision 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.