* 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_ */

View File

@@ -123,7 +123,7 @@
#include <string.h> #include <string.h>
#include <signal.h> #include <signal.h>
#include "mips_opcode.h" #include "mips_opcode.h"
#include "memlimits.h" /* #include "memlimits.h" */
#include <rtems.h> #include <rtems.h>
#include "gdb_if.h" #include "gdb_if.h"
@@ -208,10 +208,27 @@ static char do_threads; /* != 0 means we are supporting threads */
* The following external functions provide character input and output. * The following external functions provide character input and output.
*/ */
extern char getDebugChar (void); extern char getDebugChar (void);
extern void putDebugChar (char); extern void putDebugChar (char);
/*
* The following definitions are used for the gdb stub memory map
*/
struct memseg
{
unsigned begin, end, opts;
};
static int is_readable(unsigned,unsigned);
static int is_writeable(unsigned,unsigned);
static int is_steppable(unsigned);
/* /*
* BUFMAX defines the maximum number of characters in the inbound & outbound * BUFMAX defines the maximum number of characters in the inbound & outbound
* packet buffers. At least 4+(sizeof registers)*2 bytes will be needed for * packet buffers. At least 4+(sizeof registers)*2 bytes will be needed for
@@ -224,6 +241,7 @@ static char outBuffer[BUFMAX];
/* Structure to keep info on a z-breaks */ /* Structure to keep info on a z-breaks */
#define BREAKNUM 32 #define BREAKNUM 32
struct z0break struct z0break
{ {
/* List support */ /* List support */
@@ -231,8 +249,8 @@ struct z0break
struct z0break *prev; struct z0break *prev;
/* Location, preserved data */ /* Location, preserved data */
unsigned char *address; unsigned *address;
char buf[2]; unsigned instr;
}; };
static struct z0break z0break_arr[BREAKNUM]; static struct z0break z0break_arr[BREAKNUM];
@@ -623,6 +641,11 @@ putpacket (char *buffer)
while (getDebugChar () != '+'); while (getDebugChar () != '+');
} }
/* /*
* Saved instruction data for single step support * Saved instruction data for single step support
@@ -663,6 +686,7 @@ undoSStep (void)
static void static void
doSStep (void) doSStep (void)
{ {
struct z0break *z0;
InstFmt inst; InstFmt inst;
instrBuffer.targetAddr = (unsigned *)(registers[PC]+4); /* set default */ instrBuffer.targetAddr = (unsigned *)(registers[PC]+4); /* set default */
@@ -771,7 +795,8 @@ doSStep (void)
break; break;
} }
if is_steppable (instrBuffer.targetAddr)
if( is_steppable((unsigned)instrBuffer.targetAddr) && *(instrBuffer.targetAddr) != BREAK_INSTR )
{ {
instrBuffer.savedInstr = *instrBuffer.targetAddr; instrBuffer.savedInstr = *instrBuffer.targetAddr;
*instrBuffer.targetAddr = BREAK_INSTR; *instrBuffer.targetAddr = BREAK_INSTR;
@@ -784,6 +809,10 @@ doSStep (void)
return; return;
} }
/* /*
* Translate the R4600 exception code into a Unix-compatible signal. * Translate the R4600 exception code into a Unix-compatible signal.
@@ -864,18 +893,21 @@ void gdb_stub_report_exception_info(
*optr++ = highhex (sigval); *optr++ = highhex (sigval);
*optr++ = lowhex (sigval); *optr++ = lowhex (sigval);
*optr++ = gdb_hexchars[SP]; *optr++ = highhex(SP); /*gdb_hexchars[SP]; */
*optr++ = lowhex(SP);
*optr++ = ':'; *optr++ = ':';
optr = mem2hstr(optr, (unsigned char *)&frame->sp, R_SZ ); optr = mem2hstr(optr, (unsigned char *)&frame->sp, R_SZ );
*optr++ = ';'; *optr++ = ';';
*optr++ = gdb_hexchars[PC]; *optr++ = highhex(PC); /*gdb_hexchars[PC]; */
*optr++ = lowhex(PC);
*optr++ = ':'; *optr++ = ':';
optr = mem2hstr(optr, (unsigned char *)&frame->sp, R_SZ ); optr = mem2hstr(optr, (unsigned char *)&frame->epc, R_SZ );
*optr++ = ';'; *optr++ = ';';
#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
if (do_threads) { if (do_threads)
{
*optr++ = 't'; *optr++ = 't';
*optr++ = 'h'; *optr++ = 'h';
*optr++ = 'r'; *optr++ = 'r';
@@ -887,32 +919,40 @@ void gdb_stub_report_exception_info(
*optr++ = ';'; *optr++ = ';';
} }
#endif #endif
putpacket (outBuffer);
*optr++ = '\0'; *optr++ = '\0';
} }
/*
* Scratch frame used to retrieve contexts for different threads, so as
* not to disrupt our current context on the stack
*/
CPU_Interrupt_frame current_thread_registers;
/* /*
* This function handles all exceptions. It only does two things: * This function handles all exceptions. It only does two things:
* it figures out why it was activated and tells gdb, and then it * it figures out why it was activated and tells gdb, and then it
* reacts to gdb's requests. * reacts to gdb's requests.
*/ */
CPU_Interrupt_frame current_thread_registers;
void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame) void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
{ {
int host_has_detached = 0; int host_has_detached = 0;
int regno, addr, length; int regno, addr, length;
long long regval;
char *ptr; char *ptr;
int current_thread; /* current generic thread */ int current_thread; /* current generic thread */
int thread; /* stopped thread: context exception happened in */ int thread; /* stopped thread: context exception happened in */
long long regval;
void *regptr; void *regptr;
int binary; int binary;
registers = (mips_register_t *)frame; registers = (mips_register_t *)frame;
thread = 0; thread = 0;
@@ -923,15 +963,69 @@ void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
#endif #endif
current_thread = thread; current_thread = thread;
/* reply to host that an exception has occurred with some basic info */
gdb_stub_report_exception_info(vector, frame, thread);
{
/* reapply all breakpoints regardless of how we came in */
struct z0break *z0, *zother;
for (zother=z0break_list; zother!=NULL; zother=zother->next)
{
if( zother->instr == 0xffffffff )
{
/* grab the instruction */
zother->instr = *(zother->address);
/* and insert the breakpoint */
*(zother->address) = BREAK_INSTR;
}
}
/* see if we're coming from a breakpoint */
if( *((unsigned *)frame->epc) == BREAK_INSTR )
{
/* see if its one of our zbreaks */
for (z0=z0break_list; z0!=NULL; z0=z0->next)
{
if( (unsigned)z0->address == frame->epc)
break;
}
if( z0 )
{
/* restore the original instruction */
*(z0->address) = z0->instr;
/* flag the breakpoint */
z0->instr = 0xffffffff;
/*
now when we return, we'll execute the original code in
the original state. This leaves our breakpoint inactive
since the break instruction isn't there, but we'll reapply
it the next time we come in via step or breakpoint
*/
}
else
{
/* not a zbreak, see if its our trusty stepping code */
/* /*
* Restore the saved instruction at * Restore the saved instruction at
* the single-step target address. * the single-step target address.
*/ */
undoSStep (); undoSStep();
}
}
}
/* reply to host that an exception has occurred with some basic info */
gdb_stub_report_exception_info(vector, frame, thread);
putpacket (outBuffer);
while (!(host_has_detached)) { while (!(host_has_detached)) {
outBuffer[0] = '\0'; outBuffer[0] = '\0';
@@ -960,9 +1054,9 @@ void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
regptr = &current_thread_registers; regptr = &current_thread_registers;
#endif #endif
mem2hex (regptr, NUM_REGS * (sizeof registers), outBuffer); mem2hex (regptr, NUM_REGS * (sizeof registers), outBuffer);
break; break;
case 'G': /* set the values of the CPU registers - return OK */ case 'G': /* set the values of the CPU registers - return OK */
regptr = registers; regptr = registers;
#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
@@ -975,6 +1069,7 @@ void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */ strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */
break; break;
case 'P': case 'P':
/* Pn...=r... Write register n... with value r... - return OK */ /* Pn...=r... Write register n... with value r... - return OK */
ptr = &inBuffer[1]; ptr = &inBuffer[1];
@@ -989,6 +1084,7 @@ void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */ strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */
break; break;
case 'm': case 'm':
/* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
ptr = &inBuffer[1]; ptr = &inBuffer[1];
@@ -1002,6 +1098,7 @@ void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
strcpy (outBuffer, "E01"); /* E01 = bad 'm' command */ strcpy (outBuffer, "E01"); /* E01 = bad 'm' command */
break; break;
case 'X': /* XAA..AA,LLLL:<binary data>#cs */ case 'X': /* XAA..AA,LLLL:<binary data>#cs */
binary = 1; binary = 1;
case 'M': case 'M':
@@ -1022,6 +1119,8 @@ void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
strcpy (outBuffer, "E02"); /* E02 = bad 'M' command */ strcpy (outBuffer, "E02"); /* E02 = bad 'M' command */
break; break;
case 'c': case 'c':
/* cAA..AA Continue at address AA..AA(optional) */ /* cAA..AA Continue at address AA..AA(optional) */
case 's': case 's':
@@ -1035,40 +1134,75 @@ void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
if (inBuffer[0] == 's') if (inBuffer[0] == 's')
doSStep (); doSStep ();
} }
return; goto stubexit;
case 'k': /* remove all zbreaks if any */ case 'k': /* remove all zbreaks if any */
dumpzbreaks:
{ {
int ret; {
struct z0break *z0, *z0last; /* Unlink the entire list */
struct z0break *z0, *znxt;
ret = 1; while( (z0= z0break_list) )
z0last = NULL; {
for (z0=z0break_list; z0!=NULL; z0=z0->next) { /* put back the instruction */
if (!hstr2mem(z0->address, z0->buf, 1)) { if( z0->instr != 0xffffffff )
ret = 0; *(z0->address) = z0->instr;
}
z0last = z0; /* pop off the top entry */
} znxt = z0->next;
if( znxt ) znxt->prev = NULL;
z0break_list = znxt;
/* Free entries if any */ /* and put it on the free list */
if (z0last != NULL) { z0->prev = NULL;
z0last->next = z0break_avail; z0->next = z0break_avail;
z0break_avail = z0break_list; z0break_avail = z0;
z0break_list = NULL;
} }
} }
strcpy(outBuffer, "OK");
}
break; break;
case 'q': /* queries */ case 'q': /* queries */
#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
rtems_gdb_process_query( inBuffer, outBuffer, do_threads, thread ); rtems_gdb_process_query( inBuffer, outBuffer, do_threads, thread );
#endif #endif
break; break;
#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
case 'T':
{
int testThread;
if( vhstr2thread(&inBuffer[1], &testThread) == NULL )
{
strcpy(outBuffer, "E01");
break;
}
if( rtems_gdb_index_to_stub_id(testThread) == NULL )
{
strcpy(outBuffer, "E02");
}
else
{
strcpy(outBuffer, "OK");
}
}
break;
#endif
case 'H': /* set new thread */ case 'H': /* set new thread */
#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
if (inBuffer[1] != 'g') { if (inBuffer[1] != 'g') {
@@ -1121,14 +1255,143 @@ void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
current_thread = tmp; current_thread = tmp;
strcpy(outBuffer, "OK"); strcpy(outBuffer, "OK");
} }
#endif #endif
break; break;
case 'Z': /* Add breakpoint */ case 'Z': /* Add breakpoint */
{ {
int ret, type, len; int ret, type, len;
unsigned char *address; unsigned *address;
struct z0break *z0;
ret = parse_zbreak(inBuffer, &type, &address, &len);
if (!ret) {
strcpy(outBuffer, "E01");
break;
}
if (type != 0) {
/* We support only software break points so far */
strcpy(outBuffer, "E02");
break;
}
if (len != R_SZ) { /* was 1 */
strcpy(outBuffer, "E03");
break;
}
/* Let us check whether this break point already set */
for (z0=z0break_list; z0!=NULL; z0=z0->next) {
if (z0->address == address) {
break;
}
}
if (z0 != NULL) {
/* we already have a breakpoint for this address */
strcpy(outBuffer, "E04");
break;
}
/* Let us allocate new break point */
if (z0break_avail == NULL) {
strcpy(outBuffer, "E05");
break;
}
/* Get entry */
z0 = z0break_avail;
z0break_avail = z0break_avail->next;
/* Let us copy memory from address add stuff the break point in */
/*
*if (mem2hstr(z0->buf, address, 1) == NULL ||
!hstr2mem(address, "cc" , 1)) {
* Memory error *
z0->next = z0break_avail;
z0break_avail = z0;
strcpy(outBuffer, "E05");
break;
}*/
/* Fill it */
z0->address = address;
if( z0->address == frame->epc )
{
/* re-asserting the breakpoint that put us in here, so
we'll add the breakpoint but leave the code in place
since we'll be returning to it when the user continues */
z0->instr = 0xffffffff;
}
else
{
/* grab the instruction */
z0->instr = *(z0->address);
/* and insert the break */
*(z0->address) = BREAK_INSTR;
}
/* Add to the list */
{
struct z0break *znxt = z0break_list;
z0->prev = NULL;
z0->next = znxt;
if( znxt ) znxt->prev = z0;
z0break_list = z0;
}
strcpy(outBuffer, "OK");
}
break;
case 'z': /* remove breakpoint */
if (inBuffer[1] == 'z')
{
goto dumpzbreaks;
/*
* zz packet - remove all breaks *
z0last = NULL;
for (z0=z0break_list; z0!=NULL; z0=z0->next)
{
if(!hstr2mem(z0->address, z0->buf, R_SZ))
{
ret = 0;
}
z0last = z0;
}
* Free entries if any *
if (z0last != NULL) {
z0last->next = z0break_avail;
z0break_avail = z0break_list;
z0break_list = NULL;
}
if (ret) {
strcpy(outBuffer, "OK");
} else {
strcpy(outBuffer, "E04");
}
break;
*/
}
else
{
int ret, type, len;
unsigned *address;
struct z0break *z0; struct z0break *z0;
ret = parse_zbreak(inBuffer, &type, &address, &len); ret = parse_zbreak(inBuffer, &type, &address, &len);
@@ -1142,106 +1405,7 @@ void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
break; break;
} }
if (len != 1) { if (len != R_SZ) {
strcpy(outBuffer, "E02");
break;
}
/* Let us check whether this break point already set */
for (z0=z0break_list; z0!=NULL; z0=z0->next) {
if (z0->address == address) {
break;
}
}
if (z0 != NULL) {
/* Repeated packet */
strcpy(outBuffer, "OK");
break;
}
/* Let us allocate new break point */
if (z0break_avail == NULL) {
strcpy(outBuffer, "E03");
break;
}
/* Get entry */
z0 = z0break_avail;
z0break_avail = z0break_avail->next;
/* Let us copy memory from address add stuff the break point in */
if (mem2hstr(z0->buf, address, 1) == NULL ||
!hstr2mem(address, "cc" , 1)) {
/* Memory error */
z0->next = z0break_avail;
z0break_avail = z0;
strcpy(outBuffer, "E03");
break;
}
/* Fill it */
z0->address = address;
/* Add to the list */
z0->next = z0break_list;
z0->prev = NULL;
if (z0break_list != NULL) {
z0break_list->prev = z0;
}
z0break_list = z0;
strcpy(outBuffer, "OK");
}
case 'z': /* remove breakpoint */
{
int ret, type, len;
unsigned char *address;
struct z0break *z0, *z0last;
if (inBuffer[1] == 'z') {
/* zz packet - remove all breaks */
ret = 1;
z0last = NULL;
for (z0=z0break_list; z0!=NULL; z0=z0->next) {
if(!hstr2mem(z0->address, z0->buf, 1)) {
ret = 0;
}
z0last = z0;
}
/* Free entries if any */
if (z0last != NULL) {
z0last->next = z0break_avail;
z0break_avail = z0break_list;
z0break_list = NULL;
}
if (ret) {
strcpy(outBuffer, "OK");
} else {
strcpy(outBuffer, "E04");
}
break;
}
ret = parse_zbreak(inBuffer, &type, &address, &len);
if (!ret) {
strcpy(outBuffer, "E01");
break;
}
if (type != 0) {
/* We support only software break points so far */
break;
}
if (len != 1) {
strcpy(outBuffer, "E02"); strcpy(outBuffer, "E02");
break; break;
} }
@@ -1259,31 +1423,39 @@ void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
break; break;
} }
if (!hstr2mem(z0->address, z0->buf, 1)) { /*
if (!hstr2mem(z0->address, z0->buf, R_SZ)) {
strcpy(outBuffer, "E04"); strcpy(outBuffer, "E04");
break; break;
}*/
if( z0->instr != 0xffffffff )
{
/* put the old instruction back */
*(z0->address) = z0->instr;
} }
/* Unlink entry */ /* Unlink entry */
if (z0->prev == NULL) { {
z0break_list = z0->next; struct z0break *zprv = z0->prev, *znxt = z0->next;
if (z0break_list != NULL) {
z0break_list->prev = NULL; if( zprv ) zprv->next = znxt;
} if( znxt ) znxt->prev = zprv;
} else if (z0->next == NULL) {
z0->prev->next = NULL; if( !zprv ) z0break_list = znxt;
} else {
z0->prev->next = z0->next; znxt = z0break_avail;
z0->next->prev = z0->prev;
}
z0->next = z0break_avail;
z0break_avail = z0; z0break_avail = z0;
z0->prev = NULL;
z0->next = znxt;
}
strcpy(outBuffer, "OK"); strcpy(outBuffer, "OK");
} }
break; break;
default: /* do nothing */ default: /* do nothing */
break; break;
} }
@@ -1292,6 +1464,8 @@ void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
putpacket (outBuffer); putpacket (outBuffer);
} }
stubexit:
/* /*
* The original code did this in the assembly wrapper. We should consider * The original code did this in the assembly wrapper. We should consider
* doing it here before we return. * doing it here before we return.
@@ -1299,15 +1473,115 @@ void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
* On exit from the exception handler invalidate each line in the I-cache * On exit from the exception handler invalidate each line in the I-cache
* and write back each dirty line in the D-cache. This needs to be done * and write back each dirty line in the D-cache. This needs to be done
* before the target program is resumed in order to ensure that software * before the target program is resumed in order to ensure that software
* breakpoints and downloaded code will actually take effect. * breakpoints and downloaded code will actually take effect. This
* is because modifications to code in ram will affect the D-cache,
* but not necessarily the I-cache.
*/ */
{
extern void clear_cache();
clear_cache();
}
return; return;
} }
static char initialized; /* 0 means we are not initialized */
void mips_gdb_stub_install(void)
static int numsegs;
static struct memseg memsegments[NUM_MEMSEGS];
int gdbstub_add_memsegment( unsigned base, unsigned end, int opts )
{
if( numsegs == NUM_MEMSEGS ) return -1;
memsegments[numsegs].begin = base;
memsegments[numsegs].end = end;
memsegments[numsegs].opts = opts;
++numsegs;
return RTEMS_SUCCESSFUL;
}
static int is_readable(unsigned ptr, unsigned len)
{
struct memseg *ms;
int i;
if( (ptr & 0x3) ) return -1;
for(i=0; i<numsegs; i++)
{
ms= &memsegments[i];
if( ms->begin <= ptr && ptr+len <= ms->end && (ms->opts & MEMOPT_READABLE) )
return -1;
}
return 0;
}
static int is_writeable(unsigned ptr, unsigned len)
{
struct memseg *ms;
int i;
if( (ptr & 0x3) ) return -1;
for(i=0; i<numsegs; i++)
{
ms= &memsegments[i];
if( ms->begin <= ptr && ptr+len <= ms->end && (ms->opts & MEMOPT_WRITEABLE) )
return -1;
}
return 0;
}
static int is_steppable(unsigned ptr)
{
struct memseg *ms;
int i;
if( (ptr & 0x3) ) return -1;
for(i=0; i<numsegs; i++)
{
ms= &memsegments[i];
if( ms->begin <= ptr && ptr <= ms->end && (ms->opts & MEMOPT_WRITEABLE) )
return -1;
}
return 0;
}
static char initialized = 0; /* 0 means we are not initialized */
void mips_gdb_stub_install(int enableThreads)
{ {
/* /*
These are the RTEMS-defined vectors for all the MIPS exceptions These are the RTEMS-defined vectors for all the MIPS exceptions
@@ -1334,20 +1608,37 @@ void mips_gdb_stub_install(void)
int i; int i;
rtems_isr_entry old; rtems_isr_entry old;
if (initialized) { if (initialized)
{
ASSERT(0); ASSERT(0);
return; return;
} }
/* z0breaks */ memset( memsegments,0,sizeof(struct memseg)*NUM_MEMSEGS );
for (i=0; i<(sizeof(z0break_arr)/sizeof(z0break_arr[0]))-1; i++) { numsegs = 0;
z0break_arr[i].next = &z0break_arr[i+1];
}
z0break_arr[i].next = NULL; #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
z0break_avail = &z0break_arr[0]; if( enableThreads )
do_threads = 1;
else
do_threads = 0;
#endif
{
struct z0break *z0;
z0break_avail = NULL;
z0break_list = NULL; z0break_list = NULL;
/* z0breaks list init, now we'll do it so it makes sense... */
for (i=0; i<BREAKNUM; i++)
{
memset( (z0= &z0break_arr[i]), 0, sizeof(struct z0break));
z0->next = z0break_avail;
z0break_avail = z0;
}
}
for(i=0; exceptionVector[i] > -1; i++) for(i=0; exceptionVector[i] > -1; i++)
{ {
@@ -1355,8 +1646,9 @@ void mips_gdb_stub_install(void)
} }
initialized = 1; initialized = 1;
/* get the attention of gdb */ /* get the attention of gdb */
mips_break(1); /* mips_break(1); disabled so user code can choose to invoke it or not */
} }

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;
Objects_Id min_id, max_id;
int first_posix_id, first_rtems_id;
Objects_Information *obj_info;
Thread_Control *th; Thread_Control *th;
ASSERT(registers != NULL); th= rtems_gdb_index_to_stub_id(thread);
if (_System_state_Get() != SYSTEM_STATE_UP || thread <= 0) {
/* Should not happen */
return 0;
}
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 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:
if( th )
{
rtems_gdb_stub_get_registers_from_context( registers, th ); rtems_gdb_stub_get_registers_from_context( registers, th );
return 1; return 1;
}
return 0;
} }
/* 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(
@@ -336,7 +383,7 @@ int rtems_gdb_stub_get_thread_info(
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;
@@ -383,6 +430,10 @@ int rtems_gdb_stub_get_thread_info(
/*******************************************************/ /*******************************************************/
/* 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)
{ {
@@ -613,11 +664,20 @@ pack_qm_header(char *out, int count, int done, int athread)
} }
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;
Objects_Id min_id, max_id;
int first_posix_id, first_rtems_id;
Objects_Information *obj_info;
Thread_Control *th; Thread_Control *th;
ASSERT(registers != NULL); th= rtems_gdb_index_to_stub_id(thread);
if (_System_state_Get() != SYSTEM_STATE_UP || thread <= 0) {
/* Should not happen */
return 0;
}
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 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:
if( th )
{
rtems_gdb_stub_get_registers_from_context( registers, th ); rtems_gdb_stub_get_registers_from_context( registers, th );
return 1; return 1;
}
return 0;
} }
/* 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(
@@ -336,7 +383,7 @@ int rtems_gdb_stub_get_thread_info(
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;
@@ -383,6 +430,10 @@ int rtems_gdb_stub_get_thread_info(
/*******************************************************/ /*******************************************************/
/* 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)
{ {
@@ -613,11 +664,20 @@ pack_qm_header(char *out, int count, int done, int athread)
} }
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;
} }