OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [nlm/] [gdbserve.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.