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

1.1.1.2   root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1991,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: Richard P. Draves, Carnegie Mellon University
                     28:  *     Date:   10/90
                     29:  */
                     30: 
                     31: #if MACH_KDB
                     32: 
                     33: #include <mach/boolean.h>
                     34: #include <mach/vm_param.h>
                     35: #include <mach/machine/vm_types.h>
                     36: #include <mach/machine/vm_param.h>
                     37: #include <vm/vm_map.h>
                     38: 
                     39: #include <machine/db_machdep.h>
1.1.1.3   root       40: #include <machine/db_interface.h>
                     41: #include <ddb/db_command.h>
1.1       root       42: #include <ddb/db_lex.h>
                     43: #include <ddb/db_watch.h>
                     44: #include <ddb/db_access.h>
1.1.1.3   root       45: #include <ddb/db_expr.h>
                     46: #include <ddb/db_output.h>
                     47: #include <ddb/db_run.h>
1.1       root       48: #include <ddb/db_sym.h>
                     49: #include <ddb/db_task_thread.h>
                     50: 
                     51: 
                     52: 
                     53: /*
                     54:  * Watchpoints.
                     55:  */
                     56: 
                     57: boolean_t      db_watchpoints_inserted = TRUE;
                     58: 
                     59: #define        NWATCHPOINTS    100
                     60: struct db_watchpoint   db_watch_table[NWATCHPOINTS];
                     61: db_watchpoint_t                db_next_free_watchpoint = &db_watch_table[0];
                     62: db_watchpoint_t                db_free_watchpoints = 0;
                     63: db_watchpoint_t                db_watchpoint_list = 0;
                     64: 
                     65: extern vm_map_t                kernel_map;
                     66: 
                     67: db_watchpoint_t
1.1.1.4 ! root       68: db_watchpoint_alloc(void)
1.1       root       69: {
1.1.1.4 ! root       70:        db_watchpoint_t watch;
1.1       root       71: 
                     72:        if ((watch = db_free_watchpoints) != 0) {
                     73:            db_free_watchpoints = watch->link;
                     74:            return (watch);
                     75:        }
                     76:        if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) {
                     77:            db_printf("All watchpoints used.\n");
                     78:            return (0);
                     79:        }
                     80:        watch = db_next_free_watchpoint;
                     81:        db_next_free_watchpoint++;
                     82: 
                     83:        return (watch);
                     84: }
                     85: 
                     86: void
                     87: db_watchpoint_free(watch)
1.1.1.4 ! root       88:        db_watchpoint_t watch;
1.1       root       89: {
                     90:        watch->link = db_free_watchpoints;
                     91:        db_free_watchpoints = watch;
                     92: }
                     93: 
                     94: void
                     95: db_set_watchpoint(task, addr, size)
1.1.1.4 ! root       96:        const task_t    task;
1.1       root       97:        db_addr_t       addr;
                     98:        vm_size_t       size;
                     99: {
1.1.1.4 ! root      100:        db_watchpoint_t watch;
1.1       root      101: 
                    102:        /*
                    103:         *      Should we do anything fancy with overlapping regions?
                    104:         */
                    105: 
                    106:        for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
                    107:            if (watch->task == task &&
                    108:                (watch->loaddr == addr) &&
                    109:                (watch->hiaddr == addr+size)) {
                    110:                db_printf("Already set.\n");
                    111:                return;
                    112:            }
                    113:        }
                    114: 
                    115:        watch = db_watchpoint_alloc();
                    116:        if (watch == 0) {
                    117:            db_printf("Too many watchpoints.\n");
                    118:            return;
                    119:        }
                    120: 
                    121:        watch->task = task;
                    122:        watch->loaddr = addr;
                    123:        watch->hiaddr = addr+size;
                    124: 
                    125:        watch->link = db_watchpoint_list;
                    126:        db_watchpoint_list = watch;
                    127: 
                    128:        db_watchpoints_inserted = FALSE;
                    129: }
                    130: 
                    131: void
                    132: db_delete_watchpoint(task, addr)
