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

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: boolean_t
1.1.1.4 ! root       63: db_stop_at_pc(
        !            64:        boolean_t       *is_breakpoint,
        !            65:        task_t          task)
1.1       root       66: {
1.1.1.4 ! root       67:        db_addr_t               pc;
        !            68:        db_thread_breakpoint_t  bkpt;
1.1       root       69: 
                     70:        db_clear_task_single_step(DDB_REGS, task);
                     71:        db_clear_breakpoints();
                     72:        db_clear_watchpoints();
                     73:        pc = PC_REGS(DDB_REGS);
                     74: 
                     75: #ifdef FIXUP_PC_AFTER_BREAK
                     76:        if (*is_breakpoint) {
                     77:            /*
                     78:             * Breakpoint trap.  Fix up the PC if the
                     79:             * machine requires it.
                     80:             */
                     81:            FIXUP_PC_AFTER_BREAK
                     82:            pc = PC_REGS(DDB_REGS);
                     83:        }
1.1.1.4 ! root       84: #endif /* FIXUP_PC_AFTER_BREAK */
1.1       root       85: 
                     86:        /*
                     87:         * Now check for a breakpoint at this address.
                     88:         */
                     89:        bkpt = db_find_thread_breakpoint_here(task, pc);
                     90:        if (bkpt) {
                     91:            if (db_cond_check(bkpt)) {
                     92:                *is_breakpoint = TRUE;
                     93:                return (TRUE);  /* stop here */
                     94:            }
                     95:        }
                     96:        *is_breakpoint = FALSE;
                     97: 
                     98:        if (db_run_mode == STEP_INVISIBLE) {
                     99:            db_run_mode = STEP_CONTINUE;
                    100:            return (FALSE);     /* continue */
                    101:        }
                    102:        if (db_run_mode == STEP_COUNT) {
                    103:            return (FALSE); /* continue */
                    104:        }
                    105:        if (db_run_mode == STEP_ONCE) {
                    106:            if (--db_loop_count > 0) {
                    107:                if (db_sstep_print) {
                    108:                    db_print_loc_and_inst(pc, task);
                    109:                }
                    110:                return (FALSE); /* continue */
                    111:            }
                    112:        }
                    113:        if (db_run_mode == STEP_RETURN) {
                    114:            /* WARNING: the following assumes an instruction fits an int */
                    115:            db_expr_t ins = db_get_task_value(pc, sizeof(int), FALSE, task);
                    116: 
                    117:            /* continue until matching return */
                    118: 
                    119:            if (!inst_trap_return(ins) &&
                    120:                (!inst_return(ins) || --db_call_depth != 0)) {
                    121:                if (db_sstep_print) {
                    122:                    if (inst_call(ins) || inst_return(ins)) {
1.1.1.4 ! root      123:                        int i;
1.1       root      124: 
                    125:                        db_printf("[after %6d /%4d] ",
                    126:                                  db_inst_count,
                    127:                                  db_inst_count - db_last_inst_count);
                    128:                        db_last_inst_count = db_inst_count;
                    129:                        for (i = db_call_depth; --i > 0; )
                    130:                            db_printf("  ");
                    131:                        db_print_loc_and_inst(pc, task);
                    132:                        db_printf("\n");
                    133:                    }
                    134:                }
                    135:                if (inst_call(ins))
                    136:                    db_call_depth++;
                    137:                return (FALSE); /* continue */
                    138:            }
                    139:        }
                    140:        if (db_run_mode == STEP_CALLT) {
                    141:            /* WARNING: the following assumes an instruction fits an int */
                    142:            db_expr_t ins = db_get_task_value(pc, sizeof(int), FALSE, task);
                    143: 
                    144:            /* continue until call or return */
                    145: 
                    146:            if (!inst_call(ins) &&
                    147:                !inst_return(ins) &&
                    148:                !inst_trap_return(ins)) {
                    149:                return (FALSE); /* continue */
                    150:            }
                    151:        }
                    152:        if (db_find_breakpoint_here(task, pc))
                    153:                return(FALSE);
                    154:        db_run_mode = STEP_NONE;
                    155:        return (TRUE);
                    156: }
                    157: 
                    158: void
