[BACK]Return to db_break.c CVS log [TXT][DIR] Up to [local] / sys / ddb

Annotation of sys/ddb/db_break.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: db_break.c,v 1.13 2006/03/13 06:23:20 jsg Exp $       */
                      2: /*     $NetBSD: db_break.c,v 1.7 1996/03/30 22:30:03 christos Exp $    */
                      3:
                      4: /*
                      5:  * Mach Operating System
                      6:  * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
                      7:  * All Rights Reserved.
                      8:  *
                      9:  * Permission to use, copy, modify and distribute this software and its
                     10:  * documentation is hereby granted, provided that both the copyright
                     11:  * notice and this permission notice appear in all copies of the
                     12:  * software, derivative works or modified versions, and any portions
                     13:  * thereof, and that both notices appear in supporting documentation.
                     14:  *
                     15:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     16:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     17:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     18:  *
                     19:  * Carnegie Mellon requests users of this software to return to
                     20:  *
                     21:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
                     22:  *  School of Computer Science
                     23:  *  Carnegie Mellon University
                     24:  *  Pittsburgh PA 15213-3890
                     25:  *
                     26:  * any improvements or extensions that they make and grant Carnegie Mellon
                     27:  * the rights to redistribute these changes.
                     28:  *
                     29:  *     Author: David B. Golub, Carnegie Mellon University
                     30:  *     Date:   7/90
                     31:  */
                     32:
                     33: /*
                     34:  * Breakpoints.
                     35:  */
                     36: #include <sys/param.h>
                     37: #include <sys/proc.h>
                     38:
                     39: #include <uvm/uvm_extern.h>
                     40:
                     41: #include <machine/db_machdep.h>                /* type definitions */
                     42:
                     43: #include <ddb/db_lex.h>
                     44: #include <ddb/db_access.h>
                     45: #include <ddb/db_sym.h>
                     46: #include <ddb/db_break.h>
                     47: #include <ddb/db_output.h>
                     48:
                     49: #define        NBREAKPOINTS    100
                     50: struct db_breakpoint   db_break_table[NBREAKPOINTS];
                     51: db_breakpoint_t                db_next_free_breakpoint = &db_break_table[0];
                     52: db_breakpoint_t                db_free_breakpoints = 0;
                     53: db_breakpoint_t                db_breakpoint_list = 0;
                     54:
                     55: db_breakpoint_t
                     56: db_breakpoint_alloc(void)
                     57: {
                     58:        db_breakpoint_t bkpt;
                     59:
                     60:        if ((bkpt = db_free_breakpoints) != 0) {
                     61:            db_free_breakpoints = bkpt->link;
                     62:            return (bkpt);
                     63:        }
                     64:        if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) {
                     65:            db_printf("All breakpoints used.\n");
                     66:            return (0);
                     67:        }
                     68:        bkpt = db_next_free_breakpoint;
                     69:        db_next_free_breakpoint++;
                     70:
                     71:        return (bkpt);
                     72: }
                     73:
                     74: void
                     75: db_breakpoint_free(db_breakpoint_t bkpt)
                     76: {
                     77:        bkpt->link = db_free_breakpoints;
                     78:        db_free_breakpoints = bkpt;
                     79: }
                     80:
                     81: void
                     82: db_set_breakpoint(struct vm_map *map, db_addr_t addr, int count)
                     83: {
                     84:        db_breakpoint_t bkpt;
                     85:
                     86:        if (db_find_breakpoint(map, addr)) {
                     87:            db_printf("Already set.\n");
                     88:            return;
                     89:        }
                     90:
                     91: #ifdef DB_VALID_BREAKPOINT
                     92:        if (!DB_VALID_BREAKPOINT(addr)) {
                     93:                db_printf("Not a valid address for a breakpoint.\n");
                     94:                return;
                     95:        }
                     96: #endif
                     97:
                     98:        bkpt = db_breakpoint_alloc();
                     99:        if (bkpt == 0) {
                    100:            db_printf("Too many breakpoints.\n");
                    101:            return;
                    102:        }
                    103:
                    104:        bkpt->map = map;
                    105:        bkpt->address = addr;
                    106:        bkpt->flags = 0;
                    107:        bkpt->init_count = count;
                    108:        bkpt->count = count;
                    109:
                    110:        bkpt->link = db_breakpoint_list;
                    111:        db_breakpoint_list = bkpt;
                    112: }
                    113:
                    114: void
                    115: db_delete_breakpoint(struct vm_map *map, db_addr_t addr)
                    116: {
                    117:        db_breakpoint_t bkpt;
                    118:        db_breakpoint_t *prev;
                    119:
                    120:        for (prev = &db_breakpoint_list;
                    121:             (bkpt = *prev) != 0;
                    122:             prev = &bkpt->link) {
                    123:            if (db_map_equal(bkpt->map, map) &&
                    124:                (bkpt->address == addr)) {
                    125:                *prev = bkpt->link;
                    126:                break;
                    127:            }
                    128:        }
                    129:        if (bkpt == 0) {
                    130:            db_printf("Not set.\n");
                    131:            return;
                    132:        }
                    133:
                    134:        db_breakpoint_free(bkpt);
                    135: }
                    136:
                    137: db_breakpoint_t
                    138: db_find_breakpoint(struct vm_map *map, db_addr_t addr)
                    139: {
                    140:        db_breakpoint_t bkpt;
                    141:
                    142:        for (bkpt = db_breakpoint_list;
                    143:             bkpt != 0;
                    144:             bkpt = bkpt->link)
                    145:        {
                    146:            if (db_map_equal(bkpt->map, map) &&
                    147:                (bkpt->address == addr))
                    148:                return (bkpt);
                    149:        }
                    150:        return (0);
                    151: }
                    152:
                    153: db_breakpoint_t
                    154: db_find_breakpoint_here(db_addr_t addr)
                    155: {
                    156:     return db_find_breakpoint(db_map_addr(addr), addr);
                    157: }
                    158:
                    159: boolean_t      db_breakpoints_inserted = TRUE;
                    160:
                    161: void
                    162: db_set_breakpoints(void)
                    163: {
                    164:        db_breakpoint_t bkpt;
                    165:
                    166:        if (!db_breakpoints_inserted) {
                    167:
                    168:            for (bkpt = db_breakpoint_list;
                    169:                 bkpt != 0;
                    170:                 bkpt = bkpt->link)
                    171:                if (db_map_current(bkpt->map)) {
                    172:                    bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE,
                    173:                        FALSE);
                    174:                    db_put_value(bkpt->address, BKPT_SIZE,
                    175:                        BKPT_SET(bkpt->bkpt_inst));
                    176:                }
                    177:            db_breakpoints_inserted = TRUE;
                    178:        }
                    179: }
                    180:
                    181: void
                    182: db_clear_breakpoints(void)
                    183: {
                    184:        db_breakpoint_t bkpt;
                    185:
                    186:        if (db_breakpoints_inserted) {
                    187:
                    188:            for (bkpt = db_breakpoint_list;
                    189:                 bkpt != 0;
                    190:                 bkpt = bkpt->link)
                    191:                if (db_map_current(bkpt->map)) {
                    192:                    db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
                    193:                }
                    194:            db_breakpoints_inserted = FALSE;
                    195:        }
                    196: }
                    197:
                    198: /*
                    199:  * Set a temporary breakpoint.
                    200:  * The instruction is changed immediately,
                    201:  * so the breakpoint does not have to be on the breakpoint list.
                    202:  */
                    203: db_breakpoint_t
                    204: db_set_temp_breakpoint(db_addr_t addr)
                    205: {
                    206:        db_breakpoint_t bkpt;
                    207:
                    208: #ifdef DB_VALID_BREAKPOINT
                    209:        if (!DB_VALID_BREAKPOINT(addr)) {
                    210:                db_printf("Not a valid address for a breakpoint.\n");
                    211:                return (0);
                    212:        }
                    213: #endif
                    214:
                    215:        bkpt = db_breakpoint_alloc();
                    216:        if (bkpt == 0) {
                    217:            db_printf("Too many breakpoints.\n");
                    218:            return (0);
                    219:        }
                    220:
                    221:        bkpt->map = NULL;
                    222:        bkpt->address = addr;
                    223:        bkpt->flags = BKPT_TEMP;
                    224:        bkpt->init_count = 1;
                    225:        bkpt->count = 1;
                    226:
                    227:        bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE);
                    228:        db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst));
                    229:        return bkpt;
                    230: }
                    231:
                    232: void
                    233: db_delete_temp_breakpoint(db_breakpoint_t bkpt)
                    234: {
                    235:        db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
                    236:        db_breakpoint_free(bkpt);
                    237: }
                    238:
                    239: /*
                    240:  * List breakpoints.
                    241:  */
                    242: void
                    243: db_list_breakpoints(void)
                    244: {
                    245:        db_breakpoint_t bkpt;
                    246:
                    247:        if (db_breakpoint_list == 0) {
                    248:            db_printf("No breakpoints set\n");
                    249:            return;
                    250:        }
                    251:
                    252:        db_printf(" Map      Count    Address\n");
                    253:        for (bkpt = db_breakpoint_list;
                    254:             bkpt != 0;
                    255:             bkpt = bkpt->link)
                    256:        {
                    257:            db_printf("%s%p %5d    ",
                    258:                      db_map_current(bkpt->map) ? "*" : " ",
                    259:                      bkpt->map, bkpt->init_count);
                    260:            db_printsym(bkpt->address, DB_STGY_PROC, db_printf);
                    261:            db_printf("\n");
                    262:        }
                    263: }
                    264:
                    265: /* Delete breakpoint */
                    266: /*ARGSUSED*/
                    267: void
                    268: db_delete_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
                    269: {
                    270:        db_delete_breakpoint(db_map_addr(addr), (db_addr_t)addr);
                    271: }
                    272:
                    273: /* Set breakpoint with skip count */
                    274: /*ARGSUSED*/
                    275: void
                    276: db_breakpoint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
                    277: {
                    278:        if (count == -1)
                    279:            count = 1;
                    280:
                    281:        db_set_breakpoint(db_map_addr(addr), (db_addr_t)addr, count);
                    282: }
                    283:
                    284: /* list breakpoints */
                    285: /*ARGSUSED*/
                    286: void
                    287: db_listbreak_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
                    288: {
                    289:        db_list_breakpoints();
                    290: }
                    291:
                    292: /*
                    293:  *     We want ddb to be usable before most of the kernel has been
                    294:  *     initialized.  In particular, current_thread() or kernel_map
                    295:  *     (or both) may be null.
                    296:  */
                    297:
                    298: boolean_t
                    299: db_map_equal(struct vm_map *map1, struct vm_map *map2)
                    300: {
                    301:        return ((map1 == map2) ||
                    302:                ((map1 == NULL) && (map2 == kernel_map)) ||
                    303:                ((map1 == kernel_map) && (map2 == NULL)));
                    304: }
                    305:
                    306: boolean_t
                    307: db_map_current(struct vm_map *map)
                    308: {
                    309: #if 0
                    310:        thread_t        thread;
                    311:
                    312:        return ((map == NULL) ||
                    313:                (map == kernel_map) ||
                    314:                (((thread = current_thread()) != NULL) &&
                    315:                 (map == thread->proc->map)));
                    316: #else
                    317:        return (1);
                    318: #endif
                    319: }
                    320:
                    321: struct vm_map *
                    322: db_map_addr(vaddr_t addr)
                    323: {
                    324: #if 0
                    325:        thread_t        thread;
                    326:
                    327:        /*
                    328:         *      We want to return kernel_map for all
                    329:         *      non-user addresses, even when debugging
                    330:         *      kernel tasks with their own maps.
                    331:         */
                    332:
                    333:        if ((VM_MIN_ADDRESS <= addr) &&
                    334:            (addr < VM_MAX_ADDRESS) &&
                    335:            ((thread = current_thread()) != NULL))
                    336:            return thread->proc->map;
                    337:        else
                    338: #endif
                    339:            return kernel_map;
                    340: }

CVSweb