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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [common/] [current/] [src/] [generic-stub.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
#include "board.h"
2
 
3
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
4
 
5
/* Eventually, this should default to ON */
6
#if USE_GDBSTUB_PROTOTYPES
7
#include "stub-tservice.h"
8
#include "generic-stub.h"
9
#else
10
// Function declarations (prevents compiler warnings)
11
int stubhex (unsigned char ch);
12
static void unlock_thread_scheduler (void);
13
static uint32 crc32 (target_addr_t mem, int len, uint32 crc);
14
#endif
15
 
16
#include "thread-pkts.h"
17
  /* Defines function macros if thread support is not selected in board.h */
18
 
19
#ifdef __ECOS__
20
char GDB_stubs_version[] CYGBLD_ATTRIB_WEAK =
21
    "eCos GDB stubs - built " __DATE__ " / " __TIME__;
22
#endif
23
 
24
/****************************************************************************
25
 
26
                THIS SOFTWARE IS NOT COPYRIGHTED
27
 
28
   HP offers the following for use in the public domain.  HP makes no
29
   warranty with regard to the software or it's performance and the
30
   user accepts the software "AS IS" with all faults.
31
 
32
   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
33
   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
34
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
35
 
36
****************************************************************************/
37
 
38
/****************************************************************************
39
 *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
40
 *
41
 *  Module name: remcom.c $
42
 *  Revision: 1.34 $
43
 *  Date: 91/03/09 12:29:49 $
44
 *  Contributor:     Lake Stevens Instrument Division$
45
 *
46
 *  Description:     low level support for gdb debugger. $
47
 *
48
 *  Considerations:  only works on target hardware $
49
 *
50
 *  Written by:      Glenn Engel $
51
 *  ModuleState:     Experimental $
52
 *
53
 *  NOTES:           See Below $
54
 *
55
 *  Modified for SPARC by Stu Grossman, Red Hat.
56
 *  Modified for generic CygMON stub support by Bob Manson, Red Hat.
57
 *
58
 *  To enable debugger support, two things need to happen.  One, a
59
 *  call to set_debug_traps () is necessary in order to allow any breakpoints
60
 *  or error conditions to be properly intercepted and reported to gdb.
61
 *  Two, a breakpoint needs to be generated to begin communication.  This
62
 *  is most easily accomplished by a call to breakpoint ().  Breakpoint ()
63
 *  simulates a breakpoint by executing a trap #1.
64
 *
65
 *************
66
 *
67
 *    The following gdb commands are supported:
68
 *
69
 * command          function                               Return value
70
 *
71
 *    g             return the value of the CPU registers  hex data or ENN
72
 *    G             set the value of the CPU registers     OK or ENN
73
 *
74
 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
75
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
76
 *
77
 *    c             Resume at current address              SNN   ( signal NN)
78
 *    cAA..AA       Continue at address AA..AA             SNN
79
 *
80
 *    s             Step one instruction                   SNN
81
 *    sAA..AA       Step one instruction from AA..AA       SNN
82
 *
83
 *    k             kill
84
 *
85
 *    ?             What was the last sigval ?             SNN   (signal NN)
86
 *
87
 *    bBB..BB       Set baud rate to BB..BB                OK or BNN, then sets
88
 *                                                         baud rate
89
 *
90
 * All commands and responses are sent with a packet which includes a
91
 * checksum.  A packet consists of
92
 *
93
 * $<packet info>#<checksum>.
94
 *
95
 * where
96
 * <packet info> :: <characters representing the command or response>
97
 * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
98
 *
99
 * When a packet is received, it is first acknowledged with either '+' or '-'.
100
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
101
 *
102
 * Example:
103
 *
104
 * Host:                  Reply:
105
 * $m0,10#2a               +$00010203040506070809101112131415#42
106
 *
107
 ****************************************************************************/
108
 
109
#ifdef __ECOS__
110
 
111
// We cannot share memcpy and memset with the rest of the system since
112
// the user may want to step through it.
113
static inline void*
114
_memcpy(void* dest, void* src, int size)
115
{
116
    unsigned char* __d = (unsigned char*) dest;
117
    unsigned char* __s = (unsigned char*) src;
118
 
119
    while(size--)
120
        *__d++ = *__s++;
121
 
122
    return dest;
123
}
124
 
125
static inline void*
126
_memset(void* s, int c, int size)
127
{
128
    unsigned char* __s = (unsigned char*) s;
129
    unsigned char __c = (unsigned char) c;
130
 
131
    while(size--)
132
        *__s++ = __c;
133
 
134
    return s;
135
}
136
 
137
#else
138
#include <string.h>
139
#include <signal.h>
140
#define _memcpy memcpy
141
#define _memset memset
142
#endif // __ECOS__
143
 
144
/************************************************************************/
145
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
146
/* at least NUMREGBYTES*2 are needed for register packets */
147
#ifdef __ECOS__
148
#ifdef NUMREGBYTES
149
#define BUFMAX (32 + (NUMREGBYTES*2))
150
#else
151
#define BUFMAX 2048
152
#endif
153
#else
154
#define BUFMAX 2048
155
#endif
156
 
157
static int initialized = 0;     /* !0 means we've been initialized */
158
 
159
static int process_exception (int sigval);
160
static void do_nothing (void); /* and do it gracefully */
161
static int syscall_do_nothing (int);
162
 
163
#ifdef CYGSEM_ECOS_SUPPORTS_PROGRAM_ARGS
164
void __free_program_args (void);
165
static char *__add_program_arg (int argnum, uint32 arglen);
166
#endif
167
 
168
volatile __PFI __process_exception_vec = process_exception;
169
volatile __PFV __process_exit_vec = do_nothing;
170
volatile __PFI __process_syscall_vec = syscall_do_nothing;
171
volatile __PFI __process_signal_vec = NULL;
172
volatile __PFV __init_vec = NULL;
173
volatile __PFV __cleanup_vec = NULL;
174
 
175
static const char hexchars[] = "0123456789abcdef";
176
 
177
static void process_query (char *pkt);
178
static void process_set   (char *pkt);
179
 
180
char
181
__tohex (int c)
182
{
183
  return hexchars [c & 15];
184
}
185
 
186
#define __tohex(c) hexchars[(c) & 15]
187
 
188
#ifndef NUMREGS_GDB
189
#define NUMREGS_GDB NUMREGS
190
#endif
191
 
192
/* One pushback character. */
193
int ungot_char = -1;
194
 
195
static int
196
readDebugChar (void)
197
{
198
  if (ungot_char > 0)
199
    {
200
      int result = ungot_char;
201
      ungot_char = -1;
202
      return result;
203
    }
204
  else
205
    return getDebugChar ();
206
}
207
 
208
/* Convert ch from a hex digit to an int. */
209
 
210
int
211
stubhex (ch)
212
     unsigned 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
void
224
__getpacket (buffer)
225
     char *buffer;
226
{
227
    struct gdb_packet packet;
228
    int res;
229
 
230
    packet.state = 0;
231
    packet.contents = buffer;
232
    packet.err = 0;
233
    while ((res = __add_char_to_packet (readDebugChar () & 0xff, &packet)) != 1) {
234
        if (res == -2) {
235
            putDebugChar ('-'); // Tell host packet was not processed
236
            // Reset for the next packet
237
            packet.state = 0;
238
            packet.err = 0;
239
        }
240
    }
241
}
242
 
243
int
244
__add_char_to_packet (ch, packet)
245
     unsigned int ch;
246
     struct gdb_packet *packet;
247
{
248
  if (packet->state == 0)
249
    {
250
      if (ch == '$')
251
        {
252
          packet->state = 1;
253
          packet->length = 0;
254
          packet->checksum = 0;
255
          packet->xmitcsum = -1;
256
        }
257
      return 0;
258
    }
259
 
260
  if (packet->state == 1)
261
    {
262
      if (packet->length == BUFMAX)
263
        {
264
          packet->state = 0;
265
          packet->err = 1;
266
        }
267
      else if (ch == '#')
268
        {
269
          packet->contents[packet->length] = 0;
270
          packet->state = 2;
271
        }
272
      else
273
        {
274
          packet->checksum += ch;
275
          packet->contents[packet->length++] = ch;
276
        }
277
      return 0;
278
    }
279
 
280
  if (packet->state == 2)
281
    {
282
      packet->xmitcsum = stubhex (ch) << 4;
283
      packet->state = 3;
284
      return 0;
285
    }
286
 
287
  if (packet->state == 3)
288
    {
289
      packet->xmitcsum |= stubhex (ch);
290
      if (packet->err) {
291
          // Packet was too long - just tell the consumer
292
          return -2;
293
      }
294
      if ((packet->checksum & 255) != packet->xmitcsum)
295
        {
296
          putDebugChar ('-');   /* failed checksum */
297
          packet->state = 0;
298
          return -1;
299
        }
300
      else
301
        {
302
          putDebugChar ('+'); /* successful transfer */
303
          /* if a sequence char is present, reply the sequence ID */
304
          if (packet->contents[2] == ':')
305
            {
306
              uint32 count = packet->length;
307
              uint32 i;
308
              putDebugChar (packet->contents[0]);
309
              putDebugChar (packet->contents[1]);
310
              /* remove sequence chars from buffer */
311
              for (i=3; i <= count; i++)
312
                packet->contents[i-3] = packet->contents[i];
313
            }
314
          return 1;
315
        }
316
    }
317
  /* We should never get here. */
318
  packet->state = 0;
319
  return -1;
320
}
321
 
322
/* send the packet in buffer.  */
323
 
324
void
325
__putpacket (buffer)
326
     char *buffer;
327
{
328
  unsigned char checksum;
329
  uint32 count;
330
  unsigned char ch;
331
 
332
  /*  $<packet info>#<checksum>. */
333
  do
334
    {
335
      putDebugChar ('$');
336
      checksum = 0;
337
      count = 0;
338
 
339
      while ((ch = buffer[count]))
340
        {
341
          putDebugChar (ch);
342
          checksum += ch;
343
          count += 1;
344
        }
345
 
346
      putDebugChar ('#');
347
      putDebugChar (hexchars[(checksum >> 4) & 0xf]);
348
      putDebugChar (hexchars[checksum & 0xf]);
349
 
350
    }
351
  while ((readDebugChar () & 0x7f) != '+');
352
}
353
 
354
char __remcomInBuffer[BUFMAX];
355
char __remcomOutBuffer[BUFMAX];
356
 
357
/* Indicate to caller of mem2hex or hex2mem that there has been an
358
   error.  */
359
volatile int __mem_fault = 0;
360
 
361
 
362
#ifndef TARGET_HAS_OWN_MEM_FUNCS
363
/*
364
 * _target_readmem_hook / _target_writemem_hook:
365
 * Allow target to get involved in reading/writing memory.
366
 *
367
 * If these hooks are defined by the target, they will be
368
 * called for each user program memory access.  Otherwise, the stub
369
 * will simply dereference a pointer to access user program memory.
370
 */
371
 
372
unsigned char (*_target_readmem_hook)  (unsigned char* addr);
373
void          (*_target_writemem_hook) (unsigned char* addr,
374
                                        unsigned char value);
375
 
376
static unsigned char
377
get_target_byte (volatile unsigned char *address)
378
{
379
  if (_target_readmem_hook)     /* target needs to control memory access */
380
    return _target_readmem_hook ((unsigned char *) address);
381
  else
382
    return *address;
383
}
384
 
385
static void
386
put_target_byte (volatile unsigned char *address, unsigned char value)
387
{
388
  if (_target_writemem_hook)    /* target needs to control memory access */
389
    _target_writemem_hook ((unsigned char *) address, value);
390
  else
391
    *address = value;
392
}
393
 
394
/* These are the "arguments" to __do_read_mem and __do_write_mem,
395
   which are passed as globals to avoid squeezing them thru
396
   __set_mem_fault_trap.  */
397
 
398
static volatile target_register_t memCount;
399
static volatile unsigned char    *memSrc,  *memDst;
400
 
401
/*
402
 * __do_read_mem:
403
 * Copy from target memory to trusted memory.
404
 */
405
 
406
static void
407
__do_read_mem (void)
408
{
409
  __mem_fault = 0;
410
  while (memCount)
411
    {
412
      unsigned char ch = get_target_byte (memSrc++);
413
 
414
      if (__mem_fault)
415
        return;
416
      *memDst++ = ch;
417
      memCount--;
418
    }
419
}
420
 
421
/*
422
 * __do_write_mem:
423
 * Copy from trusted memory to target memory.
424
 */
425
 
426
static void
427
__do_write_mem (void)
428
{
429
  __mem_fault = 0;
430
  while (memCount)
431
    {
432
      unsigned char ch = *memSrc++;
433
 
434
      put_target_byte (memDst++, ch);
435
      if (__mem_fault)
436
        return;
437
      memCount--;
438
    }
439
}
440
 
441
/*
442
 * __read_mem_safe:
443
 * Get contents of target memory, abort on error.
444
 */
445
 
446
int
447
__read_mem_safe (void *dst, target_register_t src, int count)
448
{
449
  memCount = count;
450
  memSrc   = (unsigned char *) src;
451
  memDst   = (unsigned char *) dst;
452
  __set_mem_fault_trap (__do_read_mem);
453
  return count - memCount;      /* return number of bytes successfully read */
454
}
455
 
456
/*
457
 * __write_mem_safe:
458
 * Set contents of target memory, abort on error.
459
 */
460
 
461
int
462
__write_mem_safe (unsigned char *src, target_register_t dst, int count)
463
{
464
  memCount = count;
465
  memSrc   = (unsigned char *) src;
466
  memDst   = (unsigned char *) dst;
467
  __set_mem_fault_trap (__do_write_mem);
468
  return count - memCount;      /* return number of bytes successfully read */
469
}
470
 
471
#endif /* TARGET_HAS_OWN_MEM_FUNCS */
472
 
473
/* These are the "arguments" to __mem2hex_helper and __hex2mem_helper,
474
   which are passed as globals to avoid squeezing them thru
475
   __set_mem_fault_trap.  */
476
 
477
static int   hexMemCount;
478
static char *hexMemSrc, *hexMemDst;
479
static int   may_fault_mode;
480
#ifdef TARGET_HAS_HARVARD_MEMORY
481
static int   progMem;
482
#endif
483
 
484
/* Hamburger helper? */
485
static void
486
__mem2hex_helper (void)
487
{
488
    union {
489
        unsigned long  long_val;
490
        unsigned char  bytes[sizeof(long)];
491
    } val;
492
    int len, i;
493
    unsigned char ch;
494
    __mem_fault = 0;
495
    while (hexMemCount > 0) {
496
        if (may_fault_mode) {
497
            if ((hexMemCount >= sizeof(long)) &&
498
                (((target_register_t)hexMemSrc & (sizeof(long)-1)) == 0)) {
499
                // Should be safe to access via a long
500
                len = sizeof(long);
501
            } else if ((hexMemCount >= sizeof(short)) &&
502
                       (((target_register_t)hexMemSrc & (sizeof(short)-1)) == 0)) {
503
                // Should be safe to access via a short
504
                len = sizeof(short);
505
            } else {
506
                len = 1;
507
            }
508
#ifdef TARGET_HAS_HARVARD_MEMORY
509
            if (progMem)
510
                __read_progmem_safe(&val.bytes[0], hexMemSrc, len);
511
            else
512
#endif
513
            __read_mem_safe(&val.bytes[0], hexMemSrc, len);
514
        } else {
515
            len = 1;
516
            val.bytes[0] = *hexMemSrc;
517
        }
518
        if (__mem_fault)
519
            return;
520
 
521
        for (i = 0;  i < len;  i++) {
522
            ch = val.bytes[i];
523
            *(hexMemDst++) = hexchars[(ch >> 4) & 0xf];
524
            if (__mem_fault)
525
                return;
526
            *(hexMemDst++) = hexchars[ch & 0xf];
527
            if (__mem_fault)
528
                return;
529
        }
530
        hexMemCount -= len;
531
        hexMemSrc += len;
532
    }
533
}
534
 
535
/* Convert the memory pointed to by MEM into HEX, placing result in BUF.
536
 * Return a pointer to the last char put in buf (NUL). In case of a memory
537
 * fault, return 0.
538
 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
539
 * a 0 (and assume that MEM is a pointer into the user program), else we
540
 * treat a fault like any other fault in the stub (and assume that MEM is
541
 * a pointer into the stub's memory).
542
 */
543
 
544
char *
545
__mem2hex (mem, buf, count, may_fault)
546
     char *mem;
547
     char *buf;
548
     int count;
549
     int may_fault;
550
{
551
  hexMemDst      = (char *) buf;
552
  hexMemSrc      = (char *) mem;
553
  hexMemCount    = count;
554
  may_fault_mode = may_fault;
555
#ifdef TARGET_HAS_HARVARD_MEMORY
556
  progMem = 0;
557
#endif
558
 
559
  if (may_fault)
560
    {
561
      if (__set_mem_fault_trap (__mem2hex_helper))
562
        return 0;
563
    }
564
  else
565
    __mem2hex_helper ();
566
 
567
  *hexMemDst = 0;
568
 
569
  return (char *) hexMemDst;
570
}
571
 
572
/* Convert the target memory identified by MEM into HEX, placing result in BUF.
573
 * Return a pointer to the last char put in buf (NUL). In case of a memory
574
 * fault, return 0.
575
 */
576
 
577
static char *
578
__mem2hex_safe (target_addr_t mem, char *buf, int count)
579
{
580
  hexMemDst      = (char *) buf;
581
  hexMemSrc      = (char *) TARGET_ADDR_TO_PTR(mem);
582
  hexMemCount    = count;
583
  may_fault_mode = 1;
584
#ifdef TARGET_HAS_HARVARD_MEMORY
585
  progMem = TARGET_ADDR_IS_PROGMEM(mem);
586
#endif
587
 
588
  if (__set_mem_fault_trap (__mem2hex_helper))
589
    return 0;
590
 
591
  *hexMemDst = 0;
592
 
593
  return (char *) hexMemDst;
594
}
595
 
596
 
597
 
598
static void
599
__hex2mem_helper (void)
600
{
601
    union {
602
        unsigned long  long_val;
603
        unsigned char  bytes[sizeof(long)];
604
    } val;
605
    int len, i;
606
    unsigned char ch = '\0';
607
 
608
    __mem_fault = 0;
609
    while (hexMemCount > 0 && *hexMemSrc) {
610
        if (may_fault_mode) {
611
            if ((hexMemCount >= sizeof(long)) &&
612
                (((target_register_t)hexMemDst & (sizeof(long)-1)) == 0)) {
613
                len = sizeof(long);
614
            } else if ((hexMemCount >= sizeof(short)) &&
615
                       (((target_register_t)hexMemDst & (sizeof(short)-1)) == 0)) {
616
                len = sizeof(short);
617
            } else {
618
                len = 1;
619
            }
620
        } else {
621
            len = 1;
622
        }
623
 
624
        for (i = 0;  i < len;  i++) {
625
            // Check for short data?
626
            ch = stubhex (*(hexMemSrc++)) << 4;
627
            if (__mem_fault)
628
                return;
629
            ch |= stubhex (*(hexMemSrc++));
630
            if (__mem_fault)
631
                return;
632
            val.bytes[i] = ch;
633
        }
634
 
635
        if (may_fault_mode) {
636
#ifdef TARGET_HAS_HARVARD_MEMORY
637
            if (progMem)
638
                __write_progmem_safe (&val.bytes[0], hexMemDst, len);
639
            else
640
#endif
641
            __write_mem_safe (&val.bytes[0], hexMemDst, len);
642
        } else
643
            *hexMemDst = ch;
644
 
645
        if (__mem_fault)
646
            return;
647
        hexMemCount -= len;
648
        hexMemDst += len;
649
    }
650
}
651
 
652
/* Convert COUNT bytes of the hex array pointed to by BUF into binary
653
   to be placed in MEM.  Return a pointer to the character AFTER the
654
   last byte written.
655
 
656
   If MAY_FAULT is set, we will return a non-zero value if a memory
657
   fault occurs (and we assume that MEM is a pointer into the user
658
   program). Otherwise, we will take a trap just like any other memory
659
   fault (and assume that MEM points into the stub's memory). */
660
 
661
char *
662
__hex2mem (buf, mem, count, may_fault)
663
     char *buf;
664
     char *mem;
665
     int count;
666
     int may_fault;
667
{
668
  hexMemSrc      = (char *) buf;
669
  hexMemDst      = (char *) mem;
670
  hexMemCount    = count;
671
  may_fault_mode = may_fault;
672
#ifdef TARGET_HAS_HARVARD_MEMORY
673
  progMem = 0;
674
#endif
675
 
676
  if (may_fault)
677
    {
678
      if (__set_mem_fault_trap (__hex2mem_helper))
679
        return 0;
680
    }
681
  else
682
    __hex2mem_helper ();
683
 
684
  return (char *) hexMemDst;
685
}
686
 
687
/* Convert COUNT bytes of the hex array pointed to by BUF into binary
688
   to be placed in target MEM.  Return a pointer to the character AFTER
689
   the last byte written.
690
*/
691
char *
692
__hex2mem_safe (char *buf, target_addr_t mem, int count)
693
{
694
  hexMemSrc      = (char *) buf;
695
  hexMemDst      = (char *) TARGET_ADDR_TO_PTR(mem);
696
  hexMemCount    = count;
697
  may_fault_mode = 1;
698
#ifdef TARGET_HAS_HARVARD_MEMORY
699
  progMem = TARGET_ADDR_IS_PROGMEM(mem);
700
#endif
701
 
702
  if (__set_mem_fault_trap (__hex2mem_helper))
703
    return 0;
704
 
705
  return (char *) hexMemDst;
706
}
707
 
708
 
709
void
710
set_debug_traps (void)
711
{
712
  __install_traps ();
713
  initialized = 1;    /* FIXME: Change this to dbg_stub_initialized */
714
}
715
 
716
/*
717
 * While we find nice hex chars, build an int.
718
 * Return number of chars processed.
719
 */
720
 
721
unsigned int
722
__hexToInt (char **ptr, target_register_t *intValue)
723
{
724
  int numChars = 0;
725
  int hexValue;
726
 
727
  *intValue = 0;
728
 
729
  while (**ptr)
730
    {
731
      hexValue = stubhex (**ptr);
732
      if (hexValue < 0)
733
        break;
734
 
735
      *intValue = (*intValue << 4) | hexValue;
736
      numChars ++;
737
 
738
      (*ptr)++;
739
    }
740
 
741
  return (numChars);
742
}
743
 
744
/*
745
 * While we find nice hex chars, build a target memory address.
746
 * Return number of chars processed.
747
 */
748
 
749
unsigned int
750
__hexToAddr (char **ptr, target_addr_t *val)
751
{
752
  int numChars = 0;
753
  int hexValue;
754
 
755
  *val = 0;
756
 
757
  while (**ptr)
758
    {
759
      hexValue = stubhex (**ptr);
760
      if (hexValue < 0)
761
        break;
762
 
763
      *val = (*val << 4) | hexValue;
764
      numChars ++;
765
 
766
      (*ptr)++;
767
    }
768
 
769
  return (numChars);
770
}
771
 
772
 
773
/*
774
 * Complement of __hexToInt: take an int of size "numBits",
775
 * convert it to a hex string.  Return length of (unterminated) output.
776
 */
777
 
778
unsigned int
779
__intToHex (char *ptr, target_register_t intValue, int numBits)
780
{
781
  int numChars = 0;
782
 
783
  if (intValue == 0)
784
    {
785
      *(ptr++) = '0';
786
      *(ptr++) = '0';
787
      return 2;
788
    }
789
 
790
  numBits = (numBits + 7) / 8;
791
  while (numBits)
792
    {
793
      int v = (intValue >> ((numBits - 1) * 8));
794
      if (v || (numBits == 1))
795
        {
796
          v = v & 255;
797
          *(ptr++) = __tohex ((v / 16) & 15);
798
          *(ptr++) = __tohex (v & 15);
799
          numChars += 2;
800
        }
801
      numBits--;
802
    }
803
 
804
  return (numChars);
805
}
806
 
807
#if DEBUG_THREADS 
808
/*
809
 * Kernel Thread Control
810
 *
811
 * If the current thread is set to other than zero (or minus one),
812
 * then ask the kernel to lock it's scheduler so that only that thread
813
 * can run.
814
 */
815
 
816
static unsigned char did_lock_scheduler = 0;
817
static unsigned char did_disable_interrupts = 0;
818
 
819
/* Pointer to "kernel call" for scheduler control */
820
static int (*schedlock_fn) (int, int, long) = stub_lock_scheduler;
821
 
822
/* Pointer to target stub call for disabling interrupts.
823
   Target stub will initialize this if it can.  */
824
int (*__disable_interrupts_hook) (int); /* don't initialize here! */
825
#endif
826
 
827
static void
828
lock_thread_scheduler (int kind)        /* "step" or "continue" */
829
{
830
#if DEBUG_THREADS 
831
  int ret = 0;
832
 
833
  /* GDB will signal its desire to run a single thread
834
     by setting _gdb_cont_thread to non-zero / non-negative.  */
835
  if (_gdb_cont_thread <= 0)
836
    return;
837
 
838
  if (schedlock_fn)                     /* kernel call */
839
    ret = (*schedlock_fn) (1, kind, _gdb_cont_thread);
840
 
841
  if (ret == 1)
842
    {
843
      did_lock_scheduler = 1;
844
      return;
845
    }
846
 
847
  if (schedlock_fn == 0 ||              /* no kernel scheduler call */
848
      ret == -1)                        /* kernel asks stub to handle it */
849
    if (__disable_interrupts_hook)      /* target stub has capability */
850
      if ((*__disable_interrupts_hook) (1))
851
        {
852
          did_disable_interrupts = 1;
853
          return;
854
        }
855
#endif /* DEBUG_THREADS */
856
}
857
 
858
static void
859
unlock_thread_scheduler ()
860
{
861
#if DEBUG_THREADS
862
  if (did_lock_scheduler)
863
    if (schedlock_fn)                   /* kernel call */
864
      {
865
        (*schedlock_fn) (0, 0, _gdb_cont_thread);
866
        /* I could check the return value, but
867
           what would I do if it failed???  */
868
        did_lock_scheduler = 0;
869
      }
870
  if (did_disable_interrupts)
871
    if (__disable_interrupts_hook)      /* target stub call */
872
      {
873
        (*__disable_interrupts_hook) (0);
874
        /* Again, I could check the return value, but
875
           what would I do if it failed???  */
876
        did_disable_interrupts = 0;
877
      }
878
#endif /* DEBUG_THREADS */
879
}
880
 
881
#ifdef CYGPKG_CYGMON
882
int processing_breakpoint_function = 0;
883
#endif
884
 
885
void
886
__handle_exception (void)
887
{
888
  int sigval = 0;
889
 
890
#ifdef TARGET_HAS_NEXT_STEP
891
  if (! __next_step_done ())
892
    {
893
      __clear_breakpoints ();
894
      __install_breakpoints ();
895
      __single_step ();
896
      return;
897
    }
898
#endif
899
 
900
#ifdef __ECOS__
901
  // We need to unpack the registers before they are accessed.
902
  if (__cleanup_vec != NULL)
903
    __cleanup_vec ();
904
 
905
#if defined(CYGSEM_REDBOOT_BSP_SYSCALLS)
906
  // Temporary support for gnupro bsp SWIs
907
  if (__is_bsp_syscall())
908
  {
909
      sigval = hal_syscall_handler();
910
      if (sigval <= 0)
911
      {
912
          if (sigval < 0)
913
              __process_exit_vec ();
914
 
915
          if (__init_vec != NULL)
916
              __init_vec ();
917
          return;
918
      }
919
  }
920
#endif
921
 
922
#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
923
  // Special case for GDB BREAKs. This flag is set by cyg_stub_cleanup.
924
  if (cyg_hal_gdb_break) {
925
      cyg_hal_gdb_break = 0;
926
      sigval = SIGINT;
927
  }
928
#endif
929
 
930
  // Only compute sigval if it wasn't already computed (in
931
  // hal_syscall_handler or as a result of a GDB async break)
932
  if (0 == sigval)
933
      sigval = __computeSignal (__get_trap_number ());
934
 
935
#else  // __ECOS__
936
  /* reply to host that an exception has occurred */
937
  sigval = __computeSignal (__get_trap_number ());
938
#endif // __ECOS__
939
 
940
  if (__is_breakpoint_function ())
941
  {
942
#ifdef CYGPKG_CYGMON
943
    processing_breakpoint_function = 1;
944
#endif
945
    __skipinst ();
946
  } else {
947
#ifdef CYGPKG_CYGMON
948
    processing_breakpoint_function = 0;
949
#endif
950
  }
951
 
952
#ifndef __ECOS__
953
  if (__cleanup_vec != NULL)
954
    __cleanup_vec ();
955
#endif // !__ECOS__
956
 
957
  __clear_breakpoints ();
958
 
959
  /* Undo effect of previous single step.  */
960
  unlock_thread_scheduler ();
961
  __clear_single_step ();
962
 
963
#ifdef __ECOS__
964
      /* Need to flush the data and instruction cache here, as we may have
965
         removed a breakpoint in __single_step - and we may be sharing
966
         some code with the application! */
967
 
968
        __data_cache (CACHE_FLUSH) ;
969
        __instruction_cache (CACHE_FLUSH) ;
970
#endif
971
 
972
#ifdef SIGSYSCALL
973
  if (sigval == SIGSYSCALL)
974
    {
975
      int val;
976
      /* Do the skipinst FIRST. */
977
#ifndef SYSCALL_PC_AFTER_INST
978
      __skipinst ();
979
#endif
980
      val =  __process_syscall_vec (__get_syscall_num ());
981
      if (val < 0)
982
        sigval = -val;
983
      else
984
        sigval = 0;
985
    }
986
 
987
#endif
988
 
989
  /* Indirect function call to stub, cygmon monitor or other */
990
  if (sigval != 0)
991
    {
992
      while (__process_exception_vec (sigval))
993
        {
994
          /* Empty! */
995
        }
996
    }
997
 
998
  __install_breakpoints ();
999
 
1000
  if (__init_vec != NULL)
1001
    __init_vec ();
1002
}
1003
 
1004
/*
1005
 * _get_trace_register_hook:
1006
 * This function pointer will be non-zero if the trace component
1007
 * wants to intercept requests for register values.
1008
 *
1009
 * FIXME: evidently I need a new hook for large registers...
1010
 */
1011
 
1012
int   (*_get_trace_register_hook) (regnames_t, target_register_t *);
1013
 
1014
void
1015
stub_format_registers(char *packet, char *ptr)
1016
{
1017
    int regnum;
1018
    int sr = 0, er = NUMREGS_GDB;
1019
 
1020
    if (packet[0] == 'p')
1021
      {
1022
         target_register_t regno;
1023
         char *p = &packet[1];
1024
         if (__hexToInt (&p, &regno))
1025
           {
1026
             sr = regno;
1027
             er = regno + 1;
1028
           }
1029
         else
1030
           {
1031
             strcpy (ptr, "INVALID");
1032
             return;
1033
           }
1034
      }
1035
 
1036
    for (regnum = sr; regnum < er; regnum++)
1037
      {
1038
        /* We need to compensate for the value offset within the
1039
           register. */
1040
        char dummyDat[32];
1041
        target_register_t addr;
1042
        char *vptr;
1043
        int  reg_valid = 1;
1044
 
1045
#ifdef TARGET_HAS_LARGE_REGISTERS
1046
        if (sizeof (target_register_t) < REGSIZE (regnum)) {
1047
            get_register_as_bytes (regnum, dummyDat);
1048
            vptr = dummyDat;
1049
        } else
1050
#endif
1051
        {
1052
            if (_get_trace_register_hook)
1053
                reg_valid = _get_trace_register_hook (regnum, &addr);
1054
            else
1055
            {
1056
                addr = get_register (regnum);
1057
#ifdef CYGHWR_REGISTER_VALIDITY_CHECKING
1058
                reg_valid = get_register_valid (regnum);
1059
#endif
1060
            }
1061
            vptr = ((char *) &addr);
1062
            if (sizeof (addr) > REGSIZE(regnum)) {
1063
                /* May need to cope with endian-ness */
1064
 
1065
#if !defined(__LITTLE_ENDIAN__) && !defined(_LITTLE_ENDIAN)
1066
                vptr += sizeof (addr) - REGSIZE (regnum);
1067
#endif
1068
            } else if (sizeof (addr) < REGSIZE (regnum)) {
1069
                int off = REGSIZE (regnum) - sizeof (addr);
1070
                int x;
1071
                char extend_val = 0;
1072
 
1073
#ifdef CYGARC_SIGN_EXTEND_REGISTERS
1074
                {
1075
                    unsigned long bits_in_addr = (sizeof(addr) << 3);  // ie Size in bytes * 8
1076
                    target_register_t sign_bit_mask = (1 << (bits_in_addr - 1));
1077
                    if ((addr & sign_bit_mask) == sign_bit_mask)
1078
                        extend_val = ~0;
1079
                }
1080
#endif
1081
 
1082
#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN)
1083
                for (x = 0; x < off; x++)
1084
                    dummyDat[x + sizeof(addr)] = extend_val;
1085
                _memcpy (dummyDat, &addr, sizeof (addr));
1086
#else
1087
                for (x = 0; x < off; x++)
1088
                    dummyDat[x] = extend_val;
1089
                _memcpy (dummyDat + off, &addr, sizeof (addr));
1090
#endif
1091
                vptr = dummyDat;
1092
            }
1093
        }
1094
        if (reg_valid) {      /* we have a valid reg value */
1095
            ptr = __mem2hex (vptr, ptr, REGSIZE (regnum), 0);
1096
        } else {
1097
            /* Trace component returned a failure code.
1098
               This means that the register value is not available.
1099
               We'll fill it with 'x's, and GDB will understand.  */
1100
            _memset (ptr, 'x', 2 * REGSIZE (regnum));
1101
            ptr += 2 * REGSIZE (regnum);
1102
        }
1103
    }
1104
}
1105
 
1106
void
1107
stub_update_registers(char *in_ptr, char *out_ptr)
1108
{
1109
    char *ptr = &in_ptr[1];
1110
    int x;
1111
    int sr = 0, er = NUMREGS_GDB;
1112
 
1113
    if (*in_ptr == 'P') {
1114
        target_register_t regno;
1115
 
1116
        if (__hexToInt (&ptr, &regno) && (*ptr++ == '=')) {
1117
 
1118
            sr = regno;
1119
            er = regno + 1;
1120
        } else {
1121
            strcpy (out_ptr, "P01");
1122
            return;
1123
        }
1124
    }
1125
 
1126
    for (x = sr; x < er; x++) {
1127
        target_register_t value = 0;
1128
        char *vptr;
1129
 
1130
#ifdef TARGET_HAS_LARGE_REGISTERS
1131
        if (sizeof (target_register_t) < REGSIZE (x)) {
1132
            char dummyDat [32];
1133
 
1134
            __hex2mem (ptr, dummyDat, REGSIZE (x), 0);
1135
            put_register_as_bytes (x, dummyDat);
1136
        } else
1137
#endif
1138
        {
1139
            vptr = ((char *) &value);
1140
#if !defined(__LITTLE_ENDIAN__) && !defined(_LITTLE_ENDIAN)
1141
            vptr += sizeof (value) - REGSIZE (x);
1142
#endif
1143
            __hex2mem (ptr, vptr, REGSIZE (x), 0);
1144
            put_register (x, value);
1145
        }
1146
        ptr += REGSIZE (x) * 2;
1147
    }
1148
 
1149
    strcpy (out_ptr, "OK");
1150
}
1151
 
1152
int
1153
__process_packet (char *packet)
1154
{
1155
  int  is_binary = 0;
1156
#if defined(CYGNUM_HAL_BREAKPOINT_LIST_SIZE)
1157
  int is_Z = 0;
1158
#endif
1159
 
1160
  __remcomOutBuffer[0] = 0;
1161
  switch (packet[0])
1162
    {
1163
    case '?':
1164
      {
1165
        int sigval = __computeSignal (__get_trap_number ());
1166
        __remcomOutBuffer[0] = 'S';
1167
        __remcomOutBuffer[1] = hexchars[(sigval >> 4) & 0xf];
1168
        __remcomOutBuffer[2] = hexchars[sigval & 0xf];
1169
        __remcomOutBuffer[3] = 0;
1170
        break;
1171
      }
1172
 
1173
#ifdef __ECOS__
1174
#if !defined(CYG_HAL_STARTUP_RAM)    // Only for ROM based stubs
1175
#if 0 // Disable to avoid conflict with stub-breakpoint z/Z-packets
1176
    case 'z':
1177
        /* report IO buffer sizes so download can achieve optimal
1178
           download speed */
1179
    {
1180
        int i;
1181
        i = __intToHex (__remcomOutBuffer, BUFMAX, 32);
1182
        __remcomOutBuffer[i] = 0;
1183
        break;
1184
    }
1185
#endif
1186
    case 'd':
1187
      /* toggle debug flag */
1188
      strcpy(__remcomOutBuffer, GDB_stubs_version);
1189
      break;
1190
#endif
1191
#endif // __ECOS__
1192
 
1193
    case 'q':
1194
      /* general query packet */
1195
      process_query (&packet[1]);
1196
      break;
1197
 
1198
    case 'Q':
1199
      /* general set packet */
1200
      process_set (&packet[1]);
1201
      break;
1202
 
1203
    case 'p':           /* return the value of  a single CPU register */
1204
    case 'g':           /* return the value of the CPU registers */
1205
      {
1206
        stub_format_registers(&packet[0], __remcomOutBuffer);
1207
        break;
1208
      }
1209
 
1210
    case 'A': /* set program arguments */
1211
      {
1212
#ifdef CYGSEM_ECOS_SUPPORTS_PROGRAM_ARGS
1213
        if (packet[1] == '\0')
1214
          {
1215
            __free_program_args ();
1216
            strcpy (__remcomOutBuffer, "OK");
1217
          }
1218
        else
1219
          {
1220
            target_register_t arglen, argnum;
1221
            char *ptr = &packet[1];
1222
 
1223
            while (1)
1224
              {
1225
                if (__hexToInt (&ptr, &arglen)
1226
                    && (*ptr++ == ',')
1227
                    && __hexToInt (&ptr, &argnum)
1228
                    && (*ptr++ == ','))
1229
                  {
1230
                    if (arglen > 0)
1231
                      {
1232
                        char *s = __add_program_arg (argnum, arglen);
1233
                        if (s != NULL)
1234
                          {
1235
                            __hex2mem (ptr, s, arglen, 0);
1236
                          }
1237
                        ptr += arglen * 2;
1238
                      }
1239
 
1240
                    if (*ptr == ',')
1241
                      ptr++;
1242
                    else
1243
                      break;
1244
                  }
1245
                else
1246
                  break;
1247
              }
1248
            if (*ptr == '\0')
1249
              strcpy (__remcomOutBuffer, "OK");
1250
            else
1251
              strcpy (__remcomOutBuffer, "E01");
1252
          }
1253
#else
1254
        strcpy (__remcomOutBuffer, "E01");
1255
#endif
1256
      }
1257
      break;
1258
 
1259
    case 'P':
1260
    case 'G':      /* set the value of the CPU registers - return OK */
1261
      {
1262
        char *in_ptr = &packet[0];
1263
        char *out_ptr = __remcomOutBuffer;
1264
        stub_update_registers(in_ptr, out_ptr);
1265
        break;
1266
      }
1267
 
1268
    case 'm':     /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
1269
      /* Try to read %x,%x.  */
1270
      {
1271
        target_register_t length;
1272
        char *ptr = &packet[1];
1273
        target_addr_t addr;
1274
 
1275
        if (__hexToAddr (&ptr, &addr)
1276
            && *ptr++ == ','
1277
            && __hexToInt (&ptr, &length))
1278
          {
1279
            if (__mem2hex_safe (addr, __remcomOutBuffer, length))
1280
              break;
1281
 
1282
            strcpy (__remcomOutBuffer, "E03");
1283
          }
1284
        else
1285
          strcpy (__remcomOutBuffer, "E01");
1286
        break;
1287
      }
1288
 
1289
    case 'X':
1290
      /* XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA */
1291
      is_binary = 1;
1292
      /* fall through */
1293
    case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
1294
      /* Try to read '%x,%x:'.  */
1295
      {
1296
        target_register_t length;
1297
        char *ptr = &packet[1], buf[128];
1298
        int  i;
1299
        target_addr_t addr;
1300
 
1301
        if (__hexToAddr (&ptr, &addr)
1302
            && *ptr++ == ','
1303
            && __hexToInt (&ptr, &length)
1304
            && *ptr++ == ':')
1305
          {
1306
            /* GDB sometimes sends an impossible length */
1307
            if (length < 0 || length >= BUFMAX)
1308
              strcpy (__remcomOutBuffer, "E01");
1309
 
1310
            else if (is_binary)
1311
              {
1312
                while (length > 0)
1313
                  {
1314
                    for (i = 0; i < sizeof(buf) && i < length; i++)
1315
                      if ((buf[i] = *ptr++) == 0x7d)
1316
                        buf[i] = 0x20 | (*ptr++ & 0xff);
1317
 
1318
#ifdef TARGET_HAS_HARVARD_MEMORY
1319
                    if (TARGET_ADDR_IS_PROGMEM(addr)) {
1320
                      if (__write_progmem_safe (buf, (void *)TARGET_ADDR_TO_PTR(addr), i) != i)
1321
                        break;
1322
                    } else
1323
#endif
1324
                      if (__write_mem_safe (buf, (void *)TARGET_ADDR_TO_PTR(addr), i) != i)
1325
                        break;
1326
 
1327
 
1328
                    length -= i;
1329
                    addr += i;
1330
                  }
1331
                if (length <= 0)
1332
                  strcpy (__remcomOutBuffer, "OK");
1333
                else
1334
                  strcpy (__remcomOutBuffer, "E03");
1335
              }
1336
            else
1337
              {
1338
                if (__hex2mem_safe (ptr, addr, length) != NULL)
1339
                  strcpy (__remcomOutBuffer, "OK");
1340
                else
1341
                  strcpy (__remcomOutBuffer, "E03");
1342
              }
1343
          }
1344
        else
1345
          strcpy (__remcomOutBuffer, "E02");
1346
        break;
1347
      }
1348
 
1349
    case 'S':
1350
    case 's':    /* sAA..AA    Step from address AA..AA (optional) */
1351
    case 'C':
1352
    case 'c':    /* cAA..AA    Continue at address AA..AA (optional) */
1353
      /* try to read optional parameter, pc unchanged if no parm */
1354
 
1355
      {
1356
        char *ptr = &packet[1];
1357
        target_addr_t addr;
1358
        target_register_t sigval = 0;
1359
 
1360
        if (packet[0] == 'C' || packet[0] == 'S')
1361
          {
1362
            __hexToInt (&ptr, &sigval);
1363
            if (*ptr == ';')
1364
              ptr++;
1365
          }
1366
 
1367
        if (__hexToAddr (&ptr, &addr))
1368
          set_pc ((target_register_t)TARGET_ADDR_TO_PTR(addr));
1369
 
1370
      /* Need to flush the instruction cache here, as we may have
1371
         deposited a breakpoint, and the icache probably has no way of
1372
         knowing that a data ref to some location may have changed
1373
         something that is in the instruction cache.  */
1374
 
1375
#ifdef __ECOS__
1376
        __data_cache (CACHE_FLUSH) ;
1377
#endif
1378
        __instruction_cache (CACHE_FLUSH) ;
1379
 
1380
        /* If we have a function to handle signals, call it. */
1381
        if (sigval != 0 && __process_signal_vec != NULL)
1382
          {
1383
            /* If 0 is returned, we either ignored the signal or invoked a user
1384
               handler. Otherwise, the user program should die. */
1385
            if (! __process_signal_vec (sigval))
1386
              sigval = 0;
1387
          }
1388
 
1389
        if (sigval != 0)
1390
          {
1391
            sigval = SIGKILL; /* Always nuke the program */
1392
            __kill_program (sigval);
1393
            return 0;
1394
          }
1395
 
1396
#ifdef __ECOS__
1397
        // CASE 102327 - watchpoints fight with output, so do not step
1398
        // through $O packet output routines.
1399
#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
1400
        if ( cyg_hal_gdb_break_is_set() ) {
1401
            packet[0] = 'c'; // Force it to be a "continue" instead of step.
1402
            cyg_hal_gdb_running_step = 1; // And tell the hal_stub...
1403
        }
1404
#endif
1405
#endif
1406
 
1407
        /* Set machine state to force a single step.  */
1408
        if (packet[0] == 's' || packet[0] == 'S')
1409
          {
1410
            lock_thread_scheduler (0);  /* 0 == single-step */
1411
#ifdef __ECOS__
1412
            // PR 19845 workaround:
1413
            // Make sure the single-step magic affects the correct registers.
1414
            _registers = &registers[0];
1415
#endif
1416
            __single_step ();
1417
          }
1418
        else
1419
          {
1420
            lock_thread_scheduler (1);  /* 1 == continue */
1421
          }
1422
 
1423
#ifdef __ECOS__
1424
      /* Need to flush the data and instruction cache here, as we may have
1425
         deposited a breakpoint in __single_step. */
1426
 
1427
        __data_cache (CACHE_FLUSH) ;
1428
        __instruction_cache (CACHE_FLUSH) ;
1429
        hal_flush_output();
1430
#endif
1431
 
1432
        return -1;
1433
      }
1434
 
1435
    case 'D' :     /* detach */
1436
      __putpacket (__remcomOutBuffer);
1437
      /* fall through */
1438
    case 'k' :      /* kill the program */
1439
#ifdef __ECOS__
1440
      hal_flush_output();
1441
#endif
1442
      __process_exit_vec ();
1443
      return -1;
1444
 
1445
    case 'r':           /* Reset */
1446
      /* With the next 'k' packet, reset the board */
1447
      __process_exit_vec = &__reset;
1448
      break;
1449
 
1450
    case 'H':
1451
      STUB_PKT_CHANGETHREAD (packet+1, __remcomOutBuffer, 300) ;
1452
      break ;
1453
    case 'T' :
1454
      STUB_PKT_THREAD_ALIVE (packet+1, __remcomOutBuffer, 300) ;
1455
      break ;
1456
    case 'B':
1457
      /* breakpoint */
1458
      {
1459
        target_register_t addr;
1460
        char mode;
1461
        char *ptr = &packet[1];
1462
        if (__hexToInt (&ptr, &addr) && *(ptr++) == ',')
1463
          {
1464
            mode = *(ptr++);
1465
            if (mode == 'C')
1466
              __remove_breakpoint (addr,0);
1467
            else
1468
              __set_breakpoint (addr,0);
1469
            strcpy (__remcomOutBuffer, "OK");
1470
          }
1471
        else
1472
          {
1473
            strcpy (__remcomOutBuffer, "E01");
1474
          }
1475
        break;
1476
      }
1477
 
1478
      case 'b':   /* bBB...  Set baud rate to BB... */
1479
      {
1480
        target_register_t baudrate;
1481
 
1482
        char *ptr = &packet[1];
1483
        if (!__hexToInt (&ptr, &baudrate))
1484
          {
1485
            strcpy (__remcomOutBuffer, "B01");
1486
            break;
1487
          }
1488
 
1489
        __putpacket ("OK");     /* Ack before changing speed */
1490
        __set_baud_rate (baudrate);
1491
        break;
1492
      }
1493
 
1494
#if defined(CYGNUM_HAL_BREAKPOINT_LIST_SIZE) && (CYGNUM_HAL_BREAKPOINT_LIST_SIZE > 0)
1495
    case 'Z':
1496
      is_Z = 1;
1497
    case 'z':
1498
      {
1499
        char *ptr = &packet[1];
1500
        target_register_t ztype, addr, length;
1501
        int err;
1502
        target_addr_t taddr;
1503
 
1504
        if (__hexToInt (&ptr, &ztype) && *(ptr++) == ',')
1505
          {
1506
            if (__hexToAddr (&ptr, &taddr))
1507
              {
1508
                if (*(ptr++) == ',')
1509
                  {
1510
                      /* When there is a comma, there must be a length */
1511
                      if  (!__hexToInt (&ptr, &length))
1512
                        {
1513
                          strcpy (__remcomOutBuffer, "E02");
1514
                          break;
1515
                        }
1516
                  }
1517
                else
1518
                  length = 0;
1519
 
1520
                addr = (target_register_t)TARGET_ADDR_TO_PTR(taddr);
1521
 
1522
                switch (ztype)
1523
                  {
1524
                    case ZTYPE_SW_BREAKPOINT:
1525
                      /* sw breakpoint */
1526
                      if (is_Z)
1527
                        err = __set_breakpoint(addr,length);
1528
                      else
1529
                        err = __remove_breakpoint(addr,length);
1530
                      if (!err)
1531
                        strcpy (__remcomOutBuffer, "OK");
1532
                      else
1533
                        strcpy (__remcomOutBuffer, "E02");
1534
                      break;
1535
                    case ZTYPE_HW_BREAKPOINT:
1536
#if defined(HAL_STUB_HW_BREAKPOINT_LIST_SIZE) && (HAL_STUB_HW_BREAKPOINT_LIST_SIZE > 0)
1537
                      if (is_Z)
1538
                        err = __set_hw_breakpoint(addr, length);
1539
                      else
1540
                        err = __remove_hw_breakpoint(addr, length);
1541
                      if (!err)
1542
                        strcpy (__remcomOutBuffer, "OK");
1543
                      else
1544
#endif
1545
                        strcpy (__remcomOutBuffer, "E02");
1546
                      break;
1547
                    case ZTYPE_HW_WATCHPOINT_WRITE:
1548
                    case ZTYPE_HW_WATCHPOINT_READ:
1549
                    case ZTYPE_HW_WATCHPOINT_ACCESS:
1550
#if defined(HAL_STUB_HW_WATCHPOINT_LIST_SIZE) && (HAL_STUB_HW_WATCHPOINT_LIST_SIZE > 0)
1551
                      if (is_Z)
1552
                        err = __set_hw_watchpoint(addr, length, ztype);
1553
                      else
1554
                        err = __remove_hw_watchpoint(addr, length, ztype);
1555
                      if (!err)
1556
                        strcpy (__remcomOutBuffer, "OK");
1557
                      else
1558
#endif
1559
                        strcpy (__remcomOutBuffer, "E02");
1560
                      break;
1561
                  }
1562
              }
1563
          }
1564
        break;
1565
      }
1566
#endif // Z packet support
1567
#ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol
1568
    case 'F':
1569
    {
1570
        extern void cyg_hal_gdbfileio_process_F_packet( char *, char *);
1571
        cyg_hal_gdbfileio_process_F_packet( packet, __remcomOutBuffer );
1572
        return -1;
1573
    }
1574
#endif
1575
    default:
1576
      __process_target_packet (packet, __remcomOutBuffer, 300);
1577
      break;
1578
    }
1579
 
1580
  /* reply to the request */
1581
  __putpacket (__remcomOutBuffer);
1582
  return 0;
1583
}
1584
 
1585
static void
1586
send_t_packet (int sigval)
1587
{
1588
  __build_t_packet (sigval, __remcomOutBuffer);
1589
  __putpacket (__remcomOutBuffer);
1590
}
1591
 
1592
/*
1593
 * This function does all command procesing for interfacing to gdb.
1594
 */
1595
 
1596
static int
1597
process_exception (int sigval)
1598
{
1599
  int status;
1600
 
1601
  /* Nasty. */
1602
  if (ungot_char < 0)
1603
    send_t_packet (sigval);
1604
 
1605
  do {
1606
    __getpacket (__remcomInBuffer);
1607
    status = __process_packet (__remcomInBuffer);
1608
  } while (status == 0);
1609
 
1610
  if (status < 0)
1611
    return 0;
1612
  else
1613
    return 1;
1614
}
1615
 
1616
void
1617
__send_exit_status (int status)
1618
{
1619
  __remcomOutBuffer[0] = 'W';
1620
  __remcomOutBuffer[1] = hexchars[(status >> 4) & 0xf];
1621
  __remcomOutBuffer[2] = hexchars[status & 0xf];
1622
  __remcomOutBuffer[3] = 0;
1623
  __putpacket (__remcomOutBuffer);
1624
}
1625
 
1626
/* Read up to MAXLEN bytes from the remote GDB client, and store in DEST
1627
   (which is a pointer in the user program). BLOCK indicates what mode
1628
   is being used; if it is set, we will wait for MAXLEN bytes to be
1629
   entered. Otherwise, the function will return immediately with whatever
1630
   bytes are waiting to be read.
1631
 
1632
   The value returned is the number of bytes read. A -1 indicates that an
1633
   error of some sort occurred. */
1634
 
1635
int
1636
__get_gdb_input (target_register_t dest, int maxlen, int block)
1637
{
1638
  char buf[4];
1639
  int len, i;
1640
  char d;
1641
 
1642
  buf[0] = 'I';
1643
  buf[1] = '0';
1644
  buf[2] = block ? '0' : '1';
1645
  buf[3] = 0;
1646
  __putpacket (buf);
1647
  __getpacket (__remcomInBuffer);
1648
  if (__remcomInBuffer[0] != 'I')
1649
    return -1;
1650
  len = stubhex (__remcomInBuffer[1]) * 16 + stubhex (__remcomInBuffer[2]);
1651
  for (i = 0; i < len; i++)
1652
    {
1653
      d = stubhex (__remcomInBuffer[3 + i * 2]) * 16;
1654
      d |=  stubhex (__remcomInBuffer[3 + i * 2 + 1]);
1655
      __write_mem_safe (&d, (void *)(dest + i), 1);
1656
    }
1657
  /* Write the trailing \0. */
1658
  d = '\0';
1659
  __write_mem_safe (&d, (void *)(dest + i), 1);
1660
  return len;
1661
}
1662
 
1663
void
1664
__output_hex_value (target_register_t i)
1665
{
1666
  char buf[32], *ptr=buf+31;
1667
  unsigned int x;
1668
 
1669
  *ptr = 0;
1670
  for (x = 0; x < (sizeof (i) * 2); x++)
1671
    {
1672
      *(--ptr) = hexchars[i & 15];
1673
      i = i >> 4;
1674
    }
1675
  while (*ptr)
1676
    {
1677
      putDebugChar (*(ptr++));
1678
    }
1679
}
1680
 
1681
/* Write the C-style string pointed to by STR to the GDB comm port. */
1682
void
1683
__putDebugStr (char *str)
1684
{
1685
  while (*str)
1686
    {
1687
      putDebugChar (*str);
1688
      str++;
1689
    }
1690
}
1691
 
1692
/* Send STRING_LEN bytes of STR to GDB, using 'O' packets.
1693
   STR is assumed to be in the program being debugged. */
1694
 
1695
int
1696
__output_gdb_string (target_register_t str, int string_len)
1697
{
1698
  /* We will arbitrarily limit output packets to less than 400 bytes. */
1699
  static char buf[400];
1700
  int x;
1701
  int len;
1702
 
1703
  if (string_len == 0)
1704
    {
1705
      /* We can't do strlen on a user pointer. */
1706
      return -1;
1707
    }
1708
 
1709
  len = string_len;
1710
  while (len > 0)
1711
    {
1712
      int packetlen = ((len < 175) ? len : 175);
1713
      buf[0] = 'O';
1714
      for (x = 0; x < packetlen; x++)
1715
        {
1716
          char c;
1717
 
1718
          __read_mem_safe (&c, (void *)(str + x), 1);
1719
          buf[x*2+1] = hexchars[(c >> 4) & 0xf];
1720
          buf[x*2+2] = hexchars[c % 16];
1721
        }
1722
      str += x;
1723
      len -= x;
1724
      buf[x*2+1] = 0;
1725
      __putpacket (buf);
1726
    }
1727
  return string_len;
1728
}
1729
 
1730
static void
1731
do_nothing (void)
1732
{
1733
  /* mmmm */
1734
}
1735
 
1736
static int
1737
syscall_do_nothing (int junk)
1738
{
1739
  return 0;
1740
}
1741
 
1742
/* Start the stub running. */
1743
void
1744
__switch_to_stub (void)
1745
{
1746
  __process_exception_vec = process_exception;
1747
#ifdef CYGPKG_CYGMON
1748
  // Cygmon will have consumed the '$' character for this packet.
1749
  // Let's put one in the unget buffer.
1750
  // Actually, Cygmon does an unget, but since it uses different
1751
  // unget handling, we need to do this here.
1752
  ungetDebugChar('$');
1753
#endif
1754
}
1755
 
1756
#if ! defined(BOARD_SPECIFIC_STUB_INIT)
1757
void
1758
initialize_stub (void)
1759
{
1760
  set_debug_traps ();
1761
  /* FIXME: This function should be renamed to specifically init the
1762
     hardware required by debug operations. If initHardware is implemented at
1763
     all, it should be called before main ().
1764
     */
1765
  initHardware () ;
1766
  /* This acks any stale packets , NOT an effective solution */
1767
  putDebugChar ('+');
1768
}
1769
#endif
1770
 
1771
void
1772
ungetDebugChar (int c)
1773
{
1774
  ungot_char = c;
1775
}
1776
 
1777
void
1778
__kill_program (int sigval)
1779
{
1780
  __remcomOutBuffer[0] = 'X';
1781
  __remcomOutBuffer[1] = hexchars[(sigval >> 4) & 15];
1782
  __remcomOutBuffer[2] = hexchars[sigval & 15];
1783
  __remcomOutBuffer[3] = 0;
1784
  __putpacket (__remcomOutBuffer);
1785
}
1786
 
1787
#ifdef CYGSEM_ECOS_SUPPORTS_PROGRAM_ARGS
1788
#define MAX_ARG_COUNT 20
1789
#define MAX_ARGDATA 128
1790
 
1791
static char *program_argv [MAX_ARG_COUNT];
1792
static int program_argc;
1793
static int last_program_arg;
1794
static char program_argstr [MAX_ARGDATA], *argptr;
1795
static int args_initted = 0;
1796
 
1797
void
1798
__free_program_args (void)
1799
{
1800
  last_program_arg = -1;
1801
  program_argc = 0;
1802
  program_argv [0] = NULL;
1803
  argptr = program_argstr;
1804
  args_initted = 1;
1805
}
1806
 
1807
static char *
1808
__add_program_arg (int argc, uint32 len)
1809
{
1810
  char *res;
1811
 
1812
  if (! args_initted)
1813
    {
1814
      __free_program_args ();
1815
    }
1816
 
1817
  if ((argc >= (MAX_ARG_COUNT - 1))
1818
      || ((argptr - program_argstr + len) > MAX_ARGDATA))
1819
    {
1820
      return NULL;
1821
    }
1822
 
1823
  if (argc != last_program_arg)
1824
    {
1825
      if (argc >= program_argc)
1826
        {
1827
          program_argc = argc + 1;
1828
          program_argv [program_argc] = NULL;
1829
        }
1830
      program_argv [argc] = argptr;
1831
      last_program_arg = argc;
1832
    }
1833
 
1834
  res = argptr;
1835
  argptr += len;
1836
 
1837
  return res;
1838
}
1839
 
1840
void
1841
__set_program_args (int argc, char **argv)
1842
{
1843
  int x;
1844
 
1845
  __free_program_args ();
1846
  if (argc)
1847
    {
1848
      for (x = 0; x < argc; x++)
1849
        {
1850
          uint32 len = strlen (argv[x])+1;
1851
          char *s = __add_program_arg (x, len);
1852
 
1853
          if (s == NULL)
1854
            return;
1855
 
1856
          _memcpy (s, argv[x], len);
1857
        }
1858
    }
1859
}
1860
 
1861
char **
1862
__get_program_args (target_register_t argcPtr)
1863
{
1864
  if (!args_initted)
1865
    {
1866
      __free_program_args ();
1867
    }
1868
  __write_mem_safe ((char *) &program_argc, (void *)argcPtr, sizeof (program_argc));
1869
  return program_argv;
1870
}
1871
#endif
1872
 
1873
/* Table used by the crc32 function to calcuate the checksum. */
1874
#ifdef CYGDBG_HAL_CRCTABLE_LOCATION_RAM
1875
static uint32 crc32_table[256];
1876
static int tableInit = 0;
1877
#else
1878
static const uint32 crc32_table[256]={
1879
        0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
1880
        0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
1881
        0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
1882
        0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
1883
        0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
1884
        0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
1885
        0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
1886
        0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
1887
        0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
1888
        0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
1889
        0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
1890
        0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
1891
        0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
1892
        0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
1893
        0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
1894
        0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
1895
        0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
1896
        0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
1897
        0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
1898
        0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
1899
        0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
1900
        0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
1901
        0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
1902
        0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
1903
        0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
1904
        0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
1905
        0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
1906
        0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
1907
        0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
1908
        0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
1909
        0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
1910
        0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4,
1911
};
1912
#endif
1913
 
1914
/*
1915
   Calculate a CRC-32 using LEN bytes of PTR. CRC is the initial CRC
1916
   value.
1917
   PTR is assumed to be a pointer in the user program. */
1918
 
1919
static uint32
1920
crc32 (target_addr_t mem, int len, uint32 crc)
1921
{
1922
  unsigned char *ptr = (unsigned char *)TARGET_ADDR_TO_PTR(mem);
1923
#ifdef TARGET_HAS_HARVARD_MEMORY
1924
  int  is_progmem = TARGET_ADDR_IS_PROGMEM(mem);
1925
#endif
1926
 
1927
#ifdef CYGDBG_HAL_CRCTABLE_LOCATION_RAM
1928
  if (! tableInit)
1929
    {
1930
      /* Initialize the CRC table and the decoding table. */
1931
      uint32 i, j;
1932
      uint32 c;
1933
 
1934
      tableInit = 1;
1935
      for (i = 0; i < 256; i++)
1936
        {
1937
          for (c = i << 24, j = 8; j > 0; --j)
1938
            c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
1939
          crc32_table[i] = c;
1940
        }
1941
    }
1942
#endif
1943
 
1944
  __mem_fault = 0;
1945
  while (len--)
1946
    {
1947
      unsigned char ch;
1948
 
1949
#ifdef TARGET_HAS_HARVARD_MEMORY
1950
      if (is_progmem)
1951
          __read_progmem_safe (&ch, (void *)ptr, 1);
1952
      else
1953
#endif
1954
      __read_mem_safe (&ch, (void *)ptr, 1);
1955
      if (__mem_fault)
1956
        {
1957
          break;
1958
        }
1959
      crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ ch) & 255];
1960
      ptr++;
1961
    }