1.1.1.4 ! root      159: db_restart_at_pc(
        !           160:        boolean_t watchpt,
        !           161:        task_t    task)
1.1       root      162: {
1.1.1.4 ! root      163:        db_addr_t pc = PC_REGS(DDB_REGS);
1.1       root      164: 
                    165:        if ((db_run_mode == STEP_COUNT) ||
                    166:            (db_run_mode == STEP_RETURN) ||
                    167:            (db_run_mode == STEP_CALLT)) {
                    168: 
                    169:            /*
                    170:             * We are about to execute this instruction,
                    171:             * so count it now.
                    172:             */
                    173: 
1.1.1.4 ! root      174:            db_get_task_value(pc, sizeof(int), FALSE, task);
1.1       root      175:            db_inst_count++;
                    176:            db_load_count += inst_load(ins);
                    177:            db_store_count += inst_store(ins);
                    178: #ifdef SOFTWARE_SSTEP
1.1.1.4 ! root      179:            db_addr_t brpc;
1.1       root      180:            /* Account for instructions in delay slots */
1.1.1.4 ! root      181:            brpc = next_instr_address(pc, 1, task);
1.1       root      182:            if ((brpc != pc) && (inst_branch(ins) || inst_call(ins))) {
                    183:                /* Note: this ~assumes an instruction <= sizeof(int) */
1.1.1.4 ! root      184:                db_get_task_value(brpc, sizeof(int), FALSE, task);
1.1       root      185:                db_inst_count++;
                    186:                db_load_count += inst_load(ins);
                    187:                db_store_count += inst_store(ins);
                    188:            }
                    189: #endif /* SOFTWARE_SSTEP */
                    190:        }
                    191: 
                    192:        if (db_run_mode == STEP_CONTINUE) {
                    193:            if (watchpt || db_find_breakpoint_here(task, pc)) {
                    194:                /*
                    195:                 * Step over breakpoint/watchpoint.
                    196:                 */
                    197:                db_run_mode = STEP_INVISIBLE;
                    198:                db_set_task_single_step(DDB_REGS, task);
                    199:            } else {
                    200:                db_set_breakpoints();
                    201:                db_set_watchpoints();
                    202:            }
                    203:        } else {
                    204:            db_set_task_single_step(DDB_REGS, task);
                    205:        }
                    206: }
                    207: 
                    208: void
1.1.1.4 ! root      209: db_single_step(
        !           210:        db_regs_t *regs,
        !           211:        task_t    task)
1.1       root      212: {
                    213:        if (db_run_mode == STEP_CONTINUE) {
                    214:            db_run_mode = STEP_INVISIBLE;
                    215:            db_set_task_single_step(regs, task);
                    216:        }
                    217: }
                    218: 
                    219: #ifdef SOFTWARE_SSTEP
                    220: /*
                    221:  *     Software implementation of single-stepping.
                    222:  *     If your machine does not have a trace mode
                    223:  *     similar to the vax or sun ones you can use
                    224:  *     this implementation, done for the mips.
                    225:  *     Just define the above conditional and provide
                    226:  *     the functions/macros defined below.
                    227:  *
                    228:  * extern boolean_t
                    229:  *     inst_branch(),          returns true if the instruction might branch
                    230:  * extern unsigned
                    231:  *     branch_taken(),         return the address the instruction might
                    232:  *                             branch to
                    233:  *     db_getreg_val();        return the value of a user register,
                    234:  *                             as indicated in the hardware instruction
                    235:  *                             encoding, e.g. 8 for r8
1.1.1.2   root      236:  *
1.1       root      237:  * next_instr_address(pc,bd,task) returns the address of the first
                    238:  *                             instruction following the one at "pc",
                    239:  *                             which is either in the taken path of
                    240:  *                             the branch (bd==1) or not.  This is
                    241:  *                             for machines (mips) with branch delays.
                    242:  *
                    243:  *     A single-step may involve at most 2 breakpoints -
                    244:  *     one for branch-not-taken and one for branch taken.
                    245:  *     If one of these addresses does not already have a breakpoint,
                    246:  *     we allocate a breakpoint and save it here.
                    247:  *     These breakpoints are deleted on return.
1.1.1.2   root      248:  */
1.1       root      249: db_breakpoint_t        db_not_taken_bkpt = 0;
                    250: db_breakpoint_t        db_taken_bkpt = 0;
                    251: 
