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

📄 generic-stub.c

📁 移植到WLIT项目的redboot源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    }  else    __hex2mem_helper ();  return (char *) hexMemDst;}voidset_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);}/*  * 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! */#endifstatic voidlock_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 voidunlock_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_CYGMONint processing_breakpoint_function = 0;#endifvoid__handle_exception (void){  int sigval;#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())    {      if (hal_syscall_handler() == 0)	{	  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;  } else#endif      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 *);voidstub_format_registers(char *ptr){    int regnum;    for (regnum = 0; regnum < NUMREGS_GDB; 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);        }    }}voidstub_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, "eCos GDB stubs" #ifdef CYGPKG_REDBOOT             " [with RedBoot]"#endif             " - built " __DATE__ " / " __TIME__);      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 'g':           /* return the value of the CPU registers */      {        char *ptr = remcomOutBuffer;        stub_format_registers(ptr);        break;      }    case 'A': /* set program arguments */      {        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");          }      }      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 addr, length;        char *ptr = &packet[1];        if (__hexToInt (&ptr, &addr)            && *ptr++ == ','            && __hexToInt (&ptr, &length))          {            if (__mem2hex ((char *) addr, remcomOutBuffer, length, 1))              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 addr, length;        char *ptr = &packet[1], buf[128];        int  i;        if (__hexToInt (&ptr, &addr)            && *ptr++ == ','            && __hexToInt (&ptr, &length)            && *ptr++ == ':')          {            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);                    if (__write_mem_safe (buf, (void *)addr, i) != i)                      break;                    length -= i;                    addr += i;                  }                if (length <= 0)                  strcpy (remcomOutBuffer, "OK");                else                  strcpy (remcomOutBuffer, "E03");              }              else              {                if (__hex2mem (ptr, (char *) addr, length, 1) != 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_register_t addr;        target_register_t sigval = 0;        if (packet[0] == 'C' || packet[0] == 'S')          {            __hexToInt (&ptr, &sigval);            if (*ptr == ';')              ptr++;          }        if (__hexToInt (&ptr, &addr))          set_pc (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) ;

⌨️ 快捷键说明

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