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 *)®isters[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 *)®isters[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 *)®isters[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, ®no) && *ptr++ == '=')
817*ef5ccd6cSJohn Marino if (regno >= 0 && regno < NUMREGS)
818*ef5ccd6cSJohn Marino {
819*ef5ccd6cSJohn Marino hex2mem (ptr, (char *) ®isters[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