Annotation of Gnu-Mach/ddb/db_run.c, revision 1.1.1.3

1.1.1.2   root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1993-1990 Carnegie Mellon University
                      4:  * All Rights Reserved.
1.1.1.2   root        5:  *
1.1       root        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.
1.1.1.2   root       11:  *
1.1       root       12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.1.1.2   root       15:  *
1.1       root       16:  * Carnegie Mellon requests users of this software to return to
1.1.1.2   root       17:  *
1.1       root       18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
1.1.1.2   root       22:  *
1.1       root       23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     Author: David B. Golub, Carnegie Mellon University
                     28:  *     Date:   7/90
                     29:  */
                     30: 
                     31: #if MACH_KDB
                     32: 
                     33: /*
                     34:  * Commands to run process.
                     35:  */
                     36: #include <mach/boolean.h>
                     37: #include <machine/db_machdep.h>
                     38: 
                     39: #include <ddb/db_lex.h>
                     40: #include <ddb/db_break.h>
                     41: #include <ddb/db_access.h>
                     42: #include <ddb/db_run.h>
                     43: #include <ddb/db_task_thread.h>
1.1.1.3 ! root       44: #include <ddb/db_command.h>
        !            45: #include <ddb/db_examine.h>
        !            46: #include <ddb/db_output.h>
        !            47: #include <ddb/db_watch.h>
        !            48: #include <ddb/db_cond.h>
        !            49: 