1.1.1.4 ! root      133:        const task_t    task;
1.1       root      134:        db_addr_t       addr;
                    135: {
1.1.1.4 ! root      136:        db_watchpoint_t watch;
        !           137:        db_watchpoint_t *prev;
1.1       root      138: 
                    139:        for (prev = &db_watchpoint_list; (watch = *prev) != 0;
                    140:             prev = &watch->link) {
                    141:            if (watch->task == task &&
                    142:                (watch->loaddr <= addr) &&
                    143:                (addr < watch->hiaddr)) {
                    144:                *prev = watch->link;
                    145:                db_watchpoint_free(watch);
                    146:                return;
                    147:            }
                    148:        }
                    149: 
                    150:        db_printf("Not set.\n");
                    151: }
                    152: 
                    153: void
1.1.1.3   root      154: db_list_watchpoints(void)
1.1       root      155: {
1.1.1.4 ! root      156:        db_watchpoint_t watch;
        !           157:        int             task_id;
1.1       root      158: 
                    159:        if (db_watchpoint_list == 0) {
                    160:            db_printf("No watchpoints set\n");
                    161:            return;
                    162:        }
                    163: 
                    164:        db_printf("Space      Address  Size\n");
                    165:        for (watch = db_watchpoint_list; watch != 0; watch = watch->link)  {
                    166:            if (watch->task == TASK_NULL)
                    167:                db_printf("kernel  ");
                    168:            else {
                    169:                task_id = db_lookup_task(watch->task);
                    170:                if (task_id < 0)
                    171:                    db_printf("%*X", 2*sizeof(vm_offset_t), watch->task);
                    172:                else
                    173:                    db_printf("task%-3d ", task_id);
                    174:            }
                    175:            db_printf("  %*X  %X\n", 2*sizeof(vm_offset_t), watch->loaddr,
                    176:                      watch->hiaddr - watch->loaddr);
                    177:        }
                    178: }
                    179: 
                    180: static int
                    181: db_get_task(modif, taskp, addr)
1.1.1.4 ! root      182:        const char      *modif;
1.1       root      183:        task_t          *taskp;
                    184:        db_addr_t       addr;
                    185: {
                    186:        task_t          task = TASK_NULL;
                    187:        db_expr_t       value;
                    188:        boolean_t       user_space;
                    189: 
                    190:        user_space = db_option(modif, 'T');
                    191:        if (user_space) {
                    192:            if (db_expression(&value)) {
                    193:                task = (task_t)value;
                    194:                if (db_lookup_task(task) < 0) {
                    195:                    db_printf("bad task address %X\n", task);
                    196:                    return(-1);
                    197:                }
                    198:            } else {
                    199:                task = db_default_task;
                    200:                if (task == TASK_NULL) {
                    201:                    if ((task = db_current_task()) == TASK_NULL) {
                    202:                        db_printf("no task\n");
                    203:                        return(-1);
                    204:                    }
                    205:                }
                    206:            }
                    207:        }
                    208:        if (!DB_VALID_ADDRESS(addr, user_space)) {
1.1.1.2   root      209:            db_printf("Address %#X is not in %s space\n", addr,
1.1       root      210:                        (user_space)? "user": "kernel");
                    211:            return(-1);
                    212:        }
                    213:        *taskp = task;
                    214:        return(0);
                    215: }
                    216: 
                    217: /* Delete watchpoint */
                    218: /*ARGSUSED*/
                    219: void
                    220: db_deletewatch_cmd(addr, have_addr, count, modif)
                    221:        db_expr_t       addr;
                    222:        int             have_addr;
                    223:        db_expr_t       count;
