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

📄 generic-stub.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 4 页
字号:
            val.bytes[0] = *hexMemSrc;
        }
        if (__mem_fault)
            return;

        for (i = 0;  i < len;  i++) {
            ch = val.bytes[i];
            *(hexMemDst++) = hexchars[(ch >> 4) & 0xf];
            if (__mem_fault)
                return;
            *(hexMemDst++) = hexchars[ch & 0xf];
            if (__mem_fault)
                return;
        }
        hexMemCount -= len;
        hexMemSrc += len;
    }
}

/* Convert the memory pointed to by MEM into HEX, placing result in BUF.
 * Return a pointer to the last char put in buf (NUL). In case of a memory
 * fault, return 0.
 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
 * a 0 (and assume that MEM is a pointer into the user program), else we 
 * treat a fault like any other fault in the stub (and assume that MEM is
 * a pointer into the stub's memory).
 */

char *
__mem2hex (mem, buf, count, may_fault)
     char *mem;
     char *buf;
     int count;
     int may_fault;
{
  hexMemDst      = (unsigned char *) buf;
  hexMemSrc      = (unsigned char *) mem;
  hexMemCount    = count;
  may_fault_mode = may_fault;
#ifdef TARGET_HAS_HARVARD_MEMORY
  progMem = 0;
#endif
  
  if (may_fault)
    {
      if (__set_mem_fault_trap (__mem2hex_helper))
        return 0;
    }
  else
    __mem2hex_helper ();

  *hexMemDst = 0;

  return (char *) hexMemDst;
}

/* Convert the target memory identified by MEM into HEX, placing result in BUF.
 * Return a pointer to the last char put in buf (NUL). In case of a memory
 * fault, return 0.
 */

static char *
__mem2hex_safe (target_addr_t mem, char *buf, int count)
{
  hexMemDst      = (unsigned char *) buf;
  hexMemSrc      = (unsigned char *) TARGET_ADDR_TO_PTR(mem);
  hexMemCount    = count;
  may_fault_mode = 1;
#ifdef TARGET_HAS_HARVARD_MEMORY
  progMem = TARGET_ADDR_IS_PROGMEM(mem);
#endif
  
  if (__set_mem_fault_trap (__mem2hex_helper))
    return 0;

  *hexMemDst = 0;

  return (char *) hexMemDst;
}



static void
__hex2mem_helper (void)
{
    union {
        unsigned long  long_val;
        unsigned char  bytes[sizeof(long)];
    } val;
    int len, i;
    unsigned char ch = '\0';

    __mem_fault = 0;
    while (hexMemCount > 0 && *hexMemSrc) {
        if (may_fault_mode) {
            if ((hexMemCount >= sizeof(long)) &&
                (((target_register_t)hexMemDst & (sizeof(long)-1)) == 0)) {
                len = sizeof(long);
            } else if ((hexMemCount >= sizeof(short)) &&
                       (((target_register_t)hexMemDst & (sizeof(short)-1)) == 0)) {
                len = sizeof(short);
            } else {
                len = 1;
            }
        } else {
            len = 1;
        }

        for (i = 0;  i < len;  i++) {
            // Check for short data?
            ch = stubhex (*(hexMemSrc++)) << 4;
            if (__mem_fault)
                return;
            ch |= stubhex (*(hexMemSrc++));
            if (__mem_fault)
                return;
            val.bytes[i] = ch;
        }

        if (may_fault_mode) {
#ifdef TARGET_HAS_HARVARD_MEMORY
	    if (progMem)
		__write_progmem_safe (&val.bytes[0], hexMemDst, len);
	    else
#endif
            __write_mem_safe (&val.bytes[0], hexMemDst, len);
        } else
            *hexMemDst = ch;

        if (__mem_fault)
            return;
        hexMemCount -= len;
        hexMemDst += len;
    }
}

/* Convert COUNT bytes of the hex array pointed to by BUF into binary
   to be placed in MEM.  Return a pointer to the character AFTER the
   last byte written.

   If MAY_FAULT is set, we will return a non-zero value if a memory
   fault occurs (and we assume that MEM is a pointer into the user
   program). Otherwise, we will take a trap just like any other memory
   fault (and assume that MEM points into the stub's memory). */

