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

📄 rtems-stub-glue.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  This file contains the RTEMS thread awareness support for GDB stubs. * *  This file is derived from an RTEMS thread aware i386-stub.c that *  had the following copyright announcements: * *    This software is Copyright (C) 1998 by T.sqware - all rights limited *    It is provided in to the public domain "as is", can be freely modified *    as far as this copyight notice is kept unchanged, but does not imply *    an endorsement by T.sqware of the product in which it is included. * *   *     Modifications for RTEMS threads and more * *     Copyright (C) 2000 Quality Quorum, Inc.  *  *     All Rights Reserved *  *     Permission to use, copy, modify, and distribute this software and its  *     documentation for any purpose and without fee is hereby granted.  *  *     QQI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING *     ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL *     QQI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR *     ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, *     WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, *     ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS *     SOFTWARE. */#include <rtems.h>#include <string.h>#include "gdb_if.h"/* Change it to something meaningful when debugging */#undef ASSERT#define ASSERT(x) extern const char gdb_hexchars[];/* *  Prototypes for CPU dependent routines that are conditional *  at the bottom of this file. */void rtems_gdb_stub_get_registers_from_context(   int            *registers,  Thread_Control *th);/* Check whether it is OK to enable thread support */int rtems_gdb_stub_thread_support_ok(void){  if (_System_state_Get() == SYSTEM_STATE_UP) {    return 1;  }  return 0;}/* *  rtems_gdb_stub_id_to_index * *  Return the gdb thread id for the specified RTEMS thread id */int rtems_gdb_stub_id_to_index(  Objects_Id thread_obj_id){  Objects_Id min_id, max_id;  int first_posix_id, first_rtems_id;  Objects_Information *obj_info;  if (_System_state_Get() != SYSTEM_STATE_UP) {    /* We have one thread let us use value reserved for idle thread */    return 1;   }  if (_Thread_Executing == _Thread_Idle) {    return 1;  }  /* Let us figure out thread_id for gdb */  first_rtems_id = 2;  obj_info = _Objects_Information_table[OBJECTS_CLASSIC_API][1];  min_id = obj_info->minimum_id;  max_id = obj_info->maximum_id;  if (thread_obj_id >= min_id && thread_obj_id < max_id) {    return first_rtems_id + (thread_obj_id - min_id);  }  first_posix_id = first_rtems_id + (max_id - min_id) + 1;  min_id = _Objects_Information_table[OBJECTS_POSIX_API][1]->minimum_id;  return first_posix_id + (thread_obj_id - min_id);} /* Return the RTEMS thread id from a gdb thread id */Thread_Control *rtems_gdb_index_to_stub_id(  int thread){   Objects_Id thread_obj_id;   Objects_Id min_id, max_id;   int first_posix_id, first_rtems_id;   Objects_Information *obj_info;   Thread_Control *th;   ASSERT(registers != NULL);   if (_System_state_Get() != SYSTEM_STATE_UP || thread <= 0) {      /* Should not happen */      return NULL;   }   if (thread == 1) {      th = _Thread_Idle;      goto found;   }   /* Let us get object associtated with current thread */   first_rtems_id = 2;   thread_obj_id = _Thread_Executing->Object.id;   /* Let us figure out thread_id for gdb */   obj_info = _Objects_Information_table[OBJECTS_CLASSIC_API][1];   min_id = obj_info->minimum_id;   max_id = obj_info->maximum_id;   if (thread <= (first_rtems_id + (max_id - min_id))) {      th = (Thread_Control *)(obj_info->local_table[thread - first_rtems_id + 1]);      if (th != NULL) {         goto found;      }      /* Thread does not exist */      return NULL;   }   first_posix_id = first_rtems_id + (max_id - min_id) + 1;   obj_info = _Objects_Information_table[OBJECTS_POSIX_API][1];   min_id = obj_info->minimum_id;   max_id = obj_info->maximum_id;   th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]);   if (th == NULL) {      /* Thread does not exist */      return NULL;   }  found:   return th;}/* Get id of the thread stopped by exception */int rtems_gdb_stub_get_current_thread(void){  return rtems_gdb_stub_id_to_index( _Thread_Executing->Object.id );}/* Get id of the next thread after athread, if argument <= 0 find the   first available thread, return thread if found or 0 if not */int rtems_gdb_stub_get_next_thread(int athread){  Objects_Id id, min_id, max_id;  int lim, first_posix_id, first_rtems_id;  Objects_Information *obj_info;  int start;  if (_System_state_Get() != SYSTEM_STATE_UP) {    /* We have one thread let us use value of idle thread */    return (athread < 1) ? 1 : 0;  }  if (athread < 1) {    return 1;  }  first_rtems_id = 2;   obj_info = _Objects_Information_table[OBJECTS_CLASSIC_API][1];  min_id = obj_info->minimum_id;  max_id = obj_info->maximum_id;  lim = first_rtems_id + max_id - min_id;  if (athread < lim) {    if (athread < first_rtems_id) {      start = first_rtems_id;    } else {      start = 1 + athread;    }    for (id=start; id<=lim; id++) {      if (obj_info->local_table[id - first_rtems_id + 1] != NULL) {        return id;      }    }  }        first_posix_id = first_rtems_id + (max_id - min_id) + 1;  obj_info = _Objects_Information_table[OBJECTS_POSIX_API][1];  min_id = obj_info->minimum_id;  max_id = obj_info->maximum_id;  lim = first_posix_id + (max_id - min_id);  if (athread < lim) {    if (athread < first_posix_id) {      start = first_posix_id;    } else {      start = 1 + athread;    }          for (id=start; id<=lim; id++) {      if (obj_info->local_table[id - first_posix_id + 1] != NULL) {        return id;      }    }  }  /* Not found */  return 0;}/* Get thread registers, return 0 if thread does not    exist, and 1 otherwise */int rtems_gdb_stub_get_thread_regs(  int thread,  unsigned int *registers){   Thread_Control *th;   th= rtems_gdb_index_to_stub_id(thread);   if( th )   {      rtems_gdb_stub_get_registers_from_context( registers, th );      return 1;   }   return 0;}/* Set thread registers, return 0 if thread does not    exist or register values will screw up the threads,    and 1 otherwise */int rtems_gdb_stub_set_thread_regs(  int thread,  unsigned int *registers){  /* In current situation there is no point in changing any registers here     thread status is displayed as being deep inside thread switching      and we better do not screw up anything there - it may be fixed eventually     though */  return 1;}/* Get thread information, return 0 if thread does not    exist and 1 otherwise */int rtems_gdb_stub_get_thread_info(  int thread,  struct rtems_gdb_stub_thread_info *info){   Objects_Id thread_obj_id;   Objects_Id min_id, max_id;   int first_posix_id, first_rtems_id;   Objects_Information *obj_info;   Thread_Control *th;   unsigned32 name;   char tmp_buf[20];   ASSERT(info != NULL);   if (thread <= 0) {      return 0;   }   if (_System_state_Get() != SYSTEM_STATE_UP || thread == 1) {      /* We have one thread let us use value         which will never happen for real thread */      strcpy(info->display, "idle thread");      strcpy(info->name, "IDLE");      info->more_display[0] = 0; /* Nothing */      return 1;   }   /* Let us get object associtated with current thread */   thread_obj_id = _Thread_Executing->Object.id;   /* Let us figure out thread_id for gdb */   first_rtems_id = 2;     obj_info = _Objects_Information_table[OBJECTS_CLASSIC_API][1];   min_id = obj_info->minimum_id;   max_id = obj_info->maximum_id;   if (thread <= (first_rtems_id + (max_id - min_id))) {      th = (Thread_Control *)(obj_info->local_table[thread -                                                     first_rtems_id + 1]);      if (th == NULL) {         /* Thread does not exist */         return 0;      }      strcpy(info->display, "rtems task:   control at 0x");      tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];      tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];      tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];      tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];      tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];      tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];      tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];      tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];      tmp_buf[8] = 0;      strcat(info->display, tmp_buf);#if 0      name = *(unsigned32 *)(obj_info->local_table[thread]->name);#else      name = *(unsigned32 *)(obj_info->local_table[thread - 						   first_rtems_id + 1]->name);#endif      info->name[0] = (name >> 24) & 0xff;      info->name[1] = (name >> 16) & 0xff;      info->name[2] = (name >> 8) & 0xff;      info->name[3] = name & 0xff;      info->name[4] = 0;      info->more_display[0] = 0; /* Nothing */      return 1;   }   first_posix_id = first_rtems_id + (max_id - min_id) + 1;   obj_info = _Objects_Information_table[OBJECTS_POSIX_API][1];   min_id = obj_info->minimum_id;   max_id = obj_info->maximum_id;   th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]);   if (th == NULL)   {      /* Thread does not exist */      return 0;   }   strcpy(info->display, "posix thread: control at 0x");   tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];   tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];   tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];   tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];   tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];   tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];   tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];   tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];   tmp_buf[8] = 0;   strcat(info->display, tmp_buf);   name = *(unsigned32 *)(obj_info->local_table[thread -                                                 first_posix_id + 1]->name);   info->name[0] = (name >> 24) & 0xff;   info->name[1] = (name >> 16) & 0xff;   info->name[2] = (name >> 8) & 0xff;   info->name[3] = name & 0xff;   info->name[4] = 0;   info->more_display[0] = 0; /* Nothing */     return 1;}/*******************************************************//* Format: x<type-1x>,<address-x>,<length-x>, where x is 'z' or 'Z' */int parse_zbreak(const char *in, int *type, unsigned char **addr, int *len){  int ttmp, atmp, ltmp;    ASSERT(in != NULL);  ASSERT(type != NULL);  ASSERT(addr != NULL);  ASSERT(len != NULL);  ASSERT(*in == 'z' || *in == 'Z');  in++;  if (!hstr2nibble(in, &ttmp) || *(in+1) != ',')    {      return 0;    }  in += 2;  in = vhstr2int(in, &atmp);  if (in == NULL || *in != ',')    {      return 0;    }  in++;  in = vhstr2int(in, &ltmp);  if (in == NULL || ltmp < 1)    {      return 0;    }  *type = ttmp;  *addr = (unsigned char *)atmp;  *len  = ltmp;  return 1;}/* Format: qP<mask-08x><thread_id-ft> */static intparse_qp(const char *in, int *mask, int *thread){  const char *ptr;  ASSERT(in != NULL);  ASSERT(*in == 'q');  ASSERT(*(in+1) == 'P');  ptr = fhstr2int(in+2, mask);  if (ptr == NULL)    {      return 0;    }  ptr = fhstr2thread(ptr, thread);  if (ptr == NULL)    {      return 0;    }  return 1;}/* Format: qQ<mask-08x><thread_id-ft><tag-08x><length-02x><value>...] */static voidpack_qq(char *out, int mask, int thread, struct rtems_gdb_stub_thread_info *info){  int len;  ASSERT(out != NULL);  ASSERT(info != NULL);  *out++ = 'q';  *out++ = 'Q';  out = int2fhstr(out, mask);  out = thread2fhstr(out, thread);  if (mask & 0x1) {    /* Thread id once again */    memcpy(out, "00000001", 8);    out   += 8;    *out++ = '1';    *out++ = '0';    out = thread2fhstr(out, thread);  }  if (mask & 0x2) {    /* Exists */    memcpy(out, "00000002", 8);    out   += 8;    *out++ = '0';    *out++ = '1';    *out++ = '1';  }  if (mask & 0x4) {    /* Display */    memcpy(out, "00000004", 8);    out += 8;    info->display[sizeof(info->display)-1] = 0; /* Fot God sake */    len = strlen(info->display);    *out++ = gdb_hexchars[len >> 4];    *out++ = gdb_hexchars[len & 0x0f];    memcpy(out, info->display, len);    out += len;  }  if (mask & 0x8) {    /* Name */    memcpy(out, "00000008", 8);    out += 8;    info->name[sizeof(info->name)-1] = 0; /* Fot God sake */    len = strlen(info->name);    *out++ = gdb_hexchars[len >> 4];    *out++ = gdb_hexchars[len & 0x0f];    memcpy(out, info->name, len);    out += len;  }  if (mask & 0x10) {    /* More display */    memcpy(out, "00000010", 8);    out += 8;    info->more_display[sizeof(info->more_display)-1] = 0; /* Fot God sake */    len = strlen(info->more_display);    *out++ = gdb_hexchars[len >> 4];    *out++ = gdb_hexchars[len & 0x0f];    memcpy(out, info->more_display, len);    out += len;  }  *out = 0;  return;}/* Format qL<first-01x><max_count-02x><arg_thread_id-ft> */static intparse_ql(const char *in, int *first, int *max_count, int *athread){  const char *ptr;  ASSERT(in != NULL);  ASSERT(*in == 'q');  ASSERT(*(in+1) == 'L');  ASSERT(first != NULL);  ASSERT(max_count != NULL);  ASSERT(athread != NULL);  ptr = in + 2;  /*  First */  if (!hstr2nibble(ptr, first))    {      return 0;    }  ptr++;  /* Max count */  if (!hstr2byte(ptr, max_count))    {      return 0;    }  ptr += 2;  /* A thread */  ptr = fhstr2thread(ptr, athread);  if (ptr == NULL)    {      return 0;    }  return 1;}/* Format: qM<count-02x><done-01x><arg_thread_id>[<found_thread_id-ft>...] */static char *reserve_qm_header(char *out){  ASSERT(out != NULL);  return out + 21;}/* Format: qM<count-02x><done-01x><arg_thread_id>[<found_thread_id-ft>...] */static char*pack_qm_thread(char *out, int thread){  ASSERT(out != 0);  return thread2fhstr(out, thread);}/* Format: qM<count-02x><done-01x><arg_thread_id>[<found_thread_id-ft>...] */static voidpack_qm_header(char *out, int count, int done, int athread){   ASSERT(out != 0);   ASSERT(count >= 0 && count < 256);   *out++ = 'q';   *out++ = 'M';   *out++ = gdb_hexchars[(count >> 4) & 0x0f];   *out++ = gdb_hexchars[count & 0x0f];   if (done) {      *out++ = '1';   } else {      *out++ = '0';   }   thread2fhstr(out, athread);   return;}void rtems_gdb_process_query(   char *inbuffer,  char *outbuffer,  int   do_threads,  int   thread){  char *optr;      switch(inbuffer[1]) {    case 'C':      /* Current thread query query - return stopped thread */      if (!do_threads) {        break;      }      optr = outbuffer;      *optr++ = 'Q';      *optr++ = 'C';      optr    = thread2vhstr(optr, thread);      *optr   = 0;      break;    case 'P':      /* Thread info query */      if (!do_threads) {        break;      }      {        int ret, rthread, mask;        struct rtems_gdb_stub_thread_info info;        ret = parse_qp(inbuffer, &mask, &rthread);        if (!ret|| mask & ~0x1f) {          strcpy(outbuffer, "E01");          break;        }        ret = rtems_gdb_stub_get_thread_info(rthread, &info);        if (!ret) {          /* Good implementation would never ask for non-existing thread,             should we care about bad ones - it does not seem so */          strcpy(outbuffer, "E02");          break;        }        /* Build response */        pack_qq(outbuffer, mask, rthread, &info);      }      break;

⌨️ 快捷键说明

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