Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/alpha/alpha After some banging and bashing, commit ...
details: https://anonhg.NetBSD.org/src/rev/b37b70622d31
branches: trunk
changeset: 473383:b37b70622d31
user: ross <ross%NetBSD.org@localhost>
date: Mon May 31 20:42:15 1999 +0000
description:
After some banging and bashing, commit Jason's new ddb traceback code.
diffstat:
sys/arch/alpha/alpha/db_trace.c | 331 +++++++++++++++++++++++++++++++++++++++-
1 files changed, 328 insertions(+), 3 deletions(-)
diffs (truncated from 357 to 300 lines):
diff -r 64927c9dea43 -r b37b70622d31 sys/arch/alpha/alpha/db_trace.c
--- a/sys/arch/alpha/alpha/db_trace.c Mon May 31 20:40:23 1999 +0000
+++ b/sys/arch/alpha/alpha/db_trace.c Mon May 31 20:42:15 1999 +0000
@@ -1,19 +1,113 @@
-/* $NetBSD: db_trace.c,v 1.1 1997/09/06 02:00:50 thorpej Exp $ */
+/* $NetBSD: db_trace.c,v 1.2 1999/05/31 20:42:15 ross 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.
+ *
+ * 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 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 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.
+ */
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
-__KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.1 1997/09/06 02:00:50 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.2 1999/05/31 20:42:15 ross Exp $");
#include <sys/param.h>
#include <sys/proc.h>
#include <machine/db_machdep.h>
+#include <alpha/alpha/db_instruction.h>
+
#include <ddb/db_sym.h>
#include <ddb/db_access.h>
#include <ddb/db_variables.h>
#include <ddb/db_output.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 */
+};
+
+/*
+ * We use several symbols to take special action:
+ *
+ * Trap vectors, which use a different (fixed-size) stack frame:
+ *
+ * XentArith
+ * XentIF
+ * XentInt
+ * XentMM
+ * XentSys
+ * XentUna
+ */
+static struct special_symbol {
+ const char *ss_name;
+ db_addr_t ss_val;
+} special_symbols[] = {
+ { "XentArith", 0 },
+ { "XentIF", 0 },
+ { "XentInt", 0 },
+ { "XentMM", 0 },
+ { "XentSys", 0 },
+ { "XentUna", 0 },
+};
+
+#define SYM_XentArith 0
+#define SYM_XentIF 1
+#define SYM_XentInt 2
+#define SYM_XentMM 3
+#define SYM_XentSys 4
+#define SYM_XentUna 5
+#define SYM_COUNT 6
+
+#define SYM_IS_TRAPSYMBOL(v) \
+ ((v) == special_symbols[SYM_XentArith].ss_val || \
+ (v) == special_symbols[SYM_XentIF].ss_val || \
+ (v) == special_symbols[SYM_XentInt].ss_val || \
+ (v) == special_symbols[SYM_XentMM].ss_val || \
+ (v) == special_symbols[SYM_XentSys].ss_val || \
+ (v) == special_symbols[SYM_XentUna].ss_val)
+
+static void init_special_symbols __P((void));
+static void decode_prologue __P((db_addr_t, db_addr_t, struct prologue_info *));
+
+static boolean_t special_symbols_initted;
+static boolean_t can_trace;
+
void
db_stack_trace_cmd(addr, have_addr, count, modif)
db_expr_t addr;
@@ -21,5 +115,236 @@
db_expr_t count;
char *modif;
{
- /* nothing, yet. */
+ struct prologue_info pi;
+ db_addr_t callpc, frame, symval;
+ db_expr_t diff;
+ db_sym_t sym;
+ char *symname;
+ struct trapframe *tf;
+ boolean_t ra_from_tf;
+
+ if (special_symbols_initted == FALSE)
+ init_special_symbols();
+
+ if (can_trace == FALSE) {
+ db_printf("unable to perform back trace\n");
+ return;
+ }
+
+ if (count == -1)
+ count = 65535;
+
+ if (!have_addr)
+ addr = DDB_REGS->tf_regs[FRAME_SP] - FRAME_SIZE * 8;
+ tf = (struct trapframe *)addr;
+
+ have_trapframe:
+ frame = (db_addr_t)tf + FRAME_SIZE * 8;
+ callpc = tf->tf_regs[FRAME_PC];
+ ra_from_tf = TRUE; /* get initial RA from here */
+
+ while (count--) {
+ sym = db_search_symbol(callpc, DB_STGY_ANY, &diff);
+ if (sym == DB_SYM_NULL)
+ break;
+
+ db_symbol_values(sym, &symname, (db_expr_t *)&symval);
+
+ if (callpc < symval) {
+ db_printf("symbol botch: callpc 0x%lx < "
+ "func 0x%lx (%s)\n", callpc, symval, symname);
+ return;
+ }
+
+ /*
+ * 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).
+ */
+ 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)) {
+ tf = (struct trapframe *)frame;
+
+ if (symval == special_symbols[SYM_XentArith].ss_val)
+ db_printf("--- arithmetic trap ---\n");
+
+ if (symval == special_symbols[SYM_XentIF].ss_val)
+ db_printf("--- instruction fault ---\n");
+
+ if (symval == special_symbols[SYM_XentInt].ss_val)
+ db_printf("--- interrupt ---\n");
+
+ if (symval == special_symbols[SYM_XentMM].ss_val)
+ db_printf("--- memory management fault ---\n");
+
+ if (symval == special_symbols[SYM_XentSys].ss_val) {
+ /* Syscall number is in v0. */
+ db_printf("--- syscall (number %ld) ---\n",
+ tf->tf_regs[FRAME_V0]);
+ }
+
+ if (symval == special_symbols[SYM_XentUna].ss_val)
+ db_printf("--- unaligned access fault ---\n");
+
+ /*
+ * Terminate the search if this frame returns to
+ * usermode (i.e. this is the top of the kernel
+ * stack).
+ */
+ if (tf->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) {
+ db_printf("--- user mode ---\n");
+ break;
+ }
+
+ goto have_trapframe;
+ }
+
+ /*
+ * 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);
+ 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 == FALSE) {
+ db_printf("--- root of call graph ---\n");
+ break;
+ }
+ callpc = tf->tf_regs[FRAME_RA];
+ } else
+ callpc = *(u_long *)(frame + pi.pi_reg_offset[26]);
+ ra_from_tf = FALSE;
+#if 0
+ /*
+ * The call was actually made at RA - 4; the PC is
+ * updated before being stored in RA.
+ */
+ callpc -= 4;
+#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)
+ db_addr_t callpc, func;
+ struct prologue_info *pi;
+{
+ 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) { \
+ db_printf("frame size botch: adjust register offsets?\n"); \
+ } \
+} while (0)
+
+ for (pc = func; pc < callpc; pc += sizeof(alpha_instruction)) {
+ ins.bits = *(unsigned int *)pc;
+
+ if (ins.mem_format.opcode == op_lda &&
+ ins.mem_format.ra == 30 &&
+ ins.mem_format.rb == 30) {
+ /*
Home |
Main Index |
Thread Index |
Old Index