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

📄 generic-stub.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 4 页
字号:
	     strcpy (ptr, "INVALID");
	     return;
	   }
      }

    for (regnum = sr; regnum < er; regnum++)
      {
        /* We need to compensate for the value offset within the
           register. */
        char dummyDat[32];
        target_register_t addr;
        char *vptr;
        int  reg_valid = 1;

#ifdef TARGET_HAS_LARGE_REGISTERS
        if (sizeof (target_register_t) < REGSIZE (regnum)) {
            get_register_as_bytes (regnum, dummyDat);
            vptr = dummyDat;
        } else
#endif
        {
            if (_get_trace_register_hook)
                reg_valid = _get_trace_register_hook (regnum, &addr);
            else
            {
                addr = get_register (regnum);
#ifdef CYGHWR_REGISTER_VALIDITY_CHECKING
                reg_valid = get_register_valid (regnum);
#endif
            }
            vptr = ((char *) &addr);
            if (sizeof (addr) > REGSIZE(regnum)) {
                /* May need to cope with endian-ness */

#if !defined(__LITTLE_ENDIAN__) && !defined(_LITTLE_ENDIAN)
                vptr += sizeof (addr) - REGSIZE (regnum);
#endif
            } else if (sizeof (addr) < REGSIZE (regnum)) {
                int off = REGSIZE (regnum) - sizeof (addr);
                int x;
                char extend_val = 0;

#ifdef CYGARC_SIGN_EXTEND_REGISTERS
                {
                    unsigned long bits_in_addr = (sizeof(addr) << 3);  // ie Size in bytes * 8
                    target_register_t sign_bit_mask = (1 << (bits_in_addr - 1));
                    if ((addr & sign_bit_mask) == sign_bit_mask)
                        extend_val = ~0;
                }
#endif

#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN)
                for (x = 0; x < off; x++)
                    dummyDat[x + sizeof(addr)] = extend_val;
                _memcpy (dummyDat, &addr, sizeof (addr));
#else
                for (x = 0; x < off; x++)
                    dummyDat[x] = extend_val;
                _memcpy (dummyDat + off, &addr, sizeof (addr));
#endif
                vptr = dummyDat;
            }
        }
        if (reg_valid) {      /* we have a valid reg value */
            ptr = __mem2hex (vptr, ptr, REGSIZE (regnum), 0);
        } else {
            /* Trace component returned a failure code.
               This means that the register value is not available.
               We'll fill it with 'x's, and GDB will understand.  */
            _memset (ptr, 'x', 2 * REGSIZE (regnum));
            ptr += 2 * REGSIZE (regnum);
        }
    }
}

void
stub_update_registers(char *in_ptr, char *out_ptr)
{
    char *ptr = &in_ptr[1];
    int x;
    int sr = 0, er = NUMREGS_GDB;

    if (*in_ptr == 'P') {
        target_register_t regno;

        if (__hexToInt (&ptr, &regno) && (*ptr++ == '=')) {

            sr = regno;
            er = regno + 1;
        } else {
            strcpy (out_ptr, "P01");
            return;
        }
    }

    for (x = sr; x < er; x++) {
        target_register_t value = 0;
        char *vptr;

#ifdef TARGET_HAS_LARGE_REGISTERS
        if (sizeof (target_register_t) < REGSIZE (x)) {
            char dummyDat [32];

            __hex2mem (ptr, dummyDat, REGSIZE (x), 0);
            put_register_as_bytes (x, dummyDat);
        } else 
#endif
        {
            vptr = ((char *) &value);
#if !defined(__LITTLE_ENDIAN__) && !defined(_LITTLE_ENDIAN)
            vptr += sizeof (value) - REGSIZE (x);
#endif
            __hex2mem (ptr, vptr, REGSIZE (x), 0);
            put_register (x, value);
        }
        ptr += REGSIZE (x) * 2;
    }

    strcpy (out_ptr, "OK");
}