char *
__hex2mem (buf, mem, count, may_fault)
     char *buf;
     char *mem;
     int count;
     int may_fault;
{
  hexMemSrc      = (unsigned char *) buf;
  hexMemDst      = (unsigned char *) mem;
  hexMemCount    = count;
  may_fault_mode = may_fault;
#ifdef TARGET_HAS_HARVARD_MEMORY
  progMem = 0;
#endif

  if (may_fault)
    {
      if (__set_mem_fault_trap (__hex2mem_helper))
        return 0;
    }
  else
    __hex2mem_helper ();

  return (char *) hexMemDst;
}

/* Convert COUNT bytes of the hex array pointed to by BUF into binary
   to be placed in target MEM.  Return a pointer to the character AFTER
   the last byte written.
*/
char *
__hex2mem_safe (char *buf, target_addr_t mem, int count)
{
  hexMemSrc      = (unsigned char *) buf;
  hexMemDst      = (unsigned char *) TARGET_ADDR_TO_PTR(mem);
  hexMemCount    = count;
  may_fault_mode = 1;
#ifdef TARGET_HAS_HARVARD_MEMORY
  progMem = TARGET_ADDR_IS_PROGMEM(mem);
#endif

  if (__set_mem_fault_trap (__hex2mem_helper))
    return 0;

  return (char *) hexMemDst;
}


void
set_debug_traps (void)
{
  __install_traps ();
  initialized = 1;    /* FIXME: Change this to dbg_stub_initialized */
}

/*
 * While we find nice hex chars, build an int.
 * Return number of chars processed.
 */

unsigned int
__hexToInt (char **ptr, target_register_t *intValue)
{
  int numChars = 0;
  int hexValue;

  *intValue = 0;

  while (**ptr)
    {
      hexValue = stubhex (**ptr);
      if (hexValue < 0)
        break;

      *intValue = (*intValue << 4) | hexValue;
      numChars ++;

      (*ptr)++;
    }

  return (numChars);
}

/*
 * While we find nice hex chars, build a target memory address.
 * Return number of chars processed.
 */

unsigned int
__hexToAddr (char **ptr, target_addr_t *val)
{
  int numChars = 0;
  int hexValue;

  *val = 0;

  while (**ptr)
    {
      hexValue = stubhex (**ptr);
      if (hexValue < 0)
        break;

      *val = (*val << 4) | hexValue;
      numChars ++;

      (*ptr)++;
    }

  return (numChars);
}


/* 
 * Complement of __hexToInt: take an int of size "numBits", 
 * convert it to a hex string.  Return length of (unterminated) output.
 */

unsigned int
__intToHex (char *ptr, target_register_t intValue, int numBits)
{
  int numChars = 0;

  if (intValue == 0)
    {
      *(ptr++) = '0';
      *(ptr++) = '0';
      return 2;
    }

  numBits = (numBits + 7) / 8;
  while (numBits)
    {
      int v = (intValue >> ((numBits - 1) * 8));
      if (v || (numBits == 1))
        {
          v = v & 255;
          *(ptr++) = __tohex ((v / 16) & 15);
          *(ptr++) = __tohex (v & 15);
          numChars += 2;
        }
      numBits--;
    }

  return (numChars);
}

#if DEBUG_THREADS 
/*
 * Kernel Thread Control
 *
 * If the current thread is set to other than zero (or minus one),
 * then ask the kernel to lock it's scheduler so that only that thread
 * can run.
 */

static unsigned char did_lock_scheduler = 0;
static unsigned char did_disable_interrupts = 0;

/* Pointer to "kernel call" for scheduler control */
static int (*schedlock_fn) (int, int, long) = stub_lock_scheduler;

/* Pointer to target stub call for disabling interrupts.
   Target stub will initialize this if it can.  */
int (*__disable_interrupts_hook) (int); /* don't initialize here! */
#endif

static void
lock_thread_scheduler (int kind)        /* "step" or "continue" */
{
#if DEBUG_THREADS 
  int ret = 0;

  /* GDB will signal its desire to run a single thread
     by setting _gdb_cont_thread to non-zero / non-negative.  */
  if (_gdb_cont_thread <= 0)
    return;

  if (schedlock_fn)                     /* kernel call */
    ret = (*schedlock_fn) (1, kind, _gdb_cont_thread);

  if (ret == 1)
    {
      did_lock_scheduler = 1;
      return;
    }

  if (schedlock_fn == 0 ||              /* no kernel scheduler call */
      ret == -1)                        /* kernel asks stub to handle it */
    if (__disable_interrupts_hook)      /* target stub has capability */
      if ((*__disable_interrupts_hook) (1))
        {
          did_disable_interrupts = 1;
          return;
        }
#endif /* DEBUG_THREADS */
}

