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

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
                     68: db_watchpoint_alloc()
                     69: {
                     70:        register db_watchpoint_t        watch;
                     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)
                     88:        register db_watchpoint_t        watch;
                     89: {
                     90:        watch->link = db_free_watchpoints;
                     91:        db_free_watchpoints = watch;
                     92: }
                     93: 
                     94: void
                     95: db_set_watchpoint(task, addr, size)
                     96:        task_t          task;
                     97:        db_addr_t       addr;
                     98:        vm_size_t       size;
                     99: {
                    100:        register db_watchpoint_t        watch;
                    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)
                    133:        task_t          task;
                    134:        db_addr_t       addr;
                    135: {
                    136:        register db_watchpoint_t        watch;
                    137:        register db_watchpoint_t        *prev;
                    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: {
                    156:        register db_watchpoint_t watch;
                    157:        int      task_id;
                    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)
                    182:        char            *modif;
                    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;
                    224:        char *          modif;
                    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;
                    240:        char *          modif;
                    241: {
                    242:        vm_size_t       size;
                    243:        db_expr_t       value;
                    244:        task_t          task;
                    245:        boolean_t       db_option();
                    246: 
                    247:        if (db_get_task(modif, &task, addr) < 0)
                    248:            return;
                    249:        if (db_expression(&value))
                    250:            size = (vm_size_t) value;
                    251:        else
                    252:            size = sizeof(int);
                    253:        db_set_watchpoint(task, addr, size);
                    254: }
                    255: 
                    256: /* list watchpoints */
                    257: void
                    258: db_listwatch_cmd()
                    259: {
                    260:        db_list_watchpoints();
                    261: }
                    262: 
                    263: void
1.1.1.3 ! root      264: db_set_watchpoints(void)
1.1       root      265: {
                    266:        register db_watchpoint_t        watch;
                    267:        vm_map_t                        map;
1.1.1.3 ! root      268:        unsigned hw_idx = 0;
1.1       root      269: 
                    270:        if (!db_watchpoints_inserted) {
                    271:            for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
1.1.1.3 ! root      272:                if (db_set_hw_watchpoint(watch, hw_idx)) {
        !           273:                    hw_idx++;
        !           274:                    continue;
        !           275:                }
1.1       root      276:                map = (watch->task)? watch->task->map: kernel_map;
                    277:                pmap_protect(map->pmap,
                    278:                             trunc_page(watch->loaddr),
                    279:                             round_page(watch->hiaddr),
                    280:                             VM_PROT_READ);
                    281:            }
                    282:            db_watchpoints_inserted = TRUE;
                    283:        }
                    284: }
                    285: 
                    286: void
1.1.1.3 ! root      287: db_clear_watchpoints(void)
1.1       root      288: {
1.1.1.3 ! root      289:        unsigned hw_idx = 0;
        !           290: 
        !           291:        while (db_clear_hw_watchpoint(hw_idx))
        !           292:            hw_idx++;
        !           293: 
1.1       root      294:        db_watchpoints_inserted = FALSE;
                    295: }
                    296: 
                    297: boolean_t
                    298: db_find_watchpoint(map, addr, regs)
                    299:        vm_map_t        map;
                    300:        db_addr_t       addr;
                    301:        db_regs_t       *regs;
                    302: {
                    303:        register db_watchpoint_t watch;
                    304:        db_watchpoint_t found = 0;
                    305:        register task_t task_space;
                    306: 
                    307:        task_space = (map == kernel_map)? TASK_NULL: db_current_task();
                    308:        for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
                    309:            if (watch->task == task_space) {
                    310:                if ((watch->loaddr <= addr) && (addr < watch->hiaddr))
                    311:                    return (TRUE);
                    312:                else if ((trunc_page(watch->loaddr) <= addr) &&
                    313:                         (addr < round_page(watch->hiaddr)))
                    314:                    found = watch;
                    315:            }
                    316:        }
                    317: 
                    318:        /*
                    319:         *      We didn't hit exactly on a watchpoint, but we are
                    320:         *      in a protected region.  We want to single-step
                    321:         *      and then re-protect.
                    322:         */
                    323: 
                    324:        if (found) {
                    325:            db_watchpoints_inserted = FALSE;
                    326:            db_single_step(regs, task_space);
                    327:        }
                    328: 
                    329:        return (FALSE);
                    330: }
                    331: 
1.1.1.2   root      332: #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.