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

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