1962
  return crc;
1963
}
1964
 
1965
/* Handle the 'q' request */
1966
 
1967
static void
1968
process_query (char *pkt)
1969
{
1970
  __remcomOutBuffer[0] = '\0';
1971
#ifdef __ECOS__
1972
  if ('C' == pkt[0] &&
1973
      'R' == pkt[1] &&
1974
      'C' == pkt[2] &&
1975
      ':' == pkt[3])
1976
#else  // __ECOS__
1977
  if (strncmp (pkt, "CRC:", 4) == 0)
1978
#endif // __ECOS__
1979
    {
1980
      target_addr_t startmem;
1981
      target_register_t length;
1982
      uint32 our_crc;
1983
 
1984
      pkt += 4;
1985
      if (__hexToAddr (&pkt, &startmem)
1986
          && *(pkt++) == ','
1987
          && __hexToInt (&pkt, &length))
1988
        {
1989
          our_crc = crc32 (startmem, length, 0xffffffff);
1990
          if (__mem_fault)
1991
            {
1992
              strcpy (__remcomOutBuffer, "E01");
1993
            }
1994
          else
1995
            {
1996
              int numb = __intToHex (__remcomOutBuffer + 1, our_crc, 32);
1997
              __remcomOutBuffer[0] = 'C';
1998
              __remcomOutBuffer[numb + 1] = 0;
1999
            }
2000
        }
2001
      return;
2002
    }
2003
#ifdef CYG_HAL_STUB_PROCESS_QUERY
2004
  else if (CYG_HAL_STUB_PROCESS_QUERY (pkt, __remcomOutBuffer, sizeof(__remcomOutBuffer)))
2005
    return;
2006
#endif
2007
  else
2008
    {
2009
      char ch ;
2010
      char * subpkt ;
2011
      ch = *pkt ;
2012
      subpkt = pkt + 1 ;
2013
      switch (ch)
2014
        {
2015
        case 'L' : /* threadlistquery */
2016
          STUB_PKT_GETTHREADLIST (subpkt, __remcomOutBuffer, 300);
2017
          break ;
2018
        case 'P' : /* Thread or process information request */
2019
          STUB_PKT_GETTHREADINFO (subpkt, __remcomOutBuffer, 300);
2020
          break ;
2021
        case 'C' : /* current thread query */
2022
          STUB_PKT_CURRTHREAD(subpkt, __remcomOutBuffer, sizeof(__remcomOutBuffer));
2023
          break;
2024
        default:
2025
          __process_target_query (pkt, __remcomOutBuffer, 300);
2026
          break ;
2027
        }
2028
    }
2029
}
2030
 
2031
/* Handle the 'Q' request */
2032
 
2033
static void
2034
process_set (char *pkt)
2035
{
2036
  char ch ;
2037
 
2038
#ifdef CYG_HAL_STUB_PROCESS_SET
2039
  if (CYG_HAL_STUB_PROCESS_SET (pkt, __remcomOutBuffer, sizeof(__remcomOutBuffer)))
2040
    return;
2041
#endif
2042
 
2043
  ch = *pkt ;
2044
  switch (ch)
2045
    {
2046
    case 'p' : /* Set current process or thread */
2047
      /* reserve the packet id even if support is not present */
2048
      /* Dont strip the 'p' off the header, there are several variations of
2049
         this packet */
2050
      STUB_PKT_CHANGETHREAD (pkt, __remcomOutBuffer, 300) ;
2051
      break ;
2052
    default:
2053
      __process_target_set (pkt, __remcomOutBuffer, 300);
2054
      break ;
2055
    }
2056
}
2057
#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS

powered by: WebSVN 2.1.0

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