static void
unlock_thread_scheduler ()
{
#if DEBUG_THREADS
  if (did_lock_scheduler)
    if (schedlock_fn)                   /* kernel call */
      {
        (*schedlock_fn) (0, 0, _gdb_cont_thread);
        /* I could check the return value, but 
           what would I do if it failed???  */
        did_lock_scheduler = 0;
      }
  if (did_disable_interrupts)
    if (__disable_interrupts_hook)      /* target stub call */
      {
        (*__disable_interrupts_hook) (0);
        /* Again, I could check the return value, but 
           what would I do if it failed???  */
        did_disable_interrupts = 0;
      }
#endif /* DEBUG_THREADS */
}

#ifdef CYGPKG_CYGMON
int processing_breakpoint_function = 0;
#endif

void
__handle_exception (void)
{
  int sigval = 0;

#ifdef TARGET_HAS_NEXT_STEP
  if (! __next_step_done ())
    {
      __clear_breakpoints ();
      __install_breakpoints ();
      __single_step ();
      return;
    }
#endif

#ifdef __ECOS__
  // We need to unpack the registers before they are accessed.
  if (__cleanup_vec != NULL)
    __cleanup_vec ();

#if defined(CYGSEM_REDBOOT_BSP_SYSCALLS)
  // Temporary support for gnupro bsp SWIs
  if (__is_bsp_syscall())
  {
      sigval = hal_syscall_handler();
      if (sigval <= 0)
      {
	  if (sigval < 0)
	      __process_exit_vec ();

	  if (__init_vec != NULL)
              __init_vec ();
	  return;
      }
  }
#endif

#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
  // Special case for GDB BREAKs. This flag is set by cyg_stub_cleanup.
  if (cyg_hal_gdb_break) {
      cyg_hal_gdb_break = 0;
      sigval = SIGINT;
  }
#endif
   
  // Only compute sigval if it wasn't already computed (in
  // hal_syscall_handler or as a result of a GDB async break)
  if (0 == sigval)
      sigval = __computeSignal (__get_trap_number ());

#else  // __ECOS__
  /* reply to host that an exception has occurred */
  sigval = __computeSignal (__get_trap_number ());
#endif // __ECOS__

  if (__is_breakpoint_function ())
  {
#ifdef CYGPKG_CYGMON
    processing_breakpoint_function = 1;
#endif
    __skipinst ();
  } else {
#ifdef CYGPKG_CYGMON
    processing_breakpoint_function = 0;
#endif
  }

#ifndef __ECOS__
  if (__cleanup_vec != NULL)
    __cleanup_vec ();
#endif // !__ECOS__

  __clear_breakpoints (); 

  /* Undo effect of previous single step.  */
  unlock_thread_scheduler ();
  __clear_single_step ();

#ifdef __ECOS__
      /* Need to flush the data and instruction cache here, as we may have
         removed a breakpoint in __single_step - and we may be sharing
         some code with the application! */

        __data_cache (CACHE_FLUSH) ;
        __instruction_cache (CACHE_FLUSH) ;
#endif

#ifdef SIGSYSCALL
  if (sigval == SIGSYSCALL)
    {
      int val;
      /* Do the skipinst FIRST. */
#ifndef SYSCALL_PC_AFTER_INST
      __skipinst ();
#endif
      val =  __process_syscall_vec (__get_syscall_num ());
      if (val < 0)
        sigval = -val;
      else
        sigval = 0;
    }

#endif

  /* Indirect function call to stub, cygmon monitor or other */
  if (sigval != 0)
    {
      while (__process_exception_vec (sigval))
        {
          /* Empty! */
        }
    }

  __install_breakpoints ();

  if (__init_vec != NULL)
    __init_vec ();
}

/*
 * _get_trace_register_hook:
 * This function pointer will be non-zero if the trace component
 * wants to intercept requests for register values.
 * 
 * FIXME: evidently I need a new hook for large registers...
 */

int   (*_get_trace_register_hook) (regnames_t, target_register_t *);

void
stub_format_registers(char *packet, char *ptr)
{
    int regnum;
    int sr = 0, er = NUMREGS_GDB;

    if (packet[0] == 'p')
      {
	 target_register_t regno;
         char *p = &packet[1];
	 if (__hexToInt (&p, &regno))
	   {
	     sr = regno;
	     er = regno + 1;
	   }
	 else
	   {

⌨️ 快捷键说明

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