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