From 0381a8d47b1b508b38f510c369a16726b0497ac1 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Wed, 2 Oct 2002 17:38:36 +0000 Subject: 2002-10-02 Joel Sherrill * rtems-stub-glue.c: Removed should only be common copy. --- c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog | 4 + .../libbsp/mips/shared/gdbstub/rtems-stub-glue.c | 1418 -------------------- 2 files changed, 4 insertions(+), 1418 deletions(-) delete mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/rtems-stub-glue.c (limited to 'c') diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog b/c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog index 26a86026d9..ed0634b60f 100644 --- a/c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog +++ b/c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog @@ -1,3 +1,7 @@ +2002-10-02 Joel Sherrill + + * rtems-stub-glue.c: Removed should only be common copy. + 2002-08-14 Greg Menke * mips-stub.c: Re-debugged a breakpoint problem, zbreak target diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/rtems-stub-glue.c b/c/src/lib/libbsp/mips/shared/gdbstub/rtems-stub-glue.c deleted file mode 100644 index f99a38f7b5..0000000000 --- a/c/src/lib/libbsp/mips/shared/gdbstub/rtems-stub-glue.c +++ /dev/null @@ -1,1418 +0,0 @@ -/* - * 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 -#include - -#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_RTEMS_TASKS]; - - 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_THREADS]->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_RTEMS_TASKS]; - - 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_THREADS]; - - 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_RTEMS_TASKS]; - - 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_THREADS]; - - 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_RTEMS_TASKS]; - - 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); - - name = *(unsigned32 *)(obj_info->local_table[thread]->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; - } - - first_posix_id = first_rtems_id + (max_id - min_id) + 1; - - obj_info = _Objects_Information_table[OBJECTS_POSIX_THREADS]; - - 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,,, 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, <mp); - if (in == NULL || ltmp < 1) - { - return 0; - } - - *type = ttmp; - *addr = (unsigned char *)atmp; - *len = ltmp; - - return 1; -} - -/* Format: qP */ -static int -parse_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...] */ -static void -pack_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 */ -static int -parse_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[...] */ -static char * -reserve_qm_header(char *out) -{ - ASSERT(out != NULL); - - return out + 21; -} - -/* Format: qM[...] */ -static char* -pack_qm_thread(char *out, int thread) -{ - ASSERT(out != 0); - - return thread2fhstr(out, thread); -} - -/* Format: qM[...] */ -static void -pack_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; - - - - - - case 'L': - /* Thread list query */ - if (!do_threads) { - break; - } - - { - int ret, athread, first, max_cnt, i, done, rthread; - - ret = parse_ql(inbuffer, &first, &max_cnt, &athread); - if (!ret) { - strcpy(outbuffer, "E02"); - break; - } - - if (max_cnt == 0) { - strcpy(outbuffer, "E02"); - break; - } - - if (max_cnt > QM_MAX_THREADS) { - /* Limit max count by buffer size */ - max_cnt = QM_MAX_THREADS; - } - - /* Reserve place for output header */ - optr = reserve_qm_header(outbuffer); - - if (first) { - rthread = 0; - } else { - rthread = athread; - } - - done = 0; - - for (i=0; i> shift) & 0x0f; - - if (nibble != 0) - { - break; - } - } - - if (i == 8) - { - *buf++ = '0'; - return buf; - } - - *buf++ = gdb_hexchars[nibble]; - - for(i++, shift-=4; i<8; i++, shift-=4, buf++) - { - nibble = (thread >> shift) & 0x0f; - *buf = gdb_hexchars[nibble]; - } - - return buf; -} - -/* Present thread in fixed length string format */ -char* -thread2fhstr(char *buf, int thread) -{ - int i, nibble, shift; - - ASSERT(buf != NULL); - - for(i=0; i<8; i++, buf++) - { - *buf = '0'; - } - - for(i=0, shift=28; i<8; i++, shift-=4, buf++) - { - nibble = (thread >> shift) & 0x0f; - *buf = gdb_hexchars[nibble]; - } - - return buf; -} - -/* Parse thread presented in fixed length format */ -const char* -fhstr2thread(const char *buf, int *thread) -{ - int i, val, nibble; - - ASSERT(buf != NULL); - ASSERT(thread != NULL); - - for(i=0; i<8; i++, buf++) - { - if (*buf != '0') - { - return NULL; - } - } - - val = 0; - - for(i=0; i<8; i++, buf++) - { - if (!hstr2nibble(buf, &nibble)) - { - return NULL; - } - - ASSERT(nibble >=0 && nibble < 16); - - val = (val << 4) | nibble; - } - - *thread = val; - - return buf; -} - -/* Parse thread presented in variable length format */ -const char* -vhstr2thread(const char *buf, int *thread) -{ - int i, val, nibble; - int found_zero, lim; - - ASSERT(buf != NULL); - ASSERT(thread != NULL); - - - /* If we have leading zeros, skip them */ - found_zero = 0; - - for(i=0; i<16; i++, buf++) - { - if (*buf != '0') - { - break; - } - - found_zero = 1; - } - - /* Process non-zeros */ - lim = 16 - i; - val = 0; - - for(i=0; i= 0 && nibble < 16); - - val = (val << 4) | nibble; - } - - if (hstr2nibble(buf, &nibble)) - { - /* Value is too long */ - return NULL; - } - - *thread = val; - return buf; -} - - -/* Present integer in the variable length string format */ -char* -int2vhstr(char *buf, int val) -{ - int i, nibble, shift; - - ASSERT(buf != NULL); - - for(i=0, shift=28; i<8; i++, shift-=4) - { - nibble = (val >> shift) & 0x0f; - - if (nibble != 0) - { - break; - } - } - - if (i == 8) - { - *buf++ = '0'; - return buf; - } - - *buf++ = gdb_hexchars[nibble]; - - for(i++, shift-=4; i<8; i++, shift-=4, buf++) - { - nibble = (val >> shift) & 0x0f; - *buf = gdb_hexchars[nibble]; - } - - return buf; -} - -/* Present int in fixed length string format */ -char* -int2fhstr(char *buf, int val) -{ - int i, nibble, shift; - - ASSERT(buf != NULL); - - for(i=0, shift=28; i<8; i++, shift-=4, buf++) - { - nibble = (val >> shift) & 0x0f; - *buf = gdb_hexchars[nibble]; - } - - return buf; -} - -/* Parse int presented in fixed length format */ -const char* -fhstr2int(const char *buf, int *ival) -{ - int i, val, nibble; - - ASSERT(buf != NULL); - ASSERT(ival != NULL); - - val = 0; - - for(i=0; i<8; i++, buf++) - { - if (!hstr2nibble(buf, &nibble)) - { - return NULL; - } - - ASSERT(nibble >=0 && nibble < 16); - - val = (val << 4) | nibble; - } - - *ival = val; - - return buf; -} - -/* Parse int presented in variable length format */ -const char* -vhstr2int(const char *buf, int *ival) -{ - int i, val, nibble; - int found_zero, lim; - - ASSERT(buf != NULL); - ASSERT(ival != NULL); - - - /* If we have leading zeros, skip them */ - found_zero = 0; - - for(i=0; i<8; i++, buf++) - { - if (*buf != '0') - { - break; - } - - found_zero = 1; - } - - /* Process non-zeros */ - lim = 8 - i; - val = 0; - - for(i=0; i= 0 && nibble < 16); - - val = (val << 4) | nibble; - } - - if (hstr2nibble(buf, &nibble)) - { - /* Value is too long */ - return NULL; - } - - *ival = val; - return buf; -} - -int -hstr2byte(const char *buf, int *bval) -{ - int hnib, lnib; - - ASSERT(buf != NULL); - ASSERT(bval != NULL); - - if (!hstr2nibble(buf, &hnib) || !hstr2nibble(buf+1, &lnib)) - { - return 0; - } - - *bval = (hnib << 4) | lnib; - return 1; -} - -int -hstr2nibble(const char *buf, int *nibble) -{ - int ch; - - ASSERT(buf != NULL); - ASSERT(nibble != NULL); - - ch = *buf; - - if (ch >= '0' && ch <= '9') - { - *nibble = ch - '0'; - return 1; - } - - if (ch >= 'a' && ch <= 'f') - { - *nibble = ch - 'a' + 10; - return 1; - } - - if (ch >= 'A' && ch <= 'F') - { - *nibble = ch - 'A' + 10; - return 1; - } - - return 0; -} - -static volatile char mem_err = 0; -void set_mem_err(void); -static void (*volatile mem_fault_routine) (void) = NULL; - - - -/* convert count bytes of the memory pointed to by mem into hex string, - placing result in buf, return pointer to next location in hex strng - in case of success or NULL otherwise */ -char* -mem2hstr(char *buf, const unsigned char *mem, int count) -{ - int i; - unsigned char ch; - - mem_err = 0; - - mem_fault_routine = set_mem_err; - - for (i = 0; i> 4]; - *buf++ = gdb_hexchars[ch & 0x0f]; - } - - *buf = 0; - - mem_fault_routine = NULL; - - return buf; -} - -/* convert the hex string to into count bytes of binary to be placed in mem - return 1 in case of success and 0 otherwise */ -int -hstr2mem (unsigned char *mem, const char *buf, int count) -{ - int i; - int bval; - - mem_err = 0; - - mem_fault_routine = set_mem_err; - - for (i = 0; i < count; i++, mem++, buf+=2) - { - if (!hstr2byte(buf, &bval)) - { - mem_fault_routine = NULL; - return 0; - } - - ASSERT(bval >=0 && bval < 256); - - set_byte (mem, bval); - - if (mem_err) - { - mem_fault_routine = NULL; - return 0; - } - } - - mem_fault_routine = NULL; - return 1; -} - -void -set_mem_err (void) -{ - mem_err = 1; -} - - -/* These are separate functions so that they are so short and sweet - that the compiler won't save any registers (if there is a fault - to mem_fault, they won't get restored, so there better not be any - saved). */ - -unsigned char -get_byte (const unsigned char *addr) -{ - return *addr; -} - -void -set_byte (unsigned char *addr, int val) -{ - *addr = val; -} - - - - - - - - - -/* - * From here down, the code is CPU model specific and generally maps - * the RTEMS thread context format to gdb's. - */ - -#if defined(__i386__) - -#include "i386-stub.h" - -/* Packing order of registers */ -enum i386_stub_regnames { - I386_STUB_REG_EAX, I386_STUB_REG_ECX, I386_STUB_REG_EDX, I386_STUB_REG_EBX, - I386_STUB_REG_ESP, I386_STUB_REG_EBP, I386_STUB_REG_ESI, I386_STUB_REG_EDI, - I386_STUB_REG_PC /* also known as eip */ , - I386_STUB_REG_PS /* also known as eflags */ , - I386_STUB_REG_CS, I386_STUB_REG_SS, I386_STUB_REG_DS, I386_STUB_REG_ES, - I386_STUB_REG_FS, I386_STUB_REG_GS -}; - -void rtems_gdb_stub_get_registers_from_context( - int *registers, - Thread_Control *th -) -{ - registers[I386_STUB_REG_EAX] = 0; - registers[I386_STUB_REG_ECX] = 0; - registers[I386_STUB_REG_EDX] = 0; - registers[I386_STUB_REG_EBX] = (int)th->Registers.ebx; - registers[I386_STUB_REG_ESP] = (int)th->Registers.esp; - registers[I386_STUB_REG_EBP] = (int)th->Registers.ebp; - registers[I386_STUB_REG_ESI] = (int)th->Registers.esi; - registers[I386_STUB_REG_EDI] = (int)th->Registers.edi; - registers[I386_STUB_REG_PC] = *(int *)th->Registers.esp; - registers[I386_STUB_REG_PS] = (int)th->Registers.eflags; - - /* RTEMS never changes base registers (especially once - threads are running) */ - - registers[I386_STUB_REG_CS] = 0x8; /* We just know these values */ - registers[I386_STUB_REG_SS] = 0x10; - registers[I386_STUB_REG_DS] = 0x10; - registers[I386_STUB_REG_ES] = 0x10; - registers[I386_STUB_REG_FS] = 0x10; - registers[I386_STUB_REG_GS] = 0x10; -} - -int rtems_gdb_stub_get_offsets( - unsigned char **text_addr, - unsigned char **data_addr, - unsigned char **bss_addr -) -{ - extern unsigned char _text_start; - extern unsigned char _data_start; - extern unsigned char _bss_start; - - *text_addr = &_text_start; - *data_addr = &_data_start; - *bss_addr = &_bss_start; - - return 1; -} - - - - - -#elif defined(__mips__) - - -void rtems_gdb_stub_get_registers_from_context( - int *registers, - Thread_Control *th -) -{ - registers[S0] = (unsigned)th->Registers.s0; - registers[S1] = (unsigned)th->Registers.s1; - registers[S2] = (unsigned)th->Registers.s2; - registers[S3] = (unsigned)th->Registers.s3; - registers[S4] = (unsigned)th->Registers.s4; - registers[S5] = (unsigned)th->Registers.s5; - registers[S6] = (unsigned)th->Registers.s6; - registers[S7] = (unsigned)th->Registers.s7; - - registers[SP] = (unsigned)th->Registers.sp; - registers[RA] = (unsigned)th->Registers.ra; - - registers[SR] = (unsigned)th->Registers.c0_sr; - registers[PC] = (unsigned)th->Registers.c0_epc; -} - - -int rtems_gdb_stub_get_offsets( - unsigned char **text_addr, - unsigned char **data_addr, - unsigned char **bss_addr -) -{ -/* -** These are the right symbols for the desired addresses, -** but giving them causes gdb to have fits, so we leave -** the reported values as 0. Doesn't hurt the stub's -** operation as far as I've observed. -*/ - -/* - extern unsigned32 _ftext; - extern unsigned32 _fdata; - extern unsigned32 _bss_start; - - *text_addr = &_ftext; - *data_addr = &_fdata; - *bss_addr = &_bss_start; -*/ - *text_addr = 0; - *data_addr = 0; - *bss_addr = 0; - return 1; -} - -#else -#error "rtems-gdb-stub.c: Unsupported CPU!" -#endif -- cgit v1.2.3