xref: /dflybsd-src/contrib/gdb-7/gdb/stubs/i386-stub.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
1*ef5ccd6cSJohn Marino /****************************************************************************
2*ef5ccd6cSJohn Marino 
3*ef5ccd6cSJohn Marino 		THIS SOFTWARE IS NOT COPYRIGHTED
4*ef5ccd6cSJohn Marino 
5*ef5ccd6cSJohn Marino    HP offers the following for use in the public domain.  HP makes no
6*ef5ccd6cSJohn Marino    warranty with regard to the software or it's performance and the
7*ef5ccd6cSJohn Marino    user accepts the software "AS IS" with all faults.
8*ef5ccd6cSJohn Marino 
9*ef5ccd6cSJohn Marino    HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
10*ef5ccd6cSJohn Marino    TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11*ef5ccd6cSJohn Marino    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12*ef5ccd6cSJohn Marino 
13*ef5ccd6cSJohn Marino ****************************************************************************/
14*ef5ccd6cSJohn Marino 
15*ef5ccd6cSJohn Marino /****************************************************************************
16*ef5ccd6cSJohn Marino  *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
17*ef5ccd6cSJohn Marino  *
18*ef5ccd6cSJohn Marino  *  Module name: remcom.c $
19*ef5ccd6cSJohn Marino  *  Revision: 1.34 $
20*ef5ccd6cSJohn Marino  *  Date: 91/03/09 12:29:49 $
21*ef5ccd6cSJohn Marino  *  Contributor:     Lake Stevens Instrument Division$
22*ef5ccd6cSJohn Marino  *
23*ef5ccd6cSJohn Marino  *  Description:     low level support for gdb debugger. $
24*ef5ccd6cSJohn Marino  *
25*ef5ccd6cSJohn Marino  *  Considerations:  only works on target hardware $
26*ef5ccd6cSJohn Marino  *
27*ef5ccd6cSJohn Marino  *  Written by:      Glenn Engel $
28*ef5ccd6cSJohn Marino  *  ModuleState:     Experimental $
29*ef5ccd6cSJohn Marino  *
30*ef5ccd6cSJohn Marino  *  NOTES:           See Below $
31*ef5ccd6cSJohn Marino  *
32*ef5ccd6cSJohn Marino  *  Modified for 386 by Jim Kingdon, Cygnus Support.
33*ef5ccd6cSJohn Marino  *
34*ef5ccd6cSJohn Marino  *  To enable debugger support, two things need to happen.  One, a
35*ef5ccd6cSJohn Marino  *  call to set_debug_traps() is necessary in order to allow any breakpoints
36*ef5ccd6cSJohn Marino  *  or error conditions to be properly intercepted and reported to gdb.
37*ef5ccd6cSJohn Marino  *  Two, a breakpoint needs to be generated to begin communication.  This
38*ef5ccd6cSJohn Marino  *  is most easily accomplished by a call to breakpoint().  Breakpoint()
39*ef5ccd6cSJohn Marino  *  simulates a breakpoint by executing a trap #1.
40*ef5ccd6cSJohn Marino  *
41*ef5ccd6cSJohn Marino  *  The external function exceptionHandler() is
42*ef5ccd6cSJohn Marino  *  used to attach a specific handler to a specific 386 vector number.
43*ef5ccd6cSJohn Marino  *  It should use the same privilege level it runs at.  It should
44*ef5ccd6cSJohn Marino  *  install it as an interrupt gate so that interrupts are masked
45*ef5ccd6cSJohn Marino  *  while the handler runs.
46*ef5ccd6cSJohn Marino  *
47*ef5ccd6cSJohn Marino  *  Because gdb will sometimes write to the stack area to execute function
48*ef5ccd6cSJohn Marino  *  calls, this program cannot rely on using the supervisor stack so it
49*ef5ccd6cSJohn Marino  *  uses it's own stack area reserved in the int array remcomStack.
50*ef5ccd6cSJohn Marino  *
51*ef5ccd6cSJohn Marino  *************
52*ef5ccd6cSJohn Marino  *
53*ef5ccd6cSJohn Marino  *    The following gdb commands are supported:
54*ef5ccd6cSJohn Marino  *
55*ef5ccd6cSJohn Marino  * command          function                               Return value
56*ef5ccd6cSJohn Marino  *
57*ef5ccd6cSJohn Marino  *    g             return the value of the CPU registers  hex data or ENN
58*ef5ccd6cSJohn Marino  *    G             set the value of the CPU registers     OK or ENN
59*ef5ccd6cSJohn Marino  *
60*ef5ccd6cSJohn Marino  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
61*ef5ccd6cSJohn Marino  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
62*ef5ccd6cSJohn Marino  *
63*ef5ccd6cSJohn Marino  *    c             Resume at current address              SNN   ( signal NN)
64*ef5ccd6cSJohn Marino  *    cAA..AA       Continue at address AA..AA             SNN
65*ef5ccd6cSJohn Marino  *
66*ef5ccd6cSJohn Marino  *    s             Step one instruction                   SNN
67*ef5ccd6cSJohn Marino  *    sAA..AA       Step one instruction from AA..AA       SNN
68*ef5ccd6cSJohn Marino  *
69*ef5ccd6cSJohn Marino  *    k             kill
70*ef5ccd6cSJohn Marino  *
71*ef5ccd6cSJohn Marino  *    ?             What was the last sigval ?             SNN   (signal NN)
72*ef5ccd6cSJohn Marino  *
73*ef5ccd6cSJohn Marino  * All commands and responses are sent with a packet which includes a
74*ef5ccd6cSJohn Marino  * checksum.  A packet consists of
75*ef5ccd6cSJohn Marino  *
76*ef5ccd6cSJohn Marino  * $<packet info>#<checksum>.
77*ef5ccd6cSJohn Marino  *
78*ef5ccd6cSJohn Marino  * where
79*ef5ccd6cSJohn Marino  * <packet info> :: <characters representing the command or response>
80*ef5ccd6cSJohn Marino  * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
81*ef5ccd6cSJohn Marino  *
82*ef5ccd6cSJohn Marino  * When a packet is received, it is first acknowledged with either '+' or '-'.
83*ef5ccd6cSJohn Marino  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
84*ef5ccd6cSJohn Marino  *
85*ef5ccd6cSJohn Marino  * Example:
86*ef5ccd6cSJohn Marino  *
87*ef5ccd6cSJohn Marino  * Host:                  Reply:
88*ef5ccd6cSJohn Marino  * $m0,10#2a               +$00010203040506070809101112131415#42
89*ef5ccd6cSJohn Marino  *
90*ef5ccd6cSJohn Marino  ****************************************************************************/
91*ef5ccd6cSJohn Marino 
92*ef5ccd6cSJohn Marino #include <stdio.h>
93*ef5ccd6cSJohn Marino #include <string.h>
94*ef5ccd6cSJohn Marino 
95*ef5ccd6cSJohn Marino /************************************************************************
96*ef5ccd6cSJohn Marino  *
97*ef5ccd6cSJohn Marino  * external low-level support routines
98*ef5ccd6cSJohn Marino  */
99*ef5ccd6cSJohn Marino 
100*ef5ccd6cSJohn Marino extern void putDebugChar();	/* write a single character      */
101*ef5ccd6cSJohn Marino extern int getDebugChar();	/* read and return a single char */
102*ef5ccd6cSJohn Marino extern void exceptionHandler();	/* assign an exception handler   */
103*ef5ccd6cSJohn Marino 
104*ef5ccd6cSJohn Marino /************************************************************************/
105*ef5ccd6cSJohn Marino /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
106*ef5ccd6cSJohn Marino /* at least NUMREGBYTES*2 are needed for register packets */
107*ef5ccd6cSJohn Marino #define BUFMAX 400
108*ef5ccd6cSJohn Marino 
109*ef5ccd6cSJohn Marino static char initialized;  /* boolean flag. != 0 means we've been initialized */
110*ef5ccd6cSJohn Marino 
111*ef5ccd6cSJohn Marino int     remote_debug;
112*ef5ccd6cSJohn Marino /*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
113*ef5ccd6cSJohn Marino 
114*ef5ccd6cSJohn Marino static const char hexchars[]="0123456789abcdef";
115*ef5ccd6cSJohn Marino 
116*ef5ccd6cSJohn Marino /* Number of registers.  */
117*ef5ccd6cSJohn Marino #define NUMREGS	16
118*ef5ccd6cSJohn Marino 
119*ef5ccd6cSJohn Marino /* Number of bytes of registers.  */
120*ef5ccd6cSJohn Marino #define NUMREGBYTES (NUMREGS * 4)
121*ef5ccd6cSJohn Marino 
122*ef5ccd6cSJohn Marino enum regnames {EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
123*ef5ccd6cSJohn Marino 	       PC /* also known as eip */,
124*ef5ccd6cSJohn Marino 	       PS /* also known as eflags */,
125*ef5ccd6cSJohn Marino 	       CS, SS, DS, ES, FS, GS};
126*ef5ccd6cSJohn Marino 
127*ef5ccd6cSJohn Marino /*
128*ef5ccd6cSJohn Marino  * these should not be static cuz they can be used outside this module
129*ef5ccd6cSJohn Marino  */
130*ef5ccd6cSJohn Marino int registers[NUMREGS];
131*ef5ccd6cSJohn Marino 
132*ef5ccd6cSJohn Marino #define STACKSIZE 10000
133*ef5ccd6cSJohn Marino int remcomStack[STACKSIZE/sizeof(int)];
134*ef5ccd6cSJohn Marino static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
135*ef5ccd6cSJohn Marino 
136*ef5ccd6cSJohn Marino /***************************  ASSEMBLY CODE MACROS *************************/
137*ef5ccd6cSJohn Marino /* 									   */
138*ef5ccd6cSJohn Marino 
139*ef5ccd6cSJohn Marino extern void
140*ef5ccd6cSJohn Marino return_to_prog ();
141*ef5ccd6cSJohn Marino 
142*ef5ccd6cSJohn Marino /* Restore the program's registers (including the stack pointer, which
143*ef5ccd6cSJohn Marino    means we get the right stack and don't have to worry about popping our
144*ef5ccd6cSJohn Marino    return address and any stack frames and so on) and return.  */
145*ef5ccd6cSJohn Marino asm(".text");
146*ef5ccd6cSJohn Marino asm(".globl _return_to_prog");
147*ef5ccd6cSJohn Marino asm("_return_to_prog:");
148*ef5ccd6cSJohn Marino asm("        movw _registers+44, %ss");
149*ef5ccd6cSJohn Marino asm("        movl _registers+16, %esp");
150*ef5ccd6cSJohn Marino asm("        movl _registers+4, %ecx");
151*ef5ccd6cSJohn Marino asm("        movl _registers+8, %edx");
152*ef5ccd6cSJohn Marino asm("        movl _registers+12, %ebx");
153*ef5ccd6cSJohn Marino asm("        movl _registers+20, %ebp");
154*ef5ccd6cSJohn Marino asm("        movl _registers+24, %esi");
155*ef5ccd6cSJohn Marino asm("        movl _registers+28, %edi");
156*ef5ccd6cSJohn Marino asm("        movw _registers+48, %ds");
157*ef5ccd6cSJohn Marino asm("        movw _registers+52, %es");
158*ef5ccd6cSJohn Marino asm("        movw _registers+56, %fs");
159*ef5ccd6cSJohn Marino asm("        movw _registers+60, %gs");
160*ef5ccd6cSJohn Marino asm("        movl _registers+36, %eax");
161*ef5ccd6cSJohn Marino asm("        pushl %eax");  /* saved eflags */
162*ef5ccd6cSJohn Marino asm("        movl _registers+40, %eax");
163*ef5ccd6cSJohn Marino asm("        pushl %eax");  /* saved cs */
164*ef5ccd6cSJohn Marino asm("        movl _registers+32, %eax");
165*ef5ccd6cSJohn Marino asm("        pushl %eax");  /* saved eip */
166*ef5ccd6cSJohn Marino asm("        movl _registers, %eax");
167*ef5ccd6cSJohn Marino /* use iret to restore pc and flags together so
168*ef5ccd6cSJohn Marino    that trace flag works right.  */
169*ef5ccd6cSJohn Marino asm("        iret");
170*ef5ccd6cSJohn Marino 
171*ef5ccd6cSJohn Marino #define BREAKPOINT() asm("   int $3");
172*ef5ccd6cSJohn Marino 
173*ef5ccd6cSJohn Marino /* Put the error code here just in case the user cares.  */
174*ef5ccd6cSJohn Marino int gdb_i386errcode;
175*ef5ccd6cSJohn Marino /* Likewise, the vector number here (since GDB only gets the signal
176*ef5ccd6cSJohn Marino    number through the usual means, and that's not very specific).  */
177*ef5ccd6cSJohn Marino int gdb_i386vector = -1;
178*ef5ccd6cSJohn Marino 
179*ef5ccd6cSJohn Marino /* GDB stores segment registers in 32-bit words (that's just the way
180*ef5ccd6cSJohn Marino    m-i386v.h is written).  So zero the appropriate areas in registers.  */
181*ef5ccd6cSJohn Marino #define SAVE_REGISTERS1() \
182*ef5ccd6cSJohn Marino   asm ("movl %eax, _registers");                                   	  \
183*ef5ccd6cSJohn Marino   asm ("movl %ecx, _registers+4");			  		     \
184*ef5ccd6cSJohn Marino   asm ("movl %edx, _registers+8");			  		     \
185*ef5ccd6cSJohn Marino   asm ("movl %ebx, _registers+12");			  		     \
186*ef5ccd6cSJohn Marino   asm ("movl %ebp, _registers+20");			  		     \
187*ef5ccd6cSJohn Marino   asm ("movl %esi, _registers+24");			  		     \
188*ef5ccd6cSJohn Marino   asm ("movl %edi, _registers+28");			  		     \
189*ef5ccd6cSJohn Marino   asm ("movw $0, %ax");							     \
190*ef5ccd6cSJohn Marino   asm ("movw %ds, _registers+48");			  		     \
191*ef5ccd6cSJohn Marino   asm ("movw %ax, _registers+50");					     \
192*ef5ccd6cSJohn Marino   asm ("movw %es, _registers+52");			  		     \
193*ef5ccd6cSJohn Marino   asm ("movw %ax, _registers+54");					     \
194*ef5ccd6cSJohn Marino   asm ("movw %fs, _registers+56");			  		     \
195*ef5ccd6cSJohn Marino   asm ("movw %ax, _registers+58");					     \
196*ef5ccd6cSJohn Marino   asm ("movw %gs, _registers+60");			  		     \
197*ef5ccd6cSJohn Marino   asm ("movw %ax, _registers+62");
198*ef5ccd6cSJohn Marino #define SAVE_ERRCODE() \
199*ef5ccd6cSJohn Marino   asm ("popl %ebx");                                  \
200*ef5ccd6cSJohn Marino   asm ("movl %ebx, _gdb_i386errcode");
201*ef5ccd6cSJohn Marino #define SAVE_REGISTERS2() \
202*ef5ccd6cSJohn Marino   asm ("popl %ebx"); /* old eip */			  		     \
203*ef5ccd6cSJohn Marino   asm ("movl %ebx, _registers+32");			  		     \
204*ef5ccd6cSJohn Marino   asm ("popl %ebx");	 /* old cs */			  		     \
205*ef5ccd6cSJohn Marino   asm ("movl %ebx, _registers+40");			  		     \
206*ef5ccd6cSJohn Marino   asm ("movw %ax, _registers+42");                                           \
207*ef5ccd6cSJohn Marino   asm ("popl %ebx");	 /* old eflags */		  		     \
208*ef5ccd6cSJohn Marino   asm ("movl %ebx, _registers+36");			 		     \
209*ef5ccd6cSJohn Marino   /* Now that we've done the pops, we can save the stack pointer.");  */   \
210*ef5ccd6cSJohn Marino   asm ("movw %ss, _registers+44");					     \
211*ef5ccd6cSJohn Marino   asm ("movw %ax, _registers+46");     	       	       	       	       	     \
212*ef5ccd6cSJohn Marino   asm ("movl %esp, _registers+16");
213*ef5ccd6cSJohn Marino 
214*ef5ccd6cSJohn Marino /* See if mem_fault_routine is set, if so just IRET to that address.  */
215*ef5ccd6cSJohn Marino #define CHECK_FAULT() \
216*ef5ccd6cSJohn Marino   asm ("cmpl $0, _mem_fault_routine");					   \
217*ef5ccd6cSJohn Marino   asm ("jne mem_fault");
218*ef5ccd6cSJohn Marino 
219*ef5ccd6cSJohn Marino asm (".text");
220*ef5ccd6cSJohn Marino asm ("mem_fault:");
221*ef5ccd6cSJohn Marino /* OK to clobber temp registers; we're just going to end up in set_mem_err.  */
222*ef5ccd6cSJohn Marino /* Pop error code from the stack and save it.  */
223*ef5ccd6cSJohn Marino asm ("     popl %eax");
224*ef5ccd6cSJohn Marino asm ("     movl %eax, _gdb_i386errcode");
225*ef5ccd6cSJohn Marino 
226*ef5ccd6cSJohn Marino asm ("     popl %eax"); /* eip */
227*ef5ccd6cSJohn Marino /* We don't want to return there, we want to return to the function
228*ef5ccd6cSJohn Marino    pointed to by mem_fault_routine instead.  */
229*ef5ccd6cSJohn Marino asm ("     movl _mem_fault_routine, %eax");
230*ef5ccd6cSJohn Marino asm ("     popl %ecx"); /* cs (low 16 bits; junk in hi 16 bits).  */
231*ef5ccd6cSJohn Marino asm ("     popl %edx"); /* eflags */
232*ef5ccd6cSJohn Marino 
233*ef5ccd6cSJohn Marino /* Remove this stack frame; when we do the iret, we will be going to
234*ef5ccd6cSJohn Marino    the start of a function, so we want the stack to look just like it
235*ef5ccd6cSJohn Marino    would after a "call" instruction.  */
236*ef5ccd6cSJohn Marino asm ("     leave");
237*ef5ccd6cSJohn Marino 
238*ef5ccd6cSJohn Marino /* Push the stuff that iret wants.  */
239*ef5ccd6cSJohn Marino asm ("     pushl %edx"); /* eflags */
240*ef5ccd6cSJohn Marino asm ("     pushl %ecx"); /* cs */
241*ef5ccd6cSJohn Marino asm ("     pushl %eax"); /* eip */
242*ef5ccd6cSJohn Marino 
243*ef5ccd6cSJohn Marino /* Zero mem_fault_routine.  */
244*ef5ccd6cSJohn Marino asm ("     movl $0, %eax");
245*ef5ccd6cSJohn Marino asm ("     movl %eax, _mem_fault_routine");
246*ef5ccd6cSJohn Marino 
247*ef5ccd6cSJohn Marino asm ("iret");
248*ef5ccd6cSJohn Marino 
249*ef5ccd6cSJohn Marino #define CALL_HOOK() asm("call _remcomHandler");
250*ef5ccd6cSJohn Marino 
251*ef5ccd6cSJohn Marino /* This function is called when a i386 exception occurs.  It saves
252*ef5ccd6cSJohn Marino  * all the cpu regs in the _registers array, munges the stack a bit,
253*ef5ccd6cSJohn Marino  * and invokes an exception handler (remcom_handler).
254*ef5ccd6cSJohn Marino  *
255*ef5ccd6cSJohn Marino  * stack on entry:                       stack on exit:
256*ef5ccd6cSJohn Marino  *   old eflags                          vector number
257*ef5ccd6cSJohn Marino  *   old cs (zero-filled to 32 bits)
258*ef5ccd6cSJohn Marino  *   old eip
259*ef5ccd6cSJohn Marino  *
260*ef5ccd6cSJohn Marino  */
261*ef5ccd6cSJohn Marino extern void _catchException3();
262*ef5ccd6cSJohn Marino asm(".text");
263*ef5ccd6cSJohn Marino asm(".globl __catchException3");
264*ef5ccd6cSJohn Marino asm("__catchException3:");
265*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
266*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
267*ef5ccd6cSJohn Marino asm ("pushl $3");
268*ef5ccd6cSJohn Marino CALL_HOOK();
269*ef5ccd6cSJohn Marino 
270*ef5ccd6cSJohn Marino /* Same thing for exception 1.  */
271*ef5ccd6cSJohn Marino extern void _catchException1();
272*ef5ccd6cSJohn Marino asm(".text");
273*ef5ccd6cSJohn Marino asm(".globl __catchException1");
274*ef5ccd6cSJohn Marino asm("__catchException1:");
275*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
276*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
277*ef5ccd6cSJohn Marino asm ("pushl $1");
278*ef5ccd6cSJohn Marino CALL_HOOK();
279*ef5ccd6cSJohn Marino 
280*ef5ccd6cSJohn Marino /* Same thing for exception 0.  */
281*ef5ccd6cSJohn Marino extern void _catchException0();
282*ef5ccd6cSJohn Marino asm(".text");
283*ef5ccd6cSJohn Marino asm(".globl __catchException0");
284*ef5ccd6cSJohn Marino asm("__catchException0:");
285*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
286*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
287*ef5ccd6cSJohn Marino asm ("pushl $0");
288*ef5ccd6cSJohn Marino CALL_HOOK();
289*ef5ccd6cSJohn Marino 
290*ef5ccd6cSJohn Marino /* Same thing for exception 4.  */
291*ef5ccd6cSJohn Marino extern void _catchException4();
292*ef5ccd6cSJohn Marino asm(".text");
293*ef5ccd6cSJohn Marino asm(".globl __catchException4");
294*ef5ccd6cSJohn Marino asm("__catchException4:");
295*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
296*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
297*ef5ccd6cSJohn Marino asm ("pushl $4");
298*ef5ccd6cSJohn Marino CALL_HOOK();
299*ef5ccd6cSJohn Marino 
300*ef5ccd6cSJohn Marino /* Same thing for exception 5.  */
301*ef5ccd6cSJohn Marino extern void _catchException5();
302*ef5ccd6cSJohn Marino asm(".text");
303*ef5ccd6cSJohn Marino asm(".globl __catchException5");
304*ef5ccd6cSJohn Marino asm("__catchException5:");
305*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
306*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
307*ef5ccd6cSJohn Marino asm ("pushl $5");
308*ef5ccd6cSJohn Marino CALL_HOOK();
309*ef5ccd6cSJohn Marino 
310*ef5ccd6cSJohn Marino /* Same thing for exception 6.  */
311*ef5ccd6cSJohn Marino extern void _catchException6();
312*ef5ccd6cSJohn Marino asm(".text");
313*ef5ccd6cSJohn Marino asm(".globl __catchException6");
314*ef5ccd6cSJohn Marino asm("__catchException6:");
315*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
316*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
317*ef5ccd6cSJohn Marino asm ("pushl $6");
318*ef5ccd6cSJohn Marino CALL_HOOK();
319*ef5ccd6cSJohn Marino 
320*ef5ccd6cSJohn Marino /* Same thing for exception 7.  */
321*ef5ccd6cSJohn Marino extern void _catchException7();
322*ef5ccd6cSJohn Marino asm(".text");
323*ef5ccd6cSJohn Marino asm(".globl __catchException7");
324*ef5ccd6cSJohn Marino asm("__catchException7:");
325*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
326*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
327*ef5ccd6cSJohn Marino asm ("pushl $7");
328*ef5ccd6cSJohn Marino CALL_HOOK();
329*ef5ccd6cSJohn Marino 
330*ef5ccd6cSJohn Marino /* Same thing for exception 8.  */
331*ef5ccd6cSJohn Marino extern void _catchException8();
332*ef5ccd6cSJohn Marino asm(".text");
333*ef5ccd6cSJohn Marino asm(".globl __catchException8");
334*ef5ccd6cSJohn Marino asm("__catchException8:");
335*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
336*ef5ccd6cSJohn Marino SAVE_ERRCODE();
337*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
338*ef5ccd6cSJohn Marino asm ("pushl $8");
339*ef5ccd6cSJohn Marino CALL_HOOK();
340*ef5ccd6cSJohn Marino 
341*ef5ccd6cSJohn Marino /* Same thing for exception 9.  */
342*ef5ccd6cSJohn Marino extern void _catchException9();
343*ef5ccd6cSJohn Marino asm(".text");
344*ef5ccd6cSJohn Marino asm(".globl __catchException9");
345*ef5ccd6cSJohn Marino asm("__catchException9:");
346*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
347*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
348*ef5ccd6cSJohn Marino asm ("pushl $9");
349*ef5ccd6cSJohn Marino CALL_HOOK();
350*ef5ccd6cSJohn Marino 
351*ef5ccd6cSJohn Marino /* Same thing for exception 10.  */
352*ef5ccd6cSJohn Marino extern void _catchException10();
353*ef5ccd6cSJohn Marino asm(".text");
354*ef5ccd6cSJohn Marino asm(".globl __catchException10");
355*ef5ccd6cSJohn Marino asm("__catchException10:");
356*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
357*ef5ccd6cSJohn Marino SAVE_ERRCODE();
358*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
359*ef5ccd6cSJohn Marino asm ("pushl $10");
360*ef5ccd6cSJohn Marino CALL_HOOK();
361*ef5ccd6cSJohn Marino 
362*ef5ccd6cSJohn Marino /* Same thing for exception 12.  */
363*ef5ccd6cSJohn Marino extern void _catchException12();
364*ef5ccd6cSJohn Marino asm(".text");
365*ef5ccd6cSJohn Marino asm(".globl __catchException12");
366*ef5ccd6cSJohn Marino asm("__catchException12:");
367*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
368*ef5ccd6cSJohn Marino SAVE_ERRCODE();
369*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
370*ef5ccd6cSJohn Marino asm ("pushl $12");
371*ef5ccd6cSJohn Marino CALL_HOOK();
372*ef5ccd6cSJohn Marino 
373*ef5ccd6cSJohn Marino /* Same thing for exception 16.  */
374*ef5ccd6cSJohn Marino extern void _catchException16();
375*ef5ccd6cSJohn Marino asm(".text");
376*ef5ccd6cSJohn Marino asm(".globl __catchException16");
377*ef5ccd6cSJohn Marino asm("__catchException16:");
378*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
379*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
380*ef5ccd6cSJohn Marino asm ("pushl $16");
381*ef5ccd6cSJohn Marino CALL_HOOK();
382*ef5ccd6cSJohn Marino 
383*ef5ccd6cSJohn Marino /* For 13, 11, and 14 we have to deal with the CHECK_FAULT stuff.  */
384*ef5ccd6cSJohn Marino 
385*ef5ccd6cSJohn Marino /* Same thing for exception 13.  */
386*ef5ccd6cSJohn Marino extern void _catchException13 ();
387*ef5ccd6cSJohn Marino asm (".text");
388*ef5ccd6cSJohn Marino asm (".globl __catchException13");
389*ef5ccd6cSJohn Marino asm ("__catchException13:");
390*ef5ccd6cSJohn Marino CHECK_FAULT();
391*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
392*ef5ccd6cSJohn Marino SAVE_ERRCODE();
393*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
394*ef5ccd6cSJohn Marino asm ("pushl $13");
395*ef5ccd6cSJohn Marino CALL_HOOK();
396*ef5ccd6cSJohn Marino 
397*ef5ccd6cSJohn Marino /* Same thing for exception 11.  */
398*ef5ccd6cSJohn Marino extern void _catchException11 ();
399*ef5ccd6cSJohn Marino asm (".text");
400*ef5ccd6cSJohn Marino asm (".globl __catchException11");
401*ef5ccd6cSJohn Marino asm ("__catchException11:");
402*ef5ccd6cSJohn Marino CHECK_FAULT();
403*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
404*ef5ccd6cSJohn Marino SAVE_ERRCODE();
405*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
406*ef5ccd6cSJohn Marino asm ("pushl $11");
407*ef5ccd6cSJohn Marino CALL_HOOK();
408*ef5ccd6cSJohn Marino 
409*ef5ccd6cSJohn Marino /* Same thing for exception 14.  */
410*ef5ccd6cSJohn Marino extern void _catchException14 ();
411*ef5ccd6cSJohn Marino asm (".text");
412*ef5ccd6cSJohn Marino asm (".globl __catchException14");
413*ef5ccd6cSJohn Marino asm ("__catchException14:");
414*ef5ccd6cSJohn Marino CHECK_FAULT();
415*ef5ccd6cSJohn Marino SAVE_REGISTERS1();
416*ef5ccd6cSJohn Marino SAVE_ERRCODE();
417*ef5ccd6cSJohn Marino SAVE_REGISTERS2();
418*ef5ccd6cSJohn Marino asm ("pushl $14");
419*ef5ccd6cSJohn Marino CALL_HOOK();
420*ef5ccd6cSJohn Marino 
421*ef5ccd6cSJohn Marino /*
422*ef5ccd6cSJohn Marino  * remcomHandler is a front end for handle_exception.  It moves the
423*ef5ccd6cSJohn Marino  * stack pointer into an area reserved for debugger use.
424*ef5ccd6cSJohn Marino  */
425*ef5ccd6cSJohn Marino asm("_remcomHandler:");
426*ef5ccd6cSJohn Marino asm("           popl %eax");        /* pop off return address     */
427*ef5ccd6cSJohn Marino asm("           popl %eax");      /* get the exception number   */
428*ef5ccd6cSJohn Marino asm("		movl _stackPtr, %esp"); /* move to remcom stack area  */
429*ef5ccd6cSJohn Marino asm("		pushl %eax");	/* push exception onto stack  */
430*ef5ccd6cSJohn Marino asm("		call  _handle_exception");    /* this never returns */
431*ef5ccd6cSJohn Marino 
432*ef5ccd6cSJohn Marino void
_returnFromException()433*ef5ccd6cSJohn Marino _returnFromException ()
434*ef5ccd6cSJohn Marino {
435*ef5ccd6cSJohn Marino   return_to_prog ();
436*ef5ccd6cSJohn Marino }
437*ef5ccd6cSJohn Marino 
438*ef5ccd6cSJohn Marino int
hex(ch)439*ef5ccd6cSJohn Marino hex (ch)
440*ef5ccd6cSJohn Marino      char ch;
441*ef5ccd6cSJohn Marino {
442*ef5ccd6cSJohn Marino   if ((ch >= 'a') && (ch <= 'f'))
443*ef5ccd6cSJohn Marino     return (ch - 'a' + 10);
444*ef5ccd6cSJohn Marino   if ((ch >= '0') && (ch <= '9'))
445*ef5ccd6cSJohn Marino     return (ch - '0');
446*ef5ccd6cSJohn Marino   if ((ch >= 'A') && (ch <= 'F'))
447*ef5ccd6cSJohn Marino     return (ch - 'A' + 10);
448*ef5ccd6cSJohn Marino   return (-1);
449*ef5ccd6cSJohn Marino }
450*ef5ccd6cSJohn Marino 
451*ef5ccd6cSJohn Marino static char remcomInBuffer[BUFMAX];
452*ef5ccd6cSJohn Marino static char remcomOutBuffer[BUFMAX];
453*ef5ccd6cSJohn Marino 
454*ef5ccd6cSJohn Marino /* scan for the sequence $<data>#<checksum>     */
455*ef5ccd6cSJohn Marino 
456*ef5ccd6cSJohn Marino unsigned char *
getpacket(void)457*ef5ccd6cSJohn Marino getpacket (void)
458*ef5ccd6cSJohn Marino {
459*ef5ccd6cSJohn Marino   unsigned char *buffer = &remcomInBuffer[0];
460*ef5ccd6cSJohn Marino   unsigned char checksum;
461*ef5ccd6cSJohn Marino   unsigned char xmitcsum;
462*ef5ccd6cSJohn Marino   int count;
463*ef5ccd6cSJohn Marino   char ch;
464*ef5ccd6cSJohn Marino 
465*ef5ccd6cSJohn Marino   while (1)
466*ef5ccd6cSJohn Marino     {
467*ef5ccd6cSJohn Marino       /* wait around for the start character, ignore all other characters */
468*ef5ccd6cSJohn Marino       while ((ch = getDebugChar ()) != '$')
469*ef5ccd6cSJohn Marino 	;
470*ef5ccd6cSJohn Marino 
471*ef5ccd6cSJohn Marino     retry:
472*ef5ccd6cSJohn Marino       checksum = 0;
473*ef5ccd6cSJohn Marino       xmitcsum = -1;
474*ef5ccd6cSJohn Marino       count = 0;
475*ef5ccd6cSJohn Marino 
476*ef5ccd6cSJohn Marino       /* now, read until a # or end of buffer is found */
477*ef5ccd6cSJohn Marino       while (count < BUFMAX - 1)
478*ef5ccd6cSJohn Marino 	{
479*ef5ccd6cSJohn Marino 	  ch = getDebugChar ();
480*ef5ccd6cSJohn Marino 	  if (ch == '$')
481*ef5ccd6cSJohn Marino 	    goto retry;
482*ef5ccd6cSJohn Marino 	  if (ch == '#')
483*ef5ccd6cSJohn Marino 	    break;
484*ef5ccd6cSJohn Marino 	  checksum = checksum + ch;
485*ef5ccd6cSJohn Marino 	  buffer[count] = ch;
486*ef5ccd6cSJohn Marino 	  count = count + 1;
487*ef5ccd6cSJohn Marino 	}
488*ef5ccd6cSJohn Marino       buffer[count] = 0;
489*ef5ccd6cSJohn Marino 
490*ef5ccd6cSJohn Marino       if (ch == '#')
491*ef5ccd6cSJohn Marino 	{
492*ef5ccd6cSJohn Marino 	  ch = getDebugChar ();
493*ef5ccd6cSJohn Marino 	  xmitcsum = hex (ch) << 4;
494*ef5ccd6cSJohn Marino 	  ch = getDebugChar ();
495*ef5ccd6cSJohn Marino 	  xmitcsum += hex (ch);
496*ef5ccd6cSJohn Marino 
497*ef5ccd6cSJohn Marino 	  if (checksum != xmitcsum)
498*ef5ccd6cSJohn Marino 	    {
499*ef5ccd6cSJohn Marino 	      if (remote_debug)
500*ef5ccd6cSJohn Marino 		{
501*ef5ccd6cSJohn Marino 		  fprintf (stderr,
502*ef5ccd6cSJohn Marino 			   "bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
503*ef5ccd6cSJohn Marino 			   checksum, xmitcsum, buffer);
504*ef5ccd6cSJohn Marino 		}
505*ef5ccd6cSJohn Marino 	      putDebugChar ('-');	/* failed checksum */
506*ef5ccd6cSJohn Marino 	    }
507*ef5ccd6cSJohn Marino 	  else
508*ef5ccd6cSJohn Marino 	    {
509*ef5ccd6cSJohn Marino 	      putDebugChar ('+');	/* successful transfer */
510*ef5ccd6cSJohn Marino 
511*ef5ccd6cSJohn Marino 	      /* if a sequence char is present, reply the sequence ID */
512*ef5ccd6cSJohn Marino 	      if (buffer[2] == ':')
513*ef5ccd6cSJohn Marino 		{
514*ef5ccd6cSJohn Marino 		  putDebugChar (buffer[0]);
515*ef5ccd6cSJohn Marino 		  putDebugChar (buffer[1]);
516*ef5ccd6cSJohn Marino 
517*ef5ccd6cSJohn Marino 		  return &buffer[3];
518*ef5ccd6cSJohn Marino 		}
519*ef5ccd6cSJohn Marino 
520*ef5ccd6cSJohn Marino 	      return &buffer[0];
521*ef5ccd6cSJohn Marino 	    }
522*ef5ccd6cSJohn Marino 	}
523*ef5ccd6cSJohn Marino     }
524*ef5ccd6cSJohn Marino }
525*ef5ccd6cSJohn Marino 
526*ef5ccd6cSJohn Marino /* send the packet in buffer.  */
527*ef5ccd6cSJohn Marino 
528*ef5ccd6cSJohn Marino void
putpacket(unsigned char * buffer)529*ef5ccd6cSJohn Marino putpacket (unsigned char *buffer)
530*ef5ccd6cSJohn Marino {
531*ef5ccd6cSJohn Marino   unsigned char checksum;
532*ef5ccd6cSJohn Marino   int count;
533*ef5ccd6cSJohn Marino   char ch;
534*ef5ccd6cSJohn Marino 
535*ef5ccd6cSJohn Marino   /*  $<packet info>#<checksum>.  */
536*ef5ccd6cSJohn Marino   do
537*ef5ccd6cSJohn Marino     {
538*ef5ccd6cSJohn Marino       putDebugChar ('$');
539*ef5ccd6cSJohn Marino       checksum = 0;
540*ef5ccd6cSJohn Marino       count = 0;
541*ef5ccd6cSJohn Marino 
542*ef5ccd6cSJohn Marino       while (ch = buffer[count])
543*ef5ccd6cSJohn Marino 	{
544*ef5ccd6cSJohn Marino 	  putDebugChar (ch);
545*ef5ccd6cSJohn Marino 	  checksum += ch;
546*ef5ccd6cSJohn Marino 	  count += 1;
547*ef5ccd6cSJohn Marino 	}
548*ef5ccd6cSJohn Marino 
549*ef5ccd6cSJohn Marino       putDebugChar ('#');
550*ef5ccd6cSJohn Marino       putDebugChar (hexchars[checksum >> 4]);
551*ef5ccd6cSJohn Marino       putDebugChar (hexchars[checksum % 16]);
552*ef5ccd6cSJohn Marino 
553*ef5ccd6cSJohn Marino     }
554*ef5ccd6cSJohn Marino   while (getDebugChar () != '+');
555*ef5ccd6cSJohn Marino }
556*ef5ccd6cSJohn Marino 
557*ef5ccd6cSJohn Marino void
debug_error(format,parm)558*ef5ccd6cSJohn Marino debug_error (format, parm)
559*ef5ccd6cSJohn Marino      char *format;
560*ef5ccd6cSJohn Marino      char *parm;
561*ef5ccd6cSJohn Marino {
562*ef5ccd6cSJohn Marino   if (remote_debug)
563*ef5ccd6cSJohn Marino     fprintf (stderr, format, parm);
564*ef5ccd6cSJohn Marino }
565*ef5ccd6cSJohn Marino 
566*ef5ccd6cSJohn Marino /* Address of a routine to RTE to if we get a memory fault.  */
567*ef5ccd6cSJohn Marino static void (*volatile mem_fault_routine) () = NULL;
568*ef5ccd6cSJohn Marino 
569*ef5ccd6cSJohn Marino /* Indicate to caller of mem2hex or hex2mem that there has been an
570*ef5ccd6cSJohn Marino    error.  */
571*ef5ccd6cSJohn Marino static volatile int mem_err = 0;
572*ef5ccd6cSJohn Marino 
573*ef5ccd6cSJohn Marino void
set_mem_err(void)574*ef5ccd6cSJohn Marino set_mem_err (void)
575*ef5ccd6cSJohn Marino {
576*ef5ccd6cSJohn Marino   mem_err = 1;
577*ef5ccd6cSJohn Marino }
578*ef5ccd6cSJohn Marino 
579*ef5ccd6cSJohn Marino /* These are separate functions so that they are so short and sweet
580*ef5ccd6cSJohn Marino    that the compiler won't save any registers (if there is a fault
581*ef5ccd6cSJohn Marino    to mem_fault, they won't get restored, so there better not be any
582*ef5ccd6cSJohn Marino    saved).  */
583*ef5ccd6cSJohn Marino int
get_char(char * addr)584*ef5ccd6cSJohn Marino get_char (char *addr)
585*ef5ccd6cSJohn Marino {
586*ef5ccd6cSJohn Marino   return *addr;
587*ef5ccd6cSJohn Marino }
588*ef5ccd6cSJohn Marino 
589*ef5ccd6cSJohn Marino void
set_char(char * addr,int val)590*ef5ccd6cSJohn Marino set_char (char *addr, int val)
591*ef5ccd6cSJohn Marino {
592*ef5ccd6cSJohn Marino   *addr = val;
593*ef5ccd6cSJohn Marino }
594*ef5ccd6cSJohn Marino 
595*ef5ccd6cSJohn Marino /* convert the memory pointed to by mem into hex, placing result in buf */
596*ef5ccd6cSJohn Marino /* return a pointer to the last char put in buf (null) */
597*ef5ccd6cSJohn Marino /* If MAY_FAULT is non-zero, then we should set mem_err in response to
598*ef5ccd6cSJohn Marino    a fault; if zero treat a fault like any other fault in the stub.  */
599*ef5ccd6cSJohn Marino char *
mem2hex(mem,buf,count,may_fault)600*ef5ccd6cSJohn Marino mem2hex (mem, buf, count, may_fault)
601*ef5ccd6cSJohn Marino      char *mem;
602*ef5ccd6cSJohn Marino      char *buf;
603*ef5ccd6cSJohn Marino      int count;
604*ef5ccd6cSJohn Marino      int may_fault;
605*ef5ccd6cSJohn Marino {
606*ef5ccd6cSJohn Marino   int i;
607*ef5ccd6cSJohn Marino   unsigned char ch;
608*ef5ccd6cSJohn Marino 
609*ef5ccd6cSJohn Marino   if (may_fault)
610*ef5ccd6cSJohn Marino     mem_fault_routine = set_mem_err;
611*ef5ccd6cSJohn Marino   for (i = 0; i < count; i++)
612*ef5ccd6cSJohn Marino     {
613*ef5ccd6cSJohn Marino       ch = get_char (mem++);
614*ef5ccd6cSJohn Marino       if (may_fault && mem_err)
615*ef5ccd6cSJohn Marino 	return (buf);
616*ef5ccd6cSJohn Marino       *buf++ = hexchars[ch >> 4];
617*ef5ccd6cSJohn Marino       *buf++ = hexchars[ch % 16];
618*ef5ccd6cSJohn Marino     }
619*ef5ccd6cSJohn Marino   *buf = 0;
620*ef5ccd6cSJohn Marino   if (may_fault)
621*ef5ccd6cSJohn Marino     mem_fault_routine = NULL;
622*ef5ccd6cSJohn Marino   return (buf);
623*ef5ccd6cSJohn Marino }
624*ef5ccd6cSJohn Marino 
625*ef5ccd6cSJohn Marino /* convert the hex array pointed to by buf into binary to be placed in mem */
626*ef5ccd6cSJohn Marino /* return a pointer to the character AFTER the last byte written */
627*ef5ccd6cSJohn Marino char *
hex2mem(buf,mem,count,may_fault)628*ef5ccd6cSJohn Marino hex2mem (buf, mem, count, may_fault)
629*ef5ccd6cSJohn Marino      char *buf;
630*ef5ccd6cSJohn Marino      char *mem;
631*ef5ccd6cSJohn Marino      int count;
632*ef5ccd6cSJohn Marino      int may_fault;
633*ef5ccd6cSJohn Marino {
634*ef5ccd6cSJohn Marino   int i;
635*ef5ccd6cSJohn Marino   unsigned char ch;
636*ef5ccd6cSJohn Marino 
637*ef5ccd6cSJohn Marino   if (may_fault)
638*ef5ccd6cSJohn Marino     mem_fault_routine = set_mem_err;
639*ef5ccd6cSJohn Marino   for (i = 0; i < count; i++)
640*ef5ccd6cSJohn Marino     {
641*ef5ccd6cSJohn Marino       ch = hex (*buf++) << 4;
642*ef5ccd6cSJohn Marino       ch = ch + hex (*buf++);
643*ef5ccd6cSJohn Marino       set_char (mem++, ch);
644*ef5ccd6cSJohn Marino       if (may_fault && mem_err)
645*ef5ccd6cSJohn Marino 	return (mem);
646*ef5ccd6cSJohn Marino     }
647*ef5ccd6cSJohn Marino   if (may_fault)
648*ef5ccd6cSJohn Marino     mem_fault_routine = NULL;
649*ef5ccd6cSJohn Marino   return (mem);
650*ef5ccd6cSJohn Marino }
651*ef5ccd6cSJohn Marino 
652*ef5ccd6cSJohn Marino /* this function takes the 386 exception vector and attempts to
653*ef5ccd6cSJohn Marino    translate this number into a unix compatible signal value */
654*ef5ccd6cSJohn Marino int
computeSignal(int exceptionVector)655*ef5ccd6cSJohn Marino computeSignal (int exceptionVector)
656*ef5ccd6cSJohn Marino {
657*ef5ccd6cSJohn Marino   int sigval;
658*ef5ccd6cSJohn Marino   switch (exceptionVector)
659*ef5ccd6cSJohn Marino     {
660*ef5ccd6cSJohn Marino     case 0:
661*ef5ccd6cSJohn Marino       sigval = 8;
662*ef5ccd6cSJohn Marino       break;			/* divide by zero */
663*ef5ccd6cSJohn Marino     case 1:
664*ef5ccd6cSJohn Marino       sigval = 5;
665*ef5ccd6cSJohn Marino       break;			/* debug exception */
666*ef5ccd6cSJohn Marino     case 3:
667*ef5ccd6cSJohn Marino       sigval = 5;
668*ef5ccd6cSJohn Marino       break;			/* breakpoint */
669*ef5ccd6cSJohn Marino     case 4:
670*ef5ccd6cSJohn Marino       sigval = 16;
671*ef5ccd6cSJohn Marino       break;			/* into instruction (overflow) */
672*ef5ccd6cSJohn Marino     case 5:
673*ef5ccd6cSJohn Marino       sigval = 16;
674*ef5ccd6cSJohn Marino       break;			/* bound instruction */
675*ef5ccd6cSJohn Marino     case 6:
676*ef5ccd6cSJohn Marino       sigval = 4;
677*ef5ccd6cSJohn Marino       break;			/* Invalid opcode */
678*ef5ccd6cSJohn Marino     case 7:
679*ef5ccd6cSJohn Marino       sigval = 8;
680*ef5ccd6cSJohn Marino       break;			/* coprocessor not available */
681*ef5ccd6cSJohn Marino     case 8:
682*ef5ccd6cSJohn Marino       sigval = 7;
683*ef5ccd6cSJohn Marino       break;			/* double fault */
684*ef5ccd6cSJohn Marino     case 9:
685*ef5ccd6cSJohn Marino       sigval = 11;
686*ef5ccd6cSJohn Marino       break;			/* coprocessor segment overrun */
687*ef5ccd6cSJohn Marino     case 10:
688*ef5ccd6cSJohn Marino       sigval = 11;
689*ef5ccd6cSJohn Marino       break;			/* Invalid TSS */
690*ef5ccd6cSJohn Marino     case 11:
691*ef5ccd6cSJohn Marino       sigval = 11;
692*ef5ccd6cSJohn Marino       break;			/* Segment not present */
693*ef5ccd6cSJohn Marino     case 12:
694*ef5ccd6cSJohn Marino       sigval = 11;
695*ef5ccd6cSJohn Marino       break;			/* stack exception */
696*ef5ccd6cSJohn Marino     case 13:
697*ef5ccd6cSJohn Marino       sigval = 11;
698*ef5ccd6cSJohn Marino       break;			/* general protection */
699*ef5ccd6cSJohn Marino     case 14:
700*ef5ccd6cSJohn Marino       sigval = 11;
701*ef5ccd6cSJohn Marino       break;			/* page fault */
702*ef5ccd6cSJohn Marino     case 16:
703*ef5ccd6cSJohn Marino       sigval = 7;
704*ef5ccd6cSJohn Marino       break;			/* coprocessor error */
705*ef5ccd6cSJohn Marino     default:
706*ef5ccd6cSJohn Marino       sigval = 7;		/* "software generated" */
707*ef5ccd6cSJohn Marino     }
708*ef5ccd6cSJohn Marino   return (sigval);
709*ef5ccd6cSJohn Marino }
710*ef5ccd6cSJohn Marino 
711*ef5ccd6cSJohn Marino /**********************************************/
712*ef5ccd6cSJohn Marino /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
713*ef5ccd6cSJohn Marino /* RETURN NUMBER OF CHARS PROCESSED           */
714*ef5ccd6cSJohn Marino /**********************************************/
715*ef5ccd6cSJohn Marino int
hexToInt(char ** ptr,int * intValue)716*ef5ccd6cSJohn Marino hexToInt (char **ptr, int *intValue)
717*ef5ccd6cSJohn Marino {
718*ef5ccd6cSJohn Marino   int numChars = 0;
719*ef5ccd6cSJohn Marino   int hexValue;
720*ef5ccd6cSJohn Marino 
721*ef5ccd6cSJohn Marino   *intValue = 0;
722*ef5ccd6cSJohn Marino 
723*ef5ccd6cSJohn Marino   while (**ptr)
724*ef5ccd6cSJohn Marino     {
725*ef5ccd6cSJohn Marino       hexValue = hex (**ptr);
726*ef5ccd6cSJohn Marino       if (hexValue >= 0)
727*ef5ccd6cSJohn Marino 	{
728*ef5ccd6cSJohn Marino 	  *intValue = (*intValue << 4) | hexValue;
729*ef5ccd6cSJohn Marino 	  numChars++;
730*ef5ccd6cSJohn Marino 	}
731*ef5ccd6cSJohn Marino       else
732*ef5ccd6cSJohn Marino 	break;
733*ef5ccd6cSJohn Marino 
734*ef5ccd6cSJohn Marino       (*ptr)++;
735*ef5ccd6cSJohn Marino     }
736*ef5ccd6cSJohn Marino 
737*ef5ccd6cSJohn Marino   return (numChars);
738*ef5ccd6cSJohn Marino }
739*ef5ccd6cSJohn Marino 
740*ef5ccd6cSJohn Marino /*
741*ef5ccd6cSJohn Marino  * This function does all command procesing for interfacing to gdb.
742*ef5ccd6cSJohn Marino  */
743*ef5ccd6cSJohn Marino void
handle_exception(int exceptionVector)744*ef5ccd6cSJohn Marino handle_exception (int exceptionVector)
745*ef5ccd6cSJohn Marino {
746*ef5ccd6cSJohn Marino   int sigval, stepping;
747*ef5ccd6cSJohn Marino   int addr, length;
748*ef5ccd6cSJohn Marino   char *ptr;
749*ef5ccd6cSJohn Marino   int newPC;
750*ef5ccd6cSJohn Marino 
751*ef5ccd6cSJohn Marino   gdb_i386vector = exceptionVector;
752*ef5ccd6cSJohn Marino 
753*ef5ccd6cSJohn Marino   if (remote_debug)
754*ef5ccd6cSJohn Marino     {
755*ef5ccd6cSJohn Marino       printf ("vector=%d, sr=0x%x, pc=0x%x\n",
756*ef5ccd6cSJohn Marino 	      exceptionVector, registers[PS], registers[PC]);
757*ef5ccd6cSJohn Marino     }
758*ef5ccd6cSJohn Marino 
759*ef5ccd6cSJohn Marino   /* reply to host that an exception has occurred */
760*ef5ccd6cSJohn Marino   sigval = computeSignal (exceptionVector);
761*ef5ccd6cSJohn Marino 
762*ef5ccd6cSJohn Marino   ptr = remcomOutBuffer;
763*ef5ccd6cSJohn Marino 
764*ef5ccd6cSJohn Marino   *ptr++ = 'T';			/* notify gdb with signo, PC, FP and SP */
765*ef5ccd6cSJohn Marino   *ptr++ = hexchars[sigval >> 4];
766*ef5ccd6cSJohn Marino   *ptr++ = hexchars[sigval & 0xf];
767*ef5ccd6cSJohn Marino 
768*ef5ccd6cSJohn Marino   *ptr++ = hexchars[ESP];
769*ef5ccd6cSJohn Marino   *ptr++ = ':';
770*ef5ccd6cSJohn Marino   ptr = mem2hex((char *)&registers[ESP], ptr, 4, 0);	/* SP */
771*ef5ccd6cSJohn Marino   *ptr++ = ';';
772*ef5ccd6cSJohn Marino 
773*ef5ccd6cSJohn Marino   *ptr++ = hexchars[EBP];
774*ef5ccd6cSJohn Marino   *ptr++ = ':';
775*ef5ccd6cSJohn Marino   ptr = mem2hex((char *)&registers[EBP], ptr, 4, 0); 	/* FP */
776*ef5ccd6cSJohn Marino   *ptr++ = ';';
777*ef5ccd6cSJohn Marino 
778*ef5ccd6cSJohn Marino   *ptr++ = hexchars[PC];
779*ef5ccd6cSJohn Marino   *ptr++ = ':';
780*ef5ccd6cSJohn Marino   ptr = mem2hex((char *)&registers[PC], ptr, 4, 0); 	/* PC */
781*ef5ccd6cSJohn Marino   *ptr++ = ';';
782*ef5ccd6cSJohn Marino 
783*ef5ccd6cSJohn Marino   *ptr = '\0'
784*ef5ccd6cSJohn Marino 
785*ef5ccd6cSJohn Marino   putpacket (remcomOutBuffer);
786*ef5ccd6cSJohn Marino 
787*ef5ccd6cSJohn Marino   stepping = 0;
788*ef5ccd6cSJohn Marino 
789*ef5ccd6cSJohn Marino   while (1 == 1)
790*ef5ccd6cSJohn Marino     {
791*ef5ccd6cSJohn Marino       remcomOutBuffer[0] = 0;
792*ef5ccd6cSJohn Marino       ptr = getpacket ();
793*ef5ccd6cSJohn Marino 
794*ef5ccd6cSJohn Marino       switch (*ptr++)
795*ef5ccd6cSJohn Marino 	{
796*ef5ccd6cSJohn Marino 	case '?':
797*ef5ccd6cSJohn Marino 	  remcomOutBuffer[0] = 'S';
798*ef5ccd6cSJohn Marino 	  remcomOutBuffer[1] = hexchars[sigval >> 4];
799*ef5ccd6cSJohn Marino 	  remcomOutBuffer[2] = hexchars[sigval % 16];
800*ef5ccd6cSJohn Marino 	  remcomOutBuffer[3] = 0;
801*ef5ccd6cSJohn Marino 	  break;
802*ef5ccd6cSJohn Marino 	case 'd':
803*ef5ccd6cSJohn Marino 	  remote_debug = !(remote_debug);	/* toggle debug flag */
804*ef5ccd6cSJohn Marino 	  break;
805*ef5ccd6cSJohn Marino 	case 'g':		/* return the value of the CPU registers */
806*ef5ccd6cSJohn Marino 	  mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES, 0);
807*ef5ccd6cSJohn Marino 	  break;
808*ef5ccd6cSJohn Marino 	case 'G':		/* set the value of the CPU registers - return OK */
809*ef5ccd6cSJohn Marino 	  hex2mem (ptr, (char *) registers, NUMREGBYTES, 0);
810*ef5ccd6cSJohn Marino 	  strcpy (remcomOutBuffer, "OK");
811*ef5ccd6cSJohn Marino 	  break;
812*ef5ccd6cSJohn Marino 	case 'P':		/* set the value of a single CPU register - return OK */
813*ef5ccd6cSJohn Marino 	  {
814*ef5ccd6cSJohn Marino 	    int regno;
815*ef5ccd6cSJohn Marino 
816*ef5ccd6cSJohn Marino 	    if (hexToInt (&ptr, &regno) && *ptr++ == '=')
817*ef5ccd6cSJohn Marino 	      if (regno >= 0 && regno < NUMREGS)
818*ef5ccd6cSJohn Marino 		{
819*ef5ccd6cSJohn Marino 		  hex2mem (ptr, (char *) &registers[regno], 4, 0);
820*ef5ccd6cSJohn Marino 		  strcpy (remcomOutBuffer, "OK");
821*ef5ccd6cSJohn Marino 		  break;
822*ef5ccd6cSJohn Marino 		}
823*ef5ccd6cSJohn Marino 
824*ef5ccd6cSJohn Marino 	    strcpy (remcomOutBuffer, "E01");
825*ef5ccd6cSJohn Marino 	    break;
826*ef5ccd6cSJohn Marino 	  }
827*ef5ccd6cSJohn Marino 
828*ef5ccd6cSJohn Marino 	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
829*ef5ccd6cSJohn Marino 	case 'm':
830*ef5ccd6cSJohn Marino 	  /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
831*ef5ccd6cSJohn Marino 	  if (hexToInt (&ptr, &addr))
832*ef5ccd6cSJohn Marino 	    if (*(ptr++) == ',')
833*ef5ccd6cSJohn Marino 	      if (hexToInt (&ptr, &length))
834*ef5ccd6cSJohn Marino 		{
835*ef5ccd6cSJohn Marino 		  ptr = 0;
836*ef5ccd6cSJohn Marino 		  mem_err = 0;
837*ef5ccd6cSJohn Marino 		  mem2hex ((char *) addr, remcomOutBuffer, length, 1);
838*ef5ccd6cSJohn Marino 		  if (mem_err)
839*ef5ccd6cSJohn Marino 		    {
840*ef5ccd6cSJohn Marino 		      strcpy (remcomOutBuffer, "E03");
841*ef5ccd6cSJohn Marino 		      debug_error ("memory fault");
842*ef5ccd6cSJohn Marino 		    }
843*ef5ccd6cSJohn Marino 		}
844*ef5ccd6cSJohn Marino 
845*ef5ccd6cSJohn Marino 	  if (ptr)
846*ef5ccd6cSJohn Marino 	    {
847*ef5ccd6cSJohn Marino 	      strcpy (remcomOutBuffer, "E01");
848*ef5ccd6cSJohn Marino 	    }
849*ef5ccd6cSJohn Marino 	  break;
850*ef5ccd6cSJohn Marino 
851*ef5ccd6cSJohn Marino 	  /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
852*ef5ccd6cSJohn Marino 	case 'M':
853*ef5ccd6cSJohn Marino 	  /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
854*ef5ccd6cSJohn Marino 	  if (hexToInt (&ptr, &addr))
855*ef5ccd6cSJohn Marino 	    if (*(ptr++) == ',')
856*ef5ccd6cSJohn Marino 	      if (hexToInt (&ptr, &length))
857*ef5ccd6cSJohn Marino 		if (*(ptr++) == ':')
858*ef5ccd6cSJohn Marino 		  {
859*ef5ccd6cSJohn Marino 		    mem_err = 0;
860*ef5ccd6cSJohn Marino 		    hex2mem (ptr, (char *) addr, length, 1);
861*ef5ccd6cSJohn Marino 
862*ef5ccd6cSJohn Marino 		    if (mem_err)
863*ef5ccd6cSJohn Marino 		      {
864*ef5ccd6cSJohn Marino 			strcpy (remcomOutBuffer, "E03");
865*ef5ccd6cSJohn Marino 			debug_error ("memory fault");
866*ef5ccd6cSJohn Marino 		      }
867*ef5ccd6cSJohn Marino 		    else
868*ef5ccd6cSJohn Marino 		      {
869*ef5ccd6cSJohn Marino 			strcpy (remcomOutBuffer, "OK");
870*ef5ccd6cSJohn Marino 		      }
871*ef5ccd6cSJohn Marino 
872*ef5ccd6cSJohn Marino 		    ptr = 0;
873*ef5ccd6cSJohn Marino 		  }
874*ef5ccd6cSJohn Marino 	  if (ptr)
875*ef5ccd6cSJohn Marino 	    {
876*ef5ccd6cSJohn Marino 	      strcpy (remcomOutBuffer, "E02");
877*ef5ccd6cSJohn Marino 	    }
878*ef5ccd6cSJohn Marino 	  break;
879*ef5ccd6cSJohn Marino 
880*ef5ccd6cSJohn Marino 	  /* cAA..AA    Continue at address AA..AA(optional) */
881*ef5ccd6cSJohn Marino 	  /* sAA..AA   Step one instruction from AA..AA(optional) */
882*ef5ccd6cSJohn Marino 	case 's':
883*ef5ccd6cSJohn Marino 	  stepping = 1;
884*ef5ccd6cSJohn Marino 	case 'c':
885*ef5ccd6cSJohn Marino 	  /* try to read optional parameter, pc unchanged if no parm */
886*ef5ccd6cSJohn Marino 	  if (hexToInt (&ptr, &addr))
887*ef5ccd6cSJohn Marino 	    registers[PC] = addr;
888*ef5ccd6cSJohn Marino 
889*ef5ccd6cSJohn Marino 	  newPC = registers[PC];
890*ef5ccd6cSJohn Marino 
891*ef5ccd6cSJohn Marino 	  /* clear the trace bit */
892*ef5ccd6cSJohn Marino 	  registers[PS] &= 0xfffffeff;
893*ef5ccd6cSJohn Marino 
894*ef5ccd6cSJohn Marino 	  /* set the trace bit if we're stepping */
895*ef5ccd6cSJohn Marino 	  if (stepping)
896*ef5ccd6cSJohn Marino 	    registers[PS] |= 0x100;
897*ef5ccd6cSJohn Marino 
898*ef5ccd6cSJohn Marino 	  _returnFromException ();	/* this is a jump */
899*ef5ccd6cSJohn Marino 	  break;
900*ef5ccd6cSJohn Marino 
901*ef5ccd6cSJohn Marino 	  /* kill the program */
902*ef5ccd6cSJohn Marino 	case 'k':		/* do nothing */
903*ef5ccd6cSJohn Marino #if 0
904*ef5ccd6cSJohn Marino 	  /* Huh? This doesn't look like "nothing".
905*ef5ccd6cSJohn Marino 	     m68k-stub.c and sparc-stub.c don't have it.  */
906*ef5ccd6cSJohn Marino 	  BREAKPOINT ();
907*ef5ccd6cSJohn Marino #endif
908*ef5ccd6cSJohn Marino 	  break;
909*ef5ccd6cSJohn Marino 	}			/* switch */
910*ef5ccd6cSJohn Marino 
911*ef5ccd6cSJohn Marino       /* reply to the request */
912*ef5ccd6cSJohn Marino       putpacket (remcomOutBuffer);
913*ef5ccd6cSJohn Marino     }
914*ef5ccd6cSJohn Marino }
915*ef5ccd6cSJohn Marino 
916*ef5ccd6cSJohn Marino /* this function is used to set up exception handlers for tracing and
917*ef5ccd6cSJohn Marino    breakpoints */
918*ef5ccd6cSJohn Marino void
set_debug_traps(void)919*ef5ccd6cSJohn Marino set_debug_traps (void)
920*ef5ccd6cSJohn Marino {
921*ef5ccd6cSJohn Marino   stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
922*ef5ccd6cSJohn Marino 
923*ef5ccd6cSJohn Marino   exceptionHandler (0, _catchException0);
924*ef5ccd6cSJohn Marino   exceptionHandler (1, _catchException1);
925*ef5ccd6cSJohn Marino   exceptionHandler (3, _catchException3);
926*ef5ccd6cSJohn Marino   exceptionHandler (4, _catchException4);
927*ef5ccd6cSJohn Marino   exceptionHandler (5, _catchException5);
928*ef5ccd6cSJohn Marino   exceptionHandler (6, _catchException6);
929*ef5ccd6cSJohn Marino   exceptionHandler (7, _catchException7);
930*ef5ccd6cSJohn Marino   exceptionHandler (8, _catchException8);
931*ef5ccd6cSJohn Marino   exceptionHandler (9, _catchException9);
932*ef5ccd6cSJohn Marino   exceptionHandler (10, _catchException10);
933*ef5ccd6cSJohn Marino   exceptionHandler (11, _catchException11);
934*ef5ccd6cSJohn Marino   exceptionHandler (12, _catchException12);
935*ef5ccd6cSJohn Marino   exceptionHandler (13, _catchException13);
936*ef5ccd6cSJohn Marino   exceptionHandler (14, _catchException14);
937*ef5ccd6cSJohn Marino   exceptionHandler (16, _catchException16);
938*ef5ccd6cSJohn Marino 
939*ef5ccd6cSJohn Marino   initialized = 1;
940*ef5ccd6cSJohn Marino }
941*ef5ccd6cSJohn Marino 
942*ef5ccd6cSJohn Marino /* This function will generate a breakpoint exception.  It is used at the
943*ef5ccd6cSJohn Marino    beginning of a program to sync up with a debugger and can be used
944*ef5ccd6cSJohn Marino    otherwise as a quick means to stop program execution and "break" into
945*ef5ccd6cSJohn Marino    the debugger.  */
946*ef5ccd6cSJohn Marino 
947*ef5ccd6cSJohn Marino void
breakpoint(void)948*ef5ccd6cSJohn Marino breakpoint (void)
949*ef5ccd6cSJohn Marino {
950*ef5ccd6cSJohn Marino   if (initialized)
951*ef5ccd6cSJohn Marino     BREAKPOINT ();
952*ef5ccd6cSJohn Marino }
953