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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [nlm/] [gdbserve.c] - Blame information for rev 578

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

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

powered by: WebSVN 2.1.0

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