1.1.1.4 ! root      224:        const char *    modif;
1.1       root      225: {
                    226:        task_t          task;
                    227: 
                    228:        if (db_get_task(modif, &task, addr) < 0)
                    229:            return;
                    230:        db_delete_watchpoint(task, addr);
                    231: }
                    232: 
                    233: /* Set watchpoint */
                    234: /*ARGSUSED*/
                    235: void
                    236: db_watchpoint_cmd(addr, have_addr, count, modif)
                    237:        db_expr_t       addr;
                    238:        int             have_addr;
                    239:        db_expr_t       count;
1.1.1.4 ! root      240:        const char *    modif;
1.1       root      241: {
                    242:        vm_size_t       size;
                    243:        db_expr_t       value;
                    244:        task_t          task;
                    245: 
                    246:        if (db_get_task(modif, &task, addr) < 0)
                    247:            return;
                    248:        if (db_expression(&value))
                    249:            size = (vm_size_t) value;
                    250:        else
                    251:            size = sizeof(int);
                    252:        db_set_watchpoint(task, addr, size);
                    253: }
                    254: 
                    255: /* list watchpoints */
                    256: void
1.1.1.4 ! root      257: db_listwatch_cmd(void)
1.1       root      258: {
                    259:        db_list_watchpoints();
                    260: }
                    261: 
                    262: void
1.1.1.3   root      263: db_set_watchpoints(void)
1.1       root      264: {
1.1.1.4 ! root      265:        db_watchpoint_t         watch;
        !           266:        vm_map_t                map;
1.1.1.3   root      267:        unsigned hw_idx = 0;
1.1       root      268: 
                    269:        if (!db_watchpoints_inserted) {
                    270:            for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
1.1.1.3   root      271:                if (db_set_hw_watchpoint(watch, hw_idx)) {
                    272:                    hw_idx++;
                    273:                    continue;
                    274:                }
1.1       root      275:                map = (watch->task)? watch->task->map: kernel_map;
                    276:                pmap_protect(map->pmap,
                    277:                             trunc_page(watch->loaddr),
                    278:                             round_page(watch->hiaddr),
                    279:                             VM_PROT_READ);
                    280:            }
                    281:            db_watchpoints_inserted = TRUE;
                    282:        }
                    283: }
                    284: 
                    285: void
1.1.1.3   root      286: db_clear_watchpoints(void)
1.1       root      287: {
1.1.1.3   root      288:        unsigned hw_idx = 0;
                    289: 
                    290:        while (db_clear_hw_watchpoint(hw_idx))
                    291:            hw_idx++;
                    292: 
1.1       root      293:        db_watchpoints_inserted = FALSE;
                    294: }
                    295: 
                    296: boolean_t
1.1.1.4 ! root      297: db_find_watchpoint(
        !           298:        vm_map_t        map,
        !           299:        db_addr_t       addr,
        !           300:        db_regs_t       *regs)
1.1       root      301: {
1.1.1.4 ! root      302:        db_watchpoint_t watch;
1.1       root      303:        db_watchpoint_t found = 0;
1.1.1.4 ! root      304:        task_t          task_space;
1.1       root      305: 
                    306:        task_space = (map == kernel_map)? TASK_NULL: db_current_task();
                    307:        for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
                    308:            if (watch->task == task_space) {
                    309:                if ((watch->loaddr <= addr) && (addr < watch->hiaddr))
                    310:                    return (TRUE);
                    311:                else if ((trunc_page(watch->loaddr) <= addr) &&
                    312:                         (addr < round_page(watch->hiaddr)))
                    313:                    found = watch;
                    314:            }
                    315:        }
                    316: 
                    317:        /*
                    318:         *      We didn't hit exactly on a watchpoint, but we are
                    319:         *      in a protected region.  We want to single-step
                    320:         *      and then re-protect.
                    321:         */
                    322: 
                    323:        if (found) {
                    324:            db_watchpoints_inserted = FALSE;
                    325:            db_single_step(regs, task_space);
                    326:        }
                    327: 
                    328:        return (FALSE);
                    329: }
                    330: 
1.1.1.2   root      331: #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.