1.1.1.4 ! root      252: db_breakpoint_t __attribute__ ((pure))
1.1       root      253: db_find_temp_breakpoint(task, addr)
1.1.1.4 ! root      254:        const task_t    task;
        !           255:        db_addr_t       addr;
1.1       root      256: {
                    257:        if (db_taken_bkpt && (db_taken_bkpt->address == addr) &&
                    258:            db_taken_bkpt->task == task)
                    259:                return db_taken_bkpt;
                    260:        if (db_not_taken_bkpt && (db_not_taken_bkpt->address == addr) &&
                    261:            db_not_taken_bkpt->task == task)
                    262:                return db_not_taken_bkpt;
                    263:        return 0;
                    264: }
                    265: 
                    266: void
1.1.1.4 ! root      267: db_set_task_single_step(
        !           268:        db_regs_t       *regs,
        !           269:        task_t          task)
1.1       root      270: {
                    271:        db_addr_t pc = PC_REGS(regs), brpc;
1.1.1.4 ! root      272:        unsigned int    inst;
        !           273:        boolean_t       unconditional;
1.1       root      274: 
                    275:        /*
                    276:         *      User was stopped at pc, e.g. the instruction
                    277:         *      at pc was not executed.
                    278:         */
                    279:        inst = db_get_task_value(pc, sizeof(int), FALSE, task);
                    280:        if (inst_branch(inst) || inst_call(inst)) {
                    281:            extern db_expr_t getreg_val();
                    282: 
                    283:            brpc = branch_taken(inst, pc, getreg_val, regs);
                    284:            if (brpc != pc) {   /* self-branches are hopeless */
                    285:                db_taken_bkpt = db_set_temp_breakpoint(task, brpc);
                    286:            } else
                    287:                db_taken_bkpt = 0;
                    288:            pc = next_instr_address(pc,1,task);
                    289:        }
1.1.1.2   root      290: 
1.1       root      291:        /* check if this control flow instruction is an unconditional transfer */
                    292:        unconditional = inst_unconditional_flow_transfer(inst);
                    293: 
                    294:        pc = next_instr_address(pc,0,task);
1.1.1.2   root      295:        /*
1.1       root      296:          We only set the sequential breakpoint if previous instruction was not
                    297:          an unconditional change of flow of control. If the previous instruction
                    298:          is an unconditional change of flow of control, setting a breakpoint in the
                    299:          next sequential location may set a breakpoint in data or in another routine,
1.1.1.2   root      300:          which could screw up either the program or the debugger.
                    301:          (Consider, for instance, that the next sequential instruction is the
1.1       root      302:          start of a routine needed by the debugger.)
                    303:        */
                    304:        if (!unconditional && db_find_breakpoint_here(task, pc) == 0) {
                    305:            db_not_taken_bkpt = db_set_temp_breakpoint(task, pc);
                    306:        }
                    307:        else
                    308:            db_not_taken_bkpt = 0;
                    309: }
                    310: 
                    311: void
                    312: db_clear_task_single_step(regs, task)
1.1.1.4 ! root      313:        const db_regs_t *regs;
        !           314:        task_t          task;
