[BACK]Return to db_trace.c CVS log [TXT][DIR] Up to [local] / sys / arch / alpha / alpha

Annotation of sys/arch/alpha/alpha/db_trace.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: db_trace.c,v 1.14 2003/10/18 20:14:40 jmc Exp $       */
                      2:
                      3: /*
                      4:  * Copyright (c) 1997 Niklas Hallqvist.  All rights reserved.
                      5:  * Copyright (c) 1997 Theo de Raadt.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
                     20:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     21:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     22:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     23:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     24:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     25:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27:
                     28: #include <sys/types.h>
                     29: #include <sys/param.h>
                     30: #include <sys/systm.h>
                     31:
                     32: #include <uvm/uvm_extern.h>
                     33:
                     34: #include <machine/db_machdep.h>
                     35: #include <machine/frame.h>
                     36:
                     37: #include <ddb/db_access.h>
                     38: #include <ddb/db_command.h>
                     39: #include <ddb/db_output.h>
                     40: #include <ddb/db_sym.h>
                     41: #include <ddb/db_variables.h>
                     42: #include <ddb/db_extern.h>
                     43: #include <ddb/db_interface.h>
                     44:
                     45: extern int     etext;
                     46:
                     47: struct opcode opcode[] = {
                     48:        { OPC_PAL, "call_pal", 0 },     /* 00 */
                     49:        { OPC_RES, "opc01", 0 },        /* 01 */
                     50:        { OPC_RES, "opc02", 0 },        /* 02 */
                     51:        { OPC_RES, "opc03", 0 },        /* 03 */
                     52:        { OPC_RES, "opc04", 0 },        /* 04 */
                     53:        { OPC_RES, "opc05", 0 },        /* 05 */
                     54:        { OPC_RES, "opc06", 0 },        /* 06 */
                     55:        { OPC_RES, "opc07", 0 },        /* 07 */
                     56:        { OPC_MEM, "lda", 1 },          /* 08 */
                     57:        { OPC_MEM, "ldah", 1 },         /* 09 */
                     58:        { OPC_RES, "opc0a", 0 },        /* 0A */
                     59:        { OPC_MEM, "ldq_u", 1 },        /* 0B */
                     60:        { OPC_RES, "opc0c", 0 },        /* 0C */
                     61:        { OPC_RES, "opc0d", 0 },        /* 0D */
                     62:        { OPC_RES, "opc0e", 0 },        /* 0E */
                     63:        { OPC_MEM, "stq_u", 1 },        /* 0F */
                     64:        { OPC_OP, "inta", 0 },          /* 10 */
                     65:        { OPC_OP, "intl", 0 },          /* 11 */
                     66:        { OPC_OP, "ints", 0 },          /* 12 */
                     67:        { OPC_OP, "intm", 0 },          /* 13 */
                     68:        { OPC_RES, "opc14", 0 },        /* 14 */
                     69:        { OPC_OP, "fltv", 1 },          /* 15 */
                     70:        { OPC_OP, "flti", 1 },          /* 16 */
                     71:        { OPC_OP, "fltl", 1 },          /* 17 */
                     72:        { OPC_MEM, "misc", 0 },         /* 18 */
                     73:        { OPC_PAL, "pal19", 0 },        /* 19 */
                     74:        { OPC_MEM, "jsr", 0 },          /* 1A */
                     75:        { OPC_PAL, "pal1b", 0 },        /* 1B */
                     76:        { OPC_RES, "opc1c", 0 },        /* 1C */
                     77:        { OPC_PAL, "pal1d", 0 },        /* 1D */
                     78:        { OPC_PAL, "pal1e", 0 },        /* 1E */
                     79:        { OPC_PAL, "pal1f", 0 },        /* 1F */
                     80:        { OPC_MEM, "ldf", 1 },          /* 20 */
                     81:        { OPC_MEM, "ldg", 1 },          /* 21 */
                     82:        { OPC_MEM, "lds", 1 },          /* 22 */
                     83:        { OPC_MEM, "ldt", 1 },          /* 23 */
                     84:        { OPC_MEM, "stf", 1 },          /* 24 */
                     85:        { OPC_MEM, "stg", 1 },          /* 25 */
                     86:        { OPC_MEM, "sts", 1 },          /* 26 */
                     87:        { OPC_MEM, "stt", 1 },          /* 27 */
                     88:        { OPC_MEM, "ldl", 1 },          /* 28 */
                     89:        { OPC_MEM, "ldq", 1 },          /* 29 */
                     90:        { OPC_MEM, "ldl_l", 1 },        /* 2A */
                     91:        { OPC_MEM, "ldq_l", 1 },        /* 2B */
                     92:        { OPC_MEM, "stl", 1 },          /* 2C */
                     93:        { OPC_MEM, "stq", 1 },          /* 2D */
                     94:        { OPC_MEM, "stl_c", 1 },        /* 2E */
                     95:        { OPC_MEM, "stq_c", 1 },        /* 2F */
                     96:        { OPC_BR, "br", 1 },            /* 30 */
                     97:        { OPC_BR, "fbeq", 1 },          /* 31 */
                     98:        { OPC_BR, "fblt", 1 },          /* 32 */
                     99:        { OPC_BR, "fble", 1 },          /* 33 */
                    100:        { OPC_BR, "bsr", 1 },           /* 34 */
                    101:        { OPC_BR, "fbne", 1 },          /* 35 */
                    102:        { OPC_BR, "fbge", 1 },          /* 36 */
                    103:        { OPC_BR, "fbgt", 1 },          /* 37 */
                    104:        { OPC_BR, "blbc", 1 },          /* 38 */
                    105:        { OPC_BR, "beq", 1 },           /* 39 */
                    106:        { OPC_BR, "blt", 1 },           /* 3A */
                    107:        { OPC_BR, "ble", 1 },           /* 3B */
                    108:        { OPC_BR, "blbs", 1 },          /* 3C */
                    109:        { OPC_BR, "bne", 1 },           /* 3D */
                    110:        { OPC_BR, "bge", 1 },           /* 3E */
                    111:        { OPC_BR, "bgt", 1 },           /* 3F */
                    112: };
                    113:
                    114: static __inline int sext(u_int);
                    115: static __inline int rega(u_int);
                    116: static __inline int regb(u_int);
                    117: static __inline int regc(u_int);
                    118: static __inline int disp(u_int);
                    119:
                    120: static __inline int
                    121: sext(x)
                    122:        u_int x;
                    123: {
                    124:        return ((x & 0x8000) ? -(-x & 0xffff) : (x & 0xffff));
                    125: }
                    126:
                    127: static __inline int
                    128: rega(x)
                    129:        u_int x;
                    130: {
                    131:        return ((x >> 21) & 0x1f);
                    132: }
                    133:
                    134: static __inline int
                    135: regb(x)
                    136:        u_int x;
                    137: {
                    138:        return ((x >> 16) & 0x1f);
                    139: }
                    140:
                    141: static __inline int
                    142: regc(x)
                    143:        u_int x;
                    144: {
                    145:        return (x & 0x1f);
                    146: }
                    147:
                    148: static __inline int
                    149: disp(x)
                    150:        u_int x;
                    151: {
                    152:        return (sext(x & 0xffff));
                    153: }
                    154:
                    155: /*
                    156:  * XXX There are a couple of problems with this code:
                    157:  *
                    158:  *     The argument list printout code is likely to get confused.
                    159:  *
                    160:  *     It relies on the conventions of gcc code generation.
                    161:  *
                    162:  *     It uses heuristics to calculate the framesize, and might get it wrong.
                    163:  *
                    164:  *     It doesn't yet use the framepointer if available.
                    165:  *
                    166:  *     The address argument can only be used for pointing at trapframes
                    167:  *     since a frame pointer of its own serves no good on the alpha,
                    168:  *     you need a pc value too.
                    169:  *
                    170:  *     The heuristics used for tracing through a trap relies on having
                    171:  *     symbols available.
                    172:  */
                    173: void
                    174: db_stack_trace_print(addr, have_addr, count, modif, pr)
                    175:        db_expr_t       addr;
                    176:        int             have_addr;
                    177:        db_expr_t       count;
                    178:        char            *modif;
                    179:        int             (*pr)(const char *, ...);
                    180: {
                    181:        u_long          *frame;
                    182:        int             i, framesize;
                    183:        db_addr_t       pc, ra;
                    184:        u_int           inst;
                    185:        char            *name;
                    186:        db_expr_t       offset;
                    187:        db_regs_t       *regs;
                    188:        u_long          *slot[32];
                    189:
                    190:        bzero(slot, sizeof(slot));
                    191:        if (count == -1)
                    192:                count = 65535;
                    193:
                    194:        if (have_addr) {
                    195:                (*pr)("alpha trace requires a trap frame... giving up.\n");
                    196:                return;
                    197:        }
                    198:        regs = DDB_REGS;
                    199: trapframe:
                    200:        /* remember where various registers are stored */
                    201:        for (i = 0; i < 31; i++)
                    202:                slot[i] = &regs->tf_regs[0] +
                    203:                    ((u_long *)db_regs[i].valuep - &ddb_regs.tf_regs[0]);
                    204:        frame = (u_long *)regs->tf_regs[FRAME_SP];
                    205:        pc = (db_addr_t)regs->tf_regs[FRAME_PC];
                    206:        ra = (db_addr_t)regs->tf_regs[FRAME_RA];
                    207:
                    208:        while (count-- && pc >= (db_addr_t)KERNBASE && pc < (db_addr_t)&etext) {
                    209:                db_find_sym_and_offset(pc, &name, &offset);
                    210:                if (!name) {
                    211:                        name = "?";
                    212:                        /* Limit the search for procedure start */
                    213:                        offset = 65536;
                    214:                }
                    215:                (*pr)("%s(", name);
                    216:
                    217:                framesize = 0;
                    218:                for (i = sizeof (int); i <= offset; i += sizeof (int)) {
                    219:                        inst = *(u_int *)(pc - i);
                    220:
                    221:                        /*
                    222:                         * If by chance we don't have any symbols we have to
                    223:                         * get out somehow anyway.  Check for the preceding
                    224:                         * procedure return in that case.
                    225:                         */
                    226:                        if (name[0] == '?' && inst_return(inst))
                    227:                                break;
                    228:
                    229:                        /*
                    230:                         * Disassemble to get the needed info for the frame.
                    231:                         */
                    232:                        if ((inst & 0xffff0000) == 0x23de0000)
                    233:                                /* lda sp,n(sp) */
                    234:                                framesize -= disp(inst) / sizeof (u_long);
                    235:                        else if ((inst & 0xfc1f0000) == 0xb41e0000)
                    236:                                /* stq X,n(sp) */
                    237:                                slot[rega(inst)] =
                    238:                                    frame + disp(inst) / sizeof (u_long);
                    239:                        else if ((inst & 0xfc000fe0) == 0x44000400 &&
                    240:                            rega(inst) == regb(inst)) {
                    241:                                /* bis X,X,Y (aka mov X,Y) */
                    242:                                /* zero is hardwired */
                    243:                                if (rega(inst) != 31)
                    244:                                        slot[rega(inst)] = slot[regc(inst)];
                    245:                                slot[regc(inst)] = 0;
                    246:                                /*
                    247:                                 * XXX In here we might special case a frame
                    248:                                 * pointer setup, i.e. mov sp, fp.
                    249:                                 */
                    250:                        } else if (inst_load(inst))
                    251:                                /* clobbers a register */
                    252:                                slot[rega(inst)] = 0;
                    253:                        else if (opcode[inst >> 26].opc_fmt == OPC_OP)
                    254:                                /* clobbers a register */
                    255:                                slot[regc(inst)] = 0;
                    256:                        /*
                    257:                         * XXX Recognize more reg clobbering instructions and
                    258:                         * set slot[reg] = 0 then too.
                    259:                         */
                    260:                }
                    261:
                    262:                /*
                    263:                 * Try to print the 6 quads that might hold the args.
                    264:                 * We print 6 of them even if there are fewer, cause we don't
                    265:                 * know the number.  Maybe we could skip the last ones
                    266:                 * that never got used.  If we cannot know the value, print
                    267:                 * a question mark.
                    268:                 */
                    269:                for (i = 0; i < 6; i++) {
                    270:                        if (i > 0)
                    271:                                (*pr)(", ");
                    272:                        if (slot[16 + i])
                    273:                                (*pr)("%lx", *slot[16 + i]);
                    274:                        else
                    275:                                (*pr)("?");
                    276:                }
                    277:
                    278: #if 0
                    279:                /*
                    280:                 * XXX This will go eventually when I trust the argument
                    281:                 * printout heuristics.
                    282:                 *
                    283:                 * Print the stack frame contents.
                    284:                 */
                    285:                (*pr)(") [%p: ", frame);
                    286:                if (framesize > 1) {
                    287:                        for (i = 0; i < framesize - 1; i++)
                    288:                                (*pr)("%lx, ", frame[i]);
                    289:                        (*pr)("%lx", frame[i]);
                    290:                }
                    291:                (*pr)("] at ");
                    292: #else
                    293:                (*pr)(") at ");
                    294: #endif
                    295:                db_printsym(pc, DB_STGY_PROC, pr);
                    296:                (*pr)("\n");
                    297:
                    298:                /*
                    299:                 * If we are looking at a Xent* routine we are in a trap
                    300:                 * context.
                    301:                 */
                    302:                if (strncmp(name, "Xent", sizeof("Xent") - 1) == 0) {
                    303:                        regs = (db_regs_t *)frame;
                    304:                        goto trapframe;
                    305:                }
                    306:
                    307:                /* Look for the return address if recorded.  */
                    308:                if (slot[26])
                    309:                        ra = *(db_addr_t *)slot[26];
                    310:                else
                    311:                        break;
                    312:
                    313:                /* Advance to the next frame.  */
                    314:                frame += framesize;
                    315:                pc = ra;
                    316:        }
                    317: }

CVSweb