Annotation of XNU/osfmk/ddb/db_examine.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: /*
                     26:  * HISTORY
                     27:  * 
                     28:  * Revision 1.1.1.1  1998/09/22 21:05:47  wsanchez
                     29:  * Import of Mac OS X kernel (~semeria)
                     30:  *
                     31:  * Revision 1.2  1998/04/24 19:34:23  semeria
                     32:  * KDP and KDB support
                     33:  *
                     34:  * Revision 1.1.1.1  1998/03/07 02:26:09  wsanchez
                     35:  * Import of OSF Mach kernel (~mburg)
                     36:  *
                     37:  * Revision 1.2.42.2  1997/09/12  17:15:15  stephen
                     38:  *     make x/x do zero fill right justified hex display
                     39:  *     [1997/09/12  16:31:04  stephen]
                     40:  *
                     41:  * Revision 1.2.42.1  1997/03/27  18:46:31  barbou
                     42:  *     Add 'p' option to the "examine" command - values in
                     43:  *     memory treated as addresses and rendered as sym+offset
                     44:  *     [1995/12/29  21:32:33  mod]
                     45:  *     ri-osc CR1560: make search command output address of any matching
                     46:  *     data it finds (so user knows it did something).
                     47:  *     [1995/09/20  15:24:55  bolinger]
                     48:  *     [97/02/25            barbou]
                     49:  * 
                     50:  * Revision 1.2.25.5  1996/01/09  19:15:38  devrcs
                     51:  *     Add db_print_loc() & db_print_inst() functions.
                     52:  *     Make 'l' display 32 bits and new 'q' to display 64 bits.
                     53:  *     Allow 'u' to display unsigned decimal values (same as 'U').
                     54:  *     Changed declarations of 'register foo' to 'register int foo'.
                     55:  *     [1995/12/01  21:42:03  jfraser]
                     56:  * 
                     57:  *     Merged '64-bit safe' changes from DEC alpha port.
                     58:  *     [1995/11/21  18:02:58  jfraser]
                     59:  * 
                     60:  * Revision 1.2.25.4  1995/06/13  18:21:27  sjs
                     61:  *     Merge with flipc_shared.
                     62:  *     [95/05/22            sjs]
                     63:  * 
                     64:  * Revision 1.2.30.1  1995/04/03  17:35:17  randys
                     65:  *     Minor change; allow a repeat count to work properly when multiple
                     66:  *     modifier flags are given to the ddb 'x' command.  This allows,
                     67:  *     for instance, examination of multiple words in activations other
                     68:  *     than the current one.
                     69:  *     [95/04/03            randys]
                     70:  * 
                     71:  * Revision 1.2.25.3  1995/01/06  19:10:09  devrcs
                     72:  *     mk6 CR668 - 1.3b26 merge
                     73:  *     * Revision 1.2.6.7  1994/05/06  18:39:09  tmt
                     74:  *     Merged osc1.3dec/shared with osc1.3b19
                     75:  *     Merge Alpha changes into osc1.312b source code.
                     76:  *     64bit cleanup.
                     77:  *     * End1.3merge
                     78:  *     [1994/11/04  08:49:22  dwm]
                     79:  * 
                     80:  * Revision 1.2.25.2  1994/09/23  01:18:44  ezf
                     81:  *     change marker to not FREE
                     82:  *     [1994/09/22  21:09:44  ezf]
                     83:  * 
                     84:  * Revision 1.2.25.1  1994/06/11  21:11:43  bolinger
                     85:  *     Merge up to NMK17.2.
                     86:  *     [1994/06/11  20:01:31  bolinger]
                     87:  * 
                     88:  * Revision 1.2.23.1  1994/02/08  10:57:47  bernadat
                     89:  *     Fixed output of an examine command to have a power of 2
                     90:  *     number of fields.
                     91:  *     [93/09/29            paire]
                     92:  * 
                     93:  *     Added dump of hexadecimal address in each line of examine command.
                     94:  *     Fixed beginning of line to be always located at position 0.
                     95:  *     [93/08/11            paire]
                     96:  *     [94/02/07            bernadat]
                     97:  * 
                     98:  * Revision 1.2.21.4  1994/03/17  22:35:27  dwm
                     99:  *     The infamous name change:  thread_activation + thread_shuttle = thread.
                    100:  *     [1994/03/17  21:25:43  dwm]
                    101:  * 
                    102:  * Revision 1.2.21.3  1994/01/12  17:50:40  dwm
                    103:  *     Coloc: initial restructuring to follow Utah model.
                    104:  *     [1994/01/12  17:13:08  dwm]
                    105:  * 
                    106:  * Revision 1.2.21.2  1993/10/12  16:38:58  dwm
                    107:  *     Print '\n' in x/s statements. [rwd]
                    108:  *     [1993/10/12  16:14:41  dwm]
                    109:  * 
                    110:  * Revision 1.2.6.5  1993/08/11  20:37:37  elliston
                    111:  *     Add ANSI Prototypes.  CR #9523.
                    112:  *     [1993/08/11  03:33:05  elliston]
                    113:  * 
                    114:  * Revision 1.2.6.4  1993/08/09  19:34:42  dswartz
                    115:  *     Add ANSI prototypes - CR#9523
                    116:  *     [1993/08/06  15:47:32  dswartz]
                    117:  * 
                    118:  * Revision 1.2.6.3  1993/07/27  18:27:07  elliston
                    119:  *     Add ANSI prototypes.  CR #9523.
                    120:  *     [1993/07/27  18:11:21  elliston]
                    121:  * 
                    122:  * Revision 1.2.6.2  1993/06/09  02:20:00  gm
                    123:  *     Added to OSF/1 R1.3 from NMK15.0.
                    124:  *     [1993/06/02  20:56:10  jeffc]
                    125:  * 
                    126:  * Revision 1.2  1993/04/19  16:01:58  devrcs
                    127:  *     Changes from mk78:
                    128:  *     Added void type to functions that needed it.
                    129:  *     Added init to 'size' in db_search_cmd(). Removed unused variables.
                    130:  *     Other cleanup to quiet gcc warnings.
                    131:  *     [92/05/16            jfriedl]
                    132:  *     x/u now examines current user space. x/t still examines user
                    133:  *     space of the the specified thread. x/tu is redundant.
                    134:  *     To examine an value as unsigned decimal, use x/U.
                    135:  *     [92/04/18            danner]
                    136:  *     [93/02/02            bruel]
                    137:  * 
                    138:  *     Remember count argument when repeating commands instead of the
                    139:  *     default command, also apply all the formats to current address
                    140:  *     instead of incrementing addresses when switching to next format.
                    141:  *     [[email protected]]
                    142:  * 
                    143:  *     Support 'A' format for print 'p' command [[email protected]]
                    144:  *     [92/12/03            bernadat]
                    145:  * 
                    146:  * Revision 1.1  1992/09/30  02:01:01  robert
                    147:  *     Initial revision
                    148:  * 
                    149:  * $EndLog$
                    150:  */
                    151: /* CMU_HIST */
                    152: /*
                    153:  * Revision 2.7  91/10/09  15:59:28  af
                    154:  *      Revision 2.6.1.1  91/10/05  13:05:49  jeffreyh
                    155:  *             Supported non current task space data examination and search.
                    156:  *             Added 'm' format and db_xcdump to print with hex and characters.
                    157:  *             Added db_examine_{forward, backward}.
                    158:  *             Changed db_print_cmd to support variable number of parameters
                    159:  *             including string constant.
                    160:  *             Included "db_access.h".
                    161:  *             [91/08/29            tak]
                    162:  * 
                    163:  * Revision 2.6.1.1  91/10/05  13:05:49  jeffreyh
                    164:  *     Supported non current task space data examination and search.
                    165:  *     Added 'm' format and db_xcdump to print with hex and characters.
                    166:  *     Added db_examine_{forward, backward}.
                    167:  *     Changed db_print_cmd to support variable number of parameters
                    168:  *     including string constant.
                    169:  *     Included "db_access.h".
                    170:  *     [91/08/29            tak]
                    171:  * 
                    172:  * Revision 2.6  91/08/28  11:11:01  jsb
                    173:  *     Added 'A' flag to examine: just like 'a' (address), but prints addr
                    174:  *     as a procedure type, thus printing file/line info if available.
                    175:  *     Useful when called as 'x/Ai'.
                    176:  *     [91/08/13  18:14:55  jsb]
                    177:  * 
                    178:  * Revision 2.5  91/05/14  15:33:31  mrt
                    179:  *     Correcting copyright
                    180:  * 
                    181:  * Revision 2.4  91/02/05  17:06:20  mrt
                    182:  *     Changed to new Mach copyright
                    183:  *     [91/01/31  16:17:37  mrt]
                    184:  * 
                    185:  * Revision 2.3  90/11/07  16:49:23  rpd
                    186:  *     Added db_search_cmd, db_search.
                    187:  *     [90/11/06            rpd]
                    188:  * 
                    189:  * Revision 2.2  90/08/27  21:50:38  dbg
                    190:  *     Add 'r', 'z' to print and examine formats.
                    191:  *     Change calling sequence of db_disasm.
                    192:  *     db_examine sets db_prev and db_next instead of explicitly
                    193:  *     advancing dot.
                    194:  *     [90/08/20            dbg]
                    195:  *     Reflected changes in db_printsym()'s calling seq.
                    196:  *     [90/08/20            af]
                    197:  *     Reduce lint.
                    198:  *     [90/08/07            dbg]
                    199:  *     Created.
                    200:  *     [90/07/25            dbg]
                    201:  * 
                    202:  */
                    203: /* CMU_ENDHIST */
                    204: /* 
                    205:  * Mach Operating System
                    206:  * Copyright (c) 1991,1990 Carnegie Mellon University
                    207:  * All Rights Reserved.
                    208:  * 
                    209:  * Permission to use, copy, modify and distribute this software and its
                    210:  * documentation is hereby granted, provided that both the copyright
                    211:  * notice and this permission notice appear in all copies of the
                    212:  * software, derivative works or modified versions, and any portions
                    213:  * thereof, and that both notices appear in supporting documentation.
                    214:  * 
                    215:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                    216:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                    217:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                    218:  * 
                    219:  * Carnegie Mellon requests users of this software to return to
                    220:  * 
                    221:  *  Software Distribution Coordinator  or  [email protected]
                    222:  *  School of Computer Science
                    223:  *  Carnegie Mellon University
                    224:  *  Pittsburgh PA 15213-3890
                    225:  * 
                    226:  * any improvements or extensions that they make and grant Carnegie Mellon
                    227:  * the rights to redistribute these changes.
                    228:  */
                    229: /*
                    230:  */
                    231: /*
                    232:  *     Author: David B. Golub, Carnegie Mellon University
                    233:  *     Date:   7/90
                    234:  */
                    235: #include <string.h>                    /* For strcpy() */
                    236: #include <mach/boolean.h>
                    237: #include <machine/db_machdep.h>
                    238: 
                    239: #include <ddb/db_access.h>
                    240: #include <ddb/db_lex.h>
                    241: #include <ddb/db_output.h>
                    242: #include <ddb/db_command.h>
                    243: #include <ddb/db_sym.h>
                    244: #include <ddb/db_task_thread.h>
                    245: #include <ddb/db_command.h>            /* For db_option() */
                    246: #include <ddb/db_examine.h>
                    247: #include <ddb/db_expr.h>
                    248: #include <kern/thread.h>
                    249: #include <kern/task.h>
                    250: #include <mach/vm_param.h>
                    251: 
                    252: #define db_act_to_task(thr_act)        ((thr_act)? thr_act->task: TASK_NULL)
                    253: 
                    254: char           db_examine_format[TOK_STRING_SIZE] = "x";
                    255: int            db_examine_count = 1;
                    256: db_addr_t      db_examine_prev_addr = 0;
                    257: thread_act_t   db_examine_act = THR_ACT_NULL;
                    258: 
                    259: extern int     db_max_width;
                    260: 
                    261: 
                    262: /* Prototypes for functions local to this file.  XXX -- should be static!
                    263:  */
                    264: int db_xcdump(
                    265:        db_addr_t       addr,
                    266:        int             size,
                    267:        int             count,
                    268:        task_t          task);
                    269: 
                    270: int db_examine_width(
                    271:        int size,
                    272:        int *items,
                    273:        int *remainder);
                    274: 
                    275: /*
                    276:  * Examine (print) data.
                    277:  */
                    278: void
                    279: db_examine_cmd(
                    280:        db_expr_t       addr,
                    281:        int             have_addr,
                    282:        db_expr_t       count,
                    283:        char *          modif)
                    284: {
                    285:        thread_act_t    thr_act;
                    286:        extern char     db_last_modifier[];
                    287: 
                    288:        if (modif[0] != '\0')
                    289:            strcpy(db_examine_format, modif);
                    290: 
                    291:        if (count == -1)
                    292:            count = 1;
                    293:        db_examine_count = count;
                    294:        if (db_option(modif, 't')) {
                    295:            if (modif == db_last_modifier)
                    296:                thr_act = db_examine_act;
                    297:            else if (!db_get_next_act(&thr_act, 0))
                    298:                return;
                    299:        } else
                    300:          if (db_option(modif,'u'))
                    301:            thr_act = current_act();
                    302:          else
                    303:            thr_act = THR_ACT_NULL;
                    304: 
                    305:        db_examine_act = thr_act;
                    306:        db_examine((db_addr_t) addr, db_examine_format, count, 
                    307:                                        db_act_to_task(thr_act));
                    308: }
                    309: 
                    310: void
                    311: db_examine_forward(
                    312:        db_expr_t       addr,
                    313:        int             have_addr,
                    314:        db_expr_t       count,
                    315:        char *          modif)
                    316: {
                    317:        db_examine(db_next, db_examine_format, db_examine_count,
                    318:                                db_act_to_task(db_examine_act));
                    319: }
                    320: 
                    321: void
                    322: db_examine_backward(
                    323:        db_expr_t       addr,
                    324:        int             have_addr,
                    325:        db_expr_t       count,
                    326:        char *          modif)
                    327: {
                    328:        db_examine(db_examine_prev_addr - (db_next - db_examine_prev_addr),
                    329:                         db_examine_format, db_examine_count,
                    330:                                db_act_to_task(db_examine_act));
                    331: }
                    332: 
                    333: int
                    334: db_examine_width(
                    335:        int size,
                    336:        int *items,
                    337:        int *remainder)
                    338: {
                    339:        int sz;
                    340:        int entry;
                    341:        int width;
                    342: 
                    343:        width = size * 2 + 1;
                    344:        sz = (db_max_width - (sizeof (void *) * 2 + 4)) / width;
                    345:        for (entry = 1; (entry << 1) < sz; entry <<= 1)
                    346:                continue;
                    347: 
                    348:        sz = sizeof (void *) * 2 + 4 + entry * width;
                    349:        while (sz + entry < db_max_width) {
                    350:                width++;
                    351:                sz += entry;
                    352:        }
                    353:        *remainder = (db_max_width - sz + 1) / 2;
                    354:        *items = entry;
                    355:        return width;
                    356: }
                    357: 
                    358: void
                    359: db_examine(
                    360:        db_addr_t       addr,
                    361:        char *          fmt,    /* format string */
                    362:        int             count,  /* repeat count */
                    363:        task_t          task)
                    364: {
                    365:        int             c;
                    366:        db_expr_t       value;
                    367:        int             size;
                    368:        int             width;
                    369:        int             leader;
                    370:        int             items;
                    371:        int             nitems;
                    372:        char *          fp;
                    373:        db_addr_t       next_addr;
                    374:        int             sz;
                    375: 
                    376:        db_examine_prev_addr = addr;
                    377:        while (--count >= 0) {
                    378:            fp = fmt;
                    379:            size = sizeof(int);
                    380:            width = db_examine_width(size, &items, &leader);
                    381:            while ((c = *fp++) != 0) {
                    382:                switch (c) {
                    383:                    case 'b':
                    384:                        size = sizeof(char);
                    385:                        width = db_examine_width(size, &items, &leader);
                    386:                        break;
                    387:                    case 'h':
                    388:                        size = sizeof(short);
                    389:                        width = db_examine_width(size, &items, &leader);
                    390:                        break;
                    391:                    case 'l':
                    392:                        size = sizeof(int);
                    393:                        width = db_examine_width(size, &items, &leader);
                    394:                        break;
                    395:                    case 'q':
                    396:                        size = sizeof(long);
                    397:                        width = db_examine_width(size, &items, &leader);
                    398:                        break;
                    399:                    case 'a':   /* address */
                    400:                    case 'A':   /* function address */
                    401:                        /* always forces a new line */
                    402:                        if (db_print_position() != 0)
                    403:                            db_printf("\n");
                    404:                        db_prev = addr;
                    405:                        next_addr = addr + 4;
                    406:                        db_task_printsym(addr, 
                    407:                                        (c == 'a')?DB_STGY_ANY:DB_STGY_PROC,
                    408:                                        task);
                    409:                        db_printf(":\t");
                    410:                        break;
                    411:                    case 'm':
                    412:                        db_next = db_xcdump(addr, size, count+1, task);
                    413:                        return;
                    414:                    case 't':
                    415:                    case 'u':
                    416:                        break;
                    417:                    default:
                    418:                restart:
                    419:                        /* Reset next_addr in case we are printing in
                    420:                           multiple formats.  */
                    421:                        next_addr = addr;
                    422:                        if (db_print_position() == 0) {
                    423:                            /* If we hit a new symbol, print it */
                    424:                            char *      name;
                    425:                            db_addr_t   off;
                    426: 
                    427:                            db_find_task_sym_and_offset(addr,&name,&off,task);
                    428:                            if (off == 0)
                    429:                                db_printf("\r%s:\n", name);
                    430:                            db_printf("%#n: ", addr);
                    431:                            for (sz = 0; sz < leader; sz++)
                    432:                                    db_putchar(' ');
                    433:                            db_prev = addr;
                    434:                            nitems = items;
                    435:                        }
                    436: 
                    437:                        switch (c) {
                    438:                            case 'p':   /* Addrs rendered symbolically. */
                    439:                                if( size == sizeof(void *) )  {
                    440:                                    char       *symName;
                    441:                                    db_addr_t   offset;
                    442: 
                    443:                                    items = 1;
                    444:                                    value = db_get_task_value( next_addr,
                    445:                                        sizeof(db_expr_t), FALSE, task );
                    446:                                    db_find_task_sym_and_offset( value,
                    447:                                        &symName, &offset, task);
                    448:                                    db_printf("\n\t*%8x(%8X) = %s",
                    449:                                                next_addr, value, symName );
                    450:                                    if( offset )  {
                    451:                                        db_printf("+%X", offset );
                    452:                                    }
                    453:                                    next_addr += size;
                    454:                                }
                    455:                                break;
                    456:                            case 'r':   /* signed, current radix */
                    457:                                for (sz = size, next_addr = addr;
                    458:                                     sz >= sizeof (db_expr_t);
                    459:                                     sz -= sizeof (db_expr_t)) {
                    460:                                    if (nitems-- == 0) {
                    461:                                        db_putchar('\n');
                    462:                                        goto restart;
                    463:                                    }
                    464:                                    value = db_get_task_value(next_addr,
                    465:                                                              sizeof (db_expr_t),
                    466:                                                              TRUE,task);
                    467:                                    db_printf("%-*r", width, value);
                    468:                                    next_addr += sizeof (db_expr_t);
                    469:                                }
                    470:                                if (sz > 0) {
                    471:                                    if (nitems-- == 0) {
                    472:                                        db_putchar('\n');
                    473:                                        goto restart;
                    474:                                    }
                    475:                                    value = db_get_task_value(next_addr, sz,
                    476:                                                              TRUE, task);
                    477:                                    db_printf("%-*R", width, value);
                    478:                                    next_addr += sz;
                    479:                                }
                    480:                                break;
                    481: #ifdef APPLE
                    482:                            case 'X':   /* unsigned hex */
                    483: #endif
                    484:                            case 'x':   /* unsigned hex */
                    485:                                for (sz = size, next_addr = addr;
                    486:                                     sz >= sizeof (db_expr_t);
                    487:                                     sz -= sizeof (db_expr_t)) {
                    488:                                    if (nitems-- == 0) {
                    489:                                        db_putchar('\n');
                    490:                                        goto restart;
                    491:                                    }
                    492:                                    value = db_get_task_value(next_addr,
                    493:                                                              sizeof (db_expr_t),
                    494:                                                              FALSE,task);
                    495: #ifdef APPLE
                    496:                                    if ( c == 'X')
                    497:                                      db_printf("%0*X ", 2*size, value);
                    498:                                    else
                    499:                                      db_printf("%-*x", width, value);
                    500: #else
                    501:                                    db_printf("%-*x", width, value);
                    502: #endif
                    503:                                    next_addr += sizeof (db_expr_t);
                    504:                                }
                    505:                                if (sz > 0) {
                    506:                                    if (nitems-- == 0) {
                    507:                                        db_putchar('\n');
                    508:                                        goto restart;
                    509:                                    }
                    510:                                    value = db_get_task_value(next_addr, sz,
                    511:                                                              FALSE, task);
                    512: #ifdef APPLE
                    513:                                    if ( c == 'X')
                    514:                                      db_printf("%0*X ", 2*size, value);
                    515:                                    else
                    516:                                      db_printf("%-*X", width, value);
                    517: #else
                    518:                                    db_printf("%-*X", width, value);
                    519: #endif
                    520:                                    next_addr += sz;
                    521:                                }
                    522:                                break;
                    523:                            case 'z':   /* signed hex */
                    524:                                for (sz = size, next_addr = addr;
                    525:                                     sz >= sizeof (db_expr_t);
                    526:                                     sz -= sizeof (db_expr_t)) {
                    527:                                    if (nitems-- == 0) {
                    528:                                        db_putchar('\n');
                    529:                                        goto restart;
                    530:                                    }
                    531:                                    value = db_get_task_value(next_addr,
                    532:                                                              sizeof (db_expr_t),
                    533:                                                              TRUE, task);
                    534:                                    db_printf("%-*z", width, value);
                    535:                                    next_addr += sizeof (db_expr_t);
                    536:                                }
                    537:                                if (sz > 0) {
                    538:                                    if (nitems-- == 0) {
                    539:                                        db_putchar('\n');
                    540:                                        goto restart;
                    541:                                    }
                    542:                                    value = db_get_task_value(next_addr,sz,
                    543:                                                              TRUE,task);
                    544:                                    db_printf("%-*Z", width, value);
                    545:                                    next_addr += sz;
                    546:                                }
                    547:                                break;
                    548:                            case 'd':   /* signed decimal */
                    549:                                for (sz = size, next_addr = addr;
                    550:                                     sz >= sizeof (db_expr_t);
                    551:                                     sz -= sizeof (db_expr_t)) {
                    552:                                    if (nitems-- == 0) {
                    553:                                        db_putchar('\n');
                    554:                                        goto restart;
                    555:                                    }
                    556:                                    value = db_get_task_value(next_addr,
                    557:                                                              sizeof (db_expr_t),
                    558:                                                              TRUE,task);
                    559:                                    db_printf("%-*d", width, value);
                    560:                                    next_addr += sizeof (db_expr_t);
                    561:                                }
                    562:                                if (sz > 0) {
                    563:                                    if (nitems-- == 0) {
                    564:                                        db_putchar('\n');
                    565:                                        goto restart;
                    566:                                    }
                    567:                                    value = db_get_task_value(next_addr, sz,
                    568:                                                              TRUE, task);
                    569:                                    db_printf("%-*D", width, value);
                    570:                                    next_addr += sz;
                    571:                                }
                    572:                                break;
                    573:                            case 'U':   /* unsigned decimal */
                    574:                            case 'u':
                    575:                                for (sz = size, next_addr = addr;
                    576:                                     sz >= sizeof (db_expr_t);
                    577:                                     sz -= sizeof (db_expr_t)) {
                    578:                                    if (nitems-- == 0) {
                    579:                                        db_putchar('\n');
                    580:                                        goto restart;
                    581:                                    }
                    582:                                    value = db_get_task_value(next_addr,
                    583:                                                              sizeof (db_expr_t),
                    584:                                                              FALSE,task);
                    585:                                    db_printf("%-*u", width, value);
                    586:                                    next_addr += sizeof (db_expr_t);
                    587:                                }
                    588:                                if (sz > 0) {
                    589:                                    if (nitems-- == 0) {
                    590:                                        db_putchar('\n');
                    591:                                        goto restart;
                    592:                                    }
                    593:                                    value = db_get_task_value(next_addr, sz,
                    594:                                                              FALSE, task);
                    595:                                    db_printf("%-*U", width, value);
                    596:                                    next_addr += sz;
                    597:                                }
                    598:                                break;
                    599:                            case 'o':   /* unsigned octal */
                    600:                                for (sz = size, next_addr = addr;
                    601:                                     sz >= sizeof (db_expr_t);
                    602:                                     sz -= sizeof (db_expr_t)) {
                    603:                                    if (nitems-- == 0) {
                    604:                                        db_putchar('\n');
                    605:                                        goto restart;
                    606:                                    }
                    607:                                    value = db_get_task_value(next_addr,
                    608:                                                              sizeof (db_expr_t),
                    609:                                                              FALSE,task);
                    610:                                    db_printf("%-*o", width, value);
                    611:                                    next_addr += sizeof (db_expr_t);
                    612:                                }
                    613:                                if (sz > 0) {
                    614:                                    if (nitems-- == 0) {
                    615:                                        db_putchar('\n');
                    616:                                        goto restart;
                    617:                                    }
                    618:                                    value = db_get_task_value(next_addr, sz,
                    619:                                                              FALSE, task);
                    620:                                    db_printf("%-*o", width, value);
                    621:                                    next_addr += sz;
                    622:                                }
                    623:                                break;
                    624:                            case 'c':   /* character */
                    625:                                for (sz = 0, next_addr = addr;
                    626:                                     sz < size;
                    627:                                     sz++, next_addr++) {
                    628:                                    value = db_get_task_value(next_addr,1,
                    629:                                                              FALSE,task);
                    630:                                    if ((value >= ' ' && value <= '~') ||
                    631:                                        value == '\n' ||
                    632:                                        value == '\t')
                    633:                                            db_printf("%c", value);
                    634:                                    else
                    635:                                            db_printf("\\%03o", value);
                    636:                                }
                    637:                                break;
                    638:                            case 's':   /* null-terminated string */
                    639:                                size = 0;
                    640:                                for (;;) {
                    641:                                    value = db_get_task_value(next_addr,1,
                    642:                                                              FALSE,task);
                    643:                                    next_addr += 1;
                    644:                                    size++;
                    645:                                    if (value == 0)
                    646:                                        break;
                    647:                                    if (value >= ' ' && value <= '~')
                    648:                                        db_printf("%c", value);
                    649:                                    else
                    650:                                        db_printf("\\%03o", value);
                    651:                                }
                    652:                                break;
                    653:                            case 'i':   /* instruction */
                    654:                                next_addr = db_disasm(addr, FALSE, task);
                    655:                                size = next_addr - addr;
                    656:                                break;
                    657:                            case 'I':   /* instruction, alternate form */
                    658:                                next_addr = db_disasm(addr, TRUE, task);
                    659:                                size = next_addr - addr;
                    660:                                break;
                    661:                            default:
                    662:                                break;
                    663:                        }
                    664:                        if (db_print_position() != 0)
                    665:                            db_end_line();
                    666:                        break;
                    667:                }
                    668:            }
                    669:            addr = next_addr;
                    670:        }
                    671:        db_next = addr;
                    672: }
                    673: 
                    674: /*
                    675:  * Print value.
                    676:  */
                    677: char   db_print_format = 'x';
                    678: 
                    679: void
                    680: db_print_cmd(void)
                    681: {
                    682:        db_expr_t       value;
                    683:        int             t;
                    684:        task_t          task = TASK_NULL;
                    685: 
                    686:        if ((t = db_read_token()) == tSLASH) {
                    687:            if (db_read_token() != tIDENT) {
                    688:                db_printf("Bad modifier \"/%s\"\n", db_tok_string);
                    689:                db_error(0);
                    690:                /* NOTREACHED */
                    691:            }
                    692:            if (db_tok_string[0])
                    693:                db_print_format = db_tok_string[0];
                    694:            if (db_option(db_tok_string, 't')) {
                    695:                if (db_default_act)
                    696:                    task = db_default_act->task;
                    697:                if (db_print_format == 't')
                    698:                   db_print_format = db_tok_string[1];
                    699:            }
                    700:        } else
                    701:            db_unread_token(t);
                    702:        
                    703:        for ( ; ; ) {
                    704:            t = db_read_token();
                    705:            if (t == tSTRING) {
                    706:                db_printf("%s", db_tok_string);
                    707:                continue;
                    708:            }
                    709:            db_unread_token(t);
                    710:            if (!db_expression(&value))
                    711:                break;
                    712:            switch (db_print_format) {
                    713:            case 'a':
                    714:            case 'A':
                    715:                db_task_printsym((db_addr_t)value,
                    716:                                 (db_print_format == 'a') ? DB_STGY_ANY:
                    717:                                                            DB_STGY_PROC,
                    718:                                 task);
                    719:                break;
                    720:            case 'r':
                    721:                db_printf("%11r", value);
                    722:                break;
                    723:            case 'x':
                    724:                db_printf("%08x", value);
                    725:                break;
                    726:            case 'z':
                    727:                db_printf("%8z", value);
                    728:                break;
                    729:            case 'd':
                    730:                db_printf("%11d", value);
                    731:                break;
                    732:            case 'u':
                    733:                db_printf("%11u", value);
                    734:                break;
                    735:            case 'o':
                    736:                db_printf("%16o", value);
                    737:                break;
                    738:            case 'c':
                    739:                value = value & 0xFF;
                    740:                if (value >= ' ' && value <= '~')
                    741:                    db_printf("%c", value);
                    742:                else
                    743:                    db_printf("\\%03o", value);
                    744:                break;
                    745:            default:
                    746:                db_printf("Unknown format %c\n", db_print_format);
                    747:                db_print_format = 'x';
                    748:                db_error(0);
                    749:            }
                    750:        }
                    751: }
                    752: 
                    753: void
                    754: db_print_loc(
                    755:        db_addr_t       loc,
                    756:        task_t          task)
                    757: {
                    758:        db_task_printsym(loc, DB_STGY_PROC, task);
                    759: }
                    760: 
                    761: void
                    762: db_print_inst(
                    763:        db_addr_t       loc,
                    764:        task_t          task)
                    765: {
                    766:        (void) db_disasm(loc, TRUE, task);
                    767: }
                    768: 
                    769: void
                    770: db_print_loc_and_inst(
                    771:        db_addr_t       loc,
                    772:        task_t          task)
                    773: {
                    774:        db_task_printsym(loc, DB_STGY_PROC, task);
                    775:        db_printf(":\t");
                    776:        (void) db_disasm(loc, TRUE, task);
                    777: }
                    778: 
                    779: /*
                    780:  * Search for a value in memory.
                    781:  * Syntax: search [/bhl] addr value [mask] [,count] [thread]
                    782:  */
                    783: void
                    784: db_search_cmd(void)
                    785: {
                    786:        int             t;
                    787:        db_addr_t       addr;
                    788:        int             size = 0;
                    789:        db_expr_t       value;
                    790:        db_expr_t       mask;
                    791:        db_addr_t       count;
                    792:        thread_act_t    thr_act;
                    793:        boolean_t       thread_flag = FALSE;
                    794:        register char   *p;
                    795: 
                    796:        t = db_read_token();
                    797:        if (t == tSLASH) {
                    798:            t = db_read_token();
                    799:            if (t != tIDENT) {
                    800:              bad_modifier:
                    801:                db_printf("Bad modifier \"/%s\"\n", db_tok_string);
                    802:                db_flush_lex();
                    803:                return;
                    804:            }
                    805: 
                    806:            for (p = db_tok_string; *p; p++) {
                    807:                switch(*p) {
                    808:                case 'b':
                    809:                    size = sizeof(char);
                    810:                    break;
                    811:                case 'h':
                    812:                    size = sizeof(short);
                    813:                    break;
                    814:                case 'l':
                    815:                    size = sizeof(long);
                    816:                    break;
                    817:                case 't':
                    818:                    thread_flag = TRUE;
                    819:                    break;
                    820:                default:
                    821:                    goto bad_modifier;
                    822:                }
                    823:            }
                    824:        } else {
                    825:            db_unread_token(t);
                    826:            size = sizeof(int);
                    827:        }
                    828: 
                    829:        if (!db_expression((db_expr_t *) &addr)) {
                    830:            db_printf("Address missing\n");
                    831:            db_flush_lex();
                    832:            return;
                    833:        }
                    834: 
                    835:        if (!db_expression(&value)) {
                    836:            db_printf("Value missing\n");
                    837:            db_flush_lex();
                    838:            return;
                    839:        }
                    840: 
                    841:        if (!db_expression(&mask))
                    842:            mask = ~0;
                    843: 
                    844:        t = db_read_token();
                    845:        if (t == tCOMMA) {
                    846:            if (!db_expression((db_expr_t *) &count)) {
                    847:                db_printf("Count missing\n");
                    848:                db_flush_lex();
                    849:                return;
                    850:            }
                    851:        } else {
                    852:            db_unread_token(t);
                    853:            count = -1;         /* effectively forever */
                    854:        }
                    855:        if (thread_flag) {
                    856:            if (!db_get_next_act(&thr_act, 0))
                    857:                return;
                    858:        } else
                    859:            thr_act = THR_ACT_NULL;
                    860: 
                    861:        db_search(addr, size, value, mask, count, db_act_to_task(thr_act));
                    862: }
                    863: 
                    864: void
                    865: db_search(
                    866:        db_addr_t       addr,
                    867:        int             size,
                    868:        db_expr_t       value,
                    869:        db_expr_t       mask,
                    870:        unsigned int    count,
                    871:        task_t          task)
                    872: {
                    873:        while (count-- != 0) {
                    874:                db_prev = addr;
                    875:                if ((db_get_task_value(addr,size,FALSE,task) & mask) == value)
                    876:                        break;
                    877:                addr += size;
                    878:        }
                    879:        db_printf("0x%x: ", addr);
                    880:        db_next = addr;
                    881: }
                    882: 
                    883: #define DB_XCDUMP_NC   16
                    884: 
                    885: int
                    886: db_xcdump(
                    887:        db_addr_t       addr,
                    888:        int             size,
                    889:        int             count,
                    890:        task_t          task)
                    891: {
                    892:        register int    i, n;
                    893:        db_expr_t       value;
                    894:        int             bcount;
                    895:        db_addr_t       off;
                    896:        char            *name;
                    897:        char            data[DB_XCDUMP_NC];
                    898: 
                    899:        db_find_task_sym_and_offset(addr, &name, &off, task);
                    900:        for (n = count*size; n > 0; n -= bcount) {
                    901:            db_prev = addr;
                    902:            if (off == 0) {
                    903:                db_printf("%s:\n", name);
                    904:                off = -1;
                    905:            }
                    906:            db_printf("%0*X:%s", 2*sizeof(db_addr_t), addr,
                    907:                                        (size != 1) ? " " : "" );
                    908:            bcount = ((n > DB_XCDUMP_NC)? DB_XCDUMP_NC: n);
                    909:            if (trunc_page(addr) != trunc_page(addr+bcount-1)) {
                    910:                db_addr_t next_page_addr = trunc_page(addr+bcount-1);
                    911:                if (!DB_CHECK_ACCESS(next_page_addr, sizeof(int), task))
                    912:                    bcount = next_page_addr - addr;
                    913:            }
                    914:            db_read_bytes((vm_offset_t)addr, bcount, data, task);
                    915:            for (i = 0; i < bcount && off != 0; i += size) {
                    916:                if (i % 4 == 0)
                    917:                        db_printf(" ");
                    918:                value = db_get_task_value(addr, size, FALSE, task);
                    919:                db_printf("%0*x ", size*2, value);
                    920:                addr += size;
                    921:                db_find_task_sym_and_offset(addr, &name, &off, task);
                    922:            }
                    923:            db_printf("%*s",
                    924:                        ((DB_XCDUMP_NC-i)/size)*(size*2+1)+(DB_XCDUMP_NC-i)/4,
                    925:                         "");
                    926:            bcount = i;
                    927:            db_printf("%s*", (size != 1)? " ": "");
                    928:            for (i = 0; i < bcount; i++) {
                    929:                value = data[i];
                    930:                db_printf("%c", (value >= ' ' && value <= '~')? value: '.');
                    931:            }
                    932:            db_printf("*\n");
                    933:        }
                    934:        return(addr);
                    935: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.