⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 generic-stub.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 4 页
字号:
#include "board.h"

#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS

/* Eventually, this should default to ON */
#if USE_GDBSTUB_PROTOTYPES
#include "stub-tservice.h"
#include "generic-stub.h"
#else
// Function declarations (prevents compiler warnings)
int stubhex (unsigned char ch);
static void unlock_thread_scheduler (void);
static uint32 crc32 (target_addr_t mem, int len, uint32 crc);
#endif

#include "thread-pkts.h"
  /* Defines function macros if thread support is not selected in board.h */

#ifdef __ECOS__
char GDB_stubs_version[] CYGBLD_ATTRIB_WEAK = 
    "eCos GDB stubs - built " __DATE__ " / " __TIME__;
#endif

/****************************************************************************

                THIS SOFTWARE IS NOT COPYRIGHTED

   HP offers the following for use in the public domain.  HP makes no
   warranty with regard to the software or it's performance and the
   user accepts the software "AS IS" with all faults.

   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

****************************************************************************/

/****************************************************************************
 *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
 *
 *  Module name: remcom.c $
 *  Revision: 1.34 $
 *  Date: 91/03/09 12:29:49 $
 *  Contributor:     Lake Stevens Instrument Division$
 *
 *  Description:     low level support for gdb debugger. $
 *
 *  Considerations:  only works on target hardware $
 *
 *  Written by:      Glenn Engel $
 *  ModuleState:     Experimental $
 *
 *  NOTES:           See Below $
 *
 *  Modified for SPARC by Stu Grossman, Red Hat.
 *  Modified for generic CygMON stub support by Bob Manson, Red Hat.
 *
 *  To enable debugger support, two things need to happen.  One, a
 *  call to set_debug_traps () is necessary in order to allow any breakpoints
 *  or error conditions to be properly intercepted and reported to gdb.
 *  Two, a breakpoint needs to be generated to begin communication.  This
 *  is most easily accomplished by a call to breakpoint ().  Breakpoint ()
 *  simulates a breakpoint by executing a trap #1.
 *
 *************
 *
 *    The following gdb commands are supported:
 *
 * command          function                               Return value
 *
 *    g             return the value of the CPU registers  hex data or ENN
 *    G             set the value of the CPU registers     OK or ENN
 *
 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
 *
 *    c             Resume at current address              SNN   ( signal NN)
 *    cAA..AA       Continue at address AA..AA             SNN
 *
 *    s             Step one instruction                   SNN
 *    sAA..AA       Step one instruction from AA..AA       SNN
 *
 *    k             kill
 *
 *    ?             What was the last sigval ?             SNN   (signal NN)
 *
 *    bBB..BB       Set baud rate to BB..BB                OK or BNN, then sets
 *                                                         baud rate
 *
 * All commands and responses are sent with a packet which includes a
 * checksum.  A packet consists of
 *
 * $<packet info>#<checksum>.
 *
 * where
 * <packet info> :: <characters representing the command or response>
 * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
 *
 * When a packet is received, it is first acknowledged with either '+' or '-'.
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
 *
 * Example:
 *
 * Host:                  Reply:
 * $m0,10#2a               +$00010203040506070809101112131415#42
 *
 ****************************************************************************/

#ifdef __ECOS__

// We cannot share memcpy and memset with the rest of the system since
// the user may want to step through it.
static inline void*
_memcpy(void* dest, void* src, int size)
{
    unsigned char* __d = (unsigned char*) dest;
    unsigned char* __s = (unsigned char*) src;
    
    while(size--)
        *__d++ = *__s++;

    return dest;
}

static inline void*
_memset(void* s, int c, int size)
{
    unsigned char* __s = (unsigned char*) s;
    unsigned char __c = (unsigned char) c;
    
    while(size--)
        *__s++ = __c;

    return s;
}

#else
#include <string.h>
#include <signal.h>
#define _memcpy memcpy
#define _memset memset
#endif // __ECOS__

/************************************************************************/
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
/* at least NUMREGBYTES*2 are needed for register packets */
#ifdef __ECOS__
#ifdef NUMREGBYTES
#define BUFMAX (32 + (NUMREGBYTES*2))
#else
#define BUFMAX 2048
#endif
#else
#define BUFMAX 2048
#endif

static int initialized = 0;     /* !0 means we've been initialized */

static int process_exception (int sigval);
static void do_nothing (void); /* and do it gracefully */
static int syscall_do_nothing (int);

