Annotation of Gnu-Mach/ddb/db_break.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: David B. Golub, Carnegie Mellon University
                     28:  *     Date:   7/90
                     29:  */
1.1.1.3 ! root       30: 
1.1       root       31: #if MACH_KDB
                     32: 
                     33: 
                     34: /*
                     35:  * Breakpoints.
                     36:  */
                     37: #include <mach/boolean.h>
                     38: #include <machine/db_machdep.h>
                     39: #include <ddb/db_lex.h>
                     40: #include <ddb/db_break.h>
                     41: #include <ddb/db_access.h>
                     42: #include <ddb/db_sym.h>
                     43: #include <ddb/db_variables.h>
                     44: #include <ddb/db_command.h>
                     45: #include <ddb/db_task_thread.h>
1.1.1.3 ! root       46: #include <ddb/db_output.h>
        !            47: #include <ddb/db_cond.h>
        !            48: #include <ddb/db_expr.h>
        !            49: #include <ddb/db_access.h>
1.1       root       50: 
                     51: #define        NBREAKPOINTS    100
                     52: #define NTHREAD_LIST   (NBREAKPOINTS*3)
                     53: 
                     54: struct db_breakpoint   db_break_table[NBREAKPOINTS];
                     55: db_breakpoint_t                db_next_free_breakpoint = &db_break_table[0];
                     56: db_breakpoint_t                db_free_breakpoints = 0;
                     57: db_breakpoint_t                db_breakpoint_list = 0;
                     58: 
                     59: static struct db_thread_breakpoint     db_thread_break_list[NTHREAD_LIST];
                     60: static db_thread_breakpoint_t          db_free_thread_break_list = 0;
                     61: static boolean_t                       db_thread_break_init = FALSE;
                     62: static int                             db_breakpoint_number = 0;
                     63: 
                     64: db_breakpoint_t
                     65: db_breakpoint_alloc()
                     66: {
                     67:        register db_breakpoint_t        bkpt;
                     68: 
                     69:        if ((bkpt = db_free_breakpoints) != 0) {
                     70:            db_free_breakpoints = bkpt->link;
                     71:            return (bkpt);
                     72:        }
                     73:        if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) {
                     74:            db_printf("All breakpoints used.\n");
                     75:            return (0);
                     76:        }
                     77:        bkpt = db_next_free_breakpoint;
                     78:        db_next_free_breakpoint++;
                     79: 
                     80:        return (bkpt);
                     81: }
                     82: 
                     83: void
                     84: db_breakpoint_free(bkpt)
                     85:        register db_breakpoint_t        bkpt;
                     86: {
                     87:        bkpt->link = db_free_breakpoints;
                     88:        db_free_breakpoints = bkpt;
                     89: }
                     90: 
                     91: static int
                     92: db_add_thread_breakpoint(bkpt, task_thd, count, task_bpt)
                     93:        register db_breakpoint_t bkpt;
                     94:        vm_offset_t task_thd;
                     95:        boolean_t task_bpt;
                     96: {
                     97:        register db_thread_breakpoint_t tp;
                     98: 
                     99:        if (db_thread_break_init == FALSE) {
1.1.1.2   root      100:            for (tp = db_thread_break_list;
1.1       root      101:                tp < &db_thread_break_list[NTHREAD_LIST-1]; tp++)
                    102:                tp->tb_next = tp+1;
                    103:            tp->tb_next = 0;
                    104:            db_free_thread_break_list = db_thread_break_list;
                    105:            db_thread_break_init = TRUE;
                    106:        }
                    107:        if (db_free_thread_break_list == 0)
                    108:            return (-1);
                    109:        tp = db_free_thread_break_list;
                    110:        db_free_thread_break_list = tp->tb_next;
                    111:        tp->tb_is_task = task_bpt;
                    112:        tp->tb_task_thd = task_thd;
                    113:        tp->tb_count = count;
                    114:        tp->tb_init_count = count;
                    115:        tp->tb_cond = 0;
                    116:        tp->tb_number = ++db_breakpoint_number;
                    117:        tp->tb_next = bkpt->threads;
                    118:        bkpt->threads = tp;
                    119:        return(0);
                    120: }
                    121: 
                    122: static int
                    123: db_delete_thread_breakpoint(bkpt, task_thd)
                    124:        register db_breakpoint_t bkpt;
                    125:        vm_offset_t task_thd;
                    126: {
                    127:        register db_thread_breakpoint_t tp;
                    128:        register db_thread_breakpoint_t *tpp;
                    129: 
                    130:        if (task_thd == 0) {
                    131:            /* delete all the thread-breakpoints */
                    132: 
                    133:            for (tpp = &bkpt->threads; (tp = *tpp) != 0; tpp = &tp->tb_next)
                    134:                db_cond_free(tp);
                    135: 
                    136:            *tpp = db_free_thread_break_list;
                    137:            db_free_thread_break_list = bkpt->threads;
                    138:            bkpt->threads = 0;
                    139:            return 0;
                    140:        } else {
                    141:            /* delete the specified thread-breakpoint */
                    142: 
                    143:            for (tpp = &bkpt->threads; (tp = *tpp) != 0; tpp = &tp->tb_next)
                    144:                if (tp->tb_task_thd == task_thd) {
                    145:                    db_cond_free(tp);
                    146:                    *tpp = tp->tb_next;
                    147:                    tp->tb_next = db_free_thread_break_list;
                    148:                    db_free_thread_break_list = tp;
                    149:                    return 0;
                    150:                }
                    151: 
                    152:            return -1;  /* not found */
                    153:        }
                    154: }
                    155: 
                    156: static db_thread_breakpoint_t
                    157: db_find_thread_breakpoint(bkpt, thread)
                    158:        db_breakpoint_t bkpt;
                    159:        thread_t thread;
                    160: {
                    161:        register db_thread_breakpoint_t tp;
                    162:        register task_t task = (thread == THREAD_NULL)? TASK_NULL: thread->task;
                    163: 
                    164:        for (tp = bkpt->threads; tp; tp = tp->tb_next) {
                    165:            if (tp->tb_is_task) {
                    166:                if (tp->tb_task_thd == (vm_offset_t)task)
                    167:                    break;
                    168:                continue;
                    169:            }
                    170:            if (tp->tb_task_thd == (vm_offset_t)thread || tp->tb_task_thd == 0)
                    171:                break;
                    172:        }
                    173:        return(tp);
                    174: }
                    175: 
                    176: db_thread_breakpoint_t
                    177: db_find_thread_breakpoint_here(task, addr)
                    178:        task_t          task;
                    179:        db_addr_t       addr;
                    180: {
                    181:        db_breakpoint_t bkpt;
                    182: 
                    183:        bkpt = db_find_breakpoint(task, (db_addr_t)addr);
                    184:        if (bkpt == 0)
                    185:            return(0);
                    186:        return(db_find_thread_breakpoint(bkpt, current_thread()));
                    187: }
                    188: 
                    189: db_thread_breakpoint_t
                    190: db_find_breakpoint_number(num, bkptp)
                    191:        int num;
                    192:        db_breakpoint_t *bkptp;
                    193: {
                    194:        register db_thread_breakpoint_t tp;
                    195:        register db_breakpoint_t bkpt;
                    196: 
                    197:        for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) {
                    198:            for (tp = bkpt->threads; tp; tp = tp->tb_next) {
                    199:                if (tp->tb_number == num) {
                    200:                    if (bkptp)
                    201:                        *bkptp = bkpt;
                    202:                    return(tp);
                    203:                }
                    204:            }
                    205:        }
                    206:        return(0);
                    207: }
                    208: 
                    209: static void
                    210: db_force_delete_breakpoint(bkpt, task_thd, is_task)
                    211:        db_breakpoint_t bkpt;
                    212:        vm_offset_t  task_thd;
                    213:        boolean_t is_task;
                    214: {
                    215:        db_printf("deleted a stale breakpoint at ");
                    216:        if (bkpt->task == TASK_NULL || db_lookup_task(bkpt->task) >= 0)
                    217:           db_task_printsym(bkpt->address, DB_STGY_PROC, bkpt->task);
                    218:        else
                    219:           db_printf("%#X", bkpt->address);
                    220:        if (bkpt->task)
                    221:           db_printf(" in task %X", bkpt->task);
                    222:        if (task_thd)
                    223:           db_printf(" for %s %X", (is_task)? "task": "thread", task_thd);
                    224:        db_printf("\n");
                    225:        db_delete_thread_breakpoint(bkpt, task_thd);
                    226: }
                    227: 
                    228: void
                    229: db_check_breakpoint_valid()
                    230: {
                    231:        register db_thread_breakpoint_t tbp, tbp_next;
                    232:        register db_breakpoint_t bkpt, *bkptp;
                    233: 
                    234:        bkptp = &db_breakpoint_list;
                    235:        for (bkpt = *bkptp; bkpt; bkpt = *bkptp) {
                    236:            if (bkpt->task != TASK_NULL) {
                    237:                if (db_lookup_task(bkpt->task) < 0) {
                    238:                    db_force_delete_breakpoint(bkpt, 0, FALSE);
                    239:                    *bkptp = bkpt->link;
                    240:                    db_breakpoint_free(bkpt);
                    241:                    continue;
                    242:                }
                    243:            } else {
                    244:                for (tbp = bkpt->threads; tbp; tbp = tbp_next) {
                    245:                    tbp_next = tbp->tb_next;
                    246:                    if (tbp->tb_task_thd == 0)
                    247:                        continue;
1.1.1.2   root      248:                    if ((tbp->tb_is_task &&
1.1       root      249:                         db_lookup_task((task_t)(tbp->tb_task_thd)) < 0) ||
1.1.1.2   root      250:                        (!tbp->tb_is_task &&
1.1       root      251:                         db_lookup_thread((thread_t)(tbp->tb_task_thd)) < 0)) {
1.1.1.2   root      252:                        db_force_delete_breakpoint(bkpt,
1.1       root      253:                                        tbp->tb_task_thd, tbp->tb_is_task);
                    254:                    }
                    255:                }
                    256:                if (bkpt->threads == 0) {
                    257:                    db_put_task_value(bkpt->address, BKPT_SIZE,
                    258:                                 bkpt->bkpt_inst, bkpt->task);
                    259:                    *bkptp = bkpt->link;
                    260:                    db_breakpoint_free(bkpt);
                    261:                    continue;
                    262:                }
                    263:            }
                    264:            bkptp = &bkpt->link;
                    265:        }
                    266: }
                    267: 
