* configure.in: Add nlm subdir to configdirs for alpha-*-netware
[external/binutils.git] / gdb / nlm / gdbserve.c
1 /* i386-nlmstub.c -- NLM debugging stub for the i386.
2
3    This is originally based on an m68k software stub written by Glenn
4    Engel at HP, but has changed quite a bit.  It was modified for the
5    i386 by Jim Kingdon, Cygnus Support.  It was modified to run under
6    NetWare by Ian Lance Taylor, Cygnus Support.
7
8    This code is intended to produce an NLM (a NetWare Loadable Module)
9    to run under NetWare on an i386 platform.  To create the NLM,
10    compile this code into an object file using the NLM SDK on any i386
11    host, and use the nlmconv program (available in the GNU binutils)
12    to transform the resulting object file into an NLM.  */
13
14 /****************************************************************************
15
16                 THIS SOFTWARE IS NOT COPYRIGHTED
17
18    HP offers the following for use in the public domain.  HP makes no
19    warranty with regard to the software or it's performance and the
20    user accepts the software "AS IS" with all faults.
21
22    HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
23    TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
24    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25
26 ****************************************************************************/
27
28 /****************************************************************************
29  *
30  *    The following gdb commands are supported:
31  *
32  * command          function                               Return value
33  *
34  *    g             return the value of the CPU registers  hex data or ENN
35  *    G             set the value of the CPU registers     OK or ENN
36  *
37  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
38  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
39  *
40  *    c             Resume at current address              SNN   ( signal NN)
41  *    cAA..AA       Continue at address AA..AA             SNN
42  *
43  *    s             Step one instruction                   SNN
44  *    sAA..AA       Step one instruction from AA..AA       SNN
45  *
46  *    k             kill
47  *
48  *    ?             What was the last sigval ?             SNN   (signal NN)
49  *
50  * All commands and responses are sent with a packet which includes a
51  * checksum.  A packet consists of
52  *
53  * $<packet info>#<checksum>.
54  *
55  * where
56  * <packet info> :: <characters representing the command or response>
57  * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
58  *
59  * When a packet is received, it is first acknowledged with either '+' or '-'.
60  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
61  *
62  * Example:
63  *
64  * Host:                  Reply:
65  * $m0,10#2a               +$00010203040506070809101112131415#42
66  *
67  ****************************************************************************/
68
69 #include <nwdfs.h>
70 #include <stdio.h>
71 #include <string.h>
72 #include <stdlib.h>
73 /*#include <ctype.h>*/
74 #include <time.h>
75 /*#include <aio.h>*/
76 #include <nwconio.h>
77 #include <nwadv.h>
78 #include <nwdbgapi.h>
79 /*#include <process.h>*/
80 #include <errno.h>
81 #include <nwthread.h>
82 #include "alpha-patch.h"
83
84 /****************************************************/
85 /* This information is from Novell.  It is not in any of the standard
86    NetWare header files.  */
87
88 struct DBG_LoadDefinitionStructure
89 {
90         void *reserved1[4];
91         LONG reserved5;
92         LONG LDCodeImageOffset;
93         LONG LDCodeImageLength;
94         LONG LDDataImageOffset;
95         LONG LDDataImageLength;
96         LONG LDUninitializedDataLength;
97         LONG LDCustomDataOffset;
98         LONG LDCustomDataSize;
99         LONG reserved6[2];
100         LONG (*LDInitializationProcedure)(void);
101 };
102
103 #define LO_NORMAL               0x0000
104 #define LO_STARTUP              0x0001
105 #define LO_PROTECT              0x0002
106 #define LO_DEBUG                0x0004
107 #define LO_AUTO_LOAD            0x0008
108
109 /* Loader returned error codes */
110 #define LOAD_COULD_NOT_FIND_FILE                        1
111 #define LOAD_ERROR_READING_FILE                         2
112 #define LOAD_NOT_NLM_FILE_FORMAT                        3
113 #define LOAD_WRONG_NLM_FILE_VERSION                     4
114 #define LOAD_REENTRANT_INITIALIZE_FAILURE       5
115 #define LOAD_CAN_NOT_LOAD_MULTIPLE_COPIES       6
116 #define LOAD_ALREADY_IN_PROGRESS                        7
117 #define LOAD_NOT_ENOUGH_MEMORY                          8
118 #define LOAD_INITIALIZE_FAILURE                         9
119 #define LOAD_INCONSISTENT_FILE_FORMAT           10
120 #define LOAD_CAN_NOT_LOAD_AT_STARTUP            11
121 #define LOAD_AUTO_LOAD_MODULES_NOT_LOADED       12
122 #define LOAD_UNRESOLVED_EXTERNAL                        13
123 #define LOAD_PUBLIC_ALREADY_DEFINED                     14
124 /****************************************************/
125
126 /* The main thread ID.  */
127 static int mainthread;
128
129 /* An error message for the main thread to print.  */
130 static char *error_message;
131
132 /* The AIO port handle.  */
133 static int AIOhandle;
134
135 /* BUFMAX defines the maximum number of characters in inbound/outbound
136    buffers.  At least NUMREGBYTES*2 are needed for register packets */
137 #define BUFMAX (REGISTER_BYTES * 2 + 16)
138
139 /* remote_debug > 0 prints ill-formed commands in valid packets and
140    checksum errors. */
141 static int remote_debug = 1;
142
143 static const char hexchars[] = "0123456789abcdef";
144
145 /* Register values.  All of these values *MUST* agree with tm.h */
146 #define RA_REGNUM 26            /* Contains return address value */
147 #define SP_REGNUM 30            /* Contains address of top of stack */
148 #define PC_REGNUM 64            /* Contains program counter */
149 #define FP_REGNUM 65            /* Virtual frame pointer */
150 #define V0_REGNUM 0             /* Function integer return value */
151 #define NUM_REGS 66             /* Number of machine registers */
152 #define REGISTER_BYTES (NUM_REGS * 8) /* Total size of registers array */
153
154 #define ExceptionPC ExceptionRegs[SF_REG_PC].lo
155 #define DECR_PC_AFTER_BREAK 0   /* NT's Palcode gets this right! */
156 #define BREAKPOINT {0x80, 0, 0, 0} /* call_pal bpt */
157
158 unsigned char breakpoint_insn[] = BREAKPOINT;
159 #define BREAKPOINT_SIZE (sizeof breakpoint_insn)
160
161 /*#define flush_i_cache() asm("call_pal 0x86")*/
162
163 static char *mem2hex (void *mem, char *buf, int count, int may_fault);
164 static char *hex2mem (char *buf, void *mem, int count, int may_fault);
165 static void set_step_traps (struct StackFrame *);
166 static void clear_step_traps (struct StackFrame *);
167
168 #if 0
169 __main() {};
170 #endif
171
172 /* Read a character from the serial port.  This must busy wait, but
173    that's OK because we will be the only thread running anyhow.  */
174
175 static int
176 getDebugChar ()
177 {
178   int err;
179   LONG got;
180   unsigned char ret;
181
182   do
183     {
184       err = AIOReadData (AIOhandle, (char *) &ret, 1, &got);
185       if (err != 0)
186         {
187           error_message = "AIOReadData failed";
188           ResumeThread (mainthread);
189           return -1;
190         }
191     }
192   while (got == 0);
193
194   return ret;
195 }
196
197 /* Write a character to the serial port.  Returns 0 on failure,
198    non-zero on success.  */
199
200 static int
201 putDebugChar (c)
202      unsigned char c;
203 {
204   int err;
205   LONG put;
206
207   put = 0;
208   while (put < 1)
209     {
210       err = AIOWriteData (AIOhandle, (char *) &c, 1, &put);
211       if (err != 0)
212         ConsolePrintf ("AIOWriteData: err = %d, put = %d\r\n", err, put);
213     }
214   return 1;
215 }
216
217 /* Get the registers out of the frame information.  */
218
219 static void
220 frame_to_registers (frame, regs)
221      struct StackFrame *frame;
222      char *regs;
223 {
224   mem2hex (&frame->ExceptionPC, &regs[PC_REGNUM * 8 * 2], 8 * 1, 0);
225
226   mem2hex (&frame->ExceptionRegs[SF_IREG_OFFSET], &regs[V0_REGNUM * 8 * 2], 8 * 64, 0);
227 }
228
229 /* Put the registers back into the frame information.  */
230
231 static void
232 registers_to_frame (regs, frame)
233      char *regs;
234      struct StackFrame *frame;
235 {
236   hex2mem (&regs[PC_REGNUM * 8 * 2], &frame->ExceptionPC, 8 * 1, 0);
237
238   hex2mem (&regs[V0_REGNUM * 8 * 2], &frame->ExceptionRegs[SF_IREG_OFFSET], 8 * 64, 0);
239 }
240
241 /* Turn a hex character into a number.  */
242
243 static int
244 hex (ch)
245      char ch;
246 {
247   if ((ch >= 'a') && (ch <= 'f'))
248     return (ch-'a'+10);
249   if ((ch >= '0') && (ch <= '9'))
250     return (ch-'0');
251   if ((ch >= 'A') && (ch <= 'F'))
252     return (ch-'A'+10);
253   return (-1);
254 }
255
256 /* Scan for the sequence $<data>#<checksum>.  Returns 0 on failure,
257    non-zero on success.  */
258
259 static int
260 getpacket (buffer)
261      char * buffer;
262 {
263   unsigned char checksum;
264   unsigned char xmitcsum;
265   int i;
266   int count;
267   int ch;
268
269   do
270     {
271       /* wait around for the start character, ignore all other characters */
272       while ((ch = getDebugChar()) != '$')
273         if (ch == -1)
274           return 0;
275       checksum = 0;
276       xmitcsum = -1;
277
278       count = 0;
279
280       /* now, read until a # or end of buffer is found */
281       while (count < BUFMAX)
282         {
283           ch = getDebugChar();
284           if (ch == -1)
285             return 0;
286           if (ch == '#')
287             break;
288           checksum = checksum + ch;
289           buffer[count] = ch;
290           count = count + 1;
291         }
292       buffer[count] = 0;
293
294       if (ch == '#')
295         {
296           ch = getDebugChar ();
297           if (ch == -1)
298             return 0;
299           xmitcsum = hex(ch) << 4;
300           ch = getDebugChar ();
301           if (ch == -1)
302             return 0;
303           xmitcsum += hex(ch);
304
305           if (checksum != xmitcsum)
306             {
307               if (remote_debug)
308                 ConsolePrintf ("bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
309                                checksum,xmitcsum,buffer);
310               /* failed checksum */
311               if (! putDebugChar('-'))
312                 return 0;
313               return 1;
314             }
315           else
316             {
317               /* successful transfer */
318               if (! putDebugChar('+'))
319                 return 0;
320               /* if a sequence char is present, reply the sequence ID */
321               if (buffer[2] == ':')
322                 {
323                   if (! putDebugChar (buffer[0])
324                       || ! putDebugChar (buffer[1]))
325                     return 0;
326                   /* remove sequence chars from buffer */
327                   count = strlen(buffer);
328                   for (i=3; i <= count; i++)
329                     buffer[i-3] = buffer[i];
330                 }
331             }
332         }
333     }
334   while (checksum != xmitcsum);
335
336   if (remote_debug)
337     ConsolePrintf ("Received packet \"%s\"\r\n", buffer);
338
339   return 1;
340 }
341
342 /* Send the packet in buffer.  Returns 0 on failure, non-zero on
343    success.  */
344
345 static int
346 putpacket (buffer)
347      char * buffer;
348 {
349   unsigned char checksum;
350   int count;
351   int ch;
352
353   if (remote_debug)
354     ConsolePrintf ("Sending packet \"%s\"\r\n", buffer);
355
356   /*  $<packet info>#<checksum>. */
357   do
358     {
359       if (! putDebugChar('$'))
360         return 0;
361       checksum = 0;
362       count = 0;
363
364       while (ch=buffer[count])
365         {
366           if (! putDebugChar(ch))
367             return 0;
368           checksum += ch;
369           count += 1;
370         }
371
372       if (! putDebugChar('#')
373           || ! putDebugChar(hexchars[checksum >> 4])
374           || ! putDebugChar(hexchars[checksum % 16]))
375         return 0;
376
377       ch = getDebugChar ();
378       if (ch == -1)
379         return 0;
380     }
381   while (ch != '+');
382
383   return 1;
384 }
385
386 static char remcomInBuffer[BUFMAX];
387 static char remcomOutBuffer[BUFMAX];
388 static short error;
389
390 static void
391 debug_error (format, parm)
392      char *format;
393      char *parm;
394 {
395   if (remote_debug)
396     {
397       ConsolePrintf (format, parm);
398       ConsolePrintf ("\n");
399     }
400 }
401
402 /* This is set if we could get a memory access fault.  */
403 static int mem_may_fault;
404
405 /* Indicate to caller of mem2hex or hex2mem that there has been an
406    error.  */
407 static volatile int mem_err = 0;
408
409 /* These are separate functions so that they are so short and sweet
410    that the compiler won't save any registers (if there is a fault
411    to mem_fault, they won't get restored, so there better not be any
412    saved).  */
413
414 static int
415 get_char (addr)
416      char *addr;
417 {
418   return *addr;
419 }
420
421 static void
422 set_char (addr, val)
423      char *addr;
424      int val;
425 {
426   *addr = val;
427 }
428
429 /* This bit of assembly language just returns from a function.  If a
430    memory error occurs within get_char or set_char, the debugger
431    handler points EIP at these instructions to get out.  */
432
433 extern void just_return ();
434 #if 0
435 asm (".globl just_return");
436 asm (".globl _just_return");
437 asm ("just_return:");
438 asm ("_just_return:");
439 asm ("leave");
440 asm ("ret");
441 #endif
442
443 /* convert the memory pointed to by mem into hex, placing result in buf */
444 /* return a pointer to the last char put in buf (null) */
445 /* If MAY_FAULT is non-zero, then we should set mem_err in response to
446    a fault; if zero treat a fault like any other fault in the stub.  */
447
448 static char *
449 mem2hex (mem, buf, count, may_fault)
450      void *mem;
451      char *buf;
452      int count;
453      int may_fault;
454 {
455   int i;
456   unsigned char ch;
457   char *ptr = mem;
458
459   mem_may_fault = may_fault;
460   for (i = 0; i < count; i++)
461     {
462       ch = get_char (ptr++);
463       if (may_fault && mem_err)
464         return (buf);
465       *buf++ = hexchars[ch >> 4];
466       *buf++ = hexchars[ch % 16];
467     }
468   *buf = 0;
469   mem_may_fault = 0;
470   return(buf);
471 }
472
473 /* convert the hex array pointed to by buf into binary to be placed in mem */
474 /* return a pointer to the character AFTER the last byte written */
475
476 static char *
477 hex2mem (buf, mem, count, may_fault)
478      char *buf;
479      void *mem;
480      int count;
481      int may_fault;
482 {
483   int i;
484   unsigned char ch;
485   char *ptr = mem;
486
487   mem_may_fault = may_fault;
488   for (i=0;i<count;i++)
489     {
490       ch = hex(*buf++) << 4;
491       ch = ch + hex(*buf++);
492       set_char (ptr++, ch);
493       if (may_fault && mem_err)
494         return (ptr);
495     }
496   mem_may_fault = 0;
497   return(mem);
498 }
499
500 /* This function takes the 386 exception vector and attempts to
501    translate this number into a unix compatible signal value.  */
502
503 static int
504 computeSignal (exceptionVector)
505      int exceptionVector;
506 {
507   int sigval;
508   switch (exceptionVector)
509     {
510     case 0 : sigval = 8; break; /* divide by zero */
511     case 1 : sigval = 5; break; /* debug exception */
512     case 3 : sigval = 5; break; /* breakpoint */
513     case 4 : sigval = 16; break; /* into instruction (overflow) */
514     case 5 : sigval = 16; break; /* bound instruction */
515     case 6 : sigval = 4; break; /* Invalid opcode */
516     case 7 : sigval = 8; break; /* coprocessor not available */
517     case 8 : sigval = 7; break; /* double fault */
518     case 9 : sigval = 11; break; /* coprocessor segment overrun */
519     case 10 : sigval = 11; break; /* Invalid TSS */
520     case 11 : sigval = 11; break; /* Segment not present */
521     case 12 : sigval = 11; break; /* stack exception */
522     case 13 : sigval = 11; break; /* general protection */
523     case 14 : sigval = 11; break; /* page fault */
524     case 16 : sigval = 7; break; /* coprocessor error */
525     default:
526       sigval = 7;               /* "software generated"*/
527     }
528   return (sigval);
529 }
530
531 /**********************************************/
532 /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
533 /* RETURN NUMBER OF CHARS PROCESSED           */
534 /**********************************************/
535 static int
536 hexToInt(ptr, intValue)
537      char **ptr;
538      int *intValue;
539 {
540   int numChars = 0;
541   int hexValue;
542
543   *intValue = 0;
544
545   while (**ptr)
546     {
547       hexValue = hex(**ptr);
548       if (hexValue >=0)
549         {
550           *intValue = (*intValue <<4) | hexValue;
551           numChars ++;
552         }
553       else
554         break;
555
556       (*ptr)++;
557     }
558
559   return (numChars);
560 }
561
562 union inst
563 {
564   LONG l;
565
566   struct
567     {
568       union
569         {
570           struct
571             {
572               unsigned hint : 16;
573               unsigned rb : 5;
574               unsigned ra : 5;
575               unsigned opcode : 6;
576             } jump;
577           struct
578             {
579               signed disp : 21;
580               unsigned ra : 5;
581               unsigned opcode : 6;
582             } branch;
583         } variant;
584     } inst;
585 };
586
587 static LONG saved_inst;
588 static LONG *saved_inst_pc = 0;
589 static LONG saved_target_inst;
590 static LONG *saved_target_inst_pc = 0;
591
592 static void
593 set_step_traps (frame)
594      struct StackFrame *frame;
595 {
596   union inst inst;
597   LONG *target;
598   int opcode;
599   int ra, rb;
600   LONG *pc = (LONG *)frame->ExceptionPC;
601
602   inst.l = *pc++;
603
604   opcode = inst.inst.variant.branch.opcode;
605
606   if ((opcode & 0x30) == 0x30)  /* A branch of some sort */
607     target = inst.inst.variant.branch.disp + pc;
608   else if (opcode == 0x1a)      /* jmp, ret, etc... */
609     target = (LONG *)(frame->ExceptionRegs[SF_IREG_OFFSET
610                                            + inst.inst.variant.jump.rb].lo
611                       & ~3);
612   else
613     target = pc;
614
615   saved_inst = *pc;
616   *pc = 0x80;                   /* call_pal bpt */
617   saved_inst_pc = pc;
618
619   if (target != pc)
620     {
621       saved_target_inst = *target;
622       *target = 0x80;           /* call_pal bpt */
623       saved_target_inst_pc = target;
624     }
625 }
626
627 /* Remove step breakpoints.  Returns non-zero if pc was at a step breakpoint,
628    zero otherwise.  This routine works even if there were no step breakpoints
629    set.  */
630
631 static int
632 clear_step_traps (frame)
633      struct StackFrame *frame;
634 {
635   int retcode;
636   LONG *pc = (LONG *)frame->ExceptionPC;
637
638   if (saved_inst_pc == pc || saved_target_inst_pc == pc)
639     retcode = 1;
640   else
641     retcode = 0;
642
643   if (saved_inst_pc)
644     {
645       *saved_inst_pc = saved_inst;
646       saved_inst_pc = 0;
647     }
648
649   if (saved_target_inst_pc)
650     {
651       *saved_target_inst_pc = saved_target_inst;
652       saved_target_inst_pc = 0;
653     }
654
655   return retcode;
656 }
657
658 static void
659 do_status (ptr, frame)
660      char *ptr;
661      struct StackFrame *frame;
662 {
663   int sigval;
664
665   sigval = computeSignal (frame->ExceptionNumber);
666
667   sprintf (ptr, "T%02x", sigval);
668   ptr += 3;
669
670   sprintf (ptr, "%02x:", PC_REGNUM);
671   ptr = mem2hex (&frame->ExceptionPC, ptr + 3, 8, 0);
672   *ptr++ = ';';
673
674   sprintf (ptr, "%02x:", SP_REGNUM);
675   ptr = mem2hex (&frame->ExceptionRegs[SF_IREG_OFFSET + SP_REGNUM], ptr + 3, 8, 0);
676   *ptr++ = ';';
677
678   sprintf (ptr, "%02x:", RA_REGNUM);
679   ptr = mem2hex (&frame->ExceptionRegs[SF_IREG_OFFSET + RA_REGNUM], ptr + 3, 8, 0);
680   *ptr++ = ';';
681
682   sprintf (ptr, "%02x:", FP_REGNUM);
683   ptr = mem2hex (&frame->ExceptionRegs[SF_IREG_OFFSET + FP_REGNUM], ptr + 3, 8, 0);
684   *ptr++ = ';';
685
686   *ptr = '\000';
687 }
688
689 /* This function does all command processing for interfacing to gdb.
690    It is called whenever an exception occurs in the module being
691    debugged.  */
692
693 static LONG
694 handle_exception (frame)
695      struct StackFrame *frame;
696 {
697   int addr, length;
698   char *ptr;
699   static struct DBG_LoadDefinitionStructure *ldinfo = 0;
700   static unsigned char first_insn[BREAKPOINT_SIZE]; /* The first instruction in the program.  */
701
702   /* Apparently the bell can sometimes be ringing at this point, and
703      should be stopped.  */
704   StopBell ();
705
706   if (remote_debug)
707     {
708       ConsolePrintf ("vector=%d: %s, pc=%08x, thread=%08x\r\n",
709                      frame->ExceptionNumber,
710                      frame->ExceptionDescription,
711                      frame->ExceptionPC,
712                      GetThreadID ());
713     }
714
715   switch (frame->ExceptionNumber)
716     {
717     case START_NLM_EVENT:
718       /* If the NLM just started, we record the module load information
719          and the thread ID, and set a breakpoint at the first instruction
720          in the program.  */
721
722       ldinfo = ((struct DBG_LoadDefinitionStructure *)
723                 frame->ExceptionErrorCode);
724       memcpy (first_insn, ldinfo->LDInitializationProcedure,
725               BREAKPOINT_SIZE);
726       memcpy (ldinfo->LDInitializationProcedure, breakpoint_insn,
727               BREAKPOINT_SIZE);
728       flush_i_cache ();
729       return RETURN_TO_PROGRAM;
730
731     case ENTER_DEBUGGER_EVENT:
732     case KEYBOARD_BREAK_EVENT:
733       /* Pass some events on to the next debugger, in case it will handle
734          them.  */
735       return RETURN_TO_NEXT_DEBUGGER;
736
737     case 3:                     /* Breakpoint */
738       /* After we've reached the initial breakpoint, reset it.  */
739       if (frame->ExceptionPC - DECR_PC_AFTER_BREAK == (LONG) ldinfo->LDInitializationProcedure
740           && memcmp (ldinfo->LDInitializationProcedure, breakpoint_insn,
741                      BREAKPOINT_SIZE) == 0)
742         {
743           memcpy (ldinfo->LDInitializationProcedure, first_insn,
744                   BREAKPOINT_SIZE);
745           frame->ExceptionPC -= DECR_PC_AFTER_BREAK;
746           flush_i_cache ();
747         }
748       /* Normal breakpoints end up here */
749       do_status (remcomOutBuffer, frame);
750       break;
751
752     default:
753       /* At the moment, we don't care about most of the unusual NetWare
754          exceptions.  */
755       if (frame->ExceptionNumber > 31)
756         return RETURN_TO_PROGRAM;
757
758       /* Most machine level exceptions end up here */
759       do_status (remcomOutBuffer, frame);
760       break;
761
762     case 11:                    /* Segment not present */
763     case 13:                    /* General protection */
764     case 14:                    /* Page fault */
765       /* If we get a GP fault, and mem_may_fault is set, and the
766          instruction pointer is near set_char or get_char, then we caused
767          the fault ourselves accessing an illegal memory location.  */
768       if (mem_may_fault
769           && ((frame->ExceptionPC >= (long) &set_char
770                && frame->ExceptionPC < (long) &set_char + 50)
771               || (frame->ExceptionPC >= (long) &get_char
772                   && frame->ExceptionPC < (long) &get_char + 50)))
773         {
774           mem_err = 1;
775           /* Point the instruction pointer at an assembly language stub
776              which just returns from the function.  */
777
778           frame->ExceptionPC += 4; /* Skip the load or store */
779
780           /* Keep going.  This will act as though it returned from
781              set_char or get_char.  The calling routine will check
782              mem_err, and do the right thing.  */
783           return RETURN_TO_PROGRAM;
784         }
785       /* Random mem fault, report it */
786       do_status (remcomOutBuffer, frame);
787       break;
788
789     case TERMINATE_NLM_EVENT:
790       /* There is no way to get the exit status.  */
791       sprintf (remcomOutBuffer, "W%02x", 0);
792       break;                    /* We generate our own status */
793     }
794
795   /* FIXME: How do we know that this exception has anything to do with
796      the program we are debugging?  We can check whether the PC is in
797      the range of the module we are debugging, but that doesn't help
798      much since an error could occur in a library routine.  */
799
800   clear_step_traps (frame);
801
802   if (! putpacket(remcomOutBuffer))
803     return RETURN_TO_NEXT_DEBUGGER;
804
805   if (frame->ExceptionNumber == TERMINATE_NLM_EVENT)
806     {
807       ResumeThread (mainthread);
808       return RETURN_TO_PROGRAM;
809     }
810
811   while (1)
812     {
813       error = 0;
814       remcomOutBuffer[0] = 0;
815       if (! getpacket (remcomInBuffer))
816         return RETURN_TO_NEXT_DEBUGGER;
817       switch (remcomInBuffer[0])
818         {
819         case '?':
820           do_status (remcomOutBuffer, frame);
821           break;
822         case 'd':
823           remote_debug = !(remote_debug); /* toggle debug flag */
824           break;
825         case 'g':
826           /* return the value of the CPU registers */
827           frame_to_registers (frame, remcomOutBuffer);
828           break;
829         case 'G':
830           /* set the value of the CPU registers - return OK */
831           registers_to_frame (&remcomInBuffer[1], frame);
832           strcpy(remcomOutBuffer,"OK");
833           break;
834
835         case 'm':
836           /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
837           /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
838           ptr = &remcomInBuffer[1];
839           if (hexToInt(&ptr,&addr))
840             if (*(ptr++) == ',')
841               if (hexToInt(&ptr,&length))
842                 {
843                   ptr = 0;
844                   mem_err = 0;
845                   mem2hex((char*) addr, remcomOutBuffer, length, 1);
846                   if (mem_err)
847                     {
848                       strcpy (remcomOutBuffer, "E03");
849                       debug_error ("memory fault");
850                     }
851                 }
852
853           if (ptr)
854             {
855               strcpy(remcomOutBuffer,"E01");
856               debug_error("malformed read memory command: %s",remcomInBuffer);
857             }
858           break;
859
860         case 'M':
861           /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
862           /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
863           ptr = &remcomInBuffer[1];
864           if (hexToInt(&ptr,&addr))
865             if (*(ptr++) == ',')
866               if (hexToInt(&ptr,&length))
867                 if (*(ptr++) == ':')
868                   {
869                     mem_err = 0;
870                     hex2mem(ptr, (char*) addr, length, 1);
871
872                     if (mem_err)
873                       {
874                         strcpy (remcomOutBuffer, "E03");
875                         debug_error ("memory fault");
876                       }
877                     else
878                       {
879                         strcpy(remcomOutBuffer,"OK");
880                       }
881
882                     ptr = 0;
883                   }
884           if (ptr)
885             {
886               strcpy(remcomOutBuffer,"E02");
887               debug_error("malformed write memory command: %s",remcomInBuffer);
888             }
889           break;
890
891         case 'c':
892         case 's':
893           /* cAA..AA    Continue at address AA..AA(optional) */
894           /* sAA..AA   Step one instruction from AA..AA(optional) */
895           /* try to read optional parameter, pc unchanged if no parm */
896           ptr = &remcomInBuffer[1];
897           if (hexToInt(&ptr,&addr))
898             {
899 /*            registers[PC_REGNUM].lo = addr;*/
900               fprintf (stderr, "Setting PC to 0x%x\n", addr);
901               while (1);
902             }
903
904           if (remcomInBuffer[0] == 's')
905             set_step_traps (frame);
906
907           flush_i_cache ();
908           return RETURN_TO_PROGRAM;
909
910         case 'k':
911           /* kill the program */
912           KillMe (ldinfo);
913           ResumeThread (mainthread);
914           return RETURN_TO_PROGRAM;
915
916         case 'q':               /* Query message */
917           if (strcmp (&remcomInBuffer[1], "Offsets") == 0)
918             {
919               sprintf (remcomOutBuffer, "Text=%x;Data=%x;Bss=%x",
920                        ldinfo->LDCodeImageOffset,
921                        ldinfo->LDDataImageOffset,
922                        ldinfo->LDDataImageOffset + ldinfo->LDDataImageLength);
923             }
924           else
925             sprintf (remcomOutBuffer, "E04, Unknown query %s", &remcomInBuffer[1]);
926           break;
927         }
928
929       /* reply to the request */
930       if (! putpacket(remcomOutBuffer))
931         return RETURN_TO_NEXT_DEBUGGER;
932     }
933 }
934
935 char *baudRates[] = { "50", "75", "110", "134.5", "150", "300", "600", "1200",
936                         "1800", "2000", "2400", "3600", "4800", "7200", "9600",
937                         "19200", "38400", "57600", "115200" };
938
939 char dataBits[] = "5678";
940
941 char *stopBits[] = { "1", "1.5", "2" };
942
943 char parity[] = "NOEMS";
944
945 /* Start up.  The main thread opens the named serial I/O port, loads
946    the named NLM module and then goes to sleep.  The serial I/O port
947    is named as a board number and a port number.  It would be more DOS
948    like to provide a menu of available serial ports, but I don't want
949    to have to figure out how to do that.  */
950
951 int
952 main (argc, argv)
953      int argc;
954      char **argv;
955 {
956   int hardware, board, port;
957   LONG err;
958   struct debuggerStructure s;
959   char *cmdlin;
960   int i;
961
962 /* Use the -B option to invoke the NID if you want to debug the stub. */
963
964   if (argc > 1 && strcmp(argv[1], "-B") == 0)
965     {
966       Breakpoint(argc);
967       ++argv, --argc;
968     }
969
970   if (argc < 4)
971     {
972       fprintf (stderr,
973                "Usage: load gdbserve board port program [arguments]\n");
974       exit (1);
975     }
976
977   hardware = -1;
978   board = strtol (argv[1], (char **) NULL, 0);
979   port = strtol (argv[2], (char **) NULL, 0);
980
981   err = AIOAcquirePort (&hardware, &board, &port, &AIOhandle);
982   if (err != AIO_SUCCESS)
983     {
984       switch (err)
985         {
986         case AIO_PORT_NOT_AVAILABLE:
987           fprintf (stderr, "Port not available\n");
988           break;
989
990         case AIO_BOARD_NUMBER_INVALID:
991         case AIO_PORT_NUMBER_INVALID:
992           fprintf (stderr, "No such port\n");
993           break;
994
995         default:
996           fprintf (stderr, "Could not open port: %d\n", err);
997           break;
998         }
999
1000       exit (1);
1001     }
1002
1003   err = AIOConfigurePort (AIOhandle, AIO_BAUD_9600, AIO_DATA_BITS_8,
1004                           AIO_STOP_BITS_1, AIO_PARITY_NONE,
1005                           AIO_HARDWARE_FLOW_CONTROL_OFF);
1006
1007   if (err == AIO_QUALIFIED_SUCCESS)
1008     {
1009       AIOPORTCONFIG portConfig;
1010       AIODVRCONFIG dvrConfig;
1011
1012       fprintf (stderr, "Port configuration changed!\n");
1013       AIOGetPortConfiguration (AIOhandle, &portConfig, &dvrConfig);
1014       fprintf (stderr,
1015                "  Bit Rate: %s, Data Bits: %c, Stop Bits: %s, Parity: %c,\
1016  Flow:%s\n",
1017                baudRates[portConfig.bitRate],
1018                dataBits[portConfig.dataBits],
1019                stopBits[portConfig.stopBits],
1020                parity[portConfig.parityMode],
1021                portConfig.flowCtrlMode ? "ON" : "OFF");
1022     }
1023   else if (err != AIO_SUCCESS)
1024     {
1025       fprintf (stderr, "Could not configure port: %d\n", err);
1026       AIOReleasePort (AIOhandle);
1027       exit (1);
1028     }
1029
1030   if (AIOSetExternalControl(AIOhandle, AIO_EXTERNAL_CONTROL,
1031                             (AIO_EXTCTRL_DTR | AIO_EXTCTRL_RTS))
1032       != AIO_SUCCESS)
1033     {
1034       LONG extStatus, chgdExtStatus;
1035
1036       fprintf (stderr, "Could not set desired port controls!\n");
1037       AIOGetExternalStatus (AIOhandle, &extStatus, &chgdExtStatus);
1038       fprintf (stderr, "Port controls now: %d, %d\n", extStatus, 
1039                chgdExtStatus);
1040     }
1041
1042   /* Register ourselves as an alternate debugger.  */
1043   memset (&s, 0, sizeof s);
1044   s.DDSResourceTag = ((struct ResourceTagStructure *)
1045                       AllocateResourceTag (GetNLMHandle (),
1046                                            (BYTE *)"gdbserver",
1047                                            DebuggerSignature));
1048   if (s.DDSResourceTag == 0)
1049     {
1050       fprintf (stderr, "AllocateResourceTag failed\n");
1051       AIOReleasePort (AIOhandle);
1052       exit (1);
1053     }
1054   s.DDSdebuggerEntry = handle_exception;
1055   s.DDSFlags = TSS_FRAME_BIT;
1056
1057   err = RegisterDebuggerRTag (&s, AT_FIRST);
1058   if (err != 0)
1059     {
1060       fprintf (stderr, "RegisterDebuggerRTag failed\n");
1061       AIOReleasePort (AIOhandle);
1062       exit (1);
1063     }
1064
1065   /* Get the command line we were invoked with, and advance it past
1066      our name and the board and port arguments.  */
1067   cmdlin = getcmd ((char *) NULL);
1068   for (i = 0; i < 2; i++)
1069     {
1070       while (! isspace (*cmdlin))
1071         ++cmdlin;
1072       while (isspace (*cmdlin))
1073         ++cmdlin;
1074     }
1075   
1076   /* In case GDB is started before us, ack any packets (presumably
1077      "$?#xx") sitting there.  */
1078   if (! putDebugChar ('+'))
1079     {
1080       fprintf (stderr, "putDebugChar failed\n");
1081       UnRegisterDebugger (&s);
1082       AIOReleasePort (AIOhandle);
1083       exit (1);
1084     }
1085
1086   mainthread = GetThreadID ();
1087
1088   if (remote_debug > 0)
1089     ConsolePrintf ("About to call LoadModule with \"%s\" %08x\r\n",
1090                    cmdlin, __GetScreenID (GetCurrentScreen()));
1091
1092   /* Start up the module to be debugged.  */
1093   err = LoadModule ((struct ScreenStruct *) __GetScreenID (GetCurrentScreen()),
1094                     (BYTE *)cmdlin, LO_DEBUG);
1095   if (err != 0)
1096     {
1097       fprintf (stderr, "LoadModule failed: %d\n", err);
1098       UnRegisterDebugger (&s);
1099       AIOReleasePort (AIOhandle);
1100       exit (1);
1101     }
1102
1103   /* Wait for the debugger to wake us up.  */
1104   if (remote_debug > 0)
1105     ConsolePrintf ("Suspending main thread (%08x)\r\n", mainthread);
1106   SuspendThread (mainthread);
1107   if (remote_debug > 0)
1108     ConsolePrintf ("Resuming main thread (%08x)\r\n", mainthread);
1109
1110   /* If we are woken up, print an optional error message, deregister
1111      ourselves and exit.  */
1112   if (error_message != NULL)
1113     fprintf (stderr, "%s\n", error_message);
1114   UnRegisterDebugger (&s);
1115   AIOReleasePort (AIOhandle);
1116   exit (0);
1117 }