diff options
Diffstat (limited to 'usr.bin/doscmd/trace.c')
-rw-r--r-- | usr.bin/doscmd/trace.c | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/usr.bin/doscmd/trace.c b/usr.bin/doscmd/trace.c new file mode 100644 index 0000000..65a6ae3 --- /dev/null +++ b/usr.bin/doscmd/trace.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 1992, 1993, 1996 + * Berkeley Software Design, Inc. All rights reserved. + * + * 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 Berkeley Software + * Design, Inc. + * + * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``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 Berkeley Software Design, Inc. 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. + * + * BSDI trace.c,v 2.2 1996/04/08 19:33:07 bostic Exp + * + * $Id: trace.c,v 1.3 1996/09/25 00:03:44 miff Exp $ + */ + +#include "doscmd.h" +#include "trap.h" + +extern FILE *debugf; +int tmode = 0; + +static u_short *saddr; +static u_char *iaddr, ibyte; + +/* locals */ +static void printtrace(regcontext_t *REGS, char *buf); + + +/* + * Before exiting to VM86 mode: + * 1) Always set the trap flag. + * 2) If this is a POPF or IRET instruction, set the trap flag in the saved + * flag state on the stack. + * On enterint from VM86 mode: + * 1) Restore the trap flag from our saved flag state. + * 2) If we just finished a POPF or IRET unstruction, patch the saved flag + * state on the stack. + */ + +int tracetype; + +int +resettrace(regcontext_t *REGS) +{ + if ((R_EFLAGS & PSL_VM) == 0) /* invalid unless handling a vm86 process */ + return (0); + +/* XXX */ return 1; + + switch (tracetype) { + case 1: + R_EFLAGS &= ~PSL_T; + tracetype = 0; + return (1); + + case 2: + if ((u_char *)MAKEPTR(R_CS, R_IP - 1) == iaddr) + R_IP --; + *iaddr = ibyte; + tracetype = 0; + return (1); + + case 3: + case 4: + R_EFLAGS &= ~PSL_T; + *saddr &= ~PSL_T; + tracetype = 0; + return (1); + } + return (0); +} + +void +tracetrap(regcontext_t *REGS) +{ + u_char *addr; + int n; + char buf[100]; + + if ((R_EFLAGS & PSL_VM) == 0) + return; + + addr = (u_char *)N_GETPTR(R_CS, R_IP); + + n = i386dis(R_CS, R_IP, addr, buf, 0); + printtrace(REGS, buf); + +/* XXX */ + R_EFLAGS |= PSL_T; + return; +/* XXX */ + + + switch (addr[0]) { + case REPNZ: + case REPZ: + tracetype = 2; + iaddr = (u_char *)MAKEPTR(R_CS, R_IP + n); + break; + case PUSHF: + tracetype = 4; + saddr = (u_short *)MAKEPTR(R_SS, R_SP - 2); + break; + case POPF: + tracetype = 3; + saddr = (u_short *)MAKEPTR(R_SS, R_SP + 0); + break; + case IRET: + tracetype = 3; + saddr = (u_short *)MAKEPTR(R_SS, R_SP + 4); +#if 0 + printf("IRET: %04x %04x %04x\n", + ((u_short *)N_GETPTR(R_SS, R_SP))[0], + ((u_short *)N_GETPTR(R_SS, R_SP))[1], + ((u_short *)N_GETPTR(R_SS, R_SP))[2]); +#endif + break; + case OPSIZ: + switch (addr[1]) { + case PUSHF: + tracetype = 4; + saddr = (u_short *)MAKEPTR(R_SS, R_SP - 4); + break; + case POPF: + tracetype = 3; + saddr = (u_short *)MAKEPTR(R_SS, R_SP + 0); + break; + case IRET: + tracetype = 3; + saddr = (u_short *)MAKEPTR(R_SS, R_SP + 8); + break; + default: + tracetype = 1; + break; + } + default: + tracetype = 1; + break; + } + + switch (tracetype) { + case 1: + case 4: + if (R_EFLAGS & PSL_T) + tracetype = 0; + else + R_EFLAGS |= PSL_T; + break; + case 2: + if (*iaddr == TRACETRAP) + tracetype = 0; + else { + ibyte = *iaddr; + *iaddr = TRACETRAP; + } + break; + case 3: + R_EFLAGS |= PSL_T; + if (*saddr & PSL_T) + tracetype = 0; + else + *saddr |= PSL_T; + break; + } +} + +inline +showstate(long flags, long flag, char f) +{ + putc((flags & flag) ? f : ' ', debugf); +} + +static void +printtrace(regcontext_t *REGS, char *buf) +{ + + static int first = 1; + u_char *addr = (u_char *)N_GETPTR(R_CS, R_IP); + char *bigfmt = "%04x:%04x " +#if BIG_DEBUG + "%02x %02x %02x %02x %02x %02x " +#endif + "%-30s " + "%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x "; + + if (first) { + fprintf(debugf, "%4s:%4s " +#if BIG_DEBUG + ".. .. .. .. .. .. " +#endif + "%-30s " + "%4s %4s %4s %4s %4s %4s %4s %4s %4s %4s %4s\n", + "CS", "IP", "instruction", + "AX", "BX", "CX", "DX", + "DI", "SI", "SP", "BP", + "SS", "DS", "ES"); + first = 0; + } + + fprintf(debugf, bigfmt, + R_CS, R_IP, +#if BIG_DEBUG + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], +#endif + buf, + R_AX, R_BX, R_CX, R_DX, R_DI, R_SI, R_SP, R_BP, R_SS, R_DS, R_ES); +#if 0 + fprintf(debugf, "%04x %04x %04x %04x ", + ((u_short *)VECPTR(0x0D760FCA-14))[0], + ((u_short *)VECPTR(0x0D760FCA-14))[1], + ((u_short *)VECPTR(0x0D760F7A+8))[0], + ((u_short *)VECPTR(0x0D760F7A+8))[1]); +#endif + showstate(R_EFLAGS, PSL_C, 'C'); + showstate(R_EFLAGS, PSL_PF, 'P'); + showstate(R_EFLAGS, PSL_AF, 'c'); + showstate(R_EFLAGS, PSL_Z, 'Z'); + showstate(R_EFLAGS, PSL_N, 'N'); + showstate(R_EFLAGS, PSL_T, 'T'); + showstate(R_EFLAGS, PSL_I, 'I'); + showstate(R_EFLAGS, PSL_D, 'D'); + showstate(R_EFLAGS, PSL_V, 'V'); + showstate(R_EFLAGS, PSL_NT, 'n'); + showstate(R_EFLAGS, PSL_RF, 'r'); + showstate(R_EFLAGS, PSL_VM, 'v'); + showstate(R_EFLAGS, PSL_AC, 'a'); + showstate(R_EFLAGS, PSL_VIF, 'i'); + showstate(R_EFLAGS, PSL_VIP, 'p'); + putc('\n', debugf); +} |