diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2001-03-04 19:19:44 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2001-03-04 19:19:44 +0000 |
commit | a573b477e71dc804e389953d9a30d2882335e524 (patch) | |
tree | bf4e5b59922a56de908fd493ade2228e2b37b272 /sys | |
parent | 1e43e7a6a586e724b3957e42b3e444e35860067b (diff) |
Revert to our old traceback code, with heuristic argument printout.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/alpha/alpha/db_interface.c | 32 | ||||
-rw-r--r-- | sys/arch/alpha/alpha/db_trace.c | 583 | ||||
-rw-r--r-- | sys/arch/alpha/include/db_machdep.h | 251 |
3 files changed, 384 insertions, 482 deletions
diff --git a/sys/arch/alpha/alpha/db_interface.c b/sys/arch/alpha/alpha/db_interface.c index 9d9fd9c2e08..810c5ab30e7 100644 --- a/sys/arch/alpha/alpha/db_interface.c +++ b/sys/arch/alpha/alpha/db_interface.c @@ -1,4 +1,4 @@ -/* $OpenBSD: db_interface.c,v 1.11 2000/11/08 21:27:08 ericj Exp $ */ +/* $OpenBSD: db_interface.c,v 1.12 2001/03/04 19:19:43 niklas Exp $ */ /* $NetBSD: db_interface.c,v 1.8 1999/10/12 17:08:57 jdolecek Exp $ */ /* @@ -228,7 +228,9 @@ void db_machine_init() { +#if 0 db_machine_commands_install(db_machine_cmds); +#endif } /* @@ -533,3 +535,31 @@ db_branch_taken(ins, pc, regs) return (newpc); } + +/* + * Validate an address for use as a breakpoint. We cannot let some + * addresses have breakpoints as the ddb code itself uses that codepath. + * Recursion and kernel stack space exhaustion will follow. + */ +int +db_valid_breakpoint(addr) + db_addr_t addr; +{ + char *name; + db_expr_t offset; + + db_find_sym_and_offset(addr, &name, &offset); + if (name && strcmp(name, "alpha_pal_swpipl") == 0) + return (0); + return (1); +} + +db_addr_t +next_instr_address(pc, branch) + db_addr_t pc; + int branch; +{ + if (!branch) + return (pc + sizeof(int)); + return (branch_taken(*(u_int *)pc, pc, getreg_val, DDB_REGS)); +} diff --git a/sys/arch/alpha/alpha/db_trace.c b/sys/arch/alpha/alpha/db_trace.c index a972c24c0a5..48ce033bcbf 100644 --- a/sys/arch/alpha/alpha/db_trace.c +++ b/sys/arch/alpha/alpha/db_trace.c @@ -1,16 +1,8 @@ -/* $OpenBSD: db_trace.c,v 1.6 2000/11/08 19:16:58 ericj Exp $ */ -/* $NetBSD: db_trace.c,v 1.6 2000/05/26 03:34:24 jhawk Exp $ */ +/* $OpenBSD: db_trace.c,v 1.7 2001/03/04 19:19:42 niklas Exp $ */ -/*- - * Copyright (c) 1999 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, - * NASA Ames Research Center. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Ross Harvey. +/* + * Copyright (c) 1997 Niklas Hallqvist. All rights reserverd. + * Copyright (c) 1997 Theo de Raadt. All rights reserverd. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -22,352 +14,305 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. + * This product includes software developed by Niklas Hallqvist and + * Theo de Raadt. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <sys/types.h> #include <sys/param.h> #include <sys/systm.h> -#include <sys/proc.h> -#include <sys/user.h> -#include <machine/db_machdep.h> -#include <alpha/alpha/db_instruction.h> +#include <vm/vm.h> + +#include <machine/db_machdep.h> +#include <machine/frame.h> -#include <ddb/db_sym.h> #include <ddb/db_access.h> -#include <ddb/db_variables.h> +#include <ddb/db_command.h> #include <ddb/db_output.h> +#include <ddb/db_sym.h> +#include <ddb/db_variables.h> +#include <ddb/db_extern.h> #include <ddb/db_interface.h> -/* - * Information about the `standard' Alpha function prologue. - */ -struct prologue_info { - int pi_reg_offset[32]; /* offset of registers in stack frame */ - u_int32_t pi_regmask; /* which registers are in frame */ - int pi_frame_size; /* frame size */ +extern int etext; + +struct opcode opcode[] = { + { OPC_PAL, "call_pal", 0 }, /* 00 */ + { OPC_RES, "opc01", 0 }, /* 01 */ + { OPC_RES, "opc02", 0 }, /* 02 */ + { OPC_RES, "opc03", 0 }, /* 03 */ + { OPC_RES, "opc04", 0 }, /* 04 */ + { OPC_RES, "opc05", 0 }, /* 05 */ + { OPC_RES, "opc06", 0 }, /* 06 */ + { OPC_RES, "opc07", 0 }, /* 07 */ + { OPC_MEM, "lda", 1 }, /* 08 */ + { OPC_MEM, "ldah", 1 }, /* 09 */ + { OPC_RES, "opc0a", 0 }, /* 0A */ + { OPC_MEM, "ldq_u", 1 }, /* 0B */ + { OPC_RES, "opc0c", 0 }, /* 0C */ + { OPC_RES, "opc0d", 0 }, /* 0D */ + { OPC_RES, "opc0e", 0 }, /* 0E */ + { OPC_MEM, "stq_u", 1 }, /* 0F */ + { OPC_OP, "inta", 0 }, /* 10 */ + { OPC_OP, "intl", 0 }, /* 11 */ + { OPC_OP, "ints", 0 }, /* 12 */ + { OPC_OP, "intm", 0 }, /* 13 */ + { OPC_RES, "opc14", 0 }, /* 14 */ + { OPC_OP, "fltv", 1 }, /* 15 */ + { OPC_OP, "flti", 1 }, /* 16 */ + { OPC_OP, "fltl", 1 }, /* 17 */ + { OPC_MEM, "misc", 0 }, /* 18 */ + { OPC_PAL, "pal19", 0 }, /* 19 */ + { OPC_MEM, "jsr", 0 }, /* 1A */ + { OPC_PAL, "pal1b", 0 }, /* 1B */ + { OPC_RES, "opc1c", 0 }, /* 1C */ + { OPC_PAL, "pal1d", 0 }, /* 1D */ + { OPC_PAL, "pal1e", 0 }, /* 1E */ + { OPC_PAL, "pal1f", 0 }, /* 1F */ + { OPC_MEM, "ldf", 1 }, /* 20 */ + { OPC_MEM, "ldg", 1 }, /* 21 */ + { OPC_MEM, "lds", 1 }, /* 22 */ + { OPC_MEM, "ldt", 1 }, /* 23 */ + { OPC_MEM, "stf", 1 }, /* 24 */ + { OPC_MEM, "stg", 1 }, /* 25 */ + { OPC_MEM, "sts", 1 }, /* 26 */ + { OPC_MEM, "stt", 1 }, /* 27 */ + { OPC_MEM, "ldl", 1 }, /* 28 */ + { OPC_MEM, "ldq", 1 }, /* 29 */ + { OPC_MEM, "ldl_l", 1 }, /* 2A */ + { OPC_MEM, "ldq_l", 1 }, /* 2B */ + { OPC_MEM, "stl", 1 }, /* 2C */ + { OPC_MEM, "stq", 1 }, /* 2D */ + { OPC_MEM, "stl_c", 1 }, /* 2E */ + { OPC_MEM, "stq_c", 1 }, /* 2F */ + { OPC_BR, "br", 1 }, /* 30 */ + { OPC_BR, "fbeq", 1 }, /* 31 */ + { OPC_BR, "fblt", 1 }, /* 32 */ + { OPC_BR, "fble", 1 }, /* 33 */ + { OPC_BR, "bsr", 1 }, /* 34 */ + { OPC_BR, "fbne", 1 }, /* 35 */ + { OPC_BR, "fbge", 1 }, /* 36 */ + { OPC_BR, "fbgt", 1 }, /* 37 */ + { OPC_BR, "blbc", 1 }, /* 38 */ + { OPC_BR, "beq", 1 }, /* 39 */ + { OPC_BR, "blt", 1 }, /* 3A */ + { OPC_BR, "ble", 1 }, /* 3B */ + { OPC_BR, "blbs", 1 }, /* 3C */ + { OPC_BR, "bne", 1 }, /* 3D */ + { OPC_BR, "bge", 1 }, /* 3E */ + { OPC_BR, "bgt", 1 }, /* 3F */ }; +static __inline int sext __P((u_int)); +static __inline int rega __P((u_int)); +static __inline int regb __P((u_int)); +static __inline int regc __P((u_int)); +static __inline int disp __P((u_int)); + +static __inline int +sext(x) + u_int x; +{ + return ((x & 0x8000) ? -(-x & 0xffff) : (x & 0xffff)); +} + +static __inline int +rega(x) + u_int x; +{ + return ((x >> 21) & 0x1f); +} + +static __inline int +regb(x) + u_int x; +{ + return ((x >> 16) & 0x1f); +} + +static __inline int +regc(x) + u_int x; +{ + return (x & 0x1f); +} + +static __inline int +disp(x) + u_int x; +{ + return (sext(x & 0xffff)); +} + /* - * We use several symbols to take special action: + * XXX There are a couple of problems with this code: + * + * The argument list printout code is likely to get confused. + * + * It relies on the conventions of gcc code generation. * - * Trap vectors, which use a different (fixed-size) stack frame: + * It uses heuristics to calculate the framesize, and might get it wrong. * - * XentArith - * XentIF - * XentInt - * XentMM - * XentSys - * XentUna + * It doesn't yet use the framepointer if available. + * + * The address argument can only be used for pointing at trapframes + * since a frame pointer of its own serves no good on the alpha, + * you need a pc value too. + * + * The heuristics used for tracing through a trap relies on having + * symbols available. */ - -static struct special_symbol { - void (*ss_val) __P((void)); - const char *ss_note; -} special_symbols[] = { - { (void (*)(void))&XentArith, "arithmetic trap" }, - { (void (*)(void))&XentIF, "instruction fault" }, - { (void (*)(void))&XentInt, "interrupt" }, - { (void (*)(void))&XentMM, "memory management fault" }, - { (void (*)(void))&XentSys, "syscall" }, - { (void (*)(void))&XentUna, "unaligned access fault" }, - { (void (*)(void))&XentRestart, "console restart" }, - { NULL } -}; - -static void decode_prologue __P((db_addr_t, db_addr_t, struct prologue_info *, - int (*)(const char *, ...))); -static void decode_syscall __P((int, struct proc *, - int (*)(const char *, ...))); -static int sym_is_trapsymbol __P((void *)); - void db_stack_trace_cmd(addr, have_addr, count, modif) - db_expr_t addr; - boolean_t have_addr; - db_expr_t count; - char *modif; + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; { - db_addr_t callpc, frame, symval; - struct prologue_info pi; - void *symval_f; - db_expr_t diff; - db_sym_t sym; - int i; - u_long tfps; - char *symname; - struct pcb *pcbp; - char c, *cp = modif; - struct trapframe *tf; - boolean_t ra_from_tf; - boolean_t ra_from_pcb; - u_long last_ipl = ~0L; - struct proc *p = NULL; - boolean_t trace_thread = FALSE; - boolean_t have_trapframe = FALSE; + u_long *frame; + int i, framesize; + db_addr_t pc, ra; + u_int inst; + char *name; + db_expr_t offset; + db_regs_t *regs; + u_long *slot[32]; - while ((c = *cp++) != 0) - trace_thread |= c == 't'; + bzero(slot, sizeof(slot)); + if (count == -1) + count = 65535; - if (!have_addr) { - p = curproc; - addr = DDB_REGS->tf_regs[FRAME_SP] - FRAME_SIZE * 8; - tf = (struct trapframe *)addr; - have_trapframe = 1; - } else { - if (trace_thread) { - db_printf("trace: pid %d ", (int)addr); - p = pfind(addr); - if (p == NULL) { - db_printf("not found\n"); - return; - } - if ((p->p_flag & P_INMEM) == 0) { - db_printf("swapped out\n"); - return; - } - pcbp = &p->p_addr->u_pcb; - addr = (db_expr_t)pcbp->pcb_hw.apcb_ksp; - callpc = pcbp->pcb_context[7]; - db_printf("at 0x%lx\n", addr); - } else { - db_printf("alpha trace requires known PC =eject=\n"); - return; - } - frame = addr; - } + regs = have_addr ? (db_regs_t *)addr : DDB_REGS; +trapframe: + /* remember where various registers are stored */ + for (i = 0; i < 31; i++) + slot[i] = ®s->tf_regs[0] + + ((u_long *)db_regs[i].valuep - &ddb_regs.tf_regs[0]); + frame = (u_long *)regs->tf_regs[FRAME_SP]; + pc = (db_addr_t)regs->tf_regs[FRAME_PC]; + ra = (db_addr_t)regs->tf_regs[FRAME_RA]; - while (count--) { - if (have_trapframe) { - frame = (db_addr_t)tf + FRAME_SIZE * 8; - callpc = tf->tf_regs[FRAME_PC]; - ra_from_tf = TRUE; - have_trapframe = 0; + while (count-- && pc >= (db_addr_t)KERNBASE && pc < (db_addr_t)&etext) { + db_find_sym_and_offset(pc, &name, &offset); + if (!name) { + name = "?"; + /* Limit the search for procedure start */ + offset = 65536; } - sym = db_search_symbol(callpc, DB_STGY_ANY, &diff); - if (sym == DB_SYM_NULL) - break; + db_printf("%s(", name); - db_symbol_values(sym, &symname, (db_expr_t *)&symval); - symval_f = (void *)symval; + framesize = 0; + for (i = sizeof (int); i <= offset; i += sizeof (int)) { + inst = *(u_int *)(pc - i); + + /* + * If by chance we don't have any symbols we have to + * get out somehow anyway. Check for the preceding + * procedure return in that case. + */ + if (name[0] == '?' && inst_return(inst)) + break; - if (callpc < symval) { - db_printf("symbol botch: callpc 0x%lx < " - "func 0x%lx (%s)\n", callpc, symval, symname); - return; + /* + * Disassemble to get the needed info for the frame. + */ + if ((inst & 0xffff0000) == 0x23de0000) + /* lda sp,n(sp) */ + framesize -= disp(inst) / sizeof (u_long); + else if ((inst & 0xfc1f0000) == 0xb41e0000) + /* stq X,n(sp) */ + slot[rega(inst)] = + frame + disp(inst) / sizeof (u_long); + else if ((inst & 0xfc000fe0) == 0x44000400 && + rega(inst) == regb(inst)) { + /* bis X,X,Y (aka mov X,Y) */ + /* zero is hardwired */ + if (rega(inst) != 31) + slot[rega(inst)] = slot[regc(inst)]; + slot[regc(inst)] = 0; + /* + * XXX In here we might special case a frame + * pointer setup, i.e. mov sp, fp. + */ + } else if (inst_load(inst)) + /* clobbers a register */ + slot[rega(inst)] = 0; + else if (opcode[inst >> 26].opc_fmt == OPC_OP) + /* clobbers a register */ + slot[regc(inst)] = 0; + /* + * XXX Recognize more reg clobbering instructions and + * set slot[reg] = 0 then too. + */ } /* - * XXX Printing out arguments is Hard. We'd have to - * keep lots of state as we traverse the frame, figuring - * out where the arguments to the function are stored - * on the stack. - * - * Even worse, they may be stored to the stack _after_ - * being modified in place; arguments are passed in - * registers. - * - * So, in order for this to work reliably, we pretty much - * have to have a kernel built with `cc -g': - * - * - The debugging symbols would tell us where the - * arguments are, how many there are, if there were - * any passed on the stack, etc. - * - * - Presumably, the compiler would be careful to - * store the argument registers on the stack before - * modifying the registers, so that a debugger could - * know what those values were upon procedure entry. - * - * Because of this, we don't bother. We've got most of the - * benefit of back tracking without the arguments, and we - * could get the arguments if we use a remote source-level - * debugger (for serious debugging). + * Try to print the 6 quads that might hold the args. + * We print 6 of them even if there are fewer, cause we don't + * know the number. Maybe we could skip the last ones + * that never got used. If we cannot know the value, print + * a question mark. */ - db_printf("%s() at ", symname); - db_printsym(callpc, DB_STGY_PROC); - db_printf("\n"); - - /* - * If we are in a trap vector, frame points to a - * trapframe. - */ - if (sym_is_trapsymbol(symval_f)) { - tf = (struct trapframe *)frame; - - for (i = 0; special_symbols[i].ss_val != NULL; ++i) - if (symval_f == special_symbols[i].ss_val) - db_printf("--- %s", - special_symbols[i].ss_note); - - tfps = tf->tf_regs[FRAME_PS]; - if (symval_f == &XentSys) - decode_syscall(tf->tf_regs[FRAME_V0], p, db_printf); - if ((tfps & ALPHA_PSL_IPL_MASK) != last_ipl) { - last_ipl = tfps & ALPHA_PSL_IPL_MASK; - if (symval_f != &XentSys) - db_printf(" (from ipl %ld)", last_ipl); - } - db_printf(" ---\n"); - if (tfps & ALPHA_PSL_USERMODE) { - db_printf("--- user mode ---\n"); - break; /* Terminate search. */ - } - have_trapframe = 1; - continue; + for (i = 0; i < 6; i++) { + if (i > 0) + db_printf(", "); + if (slot[16 + i]) + db_printf("%lx", *slot[16 + i]); + else + db_printf("?"); } - /* - * This is a bit trickier; we must decode the function - * prologue to find the saved RA. - * - * XXX How does this interact w/ alloca()?! - */ - decode_prologue(callpc, symval, &pi, db_printf); - if ((pi.pi_regmask & (1 << 26)) == 0) { - /* - * No saved RA found. We might have RA from - * the trap frame, however (e.g trap occurred - * in a leaf call). If not, we've found the - * root of the call graph. - */ - if (ra_from_tf) - callpc = tf->tf_regs[FRAME_RA]; - else { - db_printf("--- root of call graph ---\n"); - break; - } - } else - callpc = *(u_long *)(frame + pi.pi_reg_offset[26]); - ra_from_tf = ra_from_pcb = FALSE; #if 0 /* - * The call was actually made at RA - 4; the PC is - * updated before being stored in RA. + * XXX This will go eventually when I trust the argument + * printout heuristics. + * + * Print the stack frame contents. */ - callpc -= 4; + db_printf(") [%p: ", frame); + if (framesize > 1) { + for (i = 0; i < framesize - 1; i++) + db_printf("%lx, ", frame[i]); + db_printf("%lx", frame[i]); + } + db_printf("] at "); +#else + db_printf(") at "); #endif - frame += pi.pi_frame_size; - } -} - -/* - * Decode the function prologue for the function we're in, and note - * which registers are stored where, and how large the stack frame is. - */ -static void -decode_prologue(callpc, func, pi, pr) - db_addr_t callpc, func; - struct prologue_info *pi; - int (*pr) __P((const char *, ...)); -{ - long signed_immediate; - alpha_instruction ins; - db_expr_t pc; - - pi->pi_regmask = 0; - pi->pi_frame_size = 0; - -#define CHECK_FRAMESIZE \ -do { \ - if (pi->pi_frame_size != 0) { \ - (*pr)("frame size botch: adjust register offsets?\n"); \ - } \ -} while (0) - - for (pc = func; pc < callpc; pc += sizeof(alpha_instruction)) { - ins.bits = *(unsigned int *)pc; + db_printsym(pc, DB_STGY_PROC); + db_printf("\n"); - if (ins.mem_format.opcode == op_lda && - ins.mem_format.ra == 30 && - ins.mem_format.rb == 30) { - /* - * GCC 2.7-style stack adjust: - * - * lda sp, -64(sp) - */ - signed_immediate = (long)ins.mem_format.displacement; -#if 1 - if (signed_immediate > 0) - (*pr)("prologue botch: displacement %ld\n", - signed_immediate); -#endif - CHECK_FRAMESIZE; - pi->pi_frame_size += -signed_immediate; - } else if (ins.operate_lit_format.opcode == op_arit && - ins.operate_lit_format.function == op_subq && - ins.operate_lit_format.ra == 30 && - ins.operate_lit_format.rc == 30) { - /* - * EGCS-style stack adjust: - * - * subq sp, 64, sp - */ - CHECK_FRAMESIZE; - pi->pi_frame_size += ins.operate_lit_format.literal; - } else if (ins.mem_format.opcode == op_stq && - ins.mem_format.rb == 30 && - ins.mem_format.ra != 31) { - /* Store of (non-zero) register onto the stack. */ - signed_immediate = (long)ins.mem_format.displacement; - pi->pi_regmask |= 1 << ins.mem_format.ra; - pi->pi_reg_offset[ins.mem_format.ra] = signed_immediate; + /* + * If we are looking at a Xent* routine we are in a trap + * context. + */ + if (strncmp(name, "Xent", sizeof("Xent") - 1) == 0) { + regs = (db_regs_t *)frame; + goto trapframe; } - } -} -static int -sym_is_trapsymbol(v) - void *v; -{ - int i; - - for (i = 0; special_symbols[i].ss_val != NULL; ++i) - if (v == special_symbols[i].ss_val) - return 1; - return 0; -} - -static void -decode_syscall(number, p, pr) - int number; - struct proc *p; - int (*pr) __P((const char *, ...)); -{ - db_sym_t sym; - db_expr_t diff; - char *symname, *ename; - int (*f) __P((struct proc *, void *, register_t *)); + /* Look for the return address if recorded. */ + if (slot[26]) + ra = *(db_addr_t *)slot[26]; + else + break; - (*pr)(" (%d", number); /* ) */ - if (!p) - goto out; - if (0 <= number && number < p->p_emul->e_nsysent) { - ename = p->p_emul->e_name; - f = p->p_emul->e_sysent[number].sy_call; - sym = db_search_symbol((db_addr_t)f, DB_STGY_ANY, &diff); - if (sym == DB_SYM_NULL || diff != 0) - goto out; - db_symbol_values(sym, &symname, NULL); - (*pr)(", %s.%s", ename, symname); + /* Advance to the next frame. */ + frame += framesize; + pc = ra; } -out: - (*pr)(")"); - return; } diff --git a/sys/arch/alpha/include/db_machdep.h b/sys/arch/alpha/include/db_machdep.h index c705274ba42..9436efb88b8 100644 --- a/sys/arch/alpha/include/db_machdep.h +++ b/sys/arch/alpha/include/db_machdep.h @@ -1,184 +1,111 @@ -/* $OpenBSD: db_machdep.h,v 1.10 2000/11/08 21:27:19 ericj Exp $ */ -/* $NetBSD: db_machdep.h,v 1.11 2000/06/29 09:02:57 mrg Exp $ */ +/* $OpenBSD: db_machdep.h,v 1.11 2001/03/04 19:19:43 niklas Exp $ */ /* - * Copyright (c) 1995 Carnegie-Mellon University. - * All rights reserved. + * Copyright (c) 1997 Niklas Hallqvist. All rights reserverd. * - * Author: Chris G. Demetriou + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niklas Hallqvist. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * Permission to use, copy, modify and distribute this software and - * its documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND - * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _ALPHA_DB_MACHDEP_H_ #define _ALPHA_DB_MACHDEP_H_ +/* XXX - Need to include vm.h for boolean_t */ +#include <vm/vm.h> + +#define DB_MACHINE_COMMANDS + /* - * Machine-dependent defines for new kernel debugger. + * We use Elf64 symbols in DDB. */ +#define DB_ELF_SYMBOLS +#define DB_ELFSIZE 64 -#include <sys/param.h> -#include <vm/vm.h> -#include <uvm/uvm_extern.h> -#include <machine/frame.h> - -typedef vaddr_t db_addr_t; /* address - unsigned */ -typedef long db_expr_t; /* expression - signed */ +struct opcode { + enum opc_fmt { OPC_PAL, OPC_RES, OPC_MEM, OPC_OP, OPC_BR } opc_fmt; + char *opc_name; + int opc_print; +}; +extern struct opcode opcode[]; +/* types the generic ddb module needs */ +typedef vm_offset_t db_addr_t; +typedef long db_expr_t; typedef struct trapframe db_regs_t; -db_regs_t ddb_regs; /* register state */ + +db_regs_t ddb_regs; #define DDB_REGS (&ddb_regs) #define PC_REGS(regs) ((db_addr_t)(regs)->tf_regs[FRAME_PC]) -#define BKPT_INST 0x00000080 /* breakpoint instruction */ -#define BKPT_SIZE (4) /* size of breakpoint inst */ -#define BKPT_SET(inst) (BKPT_INST) - -#define FIXUP_PC_AFTER_BREAK(regs) \ - ((regs)->tf_regs[FRAME_PC] -= BKPT_SIZE) +/* Breakpoint related definitions */ +#define BKPT_INST 0x00000080 /* call_pal bpt */ +#define BKPT_SIZE sizeof(int) +#define BKPT_SET(inst) BKPT_INST -#define SOFTWARE_SSTEP 1 /* no hardware support */ -#define IS_BREAKPOINT_TRAP(type, code) ((type) == ALPHA_KENTRY_IF && \ - (code) == ALPHA_IF_CODE_BPT) +#define IS_BREAKPOINT_TRAP(type, code) \ + ((type) == ALPHA_KENTRY_IF && (code) == ALPHA_IF_CODE_BPT) +#ifdef notyet +#define IS_WATCHPOINT_TRAP(type, code) ((type) == ALPHA_KENTRY_MM) +#else #define IS_WATCHPOINT_TRAP(type, code) 0 - -/* - * Functions needed for software single-stepping. - */ - -boolean_t db_inst_trap_return(int inst); -boolean_t db_inst_return(int inst); -boolean_t db_inst_call(int inst); -boolean_t db_inst_branch(int inst); -boolean_t db_inst_load(int inst); -boolean_t db_inst_store(int inst); -boolean_t db_inst_unconditional_flow_transfer(int inst); -db_addr_t db_branch_taken(int inst, db_addr_t pc, db_regs_t *regs); - -#define inst_trap_return(ins) db_inst_trap_return(ins) -#define inst_return(ins) db_inst_return(ins) -#define inst_call(ins) db_inst_call(ins) -#define inst_branch(ins) db_inst_branch(ins) -#define inst_load(ins) db_inst_load(ins) -#define inst_store(ins) db_inst_store(ins) -#define inst_unconditional_flow_transfer(ins) \ - db_inst_unconditional_flow_transfer(ins) -#define branch_taken(ins, pc, getreg, regs) \ - db_branch_taken((ins), (pc), (regs)) - -/* No delay slots on Alpha. */ -#define next_instr_address(v, b) ((db_addr_t) ((b) ? (v) : ((v) + 4))) - -u_long db_register_value(db_regs_t *, int); -int ddb_trap(unsigned long, unsigned long, unsigned long, - unsigned long, struct trapframe *); - -int alpha_debug(unsigned long, unsigned long, unsigned long, - unsigned long, struct trapframe *); - -/* - * We define some of our own commands. - */ -#define DB_MACHINE_COMMANDS - -/* - * We use Elf64 symbols in DDB. - */ -#define DB_ELF_SYMBOLS -#define DB_ELFSIZE 64 - -/* - * Stuff for KGDB. - */ -typedef long kgdb_reg_t; -#define KGDB_NUMREGS 66 /* from tm-alpha.h, NUM_REGS */ -#define KGDB_REG_V0 0 -#define KGDB_REG_T0 1 -#define KGDB_REG_T1 2 -#define KGDB_REG_T2 3 -#define KGDB_REG_T3 4 -#define KGDB_REG_T4 5 -#define KGDB_REG_T5 6 -#define KGDB_REG_T6 7 -#define KGDB_REG_T7 8 -#define KGDB_REG_S0 9 -#define KGDB_REG_S1 10 -#define KGDB_REG_S2 11 -#define KGDB_REG_S3 12 -#define KGDB_REG_S4 13 -#define KGDB_REG_S5 14 -#define KGDB_REG_S6 15 /* FP */ -#define KGDB_REG_A0 16 -#define KGDB_REG_A1 17 -#define KGDB_REG_A2 18 -#define KGDB_REG_A3 19 -#define KGDB_REG_A4 20 -#define KGDB_REG_A5 21 -#define KGDB_REG_T8 22 -#define KGDB_REG_T9 23 -#define KGDB_REG_T10 24 -#define KGDB_REG_T11 25 -#define KGDB_REG_RA 26 -#define KGDB_REG_T12 27 -#define KGDB_REG_AT 28 -#define KGDB_REG_GP 29 -#define KGDB_REG_SP 30 -#define KGDB_REG_ZERO 31 -#define KGDB_REG_F0 32 -#define KGDB_REG_F1 33 -#define KGDB_REG_F2 34 -#define KGDB_REG_F3 35 -#define KGDB_REG_F4 36 -#define KGDB_REG_F5 37 -#define KGDB_REG_F6 38 -#define KGDB_REG_F7 39 -#define KGDB_REG_F8 40 -#define KGDB_REG_F9 41 -#define KGDB_REG_F10 42 -#define KGDB_REG_F11 43 -#define KGDB_REG_F12 44 -#define KGDB_REG_F13 45 -#define KGDB_REG_F14 46 -#define KGDB_REG_F15 47 -#define KGDB_REG_F16 48 -#define KGDB_REG_F17 49 -#define KGDB_REG_F18 50 -#define KGDB_REG_F19 51 -#define KGDB_REG_F20 52 -#define KGDB_REG_F21 53 -#define KGDB_REG_F22 54 -#define KGDB_REG_F23 55 -#define KGDB_REG_F24 56 -#define KGDB_REG_F25 57 -#define KGDB_REG_F26 58 -#define KGDB_REG_F27 59 -#define KGDB_REG_F28 60 -#define KGDB_REG_F29 61 -#define KGDB_REG_F30 62 -#define KGDB_REG_F31 63 -#define KGDB_REG_PC 64 -#define KGDB_REG_VFP 65 - -/* Too much? Must be large enough for register transfer. */ -#define KGDB_BUFLEN 1024 +#endif + +#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->tf_regs[FRAME_PC] -= sizeof(int)) + +#define SOFTWARE_SSTEP +#define DB_VALID_BREAKPOINT(addr) db_valid_breakpoint(addr) + +/* Hack to skip GCC "unused" warnings. */ +#define inst_trap_return(ins) ((ins) & 0) /* XXX */ +#define inst_return(ins) (((ins) & 0xfc000000) == 0x68000000) + +int alpha_debug __P((unsigned long, unsigned long, unsigned long, + unsigned long, struct trapframe *)); +db_addr_t db_branch_taken __P((int, db_addr_t, db_regs_t *)); +boolean_t db_inst_branch __P((int)); +boolean_t db_inst_call __P((int)); +boolean_t db_inst_load __P((int)); +boolean_t db_inst_return __P((int)); +boolean_t db_inst_store __P((int)); +boolean_t db_inst_trap_return __P((int)); +boolean_t db_inst_unconditional_flow_transfer __P((int)); +u_long db_register_value __P((db_regs_t *, int)); +int db_valid_breakpoint __P((db_addr_t)); +int ddb_trap __P((unsigned long, unsigned long, unsigned long, + unsigned long, struct trapframe *)); +int kdb_trap __P((int, int, db_regs_t *)); +db_addr_t next_instr_address __P((db_addr_t, int)); + +#if 1 +/* Backwards compatibility until we switch all archs to use the db_ prefix */ +#define branch_taken(ins, pc, fun, regs) db_branch_taken((ins), (pc), (regs)) +#define inst_branch db_inst_branch +#define inst_call db_inst_call +#define inst_load db_inst_load +#define inst_store db_inst_store +#endif #endif /* _ALPHA_DB_MACHDEP_H_ */ |