int
__process_packet (char *packet)
{
  int  is_binary = 0;
#if defined(CYGNUM_HAL_BREAKPOINT_LIST_SIZE)
  int is_Z = 0;
#endif

  __remcomOutBuffer[0] = 0;
  switch (packet[0])
    {
    case '?':
      {
        int sigval = __computeSignal (__get_trap_number ());
        __remcomOutBuffer[0] = 'S';
        __remcomOutBuffer[1] = hexchars[(sigval >> 4) & 0xf];
        __remcomOutBuffer[2] = hexchars[sigval & 0xf];
        __remcomOutBuffer[3] = 0;
        break;
      }

#ifdef __ECOS__
#if !defined(CYG_HAL_STARTUP_RAM)    // Only for ROM based stubs
#if 0 // Disable to avoid conflict with stub-breakpoint z/Z-packets
    case 'z':
        /* report IO buffer sizes so download can achieve optimal
           download speed */
    {
        int i;
        i = __intToHex (__remcomOutBuffer, BUFMAX, 32);
        __remcomOutBuffer[i] = 0;
        break;
    }
#endif
    case 'd':
      /* toggle debug flag */
      strcpy(__remcomOutBuffer, GDB_stubs_version);
      break;
#endif
#endif // __ECOS__

    case 'q':
      /* general query packet */
      process_query (&packet[1]);
      break;

    case 'Q':
      /* general set packet */
      process_set (&packet[1]);
      break;

    case 'p':		/* return the value of  a single CPU register */
    case 'g':           /* return the value of the CPU registers */
      {
        stub_format_registers(&packet[0], __remcomOutBuffer);
        break;
      }

    case 'A': /* set program arguments */
      {
#ifdef CYGSEM_ECOS_SUPPORTS_PROGRAM_ARGS
        if (packet[1] == '\0')
          {
            __free_program_args ();
            strcpy (__remcomOutBuffer, "OK");
          }
        else 
          {
            target_register_t arglen, argnum;
            char *ptr = &packet[1];

            while (1)
              {
                if (__hexToInt (&ptr, &arglen)
                    && (*ptr++ == ',')
                    && __hexToInt (&ptr, &argnum)
                    && (*ptr++ == ','))
                  {
                    if (arglen > 0)
                      {
                        char *s = __add_program_arg (argnum, arglen);
                        if (s != NULL)
                          {
                            __hex2mem (ptr, s, arglen, 0);
                          }
                        ptr += arglen * 2;
                      }

                    if (*ptr == ',')
                      ptr++;
                    else
                      break;
                  }
                else
                  break;
              }
            if (*ptr == '\0')
              strcpy (__remcomOutBuffer, "OK");
            else
              strcpy (__remcomOutBuffer, "E01");
          }
#else
        strcpy (__remcomOutBuffer, "E01");
#endif
      }
      break;

    case 'P':
    case 'G':      /* set the value of the CPU registers - return OK */
      {
        char *in_ptr = &packet[0];
        char *out_ptr = __remcomOutBuffer;
        stub_update_registers(in_ptr, out_ptr);
        break;
      }

    case 'm':     /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
      /* Try to read %x,%x.  */
      {
        target_register_t length;
        char *ptr = &packet[1];
        target_addr_t addr;

        if (__hexToAddr (&ptr, &addr)
            && *ptr++ == ','
            && __hexToInt (&ptr, &length))
          {
	    if (__mem2hex_safe (addr, __remcomOutBuffer, length))
              break;

            strcpy (__remcomOutBuffer, "E03");
          }
        else
          strcpy (__remcomOutBuffer, "E01");
        break;
      }

    case 'X':
      /* XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA */
      is_binary = 1;
      /* fall through */
    case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
      /* Try to read '%x,%x:'.  */
      {
        target_register_t length;
        char *ptr = &packet[1], buf[128];
        int  i;
        target_addr_t addr;

        if (__hexToAddr (&ptr, &addr)
	    && *ptr++ == ','
            && __hexToInt (&ptr, &length)
            && *ptr++ == ':')
          {
            /* GDB sometimes sends an impossible length */
            if (length < 0 || length >= BUFMAX)
              strcpy (__remcomOutBuffer, "E01");
                
            else if (is_binary)
              {
                while (length > 0)
                  {
                    for (i = 0; i < sizeof(buf) && i < length; i++)
                      if ((buf[i] = *ptr++) == 0x7d)
                        buf[i] = 0x20 | (*ptr++ & 0xff);

#ifdef TARGET_HAS_HARVARD_MEMORY
		    if (TARGET_ADDR_IS_PROGMEM(addr)) {
		      if (__write_progmem_safe (buf, (void *)TARGET_ADDR_TO_PTR(addr), i) != i)
                        break;
		    } else
#endif
		      if (__write_mem_safe (buf, (void *)TARGET_ADDR_TO_PTR(addr), i) != i)
			break;


                    length -= i;
                    addr += i;
                  }
                if (length <= 0)
                  strcpy (__remcomOutBuffer, "OK");
                else
                  strcpy (__remcomOutBuffer, "E03");
              }
            else
              {
                if (__hex2mem_safe (ptr, addr, length) != NULL)
                  strcpy (__remcomOutBuffer, "OK");
                else
                  strcpy (__remcomOutBuffer, "E03");
              }
          }
        else
          strcpy (__remcomOutBuffer, "E02");
        break;
      }

    case 'S':
    case 's':    /* sAA..AA    Step from address AA..AA (optional) */
    case 'C':
    case 'c':    /* cAA..AA    Continue at address AA..AA (optional) */
      /* try to read optional parameter, pc unchanged if no parm */

      {
        char *ptr = &packet[1];
        target_addr_t addr;
        target_register_t sigval = 0;

        if (packet[0] == 'C' || packet[0] == 'S')
          {
            __hexToInt (&ptr, &sigval);
            if (*ptr == ';')
              ptr++;
          }

        if (__hexToAddr (&ptr, &addr))
          set_pc ((target_register_t)TARGET_ADDR_TO_PTR(addr));

      /* Need to flush the instruction cache here, as we may have
         deposited a breakpoint, and the icache probably has no way of
         knowing that a data ref to some location may have changed
         something that is in the instruction cache.  */

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

        /* If we have a function to handle signals, call it. */
        if (sigval != 0 && __process_signal_vec != NULL)
          {
            /* If 0 is returned, we either ignored the signal or invoked a user
               handler. Otherwise, the user program should die. */
            if (! __process_signal_vec (sigval))
              sigval = 0;
          }

        if (sigval != 0)
          {
            sigval = SIGKILL; /* Always nuke the program */
            __kill_program (sigval);
            return 0;
          }

#ifdef __ECOS__
        // CASE 102327 - watchpoints fight with output, so do not step
        // through $O packet output routines.
#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
        if ( cyg_hal_gdb_break_is_set() ) {
            packet[0] = 'c'; // Force it to be a "continue" instead of step.
            cyg_hal_gdb_running_step = 1; // And tell the hal_stub...
        }
#endif
#endif

        /* Set machine state to force a single step.  */
        if (packet[0] == 's' || packet[0] == 'S')
          {
            lock_thread_scheduler (0);  /* 0 == single-step */
#ifdef __ECOS__
            // PR 19845 workaround:
            // Make sure the single-step magic affects the correct registers.
            _registers = &registers[0];
#endif
            __single_step ();
          }
        else
          {
            lock_thread_scheduler (1);  /* 1 == continue */
          }

#ifdef __ECOS__
      /* Need to flush the data and instruction cache here, as we may have
         deposited a breakpoint in __single_step. */

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

        return -1;
      }

    case 'D' :     /* detach */
      __putpacket (__remcomOutBuffer);
      /* fall through */
    case 'k' :      /* kill the program */
#ifdef __ECOS__
      hal_flush_output();
#endif
      __process_exit_vec ();
      return -1;

    case 'r':           /* Reset */
      /* With the next 'k' packet, reset the board */
      __process_exit_vec = &__reset;
      break;

    case 'H':
      STUB_PKT_CHANGETHREAD (packet+1, __remcomOutBuffer, 300) ;
      break ;
    case 'T' :
      STUB_PKT_THREAD_ALIVE (packet+1, __remcomOutBuffer, 300) ;
      break ;
    case 'B':
      /* breakpoint */
      {
        target_register_t addr;
        char mode;
        char *ptr = &packet[1];
        if (__hexToInt (&ptr, &addr) && *(ptr++) == ',')
          {
            mode = *(ptr++);
            if (mode == 'C')
              __remove_breakpoint (addr,0);
            else
              __set_breakpoint (addr,0);
            strcpy (__remcomOutBuffer, "OK");
          }
        else
          {
            strcpy (__remcomOutBuffer, "E01");
          }
        break;
      }

      case 'b':   /* bBB...  Set baud rate to BB... */
      {
        target_register_t baudrate;

        char *ptr = &packet[1];
        if (!__hexToInt (&ptr, &baudrate))
          {
            strcpy (__remcomOutBuffer, "B01");
            break;
          }

        __putpacket ("OK");     /* Ack before changing speed */
        __set_baud_rate (baudrate);
        break;
      }

#if defined(CYGNUM_HAL_BREAKPOINT_LIST_SIZE) && (CYGNUM_HAL_BREAKPOINT_LIST_SIZE > 0)
    case 'Z':
      is_Z = 1;
    case 'z':
      {
	char *ptr = &packet[1];
	target_register_t ztype, addr, length;
	int err;
	target_addr_t taddr;

	if (__hexToInt (&ptr, &ztype) && *(ptr++) == ',')
	  {
	    if (__hexToAddr (&ptr, &taddr))
	      {
		if (*(ptr++) == ',')
		  {
		      /* When there is a comma, there must be a length */
		      if  (!__hexToInt (&ptr, &length))
			{
			  strcpy (__remcomOutBuffer, "E02");
			  break;
			}
		  }
		else
		  length = 0;

		addr = (target_register_t)TARGET_ADDR_TO_PTR(taddr);

		switch (ztype)
		  {
		    case ZTYPE_SW_BREAKPOINT:
		      /* sw breakpoint */
		      if (is_Z)
			err = __set_breakpoint(addr,length);
		      else
			err = __remove_breakpoint(addr,length);
		      if (!err)
			strcpy (__remcomOutBuffer, "OK");
		      else
			strcpy (__remcomOutBuffer, "E02");
		      break;
		    case ZTYPE_HW_BREAKPOINT:
#if defined(HAL_STUB_HW_BREAKPOINT_LIST_SIZE) && (HAL_STUB_HW_BREAKPOINT_LIST_SIZE > 0)
		      if (is_Z)
			err = __set_hw_breakpoint(addr, length);
		      else
			err = __remove_hw_breakpoint(addr, length);
		      if (!err)
			strcpy (__remcomOutBuffer, "OK");
		      else
#endif
			strcpy (__remcomOutBuffer, "E02");

⌨️ 快捷键说明

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