1.1       root       50: 
                     51: int    db_run_mode;
                     52: 
                     53: boolean_t      db_sstep_print;
                     54: int            db_loop_count;
                     55: int            db_call_depth;
                     56: 
                     57: int            db_inst_count;
                     58: int            db_last_inst_count;
                     59: int            db_load_count;
                     60: int            db_store_count;
                     61: 
                     62: #ifndef db_set_single_step
                     63: void           db_set_task_single_step(/* db_regs_t *, task_t */);/* forward */
                     64: #else
                     65: #define        db_set_task_single_step(regs,task)      db_set_single_step(regs)
                     66: #endif
                     67: #ifndef db_clear_single_step
                     68: void           db_clear_task_single_step(/* db_regs_t *, task_t */);
                     69: #else
                     70: #define db_clear_task_single_step(regs,task)   db_clear_single_step(regs)
                     71: #endif
                     72: 
                     73: boolean_t
                     74: db_stop_at_pc(is_breakpoint, task)
                     75:        boolean_t       *is_breakpoint;
                     76:        task_t          task;
                     77: {
                     78:        register  db_addr_t     pc;
                     79:        register  db_thread_breakpoint_t bkpt;
                     80: 
                     81:        db_clear_task_single_step(DDB_REGS, task);
                     82:        db_clear_breakpoints();
                     83:        db_clear_watchpoints();
                     84:        pc = PC_REGS(DDB_REGS);
                     85: 
                     86: #ifdef FIXUP_PC_AFTER_BREAK
                     87:        if (*is_breakpoint) {
                     88:            /*
                     89:             * Breakpoint trap.  Fix up the PC if the
                     90:             * machine requires it.
                     91:             */
                     92:            FIXUP_PC_AFTER_BREAK
                     93:            pc = PC_REGS(DDB_REGS);
                     94:        }
                     95: #endif
                     96: 
                     97:        /*
                     98:         * Now check for a breakpoint at this address.
                     99:         */
                    100:        bkpt = db_find_thread_breakpoint_here(task, pc);
                    101:        if (bkpt) {
                    102:            if (db_cond_check(bkpt)) {
                    103:                *is_breakpoint = TRUE;
                    104:                return (TRUE);  /* stop here */
                    105:            }
                    106:        }
                    107:        *is_breakpoint = FALSE;
                    108: 
                    109:        if (db_run_mode == STEP_INVISIBLE) {
                    110:            db_run_mode = STEP_CONTINUE;
                    111:            return (FALSE);     /* continue */
                    112:        }
                    113:        if (db_run_mode == STEP_COUNT) {
                    114:            return (FALSE); /* continue */
                    115:        }
                    116:        if (db_run_mode == STEP_ONCE) {
                    117:            if (--db_loop_count > 0) {
                    118:                if (db_sstep_print) {
                    119:                    db_print_loc_and_inst(pc, task);
                    120:                }
                    121:                return (FALSE); /* continue */
                    122:            }
                    123:        }
                    124:        if (db_run_mode == STEP_RETURN) {
                    125:            /* WARNING: the following assumes an instruction fits an int */
                    126:            db_expr_t ins = db_get_task_value(pc, sizeof(int), FALSE, task);
                    127: 
                    128:            /* continue until matching return */
                    129: 
                    130:            if (!inst_trap_return(ins) &&
                    131:                (!inst_return(ins) || --db_call_depth != 0)) {
                    132:                if (db_sstep_print) {
                    133:                    if (inst_call(ins) || inst_return(ins)) {
                    134:                        register int i;
                    135: 
                    136:                        db_printf("[after %6d /%4d] ",
                    137:                                  db_inst_count,
                    138:                                  db_inst_count - db_last_inst_count);
                    139:                        db_last_inst_count = db_inst_count;
                    140:                        for (i = db_call_depth; --i > 0; )
                    141:                            db_printf("  ");
                    142:                        db_print_loc_and_inst(pc, task);
                    143:                        db_printf("\n");
                    144:                    }
                    145:                }
                    146:                if (inst_call(ins))
                    147:                    db_call_depth++;
                    148:                return (FALSE); /* continue */
                    149:            }
                    150:        }
                    151:        if (db_run_mode == STEP_CALLT) {
                    152:            /* WARNING: the following assumes an instruction fits an int */
                    153:            db_expr_t ins = db_get_task_value(pc, sizeof(int), FALSE, task);
                    154: 
                    155:            /* continue until call or return */
                    156: 
                    157:            if (!inst_call(ins) &&
                    158:                !inst_return(ins) &&
                    159:                !inst_trap_return(ins)) {
                    160:                return (FALSE); /* continue */
                    161:            }
                    162:        }
                    163:        if (db_find_breakpoint_here(task, pc))
                    164:                return(FALSE);
                    165:        db_run_mode = STEP_NONE;
                    166:        return (TRUE);
                    167: }
                    168: 
                    169: void
                    170: db_restart_at_pc(watchpt, task)
                    171:        boolean_t watchpt;
                    172:        task_t    task;
                    173: {
                    174:        register db_addr_t pc = PC_REGS(DDB_REGS), brpc;
                    175: 
                    176:        if ((db_run_mode == STEP_COUNT) ||
                    177:            (db_run_mode == STEP_RETURN) ||
                    178:            (db_run_mode == STEP_CALLT)) {
                    179:            db_expr_t           ins;
                    180: 
                    181:            /*
                    182:             * We are about to execute this instruction,
                    183:             * so count it now.
                    184:             */
                    185: 
                    186:            ins = db_get_task_value(pc, sizeof(int), FALSE, task);
                    187:            db_inst_count++;
                    188:            db_load_count += inst_load(ins);
                    189:            db_store_count += inst_store(ins);
                    190: #ifdef SOFTWARE_SSTEP
                    191:            /* Account for instructions in delay slots */
                    192:            brpc = next_instr_address(pc,1,task);
                    193:            if ((brpc != pc) && (inst_branch(ins) || inst_call(ins))) {
                    194:                /* Note: this ~assumes an instruction <= sizeof(int) */
                    195:                ins = db_get_task_value(brpc, sizeof(int), FALSE, task);
                    196:                db_inst_count++;
                    197:                db_load_count += inst_load(ins);
                    198:                db_store_count += inst_store(ins);
                    199:            }
                    200: #endif /* SOFTWARE_SSTEP */
                    201:        }
                    202: 
                    203:        if (db_run_mode == STEP_CONTINUE) {
                    204:            if (watchpt || db_find_breakpoint_here(task, pc)) {
                    205:                /*
                    206:                 * Step over breakpoint/watchpoint.
                    207:                 */
                    208:                db_run_mode = STEP_INVISIBLE;
                    209:                db_set_task_single_step(DDB_REGS, task);
                    210:            } else {
                    211:                db_set_breakpoints();
                    212:                db_set_watchpoints();
                    213:            }
                    214:        } else {
                    215:            db_set_task_single_step(DDB_REGS, task);
                    216:        }
                    217: }
                    218: 
                    219: void
                    220: db_single_step(regs, task)
                    221:        db_regs_t *regs;
                    222:        task_t    task;
                    223: {
                    224:        if (db_run_mode == STEP_CONTINUE) {
                    225:            db_run_mode = STEP_INVISIBLE;
                    226:            db_set_task_single_step(regs, task);
                    227:        }
                    228: }
                    229: 
                    230: #ifdef SOFTWARE_SSTEP
                    231: /*
                    232:  *     Software implementation of single-stepping.
                    233:  *     If your machine does not have a trace mode
                    234:  *     similar to the vax or sun ones you can use
                    235:  *     this implementation, done for the mips.
                    236:  *     Just define the above conditional and provide
                    237:  *     the functions/macros defined below.
                    238:  *
                    239:  * extern boolean_t
                    240:  *     inst_branch(),          returns true if the instruction might branch
                    241:  * extern unsigned
                    242:  *     branch_taken(),         return the address the instruction might
                    243:  *                             branch to
                    244:  *     db_getreg_val();        return the value of a user register,
                    245:  *                             as indicated in the hardware instruction
                    246:  *                             encoding, e.g. 8 for r8
1.1.1.2   root      247:  *
1.1       root      248:  * next_instr_address(pc,bd,task) returns the address of the first
                    249:  *                             instruction following the one at "pc",
                    250:  *                             which is either in the taken path of
                    251:  *                             the branch (bd==1) or not.  This is
                    252:  *                             for machines (mips) with branch delays.
                    253:  *
                    254:  *     A single-step may involve at most 2 breakpoints -
                    255:  *     one for branch-not-taken and one for branch taken.
                    256:  *     If one of these addresses does not already have a breakpoint,
                    257:  *     we allocate a breakpoint and save it here.
                    258:  *     These breakpoints are deleted on return.
1.1.1.2   root      259:  */
1.1       root      260: db_breakpoint_t        db_not_taken_bkpt = 0;
                    261: db_breakpoint_t        db_taken_bkpt = 0;
                    262: 
                    263: db_breakpoint_t
                    264: db_find_temp_breakpoint(task, addr)
                    265:        task_t             task;
                    266:        db_addr_t          addr;
                    267: {
                    268:        if (db_taken_bkpt && (db_taken_bkpt->address == addr) &&
                    269:            db_taken_bkpt->task == task)
                    270:                return db_taken_bkpt;
                    271:        if (db_not_taken_bkpt && (db_not_taken_bkpt->address == addr) &&
                    272:            db_not_taken_bkpt->task == task)
                    273:                return db_not_taken_bkpt;
                    274:        return 0;
                    275: }
                    276: 
                    277: void
                    278: db_set_task_single_step(regs, task)
                    279:        register db_regs_t *regs;
                    280:        task_t             task;
                    281: {
                    282:        db_addr_t pc = PC_REGS(regs), brpc;
                    283:        register unsigned int    inst;
                    284:        register boolean_t       unconditional;
                    285: 
                    286:        /*
                    287:         *      User was stopped at pc, e.g. the instruction
                    288:         *      at pc was not executed.
                    289:         */
                    290:        inst = db_get_task_value(pc, sizeof(int), FALSE, task);
                    291:        if (inst_branch(inst) || inst_call(inst)) {
                    292:            extern db_expr_t getreg_val();
                    293: 
                    294:            brpc = branch_taken(inst, pc, getreg_val, regs);
                    295:            if (brpc != pc) {   /* self-branches are hopeless */
                    296:                db_taken_bkpt = db_set_temp_breakpoint(task, brpc);
                    297:            } else
                    298:                db_taken_bkpt = 0;
                    299:            pc = next_instr_address(pc,1,task);
                    300:        }
1.1.1.2   root      301: 
1.1       root      302:        /* check if this control flow instruction is an unconditional transfer */
                    303:        unconditional = inst_unconditional_flow_transfer(inst);
                    304: 
                    305:        pc = next_instr_address(pc,0,task);
1.1.1.2   root      306:        /*
1.1       root      307:          We only set the sequential breakpoint if previous instruction was not
                    308:          an unconditional change of flow of control. If the previous instruction
                    309:          is an unconditional change of flow of control, setting a breakpoint in the
                    310:          next sequential location may set a breakpoint in data or in another routine,
1.1.1.2   root      311:          which could screw up either the program or the debugger.
                    312:          (Consider, for instance, that the next sequential instruction is the
1.1       root      313:          start of a routine needed by the debugger.)
                    314:        */
                    315:        if (!unconditional && db_find_breakpoint_here(task, pc) == 0) {
                    316:            db_not_taken_bkpt = db_set_temp_breakpoint(task, pc);
                    317:        }
                    318:        else
                    319:            db_not_taken_bkpt = 0;
                    320: }
                    321: 
                    322: void
                    323: db_clear_task_single_step(regs, task)
                    324:        db_regs_t *regs;
                    325:        task_t    task;
                    326: {
                    327:        if (db_taken_bkpt != 0) {
                    328:            db_delete_temp_breakpoint(task, db_taken_bkpt);
                    329:            db_taken_bkpt = 0;
                    330:        }
                    331:        if (db_not_taken_bkpt != 0) {
                    332:            db_delete_temp_breakpoint(task, db_not_taken_bkpt);
                    333:            db_not_taken_bkpt = 0;
                    334:        }
                    335: }
                    336: 
                    337: #endif /* SOFTWARE_SSTEP */
                    338: 
                    339: 
                    340: extern int     db_cmd_loop_done;
                    341: 
                    342: /* single-step */
                    343: /*ARGSUSED*/
                    344: void
                    345: db_single_step_cmd(addr, have_addr, count, modif)
                    346:        db_expr_t       addr;
                    347:        int             have_addr;
                    348:        db_expr_t       count;
                    349:        char *          modif;
                    350: {
                    351:        boolean_t       print = FALSE;
                    352: 
                    353:        if (count == -1)
                    354:            count = 1;
                    355: 
                    356:        if (modif[0] == 'p')
                    357:            print = TRUE;
                    358: 
                    359:        db_run_mode = STEP_ONCE;
                    360:        db_loop_count = count;
                    361:        db_sstep_print = print;
                    362:        db_inst_count = 0;
                    363:        db_last_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_last_inst_count = 0;
                    388:        db_load_count = 0;
                    389:        db_store_count = 0;
                    390: 
                    391:        db_cmd_loop_done = 1;
                    392: }
                    393: 
                    394: /*ARGSUSED*/
                    395: void
                    396: db_trace_until_matching_cmd(addr, have_addr, count, modif)
                    397:        db_expr_t       addr;
                    398:        int             have_addr;
                    399:        db_expr_t       count;
                    400:        char *          modif;
                    401: {
                    402:        boolean_t       print = FALSE;
                    403: 
                    404:        if (modif[0] == 'p')
                    405:            print = TRUE;
                    406: 
                    407:        db_run_mode = STEP_RETURN;
                    408:        db_call_depth = 1;
                    409:        db_sstep_print = print;
                    410:        db_inst_count = 0;
                    411:        db_last_inst_count = 0;
                    412:        db_load_count = 0;
                    413:        db_store_count = 0;
                    414: 
                    415:        db_cmd_loop_done = 1;
                    416: }
                    417: 
                    418: /* continue */
                    419: /*ARGSUSED*/
                    420: void
                    421: db_continue_cmd(addr, have_addr, count, modif)
                    422:        db_expr_t       addr;
                    423:        int             have_addr;
                    424:        db_expr_t       count;
                    425:        char *          modif;
                    426: {
                    427:        if (modif[0] == 'c')
                    428:            db_run_mode = STEP_COUNT;
                    429:        else
                    430:            db_run_mode = STEP_CONTINUE;
                    431:        db_inst_count = 0;
                    432:        db_last_inst_count = 0;
                    433:        db_load_count = 0;
                    434:        db_store_count = 0;
                    435: 
                    436:        db_cmd_loop_done = 1;
                    437: }
                    438: 
                    439: boolean_t
                    440: db_in_single_step()
                    441: {
                    442:        return(db_run_mode != STEP_NONE && db_run_mode != STEP_CONTINUE);
                    443: }
                    444: 
1.1.1.2   root      445: #endif /* MACH_KDB */

unix.superglobalmegacorp.com

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