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