1.1.1.3 ! root      268: db_breakpoint_t
1.1       root      269: db_set_breakpoint(task, addr, count, thread, task_bpt)
                    270:        task_t          task;
                    271:        db_addr_t       addr;
                    272:        int             count;
                    273:        thread_t        thread;
                    274:        boolean_t       task_bpt;
                    275: {
                    276:        register db_breakpoint_t bkpt;
                    277:        db_breakpoint_t alloc_bkpt = 0;
                    278:        vm_offset_t task_thd;
                    279: 
                    280:        bkpt = db_find_breakpoint(task, addr);
                    281:        if (bkpt) {
                    282:            if (thread == THREAD_NULL
                    283:                || db_find_thread_breakpoint(bkpt, thread)) {
                    284:                db_printf("Already set.\n");
1.1.1.3 ! root      285:                return NULL;
1.1       root      286:            }
                    287:        } else {
                    288:            if (!DB_CHECK_ACCESS(addr, BKPT_SIZE, task)) {
                    289:                db_printf("Cannot set break point at %X\n", addr);
1.1.1.3 ! root      290:                return NULL;
1.1       root      291:            }
                    292:            alloc_bkpt = bkpt = db_breakpoint_alloc();
                    293:            if (bkpt == 0) {
                    294:                db_printf("Too many breakpoints.\n");
1.1.1.3 ! root      295:                return NULL;
1.1       root      296:            }
                    297:            bkpt->task = task;
                    298:            bkpt->flags = (task && thread == THREAD_NULL)?
                    299:                                (BKPT_USR_GLOBAL|BKPT_1ST_SET): 0;
                    300:            bkpt->address = addr;
                    301:            bkpt->threads = 0;
                    302:        }
                    303:        if (db_breakpoint_list == 0)
                    304:            db_breakpoint_number = 0;
                    305:        task_thd = (task_bpt)? (vm_offset_t)(thread->task): (vm_offset_t)thread;
                    306:        if (db_add_thread_breakpoint(bkpt, task_thd, count, task_bpt) < 0) {
                    307:            if (alloc_bkpt)
                    308:                db_breakpoint_free(alloc_bkpt);
                    309:            db_printf("Too many thread_breakpoints.\n");
1.1.1.3 ! root      310:            return NULL;
1.1       root      311:        } else {
                    312:            db_printf("set breakpoint #%d\n", db_breakpoint_number);
                    313:            if (alloc_bkpt) {
                    314:                bkpt->link = db_breakpoint_list;
                    315:                db_breakpoint_list = bkpt;
                    316:            }
1.1.1.3 ! root      317:            return bkpt;
1.1       root      318:        }
                    319: }
                    320: 
                    321: void
                    322: db_delete_breakpoint(task, addr, task_thd)
                    323:        task_t  task;
                    324:        db_addr_t       addr;
                    325:        vm_offset_t     task_thd;
                    326: {
                    327:        register db_breakpoint_t        bkpt;
                    328:        register db_breakpoint_t        *prev;
                    329: 
                    330:        for (prev = &db_breakpoint_list; (bkpt = *prev) != 0;
                    331:                                             prev = &bkpt->link) {
                    332:            if ((bkpt->task == task
                    333:                   || (task != TASK_NULL && (bkpt->flags & BKPT_USR_GLOBAL)))
                    334:                && bkpt->address == addr)
                    335:                break;
                    336:        }
                    337:        if (bkpt && (bkpt->flags & BKPT_SET_IN_MEM)) {
                    338:            db_printf("cannot delete it now.\n");
                    339:            return;
                    340:        }
                    341:        if (bkpt == 0
                    342:            || db_delete_thread_breakpoint(bkpt, task_thd) < 0) {
                    343:            db_printf("Not set.\n");
                    344:            return;
                    345:        }
                    346:        if (bkpt->threads == 0) {
                    347:            *prev = bkpt->link;
                    348:            db_breakpoint_free(bkpt);
                    349:        }
                    350: }
                    351: 
                    352: db_breakpoint_t
                    353: db_find_breakpoint(task, addr)
                    354:        task_t  task;
                    355:        db_addr_t       addr;
                    356: {
                    357:        register db_breakpoint_t        bkpt;
                    358: 
                    359:        for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) {
                    360:            if ((bkpt->task == task
                    361:                  || (task != TASK_NULL && (bkpt->flags & BKPT_USR_GLOBAL)))
                    362:                && bkpt->address == addr)
                    363:                return (bkpt);
                    364:        }
                    365:        return (0);
                    366: }
                    367: 
                    368: boolean_t
                    369: db_find_breakpoint_here(task, addr)
                    370:        task_t          task;
                    371:        db_addr_t       addr;
                    372: {
                    373:        register db_breakpoint_t        bkpt;
                    374: 
                    375:        for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) {
                    376:            if ((bkpt->task == task
                    377:                   || (task != TASK_NULL && (bkpt->flags & BKPT_USR_GLOBAL)))
                    378:                 && bkpt->address == addr)
                    379:                return(TRUE);
                    380:            if ((bkpt->flags & BKPT_USR_GLOBAL) == 0 &&
                    381:                  DB_PHYS_EQ(task, (vm_offset_t)addr, bkpt->task, (vm_offset_t)bkpt->address))
                    382:                return (TRUE);
                    383:        }
                    384:        return(FALSE);
                    385: }
                    386: 
                    387: boolean_t      db_breakpoints_inserted = TRUE;
                    388: 
                    389: void