#ifdef CYGSEM_ECOS_SUPPORTS_PROGRAM_ARGS
void __free_program_args (void);
static char *__add_program_arg (int argnum, uint32 arglen);
#endif

volatile __PFI __process_exception_vec = process_exception;
volatile __PFV __process_exit_vec = do_nothing;
volatile __PFI __process_syscall_vec = syscall_do_nothing;
volatile __PFI __process_signal_vec = NULL;
volatile __PFV __init_vec = NULL;
volatile __PFV __cleanup_vec = NULL;

static const char hexchars[] = "0123456789abcdef";

static void process_query (char *pkt);
static void process_set   (char *pkt);

char
__tohex (int c)
{
  return hexchars [c & 15];
}

#define __tohex(c) hexchars[(c) & 15]

#ifndef NUMREGS_GDB
#define NUMREGS_GDB NUMREGS
#endif

/* One pushback character. */
int ungot_char = -1;

static int
readDebugChar (void)
{
  if (ungot_char > 0)
    {
      int result = ungot_char;
      ungot_char = -1;
      return result;
    }
  else
    return getDebugChar ();
}

/* Convert ch from a hex digit to an int. */

int
stubhex (ch)
     unsigned char ch;
{
  if (ch >= 'a' && ch <= 'f')
    return ch-'a'+10;
  if (ch >= '0' && ch <= '9')
    return ch-'0';
  if (ch >= 'A' && ch <= 'F')
    return ch-'A'+10;
  return -1;
}

void
__getpacket (buffer)
     char *buffer;
{
    struct gdb_packet packet;
    int res;

    packet.state = 0;
    packet.contents = buffer;
    packet.err = 0;
    while ((res = __add_char_to_packet (readDebugChar () & 0xff, &packet)) != 1) {
        if (res == -2) {
            putDebugChar ('-'); // Tell host packet was not processed
            // Reset for the next packet
            packet.state = 0;
            packet.err = 0;
        }
    }
}

int
__add_char_to_packet (ch, packet)
     unsigned int ch;
     struct gdb_packet *packet;
{
  if (packet->state == 0)
    {
      if (ch == '$')
        {
          packet->state = 1;
          packet->length = 0;
          packet->checksum = 0;
          packet->xmitcsum = -1;
        }
      return 0;
    }
  
  if (packet->state == 1)
    {
      if (packet->length == BUFMAX)
        {
          packet->state = 0;
          packet->err = 1;
        }
      else if (ch == '#')
        {
          packet->contents[packet->length] = 0;
          packet->state = 2;
        }
      else 
        {
          packet->checksum += ch;
          packet->contents[packet->length++] = ch;
        }
      return 0;
    }

  if (packet->state == 2)
    {
      packet->xmitcsum = stubhex (ch) << 4;
      packet->state = 3;
      return 0;
    }

  if (packet->state == 3)
    {
      packet->xmitcsum |= stubhex (ch);
      if (packet->err) {
          // Packet was too long - just tell the consumer
          return -2;
      }
      if ((packet->checksum & 255) != packet->xmitcsum)
        {
          putDebugChar ('-');   /* failed checksum */
          packet->state = 0;
          return -1;
        }
      else
        {
          putDebugChar ('+'); /* successful transfer */
          /* if a sequence char is present, reply the sequence ID */
          if (packet->contents[2] == ':')
            {
              uint32 count = packet->length;
              uint32 i;
              putDebugChar (packet->contents[0]);
              putDebugChar (packet->contents[1]);
              /* remove sequence chars from buffer */
              for (i=3; i <= count; i++)
                packet->contents[i-3] = packet->contents[i];
            }
          return 1;
        }
    }
  /* We should never get here. */
  packet->state = 0;
  return -1;
}

/* send the packet in buffer.  */

void
__putpacket (buffer)
     char *buffer;
{
  unsigned char checksum;
  uint32 count;
  unsigned char ch;

  /*  $<packet info>#<checksum>. */
  do
    {
      putDebugChar ('$');
      checksum = 0;
      count = 0;

      while ((ch = buffer[count]))
        {
          putDebugChar (ch);
          checksum += ch;
          count += 1;
        }

      putDebugChar ('#');
      putDebugChar (hexchars[(checksum >> 4) & 0xf]);
      putDebugChar (hexchars[checksum & 0xf]);

    }
  while ((readDebugChar () & 0x7f) != '+');
}

