Merge branch 'vendor/TNFTP'
[dragonfly.git] / usr.bin / doscmd / trace.c
1 /*
2  * Copyright (c) 1992, 1993, 1996
3  *      Berkeley Software Design, Inc.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Berkeley Software
16  *      Design, Inc.
17  *
18  * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  *      BSDI trace.c,v 2.2 1996/04/08 19:33:07 bostic Exp
31  *
32  * $FreeBSD: src/usr.bin/doscmd/trace.c,v 1.3.2.1 2002/04/25 11:04:51 tg Exp $
33  * $DragonFly: src/usr.bin/doscmd/trace.c,v 1.2 2003/06/17 04:29:26 dillon Exp $
34  */
35
36 #include "doscmd.h"
37 #include "trap.h"
38
39 int             tmode = 0;
40
41 static u_short  *saddr;
42 static u_char   *iaddr, ibyte;
43
44 /* locals */
45 static void             printtrace(regcontext_t *REGS, char *buf);
46 static inline void      showstate(long, long, char);
47
48 /*
49  * Before exiting to VM86 mode:
50  * 1) Always set the trap flag.
51  * 2) If this is a POPF or IRET instruction, set the trap flag in the saved
52  *    flag state on the stack.
53  * On enterint from VM86 mode:
54  * 1) Restore the trap flag from our saved flag state.
55  * 2) If we just finished a POPF or IRET unstruction, patch the saved flag
56  *    state on the stack.
57  */
58
59 int tracetype;
60
61 int
62 resettrace(regcontext_t *REGS)
63 {
64     if ((R_EFLAGS & PSL_VM) == 0)               /* invalid unless handling a vm86 process */
65         return (0);
66
67 /* XXX */ return 1;
68
69     switch (tracetype) {
70     case 1:
71         R_EFLAGS &= ~PSL_T;
72         tracetype = 0;
73         return (1);
74
75     case 2:
76         if ((u_char *)MAKEPTR(R_CS, R_IP - 1) == iaddr)
77             R_IP --;
78         *iaddr = ibyte;
79         tracetype = 0;
80         return (1);
81
82     case 3:
83     case 4:
84         R_EFLAGS &= ~PSL_T;
85         *saddr &= ~PSL_T;
86         tracetype = 0;
87         return (1);
88     }
89     return (0);
90 }
91
92 void
93 tracetrap(regcontext_t *REGS)
94 {
95     u_char *addr;
96     int n;
97     char buf[100];
98     
99     if ((R_EFLAGS & PSL_VM) == 0)
100         return;
101     
102     addr = (u_char *)MAKEPTR(R_CS, R_IP);
103
104     n = i386dis(R_CS, R_IP, addr, buf, 0);
105     printtrace(REGS, buf);
106
107 /* XXX */
108     R_EFLAGS |= PSL_T;
109     return;
110 /* XXX */
111     
112
113     switch (addr[0]) {
114     case REPNZ:
115     case REPZ:
116         tracetype = 2;
117         iaddr = (u_char *)MAKEPTR(R_CS, R_IP + n);
118         break;
119     case PUSHF:
120         tracetype = 4;
121         saddr = (u_short *)MAKEPTR(R_SS, R_SP - 2);
122         break;
123     case POPF:
124         tracetype = 3;
125         saddr = (u_short *)MAKEPTR(R_SS, R_SP + 0);
126         break;
127     case IRET:
128         tracetype = 3;
129         saddr = (u_short *)MAKEPTR(R_SS, R_SP + 4);
130 #if 0
131         printf("IRET: %04x %04x %04x\n",
132                ((u_short *)MAKEPTR(R_SS, R_SP))[0],
133                ((u_short *)MAKEPTR(R_SS, R_SP))[1],
134                ((u_short *)MAKEPTR(R_SS, R_SP))[2]);
135 #endif  
136         break;
137     case OPSIZ:
138         switch (addr[1]) {
139         case PUSHF:
140             tracetype = 4;
141             saddr = (u_short *)MAKEPTR(R_SS, R_SP - 4);
142             break;
143         case POPF:
144             tracetype = 3;
145             saddr = (u_short *)MAKEPTR(R_SS, R_SP + 0);
146             break;
147         case IRET:
148             tracetype = 3;
149             saddr = (u_short *)MAKEPTR(R_SS, R_SP + 8);
150             break;
151         default:
152             tracetype = 1;
153             break;
154         }
155     default:
156         tracetype = 1;
157         break;
158     }
159
160     switch (tracetype) {
161     case 1:
162     case 4:
163         if (R_EFLAGS & PSL_T)
164             tracetype = 0;
165         else
166             R_EFLAGS |= PSL_T;
167         break;
168     case 2:
169         if (*iaddr == TRACETRAP)
170             tracetype = 0;
171         else {
172             ibyte = *iaddr;
173             *iaddr = TRACETRAP;
174         }
175         break;
176     case 3:
177         R_EFLAGS |= PSL_T;
178         if (*saddr & PSL_T)
179             tracetype = 0;
180         else
181             *saddr |= PSL_T;
182         break;
183     }
184 }
185
186 static inline void
187 showstate(long flags, long flag, char f)
188 {
189     putc((flags & flag) ? f : ' ', debugf);
190 }
191
192 static void
193 printtrace(regcontext_t *REGS, char *buf)
194 {
195
196     static int first = 1;
197 #if BIG_DEBUG
198     u_char *addr = (u_char *)MAKEPTR(R_CS, R_IP);
199 #endif
200
201     if (first) {
202         fprintf(debugf, "%4s:%4s "
203 #if BIG_DEBUG
204                ".. .. .. .. .. .. "
205 #endif
206                "%-30s "
207                "%4s %4s %4s %4s %4s %4s %4s %4s %4s %4s %4s\n",
208                 "CS", "IP", "instruction",
209                 "AX", "BX", "CX", "DX",
210                 "DI", "SI", "SP", "BP",
211                 "SS", "DS", "ES");
212         first = 0;
213     }
214
215     fprintf(debugf, "%04x:%04x "
216 #if BIG_DEBUG
217             "%02x %02x %02x %02x %02x %02x "
218 #endif
219             "%-30s "
220             "%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x ",
221             R_CS, R_IP,
222 #if BIG_DEBUG
223             addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
224 #endif
225             buf,
226             R_AX, R_BX, R_CX, R_DX, R_DI, R_SI, R_SP, R_BP, R_SS, R_DS, R_ES);
227 #if 0
228     fprintf(debugf, "%04x %04x %04x %04x ",
229             ((u_short *)VECPTR(0x0D760FCA-14))[0],
230             ((u_short *)VECPTR(0x0D760FCA-14))[1],
231             ((u_short *)VECPTR(0x0D760F7A+8))[0],
232             ((u_short *)VECPTR(0x0D760F7A+8))[1]);
233 #endif
234     showstate(R_EFLAGS, PSL_C, 'C');
235     showstate(R_EFLAGS, PSL_PF, 'P');
236     showstate(R_EFLAGS, PSL_AF, 'c');
237     showstate(R_EFLAGS, PSL_Z, 'Z');
238     showstate(R_EFLAGS, PSL_N, 'N');
239     showstate(R_EFLAGS, PSL_T, 'T');
240     showstate(R_EFLAGS, PSL_I, 'I');
241     showstate(R_EFLAGS, PSL_D, 'D');
242     showstate(R_EFLAGS, PSL_V, 'V');
243     showstate(R_EFLAGS, PSL_NT, 'n');
244     showstate(R_EFLAGS, PSL_RF, 'r');
245     showstate(R_EFLAGS, PSL_VM, 'v');
246     showstate(R_EFLAGS, PSL_AC, 'a');
247     showstate(R_EFLAGS, PSL_VIF, 'i');
248     showstate(R_EFLAGS, PSL_VIP, 'p');
249     putc('\n', debugf);
250 }