1.1.1.3 ! root      390: db_set_breakpoints(void)
1.1       root      391: {
                    392:        register db_breakpoint_t bkpt;
                    393:        register task_t task;
                    394:        db_expr_t       inst;
                    395:        task_t          cur_task;
                    396: 
                    397:        cur_task = (current_thread())? current_thread()->task: TASK_NULL;
                    398:        if (!db_breakpoints_inserted) {
                    399:            for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) {
                    400:                if (bkpt->flags & BKPT_SET_IN_MEM)
                    401:                    continue;
                    402:                task = bkpt->task;
                    403:                if (bkpt->flags & BKPT_USR_GLOBAL) {
                    404:                    if ((bkpt->flags & BKPT_1ST_SET) == 0) {
                    405:                        if (cur_task == TASK_NULL)
                    406:                            continue;
                    407:                        task = cur_task;
                    408:                    } else
                    409:                        bkpt->flags &= ~BKPT_1ST_SET;
                    410:                }
                    411:                if (DB_CHECK_ACCESS(bkpt->address, BKPT_SIZE, task)) {
                    412:                    inst = db_get_task_value(bkpt->address, BKPT_SIZE, FALSE,
                    413:                                                                task);
                    414:                    if (inst == BKPT_SET(inst))
                    415:                        continue;
                    416:                    bkpt->bkpt_inst = inst;
                    417:                    db_put_task_value(bkpt->address,
                    418:                                BKPT_SIZE,
                    419:                                BKPT_SET(bkpt->bkpt_inst), task);
                    420:                    bkpt->flags |= BKPT_SET_IN_MEM;
                    421:                } else {
1.1.1.2   root      422:                    db_printf("Warning: cannot set breakpoint at %X ",
1.1       root      423:                                bkpt->address);
                    424:                    if (task)
                    425:                        db_printf("in task %X\n", task);
                    426:                    else
                    427:                        db_printf("in kernel space\n");
                    428:                }
                    429:            }
                    430:            db_breakpoints_inserted = TRUE;
                    431:        }
                    432: }
                    433: 
                    434: void
