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

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