summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1997-07-23 23:29:46 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1997-07-23 23:29:46 +0000
commit6795034d67a953224bcd5c420617fc79a5b32c6c (patch)
treebd115a7d218cdbf07be75e7c2b829a4086866945 /sys/arch
parentac141e4cbce829067ca6aefe17467a5487c84a62 (diff)
Argument lists as good as I can guess at the moment
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/alpha/alpha/db_trace.c140
1 files changed, 111 insertions, 29 deletions
diff --git a/sys/arch/alpha/alpha/db_trace.c b/sys/arch/alpha/alpha/db_trace.c
index cc898abf54f..265c418887c 100644
--- a/sys/arch/alpha/alpha/db_trace.c
+++ b/sys/arch/alpha/alpha/db_trace.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_trace.c,v 1.3 1997/07/20 06:58:57 niklas Exp $ */
+/* $OpenBSD: db_trace.c,v 1.4 1997/07/23 23:29:45 niklas Exp $ */
/*
* Copyright (c) 1997 Niklas Hallqvist. All rights reserverd.
@@ -50,11 +50,51 @@
extern int etext;
+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));
+}
+
/*
* XXX There are a couple of problems with this code:
*
- * The argument lists are *not* printed, rather we print the contents
- * of the stack frame slots.
+ * The argument list printout code is likely to get confused.
*
* It relies on the conventions of gcc code generation.
*
@@ -77,22 +117,27 @@ db_stack_trace_cmd(addr, have_addr, count, modif)
char *modif;
{
u_long *frame;
- int i, framesize, ra_index;
+ 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];
+ bzero(slot, sizeof(slot));
if (count == -1)
count = 65535;
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];
-db_printf("%p %p %lx %lx\n", regs, frame, pc, ra);
while (count-- && pc >= (db_addr_t)KERNBASE && pc < (db_addr_t)&etext) {
db_find_sym_and_offset(pc, &name, &offset);
@@ -104,8 +149,7 @@ db_printf("%p %p %lx %lx\n", regs, frame, pc, ra);
db_printf("%s(", name);
framesize = 0;
- ra_index = -1;
- for (i = sizeof(int); i <= offset; i += sizeof(int)) {
+ for (i = sizeof (int); i <= offset; i += sizeof (int)) {
inst = *(u_int *)(pc - i);
/*
@@ -117,37 +161,71 @@ db_printf("%p %p %lx %lx\n", regs, frame, pc, ra);
break;
/*
- * Disassemble to get the needed info for the frame
- * size calculation.
+ * Disassemble to get the needed info for the frame.
*/
if ((inst & 0xffff0000) == 0x23de0000)
- /* lda sp,-n(sp) */
- if (inst & 0x8000)
- framesize += (-inst) & 0xffff;
- else
- framesize -= inst & 0x7fff;
- else if ((inst & 0xffff8000) == 0xb75e0000)
- /* stq ra,+n(sp) */
- ra_index = (inst & 0x7fff) >> 3;
- else if (inst == 0x47de040f) {
- /* XXX bis sp,sp,fp : has an fp register */
- }
+ /* 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 argument saving instructions too.
+ * XXX Recognize more reg clobbering instructions and
+ * set slot[reg] = 0 then too.
*/
}
/*
- * Print the stack THINGS. It's practically impossible
- * to get at the arguments without *lots* of work, and even
- * then it might not be possible at all.
+ * 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.
*/
- if ((framesize >> 3) > 1) {
- for (i = 0; i < (framesize >> 3) - 1; i++)
+ for (i = 0; i < 6; i++) {
+ if (i > 0)
+ db_printf(", ");
+ if (slot[16 + i])
+ db_printf("%lx", *slot[16 + i]);
+ else
+ db_printf("?");
+ }
+
+#if 0
+ /*
+ * XXX This will go eventually when I trust the argument
+ * printout heuristics.
+ *
+ * Print the stack frame contents.
+ */
+ 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
db_printsym(pc, DB_STGY_PROC);
db_printf("\n");
@@ -159,9 +237,13 @@ db_printf("%p %p %lx %lx\n", regs, frame, pc, ra);
regs = (db_regs_t *)frame;
goto trapframe;
}
- if (ra_index >= 0)
- ra = (db_addr_t)frame[ra_index];
- frame = (u_long *)((vm_offset_t)frame + framesize);
+
+ /* Look for the return address if recorded. */
+ if (slot[26])
+ ra = *(db_addr_t *)slot[26];
+
+ /* Advance to the next frame. */
+ frame += framesize;
pc = ra;
}
}