1.1.1.3 ! root      435: db_clear_breakpoints(void)
1.1       root      436: {
                    437:        register db_breakpoint_t bkpt, *bkptp;
                    438:        register task_t task;
                    439:        task_t          cur_task;
                    440:        db_expr_t       inst;
                    441: 
                    442:        cur_task = (current_thread())? current_thread()->task: TASK_NULL;
                    443:        if (db_breakpoints_inserted) {
                    444:            bkptp = &db_breakpoint_list;
                    445:            for (bkpt = *bkptp; bkpt; bkpt = *bkptp) {
                    446:                task = bkpt->task;
                    447:                if (bkpt->flags & BKPT_USR_GLOBAL) {
                    448:                    if (cur_task == TASK_NULL) {
                    449:                        bkptp = &bkpt->link;
                    450:                        continue;
                    451:                    }
                    452:                    task = cur_task;
                    453:                }
                    454:                if ((bkpt->flags & BKPT_SET_IN_MEM)
                    455:                    && DB_CHECK_ACCESS(bkpt->address, BKPT_SIZE, task)) {
1.1.1.2   root      456:                    inst = db_get_task_value(bkpt->address, BKPT_SIZE, FALSE,
1.1       root      457:                                                                task);
                    458:                    if (inst != BKPT_SET(inst)) {
                    459:                        if (bkpt->flags & BKPT_USR_GLOBAL) {
                    460:                            bkptp = &bkpt->link;
                    461:                            continue;
                    462:                        }
                    463:                        db_force_delete_breakpoint(bkpt, 0, FALSE);
                    464:                        *bkptp = bkpt->link;
                    465:                        db_breakpoint_free(bkpt);
                    466:                        continue;
                    467:                    }
                    468:                    db_put_task_value(bkpt->address, BKPT_SIZE,
                    469:                                 bkpt->bkpt_inst, task);
                    470:                    bkpt->flags &= ~BKPT_SET_IN_MEM;
                    471:                }
                    472:                bkptp = &bkpt->link;
                    473:            }
                    474:            db_breakpoints_inserted = FALSE;
                    475:        }
                    476: }
                    477: 
                    478: /*
                    479:  * Set a temporary breakpoint.
                    480:  * The instruction is changed immediately,
                    481:  * so the breakpoint does not have to be on the breakpoint list.
                    482:  */
                    483: db_breakpoint_t
                    484: db_set_temp_breakpoint(task, addr)
                    485:        task_t          task;
                    486:        db_addr_t       addr;
                    487: {
                    488:        register db_breakpoint_t        bkpt;
                    489: 
                    490:        bkpt = db_breakpoint_alloc();
                    491:        if (bkpt == 0) {
                    492:            db_printf("Too many breakpoints.\n");
                    493:            return 0;
                    494:        }
                    495:        bkpt->task = task;
                    496:        bkpt->address = addr;
                    497:        bkpt->flags = BKPT_TEMP;
                    498:        bkpt->threads = 0;
                    499:        if (db_add_thread_breakpoint(bkpt, 0, 1, FALSE) < 0) {
                    500:            if (bkpt)
                    501:                db_breakpoint_free(bkpt);
                    502:            db_printf("Too many thread_breakpoints.\n");
                    503:            return 0;
                    504:        }
1.1.1.2   root      505:        bkpt->bkpt_inst = db_get_task_value(bkpt->address, BKPT_SIZE,
1.1       root      506:                                                FALSE, task);
1.1.1.2   root      507:        db_put_task_value(bkpt->address, BKPT_SIZE,
1.1       root      508:                                BKPT_SET(bkpt->bkpt_inst), task);
                    509:        return bkpt;
                    510: }
                    511: 
                    512: void
                    513: db_delete_temp_breakpoint(task, bkpt)
                    514:        task_t          task;
                    515:        db_breakpoint_t bkpt;
                    516: {
                    517:        db_put_task_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst, task);
                    518:        db_delete_thread_breakpoint(bkpt, 0);
                    519:        db_breakpoint_free(bkpt);
                    520: }
                    521: 
                    522: /*
                    523:  * List breakpoints.
                    524:  */
                    525: void
                    526: db_list_breakpoints()
                    527: {
                    528:        register db_breakpoint_t        bkpt;
                    529: 
                    530:        if (db_breakpoint_list == 0) {
                    531:            db_printf("No breakpoints set\n");
                    532:            return;
                    533:        }
                    534: 
                    535:        db_printf(" No  Space    Thread      Cnt  Address(Cond)\n");
                    536:        for (bkpt = db_breakpoint_list;
                    537:             bkpt != 0;
                    538:             bkpt = bkpt->link)
                    539:        {
                    540:            register    db_thread_breakpoint_t tp;
                    541:            int         task_id;
                    542:            int         thread_id;
                    543: 
                    544:            if (bkpt->threads) {
                    545:                for (tp = bkpt->threads; tp; tp = tp->tb_next) {
                    546:                    db_printf("%3d  ", tp->tb_number);
                    547:                    if (bkpt->flags & BKPT_USR_GLOBAL)
                    548:                        db_printf("user     ");
                    549:                    else if (bkpt->task == TASK_NULL)
                    550:                        db_printf("kernel   ");
                    551:                    else if ((task_id = db_lookup_task(bkpt->task)) < 0)
                    552:                        db_printf("%0*X ", 2*sizeof(vm_offset_t), bkpt->task);
                    553:                    else
                    554:                        db_printf("task%-3d  ", task_id);
                    555:                    if (tp->tb_task_thd == 0) {
                    556:                        db_printf("all         ");
                    557:                    } else {
                    558:                        if (tp->tb_is_task) {
                    559:                            task_id = db_lookup_task((task_t)(tp->tb_task_thd));
                    560:                            if (task_id < 0)
                    561:                                db_printf("%0*X    ", 2*sizeof(vm_offset_t),
                    562:                                           tp->tb_task_thd);
                    563:                            else
                    564:                                db_printf("task%03d     ", task_id);
                    565:                        } else {
                    566:                            thread_t thd = (thread_t)(tp->tb_task_thd);
                    567:                            task_id = db_lookup_task(thd->task);
                    568:                            thread_id = db_lookup_task_thread(thd->task, thd);
                    569:                            if (task_id < 0 || thread_id < 0)
                    570:                                db_printf("%0*X    ", 2*sizeof(vm_offset_t),
                    571:                                           tp->tb_task_thd);
1.1.1.2   root      572:                            else
1.1       root      573:                                db_printf("task%03d.%-3d ", task_id, thread_id);
                    574:                        }
                    575:                    }
                    576:                    db_printf("%3d  ", tp->tb_init_count);
                    577:                    db_task_printsym(bkpt->address, DB_STGY_PROC, bkpt->task);
                    578:                    if (tp->tb_cond > 0) {
                    579:                        db_printf("(");
                    580:                        db_cond_print(tp);
                    581:                        db_printf(")");
                    582:                    }
                    583:                    db_printf("\n");
                    584:                }
                    585:            } else {
                    586:                if (bkpt->task == TASK_NULL)
                    587:                    db_printf("  ?  kernel   ");
                    588:                else
                    589:                    db_printf("%*X ", 2*sizeof(vm_offset_t), bkpt->task);
                    590:                db_printf("(?)              ");
                    591:                db_task_printsym(bkpt->address, DB_STGY_PROC, bkpt->task);
                    592:                db_printf("\n");
                    593:            }
                    594:        }
                    595: }
                    596: 
                    597: /* Delete breakpoint */
                    598: /*ARGSUSED*/
                    599: void
                    600: db_delete_cmd()
                    601: {
1.1.1.3 ! root      602:        register int n;
1.1       root      603:        thread_t thread;
                    604:        vm_offset_t task_thd;
                    605:        boolean_t user_global = FALSE;
                    606:        boolean_t task_bpt = FALSE;
                    607:        boolean_t user_space = FALSE;
                    608:        boolean_t thd_bpt = FALSE;
                    609:        db_expr_t addr;
                    610:        int t;
1.1.1.2   root      611: 
1.1       root      612:        t = db_read_token();
                    613:        if (t == tSLASH) {
                    614:            t = db_read_token();
                    615:            if (t != tIDENT) {
                    616:                db_printf("Bad modifier \"%s\"\n", db_tok_string);
                    617:                db_error(0);
                    618:            }
                    619:            user_global = db_option(db_tok_string, 'U');
                    620:            user_space = (user_global)? TRUE: db_option(db_tok_string, 'u');
                    621:            task_bpt = db_option(db_tok_string, 'T');
                    622:            thd_bpt = db_option(db_tok_string, 't');
                    623:            if (task_bpt && user_global)
                    624:                db_error("Cannot specify both 'T' and 'U' option\n");
                    625:            t = db_read_token();
                    626:        }
                    627:        if (t == tHASH) {
                    628:            db_thread_breakpoint_t tbp;
                    629:            db_breakpoint_t bkpt;
                    630: 
                    631:            if (db_read_token() != tNUMBER) {
                    632:                db_printf("Bad break point number #%s\n", db_tok_string);
                    633:                db_error(0);
                    634:            }
                    635:            if ((tbp = db_find_breakpoint_number(db_tok_number, &bkpt)) == 0) {
                    636:                db_printf("No such break point #%d\n", db_tok_number);
                    637:                db_error(0);
                    638:            }
                    639:            db_delete_breakpoint(bkpt->task, bkpt->address, tbp->tb_task_thd);
                    640:            return;
                    641:        }
                    642:        db_unread_token(t);
                    643:        if (!db_expression(&addr)) {
                    644:            /*
                    645:             *  We attempt to pick up the user_space indication from db_dot,
                    646:             *  so that a plain "d" always works.
                    647:             */
                    648:            addr = (db_expr_t)db_dot;
                    649:            if (!user_space && !DB_VALID_ADDRESS((vm_offset_t)addr, FALSE))
                    650:                user_space = TRUE;
                    651:        }
                    652:        if (!DB_VALID_ADDRESS((vm_offset_t) addr, user_space)) {
1.1.1.2   root      653:            db_printf("Address %#X is not in %s space\n", addr,
1.1       root      654:                        (user_space)? "user": "kernel");
                    655:            db_error(0);
                    656:        }
                    657:        if (thd_bpt || task_bpt) {
                    658:            for (n = 0; db_get_next_thread(&thread, n); n++) {
                    659:                if (thread == THREAD_NULL)
                    660:                    db_error("No active thread\n");
                    661:                if (task_bpt) {
                    662:                    if (thread->task == TASK_NULL)
                    663:                        db_error("No task\n");
                    664:                    task_thd = (vm_offset_t) (thread->task);
                    665:                } else
                    666:                    task_thd = (user_global)? 0: (vm_offset_t) thread;
                    667:                db_delete_breakpoint(db_target_space(thread, user_space),
                    668:                                        (db_addr_t)addr, task_thd);
                    669:            }
                    670:        } else {
                    671:            db_delete_breakpoint(db_target_space(THREAD_NULL, user_space),
                    672:                                         (db_addr_t)addr, 0);
                    673:        }
                    674: }
                    675: 
                    676: /* Set breakpoint with skip count */
                    677: /*ARGSUSED*/
                    678: void
                    679: db_breakpoint_cmd(addr, have_addr, count, modif)
                    680:        db_expr_t       addr;
                    681:        int             have_addr;
                    682:        db_expr_t       count;
                    683:        char *          modif;
                    684: {
1.1.1.3 ! root      685:        register int n;
1.1       root      686:        thread_t thread;
                    687:        boolean_t user_global = db_option(modif, 'U');
                    688:        boolean_t task_bpt = db_option(modif, 'T');
                    689:        boolean_t user_space;
                    690: 
                    691:        if (count == -1)
                    692:            count = 1;
                    693: 
                    694:        if (!task_bpt && db_option(modif,'t'))
                    695:          task_bpt = TRUE;
                    696: 
                    697:        if (task_bpt && user_global)
                    698:            db_error("Cannot specify both 'T' and 'U'\n");
                    699:        user_space = (user_global)? TRUE: db_option(modif, 'u');
                    700:        if (user_space && db_access_level < DB_ACCESS_CURRENT)
                    701:            db_error("User space break point is not supported\n");
                    702:        if (!task_bpt && !DB_VALID_ADDRESS((vm_offset_t)addr, user_space)) {
                    703:            /* if the user has explicitly specified user space,
                    704:               do not insert a breakpoint into the kernel */
                    705:            if (user_space)
                    706:              db_error("Invalid user space address\n");
                    707:            user_space = TRUE;
                    708:            db_printf("%#X is in user space\n", addr);
                    709:        }
                    710:        if (db_option(modif, 't') || task_bpt) {
                    711:            for (n = 0; db_get_next_thread(&thread, n); n++) {
                    712:                if (thread == THREAD_NULL)
                    713:                    db_error("No active thread\n");
                    714:                if (task_bpt && thread->task == TASK_NULL)
                    715:                    db_error("No task\n");
                    716:                if (db_access_level <= DB_ACCESS_CURRENT && user_space
                    717:                         && thread->task != db_current_task())
                    718:                    db_error("Cannot set break point in inactive user space\n");
1.1.1.2   root      719:                db_set_breakpoint(db_target_space(thread, user_space),
1.1       root      720:                                        (db_addr_t)addr, count,
                    721:                                        (user_global)? THREAD_NULL: thread,
                    722:                                        task_bpt);
                    723:            }
                    724:        } else {
                    725:            db_set_breakpoint(db_target_space(THREAD_NULL, user_space),
                    726:                                 (db_addr_t)addr,
                    727:                                 count, THREAD_NULL, FALSE);
                    728:        }
                    729: }
                    730: 
                    731: /* list breakpoints */
                    732: void
                    733: db_listbreak_cmd()
                    734: {
                    735:        db_list_breakpoints();
                    736: }
                    737: 
1.1.1.2   root      738: #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.