diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1997-07-23 23:29:46 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1997-07-23 23:29:46 +0000 |
commit | 6795034d67a953224bcd5c420617fc79a5b32c6c (patch) | |
tree | bd115a7d218cdbf07be75e7c2b829a4086866945 /sys/arch | |
parent | ac141e4cbce829067ca6aefe17467a5487c84a62 (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.c | 140 |
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] = ®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]; -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; } } |