1.1       root      315: {
                    316:        if (db_taken_bkpt != 0) {
                    317:            db_delete_temp_breakpoint(task, db_taken_bkpt);
                    318:            db_taken_bkpt = 0;
                    319:        }
                    320:        if (db_not_taken_bkpt != 0) {
                    321:            db_delete_temp_breakpoint(task, db_not_taken_bkpt);
                    322:            db_not_taken_bkpt = 0;
                    323:        }
                    324: }
                    325: 
                    326: #endif /* SOFTWARE_SSTEP */
                    327: 
                    328: 
                    329: extern int     db_cmd_loop_done;
                    330: 
                    331: /* single-step */
                    332: /*ARGSUSED*/
                    333: void
                    334: db_single_step_cmd(addr, have_addr, count, modif)
                    335:        db_expr_t       addr;
                    336:        int             have_addr;
                    337:        db_expr_t       count;
1.1.1.4 ! root      338:        const char *    modif;
1.1       root      339: {
                    340:        boolean_t       print = FALSE;
                    341: 
                    342:        if (count == -1)
                    343:            count = 1;
                    344: 
                    345:        if (modif[0] == 'p')
                    346:            print = TRUE;
                    347: 
                    348:        db_run_mode = STEP_ONCE;
                    349:        db_loop_count = count;
                    350:        db_sstep_print = print;
                    351:        db_inst_count = 0;
                    352:        db_last_inst_count = 0;
                    353:        db_load_count = 0;
                    354:        db_store_count = 0;
                    355: 
                    356:        db_cmd_loop_done = 1;
                    357: }
                    358: 
                    359: /* trace and print until call/return */
                    360: /*ARGSUSED*/
                    361: void
                    362: db_trace_until_call_cmd(addr, have_addr, count, modif)
                    363:        db_expr_t       addr;
                    364:        int             have_addr;
                    365:        db_expr_t       count;
1.1.1.4 ! root      366:        const char *    modif;
1.1       root      367: {
                    368:        boolean_t       print = FALSE;
                    369: 
                    370:        if (modif[0] == 'p')
                    371:            print = TRUE;
                    372: 
                    373:        db_run_mode = STEP_CALLT;
                    374:        db_sstep_print = print;
                    375:        db_inst_count = 0;
                    376:        db_last_inst_count = 0;
                    377:        db_load_count = 0;
                    378:        db_store_count = 0;
                    379: 
                    380:        db_cmd_loop_done = 1;
                    381: }
                    382: 
                    383: /*ARGSUSED*/
                    384: void
                    385: db_trace_until_matching_cmd(addr, have_addr, count, modif)
                    386:        db_expr_t       addr;
                    387:        int             have_addr;
                    388:        db_expr_t       count;
1.1.1.4 ! root      389:        const char *    modif;
1.1       root      390: {
                    391:        boolean_t       print = FALSE;
                    392: 
                    393:        if (modif[0] == 'p')
                    394:            print = TRUE;
                    395: 
                    396:        db_run_mode = STEP_RETURN;
                    397:        db_call_depth = 1;
                    398:        db_sstep_print = print;
                    399:        db_inst_count = 0;
                    400:        db_last_inst_count = 0;
                    401:        db_load_count = 0;
                    402:        db_store_count = 0;
                    403: 
                    404:        db_cmd_loop_done = 1;
                    405: }
                    406: 
                    407: /* continue */
                    408: /*ARGSUSED*/
                    409: void
                    410: db_continue_cmd(addr, have_addr, count, modif)
                    411:        db_expr_t       addr;
                    412:        int             have_addr;
                    413:        db_expr_t       count;
1.1.1.4 ! root      414:        const char *    modif;
1.1       root      415: {
                    416:        if (modif[0] == 'c')
                    417:            db_run_mode = STEP_COUNT;
                    418:        else
                    419:            db_run_mode = STEP_CONTINUE;
                    420:        db_inst_count = 0;
                    421:        db_last_inst_count = 0;
                    422:        db_load_count = 0;
                    423:        db_store_count = 0;
                    424: 
                    425:        db_cmd_loop_done = 1;
                    426: }
                    427: 
                    428: boolean_t
1.1.1.4 ! root      429: db_in_single_step(void)
1.1       root      430: {
                    431:        return(db_run_mode != STEP_NONE && db_run_mode != STEP_CONTINUE);
                    432: }
                    433: 
1.1.1.2   root      434: #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.