char __remcomInBuffer[BUFMAX];
char __remcomOutBuffer[BUFMAX];

/* Indicate to caller of mem2hex or hex2mem that there has been an
   error.  */
volatile int __mem_fault = 0;


#ifndef TARGET_HAS_OWN_MEM_FUNCS
/*
 * _target_readmem_hook / _target_writemem_hook:
 * Allow target to get involved in reading/writing memory.
 *
 * If these hooks are defined by the target, they will be
 * called for each user program memory access.  Otherwise, the stub
 * will simply dereference a pointer to access user program memory.
 */

unsigned char (*_target_readmem_hook)  (unsigned char* addr);
void          (*_target_writemem_hook) (unsigned char* addr, 
                                        unsigned char value);

static unsigned char
get_target_byte (volatile unsigned char *address)
{
  if (_target_readmem_hook)     /* target needs to control memory access */
    return _target_readmem_hook ((unsigned char *) address);
  else
    return *address;
}

static void
put_target_byte (volatile unsigned char *address, unsigned char value)
{
  if (_target_writemem_hook)    /* target needs to control memory access */
    _target_writemem_hook ((unsigned char *) address, value);
  else
    *address = value;
}

/* These are the "arguments" to __do_read_mem and __do_write_mem, 
   which are passed as globals to avoid squeezing them thru
   __set_mem_fault_trap.  */

static volatile target_register_t memCount;
static volatile unsigned char    *memSrc,  *memDst;

/*
 * __do_read_mem:
 * Copy from target memory to trusted memory.
 */

static void
__do_read_mem (void)
{
  __mem_fault = 0;
  while (memCount)
    {
      unsigned char ch = get_target_byte (memSrc++);

      if (__mem_fault)
        return;
      *memDst++ = ch;
      memCount--;
    }
}

/*
 * __do_write_mem:
 * Copy from trusted memory to target memory.
 */

static void
__do_write_mem (void)
{
  __mem_fault = 0;
  while (memCount)
    {
      unsigned char ch = *memSrc++;

      put_target_byte (memDst++, ch);
      if (__mem_fault)
        return;
      memCount--;
    }
}

/*
 * __read_mem_safe:
 * Get contents of target memory, abort on error.
 */

int
__read_mem_safe (void *dst, target_register_t src, int count)
{
  memCount = count;
  memSrc   = (unsigned char *) src;
  memDst   = (unsigned char *) dst;
  __set_mem_fault_trap (__do_read_mem);
  return count - memCount;      /* return number of bytes successfully read */
}

/*
 * __write_mem_safe:
 * Set contents of target memory, abort on error.
 */

int
__write_mem_safe (unsigned char *src, target_register_t dst, int count)
{
  memCount = count;
  memSrc   = (unsigned char *) src;
  memDst   = (unsigned char *) dst;
  __set_mem_fault_trap (__do_write_mem);
  return count - memCount;      /* return number of bytes successfully read */
}

#endif /* TARGET_HAS_OWN_MEM_FUNCS */

/* These are the "arguments" to __mem2hex_helper and __hex2mem_helper, 
   which are passed as globals to avoid squeezing them thru
   __set_mem_fault_trap.  */

static int   hexMemCount;
static char *hexMemSrc, *hexMemDst;
static int   may_fault_mode;
#ifdef TARGET_HAS_HARVARD_MEMORY
static int   progMem;
#endif

/* Hamburger helper? */
static void
__mem2hex_helper (void)
{
    union {
        unsigned long  long_val;
        unsigned char  bytes[sizeof(long)];
    } val;
    int len, i;
    unsigned char ch;
    __mem_fault = 0;
    while (hexMemCount > 0) {
        if (may_fault_mode) {
            if ((hexMemCount >= sizeof(long)) &&
                (((target_register_t)hexMemSrc & (sizeof(long)-1)) == 0)) {
                // Should be safe to access via a long
                len = sizeof(long);
            } else if ((hexMemCount >= sizeof(short)) &&
                       (((target_register_t)hexMemSrc & (sizeof(short)-1)) == 0)) {
                // Should be safe to access via a short
                len = sizeof(short);
            } else {
                len = 1;
            }
#ifdef TARGET_HAS_HARVARD_MEMORY
	    if (progMem)
		__read_progmem_safe(&val.bytes[0], hexMemSrc, len);
	    else
#endif
            __read_mem_safe(&val.bytes[0], hexMemSrc, len);
        } else {
            len = 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -