* mips-stub.c: Debugged & tweaked the gdb command processing,
	zbreak stuff, breakpoint and step code.  Implemented 'T' command
	support and debugged remote gdb support w/ the Mongoose bsp.
	Added the memory segment support.
	* memlimits.h: Disabled all contents in favor of memory sement
	support.  This file could probably go away.
	* rtems-stub-glue.c (rtems_gdb_index_to_stub_id()): New routine.
	rtems_gdb_stub_get_register_from_context(): Implemented MIPS version.
	rtems_gdb_stub_get_offsets(): Implemented MIPS version.
	* README: Updated.
This commit is contained in:
Joel Sherrill
2002-03-08 16:32:07 +00:00
parent ffdc6591ee
commit 2f89140dba
7 changed files with 1327 additions and 739 deletions

View File

@@ -1,3 +1,16 @@
2001-03-05 Greg Menke <gregory.menke@gsfc.nasa.gov>
* mips-stub.c: Debugged & tweaked the gdb command processing,
zbreak stuff, breakpoint and step code. Implemented 'T' command
support and debugged remote gdb support w/ the Mongoose bsp.
Added the memory segment support.
* memlimits.h: Disabled all contents in favor of memory sement
support. This file could probably go away.
* rtems-stub-glue.c (rtems_gdb_index_to_stub_id()): New routine.
rtems_gdb_stub_get_register_from_context(): Implemented MIPS version.
rtems_gdb_stub_get_offsets(): Implemented MIPS version.
* README: Updated.
2001-03-01 Joel Sherrill <joel@OARcorp.com> 2001-03-01 Joel Sherrill <joel@OARcorp.com>
* ChangeLog: Corrected previous entry. * ChangeLog: Corrected previous entry.

View File

@@ -2,6 +2,29 @@
# $Id$ # $Id$
# #
/*****************************************************/
Debugged this stub against the MongooseV bsp. Relies on putting break
instructions on breakpoints and step targets- normal stuff, and does not
employ hardware breakpoint support at this time. As written, a single
breakpoint in a loop will not be reasserted unless the user steps or has
a 2nd one, since breakpoints are only reset when the gdb stub is
re-entered. A useful enhancement would be to fix the break instruction
management so the stub could invisibly put a 2nd break after the 1st
"official" one so it can silently reset breakpoints. Shouldn't be too
hard, mostly a matter of working it out.
This was tested only against an R3000 MIPS. It should work OK on a
R4000. Needs to be tested at some point.
This stub supports threads as implemented by gdb 5 and doesn't have any
bugs I'm aware of.
Greg Menke
3/5/2002
/*****************************************************/
The contents of this directory are based upon the "r46kstub.tar.gz" package The contents of this directory are based upon the "r46kstub.tar.gz" package
released to the net by released to the net by

View File

@@ -49,6 +49,7 @@ const char* vhstr2int(const char *buf, int *ival);
int hstr2byte(const char *buf, int *bval); int hstr2byte(const char *buf, int *bval);
int hstr2nibble(const char *buf, int *nibble); int hstr2nibble(const char *buf, int *nibble);
Thread_Control *rtems_gdb_index_to_stub_id(int);
int rtems_gdb_stub_thread_support_ok(void); int rtems_gdb_stub_thread_support_ok(void);
int rtems_gdb_stub_get_current_thread(void); int rtems_gdb_stub_get_current_thread(void);
int rtems_gdb_stub_get_next_thread(int); int rtems_gdb_stub_get_next_thread(int);
@@ -159,4 +160,21 @@ void rtems_gdb_process_query(
#define NUM_REGS 72 #define NUM_REGS 72
void mips_gdb_stub_install(int enableThreads) ;
#define MEMOPT_READABLE 1
#define MEMOPT_WRITEABLE 2
#define NUM_MEMSEGS 10
int gdbstub_add_memsegment(unsigned,unsigned,int);
#endif /* _GDB_IF_H */ #endif /* _GDB_IF_H */

View File

@@ -12,8 +12,8 @@
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/ */
#ifndef _LIMITS_H_ #ifndef _MEMLIMITS_H_
#define _LIMITS_H_ #define _MEMLIMITS_H_
/* /*
* The macros in this file are specific to a given implementation. * The macros in this file are specific to a given implementation.
@@ -45,6 +45,7 @@
* to have different readability and/or writeability attributes. * to have different readability and/or writeability attributes.
*/ */
/*
#define K0_LIMIT_FOR_READ (K0BASE+0x18000000) #define K0_LIMIT_FOR_READ (K0BASE+0x18000000)
#define K1_LIMIT_FOR_READ (K1BASE+K1SIZE) #define K1_LIMIT_FOR_READ (K1BASE+K1SIZE)
@@ -67,4 +68,21 @@
&& (((K0BASE <= (int)ptr) && ((int)ptr < K0_LIMIT_FOR_STEP)) \ && (((K0BASE <= (int)ptr) && ((int)ptr < K0_LIMIT_FOR_STEP)) \
|| ((K1BASE <= (int)ptr) && ((int)ptr < K1_LIMIT_FOR_STEP)))) || ((K1BASE <= (int)ptr) && ((int)ptr < K1_LIMIT_FOR_STEP))))
#endif /* _LIMITS_H_ */ struct memseg
{
unsigned begin, end, opts;
};
#define MEMOPT_READABLE 1
#define MEMOPT_WRITEABLE 2
#define NUM_MEMSEGS 10
int add_memsegment(unsigned,unsigned,int);
int is_readable(unsigned,unsigned);
int is_writeable(unsigned,unsigned);
int is_steppable(unsigned);
*/
#endif /* _MEMLIMITS_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,6 @@
*/ */
#include <rtems.h> #include <rtems.h>
#include <string.h> #include <string.h>
#include "gdb_if.h" #include "gdb_if.h"
@@ -40,6 +39,7 @@
extern const char gdb_hexchars[]; extern const char gdb_hexchars[];
/* /*
* Prototypes for CPU dependent routines that are conditional * Prototypes for CPU dependent routines that are conditional
* at the bottom of this file. * at the bottom of this file.
@@ -50,6 +50,12 @@ void rtems_gdb_stub_get_registers_from_context(
Thread_Control *th Thread_Control *th
); );
/* Check whether it is OK to enable thread support */ /* Check whether it is OK to enable thread support */
int rtems_gdb_stub_thread_support_ok(void) int rtems_gdb_stub_thread_support_ok(void)
{ {
@@ -59,6 +65,10 @@ int rtems_gdb_stub_thread_support_ok(void)
return 0; return 0;
} }
/* /*
* rtems_gdb_stub_id_to_index * rtems_gdb_stub_id_to_index
* *
@@ -101,12 +111,84 @@ int rtems_gdb_stub_id_to_index(
return first_posix_id + (thread_obj_id - min_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 */ /* Get id of the thread stopped by exception */
int rtems_gdb_stub_get_current_thread(void) int rtems_gdb_stub_get_current_thread(void)
{ {
return rtems_gdb_stub_id_to_index( _Thread_Executing->Object.id ); return rtems_gdb_stub_id_to_index( _Thread_Executing->Object.id );
} }
/* Get id of the next thread after athread, if argument <= 0 find the /* Get id of the next thread after athread, if argument <= 0 find the
first available thread, return thread if found or 0 if not */ first available thread, return thread if found or 0 if not */
int rtems_gdb_stub_get_next_thread(int athread) int rtems_gdb_stub_get_next_thread(int athread)
@@ -176,6 +258,10 @@ int rtems_gdb_stub_get_next_thread(int athread)
} }
/* Get thread registers, return 0 if thread does not /* Get thread registers, return 0 if thread does not
exist, and 1 otherwise */ exist, and 1 otherwise */
int rtems_gdb_stub_get_thread_regs( int rtems_gdb_stub_get_thread_regs(
@@ -183,70 +269,27 @@ int rtems_gdb_stub_get_thread_regs(
unsigned int *registers unsigned int *registers
) )
{ {
Objects_Id thread_obj_id; Thread_Control *th;
Objects_Id min_id, max_id;
int first_posix_id, first_rtems_id;
Objects_Information *obj_info;
Thread_Control *th;
ASSERT(registers != NULL); th= rtems_gdb_index_to_stub_id(thread);
if (_System_state_Get() != SYSTEM_STATE_UP || thread <= 0) { if( th )
/* Should not happen */ {
return 0; rtems_gdb_stub_get_registers_from_context( registers, th );
} return 1;
}
if (thread == 1) { return 0;
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 0;
}
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;
}
found:
rtems_gdb_stub_get_registers_from_context( registers, th );
return 1;
} }
/* Set thread registers, return 0 if thread does not /* Set thread registers, return 0 if thread does not
exist or register values will screw up the threads, exist or register values will screw up the threads,
and 1 otherwise */ and 1 otherwise */
int rtems_gdb_stub_set_thread_regs( int rtems_gdb_stub_set_thread_regs(
int thread, int thread,
unsigned int *registers unsigned int *registers
@@ -260,6 +303,10 @@ int rtems_gdb_stub_set_thread_regs(
} }
/* Get thread information, return 0 if thread does not /* Get thread information, return 0 if thread does not
exist and 1 otherwise */ exist and 1 otherwise */
int rtems_gdb_stub_get_thread_info( int rtems_gdb_stub_get_thread_info(
@@ -267,122 +314,126 @@ int rtems_gdb_stub_get_thread_info(
struct rtems_gdb_stub_thread_info *info struct rtems_gdb_stub_thread_info *info
) )
{ {
Objects_Id thread_obj_id; Objects_Id thread_obj_id;
Objects_Id min_id, max_id; Objects_Id min_id, max_id;
int first_posix_id, first_rtems_id; int first_posix_id, first_rtems_id;
Objects_Information *obj_info; Objects_Information *obj_info;
Thread_Control *th; Thread_Control *th;
unsigned32 name; unsigned32 name;
char tmp_buf[20]; char tmp_buf[20];
ASSERT(info != NULL); ASSERT(info != NULL);
if (thread <= 0) { if (thread <= 0) {
return 0; return 0;
} }
if (_System_state_Get() != SYSTEM_STATE_UP || thread == 1) { if (_System_state_Get() != SYSTEM_STATE_UP || thread == 1) {
/* We have one thread let us use value /* We have one thread let us use value
which will never happen for real thread */ which will never happen for real thread */
strcpy(info->display, "idle thread"); strcpy(info->display, "idle thread");
strcpy(info->name, "IDLE"); strcpy(info->name, "IDLE");
info->more_display[0] = 0; /* Nothing */ info->more_display[0] = 0; /* Nothing */
return 1; return 1;
} }
/* Let us get object associtated with current thread */ /* Let us get object associtated with current thread */
thread_obj_id = _Thread_Executing->Object.id; thread_obj_id = _Thread_Executing->Object.id;
/* Let us figure out thread_id for gdb */ /* Let us figure out thread_id for gdb */
first_rtems_id = 2; first_rtems_id = 2;
obj_info = _Objects_Information_table[OBJECTS_RTEMS_TASKS]; obj_info = _Objects_Information_table[OBJECTS_RTEMS_TASKS];
min_id = obj_info->minimum_id; min_id = obj_info->minimum_id;
max_id = obj_info->maximum_id; max_id = obj_info->maximum_id;
if (thread <= (first_rtems_id + (max_id - min_id))) { if (thread <= (first_rtems_id + (max_id - min_id))) {
th = (Thread_Control *)(obj_info->local_table[thread - th = (Thread_Control *)(obj_info->local_table[thread -
first_rtems_id + 1]); first_rtems_id + 1]);
if (th == NULL) { if (th == NULL) {
/* Thread does not exist */ /* Thread does not exist */
return 0; return 0;
} }
strcpy(info->display, "rtems task: control at 0x"); strcpy(info->display, "rtems task: control at 0x");
tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf]; tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];
tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf]; tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];
tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf]; tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];
tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf]; tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];
tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf]; tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];
tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf]; tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];
tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf]; tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];
tmp_buf[7] = gdb_hexchars[((int)th) & 0xf]; tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];
tmp_buf[8] = 0; tmp_buf[8] = 0;
strcat(info->display, tmp_buf); strcat(info->display, tmp_buf);
name = *(unsigned32 *)(obj_info->local_table[thread]->name); name = *(unsigned32 *)(obj_info->local_table[thread]->name);
info->name[0] = (name >> 24) & 0xff; info->name[0] = (name >> 24) & 0xff;
info->name[1] = (name >> 16) & 0xff; info->name[1] = (name >> 16) & 0xff;
info->name[2] = (name >> 8) & 0xff; info->name[2] = (name >> 8) & 0xff;
info->name[3] = name & 0xff; info->name[3] = name & 0xff;
info->name[4] = 0; info->name[4] = 0;
info->more_display[0] = 0; /* Nothing */ info->more_display[0] = 0; /* Nothing */
return 1; return 1;
} }
first_posix_id = first_rtems_id + (max_id - min_id) + 1; first_posix_id = first_rtems_id + (max_id - min_id) + 1;
obj_info = _Objects_Information_table[OBJECTS_POSIX_THREADS]; obj_info = _Objects_Information_table[OBJECTS_POSIX_THREADS];
min_id = obj_info->minimum_id; min_id = obj_info->minimum_id;
max_id = obj_info->maximum_id; max_id = obj_info->maximum_id;
th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]); th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]);
if (th == NULL) if (th == NULL)
{ {
/* Thread does not exist */ /* Thread does not exist */
return 0; return 0;
} }
strcpy(info->display, "posix thread: control at 0x"); strcpy(info->display, "posix thread: control at 0x");
tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf]; tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];
tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf]; tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];
tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf]; tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];
tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf]; tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];
tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf]; tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];
tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf]; tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];
tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf]; tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];
tmp_buf[7] = gdb_hexchars[((int)th) & 0xf]; tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];
tmp_buf[8] = 0; tmp_buf[8] = 0;
strcat(info->display, tmp_buf); strcat(info->display, tmp_buf);
name = *(unsigned32 *)(obj_info->local_table[thread - name = *(unsigned32 *)(obj_info->local_table[thread -
first_posix_id + 1]->name); first_posix_id + 1]->name);
info->name[0] = (name >> 24) & 0xff; info->name[0] = (name >> 24) & 0xff;
info->name[1] = (name >> 16) & 0xff; info->name[1] = (name >> 16) & 0xff;
info->name[2] = (name >> 8) & 0xff; info->name[2] = (name >> 8) & 0xff;
info->name[3] = name & 0xff; info->name[3] = name & 0xff;
info->name[4] = 0; info->name[4] = 0;
info->more_display[0] = 0; /* Nothing */ info->more_display[0] = 0; /* Nothing */
return 1; return 1;
} }
/*******************************************************/ /*******************************************************/
/* Format: x<type-1x>,<address-x>,<length-x>, where x is 'z' or 'Z' */ /* 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 parse_zbreak(const char *in, int *type, unsigned char **addr, int *len)
{ {
@@ -597,27 +648,36 @@ pack_qm_thread(char *out, int thread)
static void static void
pack_qm_header(char *out, int count, int done, int athread) pack_qm_header(char *out, int count, int done, int athread)
{ {
ASSERT(out != 0); ASSERT(out != 0);
ASSERT(count >= 0 && count < 256); ASSERT(count >= 0 && count < 256);
*out++ = 'q'; *out++ = 'q';
*out++ = 'M'; *out++ = 'M';
*out++ = gdb_hexchars[(count >> 4) & 0x0f]; *out++ = gdb_hexchars[(count >> 4) & 0x0f];
*out++ = gdb_hexchars[count & 0x0f]; *out++ = gdb_hexchars[count & 0x0f];
if (done) { if (done) {
*out++ = '1'; *out++ = '1';
} else { } else {
*out++ = '0'; *out++ = '0';
} }
thread2fhstr(out, athread); thread2fhstr(out, athread);
return;
return;
} }
void rtems_gdb_process_query( void rtems_gdb_process_query(
char *inbuffer, char *inbuffer,
char *outbuffer, char *outbuffer,
@@ -642,6 +702,9 @@ void rtems_gdb_process_query(
*optr = 0; *optr = 0;
break; break;
case 'P': case 'P':
/* Thread info query */ /* Thread info query */
if (!do_threads) { if (!do_threads) {
@@ -669,10 +732,14 @@ void rtems_gdb_process_query(
/* Build response */ /* Build response */
pack_qq(outbuffer, mask, rthread, &info); pack_qq(outbuffer, mask, rthread, &info);
} }
break; break;
case 'L': case 'L':
/* Thread info query */ /* Thread list query */
if (!do_threads) { if (!do_threads) {
break; break;
} }
@@ -724,9 +791,14 @@ void rtems_gdb_process_query(
/* Fill header */ /* Fill header */
pack_qm_header(outbuffer, i, done, athread); pack_qm_header(outbuffer, i, done, athread);
} }
break; break;
default: default:
if (memcmp(inbuffer, "qOffsets", 8) == 0) { if (memcmp(inbuffer, "qOffsets", 8) == 0) {
unsigned char *t, *d, *b; unsigned char *t, *d, *b;
@@ -772,9 +844,13 @@ void rtems_gdb_process_query(
/* qCRC, qRcmd, qu and qz will be added here */ /* qCRC, qRcmd, qu and qz will be added here */
break; break;
} }
} }
/* Present thread in the variable length string format */ /* Present thread in the variable length string format */
char* char*
thread2vhstr(char *buf, int thread) thread2vhstr(char *buf, int thread)
@@ -1196,6 +1272,7 @@ set_mem_err (void)
that the compiler won't save any registers (if there is a fault 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 to mem_fault, they won't get restored, so there better not be any
saved). */ saved). */
unsigned char unsigned char
get_byte (const unsigned char *addr) get_byte (const unsigned char *addr)
{ {
@@ -1210,6 +1287,12 @@ set_byte (unsigned char *addr, int val)
/* /*
* From here down, the code is CPU model specific and generally maps * From here down, the code is CPU model specific and generally maps
* the RTEMS thread context format to gdb's. * the RTEMS thread context format to gdb's.
@@ -1273,24 +1356,53 @@ int rtems_gdb_stub_get_offsets(
return 1; return 1;
} }
#elif defined(__mips__) #elif defined(__mips__)
void rtems_gdb_stub_get_registers_from_context( void rtems_gdb_stub_get_registers_from_context(
int *registers, int *registers,
Thread_Control *th 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( int rtems_gdb_stub_get_offsets(
unsigned char **text_addr, unsigned char **text_addr,
unsigned char **data_addr, unsigned char **data_addr,
unsigned char **bss_addr unsigned char **bss_addr
) )
{ {
/*
extern unsigned32 _ftext;
extern unsigned32 _fdata;
extern unsigned32 _bss_start;
*text_addr = &_ftext;
*data_addr = &_fdata;
*bss_addr = &_bss_start;
*/
*text_addr = 0; *text_addr = 0;
*data_addr = 0; *data_addr = 0;
*bss_addr = 0; *bss_addr = 0;
return 1; return 1;
} }

View File

@@ -29,7 +29,6 @@
*/ */
#include <rtems.h> #include <rtems.h>
#include <string.h> #include <string.h>
#include "gdb_if.h" #include "gdb_if.h"
@@ -40,6 +39,7 @@
extern const char gdb_hexchars[]; extern const char gdb_hexchars[];
/* /*
* Prototypes for CPU dependent routines that are conditional * Prototypes for CPU dependent routines that are conditional
* at the bottom of this file. * at the bottom of this file.
@@ -50,6 +50,12 @@ void rtems_gdb_stub_get_registers_from_context(
Thread_Control *th Thread_Control *th
); );
/* Check whether it is OK to enable thread support */ /* Check whether it is OK to enable thread support */
int rtems_gdb_stub_thread_support_ok(void) int rtems_gdb_stub_thread_support_ok(void)
{ {
@@ -59,6 +65,10 @@ int rtems_gdb_stub_thread_support_ok(void)
return 0; return 0;
} }
/* /*
* rtems_gdb_stub_id_to_index * rtems_gdb_stub_id_to_index
* *
@@ -101,12 +111,84 @@ int rtems_gdb_stub_id_to_index(
return first_posix_id + (thread_obj_id - min_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 */ /* Get id of the thread stopped by exception */
int rtems_gdb_stub_get_current_thread(void) int rtems_gdb_stub_get_current_thread(void)
{ {
return rtems_gdb_stub_id_to_index( _Thread_Executing->Object.id ); return rtems_gdb_stub_id_to_index( _Thread_Executing->Object.id );
} }
/* Get id of the next thread after athread, if argument <= 0 find the /* Get id of the next thread after athread, if argument <= 0 find the
first available thread, return thread if found or 0 if not */ first available thread, return thread if found or 0 if not */
int rtems_gdb_stub_get_next_thread(int athread) int rtems_gdb_stub_get_next_thread(int athread)
@@ -176,6 +258,10 @@ int rtems_gdb_stub_get_next_thread(int athread)
} }
/* Get thread registers, return 0 if thread does not /* Get thread registers, return 0 if thread does not
exist, and 1 otherwise */ exist, and 1 otherwise */
int rtems_gdb_stub_get_thread_regs( int rtems_gdb_stub_get_thread_regs(
@@ -183,70 +269,27 @@ int rtems_gdb_stub_get_thread_regs(
unsigned int *registers unsigned int *registers
) )
{ {
Objects_Id thread_obj_id; Thread_Control *th;
Objects_Id min_id, max_id;
int first_posix_id, first_rtems_id;
Objects_Information *obj_info;
Thread_Control *th;
ASSERT(registers != NULL); th= rtems_gdb_index_to_stub_id(thread);
if (_System_state_Get() != SYSTEM_STATE_UP || thread <= 0) { if( th )
/* Should not happen */ {
return 0; rtems_gdb_stub_get_registers_from_context( registers, th );
} return 1;
}
if (thread == 1) { return 0;
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 0;
}
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;
}
found:
rtems_gdb_stub_get_registers_from_context( registers, th );
return 1;
} }
/* Set thread registers, return 0 if thread does not /* Set thread registers, return 0 if thread does not
exist or register values will screw up the threads, exist or register values will screw up the threads,
and 1 otherwise */ and 1 otherwise */
int rtems_gdb_stub_set_thread_regs( int rtems_gdb_stub_set_thread_regs(
int thread, int thread,
unsigned int *registers unsigned int *registers
@@ -260,6 +303,10 @@ int rtems_gdb_stub_set_thread_regs(
} }
/* Get thread information, return 0 if thread does not /* Get thread information, return 0 if thread does not
exist and 1 otherwise */ exist and 1 otherwise */
int rtems_gdb_stub_get_thread_info( int rtems_gdb_stub_get_thread_info(
@@ -267,122 +314,126 @@ int rtems_gdb_stub_get_thread_info(
struct rtems_gdb_stub_thread_info *info struct rtems_gdb_stub_thread_info *info
) )
{ {
Objects_Id thread_obj_id; Objects_Id thread_obj_id;
Objects_Id min_id, max_id; Objects_Id min_id, max_id;
int first_posix_id, first_rtems_id; int first_posix_id, first_rtems_id;
Objects_Information *obj_info; Objects_Information *obj_info;
Thread_Control *th; Thread_Control *th;
unsigned32 name; unsigned32 name;
char tmp_buf[20]; char tmp_buf[20];
ASSERT(info != NULL); ASSERT(info != NULL);
if (thread <= 0) { if (thread <= 0) {
return 0; return 0;
} }
if (_System_state_Get() != SYSTEM_STATE_UP || thread == 1) { if (_System_state_Get() != SYSTEM_STATE_UP || thread == 1) {
/* We have one thread let us use value /* We have one thread let us use value
which will never happen for real thread */ which will never happen for real thread */
strcpy(info->display, "idle thread"); strcpy(info->display, "idle thread");
strcpy(info->name, "IDLE"); strcpy(info->name, "IDLE");
info->more_display[0] = 0; /* Nothing */ info->more_display[0] = 0; /* Nothing */
return 1; return 1;
} }
/* Let us get object associtated with current thread */ /* Let us get object associtated with current thread */
thread_obj_id = _Thread_Executing->Object.id; thread_obj_id = _Thread_Executing->Object.id;
/* Let us figure out thread_id for gdb */ /* Let us figure out thread_id for gdb */
first_rtems_id = 2; first_rtems_id = 2;
obj_info = _Objects_Information_table[OBJECTS_RTEMS_TASKS]; obj_info = _Objects_Information_table[OBJECTS_RTEMS_TASKS];
min_id = obj_info->minimum_id; min_id = obj_info->minimum_id;
max_id = obj_info->maximum_id; max_id = obj_info->maximum_id;
if (thread <= (first_rtems_id + (max_id - min_id))) { if (thread <= (first_rtems_id + (max_id - min_id))) {
th = (Thread_Control *)(obj_info->local_table[thread - th = (Thread_Control *)(obj_info->local_table[thread -
first_rtems_id + 1]); first_rtems_id + 1]);
if (th == NULL) { if (th == NULL) {
/* Thread does not exist */ /* Thread does not exist */
return 0; return 0;
} }
strcpy(info->display, "rtems task: control at 0x"); strcpy(info->display, "rtems task: control at 0x");
tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf]; tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];
tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf]; tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];
tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf]; tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];
tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf]; tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];
tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf]; tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];
tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf]; tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];
tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf]; tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];
tmp_buf[7] = gdb_hexchars[((int)th) & 0xf]; tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];
tmp_buf[8] = 0; tmp_buf[8] = 0;
strcat(info->display, tmp_buf); strcat(info->display, tmp_buf);
name = *(unsigned32 *)(obj_info->local_table[thread]->name); name = *(unsigned32 *)(obj_info->local_table[thread]->name);
info->name[0] = (name >> 24) & 0xff; info->name[0] = (name >> 24) & 0xff;
info->name[1] = (name >> 16) & 0xff; info->name[1] = (name >> 16) & 0xff;
info->name[2] = (name >> 8) & 0xff; info->name[2] = (name >> 8) & 0xff;
info->name[3] = name & 0xff; info->name[3] = name & 0xff;
info->name[4] = 0; info->name[4] = 0;
info->more_display[0] = 0; /* Nothing */ info->more_display[0] = 0; /* Nothing */
return 1; return 1;
} }
first_posix_id = first_rtems_id + (max_id - min_id) + 1; first_posix_id = first_rtems_id + (max_id - min_id) + 1;
obj_info = _Objects_Information_table[OBJECTS_POSIX_THREADS]; obj_info = _Objects_Information_table[OBJECTS_POSIX_THREADS];
min_id = obj_info->minimum_id; min_id = obj_info->minimum_id;
max_id = obj_info->maximum_id; max_id = obj_info->maximum_id;
th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]); th = (Thread_Control *)(obj_info->local_table[thread - first_posix_id + 1]);
if (th == NULL) if (th == NULL)
{ {
/* Thread does not exist */ /* Thread does not exist */
return 0; return 0;
} }
strcpy(info->display, "posix thread: control at 0x"); strcpy(info->display, "posix thread: control at 0x");
tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf]; tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];
tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf]; tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];
tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf]; tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];
tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf]; tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];
tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf]; tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];
tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf]; tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];
tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf]; tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];
tmp_buf[7] = gdb_hexchars[((int)th) & 0xf]; tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];
tmp_buf[8] = 0; tmp_buf[8] = 0;
strcat(info->display, tmp_buf); strcat(info->display, tmp_buf);
name = *(unsigned32 *)(obj_info->local_table[thread - name = *(unsigned32 *)(obj_info->local_table[thread -
first_posix_id + 1]->name); first_posix_id + 1]->name);
info->name[0] = (name >> 24) & 0xff; info->name[0] = (name >> 24) & 0xff;
info->name[1] = (name >> 16) & 0xff; info->name[1] = (name >> 16) & 0xff;
info->name[2] = (name >> 8) & 0xff; info->name[2] = (name >> 8) & 0xff;
info->name[3] = name & 0xff; info->name[3] = name & 0xff;
info->name[4] = 0; info->name[4] = 0;
info->more_display[0] = 0; /* Nothing */ info->more_display[0] = 0; /* Nothing */
return 1; return 1;
} }
/*******************************************************/ /*******************************************************/
/* Format: x<type-1x>,<address-x>,<length-x>, where x is 'z' or 'Z' */ /* 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 parse_zbreak(const char *in, int *type, unsigned char **addr, int *len)
{ {
@@ -597,27 +648,36 @@ pack_qm_thread(char *out, int thread)
static void static void
pack_qm_header(char *out, int count, int done, int athread) pack_qm_header(char *out, int count, int done, int athread)
{ {
ASSERT(out != 0); ASSERT(out != 0);
ASSERT(count >= 0 && count < 256); ASSERT(count >= 0 && count < 256);
*out++ = 'q'; *out++ = 'q';
*out++ = 'M'; *out++ = 'M';
*out++ = gdb_hexchars[(count >> 4) & 0x0f]; *out++ = gdb_hexchars[(count >> 4) & 0x0f];
*out++ = gdb_hexchars[count & 0x0f]; *out++ = gdb_hexchars[count & 0x0f];
if (done) { if (done) {
*out++ = '1'; *out++ = '1';
} else { } else {
*out++ = '0'; *out++ = '0';
} }
thread2fhstr(out, athread); thread2fhstr(out, athread);
return;
return;
} }
void rtems_gdb_process_query( void rtems_gdb_process_query(
char *inbuffer, char *inbuffer,
char *outbuffer, char *outbuffer,
@@ -642,6 +702,9 @@ void rtems_gdb_process_query(
*optr = 0; *optr = 0;
break; break;
case 'P': case 'P':
/* Thread info query */ /* Thread info query */
if (!do_threads) { if (!do_threads) {
@@ -669,10 +732,14 @@ void rtems_gdb_process_query(
/* Build response */ /* Build response */
pack_qq(outbuffer, mask, rthread, &info); pack_qq(outbuffer, mask, rthread, &info);
} }
break; break;
case 'L': case 'L':
/* Thread info query */ /* Thread list query */
if (!do_threads) { if (!do_threads) {
break; break;
} }
@@ -724,9 +791,14 @@ void rtems_gdb_process_query(
/* Fill header */ /* Fill header */
pack_qm_header(outbuffer, i, done, athread); pack_qm_header(outbuffer, i, done, athread);
} }
break; break;
default: default:
if (memcmp(inbuffer, "qOffsets", 8) == 0) { if (memcmp(inbuffer, "qOffsets", 8) == 0) {
unsigned char *t, *d, *b; unsigned char *t, *d, *b;
@@ -772,9 +844,13 @@ void rtems_gdb_process_query(
/* qCRC, qRcmd, qu and qz will be added here */ /* qCRC, qRcmd, qu and qz will be added here */
break; break;
} }
} }
/* Present thread in the variable length string format */ /* Present thread in the variable length string format */
char* char*
thread2vhstr(char *buf, int thread) thread2vhstr(char *buf, int thread)
@@ -1196,6 +1272,7 @@ set_mem_err (void)
that the compiler won't save any registers (if there is a fault 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 to mem_fault, they won't get restored, so there better not be any
saved). */ saved). */
unsigned char unsigned char
get_byte (const unsigned char *addr) get_byte (const unsigned char *addr)
{ {
@@ -1210,6 +1287,12 @@ set_byte (unsigned char *addr, int val)
/* /*
* From here down, the code is CPU model specific and generally maps * From here down, the code is CPU model specific and generally maps
* the RTEMS thread context format to gdb's. * the RTEMS thread context format to gdb's.
@@ -1273,24 +1356,53 @@ int rtems_gdb_stub_get_offsets(
return 1; return 1;
} }
#elif defined(__mips__) #elif defined(__mips__)
void rtems_gdb_stub_get_registers_from_context( void rtems_gdb_stub_get_registers_from_context(
int *registers, int *registers,
Thread_Control *th 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( int rtems_gdb_stub_get_offsets(
unsigned char **text_addr, unsigned char **text_addr,
unsigned char **data_addr, unsigned char **data_addr,
unsigned char **bss_addr unsigned char **bss_addr
) )
{ {
/*
extern unsigned32 _ftext;
extern unsigned32 _fdata;
extern unsigned32 _bss_start;
*text_addr = &_ftext;
*data_addr = &_fdata;
*bss_addr = &_bss_start;
*/
*text_addr = 0; *text_addr = 0;
*data_addr = 0; *data_addr = 0;
*bss_addr = 0; *bss_addr = 0;
return 1; return 1;
} }