summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>2001-03-04 19:19:44 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>2001-03-04 19:19:44 +0000
commita573b477e71dc804e389953d9a30d2882335e524 (patch)
treebf4e5b59922a56de908fd493ade2228e2b37b272 /sys
parent1e43e7a6a586e724b3957e42b3e444e35860067b (diff)
Revert to our old traceback code, with heuristic argument printout.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/alpha/alpha/db_interface.c32
-rw-r--r--sys/arch/alpha/alpha/db_trace.c583
-rw-r--r--sys/arch/alpha/include/db_machdep.h251
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] = &regs->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_ */